Прямая трансляция HTML5 видео на холсте не работает - PullRequest
0 голосов
/ 23 января 2020

Я использую 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 ]

0 голосов
/ 23 января 2020

Решение состоит в том, чтобы извлечь canvas logi c в автономный компонент и использовать 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} />

    </>
  )
}

Компонент 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" />
  )
}
0 голосов
/ 23 января 2020

Вы используете useEffect без параметра, что означает, что ваш useEffect будет вызываться при каждом рендеринге

  useEffect(() => {
     // every render 
  })

Если вы хотите запускать drawImage только во время монтирования, используйте useEffect с []

  useEffect(() => {
      // run at component mount 
  },[])

Или, если вы хотите запустить drawImage при любом изменении параметра, передайте ему свой параметр

   useEffect(() => {
          // run when your streamManager change
      },[streamManager])

используйте его согласно вашему требованию

...