视频操作
你可以使用 drawImage() API 在 <canvas> 元素上绘制 <OffthreadVideo>、<Video> 或 <Html5Video> 的帧。
🌐 You can draw frames of a <OffthreadVideo>, <Video> or a <Html5Video> onto a <canvas> element using the drawImage() API.
在预览期间,使用 requestVideoFrameCallback() API。
浏览器支持:Firefox 130(2024年8月)、Chrome 83、Safari 15.4。
基本示例
🌐 Basic example
在此示例中,一个 <OffthreadVideo> 被渲染并设置为不可见。 每帧发出的内容都会绘制到画布上,并应用灰度 filter。
🌐 In this example, an <OffthreadVideo> is rendered and made invisible.
Every frame that is emitted is drawn to a Canvas and a grayscale filter is applied.
export const VideoOnCanvas : React .FC = () => {
const video = useRef <HTMLVideoElement >(null);
const canvas = useRef <HTMLCanvasElement >(null);
const {width , height } = useVideoConfig ();
// Process a frame
const onVideoFrame = useCallback (
(frame : CanvasImageSource ) => {
if (!canvas .current ) {
return;
}
const context = canvas .current .getContext ('2d');
if (!context ) {
return;
}
context .filter = 'grayscale(100%)';
context .drawImage (frame , 0, 0, width , height );
},
[height , width ],
);
return (
<AbsoluteFill >
<AbsoluteFill >
<OffthreadVideo
// Hide the original video tag
style ={{opacity : 0}}
onVideoFrame ={onVideoFrame }
src ="https://remotion.media/BigBuckBunny.mp4"
/>
</AbsoluteFill >
<AbsoluteFill >
<canvas ref ={canvas } width ={width } height ={height } />
</AbsoluteFill >
</AbsoluteFill >
);
};绿幕示例
🌐 Greenscreen example
在这个例子中,我们遍历图片缓冲区中的每个像素,如果它是绿色的,我们就将其透明化。拖动下面的滑块可以使视频变得透明。
🌐 In this example, we loop over each pixel in the image buffer and if it's green, we transparentize it. Drag the slider below to turn the video transparent.
export const Greenscreen : React .FC <{
opacity : number;
}> = ({opacity }) => {
const canvas = useRef <HTMLCanvasElement >(null);
const {width , height } = useVideoConfig ();
// Process a frame
const onVideoFrame = useCallback (
(frame : CanvasImageSource ) => {
if (!canvas .current ) {
return;
}
const context = canvas .current .getContext ('2d');
if (!context ) {
return;
}
context .drawImage (frame , 0, 0, width , height );
const imageFrame = context .getImageData (0, 0, width , height );
const {length } = imageFrame .data ;
// If the pixel is very green, reduce the alpha channel
for (let i = 0; i < length ; i += 4) {
const red = imageFrame .data [i + 0];
const green = imageFrame .data [i + 1];
const blue = imageFrame .data [i + 2];
if (green > 100 && red < 100 && blue < 100) {
imageFrame .data [i + 3] = opacity * 255;
}
}
context .putImageData (imageFrame , 0, 0);
},
[height , width ],
);
return (
<AbsoluteFill >
<AbsoluteFill >
<OffthreadVideo style ={{opacity : 0}} onVideoFrame ={onVideoFrame } src ="https://remotion.media/greenscreen.mp4" />
</AbsoluteFill >
<AbsoluteFill >
<canvas ref ={canvas } width ={width } height ={height } />
</AbsoluteFill >
</AbsoluteFill >
);
};在 v4.0.190 之前
🌐 Before v4.0.190
在 v4.0.190 之前,<OffthreadVideo> 和 <Html5Video> 的 onVideoFrame 属性不受支持。
你只能使用 requestVideoFrameCallback API 操作 <Html5Video>。
点击 这里 查看此页面的旧版。
🌐 Before v4.0.190, the onVideoFrame prop of <OffthreadVideo> and <Html5Video> was not supported.
You could only manipulate a <Html5Video> using the requestVideoFrameCallback API.
Click here to see the old version of this page.