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
UnifiedVideoPlayercomponent
❌ 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
MediaAnalyzerclass - Extract actual codec information from video files - Implement
BrowserCapabilityDetector- Runtime capability testing usingHTMLVideoElement.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 functionalitysrc/lib/browser-capabilities.ts- Browser capability detectionsrc/lib/codec-compatibility.ts- Codec support matrixsrc/lib/format-scorer.ts- Playback method ranking
Files to Modify:
src/lib/video-format-detector.ts- Integrate advanced detectionsrc/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
SmartFormatSelectorclass - 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 enginesrc/lib/playback-strategies.ts- Strategy definitions and interfacessrc/lib/native-support-detector.ts- HTML5 compatibility testing
Files to Modify:
src/components/unified-video-player.tsx- Integrate smart selectionsrc/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
PluginManagerclass - 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 importssrc/lib/plugins/plugin-types.ts- TypeScript interfaces for pluginssrc/lib/plugins/plugin-config.ts- Plugin configuration and capabilities
Files to Modify:
package.json- Add plugin dependenciessrc/components/artplayer-wrapper.tsx- Integrate new plugin systemsrc/lib/hls-error-handler.ts- Enhance error handlingnext.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
FallbackOrchestratorclass - 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 logicsrc/lib/error-classifier.ts- Error categorization and responsesrc/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 analyticssrc/lib/cache-manager.ts- Caching strategies and managementsrc/lib/resource-cleanup.ts- Memory and resource managementsrc/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 testingtests/browser-capability.test.ts- Browser feature detectiontests/plugin-integration.test.ts- Plugin loading and functionalitytests/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
- Start Phase 1: Begin with enhanced format detection implementation
- Install plugin dependencies: Add hls.js, mpegts.js, flv.js to package.json
- Set up TypeScript support: Ensure proper type definitions
- Create testing framework: Prepare for comprehensive testing
- Establish monitoring: Set up performance and error tracking
- 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