github derekshreds/Snacks v2.2.4
Snacks v2.2.4

7 hours ago

Snacks v2.2.4

Automated Video Library Encoder

Patch release upgrading FFmpeg from a 2023 build to the latest (transitioning Intel QSV from MediaSDK to oneVPL), adding per-encoder rate control tuning, video-only bitrate measurement, multi-point VAAPI/SVT-AV1 calibration, a configurable skip threshold setting, live settings updates without rescan, and several directory navigation and path validation fixes.


New Features

FFmpeg Upgrade — MediaSDK to oneVPL

  • FFmpeg upgraded from 2023 build to latest -- the bundled FFmpeg moves from the legacy Intel MediaSDK backend to Intel oneVPL (Video Processing Library) for all QSV encoding. FFmpeg 7.0+ dropped MediaSDK support entirely, so this upgrade is required for QSV to function on current Intel drivers. Encoder names (h264_qsv, hevc_qsv, av1_qsv) remain the same, but the underlying library is now oneVPL.

Per-Encoder Rate Control

  • Dedicated rate control flags for each hardware encoder -- NVENC, AMF, QSV, and SVT-AV1 each get tailored VBR parameters instead of sharing a generic -b:v/-minrate/-maxrate template. NVENC uses lookahead + adaptive QP, AMF uses vbr_peak with enforce_hrd to work around an FFmpeg >= 7.1 bug where -maxrate is ignored in generic VBR, QSV uses extbrc with lookahead for reliable maxrate enforcement, and SVT-AV1 uses rc=1 VBR with a 5% inflation to compensate for systematic undershoot.
  • Crop re-encodes use the same per-encoder logic -- GetCropCompressionFlags mirrors the main encoding path so black border removal encodes use the correct rate control for the active encoder.

Video-Only Bitrate Measurement

  • Quick video-only bitrate probe for borderline files -- files near the target bitrate now get a fast 15-second -c:v copy pass to measure the true video stream bitrate, stripping audio and subtitle overhead (typically 1000–4000 kbps). This prevents incorrect skip/encode decisions caused by audio inflating the total bitrate.

Multi-Point Calibration

  • VAAPI QP calibration samples two file locations -- instead of a single 60-second sample at 40%, calibration now takes two 30-second samples at 25% and 60% of the file and uses the peak bitrate for QP adjustment. Short files (< 90 seconds) fall back to a single proportional sample. Tolerance tightened from 20% to 15%.
  • SVT-AV1 VBR bitrate calibration -- new CalibrateSvtAv1BitrateAsync runs iterative test encodes at two positions, scaling -b:v until measured average output is within 5% of target. Compensates for SVT-AV1's ~20–25% systematic undershoot in VBR mode.

Configurable Skip Threshold

  • SkipPercentAboveTarget setting -- new encoder option (default 20%) controls how far above the target bitrate a file can be and still be skipped when it's already in the target codec. Replaces the hardcoded 1.2x multiplier. Exposed in the settings UI with a numeric input clamped 0–100%.

Live Settings Updates

  • Settings changes take effect immediately -- SaveSettings now deserializes the saved JSON back into an EncoderOptions and calls TranscodingService.UpdateOptions, so queued items pick up setting changes without starting a new scan. The processing loop reads from _lastOptions instead of the original scan options.

Cluster No-Savings Handling

  • Worker nodes detect and report no-savings encodes -- when encoding succeeds but the output is larger than the original (deleted by ConvertAsync), the worker reports noSavings: true in the completion payload. The master skips the download, marks the file as Skipped, releases the node, and cleans up all tracking state.
  • JobCompletion.NoSavings property -- new boolean on the completion model, propagated through the ReportCompletion endpoint via a JSON body parameter.

Remote Job Log Persistence

  • Cluster encoding logs written to disk -- ClusterService now appends remote job log lines to the same log file path used by local encodes (BuildLogFilePath made public). Logs survive page refreshes and restarts. GetLogs falls back to searching the logs directory by short ID for remote jobs not in the local _workItems dictionary.

Bug Fixes

Directory Navigation

  • Parent path computation respects library root -- BrowseSubdirectories now computes parentPath server-side instead of relying on client-side string splitting. Returns null when at the library root so the frontend shows the top-level listing, preventing navigation above the configured library path.
  • Bare Windows drive letters normalized -- the frontend appends \ to bare drive letters like D: before navigating, preventing Windows from resolving to the process CWD on that drive.
  • Top-level directory listing no longer counts video files -- LoadDirectories returns videoCount: 0 and no longer filters out empty directories, removing a potentially slow recursive file count on large libraries.

Path Validation

  • Trailing separator normalization on all path checks -- all AllowAllPaths guards now TrimEnd(Path.DirectorySeparatorChar) on both the request path and the library root before comparison, fixing edge cases where trailing slashes caused valid paths to be rejected.

Encoding

  • Hardware encoder availability test with software fallback -- before starting an encode, non-software encoders are tested with TestEncoderAsync. If the hardware encoder isn't available, the system falls back to the corresponding software encoder (libx264, libx265, or libsvtav1) and disables hardware init flags for that encode.
  • 4K VBR bitrate window tightened -- 4K encodes now use ±200k/+500k instead of ±500k/+1000k for min/max bitrate, reducing overshoot on high-definition content.
  • bufsize doubled across all encoder paths -- all rate control configurations now use bufsize = maxrate * 2 instead of bufsize = maxrate, giving the rate controller more room to smooth bitrate spikes.

Database

  • Stale EF Core migration lock cleared on startup -- InitializeAsync deletes any leftover __EFMigrationsLock row before running migrations, preventing startup hangs after a crash. Safe because Snacks is a single-instance app.

Frontend

  • Version shown in footer -- the layout footer now displays v2.2.4 alongside the copyright.
  • HistoryCleared SignalR event resets UI -- clears the local workItems and logs maps and reloads, so Clear History is reflected immediately without a page refresh.
  • SignalR reconnect reloads cluster config -- onreconnected now calls loadClusterConfig in addition to loadWorkItems, ensuring cluster state is current after a connection drop.
  • Unpause kicks off queue processing -- SetLocalEncodingPaused(false) now fires ProcessQueueAsync for any items already waiting, so unpausing doesn't require a new scan to resume work.

Files Changed

New Files

  • test-encoder/ -- encoder test utilities
  • test-encoding.bat -- encoding test script

Modified Files

  • Snacks/Controllers/ClusterController.cs -- ReportCompletion accepts JSON body with noSavings flag
  • Snacks/Controllers/HomeController.cs -- version bump, path normalization fixes, parent path computation, live settings update, directory listing simplification
  • Snacks/Data/MediaFileRepository.cs -- clears stale EF Core migration lock on startup
  • Snacks/Models/EncoderOptions.cs -- added SkipPercentAboveTarget property
  • Snacks/Models/JobAssignment.cs -- added NoSavings to JobCompletion
  • Snacks/Services/ClusterDiscoveryService.cs -- version bump
  • Snacks/Services/ClusterNodeJobService.cs -- no-savings detection, conditional completion reporting, immediate cleanup for no-savings jobs
  • Snacks/Services/ClusterService.cs -- HandleRemoteCompletionAsync no-savings path, remote log persistence, BuildLogFilePath usage
  • Snacks/Services/TranscodingService.cs -- video-only bitrate measurement, per-encoder rate control, multi-point calibration, SVT-AV1 calibration, skip threshold setting, live options update, software fallback, hardware encoder test, BuildLogFilePath made public, log directory fallback search
  • Snacks/Views/Shared/_EncoderOptions.cshtml -- skip threshold UI control
  • Snacks/Views/Shared/_Layout.cshtml -- version in footer
  • Snacks/wwwroot/js/transcoding.js -- HistoryCleared handler, reconnect cluster reload, drive letter normalization, server-side parent navigation, SkipPercentAboveTarget save/load
  • README.md -- version bump
  • electron-app/package.json -- version bump
  • electron-app/package-lock.json -- version bump

Full documentation: README.md

Don't miss a new Snacks release

NewReleases is sending notifications on new releases.