Прямая трансляция HTML5-видео с отрисовкой на холст не работает
Я использую ReactJS для отображения прямой трансляции (с моей веб-камеры) с помощью элемента видео HTML5. Медиа-сервер OpenVidu обрабатывает бэкэнд. Я хотел бы использоватьcanvas
для рисования видеопотока на холсте с помощью метода drawImage().
Я видел и другие примеры, но в них у видеоэлемента всегда есть источник. У меня нет источника - когда я проверяю видеоэлемент, я вижу только следующее:
<video autoplay id="remote-video-zfrstyztfhbojsoc_CAMERA_ZCBRG"/>
Это то, что я пробовал, но холст не работает.
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(), и поэтому предоставил решение ниже.
2 ответа
Решение состоит в том, чтобы извлечь canvas
логики в автономном компоненте и используйте setInterval()
так что он будет рисовать видеоэлемент на canvas
каждые 100 мс (или по мере необходимости).
Видео компонент
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} />
</>
)
}
Компонент холста
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" />
)
}
Вы используете useEffect без параметра, что означает, что ваш useEffect будет вызывать каждый рендер
useEffect(() => {
// every render
})
Если вы хотите запустить drawImage только во время монтирования, используйте useEffect с []
useEffect(() => {
// run at component mount
},[])
Или, если вы хотите запустить drawImage при изменении любого параметра, передайте ему свой параметр
useEffect(() => {
// run when your streamManager change
},[streamManager])
используйте его согласно вашему требованию