FFmpeg音视频倍速控制
本文除了会讲到通过命令行处理倍速,还会讲到通过FFmpeg api的方式去处理音频倍速和视频倍速,进而合并成支持倍速的音视频发布成rtmp或者存成flv文件。
介绍FFmpeg的filter工具
音视频的倍速处理少不了filter这个工具,filter可以翻译成过滤器和滤波器。
按照处理数据的类型还可分为音频filter、视频filter、字幕filter,FFmpeg可以通过filter将音视频实现出非常多不同的filter效果,视频可以实现缩放、合并、裁剪、旋转、水印添加、倍速等效果,音频可以实现回声、延迟、去噪、混音、音量调节、变速等效果。
我们可以通过filter不同方式的组合去定制出我们想要的音视频特效
介绍FFmpeg命令行倍速
1、视频的倍速主要是通过控制filter中的setpts来实现,setpts是视频滤波器通过改变每一个pts时间戳来实现倍速的效果,如下只要把PTS缩小一半就可以实现2倍速,相反的是PTS增加一倍就达到2倍慢放的效果。
ffmpeg -i in.mp4 -filter:v "setpts=0.5*PTS" out.mp4
ffmpeg -i in.mp4 -filter:v "setpts=2.0*PTS" out.mp4
2、音频的倍速则是通过控制filter的atempo来实现,atempo的配置区间在0.5和2.0之间,如果需要更高倍速,则需要多个atempo串一起,下面是2、4倍速的实现命令。
ffmpeg -i in.mp4 -filter:"atempo=2.0" -vn out.mp4
ffmpeg -i in.mp4 -filter:"atempo=2.0,atempo=2.0" -vn out.mp4
3、同时对音视频进行2倍速。
ffmpeg -i in.mp4 -filter_complex "[0:v]setpts=0.5*PTS[v];[0:a]atempo=2.0[a]" -map "[v]" -map "[a]" out.mp4
视频倍速
视频倍速可以通过filter的setpts来更改视频的倍速,但是filter只对未编码的原始视频数据进行倍速处理。
我这边对于视频的处理是将H264进行格式封装,如果使用filter的话,我还需要先对H264解码,再做倍速转换,再重新编码成H264,这样将会消耗相当多的资源。
我这边对视频倍速就没必要用filter进行处理。其实视频倍速只需要改变封装格式时设置的时间戳就可以,所以我这边只要改变video_tempo这个参数的值即可,1000是正常倍速、2000是2倍速,依次叠加。
if (tempo != video_tempo && (tempo >= 1000 && tempo <= 16000)) {
video_tempo = tempo;
Logger::Info("video_tempo = %d", video_tempo);
}
AVRational time_base = { 1, video_tempo};
pkt.pts = av_rescale_q((ptsInc++) * 2, time_base, ost->st->time_base);
pkt.dts = av_rescale_q_rnd(pkt.dts, ost->st->time_base, ost->st->time_base, (AVRounding)(AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX));
pkt.duration = av_rescale_q(pkt.duration, ost->st->time_base, ost->st->time_base);
音频倍速
音频倍速就需要用到filter进行处理了,我这边对音频的处理是,先解码音频,然后用filter进行倍速处理,对处理后的音频数据进行重采样再编码成AAC的音频格式。
如果只是对音频做处理,不做音视频封装,可以直接把filter处理后的数据存成PCM,即可验证音频的倍速。
初始化filter的abuffer,aformat,abuffersink滤波器,abuffer用于接收输入frame,形成待处理的数据缓存,abuffersink用于传出输出Frame,aformat过滤器约束最终的输出格式(采样率,声道数,存储位数等),而中间的其他过滤器可以串联多个filter,如volume(音量调节),atempo(变速)等。
int init_atempo_filter(AVFilterGraph pGraph, AVFilterContext src, AVFilterContext out, char value)
{
//初始化AVFilterGraph
AVFilterGraph *graph = avfilter_graph_alloc();
//获取abuffer用于接收输入端
const AVFilter *abuffer = avfilter_get_by_name("abuffer");
AVFilterContext *abuffer_ctx = avfilter_graph_alloc_filter(graph, abuffer, "src");
//设置参数,这里需要匹配原始音频采样率8000、数据格式(位数:16)、单声道
if (avfilter_init_str(abuffer_ctx, "sample_rate=8000:sample_fmt=s16:channel_layout=mono") < 0) {
Logger::Error("error init abuffer filter");
return -1;
}
//初始化atempo filter
const AVFilter *atempo = avfilter_get_by_name("atempo");
AVFilterContext *atempo_ctx = avfilter_graph_alloc_filter(graph, atempo, "atempo");
//这里采用av_dict_set设置参数
AVDictionary *args = NULL;
av_dict_set(&args, "tempo", value, 0);//这里传入外部参数,可以动态修改
if (avfilter_init_dict(atempo_ctx, &args) < 0) {
Logger::Error("error init atempo filter");
return -1;
}const AVFilter *aformat = avfilter_get_by_name("aformat");
AVFilterContext *aformat_ctx = avfilter_graph_alloc_filter(graph, aformat, "aformat");
if (avfilter_init_str(aformat_ctx, "sample_rates=8000:sample_fmts=s16:channel_layouts=mono") < 0) {
Logger::Error("error init aformat filter");
return -1;
}
//初始化sink用于输出
const AVFilter *sink = avfilter_get_by_name("abuffersink");
AVFilterContext *sink_ctx = avfilter_graph_alloc_filter(graph, sink, "sink");
if (avfilter_init_str(sink_ctx, NULL) < 0) {//无需参数
Logger::Error("error init sink filter");
return -1;
}
//链接各个filter上下文
if (avfilter_link(abuffer_ctx, 0, atempo_ctx, 0) != 0) {
Logger::Error("error link to atempo filter");
return -1;
}
if (avfilter_link(atempo_ctx, 0, aformat_ctx, 0) != 0) {
Logger::Error("error link to aformat filter");
return -1;
}
if (avfilter_link(aformat_ctx, 0, sink_ctx, 0) != 0) {
Logger::Error("error link to sink filter");
return -1;
}
if (avfilter_graph_config(graph, NULL) < 0) {
Logger::Error("error config filter graph");
return -1;
}
*pGraph = graph;
*src = abuffer_ctx;
*out = sink_ctx;
Logger::Info("init filter success...");
return 0;
}
1.注册所有过滤器
avfilter_register_all();
if (init_atempo_filter(&s_graph, &in_ctx, &out_ctx, "1.0") != 0) {
Logger::Error("Codec not init audio filter");
return -1;
}
使用过滤器 将解码后的AVFrame通过av_buffersrc_add_frame(in_ctx, pFrameAudio)加入到输入过滤器上下文in_ctx中,通过av_buffersink_get_frame(out_ctx, pFrameAudio)获取处理完成的pFrameAudio。pFrameAudio就可以直接存成PCM或者再编码封装音视频格式。
//将pFrameAudio放入输入filter上下文
if (av_buffersrc_add_frame(in_ctx, pFrameAudio) < 0) {
Logger::Error("error add frame");
}
//从输出filter上下文中获取pFrameAudio
while (av_buffersink_get_frame(out_ctx, pFrameAudio) >= 0) {
break;
}
动态修改倍速说明
本文由于封装音视频倍速的时候,视频倍速处理是没有通过filter去做的,只是改变视频帧封装的时间戳达到倍速效果.如果最开始是以正常速度的倍速推流,过程中再去修改倍速参数,就会导致要写进的视频时间戳大于之前的时间戳,进而出错。
所以本文讲的ffmpeg的API控制音视频倍速是没办法通过动态调整倍速的。必须一开始就设置好倍速,后续就不能再改动。如果单独对音频进行动态修改倍速,则是没问题的。
原文链接:FFmpeg 音视频倍速控制_音视频开发进阶的博客-CSDN博客
FFmpeg音视频倍速控制相关推荐
- FFmpeg 音视频倍速控制
网上关于FFmpeg音视频倍速控制的资料不多,大部分都是讲通过FFmpeg命令去做音视频文件的倍速处理,通过FFmpeg api去 处理倍速的资料少之又少. 本文除了会讲到通过命令行处理倍速,还会讲到 ...
- 音视频倍速播放之sonic
播放器中有个重要的功能就是倍速播放,比如现在有很多在线教育,或者看电影,据说现在的年轻人几乎都是1.2,1.5倍速的播放了,我个人是1.2和1.5倍速使用较多. 比如有的课程老师的语速比较慢,就调快点 ...
- 视频倍速调整(ffmpeg)
众所周知,视频是由一组图片和一段音频组成,视频如果调整倍速,就可以通过调整图片来达到画面倍速的调整,当然,调整图片的同时也要对音频进行调整,否则画面和声音对不上,岂不是贻笑大方了. 视频倍速 两倍速 ...
- 视频倍速 - 在线调倍速的加速器APP工具
视频怎么调倍速?一刀工具箱 APP 提供一键可将手机上的视频倍速播放,可以调整视频倍速的加速器,调节视频的速度也就是调节视频的播放速度! 代码片段 buildVideo(){let that = th ...
- 百度网盘视频倍速播放
百度网盘视频倍速播放 (更新一下,插件叫"百度云盘HTML5视频倍速播放",原来那个好像没用了) 因为考研需要刷网课,但是百度云倍速放视频需要svip,30元/月还是挺贵的,于是去 ...
- 超级简单的工具——Video Speed Controller,玩转百度云,轻松解锁百度云视频倍速播放功能!
有经常使用百度云盘看视频需求的小伙伴肯定清楚百度的niao性,如果我们不是人民币玩家,咱就不配享用人家的在线视频倍速播放功能.Emm- 今天给大家分享一个十分简单的工具--Video Speed Co ...
- 视频教程-FFmpeg音视频编码实战屏幕录像机视频课程-基于QT5和FFMpegSDK-C/C++
FFmpeg音视频编码实战屏幕录像机视频课程-基于QT5和FFMpegSDK 夏曹俊:南京捷帝科技有限公司创始人,南京大学计算机硕士毕业,有15年c++跨平台项目研发的经验,领导开发过大量的c++虚拟 ...
- ffplay使用ffmpeg滤镜实现倍速播放
第一章 自定义播放器接口 第二章 倍速播放(本章) ______第一节 sonic实现倍速播放 ______第二节 soundtouch实现倍速播放 ______第三节 ffmpeg滤镜实现倍速播放( ...
- 百度网页视频倍速播放
原创 百度网盘视频网页在线播放,可以设置倍速 2018-10-11 17:47:10 Schrodingers_Shiba 阅读数 3069更多 分类专栏: 杂谈 版权声明:本文为博主原创文章,遵循 ...
最新文章
- Acid: 单网页检查页面,浏览器兼容性测试,浏览器好坏的标志
- 更改列表的默认项标记的颜色、大小等样式的解决办法
- MySQL——通过EXPLAIN分析SQL的执行计划
- CSS3 选择前几个元素 选择后几个元素等问题
- How to Plan My Life?
- 为什么Unreal 4引擎能轻易实时渲染出vray要花半天才能渲染出的场景
- One-Error多标签分类_深度学习:如何在多标签分类问题中考虑标签间的相关性?
- kitti百度网盘分享 kitti百度云盘,全套kitti分享 自动驾驶
- 四则运算 来源:一位热心的网友 http://www.tqcto.com/article/software/336297.html
- 面试时,如何向HR解释自己频繁跳槽?
- 基于Android的人事管理系统 开发与设计
- Go程序设计语言 1.1 hello,world
- DOS窗口的一些简单介绍
- java封装与调用方法_java方法和封装
- tftpd-hpa使用完全教程
- 六类网线和超六类网线的区别
- 一个简易邮件群发软件设计与实现
- 微信支付:请求参数与订单信息不一致
- R软件-ggplot2 画火山图
- Android隐藏软件盘