Skip to content

Commit

Permalink
Merge pull request #52 from nzilbb/master
Browse files Browse the repository at this point in the history
Support recording directly to a given fileUrl
  • Loading branch information
edimuj committed Nov 29, 2017
2 parents 164e69c + 0d7ae97 commit b67c11d
Show file tree
Hide file tree
Showing 10 changed files with 1,297 additions and 92 deletions.
121 changes: 118 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ The plugin supports two different methods for microphone capture:
## Supported Platforms
* Android
* iOS
* browser

## Installation
From the Cordova Plugin Repository:
Expand Down Expand Up @@ -91,6 +92,81 @@ audioinput.start({
// Stop capturing audio input
audioinput.stop()

```

## Advanced Usage Example - saving to files
Use fileUrl in captureCfg if you want to save audio files directly to the file system.

This requires adding cordova-plugin-file to your project.

```javascript

// get access to the file system
window.requestFileSystem(window.TEMPORARY, 5*1024*1024, function(fs) {
console.log("Got file system: " + fs.name);
fileSystem = fs;

// now you can initialis audio, telling it about the file system you want to use
var captureCfg = {
sampleRate: 16000,
bufferSize: 8192,
channels: 1,
format: audioinput.FORMAT.PCM_16BIT,
audioSourceType: audioinput.AUDIOSOURCE_TYPE.DEFAULT,
fileUrl: cordova.file.cacheDirectory
};
window.audioinput.initialize(captureCfg, function() {

// now check whether we already have permission to access the microphone
window.audioinput.checkMicrophonePermission(function(hasPermission) {
if (hasPermission) {
console.log("already have permission to record");
} else {
// ask the user for permission to access the microphone
window.audioinput.getMicrophonePermission(function(hasPermission, message) {
if (hasPermission) {
console.log("granted permission to record");
} else {
console.warn("Denied permission to record");
}
}); // getMicrophonePermission
}
}); // checkMicrophonePermission
}); // initialize
}, function (e) {
console.log("Couldn't get file system: " + e.message)
});


// then later on, when we want to record to a file...

var captureCfg = {
fileUrl : cordova.file.cacheDirectory + "temp.wav"
}
audioinput.start(captureCfg);

// ... and when we're ready to stop recording
audioinput.stop(function(url) {
// now you have the URL (which might be different to the one passed in to start())
// you might, for example, read the data into a blob
window.resolveLocalFileSystemURL(url, function (tempFile) {
tempFile.file(function (tempWav) {
var reader = new FileReader();
reader.onloadend = function(e) {
var blob = new Blob([new Uint8Array(this.result)], { type: "audio/wav" });
// delete the temporary file
tempFile.remove(function (e) { console.log("temporary WAV deleted"); }, fileError);
// do something with the blob:
doSomethingWithWAVData(blob);
}
reader.readAsArrayBuffer(tempWav);
});
}, function(e) {
console.log("Could not resolveLocalFileSystemURL: " + e.message);
});
});


```

## Demos
Expand All @@ -104,8 +180,33 @@ Remember that unfiltered microphone output likely will create a nasty audio feed
* file-demo - How to encode recorded data to WAV format and save the resulting blob as a file. To run this demo ```cordova plugin add cordova-plugin-file``` is required.

## API
**Prepare for capturing audio** from the microphone.
Performs any required preparation for recording audio on the given platform.
```javascript
audioinput.initialize( captureCfg, onInitialized );
```

**Check whether the module already has permission to access the microphone.
The callback function has a single boolean argument, which is true if access to the microphone
has been granted, and false otherwise. The check is passive - the user is not asked for permission
if they haven't already granted it.
```javascript
audioinput.checkMicrophonePermission( onComplete );
```

**Obtains permission to access the microphone from the user.
This function will prompt the user for access to the microphone if they haven't already
granted it.
The callback function has two arguments:
* hasPermission - true if access to the microphone has been granted, and false otherwise.
* message - optionally, a reason message, hasPermission is false
```javascript
audioinput.getMicrophonePermission( onComplete );
```

**Start capturing audio** from the microphone.
If your app doesn't have recording permission on the users device, the plugin will ask for permission when start is called. And the new Android 6.0 runtime permissions are also supported.
Ensure that initialize and at least checkMicrophonePermission have been called before calling this.
The captureCfg parameter can include more configuration than previously passed to initialize.
```javascript
audioinput.start( captureCfg );
```
Expand Down Expand Up @@ -158,15 +259,29 @@ var captureCfg = {
// -VOICE_COMMUNICATION - Tuned for voice communications such as VoIP.
// -MIC - Microphone audio source. (Android only)
// -VOICE_RECOGNITION - Tuned for voice recognition if available (Android only)
audioSourceType: audioinput.AUDIOSOURCE_TYPE.DEFAULT
audioSourceType: audioinput.AUDIOSOURCE_TYPE.DEFAULT,

// Optionally specifies a file://... URL to which the audio should be saved.
// If this is set, then no audioinput events will be raised during recording.
// When stop is called, a single audioinputfinished event will be raised, with
// a "file" argument that contains the URL to which the audio was written,
// and the callback passed into stop() will be invoked.
// Currently, only WAV format files are guaranteed to be supported on all platforms.
// When called initialize(), this should be a URL to the directory in which files will
// be saved when calling start(), so that initialize() can ensure access to the directory
// is available.
fileUrl: null

};

```

**Stop capturing audio** from the microphone:
The callback function has a single string argument, which is the url where the file was saved,
if a fileUrl was passed in to start as part of captureCfg.
Note that the url passed out from stop is not guaranteed to be the same as the fileUrl passed in.
```javascript
audioinput.stop();
audioinput.stop( onStopped );
```

**Check if the plugin is capturing**, i.e. if it is started or not:
Expand Down
51 changes: 35 additions & 16 deletions plugin.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version='1.0' encoding='utf-8'?>
<plugin id="cordova-plugin-audioinput"
version="0.3.0"
version="0.5.0"
xmlns="http://apache.org/cordova/ns/plugins/1.0"
xmlns:android="http://schemas.android.com/apk/res/android">

Expand All @@ -9,8 +9,8 @@
<author>Edin Mujkanovic</author>
<license>MIT</license>
<keywords>cordova,phonegap,media,microphone,mic,input,audio,waapi,audionode,web,audio,api,audionode,capture,ios,android</keywords>
<repo>https://github.com/edimuj/cordova-plugin-audioinput.git</repo>
<issue>https://github.com/edimuj/cordova-plugin-audioinput/issues</issue>
<repo>git://github.com/nzilbb/cordova-plugin-audioinput.git</repo>
<!--issue>https://github.com/edimuj/cordova-plugin-audioinput/issues</issue-->

<js-module name="AudioInput" src="www/audioInputCapture.js">
<clobbers target="audioinput" />
Expand Down Expand Up @@ -39,21 +39,40 @@
<!-- ios -->
<platform name="ios">

<config-file parent="/*" target="config.xml">
<feature name="AudioInputCapture">
<param name="ios-package" value="CDVAudioInputCapture" />
</feature>
</config-file>
<config-file target="*-Info.plist" parent="NSMicrophoneUsageDescription">
<string>This app needs microphone access</string>
</config-file>

<source-file src="src/ios/CDVAudioInputCapture.m" />
<source-file src="src/ios/AudioReceiver.h" />
<source-file src="src/ios/AudioReceiver.m" />

<framework src="Accelerate.framework" weak="true" />
<framework src="CoreAudio.framework" weak="true" />
<framework src="AudioToolbox.framework" weak="true" />
<framework src="AVFoundation.framework" weak="true" />
<config-file parent="/*" target="config.xml">
<feature name="AudioInputCapture">
<param name="ios-package" value="CDVAudioInputCapture" />
</feature>
</config-file>

<source-file src="src/ios/CDVAudioInputCapture.m" />
<source-file src="src/ios/AudioReceiver.h" />
<source-file src="src/ios/AudioReceiver.m" />

<framework src="Accelerate.framework" weak="true" />
<framework src="CoreAudio.framework" weak="true" />
<framework src="AudioToolbox.framework" weak="true" />
<framework src="AVFoundation.framework" weak="true" />

</platform>

<!-- browser -->
<platform name="browser">
<config-file parent="/*" target="config.xml">
<feature name="AudioInputCapture">
<param name="browser-package" value="AudioInputCapture" />
</feature>
</config-file>
<js-module src="src/browser/AudioInputCaptureProxy.js" name="AudioInputCaptureProxy">
<runs />
</js-module>
<asset src="src/browser/RecorderWorker.js" target=".">
<runs />
</asset>
</platform>

</plugin>
Loading

0 comments on commit b67c11d

Please sign in to comment.