Fix jsmpeg player flickering (#12213)

This commit is contained in:
Josh Hawkins 2024-06-29 18:45:28 -05:00 committed by GitHub
parent 21a777ab45
commit f0159bf41e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -30,6 +30,8 @@ export default function JSMpegPlayer({
const internalContainerRef = useRef<HTMLDivElement | null>(null); const internalContainerRef = useRef<HTMLDivElement | null>(null);
const onPlayingRef = useRef(onPlaying); const onPlayingRef = useRef(onPlaying);
const [showCanvas, setShowCanvas] = useState(false); const [showCanvas, setShowCanvas] = useState(false);
const [hasData, setHasData] = useState(false);
const [dimensionsReady, setDimensionsReady] = useState(false);
const selectedContainerRef = useMemo( const selectedContainerRef = useMemo(
() => (containerRef.current ? containerRef : internalContainerRef), () => (containerRef.current ? containerRef : internalContainerRef),
@ -70,6 +72,7 @@ export default function JSMpegPlayer({
return finalHeight; return finalHeight;
} }
} }
return undefined;
}, [ }, [
aspectRatio, aspectRatio,
containerWidth, containerWidth,
@ -85,8 +88,15 @@ export default function JSMpegPlayer({
if (aspectRatio && scaledHeight) { if (aspectRatio && scaledHeight) {
return Math.ceil(scaledHeight * aspectRatio); return Math.ceil(scaledHeight * aspectRatio);
} }
return undefined;
}, [scaledHeight, aspectRatio]); }, [scaledHeight, aspectRatio]);
useEffect(() => {
if (scaledWidth && scaledHeight) {
setDimensionsReady(true);
}
}, [scaledWidth, scaledHeight]);
useEffect(() => { useEffect(() => {
onPlayingRef.current = onPlaying; onPlayingRef.current = onPlaying;
}, [onPlaying]); }, [onPlaying]);
@ -98,7 +108,6 @@ export default function JSMpegPlayer({
const videoWrapper = videoRef.current; const videoWrapper = videoRef.current;
const canvas = canvasRef.current; const canvas = canvasRef.current;
let hasData = false;
let videoElement: JSMpeg.VideoElement | null = null; let videoElement: JSMpeg.VideoElement | null = null;
if (videoWrapper && playbackEnabled) { if (videoWrapper && playbackEnabled) {
@ -114,8 +123,7 @@ export default function JSMpegPlayer({
videoBufferSize: 1024 * 1024 * 4, videoBufferSize: 1024 * 1024 * 4,
onVideoDecode: () => { onVideoDecode: () => {
if (!hasData) { if (!hasData) {
hasData = true; setHasData(true);
setShowCanvas(true);
onPlayingRef.current?.(); onPlayingRef.current?.();
} }
}, },
@ -139,15 +147,29 @@ export default function JSMpegPlayer({
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
}, [playbackEnabled, url]); }, [playbackEnabled, url]);
useEffect(() => {
setShowCanvas(hasData && dimensionsReady);
}, [hasData, dimensionsReady]);
return ( return (
<div className={cn(className, !containerRef.current && "size-full")}> <div className={cn(className, !containerRef.current && "size-full")}>
<div className="internal-jsmpeg-container" ref={internalContainerRef}> <div
<div ref={videoRef} className={cn("jsmpeg", !showCanvas && "hidden")}> className="internal-jsmpeg-container size-full"
ref={internalContainerRef}
>
<div
ref={videoRef}
className={cn(
"jsmpeg flex h-full w-auto items-center justify-center",
!showCanvas && "hidden",
)}
>
<canvas <canvas
ref={canvasRef} ref={canvasRef}
className="rounded-lg md:rounded-2xl"
style={{ style={{
width: scaledWidth ?? width, width: scaledWidth,
height: scaledHeight ?? height, height: scaledHeight,
}} }}
></canvas> ></canvas>
</div> </div>