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 fully self-hosted control plane 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="pk_..." /><Player contentType="clip" contentId="pk_..." />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="pk_..." 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(). They render nothing if used outside a <Player>.
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: "pk_...", 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 ?jwt= 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 | Initial controls/dev-panel mode label; use setDevModeOptions for runtime protocol preference |
options.debug | boolean | Debug logging |
onStateChange | function | State transition callback |
State Callbacks
Section titled “State Callbacks”<Player contentId="pk_..." contentType="live" onStateChange={(state, context) => { // 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 controls protocol preference order:
| Mode | Preference | Use Case |
|---|---|---|
low-latency | WebCodecs/WS → WHEP/WebRTC → MP4/WS → HLS | Real-time interaction |
quality | MP4/WS and WebCodecs/WS → HLS/MP4 → WebRTC | Stable, high quality |
vod | MP4/HLS/DASH → MP4/WS → WHEP/WebRTC | Pre-recorded content |
auto | Balanced score-based | 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="pk_..." contentType="live" options={{ playbackMode: "low-latency" }} />Runtime Protocol Overrides
Section titled “Runtime Protocol Overrides”const { setDevModeOptions } = usePlayerController({ contentId: "pk_...", contentType: "live",});
void setDevModeOptions({ forceType: "whep" });