Player — React
Installation
Section titled “Installation”npm install @livepeer-frameworks/player-reactimport "@livepeer-frameworks/player-react/player.css";Drop-in Component
Section titled “Drop-in Component”import { Player } from "@livepeer-frameworks/player-react";import "@livepeer-frameworks/player-react/player.css";
function LiveStream() { return ( <Player contentType="live" contentId="<YOUR_PLAYBACK_ID>" options={{ autoplay: true, muted: true, }} /> );}The player resolves through the official FrameWorks Gateway from the viewer’s browser, so Foghorn
routes from that viewer’s IP. Set gatewayUrl only for a provider-managed private Gateway or local
Gateway preview. For backend-generated playback URLs or custom players that do not use this
component, use the dashboard playback DNS URL directly.
Direct MistServer Node
Section titled “Direct MistServer Node”<Player contentType="live" contentId="<YOUR_PLAYBACK_ID>" options={{ mistUrl: "https://edge-egress.eu.example.com" }}/>DVR and Clips
Section titled “DVR and Clips”<Player contentType="dvr" contentId="a1b2c3d4e5f6g7h8" /><Player contentType="clip" contentId="a1b2c3d4e5f6g7h8" />Composable Controls
Section titled “Composable Controls”Pass children to <Player> to replace the built-in controls with your own layout. Sub-components auto-connect to the parent via React context.
import { Player, PlayButton, SkipButton, VolumeControl, TimeDisplay, LiveBadge, FullscreenButton, ControlBar, SettingsMenu,} from "@livepeer-frameworks/player-react";
function CustomPlayer() { return ( <Player contentId="a1b2c3d4e5f6g7h8" contentType="live"> <ControlBar> <PlayButton /> <SkipButton direction="back" /> <SkipButton direction="forward" /> <TimeDisplay /> <LiveBadge /> <VolumeControl /> <SettingsMenu /> <FullscreenButton /> </ControlBar> </Player> );}Sub-Component Reference
Section titled “Sub-Component Reference”| Component | Purpose |
|---|---|
PlayButton | Play/pause toggle |
SkipButton | Skip forward/back (pass direction="back" or "forward") |
VolumeControl | Volume slider with mute toggle |
TimeDisplay | Current time / duration display |
LiveBadge | Live indicator with jump-to-live |
FullscreenButton | Fullscreen toggle |
SettingsMenu | Quality, speed, and track selection |
ControlBar | Horizontal flex container for controls |
All sub-components read state from the nearest <Player> parent via usePlayerContextOptional(). Outside a <Player> they still render, but only reflect and act on the props you pass them (for example isPlaying and onToggle on PlayButton).
Custom UI with Hooks
Section titled “Custom UI with Hooks”For complete UI control, use usePlayerController directly:
import { usePlayerController } from "@livepeer-frameworks/player-react";
function FullyCustomPlayer() { const { containerRef, state, controller } = usePlayerController({ contentId: "a1b2c3d4e5f6g7h8", contentType: "live", autoplay: true, muted: true, });
return ( <div> <div ref={containerRef} style={{ width: "100%", aspectRatio: "16/9" }} /> <p>State: {state.state}</p> <p> {state.isPlaying ? "Playing" : "Paused"} | Volume: {state.volume} </p> <button onClick={() => controller?.togglePlay()}>{state.isPlaying ? "Pause" : "Play"}</button> <button onClick={() => controller?.toggleMute()}>{state.isMuted ? "Unmute" : "Mute"}</button> </div> );}Hook Return
Section titled “Hook Return”| Property | Type | Description |
|---|---|---|
state | PlayerControllerState | Reactive state object (isPlaying, volume, currentTime, etc.) |
controller | PlayerController | null | Controller instance for direct method calls |
containerRef | RefObject<HTMLElement> | Attach to the container div |
setDevModeOptions | function | Runtime player/source/protocol override helper |
State Properties
Section titled “State Properties”| Property | Type | Description |
|---|---|---|
state.state | PlayerState | Current lifecycle state |
state.isPlaying | boolean | Whether playing |
state.isPaused | boolean | Whether paused |
state.isMuted | boolean | Whether muted |
state.volume | number | Volume (0-1) |
state.currentTime | number | Current position in milliseconds |
state.duration | number | Duration in milliseconds (Infinity for live) |
state.isBuffering | boolean | Whether buffering |
state.isFullscreen | boolean | Whether in fullscreen |
state.isEffectivelyLive | boolean | Whether live content |
state.error | string | null | Current error message |
Props Reference
Section titled “Props Reference”| Prop | Type | Description |
|---|---|---|
contentId | string | Playback ID (live/clip/DVR/VOD) |
contentType | 'live' | 'dvr' | 'clip' | 'vod' | Content type (affects presets and UI) |
endpoints | ContentEndpoints | Advanced: pass pre-resolved endpoints |
thumbnailUrl | string | Poster image (pre-playback overlay). Seek-bar sprites are auto-detected. |
options.gatewayUrl | string | Gateway GraphQL endpoint override |
options.mistUrl | string | Direct MistServer base URL |
options.authToken | string | Bearer token for Gateway GraphQL resolution |
options.playbackAuth | { token: string; transport?: "query" | "header" } | Viewer JWT sent as ?fwjwt= by default, or Authorization: Bearer on player-controlled transports |
options.autoplay | boolean | Auto-start playback |
options.muted | boolean | Start muted (required for autoplay) |
options.stockControls | boolean | Use browser-native video controls |
options.animatePreroll | boolean | Cycle thumbnail sprite tiles as a preroll animation before playback. Default false (static poster) |
options.theme | string | Theme preset name |
options.themeOverrides | object | Per-token theme overrides |
options.locale | string | Built-in UI locale |
options.playbackMode | string | Protocol selection mode (see Playback Modes); change at runtime with setDevModeOptions({ playbackMode }) |
options.debug | boolean | Debug logging |
onStateChange | function | State transition callback |
State Callbacks
Section titled “State Callbacks”<Player contentId="a1b2c3d4e5f6g7h8" contentType="live" onStateChange={(state) => { // States: booting, gateway_loading, gateway_ready, gateway_error, // no_endpoint, selecting_player, connecting, buffering, // playing, paused, ended, error, destroyed console.log("State:", state); }}/>Playback Modes
Section titled “Playback Modes”playbackMode weights the protocol scoring axes (latency, boot time, stability, VOD suitability).
With every output available, each mode typically selects:
| Mode | Typical winner | Use Case |
|---|---|---|
low-latency | WHEP | Real-time interaction |
balanced | CMAF (LL-HLS) | Low latency, stable |
quality | HLS (TS) | Stable, high quality |
vod | HLS (TS) for long content, MP4 for short clips | Pre-recorded content |
auto | HLS (TS) | Default |
LL-HLS and DASH are served from MistServer’s CMAF output (/play/{id}/cmaf/index.m3u8 and
/play/{id}/cmaf/index.mpd) on every helmsman-managed edge.
<Player contentId="a1b2c3d4e5f6g7h8" contentType="live" options={{ playbackMode: "low-latency" }} />Runtime Protocol Overrides
Section titled “Runtime Protocol Overrides”const { setDevModeOptions } = usePlayerController({ contentId: "a1b2c3d4e5f6g7h8", contentType: "live",});
void setDevModeOptions({ forceType: "whep" });