canvas 复制 canvas

场景是这样的,业务上有一个视频通话,视频窗口是canvas的,有需求要做截图的功能,而且截图需要是canvas的。

视频通话的视频源是通过yuv数组传过来的,按点阵渲染成了canvas,如果是通过WebRTC的视频流传输(页面是video标签)就不会出现这个问题。

代码基本是这个样子的

html

<!-- 视频 -->
<canvas id="video" width="800" height="600"></canvas>

<!-- 截图 -->
<canvas id="photo" width="800" height="600"></canvas>

<!-- 截图按钮 -->
<button id="snap-button"></button>

js

$('#snap-button').on('click', function () {
  var source = $('#video')[0];
  var target = $('#photo')[0];
  var context = target.getContext('2d');
  context.drawImage(source, 0, 0, 800, 600);
});

然而神奇的一幕发生了,点击按钮测试截图效果,大概七八十回有一两回能截图成功,而且还是反的。

我试过如果把需要截图的视频canvas替换成一个静态的canvas,截图是100%成功的,那么问题来了,我该怎么保证动态的视频canvas能够截图成功呢?谢谢。

阅读 11.4k
2 个回答

后来测试了一下,基于video标签的视频截图不会出问题,比如WebRTC那样的,同时动态的canvas也不会出问题。

这就很尴尬了。

最后用了这个蠢办法先解决一下,blankData是截图失败的空白canvas出来的数据,我自己new出来的canvas结果跟它还不一样,蛋疼的很,等到真正解决了再回来补充。


var blankData = "data:image/png;base64,iVBORw0KGgoAA.......";
$('.snapshot-button').on('click', function (e) {
    //create a new canvas
    var oldCanvas = document.getElementById('video');
    var newCanvas = document.getElementById('photo');
    var context = newCanvas.getContext('2d');

    //set dimensions
    newCanvas.width = oldCanvas.width;
    newCanvas.height = oldCanvas.height;

    context.clearRect(0, 0, 664, 498);
    //apply the old canvas to the new one
    var i = 0;
    var timer = setInterval(function () {
      if (newCanvas.toDataURL() != blankData || i++ >= 100) {
        clearInterval(timer);
      }
      context.drawImage(oldCanvas, 0, 0, 664, 498);
    }, 10);
});

要想正常截图,需要了解canvas的渲染机制,电脑每秒能渲染的图片数量是有上限的,所以不能使用for来批量获取到截图,另外getDataUrl本身就是一个比较消耗性能的方法,需要在视图渲染后执行才会得到帧图,你可以在requestAnimationFrame中成功截取到每帧的图片

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题