Ready-made player
VideoPlayer is the complete layout, with features coming from plugins.
VideoPlayer arranges every control for you. It has no plugins of its own, so you decide what's in it and what you pay for.
"use client";import { defaultPlugins, VideoPlayer } from "react-video-kit/player";const sources = [ { src: "/media/sample-720.mp4", type: "video/mp4" }, { src: "/media/sample-360.webm", type: "video/webm" },];const plugins = defaultPlugins();export default function Player() { return <VideoPlayer src={sources} poster="/media/poster.jpg" plugins={plugins} load="visible" />;}Usage
"use client";import { defaultPlugins, VideoPlayer } from "react-video-kit/player";import "react-video-kit/styles.css";const plugins = defaultPlugins();export function Player() { return <VideoPlayer src="/video.mp4" poster="/poster.jpg" plugins={plugins} />;}With no plugins at all, it's still a working player with play, volume, time, and a timeline. defaultPlugins() adds these:
| Plugin | Adds |
|---|---|
idle() | Controls that hide when idle |
gestures() | Click to play, double-tap to seek |
hotkeys() | Keyboard shortcuts |
recovery() | Retries after network errors |
captions() | The captions menu |
speed() | The speed menu |
quality() | The quality menu |
pip() | Picture in picture |
fullscreen() | Fullscreen |
It's only a function returning an array, so add to it, or list your own instead. A captions list needs its options, so replace the default in that case:
const plugins = [ hls(), captions({ tracks: [{ src: "/en.vtt", language: "en", label: "English" }] }), ...defaultPlugins().filter((plugin) => plugin.name !== "captions"),];Importing defaultPlugins costs all nine plugins. Listing them yourself means you only pay for the ones you list.
Give it a title
title names the video above the timeline, eyebrow adds a smaller line over it, and description adds a sentence or two under it. All three fade with the controls, and they hide on small players, where they'd cover the picture.
"use client";import { defaultPlugins, VideoPlayer } from "react-video-kit/player";const plugins = defaultPlugins();export default function PlayerTitle() { return ( <VideoPlayer src="/media/sample-720.mp4" poster="/media/poster.jpg" plugins={plugins} load="visible" eyebrow="Season 1, Episode 1" title="The Green Coast" description="The swell arrives after a thousand miles of open ocean, and meets the first land it has seen in days." /> );}<VideoPlayer src="/video.mp4" plugins={plugins} eyebrow="Season 1, Episode 1" title="The Green Coast" description="The swell arrives after a thousand miles of open ocean."/>The description shows while the video is paused and folds away once it plays, so it isn't in the way. It stops at two lines. For longer text, or for artwork and credits, add the info panel.
When none of the three is set, the title slot takes their place. The playlist plugin fills it from the current item, so the title follows the queue.
Add your own UI
Children render above the media and below the controls, so a custom overlay goes here. Your children can use any hook.
<VideoPlayer src="/video.mp4" plugins={plugins}> <span className="absolute top-3 left-4 text-white">Sponsored</span></VideoPlayer>Configure the video element
media passes props through to the <video>, including its events. tracks takes <track> elements.
<VideoPlayer src="/video.mp4" media={{ loop: true, crossOrigin: "anonymous", onEnded: () => showNext() }}/>Props
The complete player layout: every control, styled. Features come from plugins, and defaultPlugins() is a sensible set. Leaving it out keeps it out of the bundle.
| Prop | Type | Description |
|---|---|---|
| poster? | string | An image for the video element to show before playback starts. |
| media? | Omit<VideoHTMLAttributes<HTMLVideoElement>, "src" | "controls" | "poster"> | Props for the underlying video element. |
| tracks? | ReactNode | <track> elements for the video. |
| title? | ReactNode | The video's name, shown above the timeline with the controls. |
| eyebrow? | ReactNode | A short line above the title, such as a series or an episode. |
| description? | ReactNode | A sentence or two about the video, under the title while it's paused. |
| errorMessages? | Partial<Record<VideoErrorCode, ErrorMessage>> | Replaces the error overlay's text for particular error codes. |
| onError? | ((error: MediaErrorInfo) => void) | Called with every error, fatal or not, for logging. It can change between renders. |
| children? | ReactNode | Content rendered inside the player's root element. |
| src? | SourceInput | null | The video to play, which loads afresh when its value changes. |
| plugins? | readonly AnyPlugin[] | Set once. Define the array outside the component or memoize it. |
| load? | LoadStrategy | When the provider and its engine load. Set once. Defaults to eager. |
| player? | Player | Bring your own player instead of creating one. |