I am trying to draw the video frames on canvas in react basically something which is already done in vanilla java script into react little differently.
vanilla js code:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div>
<video id="video" width="800" src="./media/video.mp4" autoplay muted loop></video>
<canvas id="output-canvas" width="800" height="450"></canvas>
</div>
<script>
let video, c1, ctx1, c_tmp, ctx_tmp;
function init() {
video = document.getElementById('video');
c1 = document.getElementById('output-canvas');
ctx1 = c1.getContext('2d');
c_tmp = document.createElement('canvas');
c_tmp.setAttribute('width', 800);
c_tmp.setAttribute('height', 450);
ctx_tmp = c_tmp.getContext('2d');
video.addEventListener('play', computeFrame);
}
function computeFrame() {
ctx_tmp.drawImage(video, 0, 0, video.videoWidth, video.videoHeight);
let frame = ctx_tmp.getImageData(0, 0, video.videoWidth, video.videoHeight);
ctx1.putImageData(frame, 0, 0);
setTimeout(computeFrame, 0);
}
document.addEventListener("DOMContentLoaded", () => {
init();
});
</script>
</body>
</html>
Now my same try for implementation in react is below
import logo from './logo.svg';
import './App.css';
import React from 'react';
import {useRef,useState, useEffect} from 'react';
import gvideo from './assets/videos/gvid.mp4'
function App() {
const video = useRef(null);
const c1= useRef(null);
const c2= useRef(null);
const [playerState, setPlayerState] = useState({
isPlaying: false,
progress: 0,
speed: 1,
isMuted: false,
});
let width= video.clientWidth;
let height= video.clientHeight;
let ctx= c2.current.getContext('2d');
function drawVid(){
ctx.drawImage(video,0,0,width,height);
let frame= ctx.getImageData(0,0,width,height);
for(let i=0; i<frame.data.length; i+=4){
let r= frame.data[i];
let g= frame.data[i+1];
let b= frame.data[i+2];
}
requestAnimationFrame(drawVid);
}
useEffect(() => {
// drawVid()
});
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<video ref={video} id="my_video" src={gvideo} height="300" width="600" autoPlay loop muted ></video>
<canvas style={{display:"none"}} ref={c1} id="c1" width="160" height="96"></canvas>
<canvas ref={c2} id="c2" width="300" height="400"></canvas>
<p>
Edit {playerState.isPlaying} <code>src/App.js</code> and save to reload.
</p>
<a
className="App-link"
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
Learn React
</a>
</header>
</div>
);
}
export default App;
kindly someone guide me , I have to implement something similar to this i.e. chroma keying
Bascially you have done right, but pay attention:
video.current
instead ofvideo
in yourfunction drawVid
, and in thewidth/height
inititaion. Check Hooks Referencelet ctx= c2.current.getContext('2d');
may cause error at first, because the c2.current will be null until the canvas really mounted. Try put it insidefunction drawId
and make some protection likeAnd it's better to do same protection for video