来自视频的HTML5 Canvas drawImage在第一次绘制时不显示

时间:2013-11-14 21:00:27

标签: javascript html5 video canvas drawimage

我有一个带有画布覆盖的视频元素。然后我有一个绘图工具设置来绘制视频和一个保存按钮,从视频和画布执行drawImage以保存一个压缩帧。但是,我第一次按Save我只从画布drawImage获得结果,视频没有显示。在随后的保存中,我收到两个图像正确分层。我认为这可能是加载视频图像的问题,但是在我点击保存之前视频已经完全加载,甚至可以推进帧并使其在第二次保存时正常工作。

这是代码......

<div style="width:960px; height:540px; display:inline-block;">
    <video id="video" src="media/_tmp/AA_017_COMP_v37.mov" width="960" height="540" ></video>
</div>
<canvas id="canvas" width="960" height="540" style="position:absolute; top:40px; left:9px; z-index:100;"></canvas>
<input type="button" value="save" id="btn" size="30" onclick="save()" style="float:left; padding:4px; margin-right:4px;" >
<div id="saved" style="border:1px solid #000; position:absolute; top:626px; left:10px; bottom:40px; width:958px; overflow:auto;">SAVED:</div>


function save() {

    //COMP CANVAS OVER VIDEOFRAME
    var video = document.getElementById("video");
    var currentFrame = Math.floor((<?php echo $mov_frames ?> / video.duration) * video.currentTime);

    var compCanvas = document.createElement('canvas');
    compCanvas.width = video.width;
    compCanvas.height = video.height;
    compContext = compCanvas.getContext('2d');
    compContext.drawImage(video, 0, 0);
    compContext.drawImage(canvas, 0, 0);
    var dataURL = compCanvas.toDataURL();

    $("#saved").append('<div style="width:954px; border-bottom:1px solid #000; padding:2px 2px 0 2px;"><img id="compFrame_'+currentFrame+'" width="180" height="90" src="'+dataURL+'" />Frame: '+currentFrame+'</div>');
}

3 个答案:

答案 0 :(得分:2)

因为这是OSX OS上的一些坏消息:

  

注意:视频作为画布drawImage()方法的源不是   目前在iOS上受支持。

Source

如果这是过时的信息,我不知道,但在任何一种情况下,当前的实施都存在问题。正如已建立的(在评论中),问题可能与编解码器无关,因为这也与其他格式一起出现。 fiddletoDataURL()方法排除为源,因此剩下的就是drawImage()方法。

由于这可以在其他平台上使用提供的代码,从它的外观来看,这既不是问题的根源,所以你在这里用OSX平台上的Safari浏览器查看一个非常可能的问题(bug)

上面引用的官方文档也说明这不受支持,所以这可能是一个非常早期的实现,仍然存在一些问题。

在这方面你没有什么可以做的,但是等待并报告它是一个问题(我找了一个报告的问题,但找不到任何所以我建议你这样做。)

答案 1 :(得分:2)

我最近遇到了同样的问题,并通过将视频绘制到&#34;虚拟&#34;来解决这个问题。做之前的画布&#34;真实&#34;与它合作。这很有效,因为我的代码中尝试解析视频的所有方法都等到“#can; canplaythrough&#34;视频已触发事件。我包装了&#34; canplaythrough&#34; Promise中的事件处理程序,只有在&#34; canplaythrough&#34;已收到事件并已尝试将视频绘制到虚拟画布上。 Safari错误This appears to be an effective workaround

例如:

var readyPromise = new Promise(function(resolve) {
    video.addEventListener("canplaythrough", function() {
        var canvas = document.createElement("canvas"),
            context = canvas.getContext("2d");

        context.drawImage(video, 0, 0);

        resolve(video);
    });
});

readyPromise.then(function() {
    // NOW manipulate the video, draw it onto a canvas, etc
});

答案 2 :(得分:1)

我遇到了同样的问题,并在上​​一条评论中尝试了解决方案。 它还没有为我工作。

我后来想到并找到了解决方法:

在我的代码中我有一些其他绘图以及来自视频的drawImage,如

context.rect(0, 0, 50, 50);
context.fillStyle = 'black';
context.fill();

并且凭借这些,第二次抽奖仍然无法工作,即使在“可以播放”之后重新绘制它们也是如此。事件

所以我删除了上面的三行,并且在事件发生之后做了第二次抽奖&#39; canplaythrough&#39;。然后它奏效了。

简单地说,对我有用的代码是这样的:

context.drawImage(video, 0, 0);
video.addEventListener('canplaythrough', function () {
    context.drawImage(video, 0, 0);
});