ffmpeg h265过滤b帧_#波导的效率私房# 1:祖宗降临!FFmpeg原来这么强

大家好,我是波导终结者。

之前开了一个“早下班”系列,结果我发现,我开了早下班的值无不言,以及早下班EXCEL之类的,屁股后面就跟了一堆“EXCEL早下班值无不言”,把我开心得直不起腰来,也写不动早下班系列了。借着这次达人专栏活动,我另开一个效率私房系列得了。

#波导的效率私房# 第一期:祖宗降临!FFmpeg原来这么强!

41582033034eb9d39986747b1a46abab.png

关于FFmpeg,我已经不止一次的谈过了,然而很多人对它的强大仍然一无所知。

诚然,它并不是世界上唯一的编码库,但是相对于TMPEGEnc、Adobe等项目,FFmpeg最大的优势当然就是开源免费。来自全世界的各方高手都在为这个库进行维护和更新,自然在各方面都有优势。

b172c42ff3866bc28ca900cc0394b44b.png

不管你用的是免费的转码软件,还是收费的MediaCoder,不管是直播串流软件OBS,还是各大视频下载工具分段下载完成之后合并视频所需的核心部件,甚至音频、图片等软件,很多依赖的都是FFmpeg。比如我之前推荐给大家过的免费开源动图录制、编辑软件ScreenToGif,它就可以调用FFmpeg的GIF模块,而且效果几乎是最好的。

c92e3da6f431d43dd38e659ea617c71e.png

关于FFmpeg怎么使用,也有好几种方式。做开发的朋友,会用代码的方式直接调用FFmpeg库,或者根据自己的软件结构进行重构(比如OBS)。但是一般朋友,在Windows底下还是采用直接EXE文件调用的形式。这方面网上已经有非常多的文章了,我就不重复了,老是洗别人的有意思么~无非就下载官方的安装程序,它会帮你把路径配置好,或者直接下载FFmpeg.exe,然后手动配置。再不济,跟脚本放到同一个目录下也能直接用。

废话不多说,我们直接来进入实战。

一、利用FFmpeg进行重封装

423bc9a642a4bfbe8025f55ea196ea3f.png

因为有不少相关方面的专业原创,在知乎老是能收到类似问题的推送。

关于容器和编码格式之间的具体定义和区别,这里就简单聊一下。编码格式是你视频用的什么标准压缩,mpeg4,H264,H265等等,音频同理。而容器则是,你用什么标准,把音频和视频整合成一个文件。

同样是H264视频编码,AAC音频编码的内容,它可以灌进MP4容器,AVI容器,FLV容器,MKV、TS等等等等。

理论上,只要容器兼容,音频和视频都可以无损重新封装进另一种容器内(只改后缀是不行的啦,死心吧)。不同容器有各自的特点。比如MP4兼容性好,支持多音轨,但是损坏之后修复困难,FLV则是流媒体标准,现在直播串的流都是这个格式,缺点是不支持多音轨,TS则是广播电视使用的容器,比如你们现在看的IPTV等。

像上图朋友,他做的“转换”,就是重编码,而不是重封装。如果内容或者具体参数不需要改变,重编码是很不划算的行为,不仅慢,而且画质损失也挺明显的。那么什么情况下我们需要重封装呢?仔细想想还是挺多的。一个FLV,你要拉到非线编软件里,你要不要把它变成MP4?一个MP4,你要把它用在数字电视广播上,一样要封装到TS里。

既然是我个人的私房,就不多说废话或者网上抄东西糊弄大家,直接上干货。

e059b7092fc1c52ee6e79b4863a8bb3e.png

BAT脚本文件的语法比较奇葩,你可能觉得图上就两三行,实际要调试一晚上的。

我稍微解释一下这些代码,output那几行,就是建一个output子文件夹用于存放转换后的文件,要不然堆一起就很乱。

set hz=.ts,就是设置一下后缀为TS,到时候FFmpeg会自动识别,封装成TS文件。

for那一行,读取BAT脚本文件同目录下的mp4和ts后畷,并且重封装成TS文件,放到output子文件夹下。因为是重封装,所以视频和音频都不重编码,这里-codec copy是关键,就是把音频和视频全部拷贝。

这样下来就能把mp4文件封装成ts,而反过来操作,就是把ts封装成mp4。由于不重编码,速度非常快,而且音视频质量绝对没有任何损失。

二、FFmpeg强制转码,满足奇葩要求

0a6433669b78110b9a434e24bdfeca8c.png

我曾接到过一个奇葩需求:某甲方他们的设备不行,有的型号的设备解码普通的H264会出现卡顿,硬说是我们内容问题,要求我们降低视频规格,把High 4.1降到Main 3.0。

但是,根据官方规范,1080P(1920X1080)的视频,要Level4以上的规格。大部分的转码软件会自动识别和调整,就算是Premiere和AME,分辨率和Level也有一个底限,选了Level3.0,分辨率就只能到720P,反过来1080P就会自动跳到Level4.0以上规格。

63409d9a47335bcf696cd4fdac75bac0.png

再加上他们还有很多奇葩要求,比如固定码率,而且要显示为CBR,帧数固定25等等,这时候,只能用FFmpeg上了。

核心代码是-c:v libx264 -profile:v main -level 3.0这几个参数,这个时候没有办法重封装了,只能重编码。

不过,-c:a copy至少保证了音频不编码,直接套用(a就是audio的意思)。

-vsync cfr force-cfr=1 -r 25这几个参数保证转出来的视频,帧率那里显示是固定的25,而不是可变帧率,需要的朋友可以拿去用~

三、快速批量减小视频音量

da5d9840226ac0974f9f25d1d85b7beb.png

现在有一批视频,甲方突然说,他们的系统有点问题(哦不,他们肯定是说:你们的视频有问题!),音量大了会爆音,要求我们的视频统一压到-10dB,这时候怎么办?

重新做一遍嘛,源那么大早就不在了。重新转码嘛,倒是有工具可以调整音量,但是在视频规格上又不能满足他们的各种要求(见上一条)。

有办法在视频不重编码的情况下,只把音频降低音量,并且重封装吗?当然可以。

f8148c2f6a3c82951e5c6be45da8736f.png

核心参数:-filter:a "volume=-10dB",懂点英文的应该知道啥意思了,不罗嗦拿去用。

3c3dbc312263633a49ef1222a05a3443.png

好了,今天的分享就到这里,各种需求千奇百怪,基本上不是反逻辑的,FFmpeg都能实现,真的是各种转码软件的祖宗,而且还不要钱。大家知道为什么那么多款软件各有优劣吗?因为它们的本质其实也就是封装FFmpeg的参数,而每个作者的理解和经验不同,所以软件就会各有所长。

脚本我会放到度盘里,大家如果有什么需求,点赞关注一下然后留言,这个要求不过份吧?这些东西你全网绝对找不到一个软件能完美实现,找人帮你弄几千块也搞不定的。

感谢观看,点个关注收藏再走呗,我们下期再见。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要使用FFmpeg解码B和视频抽,可以结合使用avcodec_send_packet()和avcodec_receive_frame()函数进行解码,然后使用av_write_frame()函数将解码后的写入输出文件。具体步骤如下: 1. 初始化FFmpeg ``` av_register_all(); avcodec_register_all(); ``` 2. 打开输入文件 ``` AVFormatContext *inputFormatCtx = NULL; avformat_open_input(&inputFormatCtx, inputFilePath, NULL, NULL); avformat_find_stream_info(inputFormatCtx, NULL); ``` 3. 找到视频流 ``` AVCodec *inputCodec = NULL; int videoStreamIndex = av_find_best_stream(inputFormatCtx, AVMEDIA_TYPE_VIDEO, -1, -1, &inputCodec, 0); AVCodecContext *inputCodecCtx = inputFormatCtx->streams[videoStreamIndex]->codec; ``` 4. 打开解码器 ``` avcodec_open2(inputCodecCtx, inputCodec, NULL); ``` 5. 初始化输出文件 ``` AVFormatContext *outputFormatCtx = NULL; avformat_alloc_output_context2(&outputFormatCtx, NULL, NULL, outputFilePath); avio_open(&outputFormatCtx->pb, outputFilePath, AVIO_FLAG_WRITE); ``` 6. 写入输出文件头 ``` avformat_write_header(outputFormatCtx, NULL); ``` 7. 读取数据并解码 ``` AVPacket packet; AVFrame *frame = av_frame_alloc(); while (av_read_frame(inputFormatCtx, &packet) == 0) { if (packet.stream_index == videoStreamIndex) { avcodec_send_packet(inputCodecCtx, &packet); while (avcodec_receive_frame(inputCodecCtx, frame) == 0) { // do something with the decoded frame, e.g. write to output file av_write_frame(outputFormatCtx, frame); } } av_packet_unref(&packet); } ``` 8. 写入输出文件尾 ``` av_write_trailer(outputFormatCtx); ``` 9. 释放资源 ``` avformat_close_input(&inputFormatCtx); avcodec_free_context(&inputCodecCtx); avformat_free_context(inputFormatCtx); avformat_free_context(outputFormatCtx); av_frame_free(&frame); ``` 这样,就可以使用FFmpeg解码B和视频抽了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值