Skip to content

Realtime Resource Observation

Resource observation subscribes to room resources. Versioned resources can carry recovery cursors, while playback info always returns player-ready data for the current source. When a resource changes, the server can push a full payload or only notify the client to fetch.

ResourceObserveResource.resource fieldVersion sourceTypical use
Playback stateplaybackStateRoomPlaybackState.versionPlayer UI and synchronized playback status
PlaybackplaybackCurrent value on every observeCurrent playback URL, headers, proxy policy, subtitles, and expiry
Room settingsroomSettingsRoom settings versionChat, playback permissions, and UI controls
Playlist itemsplaylistItemsList snapshot versionRoot lists, child playlists, provider browsing, and search results
Room membersroomMembersMember list snapshot versionMember pagination, search, role filtering, and status filtering

Each observation is identified by observeId. It only needs to be unique within the current connection, length 1-128. Prefer stable names such as playback-state, playlist-root:p1:50, or members:online.

Each connection can hold up to 64 observations. Over-limit requests return ResourceObserveError and do not close the WebSocket.

ValueBehavior
0Same as PUSH_SNAPSHOT
2Push a full ResourceChanged.payload when changed; useful for low-latency UI
1Push only changedOnly; the client then fetches through HTTP/gRPC
  1. The client connects to the room WebSocket.
  2. The client sends ClientMessage.observeResource with observeId, deliveryMode, and the target resource. Resources that support recovery can also carry an event sequence.
  3. The server loads the current resource and sends ServerMessage.resourceObserved.
  4. If the server determines that the resource changed, it sends ServerMessage.resourceChanged for the same observeId.
  5. Later room events, cache invalidation, Provider credential changes, or playback expiry can trigger re-evaluation.

ResourceObserved fields:

FieldMeaning
observeIdThe submitted subscription ID
changedWhether the server should send the current resource to the client
eventCursorRecovery cursor for resources with event replay

ResourceChanged fields:

FieldMeaning
observeIdWhich subscription changed
payloadFull snapshot or changedOnly, depending on deliveryMode
eventCursorCursor associated with replayed resource events

When a view, list, or query is no longer needed, send ClientMessage.unobserveResource:

sendClientMessage({
unobserveResource: {
observeId: 'playlist-root',
},
});

There is no acknowledgement for unsubscribe. When the WebSocket disconnects, the server automatically clears all observations for that connection.

The examples below use TypeScript-style pseudocode. Exact field names depend on your protobuf code generator.

sendClientMessage({
observeResource: {
observeId: 'playback-state',
deliveryMode: 2,
playbackState: {
afterEventSequence: cached.playbackStateEventSequence,
},
},
});

When changed, the server returns ResourceChanged.payload.playbackState.

Event typeRefreshed resources
Playback state changedplaybackState, playback
Current playback media or playlist-related media updatedplayback, and sometimes playlistItems
Playlist created, updated, deleted, reordered, or media added/removedplaylistItems
Room settings changedroomSettings, roomMembers
User joined, left, or permissions changedroomMembers
Cache invalidation hits the current room or userMatching playback, settings, list, or member resources
Provider credential changedMay affect the current user’s playback and provider browsing results
Playback expiresAutomatically re-evaluates playback observations

The server coalesces identical short-window queries in the same room. Clients do not need to rely on this optimization, but can safely create separate observeId values for separate views.