Docs

Send audio and video streams

Use the browser’s media APIs to capture audio or video, then share the stream with peers in a room. Media uses its own WebRTC tracks rather than action messages.

Add a local stream

Register your stream receiver before requesting camera access. Then add your local stream to connected peers and to each peer that joins later. Capture requires HTTPS or localhost and the user’s permission.

const localStream = await navigator.mediaDevices.getUserMedia({
  audio: true,
  video: true
})

room.addStream(localStream)

room.onPeerJoin = peerId => {
  room.addStream(localStream, {target: peerId})
}

Receive peer streams

Set onPeerStream to attach incoming streams to video or audio elements. Browsers may block autoplay with sound, so provide a play button when needed. Mute your local preview to avoid feedback.

room.onPeerStream = (stream, peerId, metadata) => {
  const video = getPeerVideo(peerId)
  video.autoplay = true
  video.playsInline = true
  video.srcObject = stream
  video.play().catch(() => showPlayButton(video))
}

Attach metadata

Metadata helps distinguish cameras, microphones, screen shares, and other stream types in your UI.

const screen = await navigator.mediaDevices.getDisplayMedia({
  video: true,
  audio: true
})

room.addStream(screen, {
  metadata: {kind: 'screen-share'}
})

Switch cameras or stop sending

replaceTrack() changes a track without removing the whole stream. It returns an array of promises, one per targeted peer. addStream() and addTrack() return arrays too.

const nextStream = await navigator.mediaDevices.getUserMedia({
  video: {deviceId: {exact: selectedCameraId}}
})

const oldTrack = localStream.getVideoTracks()[0]
const newTrack = nextStream.getVideoTracks()[0]

await Promise.all(room.replaceTrack(oldTrack, newTrack))
localStream.removeTrack(oldTrack)
localStream.addTrack(newTrack)
oldTrack.stop()

Remove a stream from the room to stop sharing it. Stop its local tracks as well to release the camera and microphone.

room.removeStream(localStream)
localStream.getTracks().forEach(track => track.stop())

Media methods accept an options object. Use target for a peer ID or array of IDs, and metadata when adding streams or tracks. Omitting a target applies the operation to connected peers.