vllm-project/vllm · error · ValueError

Could not read enough frames from video file {path} (expecte

Error message

Could not read enough frames from video file {path} (expected {num_frames} frames, got {len(frames)})

What it means

video_to_ndarrays() grabs frames sequentially and only decodes those in the sampled index set; if the stream ends early (cap.grab() fails) or retrieve() fails on sampled indices, fewer frames than the requested num_frames are collected. After np.stack, the count is checked and ValueError reports expected vs. obtained.

Source

Thrown at vllm/assets/video.py:68

    total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
    frames = []

    num_frames = num_frames if num_frames > 0 else total_frames
    frame_indices = _sample_frame_indices(total_frames, num_frames)
    for idx in range(total_frames):
        ok = cap.grab()  # next img
        if not ok:
            break
        if idx in frame_indices:  # only decompress needed
            ret, frame = cap.retrieve()
            if ret:
                # OpenCV uses BGR format, we need to convert it to RGB
                # for PIL and transformers compatibility
                frames.append(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB))

    frames = np.stack(frames)
    if len(frames) < num_frames:
        raise ValueError(
            f"Could not read enough frames from video file {path}"
            f" (expected {num_frames} frames, got {len(frames)})"
        )
    return frames


def video_to_pil_images_list(path: str, num_frames: int = -1) -> list[Image.Image]:
    frames = video_to_ndarrays(path, num_frames)
    return [Image.fromarray(frame) for frame in frames]


def video_get_metadata(path: str, num_frames: int = -1) -> dict[str, Any]:
    import cv2

    cap = cv2.VideoCapture(path)
    if not cap.isOpened():
        raise ValueError(f"Could not open video file {path}")

View on GitHub (pinned to c794754062)

Solutions

  1. Read total_frames via video_get_metadata first and clamp num_frames = min(num_frames, total_frames)
  2. Re-download or re-encode the video if it is truncated (verify with ffprobe -count_frames)
  3. Handle the ValueError per-item in a batch multimodal pipeline and skip/fallback that request

Example fix

# before
frames = video_to_ndarrays(path, num_frames=64)  # clip only has 50 decodable frames
# after
meta = video_get_metadata(path, num_frames=64)
frames = video_to_ndarrays(path, num_frames=meta["total_num_frames"])
Defensive patterns

Strategy: validation

Validate before calling

meta = video_get_metadata(path, num_frames)
actual = meta["total_num_frames"]
if num_frames > actual:
    num_frames = actual  # clamp to decodable frame budget

Try / catch

try:
    frames = video_to_ndarrays(path, num_frames)
except ValueError as e:
    if "Could not read enough frames" in str(e):
        frames = video_to_ndarrays(path, -1)  # take all frames
    else:
        raise

Prevention

When it happens

Trigger: Calling video_to_ndarrays(path, num_frames=N) where N exceeds frames actually decodable: truncated file, CAP_PROP_FRAME_COUNT lying (common with variable-frame-rate or streamed files), corrupted frames mid-file, or cv2codec partially failing.

Common situations: Asking for more frames than the clip contains (num_frames > total but metadata reported more), damaged user uploads, partially downloaded datasets where the tail is missing.

Related errors


AI-assisted analysis of vllm-project/vllm@c794754062 (2026-08-14). Data as JSON: /api/errors/b968297ca3c4b06f. Report an issue: GitHub.