Overview
StreamVault uses WebSocket connections to coordinate synchronized playback across multiple clients in Watch Together sessions. The backend acts as a relay server, forwarding sync commands and managing room state.Connection
WebSocket URL
Production:wss://streamvault-backend-server.onrender.com/ws/watchtogether
Development: ws://localhost:3001/ws/watchtogether
Connection Logic
The client automatically selects the appropriate WebSocket URL based on environment (watch_together.rs:12-21):Establishing Connection
Room Lifecycle
Creating a Room
SendCreate message after connecting:
room_created):
Joining a Room
room_joined):
participant_joined):
Leaving a Room
participant_left):
Synchronization Protocol
Ready State
Clients must signal when their player is loaded and ready:participant_ready):
Starting Playback
Only the host can start synchronized playback:playback_started):
Sync Commands
Participants send playback state changes: Play:sync):
is_echo flag indicates if this is the sender’s own command reflected back (watch_together.rs:665-668):
State Reporting
Clients periodically report their playback state (every ~1 second):state_update):
RTT Measurement
Ping-Pong Protocol
Clients measure round-trip time (RTT) by sending pings every 3 seconds (watch_together.rs:452-462): Client Ping:Heartbeat
Keep-alive messages to detect disconnections: Client:Error Handling
Server Errors
"Room not found"- Invalid room code"Room is full"- Maximum participants reached"Media mismatch"- Different media files"Already in a room"- Client already connected to another room
Connection Loss
When the WebSocket closes, emitdisconnected event (watch_together.rs:437-440):
Reconnection Strategy
The client does not automatically reconnect. Users must manually rejoin the room after disconnection. To implement auto-reconnect:Message Type Reference
Client → Server Messages
| Type | Purpose | Required Fields |
|---|---|---|
create | Create new room | media_title, media_id, nickname, client_id |
join | Join existing room | room_code, nickname, client_id, media_id |
ready | Signal player ready | duration |
start | Start playback (host only) | None |
sync | Send sync command | command |
leave | Leave room | None |
heartbeat | Keep-alive ping | None |
state_report | Report playback state | position, paused |
ping | RTT measurement | ping_id |
pong_report | Report measured RTT | ping_id, rtt |
Server → Client Messages
| Type | Purpose | Fields |
|---|---|---|
room_created | Room created successfully | room |
room_joined | Joined room successfully | room |
room_state | Room state update | room |
participant_joined | New participant joined | participant |
participant_left | Participant left | participant_id, room? |
participant_ready | Participant is ready | participant_id, duration |
playback_started | Playback started | position |
sync | Sync command from peer | command, from, timestamp, is_echo |
state_update | Authoritative state | position, paused, server_time, your_rtt, participants |
ping | Server ping for RTT | ping_id, server_time |
pong | Server pong response | ping_id, server_time, your_rtt |
heartbeat_ack | Heartbeat response | timestamp |
error | Error occurred | message |
Data Structures
RoomInfo
Participant
SyncCommand
ParticipantSyncInfo
Example Session
Testing
Test WebSocket connection:Related
Backend Overview
Backend architecture and deployment
Watch Together
Using Watch Together feature