mirror of
https://github.com/truewhile/MeBox.git
synced 2026-10-07 22:06:38 +08:00
b u g
b u g
This commit is contained in:
@@ -115,12 +115,6 @@ export function PlayerVideoStage({
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const timers = new Set<ReturnType<typeof setTimeout>>()
|
|
||||||
const delay = (fn: () => void, ms: number) => {
|
|
||||||
const id = setTimeout(fn, ms)
|
|
||||||
timers.add(id)
|
|
||||||
}
|
|
||||||
|
|
||||||
const updateCue = () => {
|
const updateCue = () => {
|
||||||
const trackEls = Array.from(video.querySelectorAll('track'))
|
const trackEls = Array.from(video.querySelectorAll('track'))
|
||||||
const selectedEl = trackEls[subtitleIndex]
|
const selectedEl = trackEls[subtitleIndex]
|
||||||
@@ -130,16 +124,24 @@ export function PlayerVideoStage({
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 优先从浏览器 activeCues 中取当前文本;若浏览器在 hidden 模式下延迟触发 cuechange,
|
||||||
|
// 则从 tt.cues 中根据 video.currentTime 实时匹配当前字幕,确保初次加载无感立即可见。
|
||||||
|
const texts: string[] = []
|
||||||
if (tt.activeCues && tt.activeCues.length > 0) {
|
if (tt.activeCues && tt.activeCues.length > 0) {
|
||||||
const texts: string[] = []
|
|
||||||
for (let i = 0; i < tt.activeCues.length; i++) {
|
for (let i = 0; i < tt.activeCues.length; i++) {
|
||||||
const cue = tt.activeCues[i] as VTTCue
|
const cue = tt.activeCues[i] as VTTCue
|
||||||
if (cue && cue.text) texts.push(cue.text)
|
if (cue && cue.text) texts.push(cue.text)
|
||||||
}
|
}
|
||||||
setActiveCueText(texts.join('\n'))
|
} else if (tt.cues && tt.cues.length > 0) {
|
||||||
} else {
|
const cur = video.currentTime
|
||||||
setActiveCueText('')
|
for (let i = 0; i < tt.cues.length; i++) {
|
||||||
|
const cue = tt.cues[i] as VTTCue
|
||||||
|
if (cue && cur >= cue.startTime && cur <= cue.endTime && cue.text) {
|
||||||
|
texts.push(cue.text)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
setActiveCueText(texts.join('\n'))
|
||||||
}
|
}
|
||||||
|
|
||||||
const apply = () => {
|
const apply = () => {
|
||||||
@@ -162,18 +164,8 @@ export function PlayerVideoStage({
|
|||||||
tt.addEventListener('cuechange', updateCue)
|
tt.addEventListener('cuechange', updateCue)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 竞态兜底重载检测
|
selected.removeEventListener('load', updateCue)
|
||||||
delay(() => {
|
selected.addEventListener('load', updateCue)
|
||||||
const curTt = selected.track
|
|
||||||
if (curTt && curTt.mode === 'hidden' && (!curTt.cues || curTt.cues.length === 0)) {
|
|
||||||
const src = selected.getAttribute('src')
|
|
||||||
if (src) {
|
|
||||||
selected.setAttribute('src', '')
|
|
||||||
selected.setAttribute('src', src)
|
|
||||||
curTt.mode = 'hidden'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, 1200)
|
|
||||||
|
|
||||||
updateCue()
|
updateCue()
|
||||||
}
|
}
|
||||||
@@ -183,20 +175,24 @@ export function PlayerVideoStage({
|
|||||||
video.addEventListener('timeupdate', updateCue)
|
video.addEventListener('timeupdate', updateCue)
|
||||||
video.addEventListener('seeking', updateCue)
|
video.addEventListener('seeking', updateCue)
|
||||||
video.addEventListener('seeked', updateCue)
|
video.addEventListener('seeked', updateCue)
|
||||||
|
video.addEventListener('playing', updateCue)
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
video.removeEventListener('loadedmetadata', apply)
|
video.removeEventListener('loadedmetadata', apply)
|
||||||
video.removeEventListener('timeupdate', updateCue)
|
video.removeEventListener('timeupdate', updateCue)
|
||||||
video.removeEventListener('seeking', updateCue)
|
video.removeEventListener('seeking', updateCue)
|
||||||
video.removeEventListener('seeked', updateCue)
|
video.removeEventListener('seeked', updateCue)
|
||||||
timers.forEach(clearTimeout)
|
video.removeEventListener('playing', updateCue)
|
||||||
const trackEls = Array.from(video.querySelectorAll('track'))
|
const trackEls = Array.from(video.querySelectorAll('track'))
|
||||||
const selected = trackEls[subtitleIndex]
|
const selected = trackEls[subtitleIndex]
|
||||||
if (selected?.track) {
|
if (selected) {
|
||||||
selected.track.removeEventListener('cuechange', updateCue)
|
selected.removeEventListener('load', updateCue)
|
||||||
|
if (selected.track) {
|
||||||
|
selected.track.removeEventListener('cuechange', updateCue)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [subtitleIndex, subs, videoRef])
|
}, [subtitleIndex, subs, videoRef, media])
|
||||||
|
|
||||||
// 根据视频画面宽高比与舞台宽高比,确定视频在哪个轴向撑满 100%
|
// 根据视频画面宽高比与舞台宽高比,确定视频在哪个轴向撑满 100%
|
||||||
const isWiderThanStage =
|
const isWiderThanStage =
|
||||||
@@ -238,13 +234,14 @@ export function PlayerVideoStage({
|
|||||||
className="h-full w-full object-contain bg-black"
|
className="h-full w-full object-contain bg-black"
|
||||||
onError={onVideoError}
|
onError={onVideoError}
|
||||||
>
|
>
|
||||||
{subs.map((track) => (
|
{subs.map((track, index) => (
|
||||||
<track
|
<track
|
||||||
key={track.path}
|
key={track.path}
|
||||||
kind="subtitles"
|
kind="subtitles"
|
||||||
src={subtitlesAPI.url(media.id, track.path)}
|
src={subtitlesAPI.url(media.id, track.path)}
|
||||||
srcLang={track.lang}
|
srcLang={track.lang}
|
||||||
label={track.label || track.lang}
|
label={track.label || track.lang}
|
||||||
|
default={index === subtitleIndex}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</video>
|
</video>
|
||||||
|
|||||||
Reference in New Issue
Block a user