{"record":{"id":"854ca7c6daad4dcb","repo":"unslothai/unsloth","slug":"path-path-name-decoded-to-no-audio-samples","errorCode":null,"errorMessage":"{Path(path).name} decoded to no audio samples.","messagePattern":"(.+?) decoded to no audio samples\\.","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"studio/backend/core/training/diffusion_h3_clips.py","lineNumber":456,"sourceCode":"        # is accepted input here -- only the first num_frames are trained and the caller is merely\n        # warned -- so decoding the rest of the soundtrack would spend a whole recording's time\n        # and memory to build a sub-second sample, and would fail on damage in a region that is\n        # never used.\n        for frame in container.decode(audio = 0):\n            for resampled in resampler.resample(frame):\n                block = resampled.to_ndarray().reshape(-1, H3_AUDIO_CHANNELS)\n                chunks.append(block)\n                have += block.shape[0]\n            if have >= target_samples:\n                break\n        if have < target_samples:\n            # Only when the stream ran out: the resampler holds a partial block back, and that\n            # tail is what the pad allowance below is measured against. After an early break\n            # there is nothing to flush for -- the window is already full.\n            for resampled in resampler.resample(None):\n                chunks.append(resampled.to_ndarray().reshape(-1, H3_AUDIO_CHANNELS))\n    if not chunks:\n        raise ValueError(f\"{Path(path).name} decoded to no audio samples.\")\n    samples = np.concatenate(chunks, axis = 0).astype(\"float32\")[:target_samples]\n    if samples.shape[0] < target_samples:\n        missing = target_samples - samples.shape[0]\n        if missing > _MAX_AUDIO_PAD_FRACTION * target_samples:\n            have_s = samples.shape[0] / H3_AUDIO_SAMPLING_RATE\n            want_s = target_samples / H3_AUDIO_SAMPLING_RATE\n            raise ValueError(\n                f\"{Path(path).name} carries {have_s:.2f}s of audio for a {want_s:.2f}s clip. \"\n                f\"MiniMax-H3 denoises video and audio together, so padding the rest with \"\n                f\"silence would train the adapter to stop generating sound. Use a clip whose \"\n                f\"soundtrack runs its full length.\"\n            )\n        samples = np.pad(samples, ((0, missing), (0, 0)))\n    # A muted track runs the clip's full length, so every check above passes and the window comes\n    # back all zeros -- the same target the short-audio refusal exists to keep out, arriving by a\n    # route that refusal cannot see. Measured as peak amplitude rather than mean energy so a clip\n    # that is merely quiet, or silent for most of its length with one real sound in it, is kept:\n    # only a track with nothing above the floor anywhere is turned away.","sourceCodeStart":438,"sourceCodeEnd":474,"githubUrl":"https://github.com/unslothai/unsloth/blob/203007d19051dcd2ae33876786d117c99f6b0368/studio/backend/core/training/diffusion_h3_clips.py#L438-L474","documentation":"Raised by _decode_clip_audio() when the audio resampler produced zero chunks — the clip has an audio track but no samples could be decoded from it. This is distinct from 'carries no audio track': the stream exists, yet decoding it yields nothing. It protects the H3 objective, where audio rows are trained, from an empty waveform.","triggerScenarios":"A container with a declared audio stream that is empty (0 samples) or whose codec data cannot be decoded by PyAV; a remux that kept the stream header but dropped the packets; a truncated download that kept the moov atom but not the media data.","commonSituations":"Broken remuxes/metadata-only rewrites; partial downloads; exotic or corrupted audio codecs; files processed by tools that create placeholder audio streams.","solutions":["Re-encode the file's audio with ffmpeg (ffmpeg -i in.mp4 -c:v copy -c:a aac out.mp4) to rebuild a decodable track.","Remove the corrupt clip from the dataset if the source is unrecoverable.","Pre-scan datasets by attempting a small decode of the audio stream and skipping files that yield no samples."],"exampleFix":"# before\nwaveform = _decode_clip_audio(path, target_samples, av, np)  # empty stream -> ValueError\n\n# after\n# repair the file first:\n#   ffmpeg -i broken.mp4 -c:v copy -c:a aac fixed.mp4\nwaveform = _decode_clip_audio(fixed_path, target_samples, av, np)","handlingStrategy":"try-catch","validationCode":"import av\n\ndef audio_decodes(path: str) -> bool:\n    try:\n        with av.open(path) as c:\n            if not c.streams.audio:\n                return False\n            for packet in c.demux(c.streams.audio[0]):\n                for _ in packet.decode():\n                    return True\n    except Exception:\n        return False\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 samples\" in str(e):\n        skip_and_log(p)  # or ffmpeg -i p -c:v copy -c:a aac repaired.mp4\n    else:\n        raise","preventionTips":["Re-encode suspect files' audio with ffmpeg before adding them to the dataset.","Avoid metadata-only remuxes that keep stream headers but drop packets."],"tags":["audio","video","codec","dataset"],"backgroundTag":null,"analyzedSha":"203007d19051dcd2ae33876786d117c99f6b0368","analyzedAt":"2026-08-15T02:48:39.846Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}