Skip to content

hewel/jellypilot

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

302 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

JellyPilot

CI Rust Tauri Solid.js License: MIT

A high-performance Jellyfin and Emby desktop client that controls an external MPV player.

Built with Tauri v2, Solid.js, and Rust.

Features β€’ Roadmap β€’ Quick Start β€’ Architecture β€’ Troubleshooting


πŸ“– Overview

JellyPilot lets you sign in to Jellyfin or Emby, browse your video libraries, and play media in MPV with full support for your custom configurations, shaders, and scripts. For Jellyfin, JellyPilot can also register as a cast target for playback from other Jellyfin clients.

πŸ’‘ Key Philosophy

JellyPilot does NOT embed libmpv. Instead, it spawns and controls a standalone MPV process via JSON IPC. This preserves your existing mpv.conf, shader packs (Anime4K, FSR, etc.), and all local customizations without compromise.

✨ Features

Feature Description
🎞️ Jellyfin + Emby Connect to Jellyfin or Emby servers with saved service profiles
πŸ“š Library Browser Browse Movies and Shows, open item details, and start playback from the desktop app
πŸ“Ί Jellyfin Cast Target Appears as a controllable device in Jellyfin's cast menu
πŸš€ External MPV Full compatibility with your system MPV configuration and shaders
πŸ›‘οΈ Type-Safe 100% type-safe Rust-to-TypeScript communication via tauri-specta
πŸ”’ Persistent Auth Login once, stay connected with secure token storage
πŸ”‘ Jellyfin 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
βœ‚οΈ Jellyfin Intro Skipper Automatically skips Intro Skipper plugin introduction and credit ranges
🧠 Series Memory Remembers audio/subtitle language preferences per TV series
⌨️ Shortcuts Use configurable MPV shortcuts (Shift+> / Shift+< by default) to skip episodes
πŸ–₯️ System Tray Runs quietly in the background with quick access controls
🍏 Cross-Platform Native support for Windows, macOS, and Linux

🧩 Server Support

Server Supported Notes
Jellyfin βœ… Password login, Quick Connect, saved profiles, library browsing, MPV playback, cast target registration, remote control, and Intro Skipper plugin support
Emby βœ… Password login, saved profiles, library browsing, MPV playback, remote control, and playback progress reporting

Emby support uses the same library and player workflow as Jellyfin where the server APIs are compatible. Jellyfin-specific features such as Quick Connect and the Jellyfin Intro Skipper plugin are not advertised for Emby connections.

πŸ—ΊοΈ Roadmap

  • 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 media server clients
  • Embedded Player - Optional built-in video player without external MPV dependency
  • MPRIS Support - Linux media player integration for desktop controls

πŸ“¦ Release Notes

v1.4.0

  • 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.

v1.3.2

  • Migrated login, diagnostics, settings, subtitle priorities, session dialog, and now playing controls to headless Ark UI Solid primitives while preserving JellyPilot Control Room styling and behavior.

v1.3.1

  • Added Arch Linux .pkg.tar.zst release packaging.

v1.3.0

  • 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.

πŸ—οΈ Architecture

JellyPilot utilizes a robust three-actor architecture to ensure stability and separation of concerns.

graph LR
    subgraph JellyPilot[JellyPilot 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 / Emby 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
Loading
  1. Sentinel (Tauri GUI): Handles UI, server connection, and state management.
  2. Bridge (Rust IPC): Translates commands and manages the external process.
  3. Player (MPV): The standalone media player instance running your config.

πŸš€ Quick Start

Prerequisites

  • MPV installed and in PATH

Installation

Download Pre-built Binaries (Recommended)

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 jellypilot-<version>-1-x86_64.pkg.tar.zst

Build from Source

Development prerequisites
  • Bun (or npm/yarn)
  • Rust (latest stable)
  • Tauri CLI: bun add -g @tauri-apps/cli
# Clone the repository
git clone https://github.com/hewel/jellypilot.git
cd jellypilot

# Install dependencies
bun install

# Build production binaries
bunx tauri build

Binaries will be in src-tauri/target/release/bundle/.

Usage Steps

  1. Launch JellyPilot from your application menu or terminal.
  2. Choose a server type: Select Jellyfin or Emby on the login screen.
  3. Authenticate with your server URL and credentials. Jellyfin also supports Quick Connect.
  4. Browse or Cast Media: Start playback from JellyPilot's Library view. Jellyfin users can also cast to "JellyPilot" from another Jellyfin client.
  5. Optional Jellyfin Intro Skipper: Install the Jellyfin Intro Skipper plugin and keep Operations Console > Automation > Automatic Intro Skip enabled to skip detected intros and credits.
  6. Enjoy: Media plays in MPV on your desktop with full control syncing.

πŸ› οΈ How It Works

  1. Authentication: User logs into Jellyfin or Emby and receives an access token.
  2. Registration: JellyPilot posts supported capabilities to the active media server.
  3. WebSocket: Connects to the server for real-time play state control when supported.
  4. Play Event: Playback can start from JellyPilot's Library Browser or from Jellyfin cast commands.
  5. MPV Control: JellyPilot spawns MPV (if needed) and sends JSON IPC commands.
  6. Progress: Event-driven progress reporting via MPV property observation.
  7. Sync: Pause/seek/volume commands flow bidirectionally between the server and MPV where supported.
  8. Auto-Play: Automatically fetches the next episode upon natural file end.

πŸ’» Development

Project Structure

jellypilot/
β”œβ”€β”€ src/                    # Solid.js frontend
β”‚   β”œβ”€β”€ index.tsx          # Entry point
β”‚   β”œβ”€β”€ bindings.ts        # Auto-generated IPC bindings
β”‚   └── components/        # UI components
β”œβ”€β”€ src-tauri/             # Rust backend
β”‚   β”œβ”€β”€ src/
β”‚   β”‚   β”œβ”€β”€ jellyfin/      # Jellyfin/Emby client implementation
β”‚   β”‚   └── mpv/           # MPV IPC driver logic
β”‚   └── tauri.conf.json    # Tauri configuration
└── docs/PRD.md            # Product requirements

Commands

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

πŸ“ Code Conventions

  • TypeScript: Single quotes, Oxfmt formatting.
  • Rust: 2-space indent (standard rustfmt.toml).
  • IPC: Always use typed commands.* from bindings, never raw invoke().
  • Solid.js: Use createSignal, createResource β€” NOT React hooks.

βž• Adding a Tauri Command

  1. Add function in src-tauri/src/command.rs with #[tauri::command] and #[specta].
  2. Register in src-tauri/src/lib.rs inside collect_commands![].
  3. Regenerate bindings by running bunx tauri dev.
  4. Import from commands in your TypeScript file.

Technology Stack

Component Technology
Framework Tauri v2
Frontend Solid.js + TypeScript
Backend Rust
Bundler Rsbuild
Styling TailwindCSS
IPC tauri-specta
Linting Oxlint
Testing Rstest

❓ Troubleshooting

JellyPilot doesn't appear as a Jellyfin cast target
  • Ensure you're logged in (check Operations Console shows "Connected").
  • Refresh the Jellyfin web page after JellyPilot connects.
  • Check Jellyfin Dashboard > Activity for the JellyPilot session.
  • Emby support is focused on in-app library playback and remote control, not Jellyfin-style cast discovery.
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): JellyPilot auto-resolves symlinks, but ensure the shim is valid.
  • Check Operations Console > Player Bridge settings for detected path.
Video doesn't play
  • Check your Jellyfin or Emby transcoding settings.
  • Verify network connectivity to your Jellyfin or Emby server.
  • Check Diagnostics in the Operations Console for error messages.
Connection lost
  • JellyPilot auto-reconnects with exponential backoff (1s β†’ 60s).
  • Check network connectivity.
  • Toast notifications will indicate connection status.

🀝 Contributing

Contributions are welcome! Please follow these steps:

  1. Fork the repository.
  2. Create a feature branch.
  3. Follow existing code conventions (Oxc for TS, rustfmt for Rust).
  4. Run bun run check before committing.
  5. Submit a pull request.

πŸ“„ License

MIT License - see LICENSE for details.

πŸ™ Acknowledgments

  • jellyfin-mpv-shim - The original Python inspiration.
  • Tauri - For the amazing desktop framework.
  • MPV - The best media player in existence.

About

A high-performance Jellyfin cast receiver that controls an external MPV player.

Topics

Resources

License

Stars

5 stars

Watchers

0 watching

Forks

Packages

 
 
 

Contributors

Languages