207 lines
8.8 KiB
JavaScript
207 lines
8.8 KiB
JavaScript
#!/usr/bin/env node
|
||
|
||
/**
|
||
* HLS Implementation Diagnostic Script
|
||
* Checks the HLS streaming implementation and identifies potential issues
|
||
*/
|
||
|
||
const fs = require('fs');
|
||
const path = require('path');
|
||
|
||
console.log('🔍 HLS Implementation Diagnostic Tool');
|
||
console.log('=====================================');
|
||
|
||
// Check if HLS routes exist
|
||
const hlsRoutes = [
|
||
'src/app/api/stream/hls/[id]/playlist/route.ts',
|
||
'src/app/api/stream/hls/[id]/playlist.m3u8/route.ts',
|
||
'src/app/api/stream/hls/[id]/segment/[segment]/route.ts'
|
||
];
|
||
|
||
console.log('\n📁 Checking HLS API Routes:');
|
||
hlsRoutes.forEach(route => {
|
||
const fullPath = path.join(process.cwd(), route);
|
||
const exists = fs.existsSync(fullPath);
|
||
console.log(`${exists ? '✅' : '❌'} ${route} ${exists ? '- EXISTS' : '- MISSING'}`);
|
||
});
|
||
|
||
// Check format detector
|
||
console.log('\n🔧 Checking Format Detector:');
|
||
const formatDetectorPath = path.join(process.cwd(), 'src/lib/video-format-detector.ts');
|
||
if (fs.existsSync(formatDetectorPath)) {
|
||
const content = fs.readFileSync(formatDetectorPath, 'utf8');
|
||
|
||
// Check for HLS format support
|
||
const hasHLSFormat = content.includes('createHLSFormat');
|
||
const hasTSsupport = content.includes("'ts'");
|
||
const hasM3U8url = content.includes('playlist.m3u8');
|
||
|
||
console.log(`${hasHLSFormat ? '✅' : '❌'} HLS format detection: ${hasHLSFormat ? 'IMPLEMENTED' : 'MISSING'}`);
|
||
console.log(`${hasTSsupport ? '✅' : '❌'} .ts file support: ${hasTSsupport ? 'INCLUDED' : 'MISSING'}`);
|
||
console.log(`${hasM3U8url ? '✅' : '❌'} M3U8 URL generation: ${hasM3U8url ? 'CONFIGURED' : 'MISSING'}`);
|
||
|
||
// Extract HLS-compatible formats
|
||
const hlsFormatsMatch = content.match(/const HLS_COMPATIBLE_FORMATS = \[([\s\S]*?)\];/);
|
||
if (hlsFormatsMatch) {
|
||
const formats = hlsFormatsMatch[1].split(',').map(f => f.trim().replace(/['"]/g, ''));
|
||
console.log(`📋 HLS-compatible formats: ${formats.join(', ')}`);
|
||
}
|
||
} else {
|
||
console.log('❌ Format detector file not found');
|
||
}
|
||
|
||
// Check ArtPlayer integration
|
||
console.log('\n🎬 Checking ArtPlayer Integration:');
|
||
const artPlayerPath = path.join(process.cwd(), 'src/components/artplayer-wrapper.tsx');
|
||
if (fs.existsSync(artPlayerPath)) {
|
||
const content = fs.readFileSync(artPlayerPath, 'utf8');
|
||
|
||
const hasHlsImport = content.includes("import Hls from 'hls.js'");
|
||
const hasHlsPlugin = content.includes('hlsInstance');
|
||
const hasErrorHandler = content.includes('HLSErrorHandler');
|
||
|
||
console.log(`${hasHlsImport ? '✅' : '❌'} hls.js import: ${hasHlsImport ? 'PRESENT' : 'MISSING'}`);
|
||
console.log(`${hasHlsPlugin ? '✅' : '❌'} HLS plugin implementation: ${hasHlsPlugin ? 'IMPLEMENTED' : 'MISSING'}`);
|
||
console.log(`${hasErrorHandler ? '✅' : '❌'} Error handler integration: ${hasErrorHandler ? 'CONFIGURED' : 'MISSING'}`);
|
||
} else {
|
||
console.log('❌ ArtPlayer wrapper file not found');
|
||
}
|
||
|
||
// Check unified video player (ArtPlayer only)
|
||
console.log('\n🔄 Checking Unified Video Player (ArtPlayer Only):');
|
||
const unifiedPlayerPath = path.join(process.cwd(), 'src/components/unified-video-player.tsx');
|
||
if (fs.existsSync(unifiedPlayerPath)) {
|
||
const content = fs.readFileSync(unifiedPlayerPath, 'utf8');
|
||
|
||
const hasArtPlayerOnly = content.includes('Always use ArtPlayer now');
|
||
const noFallbacks = !content.includes('VideoViewer') && !content.includes('InlineVideoPlayer');
|
||
const hasFormatDetection = content.includes('detectVideoFormat');
|
||
|
||
console.log(`${hasArtPlayerOnly ? '✅' : '❌'} ArtPlayer-only architecture: ${hasArtPlayerOnly ? 'IMPLEMENTED' : 'MISSING'}`);
|
||
console.log(`${noFallbacks ? '✅' : '❌'} Legacy player removal: ${noFallbacks ? 'COMPLETE' : 'INCOMPLETE'}`);
|
||
console.log(`${hasFormatDetection ? '✅' : '❌'} Format detection: ${hasFormatDetection ? 'INTEGRATED' : 'MISSING'}`);
|
||
} else {
|
||
console.log('❌ Unified video player file not found');
|
||
}
|
||
|
||
// Check player config endpoint
|
||
console.log('\n⚙️ Checking Player Config Endpoint:');
|
||
const playerConfigPath = path.join(process.cwd(), 'src/app/api/video/[id]/player-config/route.ts');
|
||
if (fs.existsSync(playerConfigPath)) {
|
||
const content = fs.readFileSync(playerConfigPath, 'utf8');
|
||
|
||
const hasFormatDetection = content.includes('detectVideoFormat');
|
||
const hasOptimalPlayer = content.includes('getOptimalPlayerType');
|
||
const hasStreamingUrls = content.includes('streaming');
|
||
|
||
console.log(`${hasFormatDetection ? '✅' : '❌'} Format detection: ${hasFormatDetection ? 'INCLUDED' : 'MISSING'}`);
|
||
console.log(`${hasOptimalPlayer ? '✅' : '❌'} Optimal player selection: ${hasOptimalPlayer ? 'IMPLEMENTED' : 'MISSING'}`);
|
||
console.log(`${hasStreamingUrls ? '✅' : '❌'} Streaming URLs: ${hasStreamingUrls ? 'CONFIGURED' : 'MISSING'}`);
|
||
} else {
|
||
console.log('❌ Player config endpoint not found');
|
||
}
|
||
|
||
// Check build output
|
||
console.log('\n🏗️ Checking Build Configuration:');
|
||
const packageJsonPath = path.join(process.cwd(), 'package.json');
|
||
if (fs.existsSync(packageJsonPath)) {
|
||
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
|
||
const hasHlsJs = packageJson.dependencies && packageJson.dependencies['hls.js'];
|
||
const hasArtPlayer = packageJson.dependencies && packageJson.dependencies['artplayer'];
|
||
|
||
console.log(`${hasHlsJs ? '✅' : '❌'} hls.js dependency: ${hasHlsJs ? 'INSTALLED' : 'MISSING'}`);
|
||
console.log(`${hasArtPlayer ? '✅' : '❌'} artplayer dependency: ${hasArtPlayer ? 'INSTALLED' : 'MISSING'}`);
|
||
|
||
if (hasHlsJs) console.log(`📦 hls.js version: ${packageJson.dependencies['hls.js']}`);
|
||
if (hasArtPlayer) console.log(`📦 artplayer version: ${packageJson.dependencies['artplayer']}`);
|
||
} else {
|
||
console.log('❌ package.json not found');
|
||
}
|
||
|
||
// Provide troubleshooting recommendations
|
||
console.log('\n🔧 Troubleshooting Recommendations:');
|
||
console.log('=====================================');
|
||
|
||
const issues = [];
|
||
|
||
// Check for missing routes
|
||
if (!fs.existsSync(path.join(process.cwd(), 'src/app/api/stream/hls/[id]/playlist.m3u8/route.ts'))) {
|
||
issues.push('Missing .m3u8 route handler - HLS clients expect .m3u8 extension');
|
||
}
|
||
|
||
if (!fs.existsSync(path.join(process.cwd(), 'src/app/api/stream/hls/[id]/segment/[segment]/route.ts'))) {
|
||
issues.push('Missing segment serving route');
|
||
}
|
||
|
||
// Check format detector issues
|
||
if (fs.existsSync(formatDetectorPath)) {
|
||
const content = fs.readFileSync(formatDetectorPath, 'utf8');
|
||
if (!content.includes("'ts'")) {
|
||
issues.push('Format detector missing .ts file support');
|
||
}
|
||
if (!content.includes('playlist.m3u8')) {
|
||
issues.push('Format detector not generating proper M3U8 URLs');
|
||
}
|
||
}
|
||
|
||
// Check ArtPlayer integration
|
||
if (fs.existsSync(artPlayerPath)) {
|
||
const content = fs.readFileSync(artPlayerPath, 'utf8');
|
||
if (!content.includes('hlsInstance')) {
|
||
issues.push('ArtPlayer missing HLS instance configuration');
|
||
}
|
||
if (!content.includes('Hls.isSupported()')) {
|
||
issues.push('ArtPlayer missing HLS support detection');
|
||
}
|
||
}
|
||
|
||
if (issues.length === 0) {
|
||
console.log('✅ All components appear to be properly configured!');
|
||
console.log('\n🧪 Next Steps:');
|
||
console.log('1. Run `pnpm build` to verify compilation');
|
||
console.log('2. Start the development server');
|
||
console.log('3. Test with the HLS test interface at /test-hls.html');
|
||
console.log('4. Monitor browser console for HLS.js debug output');
|
||
console.log('5. Check network tab for any loading issues');
|
||
} else {
|
||
console.log('❌ Issues found that may prevent HLS streaming:');
|
||
issues.forEach(issue => console.log(` • ${issue}`));
|
||
|
||
console.log('\n🔧 Suggested fixes:');
|
||
console.log('1. Ensure all HLS API routes are created');
|
||
console.log('2. Verify format detector includes .ts support');
|
||
console.log('3. Check ArtPlayer HLS integration');
|
||
console.log('4. Test with sample .ts video files');
|
||
console.log('5. Monitor browser console for detailed errors');
|
||
}
|
||
|
||
console.log('\n📚 Common HLS Issues:');
|
||
console.log('• 404 errors: Usually indicate missing routes or incorrect URL patterns');
|
||
console.log('• CORS errors: Check Access-Control-Allow-Origin headers');
|
||
console.log('• Playlist parsing: Verify M3U8 format and segment paths');
|
||
console.log('• Segment loading: Check file paths and permissions');
|
||
console.log('• Browser compatibility: Ensure hls.js support or native HLS');
|
||
|
||
console.log('\n🎯 Success Indicators:');
|
||
console.log('• HLS playlist loads with 200 status');
|
||
console.log('• M3U8 content shows valid playlist format');
|
||
console.log('• Segments load successfully (binary data)');
|
||
console.log('• Video plays without buffering issues');
|
||
console.log('• Quality switching works smoothly');
|
||
|
||
console.log('\n🚀 Ready for testing!');
|
||
|
||
// Export a simple test function for programmatic use
|
||
module.exports = {
|
||
diagnoseHLS: () => {
|
||
return {
|
||
routes: hlsRoutes.map(route => ({
|
||
path: route,
|
||
exists: fs.existsSync(path.join(process.cwd(), route))
|
||
})),
|
||
issues,
|
||
recommendations: issues.length > 0 ? issues : ['All systems ready for testing']
|
||
};
|
||
}
|
||
}; }
|
||
}; |