一、需求产生的背景
之前有撰文(使用JS快速获取video视频任意位置的缩略图)介绍过纯前端获取视频的截图,按照每秒获取一张的频率去获取,性能还是可以的。
但是,怪事发生了,最近几个版本的Chrome不知道改动了什么东西,使用<video>
元素获取视频缩略图的性能变得极差,注意这里的副词,是"极",区别非常明显。
这可就非常影响用户体验了。
当然,也不是没有解决方法,那就是使用mp4box.js加WebCodecs去解码,但是,这个方法门槛有点高,很多前端小伙伴是玩不转的。
所以就想着,要不缩略图就不实时获取了,直接写个Node.js服务,线下提前跑任务生成好就好了。
于是就有了这次的需求。
二、不哔哔直接上代码
如何安装 node-fluent-ffmpeg 我这里就不啰嗦了,安装失败自己想办法哈。
假设已经新建了一个名为temp的临时文件夹,用来存放缩略图。
const ffmpeg = require("fluent-ffmpeg");
// 每间隔2秒截取缩略图
const videoPath = './sources/zhangxinxu.mp4';
console.log('正在获取视频缩略图...');
const time = Date.now();
// 下面是核心执行方法
ffmpeg(videoPath)
.fps(0.5)
.size('128x?')
.save('./temp/thumb-%04d.jpg')
.on('error', (err) => {
console.log('获取视频缩略图失败', err);
})
.on('end', () => {
console.log('获取视频缩略图成功,耗时:', (Date.now() - time) / 1000 + 's');
});
各语句作用说明
- fps()方法可以改变视频的帧率,fps(0.5)表示每秒视频的帧数是0.5,也就是没2秒才有一帧视频。
- size('128x?')表示改变原始视频的尺寸,宽度为128px像素,高度按照原始视频比例自动计算。
- thumb-%04d.jpg中的%04d表示图片序列安装0000.jpg、0001.jpg这种四位补全的方式命名(保证排序)。具体多少位补零,要根据图片数量来,例如,一个10min的视频,总共600s,会产生300张缩略图,因此,图片序列的最大值也就是300。 如果你能保证你你要处理的视频时长都在10分钟以下,那么使用%03d.jpg就足够。%04d.jpg可以保证2小时的视频都不会有序列不足的问题。
如果不出意外,就可以输出如下图所示的图片序列结果。
三、如果希望对缩略图打包?
图片序列虽然是最终需要的资源,但是要是文件数量太多,传输的成本就会大大增加。
例如,Web网页前端需要使用这些缩略图的时候,总不可能一下子发出几十、上百个请求去拉取这些图片吧。
浏览器愿意干这件事,人家服务器还不愿意呢。
如果走ZIP打包,那么前端就只有一个请求,前端再使用JavaScript解压,效果也是一样的。
我是使用zip-local这个项目实现ZIP打包的,因为语法简单,而我们这里的打包操作比较简单,因此,这个项目就比较适合,Github地址:https://github.com/Mostafa-Samir/zip-local
使用示意:
const zipper = require("zip-local");
// 打包图片文件夹
const zipBuffer = zipper.sync.zip('./temp').memory();
此时,zipBuffer就是zip文件的buffer数据,我们可以用来上传到cos存储上,也可以下载到本地,代码示意:
fs.writeFileSync(`./videoThumb-by-zhangxinxu.zip`, zipBuffer);
PS: 前端解压可以使用jszip,之前有个ZIP打包合成并下载的需求,我就用过此项目。
四、就扯这么多吧
噢啦,就扯这么多吧。
日常工作的一点小小记录。
fluent-ffmpeg这个项目的使用示意文档还是比较全的,基本上常见的视频操作都有示意。
大家如果有什么不懂的,欢迎评论交流,我还是累积了不少使用经验的。
本周日似乎要补五一的假,要上班。
我的工作原则是绝对不会恋上6天半,所以,本周日会请年假,到时候,去河边吹吹风,做做简单的休闲运动------就是钓鱼啦,哈哈哈。
看看,这是昨天下午的钓货,两个鱼护,上百斤了。?
(本篇完)