Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support recording directly to a given fileUrl #52

Merged
merged 18 commits into from
Nov 29, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
1a1fda0
Add suppport for saving WAV file directly.
robertfromont Jan 31, 2017
99f833c
Delete temporary file after we've finished with it.
robertfromont Jan 31, 2017
2e06d29
Initial implementation of native file writing (currently excludes
robertfromont Jul 10, 2017
f8148db
Initial implementation of native file writing
robertfromont Jul 10, 2017
32b8b70
Ensure that plugin will work with or without fileUrl, validate URL, r…
robertfromont Jul 11, 2017
7bb90a7
Android: Ensure the file URL used for recording is the URL given by t…
robertfromont Jul 18, 2017
f5655a1
Change repo URL and version to differentiate plugin from 'standard' v…
robertfromont Jul 18, 2017
d4731b0
Android: Ensure current state is checked on start/stop.
robertfromont Jul 18, 2017
b8ff95c
Don't pause/start when going to background/foreground on iOS when rec…
robertfromont Jul 27, 2017
cd98e41
Add support for the "browser" platform, and add API calls for intiali…
robertfromont Nov 12, 2017
cfbb38c
Fix copy/paste error in README
robertfromont Nov 12, 2017
f2a194e
Implement new API functions on Android.
robertfromont Nov 12, 2017
cdfdf41
Add NSMicrophoneUsageDescription string to info.plist file, in order …
robertfromont Nov 19, 2017
2ff2394
iOS: implement new initialize, checkMicrophonePermission, getMicropho…
robertfromont Nov 19, 2017
76becd5
iOS: ensure file URL returned when finished recording is the one that…
robertfromont Nov 19, 2017
e850d9e
Get fileUrl usage working on Chrome by ensuring URL is of the form cd…
robertfromont Nov 27, 2017
39766b6
Fix RecorderWorker.js target.
robertfromont Nov 27, 2017
0d7ae97
Update README to include fileUrl example.
robertfromont Nov 27, 2017
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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