expo-audio
's
AndroidOutputFormat
and
AndroidAudioEncoder
unions are a strict subset of what the underlying
MediaRecorder
supports.
MediaRecorder.OutputFormat.OGG
and
MediaRecorder.AudioEncoder.OPUS
have been available since API 29 (Android 10, 2019) but are not reachable from JS, even though the rest of the recording pipeline is a straight passthrough to
MediaRecorder
.
Adding them is a ~20 line change: two enum entries plus API 29 guards in
AudioRecords.kt
, and two entries in
Audio.types.ts
.
Two concrete wins that the current M4A/AAC-only path can't deliver:
  1. Crash-safe recordings.
    M4A is an MP4 container — it requires the muxer to finalise the
    moov
    atom on
    stop()
    . If the app is killed mid-recording the file is unplayable. OGG is a chunked, self-describing container: every page is independently valid and carries its own CRC. A killed recording remains playable up to the last complete page. This is the main reason we reach for OGG on Android.
  2. Opus is dramatically more efficient for voice than AAC.
    32 kbps mono Opus is effectively transparent for speech. A 20-minute recording is ~5 MB at the settings we use, versus ~19 MB for the AAC default — useful for memory, storage, and upload cost. Opus also has lower latency and is the default voice codec for every modern browser/WebRTC stack.
Both use cases are reachable today if you drop down to writing a native module, but that's a lot of plumbing for two enum entries.