将网络摄像头视频渲染到画布时,超出了最大调用堆栈大小

时间:2019-02-22 01:43:03

标签: javascript reactjs canvas webrtc

我正在开发一个应用程序,其中一个会话中将有两个参与者,他们可以进行视频通话。基本上,将有3个视频流。两名参与者和一名参与者将共享屏幕。这部分已经在工作,但是当用户单击“录制”按钮时,应将这3个视频馈入画布,并在暂停时将其暂停。我正在尝试在画布中仅渲染一个视频以进行测试,// your array var array = [ [ [3, 5], //a [8, 2], //b [5, 3], //c [8, 1], //d ], [ [3, 9], //a [7, 4], //b [5, 6], //c [8, 8], //d ], ]; // your variables var sum = 0, id = 1; // your function as it is var fun = (a, b, c, d) => { sum = array[a][0][1] + array[b][1][1] + array[c][2][1] + array[d][3][1]; console.log('ID: ' + id++ + ' Sum = ' + sum); }; // and in just one line using map function array.map((_, a) => array.map((_, b) => array.map((_, c) => array.map((_, d) => fun(a, b, c, d)))))

"RangeError: Maximum call stack size exceeded on draw function ".

错误在此行const draw = (canva, context) => { console.log('localVideoRef', localVideoRef) context.drawImage(localVideoRef.current, 0, 0, canva.clientWidth, canva.clientHeight); console.log('context draw', context) requestAnimationFrame(draw(canva, context)) } const handleRecord = () => { const canva = document.createElement('canvas'); canva.id = "canvas"; const context = canva.getContext("2d"); canva.width = canva.clientWidth; canva.width = canva.clientHeight; console.log('canva', context, canva); console.log('room', room); draw(canva, context); requestAnimationFrame(draw(canva, context)) # above error is shown here console.log('canva after drawing image', canva); }

更新(即使停止记录后仍继续运行)

requestAnimationFrame(draw(canva, context))

2 个答案:

答案 0 :(得分:2)

requestAnimationFrame(draw(canva, context))

此代码将立即调用draw,然后将draw的返回值传递到requestAnimationFrame中。在绘图内部,您可以重复此过程,立即调用绘图,立即调用绘图等。

相反,您希望将函数传递到请求动画帧中,如下所示:

requestAnimationFrame(() => draw(canva, context));

答案 1 :(得分:1)

嗨,这是因为您已经已经在您的requestAnimationFrame()代码中调用draw()。因此,该函数已经是递归的。通过调用drawrequestAnimationFrame(draw),您可以一次调用2个无限递归函数。只需删除draw(),它就会起作用:

const draw = (canva, context) => {
    console.log('localVideoRef', localVideoRef)
    context.drawImage(localVideoRef.current, 0, 0, canva.clientWidth, canva.clientHeight);
    console.log('context draw', context)
    requestAnimationFrame( (timestamp)=>draw(canva, context) ); // EDITED AS PER @Nicholas' answer.
}
const handleRecord = () => {
    const canva = document.createElement('canvas');
    canva.id = "canvas";
    const context = canva.getContext("2d");
    canva.width = canva.clientWidth;
    canva.width = canva.clientHeight;
    console.log('canva', context, canva);
    console.log('room', room);
    //draw(canva, context);        //just remove this line
    requestAnimationFrame( (timestamp)=>draw(canva, context) ) // EDITED AS PER @Nicholas' answer.
    console.log('canva after drawing image', canva);
}

请查看此documentation,以获取有关requestAnimationFrame的更多详细信息。请注意,在它们的示例中,调用了requestAnimationFrame(step),但没有调用step()

更新: 正如@Nicholas指出的那样,您需要将draw函数包装在另一个函数中。如上所示。

关于为什么会导致maximum call size exceeded错误,我实际上有点困惑。当我在Chrome控制台上测试错误的代码时,却收到此错误:

  

未捕获的TypeError:无法在“窗口”上执行“ requestAnimationFrame”:作为参数1提供的回调不是函数。

这实际上在理论上是正确的。将requestAnimationFrame视为类似于setTimeout的事物。 setTimeout使用类似setTimeout(callback, time);的回调; requestAnimationFrame也是如此。

传递requestAnimationFrame( draw(canva, context) )时,基本上是在告诉requestAnimationFrame函数在其代码中的某处执行 draw(canva, context)() ,而不是 draw(canva, context) < / strong>,正如您所期望的那样。因此,它在我的Chrome控制台上引发了callback provided is not a function错误。

但是对于 max call stack exceeded 错误,我认为您的JavaScript引擎/编译器的requestAnimationFrame捕获了该错误,将其忽略,然后然后继续调用draw函数。因此,这基本上转化为:

draw = (canva, context)=>{
    ...
    draw(canva, context) //oh noes
}

现在基本上是无限运行的递归函数。 因此,maximum call stack exceeded错误。