TAN for Jellyfin

Adds a "TAN Normalized" version of your library right into Jellyfin's own Play Version picker, alongside the original.

How it fits together

This isn't a single install - it's two small pieces working together:

Splitting it this way means the DSP is written once, in Rust, and isn't reimplemented in C# just for Jellyfin.

What actually happens to your files

A manual scheduled task walks your library, extracts each item's audio with Jellyfin's own bundled ffmpeg, sends it to tan-server, and - for video - muxes the normalized audio back with the original video stream, copied verbatim (no re-encode) into a new file next to the source. Your original file is never modified or replaced. Once a normalized copy exists, later runs leave it alone; delete it to force a redo.

Setup

  1. Run tan-server somewhere your Jellyfin server can reach it - the same machine, by default:
    cargo run --release -p tan-server
    or grab the tan-server binary from the releases page and run it directly. It listens on http://127.0.0.1:5859 and has no authentication, so only bind it elsewhere behind something that provides some.
  2. Build the plugin (there's no plugin repository yet, so this is a manual install):
    git clone https://github.com/bknie1/True-Audio-Normalizer
    cd True-Audio-Normalizer/jellyfin-plugin-tan
    dotnet build -c Release
  3. Copy the built Jellyfin.Plugin.Tan.dll into a new folder under Jellyfin's plugins directory, e.g. <jellyfin-data>/plugins/Tan_1.0.0.0/, then restart Jellyfin.
  4. In Jellyfin: Dashboard → Plugins → TAN - set the tan-server URL (default is fine if it's on the same machine) and pick a profile (movie, music, speech, night, universal, or game).
  5. Dashboard → Scheduled Tasks → TAN → "Normalize Audio with TAN" - run it. It's manual-run only on purpose, since it touches every item in your library on a pass.
  6. Play something that was processed. Look for "TAN Normalized" in the client's Play Version (or audio track) picker.
Honest status: this plugin compiles clean against the real Jellyfin SDK and every API it uses was confirmed by reflection against the actual installed assembly, not written from memory - but it hasn't yet been run inside a live Jellyfin server end to end. If something doesn't line up on your setup, open an issue.