@livepeer/react provides a composable Player that handles HLS and WebRTC playback with automatic transport negotiation. Pass a playback source and the component handles ABR selection, poster rendering, and playback state.
npm install @livepeer/react
Basic player
import * as Player from '@livepeer/react/player';
export function VideoPlayer({ playbackId }: { playbackId: string }) {
return (
<Player.Root
src={[
{
type: 'hls',
src: \`https://livepeercdn.studio/hls/\${playbackId}/index.m3u8\`,
},
]}
>
<Player.Container>
<Player.Video title="Video player" />
<Player.Controls className="flex items-center gap-2">
<Player.PlayPauseTrigger className="w-8 h-8">
<Player.PlayingIndicator asChild matcher={false}>
<span>Play</span>
</Player.PlayingIndicator>
<Player.PlayingIndicator asChild>
<span>Pause</span>
</Player.PlayingIndicator>
</Player.PlayPauseTrigger>
<Player.MuteTrigger className="w-8 h-8" />
<Player.Volume className="w-24" />
<Player.Time className="text-sm" />
</Player.Controls>
</Player.Container>
</Player.Root>
);
}
Player.Root accepts a src array of source objects. For Livepeer streams and assets, the HLS source is at https://livepeercdn.studio/hls/{playbackId}/index.m3u8. For WebRTC, use the getSrc utility from @livepeer/react/external.
Player components
Root components:
Player.Root accepts src (source array), autoPlay, volume, and event callbacks
Player.Container wraps the video element and controls
Player.Video renders the <video> element with automatic transport selection
Playback controls:
Player.PlayPauseTrigger toggles play/pause
Player.PlayingIndicator renders conditionally based on play state (matcher={true} for playing, matcher={false} for paused)
Player.MuteTrigger toggles mute
Player.Volume renders a volume slider
Player.Seek and Player.SeekBuffer for scrubbing and buffered range display
Player.Time renders current time / duration
Player.FullscreenTrigger and Player.FullscreenIndicator
Player.PictureInPictureTrigger
Quality and rate:
Player.VideoQualitySelect and Player.VideoQualitySelectItem for manual ABR override
Player.RateSelect and Player.RateSelectItem for playback speed
Status indicators:
Player.LoadingIndicator renders during buffering
Player.ErrorIndicator renders on playback failure
Player.LiveIndicator renders when the source is a live stream
Player.Poster renders a poster image before playback starts
All components are unstyled. Apply CSS classes directly or use Tailwind utility classes. The asChild prop delegates rendering to the child element (Radix pattern).
WebRTC playback
For sub-second latency playback, add a WebRTC source alongside HLS:
import { getSrc } from '@livepeer/react/external';
const src = getSrc('https://livepeercdn.studio/hls/{playbackId}/index.m3u8');
// Returns [{ type: 'webrtc', src: '...' }, { type: 'hls', src: '...' }]
<Player.Root src={src}>
<Player.Container>
<Player.Video />
</Player.Container>
</Player.Root>
The Player tries WebRTC first and falls back to HLS if the browser or network does not support it.
Source: livepeer/ui-kit packages/react/src/player.tsx.
The video overview covers the stream creation and ingest flow that produces the playbackId used here. Last modified on June 2, 2026