github derekshreds/Snacks v2.3.1

5 hours ago

Snacks v2.3.1

Automated Video Library Encoder

Patch release focused on cluster reliability: AMD VAAPI calibration fixes, ASCII-safe cluster auth and filename headers, smarter VAAPI bitrate calibration with oscillation guard, and versioned Docker image tags.


Bug Fixes

AMD VAAPI Calibration

  • Skip Intel-only Low Power mode on AMD -- VAAPI calibration previously tried -low_power 1 on every GPU. That entrypoint (VAEntrypointEncSliceLP) is Intel-only; AMD cards only implement VAEntrypointEncSlice, so the LP pass always failed before falling back. Calibration now detects the vendor and only attempts LP mode on Intel.
  • Drop redundant hwupload on hardware-decoded frames -- when the input is already being hardware-decoded, the frames live on the GPU. The encode pipeline was still appending format=nv12|vaapi,hwupload, which fails on AMD drivers because you can't upload a surface that's already a surface. hwupload is now only inserted for software-decode -> hardware-encode paths.
  • Removed Intel-only -low_power 1 from the VAAPI encoder self-test -- the one-frame encoder capability probe no longer hard-codes an Intel flag, so AMD cards pass the test correctly.

Cluster Auth Header Encoding

  • Shared secrets are now Base64-encoded on the wire -- HTTP headers must be ASCII, but ClusterConfig.SharedSecret can contain any Unicode character. Sending a non-ASCII secret raw produced an HttpRequestException before the request ever left the client. Outbound cluster requests now Base64(UTF-8) the secret; the server decodes before the constant-time compare. Invalid Base64 returns 401 Unauthorized instead of throwing.
  • Applied everywhere secrets are sent -- ClusterDiscoveryService, ClusterNodeJobService, and ClusterFileTransferService all route through the same EncodeSecretForHeader helper.

Filename Header Encoding

  • Original filenames are URL-escaped in transit -- X-Original-FileName was being set from raw workItem.FileName, which rejects non-ASCII characters at the HTTP layer. The sender now Uri.EscapeDataStrings the filename; the receiver unescapes it (falling back to the raw value on malformed input) before resolving the temp path.

VAAPI Bitrate Calibration Oscillation

  • Bisection fallback when the QP predictor oscillates -- the log-based QP predictor assumes a constant ~0.72x bitrate change per +2 QP. Real content often breaks that assumption and the loop would bounce between two QPs that straddle the target, burning every iteration without converging. Calibration now records QP -> peak kbps for every pass and, if the predictor picks a QP that's already been tested, bisects between the closest under- and over-target bracket. When adjacent QPs are exhausted, it stops early.
  • Best-observed QP is selected at the end -- instead of returning whatever QP the last iteration happened to land on (which may have been an untested guess), the final choice is now the lowest QP whose peak fits within the upper tolerance bound, falling back to the QP whose peak was closest to target.

Build / Packaging

  • Docker images are now pushed with both :latest and :{version} tags -- build-and-export.bat tags and pushes derekshreds/snacks-docker and derekshreds/snacksweb with both the moving latest tag and a pinned version tag, so deployments can lock to a specific release.

Known Issues

  • Sporadic progress updates on some items -- the bundled Jellyfin build of FFmpeg occasionally reports incorrect timestamps or omits frame counts entirely while encoding. When that happens, the progress bar for the affected item may appear to stall or update in jumps even though the encode is proceeding normally. This is an upstream FFmpeg behavior and does not affect output quality or completion.

Files Changed

  • Snacks/Controllers/ClusterController.cs -- unescape X-Original-FileName on receive
  • Snacks/Controllers/HomeController.cs -- version bump to 2.3.1
  • Snacks/Services/ClusterAuthMiddleware.cs -- EncodeSecretForHeader helper and Base64 decode of incoming X-Snacks-Secret
  • Snacks/Services/ClusterDiscoveryService.cs -- Base64-encoded secret header, protocol version bump to 2.3.1
  • Snacks/Services/ClusterFileTransferService.cs -- URL-escape X-Original-FileName, Base64-encoded secret header, simplified authenticated-client reuse
  • Snacks/Services/ClusterNodeJobService.cs -- Base64-encoded secret header
  • Snacks/Services/TranscodingService.cs -- AMD VAAPI LP skip, conditional hwupload, oscillation-guarded QP calibration with best-observed selection
  • Snacks/Views/Shared/_Layout.cshtml -- version bump
  • README.md -- version bump
  • build-and-export.bat -- dual :latest + :2.3.1 Docker tag push
  • electron-app/package.json / package-lock.json -- version bump

Full documentation: README.md

Don't miss a new Snacks release

NewReleases is sending notifications on new releases.