作者:音视频小话
原文:https://mp.weixin.qq.com/s/S9gvexb6QAmcO_UnR6otgw
webrtc的语音通话常使用opus编码,在webrtc的会议中常有语音录音的需求:
- 会议客户需要语音会议记录,方便会后进行会议记录;
- troubleshooting需要:在后台接受的语音中进行录音,方便知道当前传输语音的质量;
opus编码的录音存在一些挑战:
- 支持opus编码的录音流媒体格式较少,如传统的flv就不支持opus格式。
- 什么格式支持opus的效率比较高(报文头小且占比小,而opus负荷占比高)。
备注(普及给小白):流媒体录音(录像)格式,常指格式支持音频(视频)能长期持续写入的格式,如flv,mpegts,fmp4等。也就是文件可以动态的持续写入。
这里推荐采用ogg封装格式来进行opus编码的录音,本文介绍:
- ogg格式详解;
- ogg的mux和demux的开源:推荐一个非常独立,移植性强的C++开源;
- 扩展:webrtc的录像怎么做(支持H264/H265/Vp8/Vp9/AV1编码);
1. Ogg格式详解
1.1 Ogg的结构
Ogg常用来存储opus编码的报文(当然也可以存储其他格式,这里主要介绍opus编码)。主要结构为:
+++++++++++++++++++++++++++++++++++++++
Ogg Page1: |Ogg Header1|Opus packet1|Opus packet2|
++++++++++++++++++++++++++++++++++++++++++++++++++++
Ogg Page2: |Ogg Header2|Opus packet1|Opus packet2|..|packet 255|
++++++++++++++++++++++++++++++++++++++++++++++++++++
|.... |
++++++++++++++++++++++++++++++++++++++++++++++++++++
如上,Ogg格式是由多个不同Ogg页面组成(Page), 每个Ogg页面由Ogg Header加上多个系列的Opus编码报文组成。上面的一行是Ogg的一个页面,比如:
- Ogg Page1: [Ogg Header1: 2个Opus报文]
- Ogg Page2: [Ogg Header2: 255个Opus报文]
- ……
这样的序列是连续的,且持续的。
1.2 Ogg Header格式
Ogg Header格式如下:
+++++++++++++++++++++++++++++++++++++++++++++
| Oggs Tag('OggS') |
+++++++++++++++++++++++++++++++++++++++++++++
|ver(1byte)|headerflag| gp |
+++++++++++++++++++++++++++++++++++++++++++++
| gp |
+++++++++++++++++++++++++++++++++++++++++++++
| gp | stream_serial |
+++++++++++++++++++++++++++++++++++++++++++++
| stream_serial | page_sequence |
+++++++++++++++++++++++++++++++++++++++++++++
| page_sequence | CRC |
+++++++++++++++++++++++++++++++++++++++++++++
| CRC |size count| size0 |
+++++++++++++++++++++++++++++++++++++++++++++
| size1 | size2 | size3 | size4 |
+++++++++++++++++++++++++++++++++++++++++++++
|.......
- Ogg Tag(4bytes):必须是字符串’OggS’
- Ver(1byte): 版本号,常规为0
- headerflag(1byte): Opus Header的类型,有以下几种
#define OGG_NULL_HEADER_TYPE 0x00
#define OGG_CONTINUE_HEADER_TYPE 0x01
#define OGG_FIRST_HEADER_TYPE 0x02
#define OGG_LAST_HEADER_TYPE 0x04
- gp(8bytes): granule position,定义Opus报文之间的dts结构,在常规的webrtc中,间隔为20ms。
- stream_serial(4bytes): 流id,唯一表示存储的一份流,一般一路opus,该id唯一。
- page_sequence(4bytes): OggS的page页序号,依次递增。
- CRC(4bytes):校验和
- size count(1byte): packets size数组长度,最大为255,也就是该页的packet的个数。
- size array(1byte x size count): 一个数组,数组成员1byte,表示一个Opus报文的长度,该数组表示一组Opus报文的长度。
1.3 Opus数据包
一个Ogg Page中,有多个Opus数据包。具体有多少个由上面的size count决定,每个Opus数据包的长度由上面的size array中的对应一项决定。
2. Ogg mux/demux开源实现
在cpp_streamer的开源中,对应Ogg mux/demux的实现(主要针对Opus编码)。代码地址:
https://github.com/runner365/cpp_streamer/tree/v1.1/src/format/ogg
该开源的特点:
- 代码独立: 没有依赖其他第三方库(如ffmpeg或gstream等):
- 移植性比较强: C++11编写,无依赖库,移植方便
- 良好的使用C++例子:1) 解封装: src/tools/ogg_dump.cpp(解析ogg文件);2) 封装: src/tools/mpegts2ogg.cpp(mpegts转写ogg文件,内部音频编码是opus)
3. 扩展讨论–录像的方案
webrtc音视频流的录像需要兼容更多的音视频编码格式:
- H264
- H265
- Vp8/Vp9
- AV1
- Opus
因为支持的格式比较多,笔者推荐两种录像格式:
- fmp4: mp4支持的codec类型非常的全面,以上的webrtc编码音视频格式都支持,fmp4具有流媒体持续写入的特点(解决了普通mp4不能持续写入的问题),因此非常适合做封装容器;
- Enhance Flv: 传统的Flv仅仅支持H264, AAC等编码格式,但是近期公布的扩展Enhance Flv支持多种codec模式,其中包括Vpx, AV1, Opus。笔者在之前的博文(Enhance rtmp-flv协议开始支持多码流)中,详细描述Enhance flv格式如何支持H265, Vpx, AV1, Opus编码。
后续会分享对应fmp4和Enhance Flv的mux和demux代码,感兴趣的可以先点赞/关注,后续继续分享和讨论。
版权声明:本文内容转自互联网,本文观点仅代表作者本人。本站仅提供信息存储空间服务,所有权归原作者所有。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至1393616908@qq.com 举报,一经查实,本站将立刻删除。