2
votes

We would like to support serving Ogg Opus on as many phones as reasonably possible.

Based on Wikipedia and our experimentation, we have found:

  • Android 5.0+ supports Ogg Opus in Matroska (.mkv,.mka) or WebM (.webm) container format
  • Android 7.0+ supports Ogg Opus in Ogg (.ogg) container format (with .opus as an alias)
  • Android 10+ supports Ogg Opus in Ogg (.opus) container format
  • iOS 11+ supports Ogg Opus in Core Audio Format (.caf) container format

Android documentation states that .ogg and .mkv is supported from 5.0+, but experimentation proves otherwise.

We would like to use AWS S3 to store the audio in some base format (like .mkv) which would be served nativity to Android. For requests from iOS, we would like to redirect those to the AWS Lambda function that would take the base format and repackage the audio stream into the .caf container format. It shouldn't need any transcoding since the codec (Ogg Opus) is the same in both cases.

Any suggestions on how implement an AWS Lambda? We would prefer to use Python, but open to using the other supported languages.

Update:

  • I was looking at Pydub based on finding this article: Simple Audio Processing in Python With Pydub, but directly using ffmpeg might be better for this.
  • The conversion is simple enough to use ffmpeg and opusenc (from opus-tools) so the .webm file will be store in S3.
ffmpeg -i foo.mp3 foo.wav
opusenc --bitrate 16 --hard-cbr foo.wav foo.opus
ffmpeg -i foo.opus -acodec copy -f webm foo.webm
  • The conversion from .webm to .caf can easily be done by ffmpeg as well.
ffmpeg -i foo.webm -acodec copy -f caf foo.caf

So the question is: how to setup a Lambda that either returns the .webm file stored in S3 or does this conversion via the lambda layer? Should the returned format be based on http headers (i.e. ACCEPT) or file extension?

1
It is unclear to me what you want to do. Transcode files with a Lambda? Serve files with a Lambda? Can you please add some detail what exactly you want to do? - Jens
@Jens Thanks. I have added more detail. Is that better? - chrish
The problem seems to be "download file from S3, rename ogg file to a caf file and returning it to the user": this won't be very fast. So if you want to do that for example in a music player app, the user experience is going to be poor. I am not 100% sure for what you need this, but I have the very strong feeling, that a Lambda is not the right way. Do you know which device you are running on before you make the request? If so: why not store the caf file alongside the mkv/ogg/opus file in S3 and directly request it? - Jens
@Jens This is a very large repository of audio. There is content stored for thousands of languages and for each language the collection of audio in MP3 64Kbps is about 500-800MB. We would like to provide a lower bitrate version and found that Ogg Opus 16Kbps is better that MP3 16Kbps. However, we would not like to keep duplicates (.webm and .caf) for each new file. As you say, it would be too slow to provide on demand so we plan on storing the audio as Ogg Opus. - chrish
I am confused now. I still don't get what you want to achieve? Do you want to use Lambda to create a caf file for every new file you store in S3 (but just once) or do you want to create a new caf file every time a opus file is requested by an iOS device? - Jens

1 Answers

1
votes

I ended up using mobile-ffmpeg-full and convert the container from webm to caf.

    // If an WebM, use FFmpeg to convert container to CAF
    let error = MobileFFmpeg.execute("-i \"\(fileURL.path)\" -acodec copy \"\(cafFileURL.path)\"")