Skip to content

fix(encode): make 8-bit the default H.264 output - #441

Merged
LeadcodeDev merged 1 commit into
mainfrom
fix/h264-8bit-by-default
Sep 29, 2026
Merged

LeadcodeDev merged 1 commit into
mainfrom
fix/h264-8bit-by-default

Conversation

@LeadcodeDev

Copy link
Copy Markdown
Owner

Refs #435 — first item. The second, publishing to crates.io, is outward-facing and
irreversible, so it stops at the boundary: see the end.

The default H.264 branch pushed -profile:v high10 -pix_fmt yuv420p10le with no
gate at all, so every render without --hardware-acceleration produced a High 10
file. QuickTime and Safari refuse those outright, and a user reported exactly
that: a file the tool had just written and they could not open.

The default is now -profile:v high -pix_fmt yuv420p. The old encode is still
reachable as --codec h264_10bit, the same libx264 call with the same crf and
preset.

Making it a codec name rather than a new flag means it travels plumbing that
already exists: codec: &str reaches ffmpeg_args from nine call sites, so
nothing needed a new parameter. Two lists had to learn the name — check_codec's
allow-list and containers_for. The first is how the initial attempt silently
produced an 8-bit file for --codec h264_10bit: the name was rejected upstream
and ffmpeg_args never saw it, while the .mp4 left over from the previous run
made it look like it had worked. The end-to-end check is the only reason that was
caught.

Verified with ffprobe:

default              h264,High,yuv420p
--codec h264_10bit   h264,High 10,yuv420p10le

The docs claimed 10-bit as the default in four places — README.md, CLAUDE.md,
SKILL.md and rules/gradient-quality.md — and gradient-quality.md recommended
ProRes for dark gradients without mentioning that 10-bit H.264 was already on. All
four now say which of the two trades away playback, and why 10-bit is not the
default: the reason is not quality.

Tests

the_default_h264_output_is_eight_bit, ten_bit_is_still_reachable_by_asking_for_it,
an_unknown_codec_name_falls_back_to_the_playable_default, and three in
validation.rs pinning that every name ffmpeg_args branches on is accepted by
check_codec — which is the invariant that broke.

Not in this PR

The release itself. main is well ahead of the 0.7.0 on crates.io, and #435 asks
for a version bump, a changelog and a publish. Publishing is outward-facing and
cannot be undone, so it is yours to run. There is also no CHANGELOG.md in the
repository, so the format is a decision rather than a fill-in.

cargo fmt --all --check clean · cargo test -p rustmotion --lib encode::video::ffmpeg cli::commands::validation 45 passed. The full workspace run is the orchestrator's after the parallel workstreams integrate.

The default H.264 branch pushed -profile:v high10 -pix_fmt yuv420p10le
with no gate at all, so every render without --hardware-acceleration
produced a High 10 file. QuickTime and Safari refuse those outright, and
a user reported exactly that: a file the tool had just written and they
could not open.

The default is now -profile:v high -pix_fmt yuv420p. The old encode is
still reachable as --codec h264_10bit, which is the same libx264 call
with the same crf and preset.

Making it a codec name rather than a new flag means it travels the
plumbing that already exists: codec: &str already reaches ffmpeg_args
from nine call sites, so nothing needed a new parameter. check_codec's
allow-list and containers_for both had to learn the name -- the first
rejected it before ffmpeg_args ever saw it, which is how the first
attempt silently produced an 8-bit file for --codec h264_10bit.

Verified end to end with ffprobe: the default gives h264/High/yuv420p,
--codec h264_10bit gives h264/High 10/yuv420p10le.

The docs claimed 10-bit as the default in five places -- README, CLAUDE,
SKILL, and rules/gradient-quality.md -- and recommended ProRes for dark
gradients without mentioning that 10-bit H.264 was already on. All four
now say which of the two trades away playback and why.

Refs #435
@LeadcodeDev LeadcodeDev added the bug Something isn't working label Sep 29, 2026
@LeadcodeDev LeadcodeDev self-assigned this Sep 29, 2026
@LeadcodeDev
LeadcodeDev merged commit 28d86eb into main Sep 29, 2026
4 checks passed
@LeadcodeDev
LeadcodeDev deleted the fix/h264-8bit-by-default branch September 29, 2026 13:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant