github derekshreds/Snacks v2.4.0
Snacks v2.4.0

10 hours ago

Snacks v2.4.0

Automated Video Library Encoder

Major feature release. Full settings overhaul with a modular codebase refactor, opt-in password auth, Plex and Jellyfin integrations with smart path mapping, HMAC-signed notification webhooks, and native in-process OCR for bitmap subtitles (PGS / VobSub / DVB) backed by Tesseract with a custom per-cue sampling pipeline and dictionary-aware post-pass spellcheck. Three encoding modes (including a mux-only path that never re-encodes video), library exclusions, and LAN-only hardening round out the release.


New Features

Password Authentication

  • Opt-in login gate for the web UI -- new AuthService, AuthMiddleware, and AuthController add an optional password layer. Passwords are stored as PBKDF2-SHA256 with 100k iterations and a per-install salt; sessions are HMAC-signed tokens with a 14-day lifetime, delivered as httpOnly / sameSite cookies. When auth is enabled, unauthenticated requests redirect to /Auth/Login.
  • Server-side session invalidation -- disabling auth or changing the password rotates the server's signing secret, which invalidates every outstanding session token immediately. No orphaned sessions can survive a credential change.
  • LAN-only credential endpoints -- new LocalNetworkOnlyFilter gates integration- and auth-credential endpoints so they're only callable from RFC1918 / CGNAT / link-local / loopback ranges AND from an IP currently registered as a connected cluster node. Reduces the blast radius if a shared secret leaks.

Plex & Jellyfin Integrations

  • Auto-refresh media servers after encodes and scans -- new IntegrationService, IntegrationsController, and IntegrationConfig let you wire in Plex (API token) and Jellyfin (API key) endpoints. The transcoder triggers a scoped library rescan for each finished file instead of a full library refresh when possible.
  • Automatic path mapping -- Snacks and the media server frequently see different filesystem roots (e.g. Docker bind-mounts where Snacks sees /media/movies/X.mkv but Plex sees /data/movies/X.mkv). The integration layer now discovers the server's library roots and remaps file paths automatically, falling back to a full refresh only when no root matches.

Notifications with HMAC Signing

  • Event-driven notifications -- new NotificationService dispatches on encode-started / encode-completed / encode-failed, scan-completed, and node-online / node-offline events. Supports webhook POSTs, ntfy, and Apprise destinations.
  • Webhook payload signing -- when a shared secret is configured on a webhook destination, each payload is signed with HMAC-SHA256("{timestamp}.{body}", secret) and sent as X-Snacks-Signature: sha256=<hex> plus X-Snacks-Timestamp. Receivers can verify authenticity and reject replayed or forged requests.

Native OCR Subtitle Extraction

  • In-process Tesseract pipeline -- new Services/Ocr/ subsystem rather than an external OCR dependency. Bitmap subtitle tracks are decoded and OCR'd in-process, with format-specific parsers for PGS (Blu-ray), VobSub / IDX+SUB (DVD), and DVB / XSUB. Output is written directly as timestamped SRT via SrtWriter.
  • Custom pre-OCR sampling for accuracy -- ImagePreprocessor upscales bitmaps ~6x to approximate Tesseract's 300 DPI training scale for 40-60px glyph height, detects italic skew per-cue rather than per-file (so movies that mix italic and upright text don't get uniformly deskewed and misaligned), and cleans up antialiasing artifacts before handoff.
  • Dictionary-aware post-pass spellchecker -- new SubtitleSpellChecker runs edit-distance-1 correction against frequency-sorted wordlists (50,000-word English dictionary shipped in tools/wordlists/eng.txt). Candidates are scored by bigram context, character-shape similarity (accounts for Tesseract's common confusables like cl/d, rn/m), and frequency rank. Proper nouns, acronyms, and rare legitimate words are protected from overcorrection.
  • Docker image ships Tesseract + traineddata -- the Linux image now includes Tesseract 5 and resolves language .traineddata files through TessdataResolver, which checks the bundled tools/tessdata/ directory first before falling back to on-demand download.
  • OCR'd subtitles are muxed back in -- extracted SRT tracks are automatically muxed into the output container with proper language metadata and preserved track titles. "English [SDH]" becomes "English [SDH] (OCR)", so SDH and standard tracks stay distinguishable.
  • Bitmap subtitle finding utility -- new test-subs-finder console project scans a library and reports which files carry image-based subtitle tracks, useful for pre-flighting OCR work across a collection.

Encoding Modes

  • Three top-level encoding modes -- a new EncodingMode setting selects the strategy Snacks uses for every file:
    • Transcode (default) -- files above the bitrate target are re-encoded per the Video tab; files at or below target are skipped. Existing behavior.
    • Hybrid -- same as Transcode for above-target files, but files at target that would otherwise be skipped get a video-copy mux pass so configured audio / subtitle work still runs. Minutes of video-copy instead of hours of re-encode when you just need to normalize audio codecs or inject OCR'd subtitles.
    • Mux Only -- guarantees the video stream is never re-encoded. Files with muxable audio / subtitle work get a mux pass; files with nothing to change are skipped entirely, regardless of bitrate or codec. Ideal for large already-optimized libraries where you want to bulk-remux audio tracks or add OCR'd subtitles without touching video.
  • Mux stream selector -- companion MuxStreams setting (Both / Audio / Subtitles) controls which stream types a mux pass is allowed to touch. Streams outside the selected type are stream-copied through untouched, ignoring their tab settings, so you can (for example) run a subtitle-only sweep without any audio changes leaking in.
  • Language-tag inference for bitmap subs -- mux passes that OCR bitmap subtitles now fall back to the track title ("English SDH") when the container's language tag is missing or und, so OCR output gets correctly tagged as .eng.srt / language=eng instead of .und.srt. The language keep-list filter also honors title-inferred language, so "keep English only" catches title-only English tracks that previous releases would have dropped.
  • Strict subtitle language filter -- when a language keep-list is set and no subtitle track matches, output subs are now stripped (previously fell back to "keep all"). Sidecar extraction and mux-pass subtitle handling behave identically.
  • Output file size on completed cards -- finished work items in the queue now display the encoded output size next to the original size for a quick before/after at a glance.

Library Exclusions

  • Auto-scan exclusion rules -- new ExclusionRules model lets the auto-scanner skip files by glob pattern, minimum file size (gigabytes), or resolution label (2160p / 1440p / 1080p / 720p / 480p). Useful for keeping 4K masters out of the encode queue or ignoring already-optimized files.

Passthrough Audio Track Titles

  • Track titles are preserved when audio is copied -- when encoding with AudioCodec: copy, the original track titles (e.g. "English 5.1 Surround", "Commentary - Director") are now carried through via FFmpeg metadata.

Unified Language Matcher

  • ISO 639-1 / 639-2 round-tripping -- new LanguageMatcher provides bidirectional mapping between 2-letter, 3-letter (both /T and /B variants), and English names. Used by audio, subtitle, and OCR pipelines so language selection and display stay consistent. Unknown codes fall back to case-insensitive exact match so exotic / private-use tags like qaa round-trip unchanged.

Refactor

Modular Codebase

  • HomeController decomposition -- the former 1000+ line catch-all controller is split into nine focused controllers: AuthApiController, AuthController, AutoScanController, ClusterAdminController, IntegrationsController, LibraryController, NotificationsController, QueueController, SettingsController. Request DTOs moved to Models/Requests/.
  • Frontend module split -- wwwroot/js/transcoding.js (2567 lines) is deleted and reorganized into modular pieces under wwwroot/js/:
    • api.js -- centralized fetch layer
    • core/ -- SignalR client, connection status
    • cluster/ -- dashboard, settings form, override dialog
    • library/ -- library browser
    • queue/ -- queue manager, work-item renderer, log viewer, pause control, stop/cancel dialog
    • settings/ -- settings tabs, encoder form, chip input, folder picker, ISO languages, plus a panels/ subfolder per tab
    • utils/ -- DOM helpers, modal controller
  • Settings view split -- the monolithic _EncoderOptions.cshtml is removed in favor of per-tab partials: _GeneralSettings, _VideoSettings, _AudioSettings, _SubtitleSettings, _MuxSettings, _LibrarySettings, _IntegrationSettings, _SecuritySettings, _AdvancedSettings.

Bug Fixes

  • Invalid IP address dispatch for misconfigured cluster nodes -- worker nodes running inside Docker Desktop or similar VMs can advertise an internal IP the master can't reach. Cluster handshake now overrides the node's self-reported IP with the actual TCP source address, and discovery overrides with the host from the reachable handshake URL. Misconfigured nodes are now routable as long as at least one of their addresses is reachable.
  • Auth cookie no longer persists across browser sessions -- the session cookie dropped its 14-day Expires attribute and is now session-only. Changing any auth setting (enable / disable / password change) clears the client's cookie immediately, forcing a fresh login so client state can't diverge from server state.
  • Settings tab scroller visibility -- the horizontal overflow indicator on the settings tab bar was failing to render on first view because the measurement ran before layout settled. The scroller now renders correctly on initial navigation.
  • Hardened worker settings visibility and override modal -- node-sync panel and the override dialog now correctly reflect which settings are overridable per-node vs cluster-wide, and sensitive values are masked consistently across the UI.

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.

Breaking Changes

  • Settings schema expanded. New sections for auth, integrations, notifications, exclusions, and muxing are persisted to the config file. Existing configs continue to load; the new sections default to off / empty.

Files Changed

New Controllers

  • Snacks/Controllers/AuthApiController.cs, AuthController.cs
  • Snacks/Controllers/AutoScanController.cs
  • Snacks/Controllers/ClusterAdminController.cs
  • Snacks/Controllers/IntegrationsController.cs
  • Snacks/Controllers/LibraryController.cs
  • Snacks/Controllers/NotificationsController.cs
  • Snacks/Controllers/QueueController.cs
  • Snacks/Controllers/SettingsController.cs

New Services

  • Snacks/Services/AuthService.cs, AuthMiddleware.cs
  • Snacks/Services/IntegrationService.cs
  • Snacks/Services/NotificationService.cs
  • Snacks/Services/ConfigFileService.cs
  • Snacks/Services/LanguageMatcher.cs
  • Snacks/Services/LocalNetworkOnlyFilter.cs
  • Snacks/Services/MediaTypeDetector.cs
  • Snacks/Services/SubtitleExtractionService.cs
  • Snacks/Services/VideoFilterBuilder.cs
  • Snacks/Services/Ocr/NativeOcrService.cs
  • Snacks/Services/Ocr/ImagePreprocessor.cs
  • Snacks/Services/Ocr/SubtitleSpellChecker.cs
  • Snacks/Services/Ocr/Parsers/PgsParser.cs
  • Snacks/Services/Ocr/Parsers/VobSubParser.cs
  • Snacks/Services/Ocr/SrtWriter.cs
  • Snacks/Services/Ocr/TessdataResolver.cs
  • Snacks/Services/Ocr/BitmapEvent.cs

New Models

  • Snacks/Models/AuthConfig.cs
  • Snacks/Models/ExclusionRules.cs
  • Snacks/Models/IntegrationConfig.cs
  • Snacks/Models/MuxStreamSummary.cs
  • Snacks/Models/NotificationConfig.cs
  • Snacks/Models/Requests/*.cs (11 new request DTOs)

New Views

  • Snacks/Views/Auth/Login.cshtml
  • Snacks/Views/Shared/_GeneralSettings.cshtml
  • Snacks/Views/Shared/_VideoSettings.cshtml
  • Snacks/Views/Shared/_AudioSettings.cshtml
  • Snacks/Views/Shared/_SubtitleSettings.cshtml
  • Snacks/Views/Shared/_MuxSettings.cshtml
  • Snacks/Views/Shared/_LibrarySettings.cshtml
  • Snacks/Views/Shared/_IntegrationSettings.cshtml
  • Snacks/Views/Shared/_SecuritySettings.cshtml
  • Snacks/Views/Shared/_AdvancedSettings.cshtml
  • Removed: Snacks/Views/Shared/_EncoderOptions.cshtml

Frontend

  • Removed: Snacks/wwwroot/js/transcoding.js (2567 lines)
  • Added: Snacks/wwwroot/js/api.js, main.js, plus modular folders core/, cluster/, library/, queue/, settings/ (including settings/panels/), and utils/
  • Snacks/wwwroot/css/site.css -- styling for new settings and panels

Tools / Data

  • Snacks/tools/tessdata/ -- Tesseract .traineddata bundle with README and download script
  • Snacks/tools/wordlists/ -- OCR spellcheck dictionaries (50,000-word English bundled) with README and download script
  • test-subs-finder/ -- console utility for locating bitmap subtitle tracks in a library
  • Snacks/Dockerfile -- Tesseract install for Linux image

Core

  • Snacks/Controllers/HomeController.cs -- slimmed to health/index/shutdown, version bump to 2.4.0
  • Snacks/Program.cs -- DI registration for new services, auth and LAN-only middleware wiring
  • Snacks/Services/TranscodingService.cs -- mux-mode pipeline, audio title passthrough, integration and notification hooks, OCR integration
  • Snacks/Services/FfprobeService.cs -- track title extraction, codec detection helpers
  • Snacks/Services/FileService.cs -- exclusion rule evaluation
  • Snacks/Services/AutoScanService.cs -- exclusion rules, notification hooks
  • Snacks/Services/ClusterService.cs, ClusterNodeJobService.cs, ClusterDiscoveryService.cs -- IP override, integration sync, protocol version bump to 2.4.0
  • Snacks/Services/ClusterFileTransferService.cs -- OCR payload transfers
  • Snacks/Models/EncoderOptions.cs, EncoderOptionsOverride.cs -- mux mode, exclusions, integration / notification config surfaces
  • Snacks/Models/WorkItem.cs -- output size, mux summary
  • Snacks/Models/MediaFile.cs, Data/MediaFileRepository.cs, Data/SnacksDbContext.cs -- new columns for exclusion / output metadata
  • Snacks/Snacks.csproj -- TesseractOCR, SkiaSharp package references; bundled tessdata and wordlist content items
  • electron-app/main.js -- backend launch adjustments for OCR resource paths

Version Bumps

  • Snacks/Controllers/HomeController.cs
  • Snacks/Services/ClusterDiscoveryService.cs -- protocol version bump to 2.4.0
  • Snacks/Views/Shared/_Layout.cshtml
  • README.md
  • build-and-export.bat
  • electron-app/package.json / package-lock.json

Full documentation: README.md

Don't miss a new Snacks release

NewReleases is sending notifications on new releases.