summaryrefslogtreecommitdiffstats
path: root/packaging
diff options
context:
space:
mode:
authorChristophe Besson <cbesson@gmail.com>2026-09-18 14:37:08 +0200
committerChristophe Besson <cbesson@gmail.com>2026-09-18 14:37:08 +0200
commitd22ce0ba5aebfff5ffaea97982472f876af5da22 (patch)
tree073b7ad96bc58aa834cd8f781d81915fdaa6e338 /packaging
parent0d56cd33b975afe7648dd6f6380a30a7b5230c90 (diff)
downloadmeshbay-d22ce0ba5aebfff5ffaea97982472f876af5da22.tar.gz
feat: decode and re-encode video on the GPU where there is one
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 <noreply@anthropic.com>
Diffstat (limited to 'packaging')
-rw-r--r--packaging/README.md30
-rw-r--r--packaging/deb/meshbay-client/DEBIAN/control3
-rw-r--r--packaging/deb/meshbay-node/DEBIAN/control6
-rw-r--r--packaging/rpm/meshbay-client.spec7
-rw-r--r--packaging/rpm/meshbay-node.spec6
-rw-r--r--packaging/win/README.md9
-rw-r--r--packaging/win/fetch-ffmpeg.ps19
7 files changed, 62 insertions, 8 deletions
diff --git a/packaging/README.md b/packaging/README.md
index ff65488..b65d0ed 100644
--- a/packaging/README.md
+++ b/packaging/README.md
@@ -42,6 +42,36 @@ sudo rpm -ivh meshbay-hub-*.rpm meshbay-node-*.rpm
sudo rpm -ivh meshbay-client-*.rpm
```
+### Hardware video acceleration is a weak dependency
+
+Both the node and the client use the GPU for video where one works — the node to
+re-encode a browser-hostile codec (`hwaccel.py`: VA-API on Linux, Quick Sync or
+NVENC on Windows), the client to decode H.264 (`main.js`; only on Linux, since
+Chromium already decodes in hardware on Windows and macOS). Neither requires it,
+and both establish it by measurement rather than by assuming the packaged driver
+is present and functional, so a machine without a GPU installs and runs exactly
+as before.
+
+Only Linux needs packaged drivers — on Windows the bundled ffmpeg carries its
+own encoders and Chromium uses the OS's decoder. The drivers are therefore
+`Recommends` (`va-driver-all` on Debian/Ubuntu;
+`libva`, `intel-media-driver`, `mesa-va-drivers` on Fedora), which matters for
+how the packages are installed: **`dpkg -i` and `rpm -ivh` both ignore weak
+dependencies; `apt` and `dnf` install them.** On a low-power machine — an Intel
+mini-PC serving and watching video is the case this exists for — use the
+resolver, so the drivers come too:
+
+```bash
+sudo apt install ./meshbay-common_*.deb ./meshbay-node_*.deb ./meshbay-client_*.deb
+sudo dnf install ./meshbay-common-*.rpm ./meshbay-node-*.rpm ./meshbay-client-*.rpm
+```
+
+Nothing has to be enabled afterwards and there are no flags to set by hand. The
+node logs which encoder it found at the first stream (`hwaccel:`), and the
+client records what it measured in its own `config.json` — the file that
+already remembers the hub address — under `videoDecodeProbe`, and
+`videoAcceleration: "off"` in that same file turns it back off.
+
## Architecture
meshbay-common owns the shared Python virtual environment at
diff --git a/packaging/deb/meshbay-client/DEBIAN/control b/packaging/deb/meshbay-client/DEBIAN/control
index aeb5865..17711c8 100644
--- a/packaging/deb/meshbay-client/DEBIAN/control
+++ b/packaging/deb/meshbay-client/DEBIAN/control
@@ -7,7 +7,8 @@ Maintainer: MeshBay Team <devel@meshbay.org>
Homepage: https://meshbay.org
Depends: libgtk-3-0, libnotify4, libnss3, libxss1, libxtst6,
libatspi2.0-0, libdrm2, libgbm1, libasound2
-Recommends: meshbay-node
+Recommends: meshbay-node, va-driver-all
+Suggests: vainfo
Description: MeshBay — peer-to-peer file sharing, streaming and group chat
Desktop client for MeshBay. Connects to MeshBay nodes over WebRTC for
file sharing, video streaming, and group chat. Includes Chromecast and
diff --git a/packaging/deb/meshbay-node/DEBIAN/control b/packaging/deb/meshbay-node/DEBIAN/control
index 3eda3fa..eb19eb7 100644
--- a/packaging/deb/meshbay-node/DEBIAN/control
+++ b/packaging/deb/meshbay-node/DEBIAN/control
@@ -6,7 +6,7 @@ Architecture: all
Maintainer: MeshBay Team <devel@meshbay.org>
Homepage: https://meshbay.org
Depends: meshbay-common (= __VERSION__)
-Recommends: ffmpeg
+Recommends: ffmpeg, va-driver-all
Description: MeshBay Node — local file host, streaming server, and group daemon
MeshBay Node indexes local directories and serves encrypted files to
authenticated group members over WebRTC. Includes video streaming (fMP4
@@ -15,4 +15,6 @@ Description: MeshBay Node — local file host, streaming server, and group daemo
.
Installs node code into the shared venv at /opt/meshbay-common/venv/.
Ships a default TMDB API token for the Videos app.
- Runs as a systemd user service.
+ Runs as a systemd user service. Re-encodes video on the GPU where one
+ works (VA-API), which is what makes streaming an HEVC film from a
+ low-power machine possible at all.
diff --git a/packaging/rpm/meshbay-client.spec b/packaging/rpm/meshbay-client.spec
index 867205f..0816741 100644
--- a/packaging/rpm/meshbay-client.spec
+++ b/packaging/rpm/meshbay-client.spec
@@ -17,6 +17,13 @@ Requires: libdrm
Requires: mesa-libgbm
Requires: alsa-lib
Recommends: meshbay-node
+# Weak deps: an unresolvable one is skipped, so naming the drivers of both
+# families costs nothing and covers Fedora and RHEL alike. See hwaccel.py
+# (node) / main.js (client) — neither assumes any of this is installed.
+Recommends: libva
+Recommends: intel-media-driver
+Recommends: mesa-va-drivers
+Suggests: libva-utils
%description
Desktop client for MeshBay. Connects to MeshBay nodes over WebRTC for
diff --git a/packaging/rpm/meshbay-node.spec b/packaging/rpm/meshbay-node.spec
index 6ac13fb..1ba7f26 100644
--- a/packaging/rpm/meshbay-node.spec
+++ b/packaging/rpm/meshbay-node.spec
@@ -10,6 +10,12 @@ BuildArch: noarch
Requires: meshbay-common = %{version}
Recommends: ffmpeg
+# Weak deps: an unresolvable one is skipped, so naming the drivers of both
+# families costs nothing and covers Fedora and RHEL alike. See hwaccel.py
+# (node) / main.js (client) — neither assumes any of this is installed.
+Recommends: libva
+Recommends: intel-media-driver
+Recommends: mesa-va-drivers
%description
MeshBay Node indexes local directories and serves encrypted files to
diff --git a/packaging/win/README.md b/packaging/win/README.md
index b5ab1cd..0598193 100644
--- a/packaging/win/README.md
+++ b/packaging/win/README.md
@@ -98,8 +98,13 @@ That runs [`build-win.ps1`](build-win.ps1):
**Bundled by default** — [`fetch-ffmpeg.ps1`](fetch-ffmpeg.ps1) downloads,
checksum-verifies and stages it into `node-runtime/` on every build, ~161 MB.
Not optional in practice: MeshBay transcodes browser-incompatible video to
-H.264 (`-c:v libx264`, a real encode, not remux), and no LGPL-only ffmpeg
-build includes an H.264 *encoder* — libx264 itself is GPL. Asking an end user
+H.264 (a real encode, not remux), and no LGPL-only ffmpeg build includes an
+H.264 *encoder* — libx264 itself is GPL. libx264 is also the floor rather
+than the only path: this build carries `h264_qsv` and `h264_nvenc` as well,
+which is what lets `hwaccel.py` move the encode onto an Intel or NVIDIA GPU
+on Windows without a second download. **A re-pin that dropped those would
+cost every low-power Windows node its hardware encoding, silently** — the
+node would simply go back to libx264. Asking an end user
to separately run `winget install ffmpeg` was considered and rejected: it
needs network access and `winget`/App Installer present at that exact moment,
and its failure mode is silent — video just does not stream, with nothing
diff --git a/packaging/win/fetch-ffmpeg.ps1 b/packaging/win/fetch-ffmpeg.ps1
index 5f6123d..6ffbc51 100644
--- a/packaging/win/fetch-ffmpeg.ps1
+++ b/packaging/win/fetch-ffmpeg.ps1
@@ -3,9 +3,12 @@
Download, verify and stage the ffmpeg/ffprobe MeshBay bundles by default.
.DESCRIPTION
- MeshBay transcodes browser-incompatible video to H.264 (webrtc_server.py,
- `-c:v libx264`) -- a real encode, not just remux/probe -- so only a GPL
- ffmpeg build works here; libx264 is GPL, no LGPL-only build includes it.
+ MeshBay transcodes browser-incompatible video to H.264 (webrtc_server.py)
+ -- a real encode, not just remux/probe -- so only a GPL ffmpeg build works
+ here; libx264 is GPL, no LGPL-only build includes it. The gpl-shared
+ preset also carries h264_qsv and h264_nvenc, which hwaccel.py uses to put
+ that encode on the GPU where there is one; a build without them still
+ works and is simply slower, on the machines that can least afford it.
Asking an end user to separately install ffmpeg (`winget install ffmpeg`)
is not viable for a non-technical install: it needs network access and
winget/App Installer present at that exact moment, and fails silently