and backtick — filtergraphs rarely contain either.\n- **`NUL` not `/dev/null`** for two-pass logs: `-passlogfile` defaults are fine, but\n `ffmpeg ... -f null NUL` (PowerShell also accepts `-f null -`, which is portable —\n prefer it).\n- **Font paths in drawtext**: `fontfile='C\\:/Windows/Fonts/arial.ttf'` — forward\n slashes, escaped drive colon, inside the filter string.\n- **Prefer `-f null -` and relative paths** to sidestep both quoting tables at once.\n\n## Decision trees\n\n**Codec** — `H.264 (libx264)`: default; universal playback, fast, good per-bit at\n`-crf 18..23`. → `H.265 (libx265)`: same quality ~40% smaller; slower; needs\n`-tag:v hvc1` for Apple; fine for storage/modern devices. → `AV1 (libsvtav1)`: best\ncompression, royalty-free, web-first (YouTube/Netflix path); encode cost highest;\nplayback on older hardware is software-only. → `VP9`: only when a pipeline demands\nwebm and AV1 is unavailable. → `FFV1`: archival masters only.\n\n**Cut method** — Need exact frames OR applying any filter → re-encode (input-side\n`-ss`, `-crf 18`). Cut points happen to sit on keyframes (verify with\n`--keyframes-near`) OR a ±2s slop is acceptable → stream copy with\n`-avoid_negative_ts make_zero`. Many cuts from one source → EDL workflow below.\n\n**CPU vs hardware encode** — Hardware (NVENC/QSV/AMF/VideoToolbox) is 5-20× faster\nbut **worse quality per bit** than libx264/x265 at slow presets. Use hardware for:\nspeed-critical batch work, live/streaming, drafts, \"good enough\" deliveries (bump\nbitrate ~30% to compensate). Use CPU for: final masters, size-constrained targets,\nquality comparisons. Always `capability-scan.sh` first — listed encoders fail at\nruntime on driver mismatches. Details: [references/hardware-accel.md](references/hardware-accel.md).\n\n## EDL workflow (edit-as-code)\n\nFor any multi-cut edit, do not fire ad-hoc trim commands. Write an **edit decision\nlist** — a JSON file naming every clip, time range, and *why* — then cut from it.\nThe edit becomes reviewable (rationale is written down), rerunnable (regenerate the\noutput any time), and diffable (versions of the edit are git history).\n\n```bash\n# 1. Find candidate cut points (silence = clean speech boundaries):\npython skills/ffmpeg-ops/scripts/detect-segments.py --silence --json take3.mp4\n\n# 2. Author the EDL (schema: assets/edl-schema.json) with per-scene rationale.\n\n# 3. Dry-run prints every ffmpeg command it would run (default — nothing executes):\npython skills/ffmpeg-ops/scripts/cut-from-edl.py edit.json\n\n# 4. Execute: cuts + concat -> final. Re-encodes by default for frame accuracy;\n# --copy for keyframe-aligned EDLs.\npython skills/ffmpeg-ops/scripts/cut-from-edl.py edit.json --execute -o final.mp4\n```\n\nRules that make this work (from the Fable launch-video pipeline): cuts must land in\n**silence**; the model reasons over **transcripts, not frames**; after cutting,\n**re-transcribe the output to verify** (no filler words survived, no words clipped).\nFull architecture, EDL schema, verification loop:\n[references/edit-as-code.md](references/edit-as-code.md).\n\n## Color grading\n\n```bash\n# Apply a .cube LUT (tetrahedral = highest quality interpolation):\nffmpeg -i in.mp4 -vf \"lut3d=file=grade.cube:interp=tetrahedral\" \\\n -c:v libx264 -crf 18 -c:a copy graded.mp4\n\n# Generate a family of grade candidates + an HTML still-chooser:\npython skills/ffmpeg-ops/scripts/gen-luts.py --variants all --out-dir work/luts \\\n --previews in.mp4\n```\n\n**The human picks the grade.** Generate variants, render preview stills, present a\nchooser — never auto-select a look. Grading is a taste call; the agent's job is the\nlattice math and the apply command. LUT format, log-footage normalization\n(S-Log3/V-Log → Rec.709), curves/eq safe ranges, checking work with ffmpeg's\nbuilt-in scopes (waveform/vectorscope):\n[references/color-grading.md](references/color-grading.md). The 25-look recipe\ncatalog — film stocks (Kodachrome, CineStill halation, Technicolor, Eterna),\nsignature grades (Mad Max, Fincher, Matrix, BR2049, Amélie…), era/genre moods,\nSin City selective color — every chain build-validated, plus the Hald-CLUT\nmatch-any-look workflow and scope-matching ladder:\n[references/look-recipes.md](references/look-recipes.md). Pipeline correctness\n(pix_fmt, HDR→SDR tonemapping, range/matrix tagging):\n[references/color-hdr.md](references/color-hdr.md).\n\n## Quality gates\n\n```bash\n# VMAF/SSIM/PSNR verdict on an encode (exit 10 = below threshold -> branch on it):\npython skills/ffmpeg-ops/scripts/quality-compare.py reference.mp4 encoded.mp4 \\\n --metrics ssim,psnr\npython skills/ffmpeg-ops/scripts/quality-compare.py reference.mp4 encoded.mp4 \\\n --metrics vmaf --min-vmaf 90 --json | jq '.data.vmaf'\n```\n\nVMAF ≥ 93 at 1080p ≈ visually transparent; 80-93 = noticeable on inspection.\nSide-by-side visual A/B (`hstack`), metric interpretation, encode-ladder tuning:\n[references/quality-metrics.md](references/quality-metrics.md).\n\n## Scripts\n\nAll eleven follow the [Skill Resource Protocol](../../docs/SKILL-RESOURCE-PROTOCOL.md):\n`--help` with examples, stdout = data only, `--json` envelopes\n(`claude-mods.ffmpeg-ops.*/v1`), semantic exit codes (`0` ok, `2` usage, `3` input\nmissing, `4` invalid input, `5` missing dependency, `7` ffmpeg unavailable,\n`10` domain finding).\n\n| Script | Job | Worked invocation |\n|---|---|---|\n| `probe-media.py` | Normalized inspection, keyframe proximity, `--doctor` triage (hazard → fix command, exit 10) | `probe-media.py --doctor in.mp4` |\n| `capability-scan.sh` | What can THIS ffmpeg build do (proof-encodes hw encoders; `--quick` skips) | `capability-scan.sh --json \\| jq '.data.encoders'` — exit 10 = a listed encoder failed verification |\n| `quality-compare.py` | VMAF/SSIM/PSNR gate | `quality-compare.py ref.mp4 enc.mp4 --min-vmaf 90` — exit 10 = below threshold |\n| `loudnorm-scan.py` | Two-pass loudnorm: measures pass 1, emits exact pass-2 filter | `loudnorm-scan.py -I -16 in.mp4 --json \\| jq -r '.data.pass2_filter'` |\n| `detect-segments.py` | Silence/scene boundaries as JSON segments (STT chunking, dead-air cuts, shot splits) | `detect-segments.py --scenes --json in.mp4 \\| jq '.data.segments'` |\n| `cut-from-edl.py` | EDL JSON → validated cuts + concat (dry-run by default) | `cut-from-edl.py edit.json --execute -o final.mp4` |\n| `make-chapters.py` | Scene/silence points (or explicit JSON) → embedded chapters / YouTube text / WebVTT | `make-chapters.py --from-scenes --media talk.mp4 --write chaptered.mp4` |\n| `smart-compress.py` | Fit a size cap: computed two-pass bitrate, auto audio/downscale, size-verified (exit 10 = still over) | `smart-compress.py --target 25MB video.mp4` |\n| `make-sprites.py` | Scrub-preview sprite sheets + WebVTT thumbnail track (#xywh) | `make-sprites.py --interval 5 video.mp4` |\n| `gen-luts.py` | Emit .cube grade variants (+ `--previews` still chooser) | `gen-luts.py --variants warm_filmic,punchy --out-dir luts/` |\n| `verify-commands.sh` | Staleness verifier: `--offline` structural (CI), `--live` checks docs against the installed build | `verify-commands.sh --live` — exit 10 = doc drift, 7 = no ffmpeg |\n\n## References\n\nLoad on demand — one concept per file:\n\n| Reference | Load when |\n|---|---|\n| [encoding.md](references/encoding.md) | Choosing codec/CRF/preset, two-pass, social platform targets, archival |\n| [hardware-accel.md](references/hardware-accel.md) | NVENC/QSV/AMF/VideoToolbox/VAAPI flags, quality caveats, detection |\n| [filtergraph.md](references/filtergraph.md) | Any `-filter_complex`, labels/chains/split, speed ramps, xstack |\n| [trim-concat.md](references/trim-concat.md) | Cut accuracy, keyframes, concat selection, segment removal |\n| [edit-as-code.md](references/edit-as-code.md) | Multi-cut edits, EDL schema, transcript-driven editing, verify loop |\n| [audio.md](references/audio.md) | Loudness, mixing, channel layout, audio repair |\n| [stt-whisper.md](references/stt-whisper.md) | Whisper/WhisperX prep, chunking, transcript JSON, summarisation pipeline |\n| [subtitles.md](references/subtitles.md) | Burn vs soft, styling, extraction, format conversion |\n| [color-grading.md](references/color-grading.md) | LUTs, .cube format, log normalization, scopes, grade workflow |\n| [look-recipes.md](references/look-recipes.md) | 25-look catalog (film stocks, signature movie grades, era/genre moods), Hald-CLUT extraction, scope-matching |\n| [color-hdr.md](references/color-hdr.md) | pix_fmt, HDR→SDR tonemap, BT.601/709 tagging, 10-bit |\n| [quality-metrics.md](references/quality-metrics.md) | VMAF/SSIM interpretation, visual A/B, ladder tuning |\n| [streaming-hls.md](references/streaming-hls.md) | HLS/DASH packaging, ABR ladders, live restream |\n| [images-gif.md](references/images-gif.md) | GIF quality, sprite sheets, dataset frame extraction |\n| [restoration.md](references/restoration.md) | Deinterlace, denoise, deband, stabilize, audio cleanup |\n| [analysis-validation.md](references/analysis-validation.md) | Corruption checks, hashing, metadata stripping, untrusted uploads |\n| [capture-devices.md](references/capture-devices.md) | Screen/webcam capture per OS (gdigrab/dshow, avfoundation, x11grab) |\n| [error-decoder.md](references/error-decoder.md) | An ffmpeg command failed with a cryptic message — symptom → cause → fix |\n| [visualization.md](references/visualization.md) | Waveform/spectrogram videos, audiograms, comparison grids |\n| [cookbook.md](references/cookbook.md) | Any concrete command: the full recipe set by job (convert, cut, transform, overlay, audio, STT prep, images, diagnostics, yt-dlp, test sources) |\n\nAssets: [encoding-presets.json](assets/encoding-presets.json) (recipe data incl.\ndate-stamped social targets), [hls-ladder.json](assets/hls-ladder.json) (ABR ladder),\n[edl-schema.json](assets/edl-schema.json) (the cut-from-edl.py contract).\n\n## Self-test\n\n```bash\nbash skills/ffmpeg-ops/tests/run.sh # offline suite; synthesizes fixtures via lavfi\n```\n\nStructural assertions always run; media round-trips run only when ffmpeg is on PATH\n(loud skip otherwise — never a silent false-clean).\n","licenseDocuments":[]}}
La interfaz está localizada; las descripciones y documentos de las Skills se traducen automáticamente con IA a su idioma. El código, los comandos, rutas y términos técnicos se mantienen en el original, y prevalece el documento del autor.
Explorar Skills
Desarrollo · SKILL.md

ffmpeg-ops

ffmpeg-ops

Comprehensive ffmpeg/ffprobe media processing: transcode, cut/trim/concat, color grading, loudness normalization, subtitles, GIFs, HLS packaging, hardware encoding, and quality gates (VMAF). Triggers on: ffmpeg, ffprobe, transcode, compress/convert video, extract audio, color grade, hls.

Independent GitHub snapshot · Automated classification · Original documentation governs

Documentación de la Skill

GitHub

name: ffmpeg-ops description: "Comprehensive ffmpeg/ffprobe media processing: transcode, cut/trim/concat, color grading, loudness normalization, subtitles, GIFs, HLS packaging, hardware encoding, and quality gates (VMAF). Triggers on: ffmpeg, ffprobe, transcode, compress/convert video, extract audio, color grade, hls." license: MIT compatibility: "ffmpeg 5.0+ (6.0+ recommended). Scripts: bash + python3.10+. Optional per task: libvmaf, libass, libzimg, libvidstab." allowed-tools: "Read Write Edit Bash Glob Grep" metadata: author: claude-mods related-skills: color-ops, debug-ops

ffmpeg Operations

Operational expertise for ffmpeg/ffprobe: the ~30 commands that cover most real work, the footguns that silently ruin output, EDL-driven editing (edit-as-code), and eight scripts that replace the logic an agent would otherwise re-derive every task.

Doctrine: probe first

Never transcode, cut, or filter blind. Every media task starts by probing the input — codec, duration, frame rate (constant or variable?), pixel format, rotation, stream layout. Half of all "ffmpeg did something weird" reports are a property of the input the command never checked.

python skills/ffmpeg-ops/scripts/probe-media.py input.mp4            # human summary
python skills/ffmpeg-ops/scripts/probe-media.py --doctor input.mp4   # TRIAGE: hazards + exact fixes
python skills/ffmpeg-ops/scripts/probe-media.py --json input.mp4 | jq '.data.streams'
python skills/ffmpeg-ops/scripts/probe-media.py --keyframes-near 92.5 input.mp4

--doctor makes the doctrine self-enforcing: VFR, HDR transfer, rotation metadata, interlacing, non-yuv420p delivery, and moov-at-EOF each come back as a finding with the exact fix command, and exit 10 means "fix before processing". The --keyframes-near form answers "can I stream-copy a cut at 92.5s?" — it reports the nearest keyframes so you know whether a copy cut will snap (see Footguns). When a command fails with a cryptic message, decode it: references/error-decoder.md.

Before recommending an encoder, verify the build has it. Installed ffmpeg builds vary wildly (especially hardware encoders — listed ≠ working):

bash skills/ffmpeg-ops/scripts/capability-scan.sh           # full: proof-encodes each hw encoder
bash skills/ffmpeg-ops/scripts/capability-scan.sh --quick   # list-only, no GPU touch

Cookbook

Copy-paste recipes, each with the trap it avoids in its comments: references/cookbook.md. Commands are bash-form (see Windows notes); always pass -y or -n so no agent-run command goes interactive.

NeedCookbook section
Web H.264, HEVC, AV1, remux, VFR normalize, FFV1 archive, fit-to-sizeConvert and compress
Copy vs frame-accurate trim, concat demuxer vs filterCut and join
Scale, crop, 9:16 blurred pad, rotate, fps, speed, slow-mo, timelapseResize, transform, retime
Watermark, drawtext timecode, burned vs soft subtitlesOverlay, text, subtitles
Extract, replace, mix, loudness, trim silenceAudio
16 kHz mono STT extraction, piping, silence chunkingSpeech-to-text prep
Thumbnails, contact sheets, GIFs, chapters, dataset frames, spritesImages, GIFs, frames
Corruption check, frame hashes, metadata strip, ffprobe one-linersDiagnostics and validation
Post-download yt-dlp patternsyt-dlp interop
Synthetic test fixturesGenerative/test sources

Footguns

The table that pays this skill's rent. Each row is a class of silent failure.

FootgunThe trapThe rule
-ss + -c copyCut starts seconds early or with frozen/black lead-in (snapped to prior keyframe)Copy cuts snap. Check probe-media.py --keyframes-near; re-encode when exact
Output-side -to after input-side -ssTimestamps reset at the seek point, so -to silently becomes a durationKeep -ss/-to on the same side of -i (both input-side is fast and absolute)
Missing -pix_fmt yuv420pEncode "works" but Safari/QuickTime/TVs show black or refuse to play (defaulted to yuv444p/yuv422p from a high-quality source)Always set it for delivery H.264/H.265
Missing -movflags +faststartBrowser can't start playback until the whole file downloads (moov at EOF)Always set it for web-served MP4
Default stream selectionffmpeg picks ONE stream per type (highest-res video, most-channels audio) — extra audio tracks and all subs are silently dropped-map 0 to keep everything, explicit -map otherwise
-vf + -c:v copy togetherHard error — filters require decodingFiltering implies re-encode; pick one
VFR source (phone/Zoom/Loom/screen-rec)Cut math drifts, concat desyncs, players stutterNormalize first: -fps_mode cfr -r 30 + re-encode (cookbook)
-vsync (deprecated)Old flag, removed directionUse -fps_mode (cfr/vfr/passthrough)
scale=W:-1Odd height → encoder error with yuv420pAlways -2
concat demuxer on mismatched inputs"Works" then glitches/desyncs at boundaries (codec/timebase mismatch)Demuxer = identical params only; else concat filter with re-encode
amix defaultEach input's volume halved (normalize defaults on)amix=...:normalize=0 + explicit volume=
One-pass loudnormDynamic mode pumps quiet passages; output silently 192 kHzTwo-pass linear via loudnorm-scan.py; add -ar 48000
-shortest absent on audio-replaceOutput runs as long as the LONGEST input (silence or frozen frame tail)Add -shortest when muxing separate A/V
BT.601/709 colour shiftSlightly wrong colours after scaling SD↔HD (matrix guessed from resolution)Tag explicitly when it matters: see references/color-hdr.md
drawtext/subtitles path escapingFilter args re-parse : and \ — Windows paths like C:\x explode inside filter stringscd to the asset's dir and use bare relative names; or escape as C\:/path
Interactive overwrite promptAgent-run command hangs forever on "File exists. Overwrite? [y/N]"Always pass -y or -n explicitly
% in cmd.exe%06d patterns and %{pts} get mangled by cmd variable expansionUse PowerShell or bash; in .bat double to %%

Windows notes

Platform-agnostic commands, but when running on Windows:

  • PowerShell quoting is friendlier than bash here: single quotes are fully literal, so -vf 'scale=1280:-2,fps=30' needs no escaping. Double quotes only interpolate $ and backtick — filtergraphs rarely contain either.
  • NUL not /dev/null for two-pass logs: -passlogfile defaults are fine, but ffmpeg ... -f null NUL (PowerShell also accepts -f null -, which is portable — prefer it).
  • Font paths in drawtext: fontfile='C\:/Windows/Fonts/arial.ttf' — forward slashes, escaped drive colon, inside the filter string.
  • Prefer -f null - and relative paths to sidestep both quoting tables at once.

Decision trees

Codec — H.264 (libx264): default; universal playback, fast, good per-bit at -crf 18..23. → H.265 (libx265): same quality ~40% smaller; slower; needs -tag:v hvc1 for Apple; fine for storage/modern devices. → AV1 (libsvtav1): best compression, royalty-free, web-first (YouTube/Netflix path); encode cost highest; playback on older hardware is software-only. → VP9: only when a pipeline demands webm and AV1 is unavailable. → FFV1: archival masters only.

Cut method — Need exact frames OR applying any filter → re-encode (input-side -ss, -crf 18). Cut points happen to sit on keyframes (verify with --keyframes-near) OR a ±2s slop is acceptable → stream copy with -avoid_negative_ts make_zero. Many cuts from one source → EDL workflow below.

CPU vs hardware encode — Hardware (NVENC/QSV/AMF/VideoToolbox) is 5-20× faster but worse quality per bit than libx264/x265 at slow presets. Use hardware for: speed-critical batch work, live/streaming, drafts, "good enough" deliveries (bump bitrate ~30% to compensate). Use CPU for: final masters, size-constrained targets, quality comparisons. Always capability-scan.sh first — listed encoders fail at runtime on driver mismatches. Details: references/hardware-accel.md.

EDL workflow (edit-as-code)

For any multi-cut edit, do not fire ad-hoc trim commands. Write an edit decision list — a JSON file naming every clip, time range, and why — then cut from it. The edit becomes reviewable (rationale is written down), rerunnable (regenerate the output any time), and diffable (versions of the edit are git history).

# 1. Find candidate cut points (silence = clean speech boundaries):
python skills/ffmpeg-ops/scripts/detect-segments.py --silence --json take3.mp4

# 2. Author the EDL (schema: assets/edl-schema.json) with per-scene rationale.

# 3. Dry-run prints every ffmpeg command it would run (default — nothing executes):
python skills/ffmpeg-ops/scripts/cut-from-edl.py edit.json

# 4. Execute: cuts + concat -> final. Re-encodes by default for frame accuracy;
#    --copy for keyframe-aligned EDLs.
python skills/ffmpeg-ops/scripts/cut-from-edl.py edit.json --execute -o final.mp4

Rules that make this work (from the Fable launch-video pipeline): cuts must land in silence; the model reasons over transcripts, not frames; after cutting, re-transcribe the output to verify (no filler words survived, no words clipped). Full architecture, EDL schema, verification loop: references/edit-as-code.md.

Color grading

# Apply a .cube LUT (tetrahedral = highest quality interpolation):
ffmpeg -i in.mp4 -vf "lut3d=file=grade.cube:interp=tetrahedral" \
  -c:v libx264 -crf 18 -c:a copy graded.mp4

# Generate a family of grade candidates + an HTML still-chooser:
python skills/ffmpeg-ops/scripts/gen-luts.py --variants all --out-dir work/luts \
  --previews in.mp4

The human picks the grade. Generate variants, render preview stills, present a chooser — never auto-select a look. Grading is a taste call; the agent's job is the lattice math and the apply command. LUT format, log-footage normalization (S-Log3/V-Log → Rec.709), curves/eq safe ranges, checking work with ffmpeg's built-in scopes (waveform/vectorscope): references/color-grading.md. The 25-look recipe catalog — film stocks (Kodachrome, CineStill halation, Technicolor, Eterna), signature grades (Mad Max, Fincher, Matrix, BR2049, Amélie…), era/genre moods, Sin City selective color — every chain build-validated, plus the Hald-CLUT match-any-look workflow and scope-matching ladder: references/look-recipes.md. Pipeline correctness (pix_fmt, HDR→SDR tonemapping, range/matrix tagging): references/color-hdr.md.

Quality gates

# VMAF/SSIM/PSNR verdict on an encode (exit 10 = below threshold -> branch on it):
python skills/ffmpeg-ops/scripts/quality-compare.py reference.mp4 encoded.mp4 \
  --metrics ssim,psnr
python skills/ffmpeg-ops/scripts/quality-compare.py reference.mp4 encoded.mp4 \
  --metrics vmaf --min-vmaf 90 --json | jq '.data.vmaf'

VMAF ≥ 93 at 1080p ≈ visually transparent; 80-93 = noticeable on inspection. Side-by-side visual A/B (hstack), metric interpretation, encode-ladder tuning: references/quality-metrics.md.

Scripts

All eleven follow the Skill Resource Protocol: --help with examples, stdout = data only, --json envelopes (claude-mods.ffmpeg-ops.*/v1), semantic exit codes (0 ok, 2 usage, 3 input missing, 4 invalid input, 5 missing dependency, 7 ffmpeg unavailable, 10 domain finding).

ScriptJobWorked invocation
probe-media.pyNormalized inspection, keyframe proximity, --doctor triage (hazard → fix command, exit 10)probe-media.py --doctor in.mp4
capability-scan.shWhat can THIS ffmpeg build do (proof-encodes hw encoders; --quick skips)capability-scan.sh --json | jq '.data.encoders' — exit 10 = a listed encoder failed verification
quality-compare.pyVMAF/SSIM/PSNR gatequality-compare.py ref.mp4 enc.mp4 --min-vmaf 90 — exit 10 = below threshold
loudnorm-scan.pyTwo-pass loudnorm: measures pass 1, emits exact pass-2 filterloudnorm-scan.py -I -16 in.mp4 --json | jq -r '.data.pass2_filter'
detect-segments.pySilence/scene boundaries as JSON segments (STT chunking, dead-air cuts, shot splits)detect-segments.py --scenes --json in.mp4 | jq '.data.segments'
cut-from-edl.pyEDL JSON → validated cuts + concat (dry-run by default)cut-from-edl.py edit.json --execute -o final.mp4
make-chapters.pyScene/silence points (or explicit JSON) → embedded chapters / YouTube text / WebVTTmake-chapters.py --from-scenes --media talk.mp4 --write chaptered.mp4
smart-compress.pyFit a size cap: computed two-pass bitrate, auto audio/downscale, size-verified (exit 10 = still over)smart-compress.py --target 25MB video.mp4
make-sprites.pyScrub-preview sprite sheets + WebVTT thumbnail track (#xywh)make-sprites.py --interval 5 video.mp4
gen-luts.pyEmit .cube grade variants (+ --previews still chooser)gen-luts.py --variants warm_filmic,punchy --out-dir luts/
verify-commands.shStaleness verifier: --offline structural (CI), --live checks docs against the installed buildverify-commands.sh --live — exit 10 = doc drift, 7 = no ffmpeg

References

Load on demand — one concept per file:

ReferenceLoad when
encoding.mdChoosing codec/CRF/preset, two-pass, social platform targets, archival
hardware-accel.mdNVENC/QSV/AMF/VideoToolbox/VAAPI flags, quality caveats, detection
filtergraph.mdAny -filter_complex, labels/chains/split, speed ramps, xstack
trim-concat.mdCut accuracy, keyframes, concat selection, segment removal
edit-as-code.mdMulti-cut edits, EDL schema, transcript-driven editing, verify loop
audio.mdLoudness, mixing, channel layout, audio repair
stt-whisper.mdWhisper/WhisperX prep, chunking, transcript JSON, summarisation pipeline
subtitles.mdBurn vs soft, styling, extraction, format conversion
color-grading.mdLUTs, .cube format, log normalization, scopes, grade workflow
look-recipes.md25-look catalog (film stocks, signature movie grades, era/genre moods), Hald-CLUT extraction, scope-matching
color-hdr.mdpix_fmt, HDR→SDR tonemap, BT.601/709 tagging, 10-bit
quality-metrics.mdVMAF/SSIM interpretation, visual A/B, ladder tuning
streaming-hls.mdHLS/DASH packaging, ABR ladders, live restream
images-gif.mdGIF quality, sprite sheets, dataset frame extraction
restoration.mdDeinterlace, denoise, deband, stabilize, audio cleanup
analysis-validation.mdCorruption checks, hashing, metadata stripping, untrusted uploads
capture-devices.mdScreen/webcam capture per OS (gdigrab/dshow, avfoundation, x11grab)
error-decoder.mdAn ffmpeg command failed with a cryptic message — symptom → cause → fix
visualization.mdWaveform/spectrogram videos, audiograms, comparison grids
cookbook.mdAny concrete command: the full recipe set by job (convert, cut, transform, overlay, audio, STT prep, images, diagnostics, yt-dlp, test sources)

Assets: encoding-presets.json (recipe data incl. date-stamped social targets), hls-ladder.json (ABR ladder), edl-schema.json (the cut-from-edl.py contract).

Self-test

bash skills/ffmpeg-ops/tests/run.sh   # offline suite; synthesizes fixtures via lavfi

Structural assertions always run; media round-trips run only when ffmpeg is on PATH (loud skip otherwise — never a silent false-clean).

Skills guardadas