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

4.2 KiB

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

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.

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

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

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

  • Design doc + scaffold
  • Build against the real SDK, fix whatever the TODO(verify) spots got wrong
  • Install on a real Emby Server (Docker)
  • Integrate into Emby's own UI instead of a standalone web app (EnableInUserMenu — see docs/architecture.md)
  • 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.