本文除了会讲到通过命令行处理倍速,还会讲到通过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音视频倍速控制相关推荐

  1. FFmpeg 音视频倍速控制

    网上关于FFmpeg音视频倍速控制的资料不多,大部分都是讲通过FFmpeg命令去做音视频文件的倍速处理,通过FFmpeg api去 处理倍速的资料少之又少. 本文除了会讲到通过命令行处理倍速,还会讲到 ...

  2. 音视频倍速播放之sonic

    播放器中有个重要的功能就是倍速播放,比如现在有很多在线教育,或者看电影,据说现在的年轻人几乎都是1.2,1.5倍速的播放了,我个人是1.2和1.5倍速使用较多. 比如有的课程老师的语速比较慢,就调快点 ...

  3. 视频倍速调整(ffmpeg)

    众所周知,视频是由一组图片和一段音频组成,视频如果调整倍速,就可以通过调整图片来达到画面倍速的调整,当然,调整图片的同时也要对音频进行调整,否则画面和声音对不上,岂不是贻笑大方了. 视频倍速 两倍速 ...

  4. 视频倍速 - 在线调倍速的加速器APP工具

    视频怎么调倍速?一刀工具箱 APP 提供一键可将手机上的视频倍速播放,可以调整视频倍速的加速器,调节视频的速度也就是调节视频的播放速度! 代码片段 buildVideo(){let that = th ...

  5. 百度网盘视频倍速播放

    百度网盘视频倍速播放 (更新一下,插件叫"百度云盘HTML5视频倍速播放",原来那个好像没用了) 因为考研需要刷网课,但是百度云倍速放视频需要svip,30元/月还是挺贵的,于是去 ...

  6. 超级简单的工具——Video Speed Controller,玩转百度云,轻松解锁百度云视频倍速播放功能!

    有经常使用百度云盘看视频需求的小伙伴肯定清楚百度的niao性,如果我们不是人民币玩家,咱就不配享用人家的在线视频倍速播放功能.Emm- 今天给大家分享一个十分简单的工具--Video Speed Co ...

  7. 视频教程-FFmpeg音视频编码实战屏幕录像机视频课程-基于QT5和FFMpegSDK-C/C++

    FFmpeg音视频编码实战屏幕录像机视频课程-基于QT5和FFMpegSDK 夏曹俊:南京捷帝科技有限公司创始人,南京大学计算机硕士毕业,有15年c++跨平台项目研发的经验,领导开发过大量的c++虚拟 ...

  8. ffplay使用ffmpeg滤镜实现倍速播放

    第一章 自定义播放器接口 第二章 倍速播放(本章) ______第一节 sonic实现倍速播放 ______第二节 soundtouch实现倍速播放 ______第三节 ffmpeg滤镜实现倍速播放( ...

  9. 百度网页视频倍速播放

    原创 百度网盘视频网页在线播放,可以设置倍速 2018-10-11 17:47:10 Schrodingers_Shiba 阅读数 3069更多 分类专栏: 杂谈 版权声明:本文为博主原创文章,遵循 ...

最新文章

  1. Acid: 单网页检查页面,浏览器兼容性测试,浏览器好坏的标志
  2. 更改列表的默认项标记的颜色、大小等样式的解决办法
  3. MySQL——通过EXPLAIN分析SQL的执行计划
  4. CSS3 选择前几个元素 选择后几个元素等问题
  5. How to Plan My Life?
  6. 为什么Unreal 4引擎能轻易实时渲染出vray要花半天才能渲染出的场景
  7. One-Error多标签分类_深度学习:如何在多标签分类问题中考虑标签间的相关性?
  8. kitti百度网盘分享 kitti百度云盘,全套kitti分享 自动驾驶
  9. 四则运算 来源:一位热心的网友 http://www.tqcto.com/article/software/336297.html
  10. 面试时,如何向HR解释自己频繁跳槽?
  11. 基于Android的人事管理系统 开发与设计
  12. Go程序设计语言 1.1 hello,world
  13. DOS窗口的一些简单介绍
  14. java封装与调用方法_java方法和封装
  15. tftpd-hpa使用完全教程
  16. 六类网线和超六类网线的区别
  17. 一个简易邮件群发软件设计与实现
  18. 微信支付:请求参数与订单信息不一致
  19. R软件-ggplot2 画火山图
  20. Android隐藏软件盘

热门文章

  1. 玩游戏蓝牙耳机哪款好?适合打游戏的无线蓝牙耳机推荐
  2. 微信还能这么玩?半透明的微信背景主题用起来!
  3. 凑个热闹,分析下Padavan的代码,一
  4. 程序员为什么不单干、接私活、自己开公司
  5. 乱斗西游2辅助 强力辅助排行一览
  6. 生命苍白无力时候遇到你,即使再难也要亲手绘出五彩生活――读《平凡的世界》有感
  7. pitch yaw roll 最直观的解释
  8. raw格式(裸数据)格式文件读写
  9. 2022保研夏令营经验贴(中科大、华科、武大、国防科大、浙大软件、中科院)
  10. python requests ssl 证书问题