Files
Media-Server-Setup/jellyfin-plugin-vanguard
Brandyn / Techy 3d42271ae2 Record streams into hidden .live/ and publish finished files via the sweep; plugin 0.1.2 feed wording
Jellyfin indexed in-progress fragmented recordings (no duration -> seek jumped to next episode).
MediaMTX now writes under <Title>/.live/; the sweep remuxes finished files into the title folder
and removes the source. Feed says 'New recording' since it fires after publish.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-30 22:45:30 -05:00
..

Vanguard Metadata — Jellyfin plugin

Metadata provider for gameplay recordings. Each streamer/submitter folder is a show; season and episode numbers come from the recording timestamp under a rolling policy; names, avatars and episode titles come from Discord via Authentik's identity link; new recordings and clips are announced in a Discord channel.

Layout

  • Jellyfin.Plugin.Vanguard.Core/ — pure logic: SeasonPolicy (rolling buckets, naming, overrides), ItemTimestamp (sidecar → filename patterns → mtime). No Jellyfin dependency. Unit-tested.
  • Jellyfin.Plugin.Vanguard/ — the plugin: providers (Series, Series images, Season, Episode), services (Discord REST, Authentik REST, event store, identity resolver, feed), scheduled tasks (Discord snapshot every 5 min; season roll nightly after the rollover hour), config page.
  • Jellyfin.Plugin.Vanguard.Tests/ — xunit.

Season scheme

age of item season # season name
current ISO week YYYYMMDD "Thursday, Oct 29"
current month 1YYYYWW "Week 44"
current year YYYYMM "October 2026"
older YYYY "2026"

Episode # = MMDDHHMMSS of the local timestamp — never changes when the season rolls. Broadcast day rolls at the configured hour (default 04:00). Overrides: seasonNumber=Name, one per line.

Timestamp sources, in order

  1. <name>.json / <name>.clip.json sidecar with "timestamp" (UTC ISO-8601) — written by the clip bot
  2. filename: MediaMTX 2026-10-29_21-03-11, Game Bar 2026-10-29 21-03-11, ShadowPlay 2026.10.29 - 21.03.11, Steam 20261029_210311
  3. file modification time (Syncthing preserves the gamer's mtime)

Build / package

./package.sh            # tests + Release build → dist/VanguardMetadata_<ver>.zip + manifest.json

Requires .NET 10 SDK. Bump version in build.yaml for a release.

Install on the server (manual, v0.1)

scp dist/VanguardMetadata_0.1.0.0.zip debian@HOST:/tmp/
ssh debian@HOST 'sudo -u "#1000" mkdir -p "/srv/appdata/jellyfin/config/plugins/Vanguard Metadata_0.1.0.0" && sudo -u "#1000" python3 -m zipfile -e /tmp/VanguardMetadata_0.1.0.0.zip "/srv/appdata/jellyfin/config/plugins/Vanguard Metadata_0.1.0.0/" && cd ~/vanguard-stream && docker compose restart jellyfin'

Later: serve dist/ at https://HOST/plugins/ (Caddy) and add it as a repository in Jellyfin so updates come through the Catalog.

Runs with an empty config

Seasons, episode numbers, timestamps and the nightly roll need nothing external. Without a Discord bot token the show is named after its folder, has no poster, and episode titles are the dock title; without Authentik no folder→Discord mapping is attempted; without a feed channel nothing is posted. Add the credentials later and re-run "roll seasons" / refresh the libraries to pick up names and avatars.

Configure (Dashboard → Plugins → Vanguard Metadata)

  • Discord: bot token (add a Bot to the existing Authentik Discord application; enable the Server Members intent; invite it to the server), guild ID, feed channel ID, public Jellyfin URL.
  • Authentik: URL + API token of a read-only service account (used to map folder → Discord user).
  • Folder → identity overrides if a streamer's folder name isn't their Authentik username.
  • Libraries (Dashboard → Libraries → each of streams/clips): content type Shows; metadata downloaders: only "Vanguard Metadata" for Series, Season and Episode; image fetchers: Vanguard Metadata (Series) and Screen Grabber (Episode) — the grab is what the Discord embed attaches.

Tasks (Dashboard → Scheduled Tasks → Vanguard)

  • "snapshot Discord events": every 5 min + startup. Run it once after configuring.
  • "roll seasons": daily at rollover+10 min. Run it once after the first library scan.