watchparty/README.md
Nicolas 6f22f72532 Integrate Watch Party into Emby's own UI instead of a standalone app
Per user feedback: no separate control panel, no chat. Found that
PluginPageInfo has EnableInUserMenu/EnableInMainMenu (confirmed via
reflection on the real MediaBrowser.Model assembly, plus an Emby
community thread showing another plugin using EnableInUserMenu=true)
- a real, if barely documented, way to surface a plugin page to
regular users, not just admins, through the exact same
IHasWebPages/GetPages() mechanism as the admin settings page.

- Plugin.cs now registers a second page (partyPage.html) with
  EnableInUserMenu=true + EnableInMainMenu=true
- partyPage.html replaces the old standalone control panel: no login
  form, it runs inside the already-authenticated Emby web client and
  calls the REST API via the global ApiClient
- Removed web/control-panel/ (the standalone app, its own login flow,
  and the custom GET /WatchParty/app* static file routes in
  WatchPartyService.cs) - no longer needed
- docs/architecture.md and README.md updated: the new mechanism, and
  the honest limitation that comes with it (reaches Web/Electron
  clients, not official mobile/TV apps - those allowlist plugin pages
  client-side)

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-13 19:44:31 +02:00

98 lines
4.2 KiB
Markdown

# Watch Party for Emby
An Emby Server plugin that lets a group of users on the same server watch the
same title together. Nobody switches players: everyone keeps using their
normal Emby app (web, mobile, TV, whatever), and the plugin nudges playback
back in sync using the same remote-control commands Emby already uses for
casting / "play on another device".
See [docs/architecture.md](docs/architecture.md) for the full design,
including which parts are solidly confirmed against Emby's SDK docs and which
still need verification against your exact server build.
## How it's meant to work
1. You start playing a title in your normal Emby app.
2. In Emby's web client (or the Electron desktop app), open **Watch Party**
from the menu and start a party. You get a 6-character join code. No
separate login — it's a real page inside Emby, using your existing session.
3. Friends open the same **Watch Party** menu item, start playing the *same*
title in their own Emby app, and enter the code to join.
4. The server treats one member (the host, by default) as the reference
position, and periodically nudges everyone else's session back in sync
(seek correction, and mirroring pause/unpause) — see
[docs/architecture.md](docs/architecture.md#sync-algorithm).
The Watch Party page is a companion panel, not a video player — it never
touches the actual video stream, playback stays in your normal Emby app.
**Known limitation**: the menu item shows up on Web and Electron clients.
Official mobile/TV apps don't surface arbitrary plugin pages, so Watch Party
won't appear there — see [docs/architecture.md](docs/architecture.md#components).
## Status
Builds clean (0 errors, 0 warnings) against the real `MediaBrowser.Server.Core`
/ `MediaBrowser.Common` 4.9.1.90 assemblies from NuGet, and is installed on a
real Emby Server (Docker) — the plugin loads and its admin page shows up.
The actual feature (`partyPage.html`, reached via `EnableInUserMenu`) hasn't
been exercised live yet. See
[docs/architecture.md](docs/architecture.md#assumptions-to-verify) for
exactly what was wrong on the first guess, what was fixed, and what's still
open.
## Requirements
- Emby Server (developed against 4.9.5.0; should work on nearby 4.9.x/4.8.x
builds, but the plugin ABI does shift between versions)
- [.NET SDK](https://dotnet.microsoft.com/download) 8.0 to build (installed
per-user under `%USERPROFILE%\.dotnet` in this environment, since the
machine-wide winget install needed admin elevation that wasn't available —
see git history if you need to redo this on another machine)
## Project layout
```
src/WatchParty/ the plugin itself (C#, netstandard2.0)
Plugin.cs plugin registration + both plugin pages
Configuration/ plugin settings, the admin settings page, and
partyPage.html - the actual user-facing feature,
integrated into Emby's own menu (not a separate app)
Parties/ Party / PartyMember model + in-memory PartyManager
Sync/ the drift-correction background loop
Api/ REST endpoints, called from partyPage.html
docs/architecture.md full design doc
```
## Building
```bash
dotnet build src/WatchParty/WatchParty.csproj
```
To have a build drop the DLL straight into a local Emby Server's plugin
folder, set `EMBY_PLUGINS_DIR` before building, e.g.:
```bash
EMBY_PLUGINS_DIR="C:/ProgramData/Emby-Server/programdata/plugins" dotnet build src/WatchParty/WatchParty.csproj
```
Adjust the path for however your server is installed (Windows service vs.
portable install vs. Docker volume).
## Roadmap
- [x] Design doc + scaffold
- [x] Build against the real SDK, fix whatever the `TODO(verify)` spots got wrong
- [x] Install on a real Emby Server (Docker)
- [x] Integrate into Emby's own UI instead of a standalone web app
(`EnableInUserMenu` — see [docs/architecture.md](docs/architecture.md#components))
- [ ] Try a full party end-to-end with two accounts
- [ ] Live (WebSocket) updates in the party page instead of polling
- [ ] Per-party override of sync settings instead of only server-wide defaults
No chat/reactions — deliberately out of scope, not just deferred.
## License
MIT — see [LICENSE](LICENSE).