This page documents all WebSocket events and room requests used in OpenTogetherTube.
Server Messages
Messages sent from the server to connected clients.
Sync
Synchronize room state with clients. Sent when room properties change.
Message Format
{
"action": "sync",
"name": "room-name",
"title": "Room Title",
"description": "Room description",
"isTemporary": false,
"visibility": "public",
"queueMode": "manual",
"isPlaying": true,
"playbackPosition": 42.5,
"playbackSpeed": 1.0,
"currentSource": {
"service": "youtube",
"id": "dQw4w9WgXcQ",
"title": "Video Title",
"length": 213
},
"queue": [
{
"service": "youtube",
"id": "next-video",
"title": "Next Video",
"length": 180
}
],
"grants": [[0, 255], [1, 511]],
"hasOwner": true,
"voteCounts": [["youtube:dQw4w9WgXcQ", 5]],
"enableVoteSkip": false,
"votesToSkip": [],
"videoSegments": [],
"autoSkipSegmentCategories": ["sponsor", "intro"]
}
Fields
Whether video is currently playing
Current playback position in seconds
Playback speed multiplier (default: 1.0)
Permission grants as [role, mask] pairs
Vote counts as ["service:id", count] pairs
SponsorBlock segments for current video
Event
Notify clients of user actions (e.g., video added, playback changed).
Message Format
{
"action": "event",
"request": {
"type": 5,
"video": {
"service": "youtube",
"id": "dQw4w9WgXcQ"
}
},
"user": {
"name": "Username",
"isLoggedIn": true
},
"additional": {
"video": {
"service": "youtube",
"id": "dQw4w9WgXcQ",
"title": "Video Title",
"length": 213
}
}
}
Fields
The original room request that triggered this event
User who performed the action
Extra context about the event (varies by request type)
Event Custom
System-generated events with custom messages.
{
"action": "eventcustom",
"text": "Skipped sponsor",
"duration": 3000
}
Display duration in milliseconds (optional)
Chat
Chat message from a user.
{
"action": "chat",
"from": {
"id": "client-123",
"name": "Username",
"isLoggedIn": true,
"status": "ready",
"role": 2
},
"text": "Hello everyone!"
}
User who sent the message
User
User join, leave, or update notification.
User Joined/Updated
{
"action": "user",
"update": {
"kind": "update",
"value": {
"id": "client-123",
"name": "Username",
"isLoggedIn": true,
"status": "ready",
"role": 2
}
}
}
User Left
{
"action": "user",
"update": {
"kind": "remove",
"value": "client-123"
}
}
Initial User List
{
"action": "user",
"update": {
"kind": "init",
"value": [
{
"id": "client-123",
"name": "User1",
"isLoggedIn": true,
"status": "ready",
"role": 2
},
{
"id": "client-456",
"name": "User2",
"isLoggedIn": false,
"status": "ready",
"role": 0
}
]
}
}
You
Server sends your client ID after authentication.
{
"action": "you",
"info": {
"id": "client-123-abc"
}
}
Your unique client identifier
Announcement
Server-wide announcement message.
{
"action": "announcement",
"text": "Server maintenance in 30 minutes"
}
Unload
Room is being unloaded. Clients should disconnect.
Client Messages
Messages sent from clients to the server.
Authenticate
{
"action": "auth",
"token": "YOUR_AUTH_TOKEN"
}
Player Status
{
"action": "status",
"status": 2
}
Status Values
0 - none (no player loaded)
1 - buffering
2 - ready
3 - error
Kick Me
Request to be kicked from the room (leave).
{
"action": "kickme",
"reason": 0
}
Notify
Notify server of client-side changes.
{
"action": "notify",
"message": "usernameChanged"
}
Room Request
Perform an action in the room.
{
"action": "req",
"request": {
"type": 5,
"video": {
"service": "youtube",
"id": "dQw4w9WgXcQ"
}
}
}
Room Requests
Room requests are actions performed within a room, sent via the req client message.
Join Request
Join a room.
{
"type": 0,
"info": {
"id": "client-123",
"username": "MyUsername",
"status": 2
}
}
0 (RoomRequestType.JoinRequest)
Your client ID (from you message)
Leave Request
Leave the room.
Playback Request
Play or pause the video.
{
"type": 2,
"state": true
}
true to play, false to pause
Skip Request
Skip to the next video (or vote to skip if vote-skip is enabled).
Seek Request
Seek to a specific position.
{
"type": 4,
"value": 42.5
}
Add Request
Add video(s) to the queue.
Single Video
{
"type": 5,
"video": {
"service": "youtube",
"id": "dQw4w9WgXcQ"
}
}
Multiple Videos
{
"type": 5,
"videos": [
{"service": "youtube", "id": "dQw4w9WgXcQ"},
{"service": "youtube", "id": "jNQXAC9IVRw"}
]
}
By URL
{
"type": 5,
"url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
}
Remove Request
Remove a video from the queue.
{
"type": 6,
"video": {
"service": "youtube",
"id": "dQw4w9WgXcQ"
}
}
Order Request
Reorder the queue.
{
"type": 7,
"fromIdx": 0,
"toIdx": 3
}
Vote Request
Vote for a video in the queue.
{
"type": 8,
"video": {
"service": "youtube",
"id": "dQw4w9WgXcQ"
},
"add": true
}
true to add vote, false to remove vote
Promote/demote a user’s role.
{
"type": 9,
"targetClientId": "client-456",
"role": 2
}
Client ID of user to promote
Update User
Update user information.
{
"type": 10,
"info": {
"id": "client-123",
"username": "NewUsername",
"status": 2
}
}
Chat Request
Send a chat message.
{
"type": 11,
"text": "Hello everyone!"
}
Undo Request
Undo a previous action.
{
"type": 12,
"event": {
"action": "event",
"request": { /* original request */ },
"user": { /* user info */ },
"additional": { /* event context */ }
}
}
The event message to undo
Apply Settings Request
Change room settings.
{
"type": 13,
"settings": {
"title": "New Title",
"queueMode": "vote",
"autoSkipSegmentCategories": ["sponsor", "intro"],
"enableVoteSkip": true
}
}
Play Now Request
Play a video immediately, pushing current video to queue.
{
"type": 14,
"video": {
"service": "youtube",
"id": "dQw4w9WgXcQ"
}
}
Shuffle Request
Shuffle the queue.
Playback Speed Request
Change playback speed.
{
"type": 16,
"speed": 1.5
}
Playback speed (0.25 - 2.0)
Restore Queue Request
Restore or discard the previous queue.
{
"type": 17,
"discard": false
}
true to discard, false to restore
Kick Request
Kick a user from the room.
{
"type": 18,
"clientId": "client-456"
}
Client ID of user to kick
RoomRequestType Enum
enum RoomRequestType {
JoinRequest = 0,
LeaveRequest = 1,
PlaybackRequest = 2,
SkipRequest = 3,
SeekRequest = 4,
AddRequest = 5,
RemoveRequest = 6,
OrderRequest = 7,
VoteRequest = 8,
PromoteRequest = 9,
UpdateUser = 10,
ChatRequest = 11,
UndoRequest = 12,
ApplySettingsRequest = 13,
PlayNowRequest = 14,
ShuffleRequest = 15,
PlaybackSpeedRequest = 16,
RestoreQueueRequest = 17,
KickRequest = 18
}
Example: Complete Client Implementation
class OTTClient {
constructor(serverUrl, token) {
this.serverUrl = serverUrl;
this.token = token;
this.ws = null;
this.clientId = null;
}
connect() {
this.ws = new WebSocket(this.serverUrl);
this.ws.onopen = () => {
this.authenticate();
};
this.ws.onmessage = (event) => {
const msg = JSON.parse(event.data);
this.handleMessage(msg);
};
}
authenticate() {
this.send({ action: 'auth', token: this.token });
}
handleMessage(msg) {
switch (msg.action) {
case 'you':
this.clientId = msg.info.id;
console.log('Got client ID:', this.clientId);
break;
case 'sync':
console.log('Room state:', msg);
break;
case 'event':
console.log('User action:', msg);
break;
case 'chat':
console.log(`${msg.from.name}: ${msg.text}`);
break;
}
}
joinRoom(roomName) {
this.send({
action: 'req',
request: {
type: 0, // JoinRequest
info: {
id: this.clientId,
username: 'Guest',
status: 2 // ready
}
}
});
}
addVideo(service, id) {
this.send({
action: 'req',
request: {
type: 5, // AddRequest
video: { service, id }
}
});
}
sendChat(text) {
this.send({
action: 'req',
request: {
type: 11, // ChatRequest
text
}
});
}
send(data) {
this.ws.send(JSON.stringify(data));
}
}
// Usage
const client = new OTTClient('wss://opentogethertube.com/', 'YOUR_TOKEN');
client.connect();