Working with Events
Events are a fundamental aspect of working with the SDK. As introduced in the getting started section, events enable your application to respond to various changes and updates. For example, you can be notified when a RemotePeer AudioOutput
The SDK primarily revolves around three core Entities, each associated with a specific set of events:
Room
->RoomEvents
- Peer (
LocalPeer
andRemotePeer
) ->PeerEvents
- Media (
AudioInput
andAudioOutput
) ->MediaEvents
How Events Propagate
AudioActivity and AudioPowerLevel events are dispatched in a fan-out chain:
- The underlying
AudioInput
orAudioOutput
decides when activity changes — voice activity detection runs on the decoded audio in the worklet, and the event is emitted on the edge (state change), not on every sample. - That media re-dispatches the event on its owning Peer.
- The Peer re-dispatches it on the
Room
.
Each level sees the same event — just at a different scope. Listening at the room level gives you every media's activity in one stream; listening on a specific peer narrows it to that peer's media; listening on a media instance narrows it to that one input or output. There is no duplication and no information loss between levels.
When rendering many users at once, prefer a single room-level handler plus your own per-user state map. Attaching a peer-level listener inside every per-user component multiplies listener traffic and re-subscribes on every component re-mount or input change — a common source of dropped events under load and momentary gaps when listeners are torn down and re-added.
AudioInputAudioActivity events come from voice activity detection on the decoded audio, not from the playback gain. Calling room.setVolume(0), remotePeer.setVolume(0), or output.setVolume(0) silences local playback but does not stop activity events from firing. To actually stop receiving activity for a remote stream, call output.pause() — the server will stop sending packets, and the SDK dispatches a final Activity = false once the stream drains. Local input activity stops only when the 'muted'.
You don't need to wait for the next event to know the current state. The following getters are always readable:
audioInput.isActive/audioOutput.isActive—truewhile the media is currently emitting voice.peer.isActive—trueif any of the peer's audio outputs is active.
This is useful when seeding UI state on mount, or after a reconnect, without waiting for the next edge-triggered event.
Room Events
The room is the main entity to work with. It's important to register its event handlers before joining. This ensures you capture all relevant events, particularly initial ones like the RoomStatus PeerJoined
As for all Events, there are two ways to register EventHandlers (callbacks). The obj.addEventlistener() and obj.onEvent approach. In the following examples, for simplicity, the onEvent property approach is used.
To prevent memory leaks when reusing a room instance for multiple connections, ensure that EventListeners are handled correctly. You should either:
- Remove event listeners when leaving the room.
- Ensure that event listeners are registered only once.
Alternatively, you can use the room.onPeerJoined syntax. This assigns a callback directly, overwriting any previous assignment, which can simplify event management and help avoid unintended multiple registrations.
Most relevant room events
Peer Events
There are two types of Peers, the LocalPeer RemotePeer PeerEvents Room
Most relevant peer events
Media (AudioInput / AudioOutput) Events
Similar to Peers, Medias are separated into AudioInput AudioOutput AudioInput RemotePeer
More details about configuring the AudioInput
Important Note: In the most apps, a Peer will always have one AudioInput AudioOutput MediaEvents