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> |
||
|---|---|---|
| .github/workflows | ||
| docs | ||
| src/WatchParty | ||
| .gitignore | ||
| LICENSE | ||
| README.md | ||
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
- You start playing a title in your normal Emby app.
- 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.
- Friends open the same Watch Party menu item, start playing the same title in their own Emby app, and enter the code to join.
- 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%\.dotnetin 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.