直播 HTML5 视频绘制到 canvas 不工作
Live stream HTML5 video draw-to-canvas not working
我使用 ReactJS 使用 HTML5 视频元素显示实时流(来自我的网络摄像头)。 OpenVidu 媒体服务器处理后端。
我想使用 canvas
元素通过 drawImage() 方法将视频直播流绘制到 canvas 上。
我看过其他示例,但其中的视频元素始终有来源。我的没有来源——当我检查视频元素时,我看到的是:
<video autoplay id="remote-video-zfrstyztfhbojsoc_CAMERA_ZCBRG"/>
这是我试过的方法,但是 canvas 不起作用。
export default function Video({ streamManager }) {
const videoRef = createRef()
const canvasRef = createRef()
useEffect(() => {
if (streamManager && !!videoRef) {
//OpenVidu media server attaches the live stream to the video element
streamManager.addVideoElement(videoRef.current)
if (canvasRef.current) {
let ctx = canvasRef.current.getContext('2d')
ctx.drawImage(videoRef.current, 0, 0)
}
}
})
return (
<>
//video element displays the live stream
<video autoPlay={true} ref={videoRef} />
// canvas element NOT working, nothing can be seen on screen
<canvas autoplay={true} ref={canvasRef} width="250" height="250" />
</>
)
}
更新:经过进一步调查,我意识到我需要使用 setInterval() 函数,因此提供了以下解决方案。
您正在使用不带参数的 useEffect,这意味着您的 useEffect 将在每次渲染时调用
useEffect(() => {
// every render
})
如果你想 运行 你的 drawImage 只在挂载时使用 useEffect 和 []
useEffect(() => {
// run at component mount
},[])
或者如果您想 运行 在任何参数更改时绘制图像,然后将您的参数传递给它
useEffect(() => {
// run when your streamManager change
},[streamManager])
根据您的要求使用它
解决方案是在自包含组件中提取 canvas
逻辑,并使用 setInterval()
以便它每 100 毫秒在 canvas
上绘制视频元素(或根据需要)。
视频组件
import React, { useEffect, createRef } from 'react'
import Canvas from './Canvas'
export default function Video({ streamManager }) {
const videoRef = createRef()
useEffect(() => {
if (streamManager && !!videoRef) {
//OpenVidu media server attaches the live stream to the video element
streamManager.addVideoElement(videoRef.current)
}
})
return (
<>
//video element displays the live stream
<video autoPlay={true} ref={videoRef} />
//extract canvas logic in new component
<Canvas videoRef={videoRef} />
</>
)
}
Canvas 组件
import React, { createRef, useEffect } from 'react'
export default function Canvas({ videoRef }) {
const canvasRef = createRef(null)
useEffect(() => {
if (canvasRef.current && videoRef.current) {
const interval = setInterval(() => {
const ctx = canvasRef.current.getContext('2d')
ctx.drawImage(videoRef.current, 0, 0, 250, 188)
}, 100)
return () => clearInterval(interval)
}
})
return (
<canvas ref={canvasRef} width="250" height="188" />
)
}
我使用 ReactJS 使用 HTML5 视频元素显示实时流(来自我的网络摄像头)。 OpenVidu 媒体服务器处理后端。
我想使用 canvas
元素通过 drawImage() 方法将视频直播流绘制到 canvas 上。
我看过其他示例,但其中的视频元素始终有来源。我的没有来源——当我检查视频元素时,我看到的是:
<video autoplay id="remote-video-zfrstyztfhbojsoc_CAMERA_ZCBRG"/>
这是我试过的方法,但是 canvas 不起作用。
export default function Video({ streamManager }) {
const videoRef = createRef()
const canvasRef = createRef()
useEffect(() => {
if (streamManager && !!videoRef) {
//OpenVidu media server attaches the live stream to the video element
streamManager.addVideoElement(videoRef.current)
if (canvasRef.current) {
let ctx = canvasRef.current.getContext('2d')
ctx.drawImage(videoRef.current, 0, 0)
}
}
})
return (
<>
//video element displays the live stream
<video autoPlay={true} ref={videoRef} />
// canvas element NOT working, nothing can be seen on screen
<canvas autoplay={true} ref={canvasRef} width="250" height="250" />
</>
)
}
更新:经过进一步调查,我意识到我需要使用 setInterval() 函数,因此提供了以下解决方案。
您正在使用不带参数的 useEffect,这意味着您的 useEffect 将在每次渲染时调用
useEffect(() => {
// every render
})
如果你想 运行 你的 drawImage 只在挂载时使用 useEffect 和 []
useEffect(() => {
// run at component mount
},[])
或者如果您想 运行 在任何参数更改时绘制图像,然后将您的参数传递给它
useEffect(() => {
// run when your streamManager change
},[streamManager])
根据您的要求使用它
解决方案是在自包含组件中提取 canvas
逻辑,并使用 setInterval()
以便它每 100 毫秒在 canvas
上绘制视频元素(或根据需要)。
视频组件
import React, { useEffect, createRef } from 'react'
import Canvas from './Canvas'
export default function Video({ streamManager }) {
const videoRef = createRef()
useEffect(() => {
if (streamManager && !!videoRef) {
//OpenVidu media server attaches the live stream to the video element
streamManager.addVideoElement(videoRef.current)
}
})
return (
<>
//video element displays the live stream
<video autoPlay={true} ref={videoRef} />
//extract canvas logic in new component
<Canvas videoRef={videoRef} />
</>
)
}
Canvas 组件
import React, { createRef, useEffect } from 'react'
export default function Canvas({ videoRef }) {
const canvasRef = createRef(null)
useEffect(() => {
if (canvasRef.current && videoRef.current) {
const interval = setInterval(() => {
const ctx = canvasRef.current.getContext('2d')
ctx.drawImage(videoRef.current, 0, 0, 250, 188)
}, 100)
return () => clearInterval(interval)
}
})
return (
<canvas ref={canvasRef} width="250" height="188" />
)
}