Files
SubMiner/docs-site/jellyfin-integration.md
T
sudacode c02edc90cc docs: audit and refresh user-facing and internal docs
Cross-check every config key, shortcut, default, and command against the
current source and fix the drift (mpv.socketPath, auto_start_overlay
default, AniSkip TAB key, JLPT N4 color, secondary-sub font/defaults,
secondary-sub language behavior, modular mpv plugin layout, and more).
Add plain-language intros and first-use definitions across onboarding and
integration pages so non-technical readers can follow along.

Internal docs/: fix stale module paths in architecture/domains.md, add
missing contract entry points and catalog rows, and bump verified dates.
Remove the obsolete docs/plans/ directory (its only plan shipped in
0.15.0) and reframe planning.md so plans live with the work, not in docs/.
2026-05-23 21:21:16 -07:00

7.6 KiB

Jellyfin Integration

Jellyfin is a free, self-hosted media server — think of it as your own private streaming service for video you own. If you keep your anime on a Jellyfin server, SubMiner can log in, browse it, and play episodes through mpv with the full mining overlay.

::: tip Who needs this? This page is only relevant if you already run (or have access to) a Jellyfin server. If you watch local files or YouTube, you can skip it. Most of this integration is driven from the command line, so it is aimed at slightly more advanced users; the in-app setup window (subminer jellyfin) is the easiest starting point. :::

SubMiner includes an optional Jellyfin CLI integration for:

  • authenticating against a server
  • listing libraries and media items
  • launching item playback in the connected mpv instance
  • receiving Jellyfin remote cast-to-device playback events in-app
  • opening an in-app setup window for server URL and authentication
  • toggling Jellyfin cast discovery from the tray once configured

Requirements

  • Jellyfin server URL and user credentials
  • For --jellyfin-play: connected mpv IPC socket (--start or existing mpv plugin workflow)
  • On Linux, token encryption defaults to gnome-libsecret; pass --password-store=<backend> to override.

Setup

  1. Set base config values (config.jsonc):
{
  "jellyfin": {
    "enabled": true,
    "serverUrl": "http://127.0.0.1:8096",
    "recentServers": ["http://127.0.0.1:8096"],
    "username": "your-user",
    "remoteControlEnabled": true,
    "remoteControlAutoConnect": true,
    "autoAnnounce": false,
    "remoteControlDeviceName": "SubMiner",
    "defaultLibraryId": "",
    "pullPictures": false,
    "iconCacheDir": "/tmp/subminer-jellyfin-icons",
    "directPlayPreferred": true,
    "directPlayContainers": ["mkv", "mp4", "webm", "mov", "flac", "mp3", "aac"],
    "transcodeVideoCodec": "h264",
  },
}
  1. Authenticate:
subminer jellyfin
subminer jellyfin -l \
  --server http://127.0.0.1:8096 \
  --username your-user \
  --password 'your-password'

subminer jellyfin opens the setup window. It pre-fills the server URL from the configured server, a recent successful server, or the local default. Successful login keeps the window open, stores the Jellyfin session token in encrypted storage, updates the configured server/username/client metadata, and refreshes recent servers. Passwords are never stored.

  1. List libraries:
SubMiner.AppImage --jellyfin-libraries

Launcher wrapper equivalent for interactive playback flow:

subminer jellyfin -p

Launcher wrapper for Jellyfin cast discovery mode (background app + tray):

subminer jellyfin -d

After Jellyfin is enabled with a server URL and SubMiner is already running, the tray menu shows Jellyfin Discovery. Use that checkbox to start or stop discovery for the current runtime session without changing config. If the stored login session is missing or expired, starting discovery shows a warning and setup remains the path to refresh credentials. It does not survive app restart.

Stop discovery session/app:

subminer app --stop

subminer jf ... is an alias for subminer jellyfin ....

To clear saved session credentials:

subminer jellyfin --logout
  1. List items in a library:
SubMiner.AppImage --jellyfin-items --jellyfin-library-id LIBRARY_ID --jellyfin-search term

Optional listing controls:

  • --jellyfin-recursive=true|false (default: true)
  • --jellyfin-include-item-types=Series,Season,Folder,CollectionFolder,Movie,...

These are used by the launcher picker flow to:

  • keep root search focused on shows/folders/movies (exclude episode rows)
  • browse selected anime/show directories as folder-or-file lists
  • recurse for playable files only after selecting a folder
  1. Start playback:
SubMiner.AppImage --start
SubMiner.AppImage --jellyfin-play --jellyfin-item-id ITEM_ID

Optional stream overrides:

  • --jellyfin-audio-stream-index N
  • --jellyfin-subtitle-stream-index N

Playback Behavior

  • Direct play is attempted first when:
    • jellyfin.directPlayPreferred=true
    • media source supports direct stream
    • source container matches jellyfin.directPlayContainers
  • If direct play is not selected/available, SubMiner requests a Jellyfin transcoded stream (master.m3u8) using jellyfin.transcodeVideoCodec.
  • Resume position (PlaybackPositionTicks) is applied via mpv seek.
  • Media title is set in mpv as [Jellyfin/<mode>] <title>.

Cast To Device Mode (jellyfin-mpv-shim style)

When SubMiner is running with a valid Jellyfin session, it can appear as a remote playback target in Jellyfin's cast-to-device menu.

Requirements

  • jellyfin.enabled=true
  • valid jellyfin.serverUrl and Jellyfin auth session (env override or stored login session)
  • jellyfin.remoteControlEnabled=true (default)
  • jellyfin.remoteControlAutoConnect=true (default) for startup auto-connect
  • jellyfin.autoAnnounce=false by default (true enables auto announce/visibility check logs on connect)

Behavior

  • SubMiner connects to Jellyfin remote websocket and posts playback capabilities.
  • Startup auto-connect still requires remoteControlAutoConnect=true; the tray Jellyfin Discovery checkbox can start discovery later even when startup auto-connect is disabled.
  • Play events open media in mpv with the same defaults used by --jellyfin-play.
  • If mpv IPC is not connected at cast time, SubMiner auto-launches mpv in idle mode with SubMiner defaults and retries playback.
  • Playstate events map to mpv pause/resume/seek/stop controls.
  • Stream selection commands (SetAudioStreamIndex, SetSubtitleStreamIndex) are mapped to mpv track selection.
  • SubMiner reports start/progress/stop timeline updates back to Jellyfin so now-playing and resume state stay synchronized.
  • --jellyfin-remote-announce forces an immediate capability re-broadcast and logs whether server sessions can see the device.

Troubleshooting

  • Device not visible in Jellyfin cast menu:
    • ensure SubMiner is running
    • ensure session token is valid (--jellyfin-login again if needed)
    • ensure remoteControlEnabled is true
    • use tray Jellyfin Discovery or subminer jellyfin -d to start discovery
  • Cast command received but playback does not start:
    • verify mpv IPC can connect (--start flow)
    • verify item is playable from normal --jellyfin-play --jellyfin-item-id ...
  • Frequent reconnects:
    • check Jellyfin server/network stability and token expiration

Failure Handling

User-visible errors are shown through CLI logs and mpv OSD for:

  • invalid credentials
  • expired/invalid token
  • server/network errors
  • missing library/item identifiers
  • no playable source
  • mpv not connected for playback

Security Notes and Limitations

  • Jellyfin auth session (accessToken + userId) is stored in local encrypted token storage after login/setup.
  • Launcher wrappers support --password-store=<backend> and forward it through to the app process.
  • Optional environment overrides are supported: SUBMINER_JELLYFIN_ACCESS_TOKEN and SUBMINER_JELLYFIN_USER_ID.
  • Treat both token storage and config files as secrets and avoid committing them.
  • Password is used only for login and is not stored.
  • Optional setup UI is available via --jellyfin; all actions are also available via CLI flags.
  • subminer wrapper uses Jellyfin subcommands (subminer jellyfin ..., alias subminer jf ...). Use SubMiner.AppImage for direct --jellyfin-libraries and --jellyfin-items.
  • For direct app CLI usage (SubMiner.AppImage ...), --jellyfin-server can override server URL for login/play flows without editing config.