wil*_*lin 11 javascript jquery html5-video video-thumbnails html5-canvas
如何<input type="file">在背景中静默地获取视频中特定时间选择的视频文件的快照(即没有可见元素,闪烁,声音等)?
wil*_*lin 23
有四个主要步骤:
<canvas>和<video>元素.src生成的视频文件加载URL.createObjectURL到<video>元素中,并通过侦听触发的特定事件等待加载.这很简单:只需创建一个<canvas>和一个<video>元素并将它们附加到<body>(或者任何地方,它并不重要):
var canvasElem = $( '<canvas class="snapshot-generator"></canvas>' ).appendTo(document.body)[0];
var $video = $( '<video muted class="snapshot-generator"></video>' ).appendTo(document.body);
Run Code Online (Sandbox Code Playgroud)
请注意,视频元素具有该属性muted.不要放任何其他属性,如autoplay或controls.还要注意他们都有班级snapshot-generator.这样我们就可以为它们设置样式,使它们不受影响:
.snapshot-generator {
display: block;
height: 1px;
left: 0;
object-fit: contain;
position: fixed;
top: 0;
width: 1px;
z-index: -1;
}
Run Code Online (Sandbox Code Playgroud)
有些浏览器设置为使用它们display: none,但是除非它们在页面上呈现,否则其他浏览器会出现严重问题,所以我们只是将它们设置得很小,这样它们基本上是不可见的.(不要将它们移到视口之外,否则你可能会在页面上看到一些丑陋的滚动条.)
事情开始变得棘手.您需要收听事件以了解何时继续.不同的浏览器会触发不同的事件,不同的时间和不同的顺序,所以我会省你的努力.在视频准备好之前,有三个事件必须始终至少触发一次; 他们是:
为这些事件设置事件处理程序并跟踪已触发的事件数.一旦三人全部解雇,你就可以继续了.请记住,由于其中一些事件可能会多次触发,因此您只想处理触发的每种类型的第一个事件,并放弃后续触发.我用jQuery .one来处理这个问题.
var step_2_events_fired = 0;
$video.one('loadedmetadata loadeddata suspend', function() {
if (++step_2_events_fired == 3) {
// Ready for next step
}
}).prop('src', insert_source_here);
Run Code Online (Sandbox Code Playgroud)
来源应该仅仅是通过创建对象的网址URL.createObjectURL(file),在那里file是文件对象.
此阶段与上一阶段类似:设置时间然后侦听事件.在我们if之前的代码块中:
$video.one('seeked', function() {
// Ready for next step
}).prop('currentTime', insert_time_here_in_seconds);
Run Code Online (Sandbox Code Playgroud)
幸运的是,这次只有一次活动,所以它非常简洁明了.最后...
这部分只是使用<canvas>元素来抓取截图.我们的seeked事件处理程序:
canvas_elem.height = this.videoHeight;
canvas_elem.width = this.videoWidth;
canvas_elem.getContext('2d').drawImage(this, 0, 0);
var snapshot = canvas_elem.toDataURL();
// Remove elements as they are no longer needed
$video.remove();
$(canvas_elem).remove();
Run Code Online (Sandbox Code Playgroud)
画布需要匹配的视频(尺寸不的<video>元素),以获得正确的图像.此外,我们设置画布的内部.height和.width属性,而不是画布高度/宽度CSS样式值.
快照的值是一个数据URI,它基本上只是一个data:image/jpeg;base64以base64数据开头的字符串.
我们的最终JS代码应如下所示:
var step_2_events_fired = 0;
$video.one('loadedmetadata loadeddata suspend', function() {
if (++step_2_events_fired == 3) {
$video.one('seeked', function() {
canvas_elem.height = this.videoHeight;
canvas_elem.width = this.videoWidth;
canvas_elem.getContext('2d').drawImage(this, 0, 0);
var snapshot = canvas_elem.toDataURL();
// Delete the elements as they are no longer needed
$video.remove();
$(canvas_elem).remove();
}).prop('currentTime', insert_time_here_in_seconds);
}
}).prop('src', insert_source_here);
Run Code Online (Sandbox Code Playgroud)
你有你的图像在base64!发送到服务器,把它作为src一个的<img>元素,或什么的.
例如,您可以将其解码为二进制文件并直接将其写入文件(首先修剪前缀),这将成为JPEG图像文件.
您还可以使用此功能在上传视频时提供视频预览.如果您将其作为src一个<img>,请使用完整数据URI (不要删除前缀).