unslothai/unsloth · error · ValueError
{Path(path).name} carries {have_s:.2f}s of audio for a {want
Error message
{Path(path).name} carries {have_s:.2f}s of audio for a {want_s:.2f}s clip. MiniMax-H3 denoises video and audio together, so padding the rest with silence would train the adapter to stop generating sound. Use a clip whose soundtrack runs its full length. What it means
Raised by _decode_clip_audio() when the clip's audio runs short of the required sample count by more than _MAX_AUDIO_PAD_FRACTION of the window. Small shortfalls are padded with silence, but a large one is refused: MiniMax-H3 denoises video and audio together, so padding most of the window with silence would train the adapter to stop generating sound. Note the follow-up check separately rejects an all-zero (muted) track by peak amplitude.
Source
Thrown at studio/backend/core/training/diffusion_h3_clips.py:463
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.
if float(np.max(np.abs(samples))) <= _SILENT_AUDIO_PEAK:
raise ValueError(
f"{Path(path).name} has a soundtrack that is silent all the way through. "
f"MiniMax-H3 denoises video and audio together, so training on it would teach the "
f"adapter to stop generating sound. Use a clip whose soundtrack has audio in it, or "
f"take this one out of the dataset."
)View on GitHub (pinned to 203007d190)
Solutions
- Use a clip whose soundtrack runs the full length — remux/trim so audio covers the video (ffmpeg -i in.mp4 -t <aud_dur> -c copy out.mp4).
- Trim the video to the audio's duration so the training window is fully covered.
- Pre-scan dataset files comparing stream durations and flag any where audio_duration < video_duration beyond the pad tolerance.
Example fix
# before # clip: 6.0s video, 3.0s audio, window 5.83s -> >pad fraction -> ValueError # after # trim video to the audio's length before adding to the dataset: # ffmpeg -i clip.mp4 -t 3.0 -c copy trimmed.mp4
Defensive patterns
Strategy: validation
Validate before calling
import av
def audio_covers_video(path: str, tolerance: float = 0.9) -> bool:
with av.open(path) as c:
v, a = c.streams.video[0], c.streams.audio[0]
vd = float(v.duration * v.time_base) if v.duration and v.time_base else 0.0
ad = float(a.duration * a.time_base) if a.duration and a.time_base else 0.0
if vd == 0.0 or ad == 0.0:
return True # unknown -> let decode decide
return ad >= vd * tolerance Try / catch
try:
frames, waveform = decode_clip(p, num_frames=n, width=w, height=h)
except ValueError as e:
if "soundtrack runs its full length" in str(e):
skip_and_log(p) # or trim: ffmpeg -i p -t <audio_dur> -c copy trimmed.mp4
else:
raise Prevention
- Trim clips so the audio stream spans the whole video before ingest.
- Compare audio vs video stream durations during dataset validation and flag short soundtracks.
When it happens
Trigger: A video track longer than its audio track — audio starts late or ends early (e.g. 6s of video over 3s of audio); clips trimmed on the video stream only; sources whose soundtrack is shorter than the container duration.
Common situations: Editing software exporting video with detached/stopped audio; concatenations where the audio stream is shorter than the video stream; clips recorded with audio starting mid-recording; downloaded streams where the last audio packets are missing.
Related errors
- {Path(path).name} carries no audio track. MiniMax-H3 denoise
- MiniMax-H3 was trained on aspect ratios from 1:4 to 4:1; thi
- {Path(path).name} carries no video track.
- {Path(path).name} decoded to {len(frames)} frames at {H3_FPS
- {Path(path).name} decoded to no audio samples.
AI-assisted analysis of unslothai/unsloth@203007d190 (2026-08-15).
Data as JSON: /api/errors/503668174736a0b4.
Report an issue: GitHub.