Player playground
Editable examples of the real player components, composed the way you would compose them.
Everything here is the real @video/video-client-react package — the same components you
install — running on a sample stream served from this site. Pick a starting point, edit the
code, then press Run (or ⌘/Ctrl + Enter). Capture components (camera and microphone) are
on the camera and microphone playground.
Try it
The smallest useful set. Each control is its own component and finds the player through context.
<Player> <TogglePlayButton /> <ToggleMuteButton /> <VolumeRange /> </Player>
The local Player helper
Player is the one thing on this page that the SDK does not ship. It is a short composition
of two things it does — the useRequestPlayer hook and the PlayerAPIProvider context —
because every control below finds its player through that provider and throws outside it.
Everything inside it is the SDK itself.
import { components, context, hooks } from '@video/video-client-react';
function Player({ source, children }) {
const playerAPI = hooks.useRequestPlayer({ source });
// Render nothing SDK-shaped until the manifest resolves: the controls call
// usePlayerAPI(), which throws rather than returning null.
if (playerAPI === null) return <div className="placeholder" />;
return (
<context.PlayerAPIProvider playerAPI={playerAPI}>
<components.Video muted playsInline />
{children}
</context.PlayerAPIProvider>
);
}
source must be an absolute URLrequestPlayer decides whether a source is HLS with
new URL(source).pathname.endsWith('.m3u8') inside a try/catch. A relative path throws,
the error is swallowed, and the player silently falls back to a non-HLS provider — the video
and controls still render, nothing errors, and QualitySelect lists no levels. Resolve
against your origin.
Components
Each control is a separate component that finds the player through context. Which ones you include, and in what order, is the whole API.
| Component | What it does | Requires |
|---|---|---|
TogglePlayButton | Play/pause in one button. Takes playing and paused objects, named for the state moved to | — |
ResumePlaybackButton | Starts playback — the play half of TogglePlayButton | — |
PausePlaybackButton | Pauses playback — the pause half of TogglePlayButton | — |
ToggleMuteButton | Mute/unmute in one button | — |
MuteAudioButton | Mutes — one half of ToggleMuteButton, for UIs showing both actions at once | — |
UnmuteAudioButton | Unmutes — the other half | — |
VolumeRange | Volume slider, committing on release rather than on drag | — |
PositionRange | Scrub bar | A seekable source |
QualitySelect | Rendition picker, listing what the manifest advertises | A multi-variant source |
FullScreenButton | Promotes the video element to fullscreen | — |
AspectRatioSelect | Aspect-ratio picker | — |
Video | The video element itself. Player renders one; use it directly for your own chrome | — |
PosterImage | Still frame shown before playback | A poster URL |
Customizing a control
Three mechanisms, each with a preset above:
childrenreplace a button's label. The base buttons renderchildren ?? "Play", so anything you pass wins. Keep anaria-labelwhen the child is a glyph.styleand other DOM props reach the element through the rest props, so they compose with the SDK's own class.classNamereplaces the SDK's class outright — you own the whole look, including the border and padding it used to provide.
Symptoms and causes
| Symptom | Cause |
|---|---|
QualitySelect renders an empty dropdown | The source advertises one rendition, or it is a relative URL and no manifest was parsed — see the warning above |
Error: must be used within a <PlayerProvider /> | A control is rendered beside Player rather than inside it. Every control calls usePlayerAPI(), which throws rather than returning null |
| Nothing plays outside Safari | Safari plays HLS natively; other browsers need hls.js, which the SDK declares as an optional peer dependency and does not install for you |
Capture and call components
The package also ships capture and call components — VideoSourceSelect,
AudioSourceSelect, ResolutionSelect, ToggleCameraButton, ToggleMicButton,
EnableCameraButton, DisableCameraButton, EnableMicButton, DisableMicButton,
CreateCallButton, JoinCallButton, EndCallButton, StartBroadcastButton,
EndBroadcastButton — plus the usePreviewPlayer, useScreensharePlayer, useMultiStream
and useCallPeers hooks.
The capture half is live on the camera and microphone playground. Full props for everything are in the SDK reference.
Version notes
classNames has no effect in 1.1.4The components accept a classNames prop, but it is discarded before it reaches the DOM: the
button wrappers merge it and then their *Base component passes the SDK default on instead,
and VolumeRange drops it outright. Use className until this is fixed upstream.