Modern, customizable video player for Next.js applications with adaptive streaming, mobile optimization, and advanced features.
- π― Next.js 15+ App Router Ready
- π± Mobile-First Design with VK Player-inspired controls
- π¬ Adaptive Streaming (HLS.js & Dash.js support)
- πΌοΈ Thumbnail Previews with sprite sheet support
- π¨ Highly Customizable with TypeScript configuration
- π Touch Gestures optimized for mobile
- β‘ Performance Optimized with lazy loading
- πͺ Single Official Preset (
default) with per-instance overrides - π Built-in Analytics tracking
- βΏ Accessibility compliant
# Using npm
npm install @madraka/nextjs-videoplayer
# Using pnpm
pnpm add @madraka/nextjs-videoplayer
# Using yarn
yarn add @madraka/nextjs-videoplayer
# Install directly from GitHub
npm install github:Madraka/nextjs-videoplayer
pnpm add github:Madraka/nextjs-videoplayer
yarn add github:Madraka/nextjs-videoplayer'use client';
import { ConfigurableVideoPlayer } from '@madraka/nextjs-videoplayer';
export default function MyVideoPage() {
return (
<div className="max-w-4xl mx-auto p-4">
<ConfigurableVideoPlayer
src="https://example.com/video.m3u8"
poster="https://example.com/poster.jpg"
aspectRatio="16/9"
/>
</div>
);
}'use client';
import {
ConfigurableVideoPlayer,
PlayerConfigProvider,
PlayerPresets
} from '@madraka/nextjs-videoplayer';
export default function AdvancedVideoPage() {
return (
<PlayerConfigProvider config={PlayerPresets.default}>
<ConfigurableVideoPlayer
src="https://example.com/video.m3u8"
thumbnailUrl="https://example.com/thumbnails/"
aspectRatio="16/9"
autoPlay={false}
muted={false}
onPlay={() => console.log('Video started playing')}
onPause={() => console.log('Video paused')}
/>
</PlayerConfigProvider>
);
}| Prop | Type | Default | Description |
|---|---|---|---|
src |
string |
- | Video source URL (HLS, DASH, MP4) |
poster |
string |
- | Poster image URL |
thumbnailUrl |
string |
- | Base URL for thumbnail previews |
aspectRatio |
'auto' | '16/9' | '4/3' | '1/1' | '9/16' |
'auto' |
Video aspect ratio |
autoPlay |
boolean |
false |
Auto-play video |
muted |
boolean |
false |
Start muted |
loop |
boolean |
false |
Loop video |
playsInline |
boolean |
true |
Plays inline on mobile |
<ConfigurableVideoPlayer
src="video.m3u8"
onReady={() => console.log('Player ready')}
onPlay={() => console.log('Playing')}
onPause={() => console.log('Paused')}
onError={(error) => console.error('Error:', error)}
onTimeUpdate={(currentTime, duration) => {
console.log(`${currentTime}s / ${duration}s`);
}}
/>Use the official default setup:
import { PlayerPresets } from '@madraka/nextjs-videoplayer';
<PlayerConfigProvider config={PlayerPresets.default}>Create custom configurations for different use cases:
import { PlayerConfig } from '@madraka/nextjs-videoplayer';
const customConfig: PlayerConfig = {
theme: {
primaryColor: '#3b82f6',
backgroundColor: '#000000',
controlsOpacity: 0.8,
},
controls: {
showPlayButton: true,
showVolumeControl: true,
showProgressBar: true,
showFullscreenButton: true,
showSettingsButton: true,
autoHide: true,
autoHideDelay: 3000,
},
playback: {
autoPlay: false,
muted: false,
loop: false,
playsInline: true,
preload: 'metadata',
},
gestures: {
enabled: true,
doubleTapToSeek: true,
swipeToSeek: true,
pinchToZoom: false,
},
analytics: {
enabled: true,
trackPlay: true,
trackPause: true,
trackSeek: true,
trackQualityChange: true,
}
};
<PlayerConfigProvider config={customConfig}>
<ConfigurableVideoPlayer src="video.m3u8" />
</PlayerConfigProvider>The player automatically detects and handles multiple video formats:
- HLS (.m3u8) - HTTP Live Streaming for adaptive bitrate
- DASH (.mpd) - Dynamic Adaptive Streaming over HTTP
- MP4 - Standard progressive download
- WebM - Modern web video format
- MOV - QuickTime format
// HLS Stream
<ConfigurableVideoPlayer src="https://example.com/stream.m3u8" />
// DASH Stream
<ConfigurableVideoPlayer src="https://example.com/stream.mpd" />
// Progressive MP4
<ConfigurableVideoPlayer src="https://example.com/video.mp4" />
// Multiple sources with fallback
<ConfigurableVideoPlayer
src={[
{ src: "video.m3u8", type: "application/x-mpegURL" },
{ src: "video.mp4", type: "video/mp4" }
]}
/>The player works seamlessly with Tailwind CSS:
<ConfigurableVideoPlayer
src="video.m3u8"
className="rounded-lg shadow-xl"
aspectRatio="16/9"
/>The player automatically detects mobile devices and provides:
- Touch-optimized controls
- Gesture support (tap, double-tap, swipe)
- Auto-hide controls
- Responsive layout
- Mobile-first design
const analyticsConfig = {
analytics: {
enabled: true,
trackPlay: true,
trackPause: true,
trackSeek: true,
trackQualityChange: true
}
};Space- Play/PauseF- FullscreenM- Mute/Unmuteβ/β- Seek backward/forwardβ/β- Volume up/down
<ConfigurableVideoPlayer
src="video.m3u8"
thumbnailUrl="https://cdn.example.com/thumbnails/"
// Expects thumbnails at: thumbnailUrl + "sprite.jpg"
// And thumbnails.vtt for timing information
/># Clone the repository
git clone https://github.com/madraka/nextjs-videoplayer.git
# Install dependencies
pnpm install
# Start showcase development server
pnpm dev
# Build showcase
pnpm build
# Build npm package
pnpm build:package
# Run package tests
pnpm testThis repository uses two separate GitHub Actions workflows:
-
Showcase CI(.github/workflows/showcase-ci.yml)- Runs on
pushandpull_requesttomain - Validates showcase quality:
lint,type-check,build - Does not publish to npm
- Runs on
-
Package Publish(.github/workflows/package-publish.yml)- Runs on version tags like
v1.2.3 - Validates package quality and runs
build:package - Publishes to npm and creates a GitHub Release
- Runs on version tags like
This keeps Vercel showcase deployment and npm package publishing isolated.
- Workspace scaffolding is active via
pnpm-workspace.yaml. - Active layout:
apps/showcase(Next.js showcase app)packages/player(publishable npm package)
- Root scripts orchestrate both workspaces.
- Migration plan and phases are documented in
docs/ROADMAP.md.
- Root
vercel.jsonnow builds the showcase app fromapps/showcase. - Build command:
pnpm -C apps/showcase build - Output directory:
apps/showcase/.next
# Option A (automated release script)
pnpm release:patch
# or
pnpm release:minor
pnpm release:major
# Option B (changesets-first workflow)
pnpm changeset
pnpm changeset:version
pnpm release:check
pnpm release:tagWhen the vX.Y.Z tag is pushed, Package Publish handles npm publish + GitHub release.
For direct GitHub installation:
# Latest from main branch
npm install github:Madraka/nextjs-videoplayer
# Specific version/tag
npm install github:Madraka/nextjs-videoplayer#v1.0.0
# In package.json
{
"dependencies": {
"@madraka/nextjs-videoplayer": "github:Madraka/nextjs-videoplayer#v1.0.0"
}
}nextjs-videoplayer/
βββ apps/
β βββ showcase/ # Next.js showcase app
βββ packages/
β βββ player/ # Publishable npm package (@madraka/nextjs-videoplayer)
βββ docs/
βββ pnpm-workspace.yaml
βββ turbo.json
Contributions are welcome! Please read our Contributing Guide for details.
MIT License - see LICENSE file for details.
- Inspired by VK Player for mobile UX
- Built with HLS.js and Dash.js
- UI components by Radix UI
- Styled with Tailwind CSS
Made with β€οΈ for the Next.js community