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:
- tan-server - a tiny local program that does the actual audio processing. It doesn't know anything about Jellyfin.
- The Jellyfin plugin - a thin client that asks tan-server to process your files, then tells Jellyfin about the result. It does no audio processing itself.
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
- Run tan-server somewhere your Jellyfin server can
reach it - the same machine, by default:
or grab thecargo run --release -p tan-servertan-serverbinary from the releases page and run it directly. It listens onhttp://127.0.0.1:5859and has no authentication, so only bind it elsewhere behind something that provides some. - 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 - Copy the built
Jellyfin.Plugin.Tan.dllinto a new folder under Jellyfin's plugins directory, e.g.<jellyfin-data>/plugins/Tan_1.0.0.0/, then restart Jellyfin. - 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).
- 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.
- 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.