@tiwz/react-video-player
v2.0.7
Published
A React component for playing video
Downloads
2,254
Readme
@tiwz/react-video-player
A modern, fully-featured, and mobile-friendly React video player component with custom controls, double-tap seek, keyboard shortcuts, fullscreen, Picture-in-Picture (PiP), subtitles, and smooth UX — built for both desktop and mobile.
✨ Features
- 🎮 Custom video controls (no native controls UI)
- 📱 Mobile optimized (double-tap to seek ±10s, touch to toggle controls)
- ⌨️ Keyboard shortcuts support (desktop)
- 🖥 Fullscreen & Picture-in-Picture (PiP)
- 🔊 Volume control + mute toggle
- 🎯 Multi-quality source switching (resumes from same timestamp)
- ⚡ Playback speed control (0.25x – 4x)
- 📡 HLS streaming support (built-in, no extra install needed)
- 🕒 Seek bar with buffered progress indicator
- 💬 Subtitle / caption support (VTT format)
- 🚀 Smooth UX with throttled interactions
- 💡 Auto-hide controls on inactivity
- 🧭 Landscape lock on fullscreen (mobile)
- 🔄 Loading indicator on buffering
- ❌ Error state UI when video fails to load
- 🧩 Fully typed with TypeScript
📦 Installation
npm install @tiwz/react-video-playeror
bun add @tiwz/react-video-playeror
yarn add @tiwz/react-video-player🚀 Quick Start
import { VideoPlayer } from '@tiwz/react-video-player'
import '@tiwz/react-video-player/style.css'
export default function App() {
return (
<VideoPlayer
title="Demo Video"
source="https://www.w3schools.com/html/mov_bbb.mp4"
/>
)
}🧩 Props
VideoPlayerProps
| Prop | Type | Required | Description |
|------|------|----------|-------------|
| source | string \| VideoSourceQuality[] | ✅ | Single URL or array of quality sources |
| title | string | ❌ | Video title shown in top bar |
| poster | string | ❌ | Thumbnail image shown before playback |
| hls | boolean \| Partial<HlsConfig> | ❌ | Enable HLS streaming |
| track | VideoTrack | ❌ | Subtitle / caption track (VTT format) |
VideoSourceQuality
type VideoSourceQuality = {
src: string // Video URL
quality: number // e.g. 1080, 720, 480. Use 0 for Auto
}VideoTrack
type VideoTrack = {
src: string // URL to .vtt subtitle file
lang: string // BCP 47 language tag, e.g. 'en', 'th'
}Example with multiple qualities:
<VideoPlayer
title="My Video"
poster="/thumbnail.jpg"
source={[
{ src: '/video-1080p.mp4', quality: 1080 },
{ src: '/video-720p.mp4', quality: 720 },
{ src: '/video-480p.mp4', quality: 480 },
{ src: '/video-auto.mp4', quality: 0 }, // Auto
]}
/>Quality sources are automatically sorted highest to lowest. Switching quality resumes from the same timestamp.
💬 Subtitles
Subtitle support uses the WebVTT format. Pass a track prop with the URL to your .vtt file and the language code.
<VideoPlayer
title="My Video"
source="/video.mp4"
track={{ src: '/subtitles-en.vtt', lang: 'en' }}
/>Users can toggle subtitles on/off from the Settings panel in the player. Subtitles are displayed as an overlay above the controls, and will float up when the control bar is visible.
Note: The
.vttfile must be served from the same origin or with CORS headers to be loaded correctly by the browser.
📡 HLS Streaming
HLS support is built-in — no extra packages needed.
// Basic HLS
<VideoPlayer
title="Live Stream"
source="/stream.m3u8"
hls
/>
// HLS with custom config
<VideoPlayer
title="Live Stream"
source="/stream.m3u8"
hls={{ maxBufferLength: 30 }}
/>Safari uses native HLS automatically — hls.js is bypassed on Safari.
🎥 Player Controls
Desktop
| Action | Control |
|--------|---------|
| Play / Pause | Click center or Space |
| Seek backward 10s | ← Arrow |
| Seek forward 10s | → Arrow |
| Toggle fullscreen | F |
| Toggle Picture-in-Picture | P |
Mobile
| Gesture | Action | |---------|--------| | Single tap | Show / hide controls | | Double tap left | Seek backward 10s | | Double tap right | Seek forward 10s | | Consecutive taps | Stacked seek (±20s, ±30s, ...) | | Drag seek bar | Seek with live preview |
⚙️ Settings Panel
The gear icon opens the settings panel with the following options:
| Setting | Description |
|---------|-------------|
| Video quality | Switch between available quality levels (shown only when multiple sources are provided) |
| Playback speed | Adjust speed from 0.25x to 4x |
| Subtitle | Toggle subtitles on/off (shown only when a track is provided) |
🖥 Fullscreen
Supports all modern browsers including:
- Chrome / Edge / Firefox
- Safari (desktop)
- Mobile Safari / Chrome Android
Includes automatic orientation lock to landscape for landscape videos on mobile.
📺 Picture-in-Picture (PiP)
Works on:
- Chrome / Edge
- Safari (desktop & iPadOS)
Automatically resumes playback when entering PiP if the video is paused.
⚡ Performance
- Throttled mouse movement (200ms)
- Optimized re-rendering via
useReducer+useRef - Stale closure prevention with refs for hot-path callbacks
- Smart seek stacking with auto-reset
- Minimal event listeners
🧪 Browser Support
| Browser | Fullscreen | PiP | HLS | Subtitles | Orientation Lock | |---------|-----------|-----|-----|-----------|-----------------| | Chrome | ✅ | ✅ | ✅ | ✅ | ✅ | | Edge | ✅ | ✅ | ✅ | ✅ | ✅ | | Firefox | ✅ | ✅ | ✅ | ✅ | ⚠️ Partial | | Safari (desktop) | ✅ | ✅ | ✅ (native) | ✅ | — | | Mobile Safari | ✅ | ✅ (iPadOS) | ✅ (native) | ✅ | ✅ | | Chrome Android | ✅ | ✅ | ✅ | ✅ | ✅ |
📄 License
MIT © 2026 tiwz
