This commit is contained in:
hibna
2025-10-29 14:37:33 +03:00
parent 0d3559300a
commit ad0c32785b
2 changed files with 176 additions and 33 deletions
+91 -24
View File
@@ -96,15 +96,9 @@ export const VideoElement: React.FC<VideoElementProps> = ({
if (tracks && processedSubtitles.length > 0) {
const defaultSubtitle = processedSubtitles.find((sub) => sub.default)
if (defaultSubtitle) {
// Find the corresponding track and set it as showing
for (let i = 0; i < tracks.length; i++) {
const track = tracks[i]
if (track.language === defaultSubtitle.lang) {
track.mode = 'showing'
setSubtitle(defaultSubtitle)
break
}
}
console.log(`🎯 Found default subtitle in metadata: ${defaultSubtitle.label}`)
// Set subtitle in context (this will trigger the useEffect that enables it)
setSubtitle(defaultSubtitle)
}
}
@@ -218,6 +212,8 @@ export const VideoElement: React.FC<VideoElementProps> = ({
// Process subtitles - convert SRT to VTT blob URLs
useEffect(() => {
let cancelled = false
// Clean up old blob URLs
subtitleBlobUrlsRef.current.forEach((url) => URL.revokeObjectURL(url))
subtitleBlobUrlsRef.current = []
@@ -239,8 +235,17 @@ 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 }
}
@@ -253,13 +258,18 @@ export const VideoElement: React.FC<VideoElementProps> = ({
}
})
)
setProcessedSubtitles(processed)
// Only update state if not cancelled
if (!cancelled) {
setProcessedSubtitles(processed)
}
}
processSubtitles()
// Cleanup function
return () => {
cancelled = true
subtitleBlobUrlsRef.current.forEach((url) => URL.revokeObjectURL(url))
subtitleBlobUrlsRef.current = []
}
@@ -475,20 +485,50 @@ export const VideoElement: React.FC<VideoElementProps> = ({
const tracks = video.textTracks
if (!tracks || tracks.length === 0) return
// Disable all tracks first
for (let i = 0; i < tracks.length; i++) {
tracks[i].mode = 'hidden'
const enableSubtitle = () => {
// Disable all tracks first
for (let i = 0; i < tracks.length; i++) {
tracks[i].mode = 'hidden'
}
// Enable the selected subtitle track
if (settings.subtitle) {
for (let i = 0; i < tracks.length; i++) {
const track = tracks[i]
if (track.language === settings.subtitle.lang) {
// 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}`)
} else {
console.warn(`⚠️ Track ${track.label} has no cues yet, waiting...`)
// Track not ready yet, will be handled by load event
track.mode = 'showing'
}
break
}
}
}
}
// Enable the selected subtitle track
if (settings.subtitle) {
// Try to enable immediately
enableSubtitle()
// Also listen for track load events to retry
const handleTrackChange = () => {
console.log(`🔄 Track changed, re-enabling subtitle`)
enableSubtitle()
}
for (let i = 0; i < tracks.length; i++) {
tracks[i].addEventListener('load', handleTrackChange)
}
return () => {
for (let i = 0; i < tracks.length; i++) {
const track = tracks[i]
if (track.language === settings.subtitle.lang) {
track.mode = 'showing'
console.log(`Enabled subtitle track: ${track.label} (${track.language})`)
break
}
tracks[i].removeEventListener('load', handleTrackChange)
}
}
}, [settings.subtitle, videoRef])
@@ -500,12 +540,26 @@ export const VideoElement: React.FC<VideoElementProps> = ({
const handleTrackLoad = (e: Event) => {
const track = e.target as HTMLTrackElement
console.log(`Track loaded: ${track.label} (${track.srclang})`, track.readyState)
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})`, track.track.cues?.length)
console.error(`Track error: ${track.label} (${track.srclang})`)
console.error(` - src: ${track.src}`)
console.error(` - readyState: ${track.readyState}`)
}
const trackElements = video.querySelectorAll('track')
@@ -520,7 +574,11 @@ export const VideoElement: React.FC<VideoElementProps> = ({
for (let i = 0; i < textTracks.length; i++) {
const track = textTracks[i]
if (track.mode === 'showing') {
console.log(`Active track: ${track.label}, cues: ${track.cues?.length || 0}, active cues: ${track.activeCues?.length || 0}`)
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}"`)
}
}
}
}
@@ -529,6 +587,15 @@ export const VideoElement: React.FC<VideoElementProps> = ({
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)