您好,欢迎访问这里是深圳市硕远科技有限公司!
戴尔服务器价格_IBM联想配置_浪潮代理-深圳市硕远科技有限公司
联系我们
戴尔服务器价格_IBM联想配置_浪潮代理-深圳市硕远科技有限公司
邮箱:2324898850@qq.com
电话:400-080-6079
地址:深圳市龙华区河背工业区108创业园A301
当前位置:主页 > 新闻动态 > 行业新闻 >

行业新闻

「总结」FFMPEG视音频流媒体服务器开发

发布时间:2022-04-22 02:00:02浏览次数:
流媒体服务框架设计 总结有福利

基于公司项目需求设计流媒体服务器,考虑到扩展性,分离了业务与音视频处理,便于后期音视频处理服务能做水平扩展,同时还能更替音视频处理方案。

登录服开发

基于公有协议栈,管理用户登录、缓存、出入房间动态等等、迎合docker特点、单独用户数据库缓存。

ffmpeg音视频合成服务开发

主要包括音视频相关内容的开发,也是开发投入时间最长的服务,主要经历了以下过程。

1)、最初基于ffmpeg的h264软件实现服务demo.

2)、然后尝试基于英特尔vaapi硬件加速驱动做h264硬解,对解码视频帧做软件overlay滤波进行音视频合成,再做vaapi硬编码。
优点是此流程软件实现上会更为简洁快速,也比较稳定。
但是后面发现系统会时不时crash。从系统日志上没有找到相关日志,于是进行了长期的软件模块排除法检查问题原因,做了解码、解码+滤波、滤波+编码等单元模块组挂机测试,仍然无法找到系统crash问题原因。
同时也在微软的github仓库提交了bug/issue,但是恢复较慢。

3)、起初怀疑是vaapi驱动问题,于是尝试使用英特尔qsv硬件加速驱动硬解,对解码视频帧做硬件overlay_qsv滤波进行音视频合成,再做qsv硬编码。
优点是音视频处理全交付于gpu处理,省下大片cpu时间。缺点是硬件帧上下文关系密切,做视频自动切换上,需要做更多软件处理,编码上略微复杂。
可惜系统crash问题依然存在。

4)、ffmpeg原生工具命令行测试系统crash问题,发现确实有这个问题,而且更换很多个ffmpeg版本都会出现,只是概率可能会有浮动:快的几分钟到几小时crash、慢的一星期可能不会出现,但是不改任何参数再次尝试依然可能crash.

5)、移植音视频服务从linux到windows系统下、经过长期测试windows下运行intel加速方案确实没有系统宕机问题了、同时因为登录服基于muduo库实现,移植复杂,改将登录服打包进docker容器运行。

6)、完善及优化音视频服务框架及功能。包括:添加适当rtp缓存解决公网环境udp包波动问题、添加音视频同步机制、增加相应业务功能接口。

7)、移植到微服务框架,进一步增强程序扩展性。

流媒体服务开发小结

音视频合成简要组成模块如下

rtp处理

rtp手写,未用ffmpeg的avformat库,这样我更便于管理网络处理部分


需要注意的是udp在公网上可能存在网络抖动问题,开一块rtp缓存消抖,按seq做最小堆。我直接用的golang的heap包实现。

然后将音频包和视频包按相对时间戳,做堆排序放进一块rtp缓存里(av_rtp_handler),这样是为了方便做音视频同步,记录第一个到达的rtp包时间戳、后续rtp的相对时间加上timestamp的增量换算来的时钟,然后用来标志这个包的相对时间。
例如 h264 90000的时钟 、 30的帧率 、 : 假如第一包为3000时间戳增量 那么本包相对时间假定为 3000 / 90000 = 33.33333ms, 假如下一包增量也是3000,第二包相对时间就是33.3+33.3 = 66.6ms依此类推。

rtp时间的同步 : av_rtp_handler里所有rtp包都带了我一个换算出来的相对时间戳的、 只需要将音视频的包做一次最小堆插入、每次取堆顶时间戳最小的rtp包即可、 是音频包就丢进音频解码器、视频包就丢进视频解码器。

视频的合成&音视频缓冲区

我想了很久音视频进行合成结构后发现有一个很重要的东西、那就是音视频帧的缓冲区、而且这个缓冲区真的很重要、它能做到以下效果:

1、控制帧率

2、解决多路流的音视频帧抖动问题

1、 通过一个定时器、你能很方便地控制帧率、例如隔33ms往合成器发送一组音视频帧进行合成即可。修改帧率你只需要更改定时器的种子值。

2、消抖、每路流到达的时间肯定是不稳定的、可能通道3一下子除了了5包数据、一下子来了10帧数据、而其他路还只有1到2帧或者没有、但是你要保持实时性肯定不能把所有帧全部保存下来、所以你必须控制每路的缓冲大小得把挤出来的非I帧删掉、注意是非I帧不然可能会花屏。




然后就是音视频合成、音频用amix、视频用overlay、

视频帧合成麻烦在qsv有一个硬件帧上下文、qsvframecontext 每次做屏幕的自动切换、或者屏幕位置交换、需要重新生成filter、而你就需要费工夫去更新这个qsvframecontext 极为麻烦、后面想到的方法是设计一张ffmpeg filter输入的映射

就是在不该ffmpeg滤波器描述符的情况下、而是直接交换filter的输入位置。

一个草图将就下: 相当于 就是打乱正当的输入顺序、做一张映射、这样子不用更改filter的描述符即可做滤波器的切换,要便利极多!


音频合成没什么好说的、就是每路的输出可能不能包含自己的通道声音、不然可能存在回音、可以弄个集合记录需要合成的流输入id的集合、合成的时候把自己的id去掉再合成就行了,还有不同编码合成可以做重采样来保证filter输入的一致性。

音视频编码

编码好像没什么重点东西、打包的时候打上个合适的时间戳即可。


音视频部分功能演示

因为csdn限制了gif的大小为5m,博客园好像是10m,所以用ffmpeg压缩了大小和帧率,比较模糊。

首先5个推流客户端

用了两个demo视频
使用推流工具:
https://github.com/ailumiyana/streaming
一直往创建音视频服务的音频端口和视频端口发rtp数据

5对流的登录

配置登录流的地址,流标识依次为 “ai“, "lu", "mi", "ya", “na“
同时自动合成一条流,并用ffplay播放出来。

总结;详细教程资料关注+后台私信;资料;两个字可以免费视频领取+文档+各大厂面试题 资料内容包括:C/C++,Linux,golang,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,TCP/IP,协程,DPDK,嵌入式 等。




400-080-6079