> ## Documentation Index
> Fetch the complete documentation index at: https://docs.livepeer.org/llms.txt
> Use this file to discover all available pages before exploring further.

# React Broadcast

> The @livepeer/react Broadcast component: browser-based WHIP live streaming with camera/microphone selection, screen sharing, and status indicators.

export const CenteredContainer = ({children, maxWidth = "800px", padding = "0", preset = "default", width = "", minWidth = "", marginRight = "", marginBottom = "", textAlign = "", style = {}, className = "", ...rest}) => {
  const presets = {
    default: {},
    fitContent: {
      width: "fit-content",
      minWidth: "fit-content"
    },
    readable70: {
      width: "70%",
      minWidth: "fit-content"
    },
    readable80: {
      width: "80%",
      minWidth: "fit-content"
    },
    readable90: {
      width: "90%"
    },
    wide900: {
      maxWidth: "900px"
    }
  };
  const presetStyle = presets[preset] || presets.default;
  return <div className={className} style={{
    maxWidth: presetStyle.maxWidth || maxWidth,
    margin: "0 auto",
    padding: padding,
    ...presetStyle.width ? {
      width: presetStyle.width
    } : {},
    ...presetStyle.minWidth ? {
      minWidth: presetStyle.minWidth
    } : {},
    ...width ? {
      width
    } : {},
    ...minWidth ? {
      minWidth
    } : {},
    ...marginRight ? {
      marginRight
    } : {},
    ...marginBottom ? {
      marginBottom
    } : {},
    ...textAlign ? {
      textAlign
    } : {},
    ...style
  }} {...rest}>
      {children}
    </div>;
};

export const CustomDivider = ({color = "var(--lp-color-border-default)", middleText = "", spacing = "default", style = {}, className = "", ...rest}) => {
  const spacingPresets = {
    default: {
      margin: "24px 0"
    },
    overlap: {
      margin: "-1rem 0 -1rem 0"
    },
    tight: {
      margin: "0 0 -1rem 0"
    },
    section: {
      margin: "0 0 -2rem 0"
    },
    sectionOverlap: {
      margin: "-1rem 0 -2rem 0"
    },
    deepOverlap: {
      margin: "-1rem 0 -1.5rem 0"
    }
  };
  const spacingStyle = spacingPresets[spacing] || spacingPresets.default;
  return <div role="separator" aria-orientation="horizontal" className={className} style={{
    display: "flex",
    alignItems: "center",
    ...spacingStyle,
    fontSize: style?.fontSize || "16px",
    height: "fit-content",
    ...style
  }} {...rest}>
      <span style={{
    marginRight: "var(--lp-spacing-px-8)",
    opacity: 0.2
  }}>
        <Icon icon="/snippets/assets/logos/Livepeer-Logo-Symbol-Theme.svg" />
      </span>
      <div style={{
    flex: 1,
    height: "1px",
    background: "var(--lp-color-border-default)",
    opacity: 0.4
  }}></div>
      {middleText && <>
          <Icon icon="circle" size={2} />
          <span style={{
    margin: "0 8px",
    fontWeight: "bold",
    color: color,
    opacity: 0.7
  }}>
            {middleText}
          </span>
          <Icon icon="circle" size={2} />
        </>}
      <div style={{
    flex: 1,
    height: "1px",
    background: "var(--lp-color-border-default)",
    opacity: 0.4
  }}></div>
      <span style={{
    marginLeft: "var(--lp-spacing-px-8)",
    opacity: 0.2
  }}>
        <span style={{
    display: "inline-block",
    transform: "scaleX(-1)"
  }}>
          <Icon icon="/snippets/assets/logos/Livepeer-Logo-Symbol-Theme.svg" />
        </span>
      </span>
    </div>;
};

<CenteredContainer preset="readable90">
  <Tip>Broadcast uses WHIP (WebRTC-HTTP Ingestion Protocol) to stream from the browser. Users stream directly without OBS or external encoders.</Tip>
</CenteredContainer>

<CustomDivider />

`@livepeer/react` provides a composable Broadcast component for browser-based live streaming. It handles WebRTC signalling, camera/microphone enumeration, and stream lifecycle.

```bash theme={"theme":{"light":"github-light","dark":"dark-plus"}}
npm install @livepeer/react
```

<CustomDivider />

## Basic broadcast

```tsx theme={"theme":{"light":"github-light","dark":"dark-plus"}}
import * as Broadcast from '@livepeer/react/broadcast';

export function LiveBroadcast({ streamKey }: { streamKey: string }) {
  return (
    <Broadcast.Root ingestUrl={\`https://livepeercdn.studio/webrtc/\${streamKey}\`}>
      <Broadcast.Container>
        <Broadcast.Video title="Live broadcast" />
        <Broadcast.Controls>
          <Broadcast.EnabledTrigger>
            <Broadcast.EnabledIndicator asChild matcher={false}>
              <span>Go Live</span>
            </Broadcast.EnabledIndicator>
            <Broadcast.EnabledIndicator asChild>
              <span>Stop</span>
            </Broadcast.EnabledIndicator>
          </Broadcast.EnabledTrigger>
          <Broadcast.AudioEnabledTrigger />
          <Broadcast.VideoEnabledTrigger />
          <Broadcast.ScreenshareTrigger />
        </Broadcast.Controls>
      </Broadcast.Container>
    </Broadcast.Root>
  );
}
```

`Broadcast.Root` accepts an `ingestUrl` (the WHIP endpoint for your stream). Get the stream key from the stream creation API response.

<CustomDivider />

## Broadcast components

**Root components:**

* `Broadcast.Root` accepts `ingestUrl` and configuration options
* `Broadcast.Container` wraps the video preview and controls
* `Broadcast.Video` renders the local camera preview

**Stream controls:**

* `Broadcast.EnabledTrigger` starts and stops the broadcast
* `Broadcast.EnabledIndicator` renders conditionally based on broadcast state
* `Broadcast.AudioEnabledTrigger` toggles microphone
* `Broadcast.AudioEnabledIndicator` shows mic state
* `Broadcast.VideoEnabledTrigger` toggles camera
* `Broadcast.VideoEnabledIndicator` shows camera state
* `Broadcast.ScreenshareTrigger` starts screen sharing
* `Broadcast.ScreenshareIndicator` shows screen share state

**Device selection:**

* `Broadcast.SourceSelect` enumerates and selects camera/microphone devices

**Status:**

* `Broadcast.StatusIndicator` renders based on connection state (connecting, connected, error)
* `Broadcast.ErrorIndicator` renders on broadcast failure
* `Broadcast.LoadingIndicator` renders during connection setup

<CustomDivider />

Source: [`livepeer/ui-kit`](https://github.com/livepeer/ui-kit) `packages/react/src/broadcast.tsx`.

The [video overview](/v2/developers/build/video/overview) covers stream creation. The [ingest and playback](/v2/developers/build/video/ingest-and-playback) page covers RTMP and WHIP ingest configuration.
