Skip to content

feat(video): support muxing an audio track in make_mp4_writer - #138

Open
lstein wants to merge 1 commit into
mainfrom
minimax-h3/01-audio-mux
Open

feat(video): support muxing an audio track in make_mp4_writer#138
lstein wants to merge 1 commit into
mainfrom
minimax-h3/01-audio-mux

Conversation

@lstein

@lstein lstein commented Aug 4, 2026

Copy link
Copy Markdown
Owner

Summary

Groundwork for MiniMax H3 (stacked PR 1 of 5): teaches the shared MP4 writer to mux an audio track, so video models that jointly generate audio (H3 produces 32 kHz stereo alongside frames) can save it inside the video container — no new asset type, service, or dependency needed.

  • make_mp4_writer gains optional audio_path / audio_codec="aac" kwargs. imageio 2.37 / imageio-ffmpeg 0.6 already forward these to ffmpeg (-i <audio> -acodec <codec>); AAC-LC is the browser-safe choice for MP4.
  • New write_stereo_wav helper: float PCM (2, n) in [-1, 1] → 16-bit stereo WAV. Conversion runs in float64 (fp16 input would round 1.0·32767 up to 32770 and wrap peaks to -32768); NaN becomes silence; out-of-range clips.
  • audio_path is existence-checked at construction: ffmpeg spawns lazily on the first frame append, so a missing file otherwise surfaces as an unexplained BrokenPipeError mid-encode — or, for tiny clips, silently produces no output.

Two caveats documented in the module docstring for future callers:

  • imageio-ffmpeg passes no -shortest, so container duration = max(stream durations). Callers must pre-trim audio to the video duration.
  • Never pass audio_codec="copy" for a PCM WAV — PCM-in-MP4 doesn't play in browsers.

Existing callers (wan_latents_to_video, video_concat, video_frame_extract_range) are unaffected: the no-audio path builds the identical writer call as before.

Testing

  • uv run pytest tests/app/util/test_video_encoding.py — 8 passed. New cases: aac stream present + container duration not stretched; codec forwarding pinned with a non-default codec (mp3) since ffmpeg's MP4 default is already aac; fast-fail on missing audio file; fp16/NaN safety; WAV format/clipping; no-audio output has no audio stream.
  • Manually verified the muxed MP4: h264 + aac (LC), 32000 Hz, stereo, duration exactly matches frames/fps.

🤖 Generated with Claude Code

Adds optional audio_path/audio_codec to make_mp4_writer (imageio-ffmpeg
forwards them to ffmpeg as a second input) and a write_stereo_wav helper
that produces the 16-bit stereo WAV the writer consumes. Groundwork for
video models that generate audio alongside frames (e.g. MiniMax H3).

Callers must pre-trim audio to the video duration: imageio-ffmpeg passes
no -shortest, so the container duration is the max of the streams.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant