nextav/docs/planning/ARTPLAYER_DIRECT_PLAYBACK_E...

23 KiB

ArtPlayer Direct Playback Enhancement Plan

Executive Summary

This document outlines the comprehensive plan to maximize direct video playback with ArtPlayer while minimizing transcoding. The strategy follows a progressive enhancement approach: Native → Plugin → DirectStream → Transcode, aiming to achieve 80-90% direct playback for modern video content.

Primary Goals:

  • 🎯 Maximize direct video format support
  • Minimize server transcoding load (60-70% reduction expected)
  • 🚀 Improve user experience (faster startup, better quality)
  • 🔧 Maintain fallback compatibility for unsupported formats

Current State Analysis

Existing Strengths

  • ArtPlayer fully integrated across all pages (/videos, /bookmarks, /folder-viewer)
  • Basic format detection system in video-format-detector.ts
  • Direct streaming API endpoints available (/api/stream/direct/{id})
  • HLS.js integration started (partial implementation)
  • Unified video player architecture via UnifiedVideoPlayer component

Current Limitations

  • Limited codec detection: Only extension-based, no actual codec analysis
  • No browser capability testing: Missing runtime support detection
  • Incomplete plugin support: HLS.js partially implemented, no mpegts.js/flv.js
  • Basic fallback strategy: No progressive enhancement logic
  • Missing format negotiation: No intelligent format selection

📊 Current Format Support Matrix

Format Container Current Support Target Support
MP4 H.264+AAC Direct Direct
WebM VP9+Opus Direct Direct
TS/MPEG-TS H.264+AAC Transcode Plugin (mpegts.js)
MKV H.264+AAC Transcode DirectStream (remux)
AVI Various Transcode ⚠️ Conditional
FLV H.264+AAC Transcode Plugin (flv.js)

Strategic Implementation Plan

Phase 1: Enhanced Format Detection & Browser Capabilities 🔍

Objective

Implement comprehensive format/codec detection with real-time browser capability testing.

Technical Requirements

1.1 Advanced Format Analyzer

interface MediaAnalysis {
  container: string;
  videoCodec: CodecInfo;
  audioCodec: CodecInfo;
  duration: number;
  bitrate: number;
  resolution: { width: number; height: number };
  needsTranscoding: boolean;
}

interface CodecInfo {
  name: string;           // 'h264', 'h265', 'vp9', etc.
  profile?: string;       // 'main', 'high', 'baseline'
  level?: string;         // '4.0', '5.1', etc.
  compatibility: BrowserCompatibility;
}

1.2 Runtime Browser Capability Detection

interface BrowserCapabilities {
  // Video codecs
  h264: boolean;
  h265: boolean;          // Platform dependent
  vp8: boolean;
  vp9: boolean;
  av1: boolean;           // Modern browsers only
  
  // Audio codecs
  aac: boolean;
  mp3: boolean;
  opus: boolean;
  vorbis: boolean;
  
  // Containers
  containers: {
    mp4: boolean;
    webm: boolean;
    ogg: boolean;
    mkv: boolean;         // Always false for browsers
  };
  
  // Advanced features
  mse: boolean;           // Media Source Extensions
  hardwareAcceleration: boolean;
  
  // Browser info
  name: string;           // 'chrome', 'firefox', 'safari'
  version: string;
}

1.3 Implementation Tasks

TODO Items:

  • Create MediaAnalyzer class - Extract actual codec information from video files
  • Implement BrowserCapabilityDetector - Runtime capability testing using HTMLVideoElement.canPlayType()
  • Build codec compatibility matrix - Map codec support across browsers
  • Add hardware acceleration detection - Test for GPU-accelerated decoding
  • Create format scoring system - Rank playback methods by quality/performance

Files to Create:

  • src/lib/media-analyzer.ts - Core media analysis functionality
  • src/lib/browser-capabilities.ts - Browser capability detection
  • src/lib/codec-compatibility.ts - Codec support matrix
  • src/lib/format-scorer.ts - Playback method ranking

Files to Modify:

  • src/lib/video-format-detector.ts - Integrate advanced detection
  • src/components/artplayer-wrapper.tsx - Use enhanced format detection

Phase 2: Progressive Enhancement Strategy 📈

Objective

Implement intelligent format selection following: Native → Plugin → DirectStream → Transcode

Technical Architecture

2.1 Smart Format Selection Engine

class SmartFormatSelector {
  async selectOptimalPlayback(
    media: VideoFile, 
    capabilities: BrowserCapabilities
  ): Promise<PlaybackPlan> {
    
    const analysis = await this.mediaAnalyzer.analyze(media);
    const strategies = [];
    
    // Strategy 1: Native HTML5 support
    if (this.canPlayNatively(analysis, capabilities)) {
      strategies.push({
        method: 'native',
        priority: 1,
        url: `/api/stream/direct/${media.id}`,
        expectedQuality: 'original',
        cpuLoad: 'minimal'
      });
    }
    
    // Strategy 2: External plugin support
    const plugin = this.findSuitablePlugin(analysis, capabilities);
    if (plugin) {
      strategies.push({
        method: 'plugin',
        priority: 2,
        plugin: plugin.name,
        url: `/api/stream/direct/${media.id}`,
        expectedQuality: 'original',
        cpuLoad: 'low'
      });
    }
    
    // Strategy 3: Container remux (DirectStream)
    if (this.canDirectStream(analysis, capabilities)) {
      strategies.push({
        method: 'directstream',
        priority: 3,
        url: `/api/stream/remux/${media.id}`,
        expectedQuality: 'original',
        cpuLoad: 'medium'
      });
    }
    
    // Strategy 4: Full transcoding (last resort)
    strategies.push({
      method: 'transcode',
      priority: 4,
      url: `/api/stream/${media.id}`,
      expectedQuality: 'transcoded',
      cpuLoad: 'high'
    });
    
    // Return best available strategy
    return strategies.sort((a, b) => a.priority - b.priority)[0];
  }
}

2.2 Implementation Tasks

TODO Items:

  • Create SmartFormatSelector class - Core format selection logic
  • Implement native support detection - Test HTML5 video element compatibility
  • Add plugin requirement analysis - Determine when plugins are needed
  • Build DirectStream detection - Identify when container remux is sufficient
  • Create fallback orchestration - Handle failures gracefully

Files to Create:

  • src/lib/smart-format-selector.ts - Main selection engine
  • src/lib/playback-strategies.ts - Strategy definitions and interfaces
  • src/lib/native-support-detector.ts - HTML5 compatibility testing

Files to Modify:

  • src/components/unified-video-player.tsx - Integrate smart selection
  • src/lib/video-format-detector.ts - Replace basic logic with smart selector

Phase 3: External Plugin Integration 🔌

Objective

Integrate external media plugins to maximize format support without transcoding.

Plugin Architecture

3.1 Plugin Support Matrix

const PLUGIN_SUPPORT_MATRIX = {
  'hls.js': {
    priority: 0,           // Highest priority
    formats: ['m3u8', 'hls'],
    codecs: {
      video: ['h264', 'h265'],
      audio: ['aac', 'mp3']
    },
    requirements: {
      mse: true,           // Requires Media Source Extensions
      browser: ['chrome', 'firefox', 'edge'] // Safari has native HLS
    },
    loadMethod: 'import',
    packageName: 'hls.js',
    importPath: 'hls.js/dist/hls.min.js'
  },
  
  'mpegts.js': {
    priority: 1,
    formats: ['ts', 'm2ts', 'mts'],
    codecs: {
      video: ['h264', 'h265'],
      audio: ['aac', 'mp3']
    },
    requirements: {
      mse: true,
      browser: ['chrome', 'firefox', 'edge']
    },
    loadMethod: 'import',
    packageName: 'mpegts.js',
    importPath: 'mpegts.js/dist/mpegts.js'
  },
  
  'flv.js': {
    priority: 2,
    formats: ['flv'],
    codecs: {
      video: ['h264'],
      audio: ['aac', 'mp3']
    },
    requirements: {
      mse: true,
      browser: ['chrome', 'firefox', 'edge']
    },
    loadMethod: 'import',
    packageName: 'flv.js',
    importPath: 'flv.js/dist/flv.min.js'
  }
};

3.2 Plugin Manager Architecture

// Import plugins as ES modules (will be bundled by Next.js)
import Hls from 'hls.js';
import mpegts from 'mpegts.js';
import flvjs from 'flv.js';

class PluginManager {
  private static instance: PluginManager;
  private pluginInstances = new Map<string, any>();
  
  // Singleton pattern for consistent plugin management
  static getInstance(): PluginManager {
    if (!PluginManager.instance) {
      PluginManager.instance = new PluginManager();
    }
    return PluginManager.instance;
  }
  
  isPluginAvailable(pluginName: string): boolean {
    const config = PLUGIN_SUPPORT_MATRIX[pluginName];
    if (!config) return false;
    
    switch (pluginName) {
      case 'hls.js':
        return typeof Hls !== 'undefined' && Hls.isSupported();
      case 'mpegts.js':
        return typeof mpegts !== 'undefined' && mpegts.isSupported();
      case 'flv.js':
        return typeof flvjs !== 'undefined' && flvjs.isSupported();
      default:
        return false;
    }
  }
  
  createPluginPlayer(
    pluginName: string, 
    videoElement: HTMLVideoElement, 
    url: string,
    config?: any
  ): any {
    if (!this.isPluginAvailable(pluginName)) {
      console.warn(`Plugin ${pluginName} is not available`);
      return null;
    }
    
    // Clean up existing instance for this video element
    this.cleanupPluginInstance(videoElement);
    
    let player;
    switch (pluginName) {
      case 'hls.js':
        player = this.createHLSPlayer(Hls, videoElement, url, config);
        break;
      case 'mpegts.js':
        player = this.createMpegTSPlayer(mpegts, videoElement, url, config);
        break;
      case 'flv.js':
        player = this.createFLVPlayer(flvjs, videoElement, url, config);
        break;
      default:
        return null;
    }
    
    if (player) {
      // Store instance for cleanup later
      this.pluginInstances.set(videoElement.id || 'default', {
        plugin: pluginName,
        player,
        element: videoElement
      });
    }
    
    return player;
  }
  
  private createHLSPlayer(Hls: any, video: HTMLVideoElement, url: string, config?: any): any {
    const hls = new Hls({
      enableWorker: true,
      lowLatencyMode: false,
      backBufferLength: 90,
      ...config
    });
    
    hls.loadSource(url);
    hls.attachMedia(video);
    
    return hls;
  }
  
  private createMpegTSPlayer(mpegts: any, video: HTMLVideoElement, url: string, config?: any): any {
    const player = mpegts.createPlayer({
      type: 'mp2t',
      isLive: false,
      url: url,
      ...config
    });
    
    player.attachMediaElement(video);
    player.load();
    
    return player;
  }
  
  private createFLVPlayer(flvjs: any, video: HTMLVideoElement, url: string, config?: any): any {
    const player = flvjs.createPlayer({
      type: 'flv',
      url: url,
      isLive: false,
      ...config
    });
    
    player.attachMediaElement(video);
    player.load();
    
    return player;
  }
  
  cleanupPluginInstance(videoElement: HTMLVideoElement): void {
    const elementId = videoElement.id || 'default';
    const instance = this.pluginInstances.get(elementId);
    
    if (instance) {
      try {
        // Plugin-specific cleanup
        switch (instance.plugin) {
          case 'hls.js':
            instance.player.destroy();
            break;
          case 'mpegts.js':
          case 'flv.js':
            instance.player.unload();
            instance.player.detachMediaElement();
            instance.player.destroy();
            break;
        }
      } catch (error) {
        console.warn(`Error cleaning up ${instance.plugin}:`, error);
      } finally {
        this.pluginInstances.delete(elementId);
      }
    }
  }
  
  cleanupAll(): void {
    for (const [elementId, instance] of this.pluginInstances) {
      this.cleanupPluginInstance(instance.element);
    }
  }
}

3.3 Implementation Tasks

TODO Items:

  • Install npm packages - Add hls.js, mpegts.js, flv.js to package.json
  • Create PluginManager class - Static plugin management with ES module imports
  • Implement enhanced HLS.js integration - Complete existing partial implementation with new architecture
  • Add mpegts.js support - Enable MPEG-TS direct playback
  • Add flv.js support - Enable FLV direct playback
  • Create plugin error handling - Graceful fallback on plugin failures
  • Add plugin capability detection - Test plugin requirements before loading
  • Implement plugin cleanup system - Proper memory management and instance cleanup

Package Dependencies to Add:

{
  "dependencies": {
    "hls.js": "^1.4.12",
    "mpegts.js": "^1.7.3",
    "flv.js": "^1.6.2"
  },
  "devDependencies": {
    "@types/hls.js": "^1.0.1"
  }
}

Files to Create:

  • src/lib/plugin-manager.ts - Core plugin management with ES module imports
  • src/lib/plugins/plugin-types.ts - TypeScript interfaces for plugins
  • src/lib/plugins/plugin-config.ts - Plugin configuration and capabilities

Files to Modify:

  • package.json - Add plugin dependencies
  • src/components/artplayer-wrapper.tsx - Integrate new plugin system
  • src/lib/hls-error-handler.ts - Enhance error handling
  • next.config.ts - Configure webpack for plugin imports if needed

Phase 4: Smart Fallback System 🛡️

Objective

Implement intelligent error recovery and graceful degradation across playback methods.

Fallback Architecture

4.1 Error Recovery Chain

interface FallbackChain {
  attempts: PlaybackAttempt[];
  currentIndex: number;
  maxRetries: number;
}

interface PlaybackAttempt {
  method: 'native' | 'plugin' | 'directstream' | 'transcode';
  url: string;
  plugin?: string;
  error?: Error;
  timestamp: number;
}

class FallbackOrchestrator {
  async executePlaybackChain(
    media: VideoFile,
    strategies: PlaybackPlan[]
  ): Promise<PlaybackResult> {
    
    for (const strategy of strategies) {
      try {
        const result = await this.attemptPlayback(strategy);
        if (result.success) {
          return result;
        }
      } catch (error) {
        console.warn(`Playback strategy ${strategy.method} failed:`, error);
        
        // Log failure for analytics
        this.logPlaybackFailure(media, strategy, error);
        
        // Continue to next strategy
        continue;
      }
    }
    
    throw new Error('All playback strategies failed');
  }
}

4.2 Implementation Tasks

TODO Items:

  • Create FallbackOrchestrator class - Manage playback attempt chains
  • Implement error classification - Categorize failures for appropriate responses
  • Add retry logic - Smart retry with exponential backoff
  • Create performance monitoring - Track success rates and failure patterns
  • Implement quality adaptation - Automatic quality reduction on failures

Files to Create:

  • src/lib/fallback-orchestrator.ts - Main fallback logic
  • src/lib/error-classifier.ts - Error categorization and response
  • src/lib/playback-analytics.ts - Performance tracking

Phase 5: Performance Optimization & Resource Management

Objective

Optimize performance, resource usage, and user experience across all playback methods.

Optimization Areas

5.1 Preloading & Caching Strategy

interface CacheStrategy {
  browserCapabilities: {
    ttl: number;          // 24 hours
    storage: 'localStorage';
  };
  mediaAnalysis: {
    ttl: number;          // 1 hour
    storage: 'indexedDB';
  };
  pluginCapabilities: {
    cache: boolean;       // Cache plugin availability results
    precheck: boolean;    // Check plugin support on app start
  };
}

5.2 Performance Monitoring

interface PerformanceMetrics {
  playbackMethodDistribution: {
    native: number;
    plugin: number;
    directstream: number;
    transcode: number;
  };
  averageStartupTime: {
    native: number;
    plugin: number;
    directstream: number;
    transcode: number;
  };
  failureRates: {
    byMethod: Record<string, number>;
    byFormat: Record<string, number>;
    byBrowser: Record<string, number>;
  };
}

5.3 Implementation Tasks

TODO Items:

  • Implement capability caching - Cache browser tests to avoid repeated detection
  • Add media analysis caching - Cache codec analysis results
  • Create plugin capability checking - Check plugin support on application start
  • Implement performance tracking - Monitor playback success rates and timing
  • Add bandwidth adaptation - Adjust quality based on network conditions
  • Create resource cleanup - Proper plugin and player cleanup
  • Optimize bundle size - Implement code splitting for plugins

Files to Create:

  • src/lib/performance-monitor.ts - Performance tracking and analytics
  • src/lib/cache-manager.ts - Caching strategies and management
  • src/lib/resource-cleanup.ts - Memory and resource management
  • src/lib/bundle-optimizer.ts - Code splitting and lazy loading

Phase 6: Testing & Validation 🧪

Objective

Comprehensive testing across browsers, formats, and edge cases.

Testing Strategy

6.1 Browser Compatibility Matrix

Browser MP4 WebM TS MKV AVI FLV
Chrome 90+ 🔌 🔄 ⚠️ 🔌
Firefox 88+ 🔌 🔄 ⚠️ 🔌
Safari 14+ 🔌 🔄 ⚠️ 🔌
Edge 90+ 🔌 🔄 ⚠️ 🔌

Legend:

  • Native support
  • 🔌 Plugin support
  • 🔄 DirectStream (remux)
  • ⚠️ Conditional/fallback
  • Not supported

6.2 Test Cases

Format Testing:

  • MP4 + H.264 + AAC - Universal baseline
  • MP4 + H.265 + AAC - Modern codec support
  • WebM + VP9 + Opus - Open source stack
  • TS + H.264 + AAC - MPEG Transport Stream
  • MKV + H.264 + AAC - Container remux
  • AVI + various codecs - Legacy format handling
  • FLV + H.264 + AAC - Flash Video

Browser Testing:

  • Chrome - Full feature testing
  • Firefox - Full feature testing
  • Safari - Limited WebM, HLS native
  • Edge - Chromium-based testing
  • Mobile browsers - iOS Safari, Android Chrome

Error Scenario Testing:

  • Plugin load failures - Network issues, blocked CDNs
  • Codec incompatibility - Unsupported codec profiles
  • Network interruptions - Playback resumption
  • Hardware limitations - Software fallback
  • Memory constraints - Resource cleanup

6.3 Implementation Tasks

TODO Items:

  • Create automated test suite - Browser compatibility testing
  • Build format test library - Sample files for each format/codec combination
  • Implement error simulation - Test failure scenarios
  • Create performance benchmarks - Measure startup time and resource usage
  • Add user experience testing - Real-world usage patterns

Files to Create:

  • tests/format-compatibility.test.ts - Format support testing
  • tests/browser-capability.test.ts - Browser feature detection
  • tests/plugin-integration.test.ts - Plugin loading and functionality
  • tests/error-handling.test.ts - Failure scenario testing

Implementation Timeline

Sprint 1 (1-2 weeks): Foundation

  • Complete Phase 1: Enhanced Format Detection
  • Basic browser capability detection
  • Upgrade video-format-detector.ts
  • Install plugin npm packages

Sprint 2 (1-2 weeks): Smart Selection

  • Complete Phase 2: Progressive Enhancement
  • Implement SmartFormatSelector
  • Integration with existing components

Sprint 3 (2-3 weeks): Plugin Integration

  • Complete Phase 3: External Plugins (npm-based)
  • HLS.js, mpegts.js, flv.js integration via ES modules
  • Plugin manager architecture with static imports
  • Bundle optimization and code splitting

Sprint 4 (1-2 weeks): Reliability

  • Complete Phase 4: Smart Fallback
  • Error handling and recovery
  • Performance optimization
  • Memory management and cleanup

Sprint 5 (1-2 weeks): Validation

  • Complete Phase 5-6: Testing & Performance
  • Comprehensive testing
  • Performance monitoring
  • Bundle size optimization

Success Metrics

Target Outcomes

  • 📈 Direct Playback Rate: 80-90% (up from ~40%)
  • Startup Time: 50% faster for supported formats
  • 🔧 Server Load: 60-70% reduction in transcoding
  • 👥 User Experience: Seamless playback across formats
  • 🌐 Browser Coverage: 95%+ compatibility

Key Performance Indicators

  • Format Support Coverage: Track percentage of videos playing directly
  • Average Startup Time: Measure time to first frame
  • Error Rate: Monitor playback failures by method
  • Resource Usage: Server CPU/memory usage for transcoding
  • User Satisfaction: Playback quality and reliability metrics

Risk Mitigation

Technical Risks

  • Bundle Size Impact: Adding multiple media plugins may increase bundle size
  • Plugin Compatibility: Regular testing across browser versions
  • Performance Regression: Continuous performance monitoring
  • Memory Leaks: Proper plugin cleanup and resource management
  • TypeScript Compatibility: Ensure proper type definitions for all plugins

Mitigation Strategies

  • Code Splitting: Implement lazy loading for plugins to reduce initial bundle size
  • Tree Shaking: Ensure unused plugin features are excluded from bundles
  • Gradual Rollout: Feature flags for controlled deployment
  • Fallback Guarantees: Always maintain transcoding as ultimate fallback
  • Monitoring: Comprehensive error tracking and performance metrics
  • Documentation: Detailed implementation and troubleshooting guides

Development Tracking

Phase Status

  • Analysis Phase: Complete
  • Planning Phase: Complete (this document)
  • Phase 1 - Format Detection: 🔄 Ready to start
  • Phase 2 - Progressive Enhancement: Pending
  • Phase 3 - Plugin Integration: Pending
  • Phase 4 - Smart Fallback: Pending
  • Phase 5 - Performance Optimization: Pending
  • Phase 6 - Testing & Validation: Pending

Next Actions

  1. Start Phase 1: Begin with enhanced format detection implementation
  2. Install plugin dependencies: Add hls.js, mpegts.js, flv.js to package.json
  3. Set up TypeScript support: Ensure proper type definitions
  4. Create testing framework: Prepare for comprehensive testing
  5. Establish monitoring: Set up performance and error tracking
  6. Configure build optimization: Set up code splitting for plugins

Last Updated: 2025-09-22 Status: 📋 Planning Complete - Ready for Implementation Last Updated: 2025-09-22 Status: 📋 Planning Complete - Ready for Implementation