Automated release: version and notes generated from pull requests merged since 2.5.1.
- feat: opt-in Apple VideoToolbox encoding.
--hw/--no-hwon every re-encoding tool andexport.py(two booleans in the contract and MCP:hw,no_hw);FFMPEG_SKILL_HW=1makes it the default for everything butexport.py's delivery presets (an export under it says so inhw,requested: false);render.py/batch.py --hwmake it explicit for every stage, andwaveform.pypasses its choice to the caption/title stage that writes its file. h264/hevc (HDR Main10 with the source's tags and HDR10 side data)/prores; AV1 stays on SVT-AV1; anexport.pypreset keeps its own format on the GPU (an h264/h265 preset stays 8-bit BT.709,proreskeeps the source's tags). CRF maps to-q:vby SSIM against x264/x265medium(tests/bench_vt.py): SDR H.264 18/23/28 → 75/64/53, SDR HEVC → 78/68/58, and HDR its own curve, 63/55/47, because its CPU line is x265 Main10 at CRF+2; matched quality costs 1.1–2.9× the CPU bytes on SDR and 1.9–3.5× on HDR. BT.709 tags go throughh264_metadata/hevc_metadata, so FFmpeg ≥7.1 never converts an untagged source. Apple Silicon only (the hardware, also under a Rosetta Python). Only a job VideoToolbox itself refuses (the encoder could not open, or its compression session failed, in FFmpeg 5.1 to master's wordings) is re-encoded on the CPU, with the odd-dimension retry a CPU run gets; any other failure fails once, names its encoder and carriesencoder/hw. Every result names itsencoder;hwsays what was asked and what ran (requested,source,used— null under--dry-run—fallback,notes); a GPU encode adds a top-levelnotesline that its quality is not CRF-equivalent, and one chosen byFFMPEG_SKILL_HW=1notes the size cost and--no-hw.render.pycarries its stages' and an executed plan'shw,batch.pyits items' (eachresultsrow names itsencoder), and both caches key on the GPU setting.doctor --jsongainshw. Built by @rymalia in #304, including the VideoToolbox quality bench (tests/bench_vt.py) and its fitted curves. - fix: a
--dry-runthat needs the encoder list (--codec av1/prores,--hw) reads it fromffprobe -encodersand no longer runsffmpeg -encoders, keeping the promise that a writing tool's dry run runs no ffmpeg; a real run keeps readingffmpeg -encoders, the build that encodes (on a mixed install, a Homebrew ffprobe next to a static ffmpeg, ffprobe's list is another build's). - fix(batch): a cache entry whose output a later run rewrote (another recipe for the same file) is dropped, so switching back re-processes the item instead of serving the other run's file as cached.
- fix(waveform):
commandslists the title/caption stages' command lines too, asrender.py's does, so it holds every ffmpeg command the run planned or ran. - feat: opt-in Apple VideoToolbox encoding (--hw) (#311)
What's Changed
Full Changelog: v2.5.1...v2.6.0