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

  1. Remove or exclude the audio-only/corrupt file from data_dir.
  2. 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.
  3. 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

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


AI-assisted analysis of unslothai/unsloth@203007d190 (2026-08-15). Data as JSON: /api/errors/87bfb2033c4121aa. Report an issue: GitHub.