← All posts
Party RoomLive AudioTutorial

How to Build a Live Party Room App: Voice for 6–32 Speakers

VoxaStream Team·May 6, 2026·10 min read

A party room is a specific kind of voice experience: multiple active speakers in a shared room, with the option for a much larger audience of listeners to tune in. Think of it like a live podcast where the hosts can hear each other and the crowd listens — except you are building it directly into your app.

This guide covers how to build exactly that using VoxaStream: a room that supports up to 32 active speakers, all broadcasting live to thousands of listeners, with role-based controls so you decide who can speak and who just listens.

Understanding the architecture

A VoxaStream party room has three types of participants:

  • Speakers — Active participants whose microphones are open. Up to 32 in a single room. They can hear each other and are heard by all listeners.
  • Listeners — Read-only participants. They receive the full audio mix from all speakers but their microphone is never activated. There is no hard limit on listener count.
  • Host — A special speaker role that cannot be forcefully muted by others. Typically the room creator.

All of this is handled by VoxaStream's voice engine. You just assign roles at join time.

Step 1: Create the room

Create a channel from your backend using your secret API key. You would typically do this when a user taps "Start a Room" in your app.

// POST /api/channels
// Authorization: Bearer vc_your_secret_key

const response = await fetch('https://voxastream.com/api/channels', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer vc_your_secret_key',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ name: 'Friday Night Party' }),
});

const room = await response.json();
// { "id": 42, "name": "Friday Night Party" }

// Store room.id — you'll need it to invite others

Step 2: Authenticate the host

Get a session token for the user who is creating the room. They will join as the host.

const tokenRes = await fetch('https://voxastream.com/api/auth/auto', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer vc_your_secret_key',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ username: 'sarah' }),
});

const { token } = await tokenRes.json();

Step 3: Connect the host as a speaker

const ws = new WebSocket('wss://voxastream.com/ws?token=' + token);

ws.onopen = () => {
  ws.send(JSON.stringify({
    type: 'join_channel',
    payload: {
      channel_id: 42,
      role: 'host',  // or 'speaker' for other active participants
    },
  }));
};

ws.onmessage = ({ data }) => {
  const { type, payload } = JSON.parse(data);

  if (type === 'channel_users') {
    // payload.users is the live list of everyone in the room
    updateParticipantList(payload.users);
  }
};

Step 4: Let listeners join

When a listener joins, they connect to the same room but with the listener role. Their microphone is never opened — they only receive audio.

// Listener side — exactly the same flow, different role
ws.send(JSON.stringify({
  type: 'join_channel',
  payload: {
    channel_id: 42,
    role: 'listener',
  },
}));

This is the key insight: you can have 32 active speakers and 10,000 listeners all in the same room simultaneously. VoxaStream's engine handles the audio mixing and distribution.

Step 5: Build the speaker list UI

Use the channel_users message to keep your UI in sync with who is in the room and whether they are speaking or muted:

ws.onmessage = ({ data }) => {
  const { type, payload } = JSON.parse(data);

  switch (type) {
    case 'channel_users':
      // Full user list update
      setUsers(payload.users);
      // Each user: { id, username, role, muted, speaking }
      break;

    case 'presence':
      // Lighter update — someone joined or left
      refreshPresence();
      break;
  }
};

Step 6: Mute controls

Let speakers toggle their own mute state:

function toggleMute(isMuted) {
  ws.send(JSON.stringify({
    type: 'mute',
    payload: { muted: isMuted },
  }));
}

Step 7: Raise hand / promote to speaker

A common party room pattern is letting listeners "raise their hand" to become speakers. You implement this in your own app layer — store a hand-raise state in your database, show it to the host, and when the host approves, have your backend call /api/auth/auto to re-issue a token with the speaker role. The listener reconnects with that token.

Step 8: End the room

// From your backend
await fetch(`https://voxastream.com/api/tenant/rooms/delete/${roomId}`, {
  method: 'POST',
  headers: { 'Cookie': tenantSessionCookie },
});

What you have built

With about 50 lines of code you now have a fully functional party room:

  • Up to 32 active speakers hearing each other in real time
  • Unlimited listeners receiving the live audio mix
  • Live participant list showing who is speaking and who is muted
  • Mute controls for each speaker
  • Host role that cannot be forcefully removed

Add a free VoxaStream account and you can have this running in your app today. Check out the API reference for the full list of WebSocket messages and REST endpoints.

Ready to build with VoxaStream?

Free tier available. No credit card required.

Get Started Free →