From d22ce0ba5aebfff5ffaea97982472f876af5da22 Mon Sep 17 00:00:00 2001 From: Christophe Besson Date: Fri, 18 Sep 2026 14:37:08 +0200 Subject: feat: decode and re-encode video on the GPU where there is one MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A 1080p film is decoded by whoever watches it and re-encoded by the node when no browser can decode the source. Both were on the CPU, and on an Atom or Celeron mini-PC neither reaches real time — which is what `transcode_incompatible_video` exists to refuse. This adds the mechanism that makes refusing it unnecessary. Node — `hwaccel.py`: VA-API on Linux, Quick Sync or NVENC on Windows, established by encoding 1080p and reading the file back with ffprobe. Nothing is accepted that does not produce the exact profile and level `stream_init` announces, since the client checks that string before it trusts a byte: an encoder that wrote another level would make the node's own codec string a lie, and ffmpeg takes `-level 4.1` and `-level 41` from h264_qsv without saying which it understood. Three modes per stream — hardware decode and encode, hardware encode alone, libx264 — demoted per source codec, because a GPU that decodes HEVC may have no decoder for MPEG-4 Part 2 and only asking it finds out. A mode that fails is detected on an empty stdout before `stream_init` goes out, so the viewer sees one working stream and never an error. Client — Chromium ships VA-API off on Linux. It is enabled where a render node and a driver are present, then verified through `navigator.mediaCapabilities`: a no moves to the next GL backend on the next launch and an exhausted list drops the switches, so a renamed feature cannot pass for a feature that is on and `--ignore-gpu-blocklist` cannot survive on a machine it did not help. Feature lists now merge rather than overwrite — `appendSwitch` replaces the value, and a second caller would have silently cancelled the mDNS switch aiortc depends on. Packaging — the drivers are weak dependencies on all four formats, so a machine without a GPU installs exactly as before. `dpkg -i` and `rpm -ivh` ignore weak deps; `packaging/README.md` now says so. Windows needs no driver: the bundled ffmpeg already carries h264_qsv and h264_nvenc, and a re-pin that dropped them would cost every low-power Windows node its hardware encoding silently. AMD on Windows (AMF) and macOS (VideoToolbox) are named gaps, not oversights: neither could be tried anywhere in this project, and both re-encode in software as before. Co-Authored-By: Claude Opus 5 --- docs/MESHBAY_DESIGN.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'docs') diff --git a/docs/MESHBAY_DESIGN.md b/docs/MESHBAY_DESIGN.md index 781438a..8c3f67a 100644 --- a/docs/MESHBAY_DESIGN.md +++ b/docs/MESHBAY_DESIGN.md @@ -1926,6 +1926,14 @@ What running it establishes, and what each fact costs: - **Installation places files, never secrets.** No key generation in a package's post-install step or an installer custom action — a golden image would give every machine the same key. +- **Hardware video decoding is asked for and then verified.** Chromium ships VA-API + off on Linux, so the client enables it where a render node and a driver are + present, and then asks `navigator.mediaCapabilities` whether the codec the node + streams really decodes `powerEfficient`ly. A no moves to the next GL backend on + the next launch, and an exhausted list drops the switches — a feature name that a + Chromium release renamed must not pass for a feature that is on, and + `--ignore-gpu-blocklist` must not survive on a machine it did not help. The + package recommends the drivers; nothing requires them. Two guards apply to anything the hub can display **inside** the application, which is a phishing surface: plain text or a very restricted markup subset, never raw @@ -2034,6 +2042,18 @@ by any of this. **Video streaming** is fragmented-MP4 remux (or transcode where the codec has no MSE string) fed to a source buffer, with the node holding one slot per viewer. +- **The re-encode runs on the GPU wherever one works** — VA-API on Linux, Quick + Sync or NVENC on Windows. Which one is established by **encoding 1080p and reading + the file back**, never inferred from the hardware or from ffmpeg's encoder list, + and nothing is accepted that does not produce the exact profile and level + `stream_init` announces: an encoder that wrote another level would make the node's + own codec string a lie, and the client checks that string before it trusts a byte. + Every mode falls back to libx264 — per source codec, because a GPU that decodes + HEVC may have no decoder for MPEG-4 Part 2 and only asking it finds out. This is + what lets a low-power node keep `transcode_incompatible_video` on: the setting + refuses a capability, and hardware encoding is the mechanism that makes refusing + it unnecessary. + - **Flow control is a window, not a debt.** Read-ahead is bounded by *time past the playhead*, with a small window of segments in flight topped up as they land, driven by a clock and by playback and **never by arriving data**. Granting a -- cgit v1.2.3