{"record":{"id":"7f9c7b3e03907033","repo":"affaan-m/ECC","slug":"ffmpeg-failed-proc-stderr-400","errorCode":null,"errorMessage":"ffmpeg failed: {proc.stderr[-400:]}","messagePattern":"ffmpeg failed: (.+?)","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"skills/taste-application/scripts/taste/render3d.py","lineNumber":288,"sourceCode":"        except Exception:\n            # A failed Blender render must not lose the asset; the software\n            # path always works, so degrade instead of raising.\n            pass\n    return turntable_software(mesh_path, dest, n_frames, size), \"software\"\n\n\ndef frames_to_video(frames: list[Path], dst: str | Path, fps: float = 24.0) -> Path:\n    \"\"\"Encode rendered frames into a clip the rest of the pipeline can eat.\"\"\"\n    dst = Path(dst)\n    dst.parent.mkdir(parents=True, exist_ok=True)\n    pattern = str(frames[0].parent / \"turn_%04d.png\")\n    proc = subprocess.run([\n        \"ffmpeg\", \"-nostdin\", \"-loglevel\", \"error\", \"-y\",\n        \"-framerate\", f\"{fps:g}\", \"-i\", pattern,\n        \"-c:v\", \"libx264\", \"-crf\", \"14\", \"-pix_fmt\", \"yuv420p\", str(dst),\n    ], capture_output=True, text=True)\n    if proc.returncode != 0:\n        raise RuntimeError(f\"ffmpeg failed: {proc.stderr[-400:]}\")\n    return dst\n","sourceCodeStart":270,"sourceCodeEnd":290,"githubUrl":"https://github.com/affaan-m/ECC/blob/8321021c54d670126ce3b2969d5deb880b4b0c2a/skills/taste-application/scripts/taste/render3d.py#L270-L290","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Confirm ffmpeg is installed and on PATH (`ffmpeg -version`).","Check the frame pattern matches actual files and they are in order.","Ensure output width/height are even (pad or crop frames) since yuv420p requires even dimensions.","Use an ffmpeg build with libx264, or change -c:v to an available codec."],"exampleFix":"// before\nffmpeg ... -i 'frame_%04d.png' ... 1081x720  # odd width\n// after\n# rescale to even dimensions in ffmpeg arguments\n\"-vf\", \"scale=trunc(iw/2)*2:trunc(ih/2)*2\"","handlingStrategy":"validation","validationCode":"import shutil, glob\ndef validate_frames_to_video(pattern, dst):\n    if shutil.which('ffmpeg') is None:\n        raise EnvironmentError('ffmpeg not on PATH')\n    frames = sorted(glob.glob(pattern.replace('%04d', '*')))\n    if not frames:\n        raise FileNotFoundError(f'no frames match {pattern}')","typeGuard":"def ffmpeg_available() -> bool:\n    import shutil\n    return shutil.which('ffmpeg') is not None","tryCatchPattern":"try:\n    frames_to_video(pattern, dst)\nexcept RuntimeError as e:\n    if 'ffmpeg failed' in str(e):\n        logger.error('ffmpeg stderr: %s', str(e))\n        raise","preventionTips":["Ensure frame dimensions are even for yuv420p/libx264","Verify the frame pattern matches the actual file naming","Use an ffmpeg build that includes libx264","Check the output path is writable and not locked by another process"],"tags":["ffmpeg","subprocess","video"],"backgroundTag":"http-error-response","analyzedSha":"8321021c54d670126ce3b2969d5deb880b4b0c2a","analyzedAt":"2026-09-16T10:08:13.343Z","contentChangedAt":"2026-09-16T10:08:13.343Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}