diff --git a/src/components/VideoElement.tsx b/src/components/VideoElement.tsx index e7ce63b..2916a7e 100644 --- a/src/components/VideoElement.tsx +++ b/src/components/VideoElement.tsx @@ -131,12 +131,12 @@ export const VideoElement: React.FC = ({ // Check if it's a CORS-related error const videoError = video.error - if (videoError.code === MediaError.MEDIA_ERR_SRC_NOT_SUPPORTED || - videoError.code === MediaError.MEDIA_ERR_NETWORK) { + if ( + videoError.code === MediaError.MEDIA_ERR_SRC_NOT_SUPPORTED || + videoError.code === MediaError.MEDIA_ERR_NETWORK + ) { // Could be a CORS issue - const corsMessage = getCORSErrorMessage(video.src || src) - console.error(corsMessage) - errorMessage = `Failed to load video. This might be a CORS issue. Check console for details.` + errorMessage = getCORSErrorMessage(video.src || src) } const error = new Error(errorMessage) @@ -153,13 +153,11 @@ export const VideoElement: React.FC = ({ if (timeSinceLastClick < 300) { // Double click - toggle fullscreen e.preventDefault() - console.log('๐Ÿ–ฑ๏ธ [Video Click] Double-click detected, toggling fullscreen') toggleFullscreen() lastClickTimeRef.current = 0 } else { // Single click - record time lastClickTimeRef.current = now - console.log('๐Ÿ–ฑ๏ธ [Video Click] Single click detected') } }, [toggleFullscreen] @@ -208,11 +206,6 @@ export const VideoElement: React.FC = ({ return } - // Log warning if external URL - if (validation.warning) { - console.warn(`โš ๏ธ [Video] ${validation.warning}`) - } - const isHLS = src.includes('.m3u8') let cleanupFn: (() => void) | null = null @@ -237,54 +230,41 @@ export const VideoElement: React.FC = ({ hls.attachMedia(video) hls.on(Hls.Events.MANIFEST_PARSED, () => { - console.log('โœ… [HLS] Manifest parsed successfully') - // Extract audio tracks after manifest is parsed // Sometimes audio tracks are not immediately available, so we try with a small delay setTimeout(() => { const tracks = getHlsAudioTracks(hls) if (tracks.length > 0) { - console.log(`โœ… [HLS] Found ${tracks.length} audio tracks:`, tracks) setAvailableAudioTracks(tracks) onAudioTracksLoaded?.(tracks) - } else { - console.log('โ„น๏ธ [HLS] No audio tracks found in manifest') } }, 100) if (autoplay) { - video.play().catch((err) => { - console.warn('โš ๏ธ [HLS] Autoplay prevented:', err) - }) + void video.play().catch(() => undefined) } }) // Also listen to audio track updates - hls.on(Hls.Events.AUDIO_TRACKS_UPDATED, (_event: any, data: any) => { - console.log('๐Ÿ”„ [HLS] Audio tracks updated:', data) + hls.on(Hls.Events.AUDIO_TRACKS_UPDATED, () => { const tracks = getHlsAudioTracks(hls) if (tracks.length > 0) { - console.log(`โœ… [HLS] Found ${tracks.length} audio tracks after update:`, tracks) setAvailableAudioTracks(tracks) onAudioTracksLoaded?.(tracks) } }) hls.on(Hls.Events.ERROR, (_event: any, data: any) => { - console.error('โŒ [HLS] Error:', data) if (data.fatal) { switch (data.type) { case Hls.ErrorTypes.NETWORK_ERROR: - console.error('โŒ [HLS] Fatal network error, trying to recover...') hls.startLoad() break case Hls.ErrorTypes.MEDIA_ERROR: - console.error('โŒ [HLS] Fatal media error, trying to recover...') hls.recoverMediaError() break default: - console.error('โŒ [HLS] Fatal error, cannot recover') handleError() break } @@ -296,19 +276,16 @@ export const VideoElement: React.FC = ({ // Setup cleanup function cleanupFn = () => { - console.log('๐Ÿงน [HLS] Cleaning up HLS instance...') if (hls) { hls.destroy() } delete (video as any).__hlsInstance } } catch (err) { - console.error('โŒ [HLS] Failed to load or initialize hls.js:', err) let error: Error if (err instanceof Error && isCORSError(err)) { const corsMessage = getCORSErrorMessage(src) - console.error(corsMessage) - error = new Error('Failed to load HLS stream. This might be a CORS issue. Check console for details.') + error = new Error(corsMessage) } else { error = err instanceof Error ? err : new Error('Failed to load HLS') } @@ -323,9 +300,7 @@ export const VideoElement: React.FC = ({ // Native support or regular video video.src = src if (autoplay) { - video.play().catch((err) => { - console.warn('โš ๏ธ [Video] Autoplay prevented:', err) - }) + void video.play().catch(() => undefined) } } } @@ -363,7 +338,6 @@ export const VideoElement: React.FC = ({ if (trackIndex !== -1) { setHlsAudioTrack(hlsInstance, trackIndex) - console.log(`โœ… [Video] Audio track changed to: ${settings.audioTrack.name}`) } }, [settings.audioTrack, availableAudioTracks, videoRef]) diff --git a/src/contexts/PlayerContext.tsx b/src/contexts/PlayerContext.tsx index e010970..aca9cb3 100644 --- a/src/contexts/PlayerContext.tsx +++ b/src/contexts/PlayerContext.tsx @@ -126,7 +126,9 @@ export const PlayerProvider: React.FC = ({ try { await videoRef.current?.requestPictureInPicture() } catch (error) { - console.error('PIP error:', error) + if (error instanceof Error) { + setVideoState((prev) => ({ ...prev, error })) + } } } else { await document.exitPictureInPicture() diff --git a/src/utils/corsHelper.ts b/src/utils/corsHelper.ts index f429a84..ebd7bc3 100644 --- a/src/utils/corsHelper.ts +++ b/src/utils/corsHelper.ts @@ -6,6 +6,7 @@ export interface CORSCheckResult { supported: boolean error?: string needsProxy: boolean + supportsRange?: boolean } /** @@ -21,6 +22,7 @@ export const checkVideoCORS = async (url: string): Promise => { const corsHeader = response.headers.get('Access-Control-Allow-Origin') const rangeHeader = response.headers.get('Accept-Ranges') + const supportsRange = !!rangeHeader && rangeHeader !== 'none' if (!corsHeader && !response.ok) { return { @@ -30,14 +32,11 @@ export const checkVideoCORS = async (url: string): Promise => { } } - if (!rangeHeader || rangeHeader === 'none') { - console.warn('โš ๏ธ [CORS] Server does not support Range Requests. Seeking may not work properly.') - } - - return { - supported: true, - needsProxy: false, - } + return { + supported: true, + needsProxy: false, + supportsRange, + } } catch (error) { // CORS error or network error if (error instanceof TypeError && error.message.includes('CORS')) { diff --git a/src/utils/hlsLoader.ts b/src/utils/hlsLoader.ts index bb95df5..7ae93ef 100644 --- a/src/utils/hlsLoader.ts +++ b/src/utils/hlsLoader.ts @@ -24,7 +24,6 @@ const loadHlsFromCDN = (): Promise => { script.onload = () => { if (typeof (window as any).Hls !== 'undefined') { - console.log('โœ… [HLS Loader] Loaded hls.js from CDN') resolve((window as any).Hls) } else { reject(new Error('HLS.js CDN loaded but Hls global not found')) @@ -45,19 +44,14 @@ const loadHlsFromCDN = (): Promise => { export const loadHls = async (): Promise => { try { // Try loading from npm package first - console.log('๐Ÿ”„ [HLS Loader] Attempting to load hls.js from npm package...') const hlsModule = await import('hls.js') - console.log('โœ… [HLS Loader] Loaded hls.js from npm package') return hlsModule.default } catch (npmError) { - console.warn('โš ๏ธ [HLS Loader] Failed to load hls.js from npm, trying CDN fallback...', npmError) - try { // Fallback to CDN const Hls = await loadHlsFromCDN() return Hls } catch (cdnError) { - console.error('โŒ [HLS Loader] Failed to load hls.js from both npm and CDN', cdnError) throw new Error('Unable to load HLS.js library. HLS streaming is not available.') } } @@ -84,18 +78,14 @@ export const hasNativeHlsSupport = (): boolean => { export const getHlsAudioTracks = (hls: any): AudioTrack[] => { try { if (!hls) { - console.warn('โš ๏ธ [HLS Loader] HLS instance is null or undefined') return [] } // Check if audioTracks property exists if (!hls.audioTracks || !Array.isArray(hls.audioTracks)) { - console.warn('โš ๏ธ [HLS Loader] audioTracks not available or not an array:', hls.audioTracks) return [] } - console.log('๐Ÿ” [HLS Loader] Raw audio tracks from HLS:', hls.audioTracks) - const audioTracks: AudioTrack[] = hls.audioTracks.map((track: any, index: number) => { const audioTrack = { name: track.name || track.label || `Audio ${index + 1}`, @@ -105,13 +95,11 @@ export const getHlsAudioTracks = (hls: any): AudioTrack[] => { default: track.default || false, autoselect: track.autoselect || false, } - console.log(`๐ŸŽต [HLS Loader] Parsed audio track ${index}:`, audioTrack) return audioTrack }) return audioTracks } catch (error) { - console.error('โŒ [HLS Loader] Error extracting audio tracks:', error) return [] } } @@ -120,20 +108,13 @@ export const getHlsAudioTracks = (hls: any): AudioTrack[] => { * Set active audio track in HLS instance */ export const setHlsAudioTrack = (hls: any, audioTrackIndex: number): void => { - try { - if (!hls || !hls.audioTracks) { - console.warn('โš ๏ธ [HLS Loader] HLS instance or audioTracks not available') - return - } - - if (audioTrackIndex < 0 || audioTrackIndex >= hls.audioTracks.length) { - console.warn('โš ๏ธ [HLS Loader] Invalid audio track index:', audioTrackIndex) - return - } - - hls.audioTrack = audioTrackIndex - console.log(`โœ… [HLS Loader] Audio track set to index ${audioTrackIndex}`) - } catch (error) { - console.error('โŒ [HLS Loader] Error setting audio track:', error) + if (!hls || !hls.audioTracks) { + return } + + if (audioTrackIndex < 0 || audioTrackIndex >= hls.audioTracks.length) { + return + } + + hls.audioTrack = audioTrackIndex } diff --git a/src/utils/m3u8Parser.ts b/src/utils/m3u8Parser.ts index c53ace9..fe98396 100644 --- a/src/utils/m3u8Parser.ts +++ b/src/utils/m3u8Parser.ts @@ -57,7 +57,6 @@ const parseAudioMediaTag = (line: string): AudioTrack | null => { const autoselect = attributes['AUTOSELECT'] === 'YES' if (!name || !uri) { - console.warn('โš ๏ธ [M3U8 Parser] Audio track missing NAME or URI:', line) return null } @@ -69,8 +68,7 @@ const parseAudioMediaTag = (line: string): AudioTrack | null => { default: defaultTrack, autoselect, } - } catch (error) { - console.error('โŒ [M3U8 Parser] Error parsing audio track:', line, error) + } catch { return null } } @@ -87,8 +85,7 @@ export const fetchAndParseM3U8 = async (url: string): Promise => { const manifestContent = await response.text() return parseM3U8AudioTracks(manifestContent) - } catch (error) { - console.error('โŒ [M3U8 Parser] Error fetching M3U8:', error) + } catch { return [] } } diff --git a/src/utils/polyfills.ts b/src/utils/polyfills.ts index bdc1fdf..327e6b9 100644 --- a/src/utils/polyfills.ts +++ b/src/utils/polyfills.ts @@ -87,29 +87,37 @@ export const checkFetchSupport = (): boolean => { * Initialize all polyfills * Call this once when the app loads */ -export const initializePolyfills = () => { +export interface PolyfillDiagnostics { + warnings: string[] + errors: string[] +} + +export const initializePolyfills = (): PolyfillDiagnostics => { + const warnings: string[] = [] + const errors: string[] = [] + try { setupFullscreenPolyfill() setupPIPPolyfill() // Check critical API support if (!checkPromiseSupport()) { - console.warn('[VideoPlayer] Promise not supported. Please add Promise polyfill.') + warnings.push('Promise not supported. Please add a Promise polyfill for full compatibility.') } if (!checkFetchSupport()) { - console.warn('[VideoPlayer] Fetch API not supported. Subtitle loading may fail.') + warnings.push('Fetch API not supported. Subtitle loading may fail without a fetch polyfill.') } // Check for MediaSource API (required for HLS.js) if (typeof MediaSource === 'undefined') { - console.warn('[VideoPlayer] MediaSource API not supported. HLS streaming will not work.') + warnings.push('MediaSource API not supported. HLS streaming will not work on this browser.') } - - console.log('โœ… [VideoPlayer] Polyfills initialized successfully') } catch (error) { - console.error('[VideoPlayer] Error initializing polyfills:', error) + errors.push(error instanceof Error ? error.message : String(error)) } + + return { warnings, errors } } /** diff --git a/src/utils/subtitles.ts b/src/utils/subtitles.ts index 6cdc9e9..8c29a10 100644 --- a/src/utils/subtitles.ts +++ b/src/utils/subtitles.ts @@ -45,18 +45,13 @@ export const createSubtitleBlobURL = (content: string, format: 'vtt' | 'srt'): s * Fetch and parse subtitle file */ export const fetchSubtitle = async (url: string): Promise => { - try { - const response = await fetch(url) - const content = await response.text() + const response = await fetch(url) + const content = await response.text() - // Detect format - if (url.endsWith('.srt')) { - return parseSRT(content) - } - - return content - } catch (error) { - console.error('Failed to fetch subtitle:', error) - throw error + // Detect format + if (url.endsWith('.srt')) { + return parseSRT(content) } + + return content }