Skip to main content

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.

Live Editor
Editable code. Tab moves focus to the next control instead of inserting an indent.
<Player>
  <TogglePlayButton />
  <ToggleMuteButton />
  <VolumeRange />
</Player>
Result
Loading...

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 URL

requestPlayer 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.

ComponentWhat it doesRequires
TogglePlayButtonPlay/pause in one button. Takes playing and paused objects, named for the state moved to
ResumePlaybackButtonStarts playback — the play half of TogglePlayButton
PausePlaybackButtonPauses playback — the pause half of TogglePlayButton
ToggleMuteButtonMute/unmute in one button
MuteAudioButtonMutes — one half of ToggleMuteButton, for UIs showing both actions at once
UnmuteAudioButtonUnmutes — the other half
VolumeRangeVolume slider, committing on release rather than on drag
PositionRangeScrub barA seekable source
QualitySelectRendition picker, listing what the manifest advertisesA multi-variant source
FullScreenButtonPromotes the video element to fullscreen
AspectRatioSelectAspect-ratio picker
VideoThe video element itself. Player renders one; use it directly for your own chrome
PosterImageStill frame shown before playbackA poster URL

Customizing a control

Three mechanisms, each with a preset above:

  • children replace a button's label. The base buttons render children ?? "Play", so anything you pass wins. Keep an aria-label when the child is a glyph.
  • style and other DOM props reach the element through the rest props, so they compose with the SDK's own class.
  • className replaces the SDK's class outright — you own the whole look, including the border and padding it used to provide.

Symptoms and causes

SymptomCause
QualitySelect renders an empty dropdownThe 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 SafariSafari 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.4

The 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.