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)
| Event | Payload | Purpose |
|---|---|---|
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_update | queue | The upcoming queue (next tracks) |
Client → Server
| Event | Payload | Purpose |
|---|---|---|
join_channel | channelId | Subscribe 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_stream | — | Begin live audio injection (studio) |
audio_data | audio chunk | Stream live audio to the server |
stop_stream | — | End live injection |
Flow examples
Now-playing update on every frontend
- A track plays in the engine (
radio-engine.js→radio.nowPlaying). - Engine emits
statusonradio.io. server.jsre-emits to all clients:io.emit('status', { channel, nowPlaying }).- Every page updates its now-playing widget.
Vibe vote
- Listener clicks a vibe in
index.html. socket.emit('interaction', { type: 'vibe_vote', vibe }).- Server relays
io.emit('interaction', data)so all listeners see the vote.
Chat (themed rooms)
- Client
joins{ name, room }→ server broadcasts admin welcome. sendMessage→ server routes to the target room and relaysmessage.- Voice notes are sent as
data:audio; images asdata:image URLs.
Live studio injection
studio.htmlpushes a button →start_stream.- Microphone chunks flow in as
audio_data. stop_streamends the session (the broadcast engine switches back to automation).
Live channel takeover (LiveManager / WHIP)
POST /api/station/live/start(or a WHIP/go-liveconnection) ranks the registered streams and restreams the winner into the Liquidsoapchannel_liveharbor (:8006).- The
.liqswitch puts the live source on air over the mix; thestatussocket payload carries the livenowPlaying. POST /api/station/live/stopdrops 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.