{"record":{"id":"a272c0e8135b2b8f","repo":"affaan-m/ECC","slug":"ffmpeg-grade-failed-proc-stderr-400-a272c0","errorCode":null,"errorMessage":"ffmpeg grade failed: {proc.stderr[-400:]}","messagePattern":"ffmpeg grade failed: (.+?)","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"skills/taste-distillation/scripts/taste/grade.py","lineNumber":683,"sourceCode":"\n    s = max(0.0, min(1.0, float(strength)))\n    if s >= 0.999:\n        vf = f\"lut3d=file='{lut.as_posix()}'\"\n    else:\n        # Blend graded over original so partial looks stay available.\n        vf = (\n            f\"split=2[a][b];[b]lut3d=file='{lut.as_posix()}'[g];\"\n            f\"[a][g]blend=all_mode=normal:all_opacity={s:.3f}\"\n        )\n\n    cmd = [\n        \"ffmpeg\", \"-nostdin\", \"-loglevel\", \"error\", \"-y\", \"-i\", str(src),\n        \"-vf\", vf, \"-c:v\", \"libx264\", \"-crf\", str(crf), \"-pix_fmt\", \"yuv420p\",\n        \"-c:a\", \"copy\", str(dst),\n    ]\n    proc = subprocess.run(cmd, capture_output=True, text=True)\n    if proc.returncode != 0:\n        raise RuntimeError(f\"ffmpeg grade failed: {proc.stderr[-400:]}\")\n    return dst\n\n\ndef grade_clip_adaptive(\n    src: str | Path,\n    dst: str | Path,\n    target: GradeStats,\n    strength: float = 1.0,\n    lut_size: int = 33,\n    n_frames: int = 32,\n    keep_lut: str | Path | None = None,\n) -> Path:\n    \"\"\"Measure the clip, bake a LUT *for that clip*, then apply it.\n\n    Prefer this over :func:`grade_clip` for anything generated.\n\n    ``look.cube`` is baked against a canonical neutral stand-in, because when\n    a pack is minted there is no way to know what footage it will meet. That","sourceCodeStart":665,"sourceCodeEnd":701,"githubUrl":"https://github.com/affaan-m/ECC/blob/8321021c54d670126ce3b2969d5deb880b4b0c2a/skills/taste-distillation/scripts/taste/grade.py#L665-L701","documentation":"grade_clip shells out to ffmpeg with a lut3d video filter and libx264 encoding. If ffmpeg exits with a non-zero return code, the wrapper raises RuntimeError containing the last 400 characters of ffmpeg's stderr, because Python itself cannot diagnose ffmpeg-level failures. The real cause is always in the captured stderr text.","triggerScenarios":"Any ffmpeg failure while grading: a malformed or unsupported .cube LUT the filter rejects, an unreadable/corrupt or unsupported input container/codec, a destination path that is not writable, or a broken ffmpeg install missing libx264.","commonSituations":"LUT exported with wrong size/format for lut3d (e.g. 1D LUT or non-cube LUT); ffmpeg on the system built without libx264; input video with a codec OpenCV/ffmpeg cannot decode; disk full or dst in a read-only directory; an old ffmpeg that lacks lut3d support.","solutions":["Read the stderr text embedded in the exception message - it names the specific ffmpeg error (filter parse error, codec missing, permission, etc.).","Validate the LUT separately: run ffmpeg -i src -vf lut3d=file='your.cube' -frames:v 1 out.png to isolate whether the LUT or the clip is the problem.","Check ffmpeg capabilities: ffmpeg -version and confirm libx264 appears in the configuration; if not, install a full ffmpeg build (e.g. via conda, brew, or a static build).","Re-encode or remux the source if the input is corrupt/unsupported (ffmpeg -i src -c copy fixed.mp4), then grade the fixed file.","Verify the destination directory is writable and has free space; test write with touch dst_dir/.probe."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"import shutil\nassert shutil.which('ffmpeg'), 'ffmpeg not on PATH'\ninfo = subprocess.run(['ffmpeg','-version'], capture_output=True, text=True)\nassert 'libx264' in info.stderr or 'libx264' in info.stdout, 'ffmpeg lacks libx264'\nassert Path(lut).is_file(), f'LUT missing: {lut}'","typeGuard":null,"tryCatchPattern":"try:\n    grade_clip(src, dst, lut=lut)\nexcept RuntimeError as e:\n    ffmpeg_err = str(e).split(': ', 1)[-1]\n    logger.error('ffmpeg grading failed; stderr tail: %s', ffmpeg_err)\n    # branch on the stderr content: LUT parse error vs codec vs permissions","preventionTips":["Keep a full-featured ffmpeg build (libx264 + lut3d support) on PATH in every environment.","Probe each source with ffprobe before grading to catch unsupported/corrupt inputs early.","Ensure destination directories exist and are writable before launching batches.","Validate LUT files once after minting (render a single test frame through lut3d)."],"tags":["ffmpeg","subprocess","video","encoding"],"backgroundTag":"ffmpeg-command-failed","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"}