许可优化
许可优化
产品
产品
解决方案
解决方案
服务支持
服务支持
关于
关于
软件库
当前位置:服务支持 >  软件文章 >  nodejs_视频转换使用_fluent-ffmpeg模块

nodejs_视频转换使用_fluent-ffmpeg模块

阅读数 6
点赞 0
article_banner

装上fluent-ffmpeg第一件事不是写代码,是确认ffmpeg和ffprobe在系统PATH里。Windows下大概率不在,`ffmpeg -version`敲出来提示不是内部或外部命令,后面代码全报错。去官网下个static build,解压到D:\ffmpeg\,把bin目录加到系统环境变量PATH里,重启终端和编辑器。不想改PATH的话在代码里用`Ffmpeg.setFfmpegPath('D:/ffmpeg/bin/ffmpeg.exe')`和`setFfprobePath`指定,两个都要设,只设ffmpeg的话读取视频元数据那一步会失败。


npm install fluent-ffmpeg装的是纯JS封装,不包含ffmpeg二进制文件,这点跟ffmpeg-static不一样。ffmpeg-static是另一个包,装完会带一个ffmpeg可执行文件在node_modules里,配合`require('ffmpeg-static')`用。fluent-ffmpeg本身只是把ffmpeg的命令行参数用链式API拼出来,真正的转码还是子进程调ffmpeg。所以fluent-ffmpeg的版本更新不代表ffmpeg版本更新,两个独立升级。有个坑是ffmpeg 7.0之后fluent-ffmpeg的版本检测逻辑会出问题,报“不适合输出格式”或者随机emitEnd错误,退回ffmpeg 6.x就正常了,社区issue里确认是fluent-ffmpeg对ffmpeg 7的能力探测有bug。


基本的格式转换写法,`ffmpeg('input.avi').videoCodec('libx264').audioCodec('aac').format('mp4').save('output.mp4')`。`save`和`run`的区别是`save`自动处理输出格式推断,`run`不推断需要手动指定format。链式调用里`videoCodec`和`audioCodec`要跟输出格式匹配,mp4容器里塞libx264加aac是标准组合,塞libx264加libmp3lame虽然能跑但mp4对mp3的支持不完整,播放器兼容性差。换成webm的话videoCodec用libvpx-vp9,audioCodec用libopus。


压缩视频不指定码率的话ffmpeg用默认值,压出来的体积看运气。`videoBitrate(1000)`给1000kbps,`audioBitrate(128)`给128kbps,两个配合着用。CRF模式质量更稳,`outputOptions('-crf 23')`,23是默认值,18到28之间调,数字越小质量越好体积越大。加了CRF之后不要再加videoBitrate,两个同时存在的话CRF被覆盖。`size('1280x720')`缩放分辨率,原视频宽高比跟目标不一致的话画面会拉伸变形,`aspect('16:9')`配合`size('1280x?')`让高度自动算,问号位置ffmpeg自己填。


截图用`screenshots`方法,参数是filename、timemarks、folder和size。timemarks可以是秒数数组`[2, 4, 6, 8]`,也可以是百分比字符串数组`['20%', '40%', '60%']`,百分比按视频总时长算。size参数控制截图分辨率,不传的话按原视频尺寸截。`folder`是输出目录,不存在的话会报错,先用`fs.mkdirSync`建好。截图本身很快,秒级视频几百毫秒就完了。


进度回调用`.on('progress', function(progress) { console.log(progress.percent); })`,但这个percent不准,fluent-ffmpeg从ffmpeg拿到的只有已写入帧数和对应时长,总时长是猜的,用的是第一个输入文件。多输入合并的场合percent会乱跳甚至超过100。要精确进度的话用`progress.timemark`读已处理的时间,跟用ffprobe拿到的总时长做除法,比percent靠谱。`progress.frames`和`progress.currentFps`也有,做实时显示的时候用得上。

使用_fluent-ffmpeg模块

水印直接用`watermark`方法,`watermark('logo.png', { x: '10%', y: '10%' })`,左上角百分之十的位置。x和y可以用像素值或者百分比,百分比更通用,换分辨率不用改。想同时加缩放和水印的话watermark跟size链在一起,`.watermark(...).size('1280x720')`,两个filter都会生效。文字水印用`outputOptions`拼drawtext filter,`-vf "drawtext=text='watermarkText':x=W-150:y=H-th-10:fontsize=32:fontcolor=white"`,路径里有中文的话fontfile指定字体文件路径,不然中文显示成方块。


输出到Buffer而不是文件,有些场景需要把转码结果直接放内存里返回给HTTP响应。`output(fs.createWriteStream(...))`是一路,但更常见的是用`pipe`,`command.pipe(res, { end: true })`。注意流输入对某些格式不支持,ogg音频用createReadStream喂进去ffmpeg报错,文档里写了“will not work on input streams”的情况就是这一类,改成写临时文件再读。输出到Buffer的话`outputOptions('-movflags frag_keyframe+empty_moov')`让mp4支持流式输出,不加的话mp4的moov atom在文件末尾,流式播放器要下完才能播。


HLS切片输出m3u8是另一套参数,`outputOptions`里加`-hls_time 10`切片时长、`-hls_list_size 0`保留所有切片、`-hls_segment_filename segment%03d.ts`切片命名格式。输出文件后缀写.m3u8,ffmpeg自动用hls muxer。切片文件跟m3u8在同一目录下,目录要先建好。转完用VLC打开m3u8确认切片顺序对不对。


D:\video_work\下面那个convert.js里setFfmpegPath的路径写的是C盘用户目录下的临时解压路径,换机器跑不了,下次改成D:\ffmpeg\bin\ffmpeg.exe,还有那个进度回调里的percent一直显示0%是因为输入文件路径传的是流不是文件,总时长没读到,改成文件路径就正常了,那个ffprobe的路径是……


免责声明:本文系网络转载或改编,未找到原创作者,版权归原作者所有。如涉及版权,请联系删

相关文章
技术文档
QR Code
微信扫一扫,欢迎咨询~
customer

online

联系我们
武汉格发信息技术有限公司
湖北省武汉市经开区科技园西路6号103孵化器
电话:155-2731-8020 座机:027-59821821
邮件:tanzw@gofarlic.com
Copyright © 2023 Gofarsoft Co.,Ltd. 保留所有权利
遇到许可问题?该如何解决!?
评估许可证实际采购量? 
不清楚软件许可证使用数据? 
收到软件厂商律师函!?  
想要少购买点许可证,节省费用? 
收到软件厂商侵权通告!?  
有正版license,但许可证不够用,需要新购? 
联系方式 board-phone 155-2731-8020
close1
预留信息,一起解决您的问题
* 姓名:
* 手机:

* 公司名称:

姓名不为空

姓名不为空

姓名不为空
手机不正确

手机不正确

手机不正确
公司不为空

公司不为空

公司不为空