Skip to content

Repository files navigation

🎬 Modern Video Player

A modern, feature-rich HTML5 video player library built with TypeScript, Tailwind CSS, and the latest web technologies.

✨ Features

  • 🎯 TypeScript - Full type safety and IntelliSense support
  • Tailwind CSS - Modern utility-first styling
  • 🎨 Custom Controls - Beautiful, customizable player controls
  • ⌨️ Keyboard Shortcuts - YouTube-style keyboard navigation
  • 📱 Responsive - Works perfectly on all devices
  • 🎭 Themes - Built-in light, dark, and auto themes
  • 🖼️ Picture-in-Picture - Native PiP support
  • Fullscreen - Full native fullscreen support
  • Playback Speed - Adjustable playback rates
  • 🎚️ Volume Control - Fine-grained volume control
  • 📊 Progress Bar - Interactive seeking with buffer display
  • 🎯 Multiple Qualities - Support for quality switching
  • 🔄 Event System - Rich event system for all player actions
  • 📦 Zero Runtime Dependencies - Pure TypeScript, minimal dependencies
  • 🚀 Modern Build - Built with Vite for optimal performance

📦 Installation

npm install @videoplayer/core

🚀 Quick Start

import { VideoPlayer } from '@videoplayer/core';
import '@videoplayer/core/style.css';

const player = new VideoPlayer('#player', {
  src: 'https://example.com/video.mp4',
  poster: 'https://example.com/poster.jpg',
  controls: true,
  autoplay: false,
  volume: 1,
  theme: 'dark',
});

// Listen to events
player.on('play', (state) => {
  console.log('Video playing!', state);
});

// Control playback
player.play();
player.pause();
player.seek(120);

🎮 API Reference

Constructor

new VideoPlayer(container: HTMLElement | string, options: VideoPlayerOptions)

Options

interface VideoPlayerOptions {
  src: string | VideoSource[];           // Video source(s)
  controls?: boolean;                     // Show controls (default: true)
  autoplay?: boolean;                     // Autoplay (default: false)
  loop?: boolean;                         // Loop playback (default: false)
  muted?: boolean;                        // Start muted (default: false)
  volume?: number;                        // Initial volume 0-1 (default: 1)
  poster?: string;                        // Poster image URL
  playbackRate?: number;                  // Initial playback rate (default: 1)
  enablePIP?: boolean;                    // Enable PiP (default: true)
  enableFullscreen?: boolean;             // Enable fullscreen (default: true)
  theme?: 'light' | 'dark' | 'auto';     // Theme (default: 'dark')
  showQualitySelector?: boolean;          // Show quality selector (default: false)
  keyboardShortcuts?: boolean;            // Enable shortcuts (default: true)
  subtitles?: SubtitleTrack[];            // Subtitle tracks
  enableThumbnails?: boolean;             // Enable thumbnails (default: false)
  thumbnailInterval?: number;             // Thumbnail interval in seconds (default: 5)
  customStyles?: CustomStyleOptions;      // Custom colors and styling
}

Methods

Playback Control

  • play(): Promise<void> - Play the video
  • pause(): void - Pause the video
  • togglePlay(): void - Toggle play/pause
  • seek(time: number): void - Seek to specific time in seconds

Volume Control

  • setVolume(volume: number): void - Set volume (0-1)
  • toggleMute(): void - Toggle mute

Playback Speed

  • setPlaybackRate(rate: number): void - Set playback rate
  • cyclePlaybackRate(): void - Cycle through common rates

Display

  • toggleFullscreen(): Promise<void> - Toggle fullscreen mode
  • togglePIP(): Promise<void> - Toggle Picture-in-Picture

Quality

  • setQuality(quality: string): void - Change video quality

State & Events

  • getState(): PlayerState - Get current player state
  • on(event: PlayerEventType, callback: EventCallback): void - Add event listener
  • off(event: PlayerEventType, callback: EventCallback): void - Remove event listener

Lifecycle

  • destroy(): void - Destroy the player instance

Events

type PlayerEventType =
  | 'play'              // Video started playing
  | 'pause'             // Video paused
  | 'ended'             // Video ended
  | 'timeupdate'        // Playback time changed
  | 'volumechange'      // Volume changed
  | 'ratechange'        // Playback rate changed
  | 'seeking'           // Seeking started
  | 'seeked'            // Seeking completed
  | 'waiting'           // Waiting for data
  | 'canplay'           // Can start playing
  | 'error'             // Error occurred
  | 'fullscreenchange'  // Fullscreen toggled
  | 'pipchange'         // PiP toggled
  | 'qualitychange';    // Quality changed

⌨️ Keyboard Shortcuts

  • Space / K - Play/Pause
  • - Seek backward 5 seconds
  • - Seek forward 5 seconds
  • - Increase volume
  • - Decrease volume
  • M - Toggle mute
  • F - Toggle fullscreen
  • P - Toggle Picture-in-Picture

🎨 Theming

The player supports a fully customizable color system with automatic dark mode support using CSS custom properties:

Color Palette

The player uses a purple-based color palette with 11 shades (50-950):

--color-primary-50: #fbf4ff;
--color-primary-100: #f7e9fe;
--color-primary-200: #eed2fc;
--color-primary-300: #e3aef9;
--color-primary-400: #d47df5;
--color-primary-500: #be4ce9;
--color-primary-600: #a52ccd; /* Primary accent */
--color-primary-700: #8b21ab;
--color-primary-800: #731d8b;
--color-primary-900: #611d72;
--color-primary-950: #3e064c;

Theme Switching

Toggle between light and dark mode programmatically:

import { initTheme, setTheme, toggleTheme, getCurrentTheme } from '@videoplayer/core';

// Initialize theme from localStorage or system preference
initTheme();

// Set a specific theme
setTheme('dark'); // or 'light'

// Toggle between themes
toggleTheme();

// Get current theme
const theme = getCurrentTheme(); // returns 'light' or 'dark'

// Watch for system theme changes
const unwatch = watchSystemTheme((theme) => {
  console.log('System theme changed to:', theme);
});

// Cleanup when done
unwatch();

Customizing Colors

Override CSS variables in your own stylesheet:

:root {
  /* Change primary color to blue */
  --color-primary-600: #2563eb;
  --color-primary-700: #1d4ed8;
  
  /* Custom text colors */
  --color-primary_txt: #1a1a1a;
  --color-secondary_txt: #666666;
}

[data-theme="dark"] {
  /* Dark mode overrides */
  --color-primary_txt: #ffffff;
  --color-card_bg: #1a1a1a;
}

Available CSS Variables

Colors

  • --color-primary-{50-950} - Primary color palette
  • --color-link_txt - Link text color
  • --color-primary_txt - Primary text color
  • --color-secondary_txt - Secondary text color
  • --color-tertiary_txt - Tertiary text color

Backgrounds

  • --color-primary_bg - Primary background
  • --color-card_bg - Card background
  • --color-surface - Surface background
  • --color-hover_bg - Hover state background
  • --color-primary_active_bg - Active state background

Borders

  • --color-primary_border - Primary border
  • --color-secondary_border - Secondary border
  • --color-tertiary_border - Tertiary border
  • --color-primary_active_border - Active state border

Tailwind Integration

The color system is integrated with Tailwind CSS:

// tailwind.config.js
export default {
  darkMode: ['class', '[data-theme="dark"]'],
  theme: {
    extend: {
      colors: {
        primary: {
          50: 'var(--color-primary-50)',
          600: 'var(--color-primary-600)',
          // ... etc
        },
      },
      backgroundColor: {
        'surface': 'var(--color-surface)',
        'card': 'var(--color-card_bg)',
      },
    },
  },
}

🎨 Custom Styling

The video player supports extensive customization through the customStyles option, allowing you to change colors, button styles, and other visual elements without modifying CSS files.

Basic Example

const player = new VideoPlayer('#player', {
  src: 'video.mp4',
  controls: true,
  customStyles: {
    primaryColor: '#ff6b6b',
    buttonBackground: 'rgba(255, 107, 107, 0.2)',
    buttonBackgroundHover: 'rgba(255, 107, 107, 0.35)',
    buttonBorderRadius: '12px',
    progressColor: '#ff6b6b',
  }
});

Available Custom Style Options

interface CustomStyleOptions {
  // Primary accent color (used throughout the player)
  primaryColor?: string;
  
  // Button styling
  buttonBackground?: string;        // Button background color
  buttonBackgroundHover?: string;   // Button background on hover
  buttonColor?: string;             // Button icon/text color
  buttonBorder?: string;            // Button border color
  buttonBorderRadius?: string;      // Button corner radius (e.g., '8px', '50%')
  
  // Progress bar
  progressColor?: string;           // Progress bar fill color
  progressBackground?: string;      // Progress bar background
  
  // Volume slider
  volumeColor?: string;             // Volume slider color
  
  // Dropdown menus (quality, speed, subtitles)
  menuBackground?: string;          // Menu background color
  menuColor?: string;               // Menu text color
  menuItemHoverBackground?: string; // Menu item hover background
  activeMenuItemColor?: string;     // Active menu item color
  
  // Controls overlay
  controlsBackground?: string;      // Controls gradient background
}

Complete Customization Example

const player = new VideoPlayer('#player', {
  src: 'your-video.mp4',
  controls: true,
  customStyles: {
    // Brand color throughout
    primaryColor: '#00d4ff',
    
    // Glassmorphism buttons with cyan tint
    buttonBackground: 'rgba(0, 212, 255, 0.15)',
    buttonBackgroundHover: 'rgba(0, 212, 255, 0.25)',
    buttonColor: '#ffffff',
    buttonBorder: 'rgba(0, 212, 255, 0.3)',
    buttonBorderRadius: '16px',
    
    // Matching progress bar
    progressColor: '#00d4ff',
    progressBackground: 'rgba(255, 255, 255, 0.2)',
    
    // Volume slider to match
    volumeColor: '#00d4ff',
    
    // Dark menus with cyan accents
    menuBackground: 'rgba(10, 10, 15, 0.98)',
    menuColor: '#ffffff',
    menuItemHoverBackground: 'rgba(0, 212, 255, 0.2)',
    activeMenuItemColor: '#00d4ff',
    
    // Custom controls gradient
    controlsBackground: 'linear-gradient(to top, rgba(0, 20, 30, 0.95) 0%, rgba(0, 20, 30, 0.3) 50%, transparent 100%)'
  }
});

Preset Examples

Netflix Style

customStyles: {
  primaryColor: '#e50914',
  buttonBackground: 'rgba(229, 9, 20, 0.1)',
  buttonBackgroundHover: 'rgba(229, 9, 20, 0.2)',
  buttonBorderRadius: '4px',
  progressColor: '#e50914',
  menuBackground: 'rgba(0, 0, 0, 0.95)',
  activeMenuItemColor: '#e50914',
}

YouTube Style

customStyles: {
  primaryColor: '#ff0000',
  buttonBackground: 'transparent',
  buttonBackgroundHover: 'rgba(255, 255, 255, 0.1)',
  buttonBorder: 'transparent',
  buttonBorderRadius: '50%',
  progressColor: '#ff0000',
  progressBackground: 'rgba(255, 255, 255, 0.4)',
  volumeColor: '#ffffff',
}

Modern Minimal

customStyles: {
  primaryColor: '#6366f1',
  buttonBackground: 'rgba(99, 102, 241, 0.08)',
  buttonBackgroundHover: 'rgba(99, 102, 241, 0.15)',
  buttonBorder: 'rgba(99, 102, 241, 0.2)',
  buttonBorderRadius: '10px',
  progressColor: '#6366f1',
  menuBackground: 'rgba(255, 255, 255, 0.98)',
  menuColor: '#1f2937',
  activeMenuItemColor: '#6366f1',
}

Tips

  • Colors can be in any CSS format: hex (#ff6b6b), rgb (rgb(255, 107, 107)), rgba (rgba(255, 107, 107, 0.5)), or named colors
  • Use CSS gradients for controlsBackground to create custom overlay effects
  • Border radius accepts any CSS unit: px, rem, %
  • All options are optional - only specify what you want to customize
  • Custom styles work with both light and dark themes

🛠️ Development

# Install dependencies
npm install

# Start development server
npm run dev

# Build library
npm run build

# Run tests
npm run test

# Lint code
npm run lint

# Format code
npm run format

📝 Examples

Multiple Quality Sources

const player = new VideoPlayer('#player', {
  src: [
    { src: 'video-1080p.mp4', quality: '1080p', label: 'Full HD' },
    { src: 'video-720p.mp4', quality: '720p', label: 'HD' },
    { src: 'video-480p.mp4', quality: '480p', label: 'SD' },
  ],
  showQualitySelector: true,
});

Event Handling

player.on('play', (state) => {
  console.log('Playing at', state.currentTime);
});

player.on('ended', (state) => {
  console.log('Video ended');
  // Auto-play next video
});

player.on('error', (state) => {
  console.error('Playback error');
});

Programmatic Control

// Play from specific time
player.seek(60);
await player.play();

// Set to 2x speed
player.setPlaybackRate(2);

// Enter fullscreen
await player.toggleFullscreen();

// Get current state
- [Tailwind CSS](https://tailwindcss.com/)
- [PostCSS](https://postcss.org/)
const state = player.getState();
console.log(`Playing: ${state.playing}`);
console.log(`Time: ${state.currentTime}/${state.duration}`);

🤝 Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

📄 License

MIT License - feel free to use this in your projects!

🙏 Credits

Built with modern web technologies:


Made with ❤️ by the community

About

A video player with multiple features by Inleed

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages