Support Ogg files with multiple tracks
Version
Media3 1.8.0
More version details
some ogg files (created from flac with libvorbis) are not playing at all, sometimes showing "(0) Source Error"
i have all extensions enabled, and DefaultRenderersFactory.EXTENSION_RENDERER_MODE_PREFER is set
my dependencies section:
dependencies {
def extensions_version = "1.8.0"
implementation "androidx.media3:media3-decode-av1:$extensions_version" // av1 extension
implementation "androidx.media3:media3-decode-ffmpeg:$extensions_version" // ffmpeg extension
implementation "androidx.media3:media3-decode-flac:$extensions_version" // flac extension
implementation "androidx.media3:media3-decode-iamf:$extensions_version" // iamf extension
implementation "androidx.media3:media3-decode-opus:$extensions_version" // opus extension
implementation "androidx.media3:media3-decode-vp9:$extensions_version" // vp9 extension
implementation "androidx.media3:media3-extractor:$extensions_version"
def exoplayer_version = "1.8.0"
implementation "androidx.media3:media3-exoplayer:$exoplayer_version"
implementation "androidx.media3:media3-exoplayer-dash:$exoplayer_version"
implementation "androidx.media3:media3-exoplayer-hls:$exoplayer_version"
implementation "androidx.media3:media3-exoplayer-smoothstreaming:$exoplayer_version"
implementation "androidx.annotation:annotation:1.8.1"
}
i'm using v1.8.0 but i also tried v1.9.0-alpha01 with the same results
how the files where created:
def convert_flac_to_ogg(flac_path, ogg_path, quality=8):
os.makedirs(os.path.dirname(ogg_path), exist_ok=True)
command = [
"ffmpeg",
"-i", flac_path,
"-c:a", "libvorbis",
"-qscale:a", str(quality),
ogg_path
]
print(f"Converting: {flac_path} -> {ogg_path}")
subprocess.run(command, check=True)
ps: file plays normally using mpv
Devices that reproduce the issue
- Redmi Note 10 (Android 11)
- Redmi Note 14 Pro (Android 14)
- (probably not device related)
Devices that do not reproduce the issue
none
Reproducible in the demo app?
Yes
Reproduction steps
- Play any file from the sample below
- no sound or progress
Expected result
should play normally
Actual result
player just stalls, no progress or sound, sometimes showing "(0) Source Error"
Media
https://github.com/user-attachments/files/19930802/1973.-.Ring.Ring.zip
Bug Report
- [ ] You will email the zip file produced by
adb bugreportto [email protected] after filing this issue.
I looked at 01 - Ring Ring.ogg. ExoPlayer is failing to play this because it is not recognized by our OggExtractor.
This is because the stream is not recognized as containing FLAC, Vorbis or Opus data here: https://github.com/androidx/media/blob/f38876c95e43b516b55df8001d33ee4d91bd80e7/libraries/extractor/src/main/java/androidx/media3/extractor/ogg/OggExtractor.java#L105-L113
The vorbis-in-ogg spec says:
The Ogg stream must be unmultiplexed (only one stream, a Vorbis audio stream, per link) ... The first Vorbis packet (the identification header), which uniquely identifies a stream as Vorbis audio, is placed alone in the first page of the logical Ogg stream. This results in a first Ogg page of exactly 58 bytes at the very beginning of the logical stream.
01 - Ring Ring.ogg has both a theora video track and a vorbis audio track (you can see this with mediainfo), which contradicts the wording of this spec. ExoPlayer expects the first Ogg packet to be a vorbis one (as the spec says), but it's actually a theora one, so sniffing fails and the file doesn't play. The second Ogg packed in the file is the vorbis ID one.
I think this boils down to a feature request to support vorbis muxed with other formats into an ogg container. We have no plans to work on this, but would consider a high quality well-tested PR for this (but it's likely a large enough piece of work we should have some design discussion in this issue first, and agree on which specs we are following, if you are interested in pursuing this).
Alternatively, you should be able to use ffmpeg or other tools to re-mux your file into an ogg file with only a vorbis track which ExoPlayer should be able to play.
thanks for the detailed response! it makes sense now
I think this boils down to a feature request to support vorbis muxed with other formats into an ogg container. We have no plans to work on this, but would consider a high quality well-tested PR for this (but it's likely a large enough piece of work we should have some design discussion in this issue first, and agree on which specs we are following, if you are interested in pursuing this).
sad but understandable, i would have loved to pr but i have no experience with this sadly, hopefully someone can take care of this in future
btw small question, if ogg sniffing returns false internally, why not instead assign ffmpeg extension to deal with the file? i assume there are internal checks like these before deciding the extractor to use but im curious for why ffmpeg isn't used as a general fallback for cases like this
thanks again!
btw small question, if ogg sniffing returns false internally, why not instead assign ffmpeg extension to deal with the file?
The ExoPlayer FFmpeg extension only provides decoding support, not extracting.
For the record a very large part was done https://github.com/google/ExoPlayer/pull/10807 but I could never get the necessary answer to finish it to be accepted.
Edit: I have an updated version maintained over current media 3 and using that in prod since a very long time without any problems.
@Tolriq oh that looks nice, is it possible to open a pr with ur changes (or share how to use ur version if possible)?
Just apply the changes and build locally. There's no point in opening and maintaining a PR if there's no follow up on the questions. The media3 team currently lack bandwidth to deal the huge amount of support and complex PRs.
for anyone looking for this, i did the changes as @Tolriq suggested and they work fine now. so far no issues.
steps:
- fork media repo and apply the changes here
- or use my fork
- fork building repo, edit
build.ymland changerepositoryandrefto your media fork, then action buildCI- or use my fork
- download the artifact, put it in
myproject/android/repo(u can remove what you won't be using except the (VIP) ones shown below), then depend on it locally (build.gradle)
rootProject.allprojects {
repositories {
google()
mavenCentral()
maven {
url = project(':myproject').file('repo')
}
}
}
dependencies {
// add these (VIP)
def exoplayer_version = "1.8.0-o"
implementation "androidx.media3:media3-extractor:$exoplayer_version"
implementation "androidx.media3:media3-common:$exoplayer_version"
implementation "androidx.media3:media3-container:$exoplayer_version"
implementation "androidx.media3:media3-database:$exoplayer_version"
implementation "androidx.media3:media3-datasource:$exoplayer_version"
// your usual exoplayer implementation
implementation "androidx.media3:media3-exoplayer:$exoplayer_version"
implementation "androidx.media3:media3-exoplayer-dash:$exoplayer_version"
implementation "androidx.media3:media3-exoplayer-hls:$exoplayer_version"
implementation "androidx.media3:media3-exoplayer-smoothstreaming:$exoplayer_version"
}
- changes source: https://github.com/google/ExoPlayer/commit/4013a97e2e4440c6c17e5860f2607d88c5d0b751
- my fork with the changes applied on v1.8.0: https://github.com/MSOB7YY/media/tree/ogg
- my fork for building the aar libraries: https://github.com/MSOB7YY/media3libs
many thanks for
- @Tolriq for providing changes and suggestion
- @ag2s20150909 for the building workflow repo
- @icbaker for the follow up and explanation
- and ofc androidx/media team for this awesome player
Would be best to have it upstream if there's anyone to answer the questions to make the decisions.