|
|
|
@ -2,7 +2,7 @@ import { Transition } from "@/components/Transition"; |
|
|
|
import { useSettings } from "@/state/settings"; |
|
|
|
import { useSettings } from "@/state/settings"; |
|
|
|
import { sanitize, parseSubtitles } from "@/backend/helpers/captions"; |
|
|
|
import { sanitize, parseSubtitles } from "@/backend/helpers/captions"; |
|
|
|
import { ContentCaption } from "subsrt-ts/dist/types/handler"; |
|
|
|
import { ContentCaption } from "subsrt-ts/dist/types/handler"; |
|
|
|
import { useRef } from "react"; |
|
|
|
import { useRef, useEffect, useCallback } from "react"; |
|
|
|
import { useAsync } from "react-use"; |
|
|
|
import { useAsync } from "react-use"; |
|
|
|
import { useVideoPlayerDescriptor } from "../../state/hooks"; |
|
|
|
import { useVideoPlayerDescriptor } from "../../state/hooks"; |
|
|
|
import { useProgress } from "../../state/logic/progress"; |
|
|
|
import { useProgress } from "../../state/logic/progress"; |
|
|
|
@ -47,7 +47,7 @@ export function CaptionRendererAction({ |
|
|
|
const descriptor = useVideoPlayerDescriptor(); |
|
|
|
const descriptor = useVideoPlayerDescriptor(); |
|
|
|
const source = useSource(descriptor).source; |
|
|
|
const source = useSource(descriptor).source; |
|
|
|
const videoTime = useProgress(descriptor).time; |
|
|
|
const videoTime = useProgress(descriptor).time; |
|
|
|
const { captionSettings } = useSettings(); |
|
|
|
const { captionSettings, setCaptionDelay } = useSettings(); |
|
|
|
const captions = useRef<ContentCaption[]>([]); |
|
|
|
const captions = useRef<ContentCaption[]>([]); |
|
|
|
|
|
|
|
|
|
|
|
useAsync(async () => { |
|
|
|
useAsync(async () => { |
|
|
|
@ -60,20 +60,37 @@ export function CaptionRendererAction({ |
|
|
|
} catch (error) { |
|
|
|
} catch (error) { |
|
|
|
captions.current = []; |
|
|
|
captions.current = []; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// reset delay on every subtitle change
|
|
|
|
|
|
|
|
setCaptionDelay(0); |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
captions.current = []; |
|
|
|
captions.current = []; |
|
|
|
} |
|
|
|
} |
|
|
|
}, [source?.caption?.url]); |
|
|
|
}, [source?.caption?.url]); |
|
|
|
|
|
|
|
useEffect(() => { |
|
|
|
|
|
|
|
// reset delay after video ends
|
|
|
|
|
|
|
|
return () => setCaptionDelay(0); |
|
|
|
|
|
|
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
|
|
|
|
|
|
}, []); |
|
|
|
|
|
|
|
const isVisible = useCallback( |
|
|
|
|
|
|
|
( |
|
|
|
|
|
|
|
start: number, |
|
|
|
|
|
|
|
end: number, |
|
|
|
|
|
|
|
delay: number, |
|
|
|
|
|
|
|
currentTime: number |
|
|
|
|
|
|
|
): boolean => { |
|
|
|
|
|
|
|
const delayedStart = start / 1000 + delay; |
|
|
|
|
|
|
|
const delayedEnd = end / 1000 + delay; |
|
|
|
|
|
|
|
return ( |
|
|
|
|
|
|
|
Math.max(0, delayedStart) <= currentTime && |
|
|
|
|
|
|
|
Math.max(0, delayedEnd) >= currentTime |
|
|
|
|
|
|
|
); |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
[] |
|
|
|
|
|
|
|
); |
|
|
|
if (!captions.current.length) return null; |
|
|
|
if (!captions.current.length) return null; |
|
|
|
const isVisible = (start: number, end: number): boolean => { |
|
|
|
const visibileCaptions = captions.current.filter(({ start, end }) => |
|
|
|
const delayedStart = start / 1000 + captionSettings.delay; |
|
|
|
isVisible(start, end, captionSettings.delay, videoTime) |
|
|
|
const delayedEnd = end / 1000 + captionSettings.delay; |
|
|
|
); |
|
|
|
return ( |
|
|
|
|
|
|
|
Math.max(0, delayedStart) <= videoTime && |
|
|
|
|
|
|
|
Math.max(0, delayedEnd) >= videoTime |
|
|
|
|
|
|
|
); |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
return ( |
|
|
|
return ( |
|
|
|
<Transition |
|
|
|
<Transition |
|
|
|
className={[ |
|
|
|
className={[ |
|
|
|
@ -83,12 +100,9 @@ export function CaptionRendererAction({ |
|
|
|
animation="slide-up" |
|
|
|
animation="slide-up" |
|
|
|
show |
|
|
|
show |
|
|
|
> |
|
|
|
> |
|
|
|
{captions.current.map( |
|
|
|
{visibileCaptions.map(({ start, end, content }) => ( |
|
|
|
({ start, end, content }) => |
|
|
|
<CaptionCue key={`${start}-${end}`} text={content} /> |
|
|
|
isVisible(start, end) && ( |
|
|
|
))} |
|
|
|
<CaptionCue key={`${start}-${end}`} text={content} /> |
|
|
|
|
|
|
|
) |
|
|
|
|
|
|
|
)} |
|
|
|
|
|
|
|
</Transition> |
|
|
|
</Transition> |
|
|
|
); |
|
|
|
); |
|
|
|
} |
|
|
|
} |
|
|
|
|