Skip to main content

Socket.io Events

All event names below are the active paths in server.js. Several older names (start_stream, audio_data, stop_stream) still exist for the studio/live injection flow.

Server → Client (broadcast to all)

EventPayloadPurpose
status{ channel, nowPlaying }Current track on a channel. Emitted on join, on track change, and on a loop when a track fails
new_comment{ name, text, … }A chat comment was posted
interaction{ type: 'vibe_vote', vibe }A listener voted on the vibe
message{ user, text }Chat room message (admin welcome, room joins)
stream_error{ message }Live-stream audio pipeline failed
stats_update{ listeners, bandwidth, history }Periodic listener/bandwidth telemetry
timeline_updatequeueThe upcoming queue (next tracks)

Client → Server

EventPayloadPurpose
join_channelchannelIdSubscribe to a channel's status feed
send_comment{ name, text }Post a comment
interaction{ type: 'vibe_vote', vibe }Cast a vibe vote
join{ name, room }Join a chat room
sendMessage{ type: 'text'|'voice'|'image', … }Chat message (text, voice note, image data-URL)
reaction{ msgId, emoji, user }React to a chat message
start_streamBegin live audio injection (studio)
audio_dataaudio chunkStream live audio to the server
stop_streamEnd live injection

Flow examples

Now-playing update on every frontend

  1. A track plays in the engine (radio-engine.jsradio.nowPlaying).
  2. Engine emits status on radio.io.
  3. server.js re-emits to all clients: io.emit('status', { channel, nowPlaying }).
  4. Every page updates its now-playing widget.

Vibe vote

  1. Listener clicks a vibe in index.html.
  2. socket.emit('interaction', { type: 'vibe_vote', vibe }).
  3. Server relays io.emit('interaction', data) so all listeners see the vote.

Chat (themed rooms)

  1. Client joins { name, room } → server broadcasts admin welcome.
  2. sendMessage → server routes to the target room and relays message.
  3. Voice notes are sent as data: audio; images as data: image URLs.

Live studio injection

  1. studio.html pushes a button → start_stream.
  2. Microphone chunks flow in as audio_data.
  3. stop_stream ends the session (the broadcast engine switches back to automation).

Live channel takeover (LiveManager / WHIP)

  1. POST /api/station/live/start (or a WHIP /go-live connection) ranks the registered streams and restreams the winner into the Liquidsoap channel_live harbor (:8006).
  2. The .liq switch puts the live source on air over the mix; the status socket payload carries the live nowPlaying.
  3. POST /api/station/live/stop drops the restream and Liquidsoap automatically returns to the normal rotation.

Status payload shape

{
"channel": "main",
"nowPlaying": {
"title": "…",
"artist": "…",
"file": "music/arabic_hits/….mp3"
}
}

See also API endpoints for the HTTP equivalents.