affaan-m/ECC · error · RuntimeError
ffmpeg encode failed
Error message
ffmpeg encode failed: {err} What it means
`grade_clip_direct()` pipes raw frames into an FFmpeg subprocess and after the stream ends reads FFmpeg's stderr; if the encoder exits non-zero it raises a RuntimeError with the last 400 bytes of stderr. This detects encode-side failures that only appear at flush/termination — invalid encoder options, corrupted output target, disk full, or an FFmpeg that died mid-stream.
Solutions
- Read the stderr captured in the exception (last 400 chars) for the concrete FFmpeg message.
- Verify FFmpeg supports libx264: `ffmpeg -encoders | grep libx264`; install a full build if absent.
- Check destination disk space and write permissions before encoding.
- Ensure probe-derived width/height/fps actually match the source frames so the rawvideo header is correct.
Example fix
// before
cmd = [..., '-c:v', 'libx264', '-crf', str(crf), ...] # libx264 absent -> encode failed
// after
if b'libx264' not in subprocess.run(['ffmpeg','-encoders'], capture_output=True).stdout:
cmd = [c if c != 'libx264' else 'mpeg4' for c in cmd]
subprocess.Popen(cmd, stdin=subprocess.PIPE, stderr=subprocess.PIPE, ...) Defensive patterns
Strategy: try-catch
Validate before calling
import shutil, subprocess
assert shutil.which('ffmpeg')
enc = subprocess.run(['ffmpeg', '-hide_banner', '-encoders'], capture_output=True)
assert b'libx264' in enc.stdout, 'libx264 encoder unavailable' Try / catch
try:
grade_clip_direct(src, dst, lut)
except RuntimeError as e:
if str(e).startswith('ffmpeg encode failed'):
err = str(e).split(':', 1)[-1]
logger.error('encoder stderr: %s', err)
cleanup_partial(dst)
raise EncodeError(dst, err) from e
raise Prevention
- Check disk space before long encodes
- Verify libx264 availability or fall back to another encoder
- Confirm probe width/height/fps match actual frames so the rawvideo header is correct
- Always read/close the stderr pipe and wait() on the process to surface real exit codes
When it happens
Trigger: Calling `grade_clip_direct()` where the piped ffmpeg process returns non-zero at wait() — bad `-crf`/encoder args, destination path unwritable, ffmpeg killed or OOM, unsupported output pixel format.
Common situations: Very old or unusual FFmpeg builds missing libx264; output volume filling mid-encode; destination file locked by another process; stderr revealing 'Conversion failed' after a frame-size mismatch between declared `-s` and actual frames.
Understand the failure class
Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.
Related errors
AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16).
Data as JSON: /api/errors/f5687d5f5e79ffbb.
Report an issue: GitHub.
Appendix: source
Thrown at skills/taste-application/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)