生成在特定时间由文件输入选择的video文件的缩略图/快照

如何在背景中静默地在video中的特定时间获取通过选择的video文件的快照(即没有可见元素,闪烁,声音等)?

有四个主要步骤:

  1. 创建元素。
  2. URL.createObjectURL生成的video文件的src加载到元素中,并通过侦听触发的特定事件等待加载。
  3. 将video的时间设置为您要拍摄快照的位置并侦听其他事件
  4. 使用canvas抓取图像。

第1步 – 创建元素

这很简单:只需创建一个和一个元素并将它们附加到 (或者任何地方,实际上,它并不重要):

 var canvasElem = $( '' ).appendTo(document.body)[0]; var $video = $( '' ).appendTo(document.body); 

请注意,video元素的属性已muted 。 不要放置任何其他属性,如autoplaycontrols 。 还要注意它们都有类snapshot-generator 。 这样我们就可以为它们设置样式,使它们不受影响:

 .snapshot-generator { display: block; height: 1px; left: 0; object-fit: contain; position: fixed; top: 0; width: 1px; z-index: -1; } 

有些浏览器使用它们设置为display: none ,但是除非它们在页面上呈现,否则其他浏览器会出现严重问题,所以我们只是将它们设置得很小,这样它们基本上是不可见的。 (不要将它们移到视口之外,否则你可能会在页面上看到一些丑陋的滚动条。)

第2步 – 加载video

事情开始变得棘手。 您需要收听事件以了解何时继续。 不同的浏览器会触发不同的事件,不同的时间和不同的顺序,所以我会省你省力。 在video准备好之前,有三个事件必须始终至少触发一次; 他们是:

  • 等待loadedmetadata
  • loadeddata
  • 暂停

为这些事件设置事件处理程序并跟踪已触发的事件数。 一旦三人全部解雇,你就可以继续了。 请记住,由于其中一些事件可能会多次触发,因此您只想处理触发的每种类型的第一个事件,并放弃后续触发。 我使用了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); 

源应该只是通过URL.createObjectURL(file)创建的对象URL,其中file是文件对象。

第3步 – 设置时间

此阶段与上一阶段类似:设置时间然后侦听事件。 在我们之前代码的if块中:

 $video.one('seeked', function() { // Ready for next step }).prop('currentTime', insert_time_here_in_seconds); 

幸运的是,这次只有一次活动,所以它非常简洁明了。 最后…

第4步 – 抓取快照

这部分只是使用元素来获取截图。 在我们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(); 

canvas需要匹配video的尺寸( 而不是 元素)以获得正确的图像。 此外,我们设置canvas的内部.height.width属性, 而不是canvas高度/宽度CSS样式值。

snapshot的值是一个数据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); 

庆祝!

你有你的图像在base64! 将其发送到您的服务器,将其作为元素的src或其他任何内容。

例如,您可以将其解码为二进制文件并直接将其写入文件(首先修剪前缀) ,这将成为JPEG图像文件。

您还可以使用此function在上传video时提供video预览。 如果您将其作为src ,请使用完整数据URI (不要删除前缀)