nextav/tests/diagnostics/diagnose-hls.js

207 lines
8.8 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/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']
};
}
}; }
};