1- import { useCallback , useEffect , useRef , useState } from 'react' ;
1+ import { useEffect , useRef , useState } from 'react' ;
22import { Alert , Result , Spin } from 'antd' ;
33import clsx from 'clsx' ;
44import { useAtomValue , useSetAtom , useAtom } from 'jotai' ;
@@ -29,17 +29,17 @@ const App = () => {
2929 const isKeyboardEnable = useAtomValue ( isKeyboardEnableAtom ) ;
3030 const setResolution = useSetAtom ( resolutionAtom ) ;
3131 const canvasRef = useRef < HTMLCanvasElement > ( null ) ;
32- const requestRef = useRef < number > ( 0 ) ;
3332 const videoRef = useRef < HTMLVideoElement > ( null ) ;
3433
3534 const [ isLoading , setIsLoading ] = useState ( true ) ;
3635 const [ isCameraAvailable , setIsCameraAvailable ] = useState ( false ) ;
3736
38- const renderFrame = useCallback ( ( ) => {
39- const video = videoRef . current ;
37+ const videoStyle = clsx ( 'block select-none origin-center max-w-full max-h-full object-scale-down' , mouseStyle )
38+
39+ const renderFrame = ( frame : VideoFrame ) => {
4040 const canvas = canvasRef . current ;
4141
42- if ( ! video || ! canvas || video . paused || video . ended ) return ;
42+ if ( ! canvas ) return ;
4343
4444 const ctx = canvas . getContext ( '2d' ) ;
4545 if ( ! ctx ) return ;
@@ -51,17 +51,15 @@ const App = () => {
5151 ctx . rotate ( ( videoRotate * Math . PI ) / 180 ) ;
5252
5353 ctx . drawImage (
54- video ,
55- - video . videoWidth / 2 ,
56- - video . videoHeight / 2 ,
57- video . videoWidth ,
58- video . videoHeight
54+ frame ,
55+ - frame . displayWidth / 2 ,
56+ - frame . displayHeight / 2 ,
57+ frame . displayWidth ,
58+ frame . displayHeight
5959 ) ;
6060
6161 ctx . restore ( ) ;
62-
63- requestRef . current = requestAnimationFrame ( renderFrame ) ;
64- } , [ videoRotate ] ) ;
62+ } ;
6563
6664 const setCanvas = ( ) => {
6765 const video = videoRef . current ;
@@ -77,11 +75,20 @@ const App = () => {
7775 canvas . height = video . videoWidth ;
7876 }
7977
80- if ( requestRef . current ) {
81- cancelAnimationFrame ( requestRef . current ) ;
78+ if ( videoRotate !== 0 ) {
79+ processVideoFrames ( ) ;
8280 }
81+ }
8382
84- renderFrame ( ) ;
83+ const processVideoFrames = ( ) => {
84+ const video = videoRef . current ;
85+ if ( video == null || videoRotate === 0 ) return ;
86+ video . requestVideoFrameCallback ( ( ) => {
87+ const frame = new VideoFrame ( video ) ;
88+ renderFrame ( frame ) ;
89+ frame . close ( ) ;
90+ processVideoFrames ( ) ;
91+ } )
8592 }
8693
8794 useEffect ( ( ) => {
@@ -173,21 +180,23 @@ const App = () => {
173180
174181 < video
175182 id = "video"
176- className = "hidden"
183+ className = { clsx ( videoRotate == 0 ? videoStyle : "hidden" , "min-h-[480px] min-w-[640px]" ) }
177184 ref = { videoRef }
178185 autoPlay
179186 playsInline
180187 onLoadedMetadata = { setCanvas }
181188 />
182189
183- < canvas
184- id = "video-canvas"
185- ref = { canvasRef }
186- className = { clsx ( 'block min-h-[480px] min-w-[640px] select-none origin-center max-w-full max-h-full object-scale-down' , mouseStyle ) }
187- style = { {
188- transform : `scale(${ videoScale } )` ,
189- } }
190- />
190+ { videoRotate == 0 ||
191+ < canvas
192+ id = "video-canvas"
193+ ref = { canvasRef }
194+ className = { videoStyle }
195+ style = { {
196+ transform : `scale(${ videoScale } )` ,
197+ } }
198+ />
199+ }
191200
192201 < VirtualKeyboard isBigScreen = { isBigScreen } />
193202 </ >
0 commit comments