From 6248979ce8eda1e1e623c316a2347f8f9d809a36 Mon Sep 17 00:00:00 2001 From: Daniil Polyakov Date: Fri, 24 Jul 2026 18:09:09 +0300 Subject: [PATCH] Fix Symphonia total_duration for video containers --- CHANGELOG.md | 3 ++- assets/README.md | 3 +++ assets/video_with_audio.mp4 | Bin 0 -> 23924 bytes src/decoder/symphonia.rs | 9 ++++---- tests/video_container_test.rs | 40 ++++++++++++++++++++++++++++++++++ 5 files changed, 49 insertions(+), 6 deletions(-) create mode 100644 assets/video_with_audio.mp4 create mode 100644 tests/video_container_test.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index e0f149dec..4acc1aefb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -51,7 +51,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fixed sources to correctly handle sample rate and channel count changes at span boundaries. - Fixed sources to detect parameter updates after mid-span seeks. - Fixed `Stoppable` and `Skippable` not signaling exhaustion. -- Fixed `SpatialAudio` left and write channel swapping +- Fixed `SpatialAudio` left and write channel swapping. +- Fixed the Symphonia decoder reporting a wrong `total_duration` for containers whose default track is not the decoded audio track. ## Version [0.22.2] (2026-03-05) diff --git a/assets/README.md b/assets/README.md index c65c31664..d47067c56 100644 --- a/assets/README.md +++ b/assets/README.md @@ -1,3 +1,6 @@ ## License The `music.wav` and `music.ogg` files in this directory are under cc-by-sa. + +`video_with_audio.mp4` is synthetic, generated from ffmpeg's `testsrc` (video) +and `sine` (audio) sources, and carries no third-party licensing. diff --git a/assets/video_with_audio.mp4 b/assets/video_with_audio.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..57db0fdf29535d337fb044dcfbb92935c196793c GIT binary patch literal 23924 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 OiS6NNVs$u~Sm|G3>p5Nk literal 0 HcmV?d00001 diff --git a/src/decoder/symphonia.rs b/src/decoder/symphonia.rs index 5e1c68849..82f3ea302 100644 --- a/src/decoder/symphonia.rs +++ b/src/decoder/symphonia.rs @@ -107,10 +107,9 @@ impl SymphoniaDecoder { }; let mut probed = get_probe().format(&hint, mss, &format_opts, &metadata_opts)?; - let stream = match probed.format.default_track() { - Some(stream) => stream, - None => return Ok(None), - }; + if probed.format.default_track().is_none() { + return Ok(None); + } // Select the first supported track let track = probed @@ -131,7 +130,7 @@ impl SymphoniaDecoder { let total_duration = track .codec_params .time_base - .zip(stream.codec_params.n_frames) + .zip(track.codec_params.n_frames) .map(|(base, spans)| base.calc_time(spans).into()) .filter(|d: &Duration| !d.is_zero()); diff --git a/tests/video_container_test.rs b/tests/video_container_test.rs new file mode 100644 index 000000000..8cbacc1df --- /dev/null +++ b/tests/video_container_test.rs @@ -0,0 +1,40 @@ +//! Regression tests for decoding the audio track of a container whose +//! *default* track is not the audio track — i.e. a video file. +//! +//! `assets/video_with_audio.mp4` holds a 2 s H.264 video track (the default, +//! 60 frames) plus a 2 s mono AAC audio track. + +#![cfg(all(feature = "symphonia-aac", feature = "symphonia-isomp4"))] + +use rodio::{Decoder, Source}; + +fn decode_video_asset() -> Decoder { + let file = std::fs::File::open("assets/video_with_audio.mp4").unwrap(); + let len = file.metadata().unwrap().len(); + Decoder::builder() + .with_data(file) + .with_byte_len(len) + .with_seekable(true) + .build() + .unwrap() +} + +/// `total_duration` must come from the audio track (~2.02 s), not the video +/// track. The buggy pairing reported ~0.7 s, so a generous lower bound alone +/// distinguishes the two, and the tight check pins the correct value. +#[test] +fn reports_audio_track_duration_not_default_track() { + let duration = decode_video_asset() + .total_duration() + .expect("video container should report a total duration") + .as_secs_f64(); + assert!( + duration > 1.5, + "duration {duration}s looks like the video track's frame count, not the audio track" + ); + let expected = 2.023_219_954; + assert!( + (duration - expected).abs() < 0.01, + "got {duration}s, expected about {expected}s" + ); +}