A high-performance Jellyfin cast receiver that controls an external MPV player.
Built with Tauri v2, Solid.js, and Rust.
Features β’ Roadmap β’ Quick Start β’ Architecture β’ Troubleshooting
JMSR allows you to cast media from any Jellyfin client (web, mobile, TV) to your desktop, where it plays in MPV with full support for your custom configurations, shaders, and scripts.
π‘ Key Philosophy
JMSR does NOT embed
libmpv. Instead, it spawns and controls a standalone MPV process via JSON IPC. This preserves your existingmpv.conf, shader packs (Anime4K, FSR, etc.), and all local customizations without compromise.
| Feature | Description |
|---|---|
| πΊ Cast Target | Appears as a controllable device in Jellyfin's cast menu |
| π External MPV | Full compatibility with your system MPV configuration and shaders |
| π Persistent Auth | Login once, stay connected with secure token storage |
| π Quick Connect | Authenticate with Jellyfin by approving a one-time code on another device |
| π Auto-Reconnect | Resilient WebSocket connection with exponential backoff strategy |
| βοΈ Smart Playback | Automatically plays the next episode when the current one finishes |
| βοΈ Intro Skipper | Automatically skips Intro Skipper plugin introduction and credit ranges |
| π§ Series Memory | Remembers audio/subtitle language preferences per TV series |
| β¨οΈ Shortcuts | Use Shift+N / Shift+P directly in MPV to skip episodes |
| π₯οΈ System Tray | Runs quietly in the background with quick access controls |
| π‘οΈ Type-Safe | 100% type-safe Rust-to-TypeScript communication via tauri-specta |
| π Cross-Platform | Native support for Windows, macOS, and Linux |
- Quick Connect - Login via code from another device
- Intro Skipper Integration - Auto-skip intros/credits
- Full-Featured Client UI - Browse libraries, manage media, and control playback like other Jellyfin clients
- Embedded Player - Optional built-in video player without external MPV dependency
- MPRIS Support - Linux media player integration for desktop controls
- Discord Rich Presence - Show current playback status on Discord profile
- Custom Shaders Manager - Easy toggle for Anime4K, FSR, and other MPV shaders
- SyncPlay Support - Watch together with friends via Jellyfin SyncPlay group
- Picture-in-Picture (PiP) - Floating mini-player mode
- Global Hotkeys - Customizable shortcuts that work in the background
- Offline Mode - Download media for offline playback
- Added saved-session route gating and automatic reconnect through the authenticated session access path.
- Added mute-state visibility to the Now Playing controls.
- Improved Player Bridge command handling, playback control sharing, and Jellyfin websocket ownership for more reliable external MPV control.
- Migrated login, diagnostics, settings, subtitle priorities, session dialog, and now playing controls to headless Ark UI Solid primitives while preserving JMSR Control Room styling and behavior.
- Added Arch Linux
.pkg.tar.zstrelease packaging.
- Added Intro Skipper plugin support for automatic introduction and credit skips.
- Added a global Automation toggle to enable or disable Intro Skipper behavior.
- Added once-per-session skip semantics so manual seeks back into skipped ranges are respected.
- Added verification coverage for plugin failures, malformed ranges, disabled behavior, progress reporting, and existing track controls.
JMSR utilizes a robust three-actor architecture to ensure stability and separation of concerns.
graph LR
subgraph JMSR[JMSR Desktop App]
A[<b>Sentinel</b><br>Tauri GUI]
B[<b>Bridge</b><br>Rust Backend]
A <--> B
end
B <-->|JSON IPC| C[<b>Player</b><br>External MPV]
B <-->|WebSocket + REST| D[<b>Jellyfin Server</b>]
style A fill:#00a4dc,stroke:#333,color:white
style B fill:#dea584,stroke:#333,color:black
style C fill:#4c3c69,stroke:#333,color:white
style D fill:#aa5cc3,stroke:#333,color:white
- Sentinel (Tauri GUI): Handles UI, WebSocket connection to Jellyfin, and state management.
- Bridge (Rust IPC): Translates commands and manages the external process.
- Player (MPV): The standalone media player instance running your config.
- MPV installed and in PATH
Download the latest release for your platform from the Releases page:
| Platform | Download |
|---|---|
| Windows | .msi (installer) or .exe (NSIS) |
| macOS | .dmg |
| Linux | .deb, .AppImage, or Arch Linux .pkg.tar.zst |
Install the Arch Linux package from a release asset with:
sudo pacman -U jmsr-<version>-1-x86_64.pkg.tar.zstDevelopment prerequisites
# Clone the repository
git clone https://github.com/hewel/jmsr.git
cd jmsr
# Install dependencies
bun install
# Build production binaries
bunx tauri buildBinaries will be in src-tauri/target/release/bundle/.
- Launch JMSR from your application menu or terminal.
- Authenticate with Quick Connect or by entering your Jellyfin server URL and credentials.
- Cast Media: JMSR will appear as "JMSR" in your Jellyfin client's cast menu.
- Optional Intro Skipper: Install the Jellyfin Intro Skipper plugin and keep Operations Console > Automation > Automatic Intro Skip enabled to skip detected intros and credits.
- Enjoy: Media plays in MPV on your desktop with full control syncing.
- Authentication: User logs into Jellyfin and receives an access token.
- Registration: JMSR posts capabilities to
/Sessions/Capabilities/Full. - WebSocket: Connects to Jellyfin for real-time play state control.
- Cast Event: When user casts, Jellyfin sends a
Playcommand. - MPV Control: JMSR spawns MPV (if needed) and sends JSON IPC commands.
- Progress: Event-driven progress reporting via MPV property observation.
- Sync: Pause/seek/volume commands flow bidirectionally (Jellyfin β MPV).
- Auto-Play: Automatically fetches the next episode upon natural file end.
jmsr/
βββ src/ # Solid.js frontend
β βββ index.tsx # Entry point
β βββ bindings.ts # Auto-generated IPC bindings
β βββ components/ # UI components
βββ src-tauri/ # Rust backend
β βββ src/
β β βββ jellyfin/ # Jellyfin client implementation
β β βββ mpv/ # MPV IPC driver logic
β βββ tauri.conf.json # Tauri configuration
βββ docs/PRD.md # Product requirements| Task | Command |
|---|---|
| Frontend Dev | bun run dev |
| Tauri Dev | bunx tauri dev |
| Build Prod | bunx tauri build |
| Test | bun run test |
| Lint/Format | bun run check |
- TypeScript: Single quotes, Biome formatting.
- Rust: 2-space indent (standard
rustfmt.toml). - IPC: Always use typed
commands.*from bindings, never rawinvoke(). - Solid.js: Use
createSignal,createResourceβ NOT React hooks.
- Add function in
src-tauri/src/command.rswith#[tauri::command]and#[specta]. - Register in
src-tauri/src/lib.rsinsidecollect_commands![]. - Regenerate bindings by running
bunx tauri dev. - Import from
commandsin your TypeScript file.
| Component | Technology |
|---|---|
| Framework | Tauri v2 |
| Frontend | Solid.js + TypeScript |
| Backend | Rust |
| Bundler | Rsbuild |
| Styling | TailwindCSS |
| IPC | tauri-specta |
| Linting | Biome |
| Testing | Rstest |
JMSR doesn't appear as cast target
- Ensure you're logged in (check Operations Console shows "Connected").
- Refresh the Jellyfin web page after JMSR connects.
- Check Jellyfin Dashboard > Activity for the JMSR session.
MPV doesn't start
- Verify MPV is installed:
mpv --version. - Check MPV is in PATH (or set explicit path in Operations Console settings).
- Windows (Scoop): JMSR auto-resolves symlinks, but ensure the shim is valid.
- Check Operations Console > Player Bridge settings for detected path.
Video doesn't play
- Check Jellyfin transcoding settings.
- Verify network connectivity to Jellyfin server.
- Check Diagnostics in the Operations Console for error messages.
Connection lost
- JMSR auto-reconnects with exponential backoff (1s β 60s).
- Check network connectivity.
- Toast notifications will indicate connection status.
Contributions are welcome! Please follow these steps:
- Fork the repository.
- Create a feature branch.
- Follow existing code conventions (Biome for TS, rustfmt for Rust).
- Run
bun run checkbefore committing. - Submit a pull request.
MIT License - see LICENSE for details.
- jellyfin-mpv-shim - The original Python inspiration.
- Tauri - For the amazing desktop framework.
- MPV - The best media player in existence.