视频捕获期间移动 safari 内存不足

Mobile safari out of memory during video capturing

我的 React class 有两个主要元素。 Canvas 和视频。 我获取视频流并以 30fps 将其渲染到 canvas。

class GetImage extends Component {

  constructor() {
    super();
    this.constraints = {
      video: {
        width: { ideal: 2048 },
        height: { ideal: 1080 },
        facingMode: {
          exact: 'environment'
        }
      }
    }
  }

  componentDidMount() {
    setVideo(this.video, this.constraints, this.readyToPlayVideo)
  }

  capture = () => {
    const { video } = this
    let canvas = document.createElement('canvas')
    canvas.width = video.videoWidth
    canvas.height = video.videoHeight

    let context = canvas.getContext('2d')
    context.clearRect(0, 0, canvas.width, canvas.height);
    context.drawImage(this.video, 0, 0, canvas.width, canvas.height)
    this.setState({ capture: canvas.toDataURL('image/jpeg') })
    stopVideo()
  }


  readyToPlayVideo = () => {
    const { canvas, video }  = this
    const { offsetHeight, offsetWidth } = video
    const ctx = canvas.getContext('2d')
    ctx.canvas.setAttribute('height', offsetHeight)
    ctx.canvas.setAttribute('width', offsetWidth)

    const timeout = 1000 / 30 // drawing at 30fps

    ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);

    let _listener = () => {
      (function loop() {
        ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
        ctx.drawImage(video, 0, 0)
        setTimeout(loop, timeout)
      })()
    }

    _listener();
  }


  retake = () =>
    this.setState({ capture: null },
      () => {
        setVideo(this.video, this.constraints, this.readyToPlayVideo, this.handleError)
      }
    )

  render() {
    return (
        <div>
          <video
            style={{ visibility: 'hidden'}}
            ref={video => (this.video = video)}
            playsInline
            autoPlay
          />
          <canvas ref={canvas => (this.canvas = canvas)}/>
        </div>
    )
  }
}

到目前为止一切顺利。 但是我遇到了移动版 Safari 的问题。看起来它保留了内存中创建的每个 Canvas 对象。

拍了几张照片后,Safari 崩溃 "out of memory"。 我已经在渲染新图像之前执行了 clearRect,但这没有帮助。

不确定这是否能 100% 解决您的问题,但这可能会有所帮助。不要为你的动画使用 setInterval,而是使用 window.requestAnimationFrame.

这是一个例子

var requestAnimFrame = (function() {
    return  window.requestAnimationFrame       ||
            window.webkitRequestAnimationFrame ||
            window.mozRequestAnimationFrame    ||
            window.msRequestAnimationFrame     ||
            function( callback ) {
                window.setTimeout(callback, 1000 / 30);
            };
})();

function loop(){
     requestAnimFrame(loop);
     ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
     ctx.drawImage(video, 0, 0);
     setTimeout(loop, timeout);
}
loop();

再说一次,我不是 100% 确定这会解决您的问题,但是,它可能会有所帮助。如果您还有其他问题,请告诉我。

希望对您有所帮助!

这里有几个问题需要解决。首先,您的 loop 函数中似乎有一个循环引用;您正在调用函数内的函数。

因此,自动播放视频(渲染时)不会停止..导致 'out of memory' 错误。

此外,我认为最佳做法是创建一个 componentDidUnmount 函数来销毁视频(当不再需要时)。使用.dispose销毁视频。

希望对您有所帮助