# tsplay A terminal Jellyfin client for Arch / Omarchy. Browse your server's libraries in the terminal; the selected title plays in an **mpv window** (hardware accelerated) while the TUI acts as the remote — pause, seek, and a live progress bar, with resume points reported back to the server. It's the watch-side companion to [TUISTREAM](https://github.com/28allday/TUISTREAM) (which sets up and manages the Jellyfin *server*). tsplay only *plays*. > **New here?** The [User Guide](USER_GUIDE.md) is a plain-English, step-by-step > walkthrough of installing, signing in, and watching. This README is the > technical overview. ## How it works - **BubbleTea** drives the login form and a stack-based library browser. - **mpv** does the actual playback. tsplay spawns it with `--input-ipc-server` and talks to it over a JSON IPC socket: it sends pause/seek/quit and observes `time-pos`/`duration`/`pause`/`eof-reached`, so the terminal can render a progress bar and report progress to Jellyfin. - Media is **direct-played** (`/Videos/{id}/stream?static=true`) — mpv handles almost every container/codec natively, so the server doesn't transcode. - Colours follow the active **Omarchy** theme, falling back to ANSI palette indices over SSH / on non-Omarchy boxes. ## Requirements - **mpv** — the only run-time dependency - **Go ≥ 1.26** — build-time only (compiled into the binary) On Arch / Omarchy the installer fetches both for you via `pacman` if they're missing, so you don't normally need to install anything by hand. ### GPU drivers (hardware-accelerated playback) mpv leans on your GPU's video-decode drivers (VA-API on Intel/AMD, NVDEC on NVIDIA) for smooth, low-CPU playback. A normal Omarchy desktop already has these, so there's nothing to do. On a **fresh, minimal** Arch box you'd want the matching stack, e.g.: - Intel: `intel-media-driver` (or `libva-intel-driver` for older iGPUs) - AMD: `libva-mesa-driver` `mesa` - NVIDIA: `nvidia-utils` (provides NVDEC) The installer deliberately does **not** touch graphics drivers — that's a system-level choice, not tsplay's to make. Without them mpv still plays, just with software decoding (higher CPU use). ## Install One line, nothing to clone: ```sh curl -fsSL https://raw.githubusercontent.com/28allday/tsplay/main/install.sh | bash ``` This installs `mpv` if it's missing (Arch), downloads the right binary for your architecture into `~/.local/bin`, then you just run `tsplay`. Pin a version with `TSPLAY_VERSION=v1.0.0`, or change the prefix with `PREFIX=/opt`. From a clone it builds from source instead (if Go is present), otherwise it falls back to downloading the released binary: ```sh git clone https://github.com/28allday/tsplay.git cd tsplay && ./install.sh ``` On an **Omarchy desktop** the installer also adds a Walker entry (with icon) that launches tsplay as a floating terminal window — search **`tsplay`** in Walker — using the stock `TUI.float` app-id, so no Hyprland config is needed. On headless boxes this step is skipped and tsplay stays a plain shell TUI. ## Usage First run shows a login form. tsplay **auto-detects Jellyfin servers on your LAN** (Jellyfin's UDP discovery on port 7359) and pre-fills the server URL, so you usually only type your username and password. Credentials and a stable device id are saved to `~/.config/tsplay/config.json` (mode 0600), so subsequent runs go straight to the library. > Discovery probes both broadcast **and** a unicast sweep of your subnet, > because many home networks (especially WiFi) silently drop broadcast packets. **Switching servers.** Once signed in, tsplay locks onto that server and goes straight to the library on every later run — it won't ask again. If you move to a different Jellyfin box, press **`s`** in the browser to drop back to discovery, pick the new server, and sign in; the new one is then saved and locked in. If a saved server has gone away (e.g. you rebuilt it elsewhere), tsplay notices the failed connection on startup and falls back to discovery automatically so you're never stuck pointing at a dead server. ### Login | Key | Action | |-----------|------------------------------------------| | `tab` | move between fields | | `ctrl+n` | next discovered server (if more than one)| | `ctrl+r` | rescan the network | | `enter` | sign in | | `esc` | cancel — back to the library, or quit if not yet signed in | ### Browse | Key | Action | |--------------------|---------------------------------| | `↑`/`↓` `j`/`k` | move | | `enter` / `l` / `→`| open folder · play item | | `esc` / `←` / `h` | back | | `c` | jump to Continue Watching | | `s` | switch server (back to discovery)| | `/` | filter the current list | | `q` | quit | ### Playing | Key | Action | |----------------|-------------------| | `space` / `k` | play / pause | | `←` / `→` | seek ∓10s | | `shift`+`←`/`→`| seek ∓60s | | `n` / `p` | next / previous track (music) | | `↑` / `↓` | volume ±5 | | `m` | mute / unmute | | `q` / `esc` | stop, back to list| ## Features - **LAN auto-discovery** of Jellyfin servers, with one-key **server switching** and automatic fallback if a saved server goes away. - Browse **movies, shows** (season/episode drill-down) **and music**, with a compact one-line list (media-type icon, title, and a right-aligned year · duration · watched column) and `/` to filter. - **Direct-play** to mpv (no server-side transcoding), **resume from your last position**, and progress/stop reporting so **Continue Watching** stays in sync across all your devices. - **Audio auto-advance** — music plays through the album/folder and returns to the browser when it's done — with volume remembered across tracks and runs. - Colours follow the active **Omarchy** theme, with an ANSI fallback over SSH. ## Notes - Self-signed TLS isn't trusted by default — use a proper cert (your Jellyfin is usually behind Caddy anyway) or a plain `http://…:8096` URL on the LAN.