Skip to content

Adavo/cordova-plugin-media

 
 

Repository files navigation

What's new in this "edition"

I had a simple issue : record the voice of the user and get the byte in order to send it to the server. With the official plugin I encounter lot of issues (encoding, store file in the cache folder of the app, get the byte). So I change some code. For more information, see "My Work" section.

Here is the new feature (iOS & Android):

  • encoding in mp4
  • get byte of the recorded file into a base64 string

To use it :

// set filename 
filename = "record.mp4";

// prepare the record and start it.
recordAudio = new Media(filename, recordAudioSuccessCallbackManagement, errorCallback);
recordAudio.startRecord();

...

recordAudio.stopRecord();
recordAudio.play();

...

recordAudio.getBinRecordAudio(successCallback, errorCallback);

successCallback will be called with one argument : a string that represents the base64 encoded of the byte array (byte[]) of the recorded file

For (iOS)

To encode in mp4 ( for ios default extension is .acc, I just save it as .mp4), I update CDVSound.m :

Add:

#define RECORDING_MP4 @"mp4"

Update:

// first check for correct extension
if ([[resourcePath pathExtension] caseInsensitiveCompare:RECORDING_WAV] != NSOrderedSame) {
    ...
    NSLog(@"Resource for recording must have %@ extension", RECORDING_WAV);
...
        audioFile.recorder = [[CDVAudioRecorder alloc] initWithURL:audioFile.resourceURL settings:nil error:&error];
		
become 

// first check for correct extension
if ([[resourcePath pathExtension] caseInsensitiveCompare:RECORDING_MP4] != NSOrderedSame) {
    ...
    NSLog(@"Resource for recording must have %@ extension", RECORDING_MP4);
...
        audioFile.recorder = [[CDVAudioRecorder alloc] initWithURL:audioFile.resourceURL settings:audioSettings error:&error];	

To get the record byte, I update CDVSound.h by adding this new method :

- (void)getBinRecordAudio:(CDVInvokedUrlCommand*)command;

The file CDVSound.m by adding this new method :

- (void)getBinRecordAudio:(CDVInvokedUrlCommand*)command
{
	NSString* callbackId = command.callbackId;
	NSString* mediaId = [command argumentAtIndex:0];
	
#pragma unused(mediaId)
	CDVAudioFile* audioFile = [[self soundCache] objectForKey:mediaId];
	double position = -1;
	
	NSFileHandle *readHandle = [NSFileHandle fileHandleForReadingFromURL:audioFile.resourceURL error: nil];
	NSData *nsdata = [readHandle readDataToEndOfFile];
	NSString *base64Data  = [[NSString alloc] initWithData:[nsdata base64EncodedDataWithOptions:0] encoding:NSASCIIStringEncoding];
	
	CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:base64Data];
	
	NSString* jsString = [NSString stringWithFormat:@"%@(\"%@\",%d,%.3f);", @"cordova.require('cordova-plugin-media.Media').onStatus", mediaId, MEDIA_POSITION, position];
	[self.commandDelegate evalJs:jsString];
	[self.commandDelegate sendPluginResult:result callbackId:callbackId];
}

My work (android)

To encode in mp4 (better than ... amr from my point of view), I update AudioPlayer.java :

this.recorder.setOutputFormat(MediaRecorder.OutputFormat.DEFAULT); // THREE_GPP);
this.recorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT); //AMR_NB);
		
become 

this.recorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4); // ADAVO : encode to MPEG_4
this.recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC); // ADAVO : encode to MPEG_4

To get the record byte, I update AudioPlayer.java by adding this new method :

/**
 * Get bin of the recorded file encoded into a base 64 object
 */
public String getBinRecordAudio() {
	try {
		String filePath = this.audioFile;
		if (!filePath.startsWith("/")) {
			if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
				filePath = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + filePath;
			} else {
				filePath = "/data/data/" + handler.cordova.getActivity().getPackageName() + "/cache/" + filePath;
			}
		}
		Log.d(LOG_TAG, "Get binary data of the file :" + filePath);
		return android.util.Base64.encodeToString(FileHelper.readFile(filePath), android.util.Base64.DEFAULT);
	}
	catch (Exception e) {
            e.printStackTrace();
			return null;
    }
}

The file AudioHandler.java by adding this new method :

/**
 * get binary data of the audio file encoded into base64 object
 * @param id				The id of the audio player
 */
public String getBinRecordAudio(String id) {
    AudioPlayer audio = this.players.get(id);
    return audio.getBinRecordAudio();
}

and editing the execute method by adding this new condition :

	else if (action.equals("getBinRecordAudio")) {
        String data = this.getBinRecordAudio(args.getString(0));
		callbackContext.sendPluginResult(new PluginResult(status, data));
	}

I edit also the FileHelper.java by adding this two new methods (think to import java.io.*) :

public static byte[] readFile(String file) throws IOException {
    return readFile(new File(file));
}

public static byte[] readFile(File file) throws IOException {
    // Open file
    RandomAccessFile f = new RandomAccessFile(file, "r");
    try {
        // Get and check length
        long longlength = f.length();
        int length = (int) longlength;
        if (length != longlength)
            throw new IOException("File size >= 2 GB");
        // Read file and return data
        byte[] data = new byte[length];
        f.readFully(data);
        return data;
    } finally {
        f.close();
    }
}

and finally Media.js by adding the new method :

/**
 * Get binary recording audio file.
 */
Media.prototype.getBinRecordAudio = function(success, fail) {
	exec(success, fail, "Media", "getBinRecordAudio", [this.id]);
};

cordova-plugin-media

This plugin provides the ability to record and play back audio files on a device.

NOTE: The current implementation does not adhere to a W3C specification for media capture, and is provided for convenience only. A future implementation will adhere to the latest W3C specification and may deprecate the current APIs.

This plugin defines a global Media Constructor.

Although in the global scope, it is not available until after the deviceready event.

document.addEventListener("deviceready", onDeviceReady, false);
function onDeviceReady() {
    console.log(Media);
}

Report issues with this plugin on the Apache Cordova issue tracker

Installation

cordova plugin add cordova-plugin-media

Supported Platforms

  • Android
  • BlackBerry 10
  • iOS
  • Windows Phone 7 and 8
  • Tizen
  • Windows 8
  • Windows
  • Browser

Windows Phone Quirks

  • Only one media file can be played back at a time.

Media

var media = new Media(src, mediaSuccess, [mediaError], [mediaStatus]);

Parameters

  • src: A URI containing the audio content. (DOMString)

  • mediaSuccess: (Optional) The callback that executes after a Media object has completed the current play, record, or stop action. (Function)

  • mediaError: (Optional) The callback that executes if an error occurs. (Function)

  • mediaStatus: (Optional) The callback that executes to indicate status changes. (Function)

NOTE: cdvfile path is supported as src parameter:

var my_media = new Media('cdvfile://localhost/temporary/recording.mp3', ...);

Constants

The following constants are reported as the only parameter to the mediaStatus callback:

  • Media.MEDIA_NONE = 0;
  • Media.MEDIA_STARTING = 1;
  • Media.MEDIA_RUNNING = 2;
  • Media.MEDIA_PAUSED = 3;
  • Media.MEDIA_STOPPED = 4;

Methods

  • media.getCurrentAmplitude: Returns the current position within an audio file.

  • media.getCurrentPosition: Returns the current position within an audio file.

  • media.getDuration: Returns the duration of an audio file.

  • media.play: Start or resume playing an audio file.

  • media.pause: Pause playback of an audio file.

  • media.release: Releases the underlying operating system's audio resources.

  • media.seekTo: Moves the position within the audio file.

  • media.setVolume: Set the volume for audio playback.

  • media.startRecord: Start recording an audio file.

  • media.stopRecord: Stop recording an audio file.

  • media.stop: Stop playing an audio file.

Additional ReadOnly Parameters

  • position: The position within the audio playback, in seconds.

    • Not automatically updated during play; call getCurrentPosition to update.
  • duration: The duration of the media, in seconds.

media.getCurrentAmplitude

Returns the current amplitude of the current recording.

media.getCurrentAmplitude(mediaSuccess, [mediaError]);

Supported Platforms

  • Android
  • iOS

Parameters

  • mediaSuccess: The callback that is passed the current amplitude (0.0 - 1.0).

  • mediaError: (Optional) The callback to execute if an error occurs.

Quick Example

// Audio player
//
var my_media = new Media(src, onSuccess, onError);

// Record audio
my_media.startRecord();

mediaTimer = setInterval(function () {
    // get media amplitude
    my_media.getCurrentAmplitude(
        // success callback
        function (amp) {
            console.log(amp + "%");
        },
        // error callback
        function (e) {
            console.log("Error getting amp=" + e);
        }
    );
}, 1000);

media.getCurrentPosition

Returns the current position within an audio file. Also updates the Media object's position parameter.

media.getCurrentPosition(mediaSuccess, [mediaError]);

Parameters

  • mediaSuccess: The callback that is passed the current position in seconds.

  • mediaError: (Optional) The callback to execute if an error occurs.

Quick Example

// Audio player
//
var my_media = new Media(src, onSuccess, onError);

// Update media position every second
var mediaTimer = setInterval(function () {
    // get media position
    my_media.getCurrentPosition(
        // success callback
        function (position) {
            if (position > -1) {
                console.log((position) + " sec");
            }
        },
        // error callback
        function (e) {
            console.log("Error getting pos=" + e);
        }
    );
}, 1000);

media.getDuration

Returns the duration of an audio file in seconds. If the duration is unknown, it returns a value of -1.

media.getDuration();

Quick Example

// Audio player
//
var my_media = new Media(src, onSuccess, onError);

// Get duration
var counter = 0;
var timerDur = setInterval(function() {
    counter = counter + 100;
    if (counter > 2000) {
        clearInterval(timerDur);
    }
    var dur = my_media.getDuration();
    if (dur > 0) {
        clearInterval(timerDur);
        document.getElementById('audio_duration').innerHTML = (dur) + " sec";
    }
}, 100);

media.pause

Pauses playing an audio file.

media.pause();

Quick Example

// Play audio
//
function playAudio(url) {
    // Play the audio file at url
    var my_media = new Media(url,
        // success callback
        function () { console.log("playAudio():Audio Success"); },
        // error callback
        function (err) { console.log("playAudio():Audio Error: " + err); }
    );

    // Play audio
    my_media.play();

    // Pause after 10 seconds
    setTimeout(function () {
        my_media.pause();
    }, 10000);
}

media.play

Starts or resumes playing an audio file.

media.play();

Quick Example

// Play audio
//
function playAudio(url) {
    // Play the audio file at url
    var my_media = new Media(url,
        // success callback
        function () {
            console.log("playAudio():Audio Success");
        },
        // error callback
        function (err) {
            console.log("playAudio():Audio Error: " + err);
        }
    );
    // Play audio
    my_media.play();
}

iOS Quirks

  • numberOfLoops: Pass this option to the play method to specify the number of times you want the media file to play, e.g.:

      var myMedia = new Media("http://audio.ibeat.org/content/p1rj1s/p1rj1s_-_rockGuitar.mp3")
      myMedia.play({ numberOfLoops: 2 })
    
  • playAudioWhenScreenIsLocked: Pass in this option to the play method to specify whether you want to allow playback when the screen is locked. If set to true (the default value), the state of the hardware mute button is ignored, e.g.:

      var myMedia = new Media("http://audio.ibeat.org/content/p1rj1s/p1rj1s_-_rockGuitar.mp3")
      myMedia.play({ playAudioWhenScreenIsLocked : false })
    
  • order of file search: When only a file name or simple path is provided, iOS searches in the www directory for the file, then in the application's documents/tmp directory:

      var myMedia = new Media("audio/beer.mp3")
      myMedia.play()  // first looks for file in www/audio/beer.mp3 then in <application>/documents/tmp/audio/beer.mp3
    

media.release

Releases the underlying operating system's audio resources. This is particularly important for Android, since there are a finite amount of OpenCore instances for media playback. Applications should call the release function for any Media resource that is no longer needed.

media.release();

Quick Example

// Audio player
//
var my_media = new Media(src, onSuccess, onError);

my_media.play();
my_media.stop();
my_media.release();

media.seekTo

Sets the current position within an audio file.

media.seekTo(milliseconds);

Parameters

  • milliseconds: The position to set the playback position within the audio, in milliseconds.

Quick Example

// Audio player
//
var my_media = new Media(src, onSuccess, onError);
    my_media.play();
// SeekTo to 10 seconds after 5 seconds
setTimeout(function() {
    my_media.seekTo(10000);
}, 5000);

BlackBerry 10 Quirks

  • Not supported on BlackBerry OS 5 devices.

media.setVolume

Set the volume for an audio file.

media.setVolume(volume);

Parameters

  • volume: The volume to set for playback. The value must be within the range of 0.0 to 1.0.

Supported Platforms

  • Android
  • iOS

Quick Example

// Play audio
//
function playAudio(url) {
    // Play the audio file at url
    var my_media = new Media(url,
        // success callback
        function() {
            console.log("playAudio():Audio Success");
        },
        // error callback
        function(err) {
            console.log("playAudio():Audio Error: "+err);
    });

    // Play audio
    my_media.play();

    // Mute volume after 2 seconds
    setTimeout(function() {
        my_media.setVolume('0.0');
    }, 2000);

    // Set volume to 1.0 after 5 seconds
    setTimeout(function() {
        my_media.setVolume('1.0');
    }, 5000);
}

media.startRecord

Starts recording an audio file.

media.startRecord();

Supported Platforms

  • Android
  • iOS
  • Windows Phone 7 and 8
  • Windows

Quick Example

// Record audio
//
function recordAudio() {
    var src = "myrecording.mp3";
    var mediaRec = new Media(src,
        // success callback
        function() {
            console.log("recordAudio():Audio Success");
        },

        // error callback
        function(err) {
            console.log("recordAudio():Audio Error: "+ err.code);
        });

    // Record audio
    mediaRec.startRecord();
}

Android Quirks

  • Android devices record audio in Adaptive Multi-Rate format. The specified file should end with a .amr extension.
  • The hardware volume controls are wired up to the media volume while any Media objects are alive. Once the last created Media object has release() called on it, the volume controls revert to their default behaviour. The controls are also reset on page navigation, as this releases all Media objects.

iOS Quirks

  • iOS only records to files of type .wav and returns an error if the file name extension is not correct.

  • If a full path is not provided, the recording is placed in the application's documents/tmp directory. This can be accessed via the File API using LocalFileSystem.TEMPORARY. Any subdirectory specified at record time must already exist.

  • Files can be recorded and played back using the documents URI:

      var myMedia = new Media("documents://beer.mp3")
    

Windows Quirks

  • Windows devices can use MP3, M4A and WMA formats for recorded audio. However in most cases it is not possible to use MP3 for audio recording on Windows Phone 8.1 devices, because an MP3 encoder is not shipped with Windows Phone.

  • If a full path is not provided, the recording is placed in the AppData/temp directory. This can be accessed via the File API using LocalFileSystem.TEMPORARY or ms-appdata:///temp/<filename> URI.

  • Any subdirectory specified at record time must already exist.

Tizen Quirks

  • Not supported on Tizen devices.

media.stop

Stops playing an audio file.

media.stop();

Quick Example

// Play audio
//
function playAudio(url) {
    // Play the audio file at url
    var my_media = new Media(url,
        // success callback
        function() {
            console.log("playAudio():Audio Success");
        },
        // error callback
        function(err) {
            console.log("playAudio():Audio Error: "+err);
        }
    );

    // Play audio
    my_media.play();

    // Pause after 10 seconds
    setTimeout(function() {
        my_media.stop();
    }, 10000);
}

media.stopRecord

Stops recording an audio file.

media.stopRecord();

Supported Platforms

  • Android
  • iOS
  • Windows Phone 7 and 8
  • Windows

Quick Example

// Record audio
//
function recordAudio() {
    var src = "myrecording.mp3";
    var mediaRec = new Media(src,
        // success callback
        function() {
            console.log("recordAudio():Audio Success");
        },

        // error callback
        function(err) {
            console.log("recordAudio():Audio Error: "+ err.code);
        }
    );

    // Record audio
    mediaRec.startRecord();

    // Stop recording after 10 seconds
    setTimeout(function() {
        mediaRec.stopRecord();
    }, 10000);
}

Tizen Quirks

  • Not supported on Tizen devices.

MediaError

A MediaError object is returned to the mediaError callback function when an error occurs.

Properties

  • code: One of the predefined error codes listed below.

  • message: An error message describing the details of the error.

Constants

  • MediaError.MEDIA_ERR_ABORTED = 1
  • MediaError.MEDIA_ERR_NETWORK = 2
  • MediaError.MEDIA_ERR_DECODE = 3
  • MediaError.MEDIA_ERR_NONE_SUPPORTED = 4

About

Adavo edition

Resources

License

Contributing

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages

  • JavaScript 37.3%
  • C# 21.0%
  • Objective-C 18.8%
  • Java 17.8%
  • C++ 5.1%