# How it works A five-minute tour. Details: [ARCHITECTURE.md](ARCHITECTURE.md), wire format: [PROTOCOL.md](PROTOCOL.md). ## The pieces ``` your PC friend's PC +-------------------+ +-------------------+ | app (mpv inside) | | app (mpv inside) | +---------+---------+ +---------+---------+ | sync (WebSocket) | sync (WebSocket) v v +----------------------------------------+ | server (who is ready, where are we) | +----------------------------------------+ video bytes come from somewhere else: - a link (Jellyfin, any http/https URL): each app fetches it directly - a file on the host's disk: the server streams it (/m/... endpoint) ``` - **App**: the desktop window. It draws the video with mpv, shows who is here, and sends what you do (ready, seek, chat). - **Server**: keeps one shared clock and the list of people. It never sees video frames, only "position 123 s, playing". There is exactly one server and one watch session on it. - **Jellyfin** (or any web host): where a link's video lives. The server does not touch it today; each app downloads it itself. ## Ways to run - **Host from the app**: the app you click Host in also runs the server. Simplest. The server lives as long as that app. - **Dedicated server**: a separate server program on an always-on box. Planned, see [ROADMAP.md](ROADMAP.md). Friends join either way with the Join card on Home. ## One session, start to finish 1. **Connect.** The app opens a WebSocket to the server and says hello (version, password, name, avatar). Wrong password or version: refused with a reason. Otherwise the server answers with a welcome and the current state. 2. **Catch up.** The app opens the current video, jumps to where the server says we are, and buffers. A new arrival is not ready yet and never holds anyone back. 3. **Ready gate.** Press Space to say you are ready. The server starts playback only when everyone who is ready has at least 4 seconds buffered. If two or more people are ready, one person alone cannot start it for the others. A lone viewer can play alone. 4. **Play.** The server owns the clock. Each app compares its mpv position to the clock: a small lead slows mpv a little (0.95x), a big gap (over 5 s) jumps. If someone's buffer runs dry the server pauses everyone and resumes when they have caught up. 5. **Seek.** Anyone can seek, anytime. The server moves the clock and everybody follows. Seeking does not change anyone's ready flag. 6. **Swap.** Anyone can change the video by pasting another link. Everybody stops at 0, ready flags clear, and the gate runs again. 7. **Leave.** Closing or leaving drops you from the server; the others keep going. If you vanish without saying goodbye, you are marked stale after 15 s (stops blocking) and removed after 30 s. The app reconnects by itself and restores your ready flag. There are no roles: anyone can seek, swap, force-ready others and kick anyone except the host. ## Where video comes from - **Link**: you paste an http(s) URL. Every app plays it directly with mpv. Works for a Jellyfin direct-download link or any file on the web. - **Local file (host only)**: you pick a file on your disk. The server streams it to everyone, host included, over HTTP with range requests, each with a per-person token. Nothing is stored or converted. - No transcoding, ever. Quality is whatever the file is.