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
- Read the stderr tail in the exception - it pinpoints the encoder complaint (dimension mismatch, no x264, permission).
- 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()).
- Sanitize dimensions to even numbers for yuv420p/libx264 (round width/height down to even) before building the ffmpeg command.
- Verify ffmpeg has libx264 (ffmpeg -version shows --enable-libx264) or switch the command to a codec your build has (e.g. mpeg4).
- 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
- Convert every frame to 3-channel RGB and the probed width/height before writing to stdin.
- Keep width/height even for libx264 yuv420p output.
- Confirm libx264 support in the target environment's ffmpeg before batch runs.
- Write to a temp file then atomically rename, so failed encodes never leave half-written outputs.
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)