affaan-m/ECC · error · RuntimeError

ffmpeg encode failed

Error message

ffmpeg encode failed: {err}

What it means

grade_clip_direct writes raw rgb24 frames to ffmpeg's stdin and lets ffmpeg encode with libx264. When the process exits non-zero, the finally-block reads ffmpeg's stderr and raises RuntimeError('ffmpeg encode failed: <tail of stderr>'). The Python-side frame feeding worked; the failure happened inside the encoder.

Solutions

  1. Read the stderr tail in the exception - it pinpoints the encoder complaint (dimension mismatch, no x264, permission).
  2. Ensure frames match the declared rawvideo parameters: convert each frame to 3-channel RGB and resize to info.width x info.height before cap.write/proc.stdin.write(frame.tobytes()).
  3. Sanitize dimensions to even numbers for yuv420p/libx264 (round width/height down to even) before building the ffmpeg command.
  4. Verify ffmpeg has libx264 (ffmpeg -version shows --enable-libx264) or switch the command to a codec your build has (e.g. mpeg4).
  5. Check dst is writable and the filesystem has free space; ffmpeg cannot append - make sure dst does not conflict with an open handle.

Example fix

// before
proc.stdin.write(frame.tobytes())  # frame is BGR / 4-channel -> encoder fails
// after
rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
if rgb.shape[:2] != (info.height, info.width):
    rgb = cv2.resize(rgb, (info.width, info.height))
proc.stdin.write(rgb.tobytes())
Defensive patterns

Strategy: validation

Validate before calling

import cv2
cap = cv2.VideoCapture(str(src))
ok, frame = cap.read()
cap.release()
assert ok, f'cannot read first frame of {src}'
assert frame.ndim == 3 and frame.shape[2] == 3, f'unexpected channels: {frame.shape}'
h, w = frame.shape[:2]
assert w % 2 == 0 and h % 2 == 0, f'odd dimensions {w}x{h} break yuv420p; resize first'

Try / catch

try:
    grade_clip_direct(src, dst)
except RuntimeError as e:
    logger.error('ffmpeg encode failed: %s', str(e).split(': ', 1)[-1])
    # fall back to the simple lut3d path which lets ffmpeg decode natively
    grade_clip(src, dst, lut=lut)

Prevention

When it happens

Trigger: ffmpeg exits non-zero while encoding the piped rawvideo stream: mismatch between the declared -s/-pix_fmt/-r and the frames actually written (wrong frame size or channel count from OpenCV), stdin closed early, an invalid dst path, or libx264 rejecting the pixel format.

Common situations: Source video with odd dimensions or an unusual fps that was probed wrong; frames read as BGR/4-channel but piped as rgb24; dst on a read-only or full filesystem; OpenCV returning fewer/garbled frames so ffmpeg gets a truncated stream; ffmpeg build without libx264.

Related errors


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

Appendix: source

Thrown at skills/taste-distillation/scripts/taste/grade.py:817

                       tone_mode=tone_mode)
        proc.stdin.write((np.clip(out, 0, 1) * 255).astype(np.uint8).tobytes())
        buf.clear()

    try:
        while True:
            ok, bgr = cap.read()
            if not ok:
                break
            buf.append(_cv2.cvtColor(bgr, _cv2.COLOR_BGR2RGB).astype(np.float32) / 255.0)
            if len(buf) >= batch:
                flush()
        flush()
    finally:
        cap.release()
        proc.stdin.close()
        err = proc.stderr.read().decode()[-400:]
        if proc.wait() != 0:
            raise RuntimeError(f"ffmpeg encode failed: {err}")
    return dst

View on GitHub (pinned to 8321021c54)