VayuUI

VideoPlayer

A fully-featured video player component with playlist support, HLS streaming, and keyboard controls.

Installation

npx vayu-ui-cli@latest add video-player

Usage

Buffering...Loading video…
Big Buck Bunny (HLS)

Big Buck Bunny (HLS)

Blender Foundation

0:000:00
<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>

Anatomy

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)

Accessibility

  • 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

Keyboard shortcuts

KeyAction
Space / kToggle play/pause
mToggle mute
fToggle fullscreen
cToggle captions
ArrowLeftSeek backward 5 seconds
ArrowRightSeek forward 5 seconds
ArrowUpVolume up
ArrowDownVolume down
nNext track
pPrevious track
lToggle loop
sToggle shuffle

Screen reader behavior

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

Component Folder Structure

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

Props

VideoPlayer.Root

PropTypeDefaultDescription
trackVideoTrackInitial single track to play
playlistVideoTrack[]Additional tracks (prepended after track)
defaultVolumenumber0.8Initial volume level (0-1)
defaultMutedbooleanfalseInitial muted state
defaultPlaybackRatenumber1Initial playback speed
allowMultiplebooleanfalseAllow multiple players to play simultaneously
autoPlaybooleanfalseAutomatically start playback on mount
onPlay() => voidCallback when video starts playing
onPause() => voidCallback when video is paused
onTrackChange(track: VideoTrack | null) => voidCallback when active track changes
onTimeUpdate(currentTime: number) => voidCallback when playback time updates
onEnded() => voidCallback when video finishes
onError(error: string) => voidCallback when playback fails
onFullscreenChange(isFullscreen: boolean) => voidCallback when fullscreen state changes

VideoPlayer.Source

PropTypeDefaultDescription
srcstringVideo source URL (required)
titlestringTrack title
artiststringTrack artist
posterstringPoster image URL
subtitleSrcstringSubtitle track URL (VTT format)

VideoPlayer.Video

PropTypeDefaultDescription
posterstringPoster image URL
objectFit"contain" | "cover"Video object fit style

VideoPlayer.Controls

PropTypeDefaultDescription
autoHidebooleanAuto-hide controls when playing
autoHideDelaynumber3000Delay in ms before hiding controls

VideoPlayer.PlayPause

PropTypeDefaultDescription
childrenReactNode | ((playing: boolean) => ReactNode)Custom content or render function

VideoPlayer.Next / VideoPlayer.Previous

No custom props. Extends ButtonHTMLAttributes<HTMLButtonElement>.

VideoPlayer.Seek / VideoPlayer.Progress

PropTypeDefaultDescription
showBufferbooleanShow buffer progress bar
showThumbbooleanShow seek thumb handle (Seek only)

VideoPlayer.Time

PropTypeDefaultDescription
showRemainingbooleanShow remaining time instead of total duration

VideoPlayer.Volume

PropTypeDefaultDescription
verticalbooleanDisplay volume slider vertically

VideoPlayer.Mute

PropTypeDefaultDescription
childrenReactNode | ((muted: boolean) => ReactNode)Custom content or render function

VideoPlayer.Fullscreen / VideoPlayer.PiP / VideoPlayer.Captions

PropTypeDefaultDescription
childrenReactNode | ((state: boolean) => ReactNode)Custom content or render function

VideoPlayer.Quality

No custom props. Extends HTMLAttributes<HTMLSelectElement>. Only rendered when HLS quality levels are available.

VideoPlayer.Speed

PropTypeDefaultDescription
ratesnumber[][0.25, 0.5, 0.75, 1, 1.25, 1.5, 1.75, 2]Available playback speed options

VideoPlayer.Buffer

No custom props. Extends HTMLAttributes<HTMLDivElement>.

VideoPlayer.Playlist

No custom props. Extends HTMLAttributes<HTMLDivElement>.

VideoPlayer.Track

PropTypeDefaultDescription
trackVideoTrackTrack data object (required)
activeClassNamestringClass name for active track
showIndexbooleanShow track index number

VideoPlayer.TrackInfo

PropTypeDefaultDescription
showPosterbooleanDisplay poster image

VideoPlayer.Loading / VideoPlayer.Error

PropTypeDefaultDescription
childrenReactNodeCustom loading/error content

On this page