Skip to main content

Broadcast API

The createBroadcast function lets you send video to Daydream for real-time AI processing.

Basic Usage

import { createBroadcast } from "@daydreamlive/browser";

// Get user's webcam
const stream = await navigator.mediaDevices.getUserMedia({
  video: { width: 512, height: 512 },
  audio: false,
});

// Create broadcast
const broadcast = createBroadcast({
  whipUrl: "https://...", // from your backend
  stream,
});

// Listen for state changes
broadcast.on("stateChange", (state) => {
  console.log("State:", state);
  // 'connecting' | 'live' | 'reconnecting' | 'ended' | 'error'
});

// Connect
await broadcast.connect();

// The WHEP URL for playing the AI output is now available
// It's captured from the WHIP response header 'livepeer-playback-url'
console.log("Watch at:", broadcast.whepUrl);
The WHEP playback URL is returned in the WHIP response header livepeer-playback-url. The Browser SDK automatically captures this for you in broadcast.whepUrl after connecting.

Configuration Options

const broadcast = createBroadcast({
  // Required
  whipUrl: string,           // WHIP endpoint from your backend
  stream: MediaStream,       // Video stream to broadcast

  // Optional
  reconnect: {
    enabled: true,           // Auto-reconnect on disconnect
    maxAttempts: 5,          // Max reconnection attempts
    baseDelay: 1000,         // Initial delay (ms)
    maxDelay: 30000,         // Max delay (ms)
  },
  video: {
    maxBitrate: 2500000,     // Max video bitrate (bps)
    maxFramerate: 30,        // Max framerate
  },
});

State Machine

The broadcast goes through these states:

Events

// State changes
broadcast.on("stateChange", (state) => {
  switch (state) {
    case "connecting":
      console.log("Connecting to Daydream...");
      break;
    case "live":
      console.log("Broadcasting! WHEP URL:", broadcast.whepUrl);
      break;
    case "reconnecting":
      console.log("Lost connection, reconnecting...");
      break;
    case "error":
      console.log("Error occurred");
      break;
    case "ended":
      console.log("Broadcast ended");
      break;
  }
});

// Error details
broadcast.on("error", (error) => {
  console.error("Broadcast error:", error.message);
});

Replace Stream

You can swap the video source while broadcasting (e.g., switch from camera to screen share):
// Start with camera
const cameraStream = await navigator.mediaDevices.getUserMedia({ video: true });
const broadcast = createBroadcast({ whipUrl, stream: cameraStream });
await broadcast.connect();

// Later, switch to screen share
const screenStream = await navigator.mediaDevices.getDisplayMedia({ video: true });
await broadcast.replaceStream(screenStream);

// Stop old stream tracks
cameraStream.getTracks().forEach(track => track.stop());

Adjust Framerate

Dynamically change the max framerate:
// Reduce framerate to save bandwidth
broadcast.setMaxFramerate(15);

// Restore full framerate
broadcast.setMaxFramerate(30);

// Remove limit
broadcast.setMaxFramerate(undefined);

Stop Broadcasting

await broadcast.stop();
This will:
  1. Close the WebRTC connection
  2. Set state to "ended"
  3. The whepUrl is no longer valid
Calling stop() doesn’t stop the MediaStream tracks. You should stop them separately if needed:
stream.getTracks().forEach(track => track.stop());

Complete Example

import { createBroadcast } from "@daydreamlive/browser";

async function startBroadcast(whipUrl: string) {
  // Get camera
  const stream = await navigator.mediaDevices.getUserMedia({
    video: { width: 512, height: 512, frameRate: 30 },
    audio: false,
  });

  // Preview locally
  const preview = document.querySelector("video#preview");
  preview.srcObject = stream;

  // Create broadcast
  const broadcast = createBroadcast({
    whipUrl,
    stream,
    reconnect: { enabled: true },
    video: { maxBitrate: 2000000 },
  });

  // Handle state changes
  broadcast.on("stateChange", (state) => {
    const statusEl = document.querySelector("#status");
    statusEl.textContent = state;

    if (state === "live") {
      // Start player with the AI output
      playOutput(broadcast.whepUrl);
    }
  });

  broadcast.on("error", (error) => {
    console.error("Broadcast failed:", error);
    alert("Broadcast error: " + error.message);
  });

  // Connect
  await broadcast.connect();

  return broadcast;
}

// Usage
const broadcast = await startBroadcast(whipUrl);

// Later...
await broadcast.stop();

Next Steps