VideoPlayer
A fully-featured video player component with playlist support, HLS streaming, and keyboard controls.
npx vayu-ui-cli@latest add video-player
Buffering...Loading video… 
Big Buck Bunny (HLS)
Blender Foundation
<VideoPlayer.Root
track={tracks[0]}
playlist={tracks}
defaultVolume={0.8}
>
<div className="relative">
<VideoPlayer.Video />
<VideoPlayer.Loading>
<span>Buffering...</span>
</VideoPlayer.Loading>
<VideoPlayer.Error />
</div>
<VideoPlayer.TrackInfo showPoster />
<VideoPlayer.Seek showBuffer showThumb />
<VideoPlayer.Time />
<VideoPlayer.Controls autoHide autoHideDelay={3000}>
<div className="flex items-center justify-between">
<div className="flex items-center gap-1">
<VideoPlayer.Previous />
<VideoPlayer.PlayPause />
<VideoPlayer.Next />
<VideoPlayer.Mute />
<VideoPlayer.Volume />
<VideoPlayer.Captions />
</div>
<div className="flex items-center gap-2">
<VideoPlayer.Speed />
<VideoPlayer.Quality />
<VideoPlayer.PiP />
<VideoPlayer.Fullscreen />
</div>
</div>
</VideoPlayer.Controls>
<VideoPlayer.Playlist>
{tracks.map((track) => (
<VideoPlayer.Track key={track.id} track={track} showIndex />
))}
</VideoPlayer.Playlist>
</VideoPlayer.Root>
VideoPlayer.Root
├── VideoPlayer.Video
├── VideoPlayer.Loading
├── VideoPlayer.Error
├── VideoPlayer.Source (renderless)
├── VideoPlayer.TrackInfo
├── VideoPlayer.Seek (alias: VideoPlayer.Progress)
│ └── VideoPlayer.Buffer
├── VideoPlayer.Time
├── VideoPlayer.Controls
│ ├── VideoPlayer.PlayPause
│ ├── VideoPlayer.Next
│ ├── VideoPlayer.Previous
│ ├── VideoPlayer.Mute
│ ├── VideoPlayer.Volume
│ ├── VideoPlayer.Captions
│ ├── VideoPlayer.Fullscreen
│ ├── VideoPlayer.PiP
│ ├── VideoPlayer.Quality
│ └── VideoPlayer.Speed
└── VideoPlayer.Playlist
└── VideoPlayer.Track (repeated)
└── VideoPlayer.TrackInfo (optional)
- Keyboard navigation is supported via global shortcuts when the player is focused
- All interactive elements have appropriate ARIA labels and roles
- Screen readers announce playback state, track changes, and progress updates
- Supports HLS streams for adaptive bitrate playback
- Focus is managed within the player controls and playlist
| Key | Action |
|---|
Space / k | Toggle play/pause |
m | Toggle mute |
f | Toggle fullscreen |
c | Toggle captions |
ArrowLeft | Seek backward 5 seconds |
ArrowRight | Seek forward 5 seconds |
ArrowUp | Volume up |
ArrowDown | Volume down |
n | Next track |
p | Previous track |
l | Toggle loop |
s | Toggle shuffle |
The root element is marked as a landmark region with role="region" and aria-label="Video Player". Screen readers will:
- Announce "Video Player" when entering the region
- Announce "Play" or "Pause" for the play/pause button based on current state
- Announce "Mute" or "Unmute" for the mute button based on current state
- Announce current video position and duration when seeking (e.g., "1:23 of 5:00")
- Announce "Next Track" and "Previous Track" for navigation buttons
- Announce "Enable captions" or "Disable captions" for the captions button
- Announce "Enter fullscreen" or "Exit fullscreen" for the fullscreen button
- Announce "Enter picture-in-picture" or "Exit picture-in-picture" for the PiP button
- Announce playlist item count and currently selected track
- Announce errors via an alert role when playback fails
- Announce "Loading video..." via a live region when buffering
VideoPlayer/
├── VideoPlayer.tsx # Root component, context provider, all state logic
├── VideoPlayerControls.tsx # Controls container with auto-hide behavior
├── VideoPlayerProgress.tsx # Seek bar, progress bar, time display, buffer
├── VideoPlayerPlayback.tsx # Play/Pause, Next, Previous buttons
├── VideoPlayerVolume.tsx # Volume slider and Mute toggle
├── VideoPlayerAdvanced.tsx # Fullscreen, PiP, Captions, Quality, Speed
├── VideoPlayerPlaylist.tsx # Playlist container, Track items, Source, TrackInfo
├── VideoPlayerStatus.tsx # Loading spinner, Error display
├── Video.tsx # Video element wrapper with registration
├── types.ts # TypeScript interfaces
├── utils.ts # Utility functions (formatTime, isHLS, shuffleArray)
├── index.ts # Public API exports
└── README.md # Component documentation
| Prop | Type | Default | Description |
|---|
track | VideoTrack | — | Initial single track to play |
playlist | VideoTrack[] | — | Additional tracks (prepended after track) |
defaultVolume | number | 0.8 | Initial volume level (0-1) |
defaultMuted | boolean | false | Initial muted state |
defaultPlaybackRate | number | 1 | Initial playback speed |
allowMultiple | boolean | false | Allow multiple players to play simultaneously |
autoPlay | boolean | false | Automatically start playback on mount |
onPlay | () => void | — | Callback when video starts playing |
onPause | () => void | — | Callback when video is paused |
onTrackChange | (track: VideoTrack | null) => void | — | Callback when active track changes |
onTimeUpdate | (currentTime: number) => void | — | Callback when playback time updates |
onEnded | () => void | — | Callback when video finishes |
onError | (error: string) => void | — | Callback when playback fails |
onFullscreenChange | (isFullscreen: boolean) => void | — | Callback when fullscreen state changes |
| Prop | Type | Default | Description |
|---|
src | string | — | Video source URL (required) |
title | string | — | Track title |
artist | string | — | Track artist |
poster | string | — | Poster image URL |
subtitleSrc | string | — | Subtitle track URL (VTT format) |
| Prop | Type | Default | Description |
|---|
poster | string | — | Poster image URL |
objectFit | "contain" | "cover" | — | Video object fit style |
| Prop | Type | Default | Description |
|---|
autoHide | boolean | — | Auto-hide controls when playing |
autoHideDelay | number | 3000 | Delay in ms before hiding controls |
| Prop | Type | Default | Description |
|---|
children | ReactNode | ((playing: boolean) => ReactNode) | — | Custom content or render function |
No custom props. Extends ButtonHTMLAttributes<HTMLButtonElement>.
| Prop | Type | Default | Description |
|---|
showBuffer | boolean | — | Show buffer progress bar |
showThumb | boolean | — | Show seek thumb handle (Seek only) |
| Prop | Type | Default | Description |
|---|
showRemaining | boolean | — | Show remaining time instead of total duration |
| Prop | Type | Default | Description |
|---|
vertical | boolean | — | Display volume slider vertically |
| Prop | Type | Default | Description |
|---|
children | ReactNode | ((muted: boolean) => ReactNode) | — | Custom content or render function |
| Prop | Type | Default | Description |
|---|
children | ReactNode | ((state: boolean) => ReactNode) | — | Custom content or render function |
No custom props. Extends HTMLAttributes<HTMLSelectElement>. Only rendered when HLS quality levels are available.
| Prop | Type | Default | Description |
|---|
rates | number[] | [0.25, 0.5, 0.75, 1, 1.25, 1.5, 1.75, 2] | Available playback speed options |
No custom props. Extends HTMLAttributes<HTMLDivElement>.
No custom props. Extends HTMLAttributes<HTMLDivElement>.
| Prop | Type | Default | Description |
|---|
track | VideoTrack | — | Track data object (required) |
activeClassName | string | — | Class name for active track |
showIndex | boolean | — | Show track index number |
| Prop | Type | Default | Description |
|---|
showPoster | boolean | — | Display poster image |
| Prop | Type | Default | Description |
|---|
children | ReactNode | — | Custom loading/error content |