OrchardDocs

Listening Parties

Peer-to-peer synchronized playback with host-controlled queues, backed by a signaling worker that never proxies audio.

A listening party is synchronized playback across several people, each running their own copy of Orchard.

How it works

Parties are peer-to-peer. Orchard’s listening-party Cloudflare Worker handles room coordination and WebRTC signaling only; it never proxies or streams audio. Every participant plays the audio locally from their own YouTube Music session.

That has two consequences worth knowing:

  • Everyone needs their own working Orchard playback. The host is not streaming to anyone.
  • Nothing about the audio passes through Orchard’s infrastructure.

Roles

The host controls playback and the queue. Host actions broadcast to everyone.

Guests follow along and can send requests to the host to play, pause, seek, or queue something. The host decides whether to act on them.

The host can transfer host status to another participant, and can close the room.

Starting and joining

Start a party from the player. Orchard creates a room and gives you an invite to share. Joining uses that invite. Room metadata is public to anyone holding the room id, and each participant gets a token scoped to that room.

Protocol

The worker exposes:

EndpointPurpose
GET /healthLiveness
POST /roomsCreate a room, returns a host participant token
GET /rooms/:roomIdPublic room metadata
POST /rooms/:roomId/joinCreate a guest participant token
GET /rooms/:roomId/socketUpgrade to the room WebSocket

Over the socket, clients send signal to relay WebRTC offer, answer, and ICE payloads; the host sends party:update to broadcast synced playback state, party:host-transfer, and party:close; guests send party:request; and party:ping keeps connections alive.

Rooms are backed by a Durable Object, which is what makes a single authoritative room state possible at the edge.

Sync accuracy

Sync is state-based rather than stream-based: the host broadcasts what it is playing and where it is, and each client seeks to match. Small drift between participants is normal, particularly across very different network conditions. Skips and seeks resynchronize everyone.

Limitations

  • All participants need access to the track. Regional availability differs by account, so a track playable for the host may not be playable for a guest.
  • A guest without a signed-in session may be unable to play age-restricted content the host can play.
  • Closing the host’s Orchard ends the room unless the host has transferred the role first.
  • Orchard Connect is for your own devices on a LAN, which is a different problem from a party across the internet.
  • Cloudflare Workers covers deploying your own signaling worker.

Source map

PathRole
src/app/social/listeningPartyActions.jsParty lifecycle in the renderer
src/app/social/listeningPartyClient.jsSocket and WebRTC client
workers/listening-party/Room coordination and signaling worker