Emby Server plugin: watch party feature (session sync via Emby's remote-control commands) + companion web control panel
Find a file
Nicolas d4a365ae5c Drop EnableInMainMenu=true - broke Emby's modern ViewManager
Real error from the field: navigating to the party page threw inside
Emby's own viewmanager.js (v4.10.0.40): TypeError, cannot read
properties of undefined (reading lifeCycleAbortSignal), at
getResumeOptions/dispatchViewBeforeShow. EnableInMainMenu=true was
never confirmed by any real example (only EnableInUserMenu=true was,
via the forum thread cited in Plugin.cs) - it very likely routes the
page through the newer ViewManager meant for full content views
(Home, Movies, ...), which expects a lifecycle contract this static
embedded-resource page doesn't provide. Reverting to exactly the
confirmed-working combination.

The raw page itself was confirmed served correctly beforehand (200,
correct content, via GET /web/configurationpage?name=WatchPartyRoom)
so the plugin/registration side was never the problem - just this one
flag.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-13 20:01:45 +02:00
.github/workflows Scaffold Emby Watch Party plugin 2026-09-13 14:02:43 +02:00
docs Integrate Watch Party into Emby's own UI instead of a standalone app 2026-09-13 19:44:31 +02:00
src/WatchParty Drop EnableInMainMenu=true - broke Emby's modern ViewManager 2026-09-13 20:01:45 +02:00
.gitignore Scaffold Emby Watch Party plugin 2026-09-13 14:02:43 +02:00
LICENSE Scaffold Emby Watch Party plugin 2026-09-13 14:02:43 +02:00
README.md Integrate Watch Party into Emby's own UI instead of a standalone app 2026-09-13 19:44:31 +02:00

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.