affaan-m/ECC · error · RuntimeError

decoded zero frames from

Error message

decoded zero frames from {path}

What it means

`sample_frames()` decodes sampled frames and raises a RuntimeError if zero frames were successfully read even though the video opened. This catches containers where seeking/read failed for every frame (or the file is effectively empty of video). Downstream grade statistics would otherwise be computed from nothing.

Solutions

  1. Verify with `ffprobe -count_frames` that the file actually contains decodable video frames.
  2. Re-encode/re-mux the file: `ffmpeg -i bad.mp4 -c copy fixed.mp4` to rebuild the index.
  3. Confirm the input is a video, not an audio-only or image file.
  4. Pre-check duration/frame_count via `probe()` and reject videos with frame_count <= 0.

Example fix

// before
frames = sample_frames('truncated.mp4', n=32)   # raises decoded zero frames
// after
info = probe('truncated.mp4')
if info.frame_count <= 0:
    raise ValueError(f"no decodable frames in {info.path}")
frames = sample_frames('truncated.mp4', n=32)
Defensive patterns

Strategy: fallback

Validate before calling

info = probe(src)
if info.frame_count <= 0:
    raise ValueError(f"no decodable frames in {src}")

Try / catch

try:
    frames = sample_frames(src, n=24)
except RuntimeError as e:
    if 'decoded zero frames' in str(e):
        frames = fallback_extract_via_ffmpeg(src, n=24)  # ffmpeg -vf select
    else:
        raise

Prevention

When it happens

Trigger: Calling `sample_frames()` on a video that opens but yields no decodable frames at the requested positions — corrupt index, zero-length video stream, every `cap.read()` returning `ok=False`, or the sequential fallback also decoding nothing.

Common situations: Truncated or interrupted downloads; videos whose container metadata lies about frame count and whose stream is actually empty; audio-only files passed as video; hardware/driver decode failures producing unreadable frames.

Understand the failure class

Background: EmptyResultError / "no results found": when an API or scraper succeeds but returns zero rows — this error's family across 9 libraries.

Related errors


AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16). Data as JSON: /api/errors/5120ad61eb9ccca6. Report an issue: GitHub.

Appendix: source

Thrown at skills/taste-application/scripts/taste/frames.py:81

        cap.release()
        return frames

    lo = int(total * skip_edges)
    hi = int(total * (1.0 - skip_edges))
    idxs = np.linspace(lo, max(lo + 1, hi - 1), num=min(n, max(1, hi - lo)))
    idxs = np.unique(idxs.astype(int))

    out: list[np.ndarray] = []
    for i in idxs:
        cap.set(cv2.CAP_PROP_POS_FRAMES, int(i))
        ok, bgr = cap.read()
        if not ok:
            continue
        out.append(_prep(bgr, max_edge))
    cap.release()

    if not out:
        raise RuntimeError(f"decoded zero frames from {path}")
    return out


def _sequential_sample(cap, n: int, max_edge: int) -> list[np.ndarray]:
    frames = []
    while True:
        ok, bgr = cap.read()
        if not ok:
            break
        frames.append(bgr)
    if not frames:
        return []
    idxs = np.unique(np.linspace(0, len(frames) - 1, num=min(n, len(frames))).astype(int))
    return [_prep(frames[i], max_edge) for i in idxs]


def _prep(bgr: np.ndarray, max_edge: int) -> np.ndarray:
    h, w = bgr.shape[:2]

View on GitHub (pinned to 8321021c54)