直播 HTML5 视频绘制到画布不工作

Posted

技术标签:

【中文标题】直播 HTML5 视频绘制到画布不工作【英文标题】:Live stream HTML5 video draw-to-canvas not working 【发布时间】:2020-05-09 03:52:08 【问题描述】:

我使用 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   />
    </>
  )

更新:经过进一步调查,我意识到我需要使用 setInterval() 函数,因此提供了以下解决方案。

【问题讨论】:

【参考方案1】:

您正在使用不带参数的 useEffect,这意味着您的 useEffect 将在每个渲染中调用

  useEffect(() => 
     // every render 
  )

如果你只想在挂载时运行你的 drawImage,那么使用 useEffect 和 []

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

或者如果您想在任何参数更改时运行drawImage,然后将您的参数传递给它

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

根据您的要求使用它

【讨论】:

感谢您的观察,useEffect 确实缺少参数 [],但这不是问题,因为在这种情况下,组件不会多次重新渲染自身。经过进一步调查,我发现我的组件中只需要一个 setInterval() 函数,因此我提供了以下解决方案。【参考方案2】:

解决方案是在自包含组件中提取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 />

    </>
  )

画布组件

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   />
  )

【讨论】:

以上是关于直播 HTML5 视频绘制到画布不工作的主要内容,如果未能解决你的问题,请参考以下文章

ReactJS画布drawImage不显示html5视频元素

HTML5:在带有控件的视频上放置画布

HTML5:在 IOS Safari 中手动“播放”画布内的视频

在画布上用鼠标绘制矩形与鼠标坐标不同步

html5:在画布内显示视频

html5:在画布内显示视频