unslothai/unsloth · error · ValueError
{Path(path).name} carries no video track.
Error message
{Path(path).name} carries no video track. What it means
Raised by decode_clip() (via av) when the opened container has no video stream at all. MiniMax-H3 training decodes video frames plus audio jointly, so a container without a video track cannot produce a training clip. The sibling check immediately after refuses audio-less files, so both halves of the packed sequence are enforced.
Source
Thrown at studio/backend/core/training/diffusion_h3_clips.py:292
The window is the FIRST ``num_frames`` of the source, and the latents are cached once for
the run, so a longer clip trains only its opening and its caption is paired with that. That
is the dataset contract -- pre-trim to the training duration -- but it used to be silent,
which is how a caption describing a whole scene ended up on its first second. ``on_note``
is called once per over-long clip with the numbers, so the run reports it.
``waveform`` is a float32 array of shape ``(2, h3_audio_sample_count(num_frames))`` at
32 kHz. A mono source is duplicated to both channels; a clip with **no** audio track is
refused rather than silently trained as silence, because the audio rows are in the objective
and a silent target teaches the model to stop generating sound.
"""
import av
import numpy as np
from PIL import Image
target_samples = h3_audio_sample_count(num_frames)
with av.open(str(path)) as container:
if not container.streams.video:
raise ValueError(f"{Path(path).name} carries no video track.")
if not container.streams.audio:
raise ValueError(
f"{Path(path).name} carries no audio track. MiniMax-H3 denoises video and audio "
f"in one packed sequence, so its training clips must have sound."
)
stream = container.streams.video[0]
source_fps = float(stream.average_rate or stream.guessed_rate or H3_FPS) or float(H3_FPS)
# Container duration, in seconds, for the over-long note below. Best effort: an unknown
# duration simply means no note, never a failed decode.
source_duration_s = 0.0
try:
if stream.duration is not None and stream.time_base is not None:
source_duration_s = float(stream.duration * stream.time_base)
elif getattr(container, "duration", None):
source_duration_s = float(container.duration) / 1_000_000.0
except Exception: # noqa: BLE001 -- a note is not worth failing a decode over
source_duration_s = 0.0
View on GitHub (pinned to 203007d190)
Solutions
- Remove or exclude the audio-only/corrupt file from data_dir.
- Re-encode the source to a normal .mp4 with both tracks (ffmpeg -i in.mp4 -c:v libx264 -c:a aac out.mp4) if the file was supposed to have video.
- Pre-scan the dataset with av.open and skip files whose container.streams.video is empty, reporting them by name.
Example fix
# before
# data/sound_effect.mp3 in the training dir -> "carries no video track"
# after
import av
with av.open(p) as c:
ok = bool(c.streams.video) and bool(c.streams.audio)
# keep only ok files in the dataset Defensive patterns
Strategy: validation
Validate before calling
import av
def has_video_track(path: str) -> bool:
try:
with av.open(path) as c:
return bool(c.streams.video)
except av.error.InvalidDataError:
return False Try / catch
try:
frames, waveform = decode_clip(p, num_frames=n, width=w, height=h)
except ValueError as e:
if "no video track" in str(e):
skip_and_log(p)
else:
raise Prevention
- Pre-scan datasets with PyAV, keeping only files with both video and audio streams.
- Keep audio-only media out of video training directories.
When it happens
Trigger: Passing an audio-only file (.m4a/.mp3/.wav renamed or genuinely audio) or a still image wrapped in a container; a corrupt video file whose stream headers are unreadable but the container opens; an .avi/.mp4 whose video stream index is absent.
Common situations: Music/sfx folders accidentally included in a video training dir; motion-visualization exports that wrote audio only; files truncated during download so the video track is missing.
Related errors
- MiniMax-H3 was trained on aspect ratios from 1:4 to 4:1; thi
- {Path(path).name} carries no audio track. MiniMax-H3 denoise
- {Path(path).name} decoded to {len(frames)} frames at {H3_FPS
- {Path(path).name} decoded to no audio samples.
- {Path(path).name} carries {have_s:.2f}s of audio for a {want
AI-assisted analysis of unslothai/unsloth@203007d190 (2026-08-15).
Data as JSON: /api/errors/87bfb2033c4121aa.
Report an issue: GitHub.