llfbandit / record

Audio recorder from microphone to a given file path. No external dependencies, MediaRecorder is used for Android an AVAudioRecorder for iOS.
https://pub.dev/packages/record
228 stars 188 forks source link

OPUS format does not record on iOS, documentation conflicting #320

Open jt274 opened 3 months ago

jt274 commented 3 months ago

Package version 5.1.0

Environment

Describe the bug

Front page of documentation states OPUS encoding is not available on iOS: https://pub.dev/packages/record

AudioEncoder enum states under opus that it is supported with SDK 11+: https://pub.dev/documentation/record/latest/record/AudioEncoder.html

However, when recording on iOS it throws an error: PlatformException(record, Failed to start recording, opus not supported., null)

Either this is a bug, or the documentation is incorrect. However, iOS does indeed support an opus encoder since SDK 11, so it should be working.

Add your record configuration RecordConfig(...)

RecordConfig(
  encoder: AudioEncoder.opus,
  sampleRate: 16000,
  bitRate: 8000,
  numChannels: 1,
)

Expected behavior

Audio should record using opus encoder on iOS 11+.

Additionally, documentation states OPUS is recorded in MPEG_4 container, but CHANGELOG states with version 4.0.1 that OPUS is now in OGG containers, so documentation is out of date.

llfbandit commented 3 months ago

Opus audio format is not natively supported by iOS. Fixing documentation.

jt274 commented 3 months ago

@llfbandit According to Apple Developer docs, opus codec is supported on iOS 11+ using kAudioFormatOpus for AVFormatIDKey. https://developer.apple.com/documentation/coreaudiotypes/kaudioformatopus

record_darwin specifies this here: https://github.com/llfbandit/record/blob/de508bbeddff92aa087412c4e20660d0e65fe03c/record_darwin/darwin/Classes/RecorderFormat.swift#L80

llfbandit commented 3 months ago

Opus is available for decoding only.

jt274 commented 3 months ago

Opus is available for decoding only.

@llfbandit I edited this file: https://github.com/llfbandit/record/blob/de508bbeddff92aa087412c4e20660d0e65fe03c/record_darwin/darwin/Classes/Recorder.swift#L127

I added the line: AudioEncoder.opus.rawValue

I then tried recording using AudioEncoder.opus on iOS, and the recording was successful. Reading the first bytes of the output file I can see that it was recorded in a CAFF container, which is what is expected for iOS.

So I believe iOS does support opus as an encoder (and the documentation of the package was correct in saying SDK 11+), but the record_darwin package left out the opus format in the isEncoderSupported function.

llfbandit commented 3 months ago

Can you send me a simple audio file with this setup? If I remember well, the underlying encoder was not opus. Maybe I'm wrong?

jt274 commented 3 months ago

I used the following config:

RecordConfig(
  encoder: AudioEncoder.opus,
  sampleRate: 16000,
  bitRate: 8000,
  numChannels: 1,
)

After recording an audio file, I analyzed it with ffprobe:

Input #0, caf, from '1.caf':
  Duration: 00:00:08.66, start: 0.000000, bitrate: 37 kb/s
  Stream #0:0: Audio: opus (opus / 0x7375706F), 48000 Hz, mono, fltp

For some reason the bitrate and sample rate are not correct, but it is working in opus format.

llfbandit commented 3 months ago

Ok, that's good news! I'm not very surprised if iOS does not support those values.

The only caveat here (before testing & re-introducing this encoding) is CAF. This container is only supported by Apple products/platforms.

jt274 commented 3 months ago

Yes, ideally there would be a solution to convert to OGG container, but I can figure something out for that.

llfbandit commented 3 months ago

Another funny thing, Safari only supports opus in CAF container and not OGG. Welcome to my world :)