The video player your brand deserves
Lightweight, production-ready, and dependency-free. Supports local files, YouTube, Vimeo, and Bilibili — with playlists, captions, chapters, ref API, and analytics callbacks built in.
npm i vplayer-reactZero Dependencies
No external packages required. Pure React with inline styles. Keeps your bundle lean.
Universal Sources
Local video files, YouTube, Vimeo, and Bilibili — all from one unified component.
Brand Configurable
Change accent and icon colors with a single prop. Match your brand perfectly.
Playlist & Controlled Index
Pass a URL array for auto-advance, or control the active track externally with activeIndex + onIndexChange.
Ref API
Programmatic control via play(), pause(), seek(), setVolume(), toggleFullscreen() and more.
Captions & Chapters
WebVTT subtitle tracks with a CC picker, plus chapter tick marks and labels on the progress bar.
Error Handling
Built-in error overlay UI with onError callback. No more silent failures on broken URLs.
Analytics Callbacks
onBuffer, onMilestone, onSeek, onChapterChange, onVolumeChange, onError — everything you need for video analytics.
Resume & Persist
initialTime to resume playback. persistVolume to remember volume across page reloads via localStorage.
Keyboard First
Full keyboard controls scoped to the player. Fully remappable via the keymap prop — or disable any key.
Performance Optimized
Lazy-loaded embeds, metadata-only preload, and no layout shift. Excellent Core Web Vitals.
Accessible & Mobile
ARIA labels, focus management, touch scrubbing, iOS fullscreen, and mobile-optimized controls built in.
Interactive Demo
Switch between sources and customize the accent color in real time. The Native MP4 tab demos playlist, chapter markers, and live analytics callbacks.
No More Barrier to Cross
Local MP4 playlist with chapters, captions, ref API, and all callbacks
Ref API Controls
Feature Toggles
Track
1 / 2
Chapter
—
Volume
100%
Buffered
Milestones
Callback Log
Interact with the player to see callback events here
Brand Accent Color
Quick Start
Install and start using in under a minute.
npm install vplayer-reactimport { VPlayer } from 'vplayer-react';
export default function Page() {
return (
<VPlayer
src="https://example.com/video.mp4"
poster="/poster.jpg"
title="My Video"
accentColor="#e11d48"
iconColor="#ffffff"
aspectRatio="16:9"
/>
);
}// Pass an array of URLs for playlist mode.
// Prev / Next buttons appear automatically.
<VPlayer
src={[
"/episode-1.mp4",
"/episode-2.mp4",
"/episode-3.mp4",
]}
title="My Series"
loopPlaylist // wraps back to track 1 after the last
onNext={() => console.log("advanced")}
onPrev={() => console.log("went back")}
/>// Drive the active track from your own UI
const [track, setTrack] = useState(0);
<VPlayer
src={episodes.map(e => e.url)}
activeIndex={track}
onIndexChange={(i) => setTrack(i)}
/>
{/* Sidebar episode list */}
<ul>
{episodes.map((ep, i) => (
<li key={i} onClick={() => setTrack(i)}>
{ep.title}
</li>
))}
</ul>import { useRef } from 'react';
import { VPlayer, type VPlayerHandle } from 'vplayer-react';
function MyPlayer() {
const ref = useRef<VPlayerHandle>(null);
return (
<>
<VPlayer ref={ref} src="/video.mp4" />
<button onClick={() => ref.current?.play()}>Play</button>
<button onClick={() => ref.current?.pause()}>Pause</button>
<button onClick={() => ref.current?.seek(60)}>1:00</button>
</>
);
}// Start playback at a specific timestamp
// Great for "continue where you left off" flows
<VPlayer
src="/movie.mp4"
initialTime={1234} // starts at 20:34
persistVolume // remembers volume across reloads
/>// Subtitles / closed captions via WebVTT tracks.
// CC button appears automatically in the control bar.
<VPlayer
src="/video.mp4"
tracks={[
{ src: "/en.vtt", label: "English", lang: "en", default: true },
{ src: "/es.vtt", label: "Espanol", lang: "es" },
]}
/>// Tick marks on the progress bar; hover for chapter label.
// Shift+Left / Shift+Right to jump between chapters.
<VPlayer
src="/documentary.mp4"
chapters={[
{ time: 0, label: "Introduction" },
{ time: 120, label: "Act I" },
{ time: 360, label: "Act II" },
{ time: 600, label: "Finale" },
]}
onChapterChange={(ch) => console.log("Now:", ch?.label)}
/>// Analytics-ready callbacks — all fire automatically.
<VPlayer
src="/product-demo.mp4"
onPlay={() => analytics.track("video_play")}
onPause={() => analytics.track("video_pause")}
onEnded={() => analytics.track("video_complete")}
onSeek={(time) => console.log("seeked to", time)}
onBuffer={(pct) => console.log("buffered", pct)}
onMilestone={(pct) => analytics.track("milestone", { pct })}
onVolumeChange={(vol, muted) => console.log({ vol, muted })}
onError={(err) => console.error("error:", err?.code)}
/>// Override any key binding or disable it entirely.
import type { VPlayerKeymap } from 'vplayer-react';
const keymap: VPlayerKeymap = {
play: "p", // p to play/pause instead of Space/K
fullscreen: ["f", "F"], // accept both cases
mute: false, // disable M key completely
};
<VPlayer src="/video.mp4" keymap={keymap} />Keyboard Controls
All shortcuts are scoped to the player. They only work when the player has focus, never hijacking the entire page. Every binding can be remapped or disabled via the keymap prop.
Keyboard Shortcuts
Only active when the player is focused (clicked)