Implement Jellyfin MusicVideo library sync (currently silently dropped) #42

Closed
opened 2026-06-27 14:41:31 +02:00 by timothy · 3 comments
Owner

Summary

ErsatzTV can't sync MusicVideo items from a Jellyfin media source — the musicvideos Jellyfin CollectionType is silently dropped, so only Movies/Shows sync. Music-video / concert content therefore has to be shoehorned into Jellyfin's Movie type (NFO <movie> + DB Type=Movie, IsLocked=1) just so ErsatzTV will ingest it. Native MusicVideo sync would remove that workaround.

Known blockers (from prior analysis — server-management#174)

  1. JellyfinApiClient.cs Project() — only tvshows/movies/boxsets recognized; musicvideosNone (dropped).
  2. SynchronizeJellyfinLibraryByIdHandler.cs — only routes Movies/Shows; no IJellyfinMusicVideoLibraryScanner.
  3. IJellyfinApi.cs — hardcodes includeItemTypes=Movie.

Note: local libraries already support MusicVideos (MusicVideoFolderScanner); only the Jellyfin sync path is missing. LibraryMediaKind.MusicVideos = 3 exists but is unused on the Jellyfin path. Plex/Emby sources likely have the same gap — worth checking while in here.

Driver

Recurring real-world pain: server-management#489 — MTV Unplugged concerts repeatedly dropped out of Jellyfin's index and needed a per-folder restructure + Movie/IsLocked override to stay usable by ErsatzTV. Native MusicVideo sync would let such content stay typed MusicVideo and drop the Jellyfin-side hack.

Scope

Backlog stub — design/spec + implementation to be fleshed out within this project. Low priority (the workaround is effective), but a clean, possibly-upstreamable candidate now that the fork is actively maintained.

## Summary ErsatzTV can't sync **MusicVideo** items from a Jellyfin media source — the `musicvideos` Jellyfin CollectionType is silently dropped, so only Movies/Shows sync. Music-video / concert content therefore has to be shoehorned into Jellyfin's **Movie** type (NFO `<movie>` + DB `Type=Movie, IsLocked=1`) just so ErsatzTV will ingest it. Native MusicVideo sync would remove that workaround. ## Known blockers (from prior analysis — server-management#174) 1. `JellyfinApiClient.cs` `Project()` — only `tvshows`/`movies`/`boxsets` recognized; `musicvideos` → `None` (dropped). 2. `SynchronizeJellyfinLibraryByIdHandler.cs` — only routes `Movies`/`Shows`; no `IJellyfinMusicVideoLibraryScanner`. 3. `IJellyfinApi.cs` — hardcodes `includeItemTypes=Movie`. Note: **local** libraries already support MusicVideos (`MusicVideoFolderScanner`); only the Jellyfin sync path is missing. `LibraryMediaKind.MusicVideos = 3` exists but is unused on the Jellyfin path. Plex/Emby sources likely have the same gap — worth checking while in here. ## Driver Recurring real-world pain: server-management#489 — MTV Unplugged concerts repeatedly dropped out of Jellyfin's index and needed a per-folder restructure + Movie/IsLocked override to stay usable by ErsatzTV. Native MusicVideo sync would let such content stay typed MusicVideo and drop the Jellyfin-side hack. ## Scope Backlog stub — design/spec + implementation to be fleshed out within this project. Low priority (the workaround is effective), but a clean, possibly-upstreamable candidate now that the fork is actively maintained.
Author
Owner

Starting implementation in isolated worktree /private/tmp/ersatztv-issue42 from origin/main at f25cfdb5.

Initial findings match the issue:

  • JellyfinApiClient.Project() drops CollectionType=musicvideos.
  • SynchronizeJellyfinLibraryByIdHandler only routes Movies and Shows; unsupported kinds silently return success.
  • The EF model already supports MusicVideo under JellyfinLibrary, so this appears to be a sync/projection/scanner gap rather than a migration task.

Plan is TDD: add failing tests for Jellyfin MusicVideo library projection and sync routing, then implement the smallest Jellyfin-only scanner path needed. I’ll keep Plex/Emby out of scope unless a shared interface change forces touching them.

Starting implementation in isolated worktree `/private/tmp/ersatztv-issue42` from `origin/main` at `f25cfdb5`. Initial findings match the issue: - `JellyfinApiClient.Project()` drops `CollectionType=musicvideos`. - `SynchronizeJellyfinLibraryByIdHandler` only routes `Movies` and `Shows`; unsupported kinds silently return success. - The EF model already supports `MusicVideo` under `JellyfinLibrary`, so this appears to be a sync/projection/scanner gap rather than a migration task. Plan is TDD: add failing tests for Jellyfin MusicVideo library projection and sync routing, then implement the smallest Jellyfin-only scanner path needed. I’ll keep Plex/Emby out of scope unless a shared interface change forces touching them.
Author
Owner

Implementation is pushed and PR is open: #55

Status

What was done: Added Jellyfin MusicVideo library projection and sync routing, plus a new Jellyfin MusicVideo scanner that imports Jellyfin MusicVideo items into existing ErsatzTV MusicVideo entities.

Root cause: Jellyfin CollectionType=musicvideos was not recognized in JellyfinApiClient.Project(), so the library was dropped. The scanner handler also only routed Movies and Shows; unsupported library kinds silently returned success without scanning.

Files changed: Jellyfin API client/interface/model, Scanner Jellyfin sync handler, new IJellyfinMusicVideoLibraryScanner, new JellyfinMusicVideoLibraryScanner, scanner DI registration, and focused NUnit tests.

Verification:

  • RED confirmed for library projection: MusicVideo library projected as 0 libraries before the fix.
  • RED confirmed for sync routing: missing MusicVideo scanner contract/route before the fix.
  • TZ=UTC dotnet test ErsatzTV.Infrastructure.Tests/ErsatzTV.Infrastructure.Tests.csproj -v minimal passed (16 tests).
  • TZ=UTC dotnet test ErsatzTV.Scanner.Tests/ErsatzTV.Scanner.Tests.csproj -v minimal passed (1467 tests).
  • TZ=UTC dotnet test ErsatzTV.Architecture.Tests/ErsatzTV.Architecture.Tests.csproj -v minimal passed (5 tests).
  • git diff --check passed.

Deferred: PR #55 is waiting for CI; issue remains open until PR CI passes and the PR is merged.

Follow-up issues: none currently.

Docs updated: n/a; no operator-facing config or workflow changed.

Implementation is pushed and PR is open: https://gitea.tblindustries.be/timothy/ersatztv/pulls/55 ## Status **What was done**: Added Jellyfin MusicVideo library projection and sync routing, plus a new Jellyfin MusicVideo scanner that imports Jellyfin `MusicVideo` items into existing ErsatzTV `MusicVideo` entities. **Root cause**: Jellyfin `CollectionType=musicvideos` was not recognized in `JellyfinApiClient.Project()`, so the library was dropped. The scanner handler also only routed Movies and Shows; unsupported library kinds silently returned success without scanning. **Files changed**: Jellyfin API client/interface/model, Scanner Jellyfin sync handler, new `IJellyfinMusicVideoLibraryScanner`, new `JellyfinMusicVideoLibraryScanner`, scanner DI registration, and focused NUnit tests. **Verification**: - RED confirmed for library projection: MusicVideo library projected as 0 libraries before the fix. - RED confirmed for sync routing: missing MusicVideo scanner contract/route before the fix. - `TZ=UTC dotnet test ErsatzTV.Infrastructure.Tests/ErsatzTV.Infrastructure.Tests.csproj -v minimal` passed (16 tests). - `TZ=UTC dotnet test ErsatzTV.Scanner.Tests/ErsatzTV.Scanner.Tests.csproj -v minimal` passed (1467 tests). - `TZ=UTC dotnet test ErsatzTV.Architecture.Tests/ErsatzTV.Architecture.Tests.csproj -v minimal` passed (5 tests). - `git diff --check` passed. **Deferred**: PR #55 is waiting for CI; issue remains open until PR CI passes and the PR is merged. **Follow-up issues**: none currently. **Docs updated**: n/a; no operator-facing config or workflow changed.
Author
Owner

Done

What was done: Implemented Jellyfin MusicVideo library sync and merged PR #55. Jellyfin CollectionType=musicvideos libraries now project as LibraryMediaKind.MusicVideos, fetch Jellyfin MusicVideo items with includeItemTypes=MusicVideo, and route through a new Jellyfin MusicVideo scanner that imports into existing ErsatzTV MusicVideo entities.

Root cause: The Jellyfin sync path only recognized tvshows, movies, and boxsets, so musicvideos libraries were projected to None and dropped. The library sync handler also only routed Movies and Shows, so unsupported library kinds silently returned success without scanning.

Files changed: Jellyfin API client/interface/model; Jellyfin sync handler; new IJellyfinMusicVideoLibraryScanner; new JellyfinMusicVideoLibraryScanner; Scanner DI registration; focused NUnit tests for library projection and sync routing.

Verification: Local TDD red tests were observed before implementation. Local verification passed: TZ=UTC dotnet test ErsatzTV.Infrastructure.Tests/ErsatzTV.Infrastructure.Tests.csproj -v minimal (16 tests), TZ=UTC dotnet test ErsatzTV.Scanner.Tests/ErsatzTV.Scanner.Tests.csproj -v minimal (1467 tests), TZ=UTC dotnet test ErsatzTV.Architecture.Tests/ErsatzTV.Architecture.Tests.csproj -v minimal (5 tests), and git diff --check. PR CI passed: Build & test (.NET) succeeded in 3m53s; EF migration integrity succeeded in 5m4s; PR image push job skipped as expected.

Deferred: Plex/Emby MusicVideo parity was not changed; this issue scoped the Jellyfin path only.

Follow-up issues: none.

Docs updated: n/a; no operator-facing config, deployment, or workflow changed.

## Done **What was done**: Implemented Jellyfin MusicVideo library sync and merged PR #55. Jellyfin `CollectionType=musicvideos` libraries now project as `LibraryMediaKind.MusicVideos`, fetch Jellyfin `MusicVideo` items with `includeItemTypes=MusicVideo`, and route through a new Jellyfin MusicVideo scanner that imports into existing ErsatzTV `MusicVideo` entities. **Root cause**: The Jellyfin sync path only recognized `tvshows`, `movies`, and `boxsets`, so `musicvideos` libraries were projected to `None` and dropped. The library sync handler also only routed Movies and Shows, so unsupported library kinds silently returned success without scanning. **Files changed**: Jellyfin API client/interface/model; Jellyfin sync handler; new `IJellyfinMusicVideoLibraryScanner`; new `JellyfinMusicVideoLibraryScanner`; Scanner DI registration; focused NUnit tests for library projection and sync routing. **Verification**: Local TDD red tests were observed before implementation. Local verification passed: `TZ=UTC dotnet test ErsatzTV.Infrastructure.Tests/ErsatzTV.Infrastructure.Tests.csproj -v minimal` (16 tests), `TZ=UTC dotnet test ErsatzTV.Scanner.Tests/ErsatzTV.Scanner.Tests.csproj -v minimal` (1467 tests), `TZ=UTC dotnet test ErsatzTV.Architecture.Tests/ErsatzTV.Architecture.Tests.csproj -v minimal` (5 tests), and `git diff --check`. PR CI passed: Build & test (.NET) succeeded in 3m53s; EF migration integrity succeeded in 5m4s; PR image push job skipped as expected. **Deferred**: Plex/Emby MusicVideo parity was not changed; this issue scoped the Jellyfin path only. **Follow-up issues**: none. **Docs updated**: n/a; no operator-facing config, deployment, or workflow changed.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: timothy/ersatztv#42