Skip to content

Commit d5b2778

Browse files
rakannimerjsierles
authored andcommitted
Added dynamic passing of AudioEncoding, OutputFormat and AudioEncodingBitRate (jsierles#86)
* Added Android support. Missing progress tracking. * Re-indent and added skipToSeconds and setCurrentTime * Reset state after playback is finished * Updated README.md, added android support * Updated instructions for Android * added shared index for example. * Renamed playFromPath to play for consistency with iOS API * Reflected AudioPlayerManager method name change in AudioRecorderManager * Added ReadableMap options argument to preparePlaybackPath * Returned result of all methods in AudioPlayer [js] for promise support. * Removed unused imports from AudioPlayerManager * Better error when path is not specified * Added support for dynamically passing OutputFormat, AudioEncoding and AudioEncodingBitRate. * Integrated README changes before merge * Added getDurationFromPath(path) [Android]
1 parent 1a13bce commit d5b2778

File tree

4 files changed

+82
-23
lines changed

4 files changed

+82
-23
lines changed

Audio.ios.js

+14-8
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ var AudioPlayer = {
2121
} else {
2222
options = {sessionCategory: 'SoloAmbient', numberOfLoops: 0}
2323
}
24-
AudioPlayerManager.play(path, options);
24+
return AudioPlayerManager.play(path, options);
2525
},
2626
playWithUrl: function(url, options) {
2727
if (options) {
@@ -32,22 +32,22 @@ var AudioPlayer = {
3232
} else {
3333
options = {sessionCategory: 'SoloAmbient', numberOfLoops: 0}
3434
}
35-
AudioPlayerManager.playWithUrl(url, options);
35+
return AudioPlayerManager.playWithUrl(url, options);
3636
},
3737
pause: function() {
38-
AudioPlayerManager.pause();
38+
return AudioPlayerManager.pause();
3939
},
4040
unpause: function() {
41-
AudioPlayerManager.unpause();
41+
return AudioPlayerManager.unpause();
4242
},
4343
stop: function() {
44-
AudioPlayerManager.stop();
44+
return AudioPlayerManager.stop();
4545
},
4646
setCurrentTime: function(time) {
47-
AudioPlayerManager.setCurrentTime(time);
47+
return AudioPlayerManager.setCurrentTime(time);
4848
},
4949
skipToSeconds: function(position) {
50-
AudioPlayerManager.skipToSeconds(position);
50+
return AudioPlayerManager.skipToSeconds(position);
5151
},
5252
setProgressSubscription: function() {
5353
if (this.progressSubscription) this.progressSubscription.remove();
@@ -69,6 +69,10 @@ var AudioPlayer = {
6969
}
7070
);
7171
},
72+
getDurationFromPath: function(path){
73+
return AudioPlayerManager.getDurationFromPath(path);
74+
},
75+
7276
getDuration: function(callback) {
7377
AudioPlayerManager.getDuration((error, duration) => {
7478
callback(duration);
@@ -88,7 +92,9 @@ var AudioRecorder = {
8892
Channels: 2,
8993
AudioQuality: 'High',
9094
AudioEncoding: 'ima4',
91-
MeteringEnabled: false
95+
OutputFormat: 'mpeg_4',
96+
MeteringEnabled: false,
97+
AudioEncodingBitRate: 32000
9298
};
9399
var recordingOptions = {...defaultOptions, ...options};
94100

AudioExample/index.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@ class AudioExample extends Component {
2727
SampleRate: 22050,
2828
Channels: 1,
2929
AudioQuality: "Low",
30-
AudioEncoding: "aac"
30+
AudioEncoding: "aac",
31+
AudioEncodingBitRate: 32000
3132
});
3233
}
3334

android/src/main/java/com/rnim/rn/audio/AudioPlayerManager.java

+18-8
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package com.rnim.rn.audio;
22

3-
import android.Manifest;
43
import android.content.Context;
54

65
import com.facebook.react.bridge.ReactApplicationContext;
@@ -15,13 +14,10 @@
1514
import java.util.HashMap;
1615
import java.util.Map;
1716

18-
import android.content.pm.PackageManager;
1917
import android.os.Environment;
20-
import android.media.MediaRecorder;
2118
import android.media.MediaPlayer;
2219
import android.media.AudioManager;
23-
import android.support.v4.app.ActivityCompat;
24-
import android.support.v4.content.ContextCompat;
20+
2521
import android.util.Log;
2622

2723
import com.facebook.react.modules.core.DeviceEventManagerModule;
@@ -72,6 +68,20 @@ public Map<String, Object> getConstants() {
7268
}
7369

7470

71+
@ReactMethod
72+
public void getDurationFromPath(String path, Promise promise ) {
73+
if (path == null) {
74+
Log.e("PATH_NOT_SET", "Please add path");
75+
promise.reject("PATH_NOT_SET", "Please add path");
76+
return;
77+
}
78+
boolean mediaPlayerReady = preparePlaybackAtPath("local", path, promise);
79+
if (!mediaPlayerReady){
80+
return;
81+
}
82+
promise.resolve(mediaPlayer.getDuration());
83+
}
84+
7585
@ReactMethod
7686
public void getDuration(Promise promise) {
7787
if (mediaPlayer == null) {
@@ -127,7 +137,7 @@ public void unpause(Promise promise) {
127137
}
128138

129139
@ReactMethod
130-
public void play(String path, final Promise promise) {
140+
public void play(String path, ReadableMap playbackSettings, final Promise promise) {
131141
if (isPlaying) {
132142
Log.e("INVALID_STATE", "Please wait for previous playback to finish.");
133143
promise.reject("INVALID_STATE", "Please set valid path");
@@ -138,8 +148,8 @@ public void play(String path, final Promise promise) {
138148
return;
139149
}
140150
if (path == null) {
141-
Log.e("INVALID_STATE", "Please set valid path");
142-
promise.reject("INVALID_STATE", "Please set valid path");
151+
Log.e("INVALID_PATH", "Please set valid path");
152+
promise.reject("INVALID_PATH", "Please set valid path");
143153
return;
144154
}
145155

android/src/main/java/com/rnim/rn/audio/AudioRecorderManager.java

+48-6
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,6 @@ public AudioRecorderManager(ReactApplicationContext reactContext) {
5151
@Override
5252
public Map<String, Object> getConstants() {
5353
Map<String, Object> constants = new HashMap<>();
54-
5554
constants.put(DocumentDirectoryPath, this.getReactApplicationContext().getFilesDir().getAbsolutePath());
5655
constants.put(PicturesDirectoryPath, Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).getAbsolutePath());
5756
constants.put(MainBundlePath, "");
@@ -85,15 +84,17 @@ public void prepareRecordingAtPath(String recordingPath, ReadableMap recordingSe
8584
recorder = new MediaRecorder();
8685
try {
8786
recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
88-
recorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
89-
recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
87+
int outputFormat = getOutputFormatFromString(recordingSettings.getString("OutputFormat"));
88+
recorder.setOutputFormat(outputFormat);
89+
int audioEncoder = getAudioEncoderFromString(recordingSettings.getString("AudioEncoding"));
90+
recorder.setAudioEncoder(audioEncoder);
9091
recorder.setAudioSamplingRate(recordingSettings.getInt("SampleRate"));
9192
recorder.setAudioChannels(recordingSettings.getInt("Channels"));
92-
recorder.setAudioEncodingBitRate(32000); //recordingSettings.getInt("EncodingBitRate"));
93+
recorder.setAudioEncodingBitRate(recordingSettings.getInt("AudioEncodingBitRate"));
9394
recorder.setOutputFile(recordingPath);
9495
}
9596
catch(final Exception e) {
96-
promise.reject("COULDNT_CONFIGURE_AUDIO_SOURCE" , "Make sure you've added RECORD_AUDIO permission to your AndroidManifest.xml file "+e.getMessage());
97+
promise.reject("COULDNT_CONFIGURE_MEDIA_RECORDER" , "Make sure you've added RECORD_AUDIO permission to your AndroidManifest.xml file "+e.getMessage());
9798
return;
9899
}
99100

@@ -107,6 +108,47 @@ public void prepareRecordingAtPath(String recordingPath, ReadableMap recordingSe
107108

108109
}
109110

111+
private int getAudioEncoderFromString(String audioEncoder) {
112+
switch (audioEncoder) {
113+
case "aac":
114+
return MediaRecorder.AudioEncoder.AAC;
115+
case "aac_eld":
116+
return MediaRecorder.AudioEncoder.AAC_ELD;
117+
case "amr_nb":
118+
return MediaRecorder.AudioEncoder.AMR_NB;
119+
case "amr_wb":
120+
return MediaRecorder.AudioEncoder.AMR_WB;
121+
case "he_aac":
122+
return MediaRecorder.AudioEncoder.HE_AAC;
123+
case "vorbis":
124+
return MediaRecorder.AudioEncoder.VORBIS;
125+
default:
126+
Log.d("INVALID_AUDIO_ENCODER", "USING MediaRecorder.AudioEncoder.DEFAULT instead of "+audioEncoder+": "+MediaRecorder.AudioEncoder.DEFAULT);
127+
return MediaRecorder.AudioEncoder.DEFAULT;
128+
}
129+
}
130+
131+
private int getOutputFormatFromString(String outputFormat) {
132+
switch (outputFormat) {
133+
case "mpeg_4":
134+
return MediaRecorder.OutputFormat.MPEG_4;
135+
case "aac_adts":
136+
return MediaRecorder.OutputFormat.AAC_ADTS;
137+
case "amr_nb":
138+
return MediaRecorder.OutputFormat.AMR_NB;
139+
case "amr_wb":
140+
return MediaRecorder.OutputFormat.AMR_WB;
141+
case "three_gpp":
142+
return MediaRecorder.OutputFormat.THREE_GPP;
143+
case "webm":
144+
return MediaRecorder.OutputFormat.WEBM;
145+
default:
146+
Log.d("INVALID_OUPUT_FORMAT", "USING MediaRecorder.OutputFormat.DEFAULT : "+MediaRecorder.OutputFormat.DEFAULT);
147+
return MediaRecorder.OutputFormat.DEFAULT;
148+
149+
}
150+
}
151+
110152
@ReactMethod
111153
public void startRecording(Promise promise){
112154
if (recorder == null){
@@ -161,7 +203,7 @@ public void unpausePlaying(Promise promise){
161203

162204
@ReactMethod
163205
public void playRecording(final Promise promise) {
164-
audioPlayerManager.play(currentOutputFile, promise);
206+
audioPlayerManager.play(currentOutputFile, null, promise);
165207
}
166208

167209

0 commit comments

Comments
 (0)