affaan-m/ECC · error · RuntimeError
ffmpeg failed
Error message
ffmpeg failed: {proc.stderr[-400:]} What it means
frames_to_video encodes a numbered PNG sequence (e.g. turn_%04d.png) into an H.264 video with ffmpeg. If ffmpeg exits non-zero, it raises RuntimeError with the last 400 characters of ffmpeg's stderr. Since the input is a filename pattern, the usual failure is that the pattern matched nothing or the frames are malformed, which ffmpeg reports as an impossible-to-open input.
Solutions
- Read the stderr tail in the exception - 'No such file or directory' means the pattern matched nothing; 'Unknown encoder libx264' means the codec is missing.
- Verify the pattern against the real files: ls the frames directory and confirm padding/start number; add -start_number to the ffmpeg input options if the sequence starts at 1 (or adjust your pattern).
- Regenerate frames if corrupt, and make sure the glob used for counting matches the ffmpeg pattern exactly.
- Confirm libx264 is available (ffmpeg -version shows --enable-libx264) or switch to an available codec (e.g. -c:v mpeg4).
- Check dst's directory is writable and has space; quote any pattern containing spaces when constructing the command.
Example fix
// before
frames_to_video('renders/turn_%03d.png', 'out.mp4') # files are turn_0001.png (4-digit, starts at 1)
// after
subprocess.run(['ffmpeg','-y','-framerate','24','-start_number','1','-i','renders/turn_%04d.png','-c:v','libx264','-pix_fmt','yuv420p','out.mp4'], check=True) Defensive patterns
Strategy: validation
Validate before calling
from pathlib import Path
import re
# confirm the pattern matches the frames that actually exist
frames = sorted(Path(pattern_dir).glob('turn_*.png'))
assert frames, f'no frames match in {pattern_dir}'
nums = [int(re.search(r'(\d+)\.png$', f.name).group(1)) for f in frames]
padding = len(re.search(r'\d+', frames[0].name).group(0))
print(f'{len(frames)} frames, start={min(nums)}, padding={padding}') # build pattern from these facts Try / catch
try:
frames_to_video(pattern, dst)
except RuntimeError as e:
msg = str(e).split(': ', 1)[-1]
if 'No such file' in msg:
raise SystemExit('frame pattern mismatch: check padding and -start_number') from e
if 'libx264' in msg:
raise SystemExit('ffmpeg lacks libx264; install a full build') from e
raise Prevention
- Derive the ffmpeg pattern from the actual frame filenames (padding + start number), don't assume %04d from 1.
- Write frames with consistent zero padding from the rendering step.
- Verify libx264 in ffmpeg -version for each deployment environment.
- Ensure the output directory exists and is writable before encoding; encode to a temp file then rename.
When it happens
Trigger: frames_to_video(pattern, dst) fails when: the pattern doesn't match actual filenames (wrong padding, e.g. %03d vs turn_0001.png), frames live in a different directory than the pattern assumes, ffmpeg lacks libx264, dst is unwritable, or a source frame is corrupt so decoding aborts.
Common situations: Off-by-one start number (sequence starts at 0 or 1 while the pattern implies another), renamed/alphabetically-sorted frames with inconsistent zero padding, headless CI ffmpeg without libx264, spaces or special chars in the unquoted pattern, or dst in a read-only output directory.
Related errors
AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16).
Data as JSON: /api/errors/0053637e77d3ab9e.
Report an issue: GitHub.
Appendix: source
Thrown at skills/taste-distillation/scripts/taste/render3d.py:288
except Exception:
# A failed Blender render must not lose the asset; the software
# path always works, so degrade instead of raising.
pass
return turntable_software(mesh_path, dest, n_frames, size), "software"
def frames_to_video(frames: list[Path], dst: str | Path, fps: float = 24.0) -> Path:
"""Encode rendered frames into a clip the rest of the pipeline can eat."""
dst = Path(dst)
dst.parent.mkdir(parents=True, exist_ok=True)
pattern = str(frames[0].parent / "turn_%04d.png")
proc = subprocess.run([
"ffmpeg", "-nostdin", "-loglevel", "error", "-y",
"-framerate", f"{fps:g}", "-i", pattern,
"-c:v", "libx264", "-crf", "14", "-pix_fmt", "yuv420p", str(dst),
], capture_output=True, text=True)
if proc.returncode != 0:
raise RuntimeError(f"ffmpeg failed: {proc.stderr[-400:]}")
return dst
View on GitHub (pinned to 8321021c54)