Installing NoriSync on Jellyfin

NoriSync is distributed as a Jellyfin plugin repository, so the recommended install path is to add the repo to your Jellyfin server and let Jellyfin handle downloads and updates.

NoriSync · latest 1.0.0.71 · target ABI 10.11.0.0 · published 2026-05-06

Requirements

1. Add the plugin repository

The manifest is published from the project's Gitea releases.

Manifest URL:

https://git.missen.ca/Esmond/jellyfin-plugin-norisync/releases/download/manifest/manifest.json

In Jellyfin:

  1. Open Dashboard → Plugins → Repositories.
  2. Click the + button to add a new repository.
  3. Fill in:
  4. Click Save and accept the prompt to trust the repository.

Jellyfin fetches the manifest and merges NoriSync into the plugin catalog.

2. Install the plugin

  1. Switch to the Catalog tab on the Plugins page.
  2. Under the General category, find NoriSyncSync local tracks with Jellyfin.
  3. Click it, pick the latest version (1.0.0.71, published 2026-05-06), and click Install.
  4. Restart Jellyfin when prompted. The plugin won't load until the server process restarts.

After restart, the plugin appears under Dashboard → Plugins → My Plugins. Identifying details:

Plugin GUID
11c1ffe5-e4de-4cbb-a30c-c2870eb81603
Owner
Esmond
Description
A Jellyfin plugin for synchronizing Nori with your Jellyfin server library.
Category
General

Manual install (alternative)

If your server can't reach the manifest URL, download the latest zip directly and extract it into Jellyfin's plugins/NoriSync_<version>/ directory, then restart Jellyfin.

Plugin zip
Jellyfin.Plugin.NoriSync_1.0.0.71.zip
MD5 checksum
100a488041f50c210c6df810ed7b9292
Manifest
manifest.json

Source code

NoriSync is licensed under GPL-2.0-or-later. The source archive for this build is available if you'd like to inspect or rebuild it before installing the binary.

Source zip (v1.0.0.71)
jellyfin-plugin-norisync-v1.0.0.71.zip

To rebuild from source: extract the zip and run dotnet build Jellyfin.Plugin.NoriSync/Jellyfin.Plugin.NoriSync.csproj -c Release. Outputs land in bin/Release/net9.0/.

3. Run the companion service (optional)

Skip this section if you don't want audio embeddings — the delta-sync API works without the companion. Otherwise, the norisync-embedder is a small FastAPI server that wraps a YAMNet ONNX model and exposes /embed and /health. The plugin calls it over HTTP from the Compute Audio Embeddings scheduled task.

Run it on whichever host you want — Jellyfin's box, an Apple Silicon Mac, or a Linux machine with a CUDA GPU. The plugin only needs to reach it on the network.

Install

Source lives in the companion/ directory of this repo. Easiest path is uv, which the project's uv.lock is built against. Python ≥ 3.11 is required.

git clone https://git.missen.ca/Esmond/jellyfin-plugin-norisync.git
cd jellyfin-plugin-norisync/companion
uv sync --extra fetch

The fetch extra pulls in TensorFlow, tensorflow-hub, and tf2onnx — only needed for the one-time model conversion below. Drop it if you already have yamnet.onnx on disk and point NORISYNC_EMBEDDER_YAMNET_ONNX at it.

Fetch the model (one-time)

uv run python -m norisync_embedder.tools.fetch_yamnet

Pulls YAMNet from tfhub.dev/google/yamnet/1 and writes yamnet.onnx into the cache directory (~/Library/Caches/norisync-embedder on macOS, overridable via NORISYNC_EMBEDDER_CACHE_DIR). After this you can drop the fetch extra — the runtime server only needs onnxruntime.

Run

uv run norisync-embedder

Listens on 0.0.0.0:9000 by default. Verify it's up:

curl http://<companion-host>:9000/health
# {"status":"ok","model_version":"yamnet-v3+bpm1","providers":["CPUExecutionProvider"], ...}

Environment variables

VariableDefaultNotes
NORISYNC_EMBEDDER_HOST 0.0.0.0 Bind address.
NORISYNC_EMBEDDER_PORT 9000 Bind port. Whatever you pick goes into the plugin's Embedder Endpoint field.
NORISYNC_EMBEDDER_DEVICE auto onnxruntime execution provider: cpu, cuda, or coreml (alias mps). Auto picks CUDA when available, otherwise CPU. CoreML is opt-in — see the requirements section.
NORISYNC_EMBEDDER_CACHE_DIR ~/Library/Caches/norisync-embedder Where yamnet.onnx is read from / written to.
NORISYNC_EMBEDDER_YAMNET_ONNX (blank) Explicit path to a pre-existing ONNX file. Overrides the cache dir lookup.
NORISYNC_EMBEDDER_LOG_LEVEL INFO Standard Python logging levels.

To run as a long-lived service, wrap uv run norisync-embedder in whatever supervisor your host uses — launchd on macOS, systemd on Linux, a Docker CMD, etc.

4. Configure the plugin

Open Dashboard → Plugins → My Plugins → NoriSync to reach the settings page. There are two sections.

Retention

SettingDefaultNotes
Retention Period (days) 30 Change records older than this are purged. Also the idle threshold for registered clients — instances silent for this many days are dropped from retention gating.

Lower this if disk usage on the change log is a concern; raise it if you have clients that go offline for extended periods and you don't want them to miss deletes.

Audio embeddings

These settings drive the NoriSync: Compute Audio Embeddings scheduled task (daily at 03:00 by default). Leave embeddings disabled if you only want the delta-sync API.

SettingDefaultNotes
Enable Audio Embeddings off Master switch. The scheduled task is a no-op until this is on.
Max Tracks Per Run 0 Cap on tracks processed per run. 0 = unlimited. Useful when first enabling on a large library to spread the initial scan across multiple nights.
Embedding Concurrency 2 Parallel workers. Each spawns its own ffmpeg decode, so this multiplies CPU and process count. 2–3 is typical; raise carefully.
Embedder Endpoint (blank) Base URL of the norisync-embedder companion, e.g. http://m5-mac:9000. Required when embeddings are enabled — inference is always offloaded to this service over HTTP, there is no in-process path.

The model is YAMNet (Apache-2.0, 521-class AudioSet classifier). The companion ships a one-time conversion tool — python -m norisync_embedder.tools.fetch_yamnet — that pulls the weights from TF Hub and writes a local yamnet.onnx served by onnxruntime. Embedding model version is reported in /health as yamnet-v3+bpm1.

Verifying the install

After saving config, confirm the plugin is live without auth by hitting:

GET http://<your-jellyfin>/api/norisync/info

It returns { id, name, version }. All other endpoints require Jellyfin authentication — see the API section of the README for the full endpoint list.

Updating

Once the repository is added, Jellyfin's plugin catalog will surface new versions automatically. Use Dashboard → Plugins → My Plugins to update, then restart Jellyfin.