Repository navigation
[Model][Bug fix] Decode request audio with libsndfile first, so uploads work with a video-only FFmpeg - #639
Conversation
Automated reviewThis PR changes Findings: none. I checked the following:
The description is accurate and states what was tested and what wasn't. It also discloses the one behavior change for current users: stereo input now comes out 1/√2 as loud as FFmpeg's downmix produced. Advisory, not a merge gate. Rules: |
9ecb45d to
5cce1fd
Compare
merceod
left a comment
There was a problem hiding this comment.
Checked on klone (1bca43a, same own files as this head). libsndfile first works for the uploads tried, and with #609 under it the 48,001 Hz and 100,003 Hz uploads are refused in 0.02-0.05 s. The first head opened the unbounded-resample hole (#589) on every model through the base loader (a 3 s WAV at 48,001 Hz took 4.5 s and 13 GB, at 100,003 Hz 9.2 s and 26.5 GB); stacking on #609 closed it and the description says so now. CPU tests pass, ruff clean. Nothing to fix.
6b0a375 to
4086c07
Compare
Live test: [Model][Bug fix] Decode request audio with libsndfile first, for a video-only FFmpegWorks: with FFmpeg's audio decoders removed, WAV, FLAC, OGG and MP3 transcribe on the PR and fail on base. 1x H200, Whisper large-v3, Python frontend, SHM transport · PR head
Other
|
4086c07 to
ab60fb8
Compare
|
Thanks for the live test.
Since the approval: no code change. The description now has a merge-order note for #644 (both rewrite |
The Dynamo base image's FFmpeg 8 is video-only, and torchcodec loads it before the full FFmpeg the image installs. Fixes mstar-project#534
…o resamples it The libsndfile path resamples with torchaudio, whose kernel for a rate coprime to 16 kHz grows with rate * 16000; on top of the resample-rate bound, such a header is a 400, not gigabytes of kernel in the data worker.
ab60fb8 to
b81a833
Compare
…libsndfile first, and check Chatterbox's at the API (#779) * [TTS][API server] Read OmniVoice and Chatterbox reference audio with libsndfile first, and check Chatterbox's at the API OmniVoice decoded its cloning reference with torchcodec only, so on a server whose FFmpeg has no audio decoders (the base image #639 fixed Model.load_audio for) even a WAV reference failed; its API check used torchcodec too. Chatterbox's adapter never checked ref_audio at all: a bad clip failed only after admission, and a reference up to the data worker's 30-minute cap was accepted where the other voice-clone adapters stop at 60 s. - check_ref_audio gains decoder="soundfile+torchcodec", the base loader's order: libsndfile, then FFmpeg for what it cannot open. - OmniVoice's load_audio uses load_audio_file at the codec rate, and its adapter checks with that mode. - Chatterbox's adapter goes through _resolve_ref_audio with that mode, like the OmniVoice and Qwen3-TTS adapters, so it also takes bare base64. A reference not at the codec rate is now resampled by torchaudio instead of FFmpeg's resampler, so OmniVoice's cloned output can move slightly for it. * Docs: say what Chatterbox's ref_audio check accepts and refuses Routing Chatterbox's ref_audio through the shared check means bare base64 is now accepted, and a clip over 60 s or below 8 kHz is a 400 instead of being trimmed by the model. Update the adapter docstring, the MAX_REF_AUDIO_SECONDS comment and docs/models.rst to match. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * media_io: refuse a reference clip with no samples A WAV with a valid header and 0 frames passed check_ref_audio in both libsndfile modes: sound_file_seconds reads 0 frames as "not declared", the count then gives 0 s, and only the upper bound was checked. --------- Co-authored-by: Kirill Vasilev <290354918+vasilevklart@users.noreply.github.com> Co-authored-by: Joseph Tan <jdtan638@gmail.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Fixes #534
What does this PR do?
In the Dynamo base image, torchcodec loads the base's video-only FFmpeg 8 before the full FFmpeg 6.1 the Dockerfile installs, so every audio upload fails to decode ("Invalid data found when processing input"). A host without FFmpeg's shared libraries fails the same way today.
Model.load_audionow goes through the sharedload_audio_file: libsndfile (soundfile) first, torchcodec for the containers libsndfile cannot open. WAV, FLAC, OGG and MP3 no longer depend on the FFmpeg build.load_audioinmstar/model/base.pydecodes viaload_audio_file: soundfile first, torchcodec second, torchaudio resample, channel mean. [API server][Model][Security] Refuse audio sample rates whose resampling kernel is unbounded #609's sample-rate bound inload_audio_filerefuses a crafted header rate before torchaudio builds its kernel, which FFmpeg's resampler never needed on this path.pip install soundfilein CPU Core (.github/workflows/ci.yml): the new tests, and 26 cases intest_media_paths.py, skip without it.test/modular/test_base_load_audio.py: a torchcodec stand-in that fails as FFmpeg 8 does; 4 containers at 16 and 24 kHz; a crafted 100,003 or 48,001 Hz header refused before torchaudio resamples it.How was it tested?
On b81a833 (head, on main f17b321), CI's install plus soundfile: CPU Core, the
ci.ymlpaths with-n 4: 5,064 passed, 610 skipped, 5 failed: three LingBot-World shell tests that needftfyandscipy, which CI installs and this venv lacks (they fail the same way on main here), and two signal tests (test_e2e_validators.py,test_eval_framework.py) that fail only undernohup, which this run used, and pass when run directly;test_base_load_audio.pywithtest_resample_rate_bound.py: 187 passed. Earlier, on 6b0a375 (the head's own diff, on main 422d785), CPU, CI's install plus soundfile:ruff check .is clean. The CPU core list then: 2660 passed, 203 skipped, 2 failed (test_wan_vae_decode.py; the same 2 fail on main in this environment).python -m pytest test/modular/test_base_load_audio.py: 12 passed (11 fail on main, and the 2 crafted-rate cases fail on 2539338, before the rebase onto #609; the torchcodec fallback case passes on main too). Decode against main's torchcodec path (FFmpeg 6.1, 3 s clips): a 16 kHz mono WAV is sample-identical; details in "Decoded audio against main".Real-user checks on one H200 (served on b733780, the same commits on #609's previous head dec613d): Whisper-large-v3 served from this PR and from main on 115 uploads (WAV in 10 encodings, FLAC, MP3, OGG, M4A, 16 sample rates, crafted and broken headers, 30 min files). With torchcodec hidden, main answers 103 of them with a 500 and this PR serves 94, as main does with FFmpeg; with FFmpeg both serve 95, 84 of 92 transcripts are identical (the rest differ at resampler level), and three of main's 500s for broken WAVs become a 200 or a 400. Before the rebase onto #609, one 320 KB WAV with a 768,001 Hz header pushed the server process to 192 GB until the kernel killed it.
Not tested
The Dynamo image itself (needs an image build); the stand-in fails the way the issue's FFmpeg 8 does, and an H200 without torchcodec stands in for it in the served check.
Not here: OmniVoice's own
load_audiostill uses torchcodec only. A FLAC whose header leaves the sample count out is refused by libsndfile's whole-file read and still needs FFmpeg (#708). M4A and WebM in the Dynamo image still need the issue's option 1 (keep FFmpeg 8 off the M* stage's loader path).Merge order with #644
#644 also rewrites
Model.load_audio(a torchcodec decode capped at 30 min). Neither PR is stacked on the other: whichever lands second resolvesload_audiotoload_audio_file, which #644 caps, so the result keeps libsndfile first and the cap.Decoded audio against main
Synthetic 3 s clips (220 Hz tone plus noise), decoded to 16 kHz mono by main's
AudioDecoder(path, sample_rate=16000, num_channels=1)and byload_audio_file(path, 16000); torch 2.12.1, torchcodec 0.17.0, Ubuntu's FFmpeg 6.1, libsndfile 1.2.2.librosa.load(mono=True)) and M*'s other decode paths doSame sample count in every case.
Tests in detail
test_base_load_audio.pyswaps in atorchcodec.decoders.AudioDecoderthat raises "Could not open input file ... Invalid data found when processing input" and records its calls:Checklist
ruff check .passesAI assistance: written with AI coding agent