Skip to content

Hardware video encoding for H.264 and HEVC (#100) - #109

Merged
KnifeLemon merged 7 commits into
mainfrom
feature/hardware-video-encoding
Oct 18, 2026
Merged

KnifeLemon merged 7 commits into
mainfrom
feature/hardware-video-encoding

Conversation

@KnifeLemon

Copy link
Copy Markdown
Owner

Summary

For #100: an opt-in "Hardware acceleration" option on video presets (MediaOptions.HardwareEncoding, off by default so existing presets don't change). It applies to H.264 and HEVC encodes only. Stream copy, AV1, VP9 and the other codecs are unchanged.

Encoders, tried in order and only if ffmpeg -encoders lists them:

  • macOS: *_videotoolbox, with -q:v on Apple Silicon and a -b:v fallback for Intel Macs
  • Windows: *_nvenc → *_qsv → *_amf
  • Linux: *_nvenc → *_vaapi (only when /dev/dri/renderD128 exists)

Probe: each candidate is tried once with a tiny lavfi encode (15 s timeout) using the real options. Results are cached per ffmpeg executable and logged. That way a listed but unusable encoder (no GPU or driver) is skipped.

Quality maps the High/Balanced/Small tiers to each encoder's rate control:

Encoder Rate control
NVENC -rc vbr -cq
QSV ICQ -global_quality
AMF CQP
VA-API CQP
VideoToolbox -q:v, or bits per pixel on Intel Macs
  • 10-bit and HDR sources use main10/p010 on HEVC only when the 10-bit probe passes; otherwise they go to x265. The hvc1 tag is kept.
  • Fallback: if a hardware encode fails, the partial output is removed and the file is re-encoded with x264/x265. This is logged as a warning, not shown as a failure. A cancelled conversion is not retried.
  • VersionOf/EncodersOf timeouts now actually apply: reads are async and the process is killed on timeout.

Test plan

  • Core 201, Engines 915 (FFmpeg linked, 0 skipped), Cli 21, App 266 and Platform 18 tests pass. dotnet format is clean.
  • Real Quick Sync H.264/HEVC encodes pass on Intel Iris Xe. A missing encoder falls back to x264 in a real conversion.
  • Not verified on real NVENC, AMF, VideoToolbox or VA-API hardware. CI has no GPUs, so those tests skip. Quality values are first approximations.

Note: FfmpegConverter.VersionOf/EncodersOf overlap with #108.

🤖 Generated with Claude Code

KnifeLemon and others added 7 commits October 17, 2026 23:53
calibre's GitHub releases keep files only for the newest version: when 9.16.0
came out, the pinned 9.15.0 .txz and .dmg links there started returning 404,
so installing calibre failed on macOS and Linux. download.calibre-ebook.com
keeps every version; the files are the same (sizes and SHA-256 checked).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A Filee running as administrator (started by an installer run elevated)
ignores drops from Explorer, can't read Explorer's selection, and the
Filee that Explorer's menu starts crashed on the elevated Filee's mutex
or waited 30 s on its pipe, all without a log line.

- Read Filee's and Explorer's integrity levels at start-up. When Filee
  runs elevated and Explorer doesn't: log a warning, show a banner on
  the Home page and a one-time notice card, both with "Restart without
  administrator rights" (relaunch through Explorer's shell, after
  releasing the single-instance lock; a failed restart says so).
- A later launch that can't open the lock or is refused by the pipe
  logs it and shows one message box (once per burst of launches); the
  pipe refusal no longer waits the whole 30 s.
- Log unhandled exceptions (any thread, unobserved tasks, UI thread)
  through a logger set up before anything else, and one start-up line
  with version, path, install kind, integrity levels, OS and argument
  count.
- UI watchdog: logs a UI thread blocked for more than 5 s and when it
  answers again.
- Rate-limited diagnostics: forwarded launches received and handled,
  drag gestures that never reached the donut, shortcuts that found no
  selection (with the foreground window), the first drag over the drop
  zone.
- FFmpeg -version / -encoders time out for real (background reads, kill
  on timeout); engine statuses are checked once in the background at
  start-up; unreachable network shares on PATH are skipped after 2 s.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A new preset option, off by default, encodes H.264 and HEVC on the GPU:
NVENC, Quick Sync and AMF on Windows, VideoToolbox on macOS (quality
mode on Apple Silicon, bitrate mode on Intel Macs), NVENC and VA-API on
Linux. Only encoders the bundled FFmpeg has are tried, best first, and
each must pass a tiny test encode with the real options (cached per
FFmpeg, encoder and bit depth) before it is used.

Quality levels map to each encoder's constant-quality control, one step
coarser than the x264/x265 CRF. HEVC keeps 10 bits, HDR colour tags and
the hvc1 tag; H.264 stays 8-bit 4:2:0 as with x264. Stream copy rules
are unchanged, and AV1, VP9 and the other codecs stay in software.

When a hardware encode fails anyway, the partial output is removed and
the file is encoded again with x264/x265; the failure goes to the log,
not to the user. Cancellation is never retried.

FFmpeg's version and encoder queries now read output asynchronously and
kill the process at their time limit, so a hung FFmpeg no longer blocks
engine detection.

The preset editor shows the option for H.264 and HEVC targets, with
English, Korean and Simplified Chinese text. ENGINES.md documents the
encoders, the probe, the quality mapping and the software retry.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Avalonia toggles the selected item of a ComboBox or ListBox off when it is
picked again with the command modifier (Ctrl+Space, Ctrl+Enter, Ctrl+click;
Cmd on macOS). A combo box was left empty and pushed null into settings that
always hold a value, which threw NullReferenceException in the view models
(e.g. TriggerGestureViewModel) and showed it under the combo box.

- SingleSelectionGuard (registered in App.Initialize) swallows that toggle on
  the selected item of combo boxes and single-selection list boxes; an open
  drop-down closes as after any pick. Multi-selection lists keep the toggle.
- Choices.Restore: every Choice<T> property (Triggers, Presets editor,
  General, Theme, Watch folders, rename rules) and the navigation selection
  ignore null and keep their previous value; the control then reads the bound
  value again.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…to HEAD

# Conflicts:
#	src/Filee.App/App.axaml.cs
… into HEAD

# Conflicts:
#	src/Filee.Engines/Media/FfmpegConverter.cs
@KnifeLemon
KnifeLemon merged commit 43419c2 into main Oct 18, 2026
5 checks passed
@KnifeLemon
KnifeLemon deleted the feature/hardware-video-encoding branch October 19, 2026 12:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant