affaan-m/ECC · error · RuntimeError

ffmpeg failed

Error message

ffmpeg failed: {proc.stderr[-400:]}

What it means

render3d.py raises RuntimeError('ffmpeg failed: {stderr}') when the ffmpeg subprocess encoding PNG frames into an H.264 video returns a non-zero exit code. The last 400 characters of ffmpeg's stderr are included to diagnose the encoding failure.

Solutions

  1. Confirm ffmpeg is installed and on PATH (`ffmpeg -version`).
  2. Check the frame pattern matches actual files and they are in order.
  3. Ensure output width/height are even (pad or crop frames) since yuv420p requires even dimensions.
  4. Use an ffmpeg build with libx264, or change -c:v to an available codec.

Example fix

// before
ffmpeg ... -i 'frame_%04d.png' ... 1081x720  # odd width
// after
# rescale to even dimensions in ffmpeg arguments
"-vf", "scale=trunc(iw/2)*2:trunc(ih/2)*2"
Defensive patterns

Strategy: validation

Validate before calling

import shutil, glob
def validate_frames_to_video(pattern, dst):
    if shutil.which('ffmpeg') is None:
        raise EnvironmentError('ffmpeg not on PATH')
    frames = sorted(glob.glob(pattern.replace('%04d', '*')))
    if not frames:
        raise FileNotFoundError(f'no frames match {pattern}')

Type guard

def ffmpeg_available() -> bool:
    import shutil
    return shutil.which('ffmpeg') is not None

Try / catch

try:
    frames_to_video(pattern, dst)
except RuntimeError as e:
    if 'ffmpeg failed' in str(e):
        logger.error('ffmpeg stderr: %s', str(e))
        raise

Prevention

When it happens

Trigger: Calling frames_to_video when ffmpeg is not installed, the input frame pattern matches no files, an odd width/height conflicts with yuv420p pixel format, or the destination is unwritable/locked.

Common situations: ffmpeg missing from PATH; glob pattern mismatched (wrong directory or naming); video dimensions not divisible by 2 with libx264/yuv420p; codec libx264 unavailable in the ffmpeg build.

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/7f9c7b3e03907033. Report an issue: GitHub.

Appendix: source

Thrown at skills/taste-application/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)