feat: apply phase1 DX cleanup for private registry

This commit is contained in:
hibna
2026-02-12 18:27:50 +03:00
parent 8a32c5c1b3
commit fcd2a14a05
21 changed files with 281 additions and 279 deletions
+25 -106
View File
@@ -8,6 +8,7 @@ import { setupRtmpInstance } from '../utils/rtmpSetup'
import { setupMpegtsInstance } from '../utils/mpegtsSetup'
import { detectVideoProtocol } from '../utils/videoProtocol'
import { createSubtitleBlobURL } from '../utils/subtitles'
import { logger } from '../utils/logger'
import './VideoElement.css'
interface VideoElementProps {
@@ -112,7 +113,7 @@ export const VideoElement: React.FC<VideoElementProps> = ({
// Check if this is a live broadcast (duration is Infinity for live streams)
const isLiveBroadcast = !isFinite(video.duration) || video.duration === 0
console.log('[VideoElement] Is live broadcast?', isLiveBroadcast, 'duration:', video.duration)
logger.log('[VideoElement] Is live broadcast?', isLiveBroadcast, 'duration:', video.duration)
setVideoState((prev) => ({
...prev,
@@ -127,7 +128,7 @@ export const VideoElement: React.FC<VideoElementProps> = ({
if (tracks && processedSubtitles.length > 0) {
const defaultSubtitle = processedSubtitles.find((sub) => sub.default)
if (defaultSubtitle) {
console.log(`🎯 Found default subtitle in metadata: ${defaultSubtitle.label}`)
logger.log(`🎯 Found default subtitle in metadata: ${defaultSubtitle.label}`)
// Set subtitle in context (this will trigger the useEffect that enables it)
setSubtitle(defaultSubtitle)
}
@@ -142,7 +143,7 @@ export const VideoElement: React.FC<VideoElementProps> = ({
// Re-check if this is a live broadcast when duration changes
const isLiveBroadcast = !isFinite(video.duration) || video.duration === 0
console.log('[VideoElement] Duration changed. Is live broadcast?', isLiveBroadcast, 'duration:', video.duration)
logger.log('[VideoElement] Duration changed. Is live broadcast?', isLiveBroadcast, 'duration:', video.duration)
setVideoState((prev) => ({
...prev,
@@ -339,25 +340,16 @@ export const VideoElement: React.FC<VideoElementProps> = ({
throw new Error(`Failed to fetch subtitle: ${response.status} ${response.statusText}`)
}
const srtContent = await response.text()
console.log(`SRT content length: ${srtContent.length} chars`)
const blobUrl = createSubtitleBlobURL(srtContent, 'srt')
subtitleBlobUrlsRef.current.push(blobUrl)
// Debug: fetch the blob URL to verify VTT content
const vttResponse = await fetch(blobUrl)
const vttContent = await vttResponse.text()
console.log(`VTT content preview (first 500 chars):`, vttContent.substring(0, 500))
console.log(`Total VTT length: ${vttContent.length} chars`)
console.log(`Processed SRT subtitle "${subtitle.label}": ${subtitle.src} -> ${blobUrl}`)
return { ...subtitle, src: blobUrl }
}
// VTT files can be used directly
console.log(`Using VTT subtitle "${subtitle.label}": ${subtitle.src}`)
return subtitle
} catch (error) {
console.error(`Failed to process subtitle ${subtitle.label}:`, error)
logger.error(`Failed to process subtitle ${subtitle.label}:`, error)
return subtitle
}
})
@@ -459,10 +451,10 @@ export const VideoElement: React.FC<VideoElementProps> = ({
}
}
console.log('[VideoElement] Source:', src)
console.log('[VideoElement] Detected protocol:', detection.protocol)
console.log('[VideoElement] Is live stream?', detection.isLive)
console.log('[VideoElement] Needs special player?', detection.needsSpecialPlayer)
logger.log('[VideoElement] Source:', src)
logger.log('[VideoElement] Detected protocol:', detection.protocol)
logger.log('[VideoElement] Is live stream?', detection.isLive)
logger.log('[VideoElement] Needs special player?', detection.needsSpecialPlayer)
const setupPlayer = async () => {
try {
@@ -473,12 +465,12 @@ export const VideoElement: React.FC<VideoElementProps> = ({
const isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent)
const shouldUseHlsJs = canPlayHLS === '' || !isSafari
console.log('[VideoElement] Native HLS support?', canPlayHLS)
console.log('[VideoElement] Is Safari?', isSafari)
console.log('[VideoElement] Will use HLS.js?', shouldUseHlsJs)
logger.log('[VideoElement] Native HLS support?', canPlayHLS)
logger.log('[VideoElement] Is Safari?', isSafari)
logger.log('[VideoElement] Will use HLS.js?', shouldUseHlsJs)
if (shouldUseHlsJs) {
console.log('[VideoElement] Setting up HLS.js...')
logger.log('[VideoElement] Setting up HLS.js...')
cleanupFn = await setupHlsInstance({
video,
src,
@@ -507,7 +499,7 @@ export const VideoElement: React.FC<VideoElementProps> = ({
}
} else {
if (isCancelled) return
console.log('[VideoElement] Using native HLS playback')
logger.log('[VideoElement] Using native HLS playback')
video.src = src
if (autoplay) {
void video.play().catch(() => undefined)
@@ -518,7 +510,7 @@ export const VideoElement: React.FC<VideoElementProps> = ({
case 'rtmp': {
// RTMP/FLV streaming setup
console.log('[VideoElement] Setting up RTMP/FLV player...')
logger.log('[VideoElement] Setting up RTMP/FLV player...')
cleanupFn = await setupRtmpInstance({
video,
src,
@@ -536,7 +528,7 @@ export const VideoElement: React.FC<VideoElementProps> = ({
case 'mpegts': {
// MPEG-TS/IPTV streaming setup
console.log('[VideoElement] Setting up MPEG-TS player...')
logger.log('[VideoElement] Setting up MPEG-TS player...')
cleanupFn = await setupMpegtsInstance({
video,
src,
@@ -556,7 +548,7 @@ export const VideoElement: React.FC<VideoElementProps> = ({
// DASH streaming - not yet implemented
if (isCancelled) return
const error = new Error('DASH streaming is not yet supported')
console.error('[VideoElement]', error.message)
logger.error('[VideoElement]', error.message)
setVideoState((prev) => ({ ...prev, error, loading: false }))
onError?.(error)
break
@@ -566,7 +558,7 @@ export const VideoElement: React.FC<VideoElementProps> = ({
default: {
// Native HTML5 video (MP4, WebM, etc.)
if (isCancelled) return
console.log('[VideoElement] Using native video.src')
logger.log('[VideoElement] Using native video.src')
video.src = src
if (autoplay) {
void video.play().catch(() => undefined)
@@ -585,7 +577,7 @@ export const VideoElement: React.FC<VideoElementProps> = ({
if (isCancelled) return
console.error('[VideoElement] Setup error:', error)
logger.error('[VideoElement] Setup error:', error)
setVideoState((prev) => ({
...prev,
error,
@@ -728,11 +720,11 @@ export const VideoElement: React.FC<VideoElementProps> = ({
// Wait for track to have cues before showing
if (track.cues && track.cues.length > 0) {
track.mode = 'showing'
console.log(`🔊 Enabled subtitle track: ${track.label} (${track.language})`)
console.log(` - cues available: ${track.cues.length}`)
console.log(` - track.mode: ${track.mode}`)
logger.log(`🔊 Enabled subtitle track: ${track.label} (${track.language})`)
logger.log(` - cues available: ${track.cues.length}`)
logger.log(` - track.mode: ${track.mode}`)
} else {
console.warn(`⚠️ Track ${track.label} has no cues yet, waiting...`)
logger.warn(`⚠️ Track ${track.label} has no cues yet, waiting...`)
// Track not ready yet, will be handled by load event
track.mode = 'showing'
}
@@ -747,7 +739,7 @@ export const VideoElement: React.FC<VideoElementProps> = ({
// Also listen for track load events to retry
const handleTrackChange = () => {
console.log(`🔄 Track changed, re-enabling subtitle`)
logger.log(`🔄 Track changed, re-enabling subtitle`)
enableSubtitle()
}
@@ -762,80 +754,6 @@ export const VideoElement: React.FC<VideoElementProps> = ({
}
}, [settings.subtitle, videoRef])
// Debug: Monitor text track loading
useEffect(() => {
const video = videoRef.current
if (!video) return
const handleTrackLoad = (e: Event) => {
const track = e.target as HTMLTrackElement
const textTrack = track.track
console.log(`✅ Track loaded: ${track.label} (${track.srclang})`)
console.log(` - readyState: ${track.readyState}`)
console.log(` - track.mode: ${textTrack.mode}`)
console.log(` - track.cues: ${textTrack.cues?.length || 0}`)
console.log(` - src: ${track.src}`)
// Log first few cues if available
if (textTrack.cues && textTrack.cues.length > 0) {
console.log(` - First cue: ${(textTrack.cues[0] as VTTCue).startTime}s - ${(textTrack.cues[0] as VTTCue).endTime}s: "${(textTrack.cues[0] as VTTCue).text}"`)
} else {
console.warn(` ⚠️ No cues found in track!`)
}
}
const handleTrackError = (e: Event) => {
const track = e.target as HTMLTrackElement
console.error(`❌ Track error: ${track.label} (${track.srclang})`)
console.error(` - src: ${track.src}`)
console.error(` - readyState: ${track.readyState}`)
}
const trackElements = video.querySelectorAll('track')
trackElements.forEach((track) => {
track.addEventListener('load', handleTrackLoad)
track.addEventListener('error', handleTrackError)
})
// Also monitor text tracks
const textTracks = video.textTracks
const handleCueChange = () => {
for (let i = 0; i < textTracks.length; i++) {
const track = textTracks[i]
if (track.mode === 'showing') {
console.log(`🎬 Cuechange: ${track.label}, cues: ${track.cues?.length || 0}, active cues: ${track.activeCues?.length || 0}`)
if (track.activeCues && track.activeCues.length > 0) {
const cue = track.activeCues[0] as VTTCue
console.log(` - Active cue text: "${cue.text}"`)
}
}
}
}
for (let i = 0; i < textTracks.length; i++) {
textTracks[i].addEventListener('cuechange', handleCueChange)
}
// Log all text tracks after a delay to see their state
setTimeout(() => {
console.log(`📊 Text tracks summary (${textTracks.length} total):`)
for (let i = 0; i < textTracks.length; i++) {
const track = textTracks[i]
console.log(` [${i}] ${track.label} (${track.language}): mode=${track.mode}, cues=${track.cues?.length || 0}`)
}
}, 1000)
return () => {
trackElements.forEach((track) => {
track.removeEventListener('load', handleTrackLoad)
track.removeEventListener('error', handleTrackError)
})
for (let i = 0; i < textTracks.length; i++) {
textTracks[i].removeEventListener('cuechange', handleCueChange)
}
}
}, [videoRef, processedSubtitles])
return (
<div className="video-container">
<video
@@ -876,3 +794,4 @@ export const VideoElement: React.FC<VideoElementProps> = ({
</div>
)
}