Raven Docs

Rooms & Participants

Participant state, device selection, sending data, and the track model — on Web, React, React Native, and Flutter.

Participants

room.localParticipant.identity; // this session's own identity
room.localParticipant.tracks;   // LocalTrack[] currently published
 
room.remoteParticipants;        // RemoteParticipant[]
participant.identity;
participant.metadata;           // opaque, set when the token was minted
participant.tracks;             // RemoteTrack[] currently subscribed
 
room.on('participantJoined', (participant) => {});
room.on('participantLeft', (participant) => {});

metadata is whatever your backend attached when it minted the token — Raven never inspects or interprets it.

Device selection

Web-only — React Native and Flutter select devices through the OS, not a JavaScript device-enumeration API.

const devices = await client.getDevices();
// { deviceId, label, kind }[] — kind: 'videoinput' | 'audioinput' | 'audiooutput'
// labels are populated only once permission has been granted at least once
 
await room.setCameraDevice(deviceId);
await room.setMicrophoneDevice(deviceId);
await room.setSpeakerDevice(deviceId); // where the browser supports setSinkId — not Safari; throws DEVICE_NOT_FOUND there
 
const unsubscribe = client.onDeviceChange(() => {
  // re-enumerate — a camera or mic was connected or disconnected
});

On React Native, the closest equivalent is switching front/rear camera — see Flutter's switchCamera() for the Dart SDK's version of the same phone-only concern.

Sending data

await room.sendData('hello'); // string or Uint8Array
 
room.on('dataReceived', (payload, participant) => {
  console.log(new TextDecoder().decode(payload), participant?.identity);
});

Requires the token's publishData grant — throws PERMISSION_DENIED otherwise. Deliberately minimal: no reliability options, no per-participant targeting. If you need routed, ordered, or persisted messages between participants, that's what Chat is for — it's a first-class service, not a fallback bolted onto the data channel.

Track model

Track   (base: kind, mediaStreamTrack, mediaStream, isMuted, attach(), detach())
  ├── LocalTrack   (+ mute(), unmute(), stop())
  └── RemoteTrack

track.attach() / track.attach(existingElement) and track.detach() are the SDK's only media-element helpers — it's an SDK, not a UI component library:

room.on('trackSubscribed', (track, participant) => {
  videoElement.appendChild(track.attach());
});
 
room.on('trackUnsubscribed', (track) => {
  track.detach().forEach((el) => el.remove());
});

Common errors

ErrorWhyFix
PERMISSION_DENIED on sendData()Token was minted without publishData.Set publishData: true when calling tokens.create().
DEVICE_NOT_FOUND on setSpeakerDevice()Browser doesn't support setSinkId (Safari).Fall back to system output selection — there's no workaround.
  • Audio & Video — enabling the devices whose tracks show up here.
  • RTC → Overview — the full event list.
  • Chat — for anything data messages are too minimal for.