{"record":{"id":"67274f86ddb5d754","repo":"unslothai/unsloth","slug":"path-path-name-carries-no-audio-track-minimax","errorCode":null,"errorMessage":"{Path(path).name} carries no audio track. MiniMax-H3 denoises video and audio in one packed sequence, so its training clips must have sound.","messagePattern":"(.+?) carries no audio track\\. MiniMax-H3 denoises video and audio in one packed sequence, so its training clips must have sound\\.","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"studio/backend/core/training/diffusion_h3_clips.py","lineNumber":294,"sourceCode":"    is the dataset contract -- pre-trim to the training duration -- but it used to be silent,\n    which is how a caption describing a whole scene ended up on its first second. ``on_note``\n    is called once per over-long clip with the numbers, so the run reports it.\n\n    ``waveform`` is a float32 array of shape ``(2, h3_audio_sample_count(num_frames))`` at\n    32 kHz. A mono source is duplicated to both channels; a clip with **no** audio track is\n    refused rather than silently trained as silence, because the audio rows are in the objective\n    and a silent target teaches the model to stop generating sound.\n    \"\"\"\n    import av\n    import numpy as np\n    from PIL import Image\n\n    target_samples = h3_audio_sample_count(num_frames)\n    with av.open(str(path)) as container:\n        if not container.streams.video:\n            raise ValueError(f\"{Path(path).name} carries no video track.\")\n        if not container.streams.audio:\n            raise ValueError(\n                f\"{Path(path).name} carries no audio track. MiniMax-H3 denoises video and audio \"\n                f\"in one packed sequence, so its training clips must have sound.\"\n            )\n        stream = container.streams.video[0]\n        source_fps = float(stream.average_rate or stream.guessed_rate or H3_FPS) or float(H3_FPS)\n        # Container duration, in seconds, for the over-long note below. Best effort: an unknown\n        # duration simply means no note, never a failed decode.\n        source_duration_s = 0.0\n        try:\n            if stream.duration is not None and stream.time_base is not None:\n                source_duration_s = float(stream.duration * stream.time_base)\n            elif getattr(container, \"duration\", None):\n                source_duration_s = float(container.duration) / 1_000_000.0\n        except Exception:  # noqa: BLE001 -- a note is not worth failing a decode over\n            source_duration_s = 0.0\n\n        frames: list[Any] = []\n        next_target = 0","sourceCodeStart":276,"sourceCodeEnd":312,"githubUrl":"https://github.com/unslothai/unsloth/blob/203007d19051dcd2ae33876786d117c99f6b0368/studio/backend/core/training/diffusion_h3_clips.py#L276-L312","documentation":"Raised by decode_clip() when the container has a video track but no audio track. MiniMax-H3 denoises video and audio in one packed sequence, and the audio rows are part of the training objective, so an audio-less clip is refused rather than silently trained as silence (a silent target would teach the model to stop generating sound).","triggerScenarios":"Passing a muted render, a screen recording captured without system audio, an exported animation/GIF-to-mp4 conversion, or stock b-roll delivered without a soundtrack.","commonSituations":"AI-generated video clips (many generators emit silent files); OBS/screen-capture defaults with audio disabled; stock footage proxies stripped of audio for size; timelapse exports.","solutions":["Replace the clip with a version that has a real audio track, or add a soundtrack before training.","Exclude silent clips from the dataset via a pre-scan (container.streams.audio empty).","For generated clips, pair them with a licensed audio bed so captions describing sound have a target."],"exampleFix":"# before\n# dataset of AI-generated silent .mp4s -> \"carries no audio track\"\n\n# after\n# mux an audio bed: ffmpeg -loop 1 -i silent.mp4 -i bed.wav -shortest out.mp4\n# or filter at ingest:\nwith av.open(p) as c:\n    if not c.streams.audio:\n        skip(p)  # report and exclude","handlingStrategy":"validation","validationCode":"import av\n\ndef has_audio_track(path: str) -> bool:\n    try:\n        with av.open(path) as c:\n            return bool(c.streams.audio)\n    except av.error.InvalidDataError:\n        return False","typeGuard":null,"tryCatchPattern":"try:\n    frames, waveform = decode_clip(p, num_frames=n, width=w, height=h)\nexcept ValueError as e:\n    if \"no audio track\" in str(e):\n        skip_and_log(p)\n    else:\n        raise","preventionTips":["Exclude silent/AI-generated clips unless you mux in a soundtrack first.","Check container.streams.audio during dataset ingestion, not at train time."],"tags":["video","audio","dataset","minimax-h3"],"backgroundTag":null,"analyzedSha":"203007d19051dcd2ae33876786d117c99f6b0368","analyzedAt":"2026-08-15T02:48:39.846Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}