13

I am using expo and I am trying to record on android by using the webm output format ( Expo.Audio.RECORDING_OPTION_ANDROID_OUTPUT_FORMAT_WEBM ). My issue is that I have tried all the different encoders and none of them seem to work. I was expecting that the vorbis encoder would work ( Expo.Audio.RECORDING_OPTION_ANDROID_AUDIO_ENCODER_VORBIS ) but I always get back an exception

    {
        "tryLoc": "root",
        "completion": {
            "type": "throw",
            "arg": {
                "framesToPop": 1,
                "code": "E_AUDIO_RECORDING",
                "message": "Start encountered an error: recording not started",
                "stack": "Error: Start encountered an error: recording not started\n    at createErrorFromErrorData (blob:http://172.16.6.80:19001/96c6e3c7-f483-40d9-a3ad-7a7114468a07:2297:17)\n    at blob:http://172.16.6.80:19001/96c6e3c7-f483-40d9-a3ad-7a7114468a07:2249:27\n    at MessageQueue.__invokeCallback (blob:http://172.16.6.80:19001/96c6e3c7-f483-40d9-a3ad-7a7114468a07:2691:18)\n    at blob:http://172.16.6.80:19001/96c6e3c7-f483-40d9-a3ad-7a7114468a07:2436:18\n    at MessageQueue.__guardSafe (blob:http://172.16.6.80:19001/96c6e3c7-f483-40d9-a3ad-7a7114468a07:2604:11)\n    at MessageQueue.invokeCallbackAndReturnFlushedQueue (blob:http://172.16.6.80:19001/96c6e3c7-f483-40d9-a3ad-7a7114468a07:2435:14)\n    at http://172.16.6.80:19001/debugger-ui/debuggerWorker.js:72:58"
            }
        }
    }

This is the configuration that I am trying:

const recording = new Audio.Recording();
debugger;
await recording.prepareToRecordAsync({
  android: {
    extension: '.webm',
    outputFormat: Audio.RECORDING_OPTION_ANDROID_OUTPUT_FORMAT_WEBM,
    audioEncoder: Audio.RECORDING_OPTION_ANDROID_AUDIO_ENCODER_VORBIS,
    sampleRate: 44100,
    numberOfChannels: 2,
    bitRate: 128000
  },
  ios: {
    extension: '.wav',
    audioQuality: Audio.RECORDING_OPTION_IOS_AUDIO_QUALITY_MAX,
    sampleRate: 44100,
    numberOfChannels: 2,
    bitRate: 128000,
    linearPCMBitDepth: 16,
    linearPCMIsBigEndian: false,
    linearPCMIsFloat: false,
  },
});

Any ideas on why that happens and what is the appropriate encoder that I have to use?

Stavros Zavrakas
  • 3,045
  • 1
  • 17
  • 30
  • Have you asked for permission before trying to record? `const { status } = await Expo.Permissions.askAsync(Expo.Permissions.AUDIO_RECORDING);` The const `status` will have the value `granted` if user authorizes audio recording. – shimatai Feb 12 '18 at 04:38
  • @shimatai - yes I ask for the proper permissions. I am able to record with the `outputFormat: Audio.RECORDING_OPTION_ANDROID_OUTPUT_FORMAT_AAC_ADTS` and `audioEncoder: Audio.RECORDING_OPTION_ANDROID_AUDIO_ENCODER_AAC` but ideally i'd like to happen with webm. – Stavros Zavrakas Feb 12 '18 at 10:25
  • Did you ever get this to work? My observation is that when I duplicate the HIGH quality definition in my code (with a modified name) and then reference the local definition, it is ignored and the low quality recording, 3gp vs m4a, results. – Fitter Man Feb 16 '21 at 04:37
  • @FitterMan As far as I remember I couldn't find something that was working for me. I ended up creating a backend service, send whatever I was getting from ios and android and transcoding it by using AWS transcode. It wasn't ideal but was covering our needs. – Stavros Zavrakas Feb 16 '21 at 08:53

2 Answers2

0

I am shooting in the dark, hope this may be of help.

Enabling Audio and customizing Audio Mode

Expo.Audio.setIsEnabledAsync(value) Audio is enabled by default, but if you want to write your own Audio API in a detached app, you might want to disable the Expo Audio API.

Arguments value (boolean) — true enables Expo Audio, and false disables it.

Returns A Promise that will reject if audio playback could not be enabled for the device.

Expo.Audio.setAudioModeAsync(mode) We provide this API to customize the audio experience on iOS and Android.

These key value pairs may help as well.

  • prepareToRecordAsync()
  • stopAndUnloadAsync()

Audio Encoder list: (*I suggest using the Default just to debug it)

audioEncoder:

  • Expo.Audio.RECORDING_OPTION_ANDROID_AUDIO_ENCODER_DEFAULT

  • Expo.Audio.RECORDING_OPTION_ANDROID_AUDIO_ENCODER_AMR_NB

  • Expo.Audio.RECORDING_OPTION_ANDROID_AUDIO_ENCODER_AMR_WB

  • Expo.Audio.RECORDING_OPTION_ANDROID_AUDIO_ENCODER_AAC

  • Expo.Audio.RECORDING_OPTION_ANDROID_AUDIO_ENCODER_HE_AAC

  • Expo.Audio.RECORDING_OPTION_ANDROID_AUDIO_ENCODER_AAC_ELD

  • Expo.Audio.RECORDING_OPTION_ANDROID_AUDIO_ENCODER_VORBIS

Reference: expo.io (13/Feb/2018).

NOTE *.webm (Streamable only in Android 4.0 and above)

Reference: developer.android.com (13/Feb/2018).

Try use below code, high and low quality and android & ios:

  export const RECORDING_OPTIONS_PRESET_HIGH_QUALITY: RecordingOptions = {
  android: {
    extension: '.m4a',
    outputFormat: RECORDING_OPTION_ANDROID_OUTPUT_FORMAT_MPEG_4,
    audioEncoder: RECORDING_OPTION_ANDROID_AUDIO_ENCODER_AAC,
    sampleRate: 44100,
    numberOfChannels: 2,
    bitRate: 128000,
  },
  ios: {
    extension: '.caf',
    audioQuality: RECORDING_OPTION_IOS_AUDIO_QUALITY_MAX,
    sampleRate: 44100,
    numberOfChannels: 2,
    bitRate: 128000,
    linearPCMBitDepth: 16,
    linearPCMIsBigEndian: false,
    linearPCMIsFloat: false,
  },
};

export const RECORDING_OPTIONS_PRESET_LOW_QUALITY: RecordingOptions = {
  android: {
    extension: '.3gp',
    outputFormat: RECORDING_OPTION_ANDROID_OUTPUT_FORMAT_THREE_GPP,
    audioEncoder: RECORDING_OPTION_ANDROID_AUDIO_ENCODER_AMR_NB,
    sampleRate: 44100,
    numberOfChannels: 2,
    bitRate: 128000,
  },
  ios: {
    extension: '.caf',
    audioQuality: RECORDING_OPTION_IOS_AUDIO_QUALITY_MIN,
    sampleRate: 44100,
    numberOfChannels: 2,
    bitRate: 128000,
    linearPCMBitDepth: 16,
    linearPCMIsBigEndian: false,
    linearPCMIsFloat: false,
  },
};

Reference: expo.io (13/Feb/2018).

BH7
  • 204
  • 2
  • 8
  • I already use everything from the things above except for the `setIsEnabledAsync` because the application is not detached (yet). Is there a specific combination that can work? I can proved with the configurations that I provide to `Expo.Audio.setAudioModeAsync`, `prepareToRecordAsync` and `stopAndUnloadAsync`. – Stavros Zavrakas Feb 14 '18 at 10:35
  • @stavros.zavrakas - use above code for a guide and see if it can work with your current setup. – BH7 Feb 15 '18 at 02:38
0

I spotted 2 problems. One was a mysterious issue with Expo where if I duplicated the high definition from the docs (source code) and used it locally, it would fail to register. I eventually went back to one of their examples that just did a simple start/stop of recording and worked forward, without a problem. I dug around a while and my conclusion is there is a sequence of initialization that has to be followed precisely to get the initialization of these settings to be accepted.

Once past the previous problem, I found that the following worked with Google Speech to Text. AWS indicates that they also accept AMR audio.

    android: {
      extension: '.amr',
      outputFormat: Audio.RECORDING_OPTION_ANDROID_OUTPUT_FORMAT_AMR_WB,
      audioEncoder: Audio.RECORDING_OPTION_ANDROID_AUDIO_ENCODER_AMR_WB,
      sampleRate: 16000,
      numberOfChannels: 1,
      bitRate: 128000,
    },
Fitter Man
  • 682
  • 8
  • 17