生成由文件输入在特定时间选择的视频文件的缩略图/快照
Generate a thumbnail/snapshot of a video file selected by a file input at a specific time
如何在视频中静默地抓取通过<input type="file">
在特定时间选择的视频文件的快照(即没有可见元素、闪烁、声音等)?
有四个主要步骤:
- 创建
<canvas>
和<video>
元素。 - 将
URL.createObjectURL
生成的视频文件的src
加载到<video>
元素中,并通过侦听正在触发的特定事件来等待其加载。 - 将视频的时间设置为要拍摄快照并侦听其他事件的位置。
- 使用画布抓取图像。
步骤 1 - 创建元素
这很简单:只需创建一个<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);
请注意,视频元素具有属性 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;
}
一些浏览器将它们设置为 display: none
,但其他浏览器除非在页面上呈现,否则会出现严重问题,因此我们只是将它们缩小,以便它们基本上不可见。(但是不要将它们移到视口之外,否则您可能会在页面上看到一些丑陋的滚动条。
第 2 步 - 加载视频
这就是事情开始变得棘手的地方。您需要收听事件以了解何时继续。不同的浏览器会触发不同的事件,不同的时间和不同的顺序,所以我会省去你的工作量。在视频准备就绪之前,有三个事件必须始终至少触发一次;它们是:
- 加载的元数据
- 加载的数据
- 暂停
为这些事件设置事件处理程序,并跟踪已触发的事件数。一旦所有三个都开火了,您就可以继续了。请记住,由于其中一些事件可能会触发多次,因此您只想处理触发的每种类型的第一个事件,并放弃后续触发。我使用了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 - 获取快照
这部分只是使用 <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();
画布需要匹配视频的尺寸(而不是<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);
庆祝!
你的图像在base64中!将其发送到您的服务器,将其作为<img>
元素的src
,或者其他什么。
例如,您可以将其解码为二进制并直接将其写入文件(先修剪前缀),该文件将成为JPEG图像文件。
您还可以使用它在上传视频时提供视频预览。如果要将其作为<img>
的src
,请使用完整的数据 URI(不要删除前缀)。
- 我可以设置HTML5文件上传的视频长度限制吗
- HTML5视频无法在chrome上工作,在服务器上托管后的IE,mov文件中的视频(quicktime格式)
- 通过Jquery更改html5中的视频(不同质量)文件
- 生成由文件输入在特定时间选择的视频文件的缩略图/快照
- Node.js:获取一个mp4文件的视频和音频格式信息
- 如何设置视频文件的预览,从输入类型='文件'中选择
- iPhone应用程序或移动野生动物园的动画PNG文件的替代方案,目标是模拟短视频剪辑的即时播放
- 显示不受支持的文件格式的<视频>回退消息
- 如何在 HTML 中降低视频文件的饱和度
- 使用编解码器编码的视频文件.mov:Apple ProRes (apch) 无法通过 chrome 或 IE11 中的视
- 用于多个文件的HTML视频播放器
- 如何创建视频文件的blob
- 从json文件中获取视频源和数据的视频播放器
- 如何使用youtube API获得视频文件的直接链接
- 如何将录制的视频保存到phonegap的指定文件中
- 使用Dropzone.js获取视频文件的持续时间
- Javascript或jQuery用于拍摄视频文件的第一秒快照
- 播放多个文件类型的视频循环
- 如何在chrome中播放.avi文件格式的视频
- 如何通过API更改本地文件的视频源"input type='file'“;没有Jquery或外