前言
周末在家无事,室友在聚精会神的看综艺节目,时不时还暂停记下笔记。
我就问她在干嘛,她说接了一个活,是要统计节目中某个广告出现的次数和时间,最后汇总成一个表格。
我说这还不简单,把视频每一帧都截图下来,直接对着看就可以了呀。
所以你看,当程序员的好处就是可以随便的信口开河,坏处就是自己说的话还是要自己去圆。
虽然说话的时候我也不知道怎么做这样的事情,不过有万能的谷歌和github,相信不是什么难事。
FFmpeg
一开始搜索的关键词是“chrome 视频 截图”,想法是通过chrome插件的形式完成截图。找到了一些现成的插件,但是关于原理性的东西基本没有查到,而且flash播放器的截图也都十分麻烦,看起来不像是只用js就搞得定的事情,于是想到曲线救国,先把视频弄到本地,然后对本地的视频文件做解析。果然就找到了一个类库:FFmpeg
在维基百科和百度百科可以看到一些关于FFmpeg这个项目的介绍。这是一个非常古老的项目,几乎覆盖了视频解码所有的需求,很有意思的是,项目有一个耻辱柱(Hall Of Shame),点名批评了很多使用了改项目,但是没有遵循其开源协议的软件,很多大家耳熟能详的播放器都名列其中。
(Hall Of Shame)
FFmpeg被许多开源项目采用,比如ffmpeg2theora,VLC, MPlayer, HandBrake, Blender, Google Chrome等。还有DirectShow/VFW的ffdshow(external project)和QuickTime的Perian (external project)也采用了FFmpeg。
由于FFmpeg是在LGPL/GPL协议下发布的(如果使用了其中一些使用GPL协议发布的模块则必须使用GPL协议),任何人都可以自由使用,但必须严格遵守LGPL/GPL协议。有很多播放软件都使用了FFmpeg的代码,但它们并没有遵守LGPL/GPL协议,没有公开任何源代码。我们应该对这种侵权行为表示耻辱。
2009年加入FFmpeg的播放软件:暴风影音、QQ影音、KMP、GOM Player、PotPlayer(2010)都在其列。
2009年2月,韩国名软KMPlayer被FFmpeg开源项目发现使用了它们的代码和二进制文件,但是没有按照规定/惯例开放相应说明/源码。因此被人举报,进入了FFmpeg官网上的耻辱黑名单。
2009年5月,网友cehoyos下载了暴风影音软件,解压之后发现其安装程序内包含了大量的开源和私有解码器:avcodec,avformat,avutil,x264,xvid,bass,wmvdmod等,之后暴风影音被正式加入到FFmpeg耻辱名单。
2009年7月22日,陈俊豪(格式工厂作者)因用到了ffmpeg和RMVB的编码库,用到了FFmpeg的译码/编码算法,违反FFmpeg的LGPL协议,登上了2009年7月22日FFmpeg的“耻辱柱”上。
2009年11月,网友roo_zhou向FFmpeg举报,指出QQ影音的credit只给出了修改的FFmpeg源码下载,声称是LGPL许可证。但实际是修改过的ffdshow,采用的是GPL许可证,之后QQ影音被正式加入到FFmpeg耻辱名单之列。
Libav项目启动之后,FFmpeg官方版本也仍然在一直维护中。FFmpeg与libav属于独立的两个项目。
ffmpeg提供了控制台的版本,在官网提供下载,自然而然会想到,是不是有nodejs的版本,于是上npm搜索,找到了几个相关的类库,分别点进github主页,从中挑选了一个star数最多的项目node-fluent-ffmpeg(截止发文时,Star1543)
node-fluent-ffmpeg还是要依赖控制台版的FFmpeg。
这时在cmd中输入ffmpeg
,应该可以看到版本信息
在项目文件夹内输入npm i node-fluent-ffmpeg -save
引入类库,cd. >index.js
创建新的脚本文件,准备开工。
脚本编写
在FFmpeg的github项目页有很详细的文档,我们需要的是截屏功能,也就是screenshot,直接在页内搜索关键字,然后我们可以看到示例代码如下:
获取截屏
ffmpeg('/path/to/video.avi')
.on('filenames', function(filenames) {
console.log('Will generate ' + filenames.join(', '))
})
.on('end', function() {
console.log('Screenshots taken');
})
.screenshots({
// Will take screens at 20%, 40%, 60% and 80% of the video
count: 4,
folder: '/path/to/output'
});
ffmpeg('/path/to/video.avi')
.screenshots({
timestamps: [30.5, '50%', '01:10.123'],
filename: 'thumbnail-at-%s-seconds.png',
folder: '/path/to/output',
size: '320x240'
});
可以看到,操作是流式的,截图可以自定义时间,文件名,输出路径和尺寸。
我们的思路是,把截图功能封装成一个函数,把每一秒作为时间参数传入,同时也把格式化后的时间作为文件名进行保存。
获取视频信息
ffmpeg.ffprobe('VIDEO_NAME', function(err, metadata) {
console.log(metadata);
console.log(metadata.format.duration);
});
metadata可以拿到很多视频相关的信息,我们目前就只需要视频长度
完整代码的:传送门
完成之后大概是这个效果
每一帧都是按时间命名的,可以方便的检索到内容。如果对时间精度要求比较高,FFmpeg是支持到毫秒级的截图。
结尾
这个东西除了给室友用来看广告以外还能有什么用处呢,我大概想了几个方向。
比如可以把下载的教育视频(真的是说教育视频)截图,直接选取有PPT的几页保存下来,可以快速的得到课堂笔记。
或者做电影简介之类的文章,可以快速的找到关键剧情的截图,拼接出文章。
其他的暂时就想不到什么更有意义的事情了。
闲来无事,我把下载下来的葫芦娃跑了一下脚本。
发现真的是一部葫芦娃。