Audio-only pricing
Accounts are automatically billed at the lower audio-only rate when no video tracks are present in a call. See our pricing page for details.If even one participant has an active video track at any point, the call will be billed as a video call.
Set up an audio-only room
The best way to enforce an audio-only experience is to configure room-level permissions to allow audio only. This way, even if a participant tries to turn on their camera, it won’t work.Best practices for audio quality
Decouple <audio> elements from visual components
When <audio> tags are tied to visual elements (like an avatar), audio stops playing when the element scrolls out of view. Render <audio> elements separately from visual components:
Offload expensive processing to an AudioWorklet
An AudioWorklet executes custom audio processing in a separate thread for low-latency processing. Daily Prebuilt uses this approach to detect microphone audio.Managing larger calls
For calls with more than ~5 participants, you need to actively manage audio to keep the experience usable. There are two complementary approaches: receive-side (limit which tracks each participant subscribes to) and send-side (limit who can unmute and speak).Receive-side: subscribe to active speakers only
By default, Daily subscribes every participant to every other participant’s tracks. In a large audio-only call with many unmuted participants, this creates a cacophony of background noise and wastes bandwidth. Disable automatic subscriptions and manage them manually:active-speaker-change event:
DailyAudio component:
Send-side: control who can speak
For moderated experiences — webinars, Q&As, stage-based calls — you’ll want to limit how many participants can unmute at once. There are two approaches depending on whether participants should start muted or be promoted dynamically.Start all participants as listeners
SetcanSend to False at the room level so participants join as listeners by default, then grant audio permission individually:
updateParticipant() with updated permissions:
updateParticipant() with updatePermissions requires the caller to have canAdmin: ['participants'] permission (i.e. they must be an owner or have been granted admin rights).Hand raising
Rather than polling or using app messages, usesetUserData() to broadcast raise/lower hand state. Each participant controls their own userData, and changes propagate to all participants via participant-updated events:
participant-updated to update your UI when any participant’s hand state changes:
updateParticipant() to grant the raised-hand participant canSend: ['audio'].
Analyze performance issues
Audio-only calls require relatively low bandwidth and CPU compared to video calls. If you see CPU or stale WebSocket issues, check for other causes — complex CSS animations can have a noticeable impact.- Use the
/logsendpoint after a session to analyze data. - Use
getNetworkStats()to get live audio bitrates and packet loss during a call.