unslothai/unsloth · error · ValueError
{Path(path).name} decoded to no audio samples.
Error message
{Path(path).name} decoded to no audio samples. What it means
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.
Source
Thrown at studio/backend/core/training/diffusion_h3_clips.py:456
# is accepted input here -- only the first num_frames are trained and the caller is merely
# warned -- so decoding the rest of the soundtrack would spend a whole recording's time
# and memory to build a sub-second sample, and would fail on damage in a region that is
# never used.
for frame in container.decode(audio = 0):
for resampled in resampler.resample(frame):
block = resampled.to_ndarray().reshape(-1, H3_AUDIO_CHANNELS)
chunks.append(block)
have += block.shape[0]
if have >= target_samples:
break
if have < target_samples:
# Only when the stream ran out: the resampler holds a partial block back, and that
# tail is what the pad allowance below is measured against. After an early break
# there is nothing to flush for -- the window is already full.
for resampled in resampler.resample(None):
chunks.append(resampled.to_ndarray().reshape(-1, H3_AUDIO_CHANNELS))
if not chunks:
raise ValueError(f"{Path(path).name} decoded to no audio samples.")
samples = np.concatenate(chunks, axis = 0).astype("float32")[:target_samples]
if samples.shape[0] < target_samples:
missing = target_samples - samples.shape[0]
if missing > _MAX_AUDIO_PAD_FRACTION * target_samples:
have_s = samples.shape[0] / H3_AUDIO_SAMPLING_RATE
want_s = target_samples / H3_AUDIO_SAMPLING_RATE
raise ValueError(
f"{Path(path).name} carries {have_s:.2f}s of audio for a {want_s:.2f}s clip. "
f"MiniMax-H3 denoises video and audio together, so padding the rest with "
f"silence would train the adapter to stop generating sound. Use a clip whose "
f"soundtrack runs its full length."
)
samples = np.pad(samples, ((0, missing), (0, 0)))
# A muted track runs the clip's full length, so every check above passes and the window comes
# back all zeros -- the same target the short-audio refusal exists to keep out, arriving by a
# route that refusal cannot see. Measured as peak amplitude rather than mean energy so a clip
# that is merely quiet, or silent for most of its length with one real sound in it, is kept:
# only a track with nothing above the floor anywhere is turned away.View on GitHub (pinned to 203007d190)
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.
Example fix
# before waveform = _decode_clip_audio(path, target_samples, av, np) # empty stream -> ValueError # after # repair the file first: # ffmpeg -i broken.mp4 -c:v copy -c:a aac fixed.mp4 waveform = _decode_clip_audio(fixed_path, target_samples, av, np)
Defensive patterns
Strategy: try-catch
Validate before calling
import av
def audio_decodes(path: str) -> bool:
try:
with av.open(path) as c:
if not c.streams.audio:
return False
for packet in c.demux(c.streams.audio[0]):
for _ in packet.decode():
return True
except Exception:
return False
return False Try / catch
try:
frames, waveform = decode_clip(p, num_frames=n, width=w, height=h)
except ValueError as e:
if "no audio samples" in str(e):
skip_and_log(p) # or ffmpeg -i p -c:v copy -c:a aac repaired.mp4
else:
raise Prevention
- Re-encode suspect files' audio with ffmpeg before adding them to the dataset.
- Avoid metadata-only remuxes that keep stream headers but drop packets.
When it happens
Trigger: 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.
Common situations: Broken remuxes/metadata-only rewrites; partial downloads; exotic or corrupted audio codecs; files processed by tools that create placeholder audio streams.
Related errors
- {Path(path).name} carries no video track.
- {Path(path).name} carries no audio track. MiniMax-H3 denoise
- {Path(path).name} carries {have_s:.2f}s of audio for a {want
- WebM export failed (libvpx-vp9 unavailable?): {exc}
- MiniMax-H3 was trained on aspect ratios from 1:4 to 4:1; thi
AI-assisted analysis of unslothai/unsloth@203007d190 (2026-08-15).
Data as JSON: /api/errors/854ca7c6daad4dcb.
Report an issue: GitHub.