WebRTC 编解码
作者:追风剑情 发布于:2024-1-29 15:31 分类:Unity3d
一个未压缩的视频数据有多大?我们举个例子计算一下。
- 分辨率为1920像素 x 1080像素的真彩色视频,每帧数据是 1920x1080x4=8294400字节。
- 如果该视频的帧率是 30Hz,则每秒产生的数据量是 8294400x30=248832000字 节,约为 249MB。
在今天的网络环境下,这么大的数据量是不可能进行实时传输的,我们需要对视频进行有效压缩,这是对视频(或音频) 进行编解码的主要目的。
WebRTC 规范对音视频编码有强制要求,对于视频,要求所有兼容 WebRTC 的浏览器必须支持 VP8 和 AVC/H.264 视频编码,当然除了这两种编码格式之外,浏览器也可以选择支持其他编码格式;对于音频,要求必须支持 Opus 和 G.711 PCM 编码格式。
当前主流浏览器对 WebRTC 编码格式的支持情况如下表所示。
WebRTC 编码格式 | |||
编码格式 | 媒体类型 | 兼容浏览器 | 说明 |
VP8 | 视频 | Chrome、Edge、Firefox、Safari(12.1+) | WebRTC 规范 |
H.264 | 视频 | Chrome(52+)、Edge、 Firefox、 Safari | WebRTC 规范 |
VP9 | 视频 | Chrome(48+)、Firefox | |
AV1 | 视频 | Chrome(70+)、Firefox(67+) | |
Opus | 音频 | Chrome、 Firefox、Safari、 Edge | WebRTC 规范 |
G.711 PCM | 音频 | Chrome、Firefox、Safari | WebRTC 规范 |
AV1专门为 Web 技术设计,拥有比 VP9 更高的压缩率,但由于 AV1 技术尚未成熟目前不具备产品化条件,我们就不做过多介绍了。
1.视频编码 VP8/VP9
VP8 (Video Processor 8)由 On2 公司开发,谷歌收购 On2 后,将 VP8 开源。从压缩率和视频质量方面看,VP8 与 H264 很相近。
VP9 (Video Processor 9)是谷歌在 VP8 的基础上研发的优化版,拥有比 VP8 更好的性能和视频质量,与 H.265 更相近。
VP8/VP9都是开源且免费的技术,没有版权相关的问题(H.265 有版权问题),可以放心使用。
通常将视频格式WebM与VP8/VP9结合使用。注意,因为目前Safari浏览器不支持VP9也不支持WebM,所以如果要使用VP9,需要考虑为 Safari提供其他编码方案。
2.视频编码 H.264
H.264是在MPEG-4技术的基础上建立起来的编码格式,又名为AVC(Advanced VideoCoding),目前被广泛应用于各种流媒体。
H.264 的使用非常灵活,通过更改配置可以胜任不同场景,如配置 Constrained BaselineProfile(CBP)使用了较低的带宽,适合用于视频会议和移动网络;Main Profile 适用于标准的视频内容;而 High Profile 则适用于高清蓝光 DVD 视频。
H.264 配置表 | |
配置 | 16进制编码值 |
Constrained Baseline Profile (CBP) | 42 |
Baseline Profile (BP) | 42 |
Main Profile (MP) | 4D |
High Profile (HiP) | 64 |
WebRTC规范要求必须支持 Constrained Baseline(CB) 配置,以便应用于低延时的视频会议场景。SDP 在参数 profile-level-id 指定 H.264 配置(profile)和级别(level),形式如下。
profile-level-id=42e01f
其中42 对应着 Constrained BaselineProfile 配置。
参数 packetization-mode 用于指明封包模式,取值说明如下。
- 取值为 0: 一个 RTP 包里只包含一个 NALU 包,不分片。
- 取值为 1: 一个 RTP 包可以包含多个 NALU 包,可分片。
- 取值为 2: 一个 RTP 包可以包含多个 NALU 包,且允许乱序,可分片。
注意,WebRTC 两端的编码格式和相应的配置参数都需要保持一致,否则建立连接过程会失败。
3.音频编码 Opus/G.711
Opus是WebRTC主要使用的音频编码格式,具备很好的灵活性和可扩展性,可用于语音、音乐播放等复杂的音频场景。
Opus支持多种压缩算法,甚至可以在同一个音频内应用多个压缩算法,编码器可灵活设置码率、带宽、算法压缩等参数。
Opus完全开源,支持码率范围为6~510kbps,支持最多255个音频通道,最大采样率 48kHz,延时范围为5~66.5ms,可用于 MP4/WebM/MPEG-TS 封装格式。
G.711 PCM 是一种实现简单,兼容性好的音频编码格式,支持码率64kbps,支持采样率 8kHz,通常用于向下兼容。
4.编码格式选择
推荐在应用中采用WebRTC规范支持的编码格式,如果采用非推荐的编码格式,需要认真考虑回退方案。
不同的编码格式在浏览器兼容性、占用带宽、能耗等方面存在明显差异,我们可以根据应用程序的特点灵活选择。
(1)音频
即使是在网络环境不好的情况下,使用Opus的窄带模式仍然可以保证较好的通话质量。如果希望应用程序能提供较好的兼容性,可以考虑使用G.711编码格式提供较好的通话质量。
(2)视频
选择视频编码通常需要考虑如下因素。
① 许可条款
VP8/VP9 是完全免费的,但是H.264可能会有潜在的专利费用,不过对于大多数Web开发者来讲,目前无须担心费用问题,H.264的专利所有人表示只会向编解码软件收费。
② 耗能
尤其是在iOS和iPadOS平台,支持硬件编码的H.264更加省电。出于兼容性考虑Safari12.1以后的版本支持 VP8,但是很遗憾,没有提供硬件编码支持。
③ 性能
从终端用户角度来看,VP8与H.264的性能差不多,可以同等应用到WebRTC应用中。
④ 使用复杂度
因为H.264涉及较多的配置和参数,所以使用复杂度较高,而VP8则相对简单很多。
5.编码能力 RTCRtpCodecCapability
WebRTC 使用 RTCRtpCodecCapability 描述当前平台支持的编码格式。RTCRtpCodecCapability 的定义如下面的代码清单所示。
//RTCRtpCodecCapabiity的定义
dictionary RTCRtpCodecCapability {
required DOMString mimeType;
required unsigned long clockRate;
unsigned short channels;
DOMString sdpFmtpLine;
};
RTCRtpCodecCapability 属性说明 | |
属性 | 说明 |
mimeType | MIME媒体类型 |
clockRate | 时钟频率 |
channels | 最大通道数 |
sdpFmtpLine | SDP与该编码格式对应的a=fmtp行信息 |
6.编码格式 RTCRtpCodecParameters
WebRTC 使用 RTCRtpCodecParameters 描述当前使用的编码格式。RTCRtpCodecParameters 的定义如下面的代码清单所示。
//RTCRtpCodecParameters的定义
dictionary RTCRtpCodecParameters {
required octet payloadType;
required DOMstring mimeType;
required unsigned long clockRate;
unsigned short channels;
DOMString sdpFmtpLine;
};
RTCRtpCodecParameters 属性说明 | |
属性 | 说明 |
payloadType | RTP载荷类型,用于标识该编码格式。我们在RTP协议相关内容里介绍过载荷类型 |
mimeType | MIME 媒体类型 |
clockRate | 时钟频率 |
channels | 最大通道数 |
sdpFmtpLine | SDP与该编码格式对应的a=fmtp行信息 |
7.编码参数 RTCRtpEncodingParameters
WebRTC 使用 RTCRtpEncodingParameters 描述编码格式使用到的编码参数。RTCRtpEncodingParameters 的定义如下面的代码清单所示。
//RTCRtpEncodingParameters的定义
dictionary RTCRtpEncodingParameters : RTCRtpCodingParameters {
boolean active = true;
unsigned long maxBitrate;
double scaleResolutionDownBy;
};
dictionary RTCRtpCodingParameters {
DOMString rid;
};
RTCRtpEncodingParameters 属性说明 | |
属性 | 说明 |
active | 编码是否处于活跃状态,true表示活跃,false表示不活跃 |
maxBitrate | 媒体流的最大码率,单位是 bps |
scaleResolutionDownBy | 指示将视频内容发送给对等端之前,如何缩减视频尺寸。比如,该值取2,则高和宽都除以2,结果只发送原尺寸的1/4;该值取1,则尺寸保持不变,默认值为1 |
rid | RTP id,rid 头扩展 |
8.获取平台支持的编码格式
由于不同平台支持的编码格式不同,所以在为WebRTC应用编码之前,要先获取当前平台支持的编码格式列表。
使用静态方法 RTCRtpSender.getCapabilities() 或者 RTCRtpReceiver.getCapabilities() 可以获得当前平台支持的编码格式列表,方法的参数是媒体类型,如下面的代码清单所示。
codecList = RCRtpSender.getCapabilities("video" ).codecs;
codecList 是一个 RTCRtpCodecCapability 对象数组,每个对象描述一个编码格式。 在Chrome83中执行上述方法,codecList的结果如下面的代码清单所示。
//RTCRtpSender.getCapabilities()输出
0:{clockRate:90000,mimeType:"video/VP8"}
1:{clockRate:90000,mimeType:"video/rtx"}
2:{clockRate:90000,mimeType:"video/VP9",sdpFmtpLine:"profile-id=0"}
3:(clockRate: 90000,mimeType:"video/vp9",sdpFmtpLine: "profile-id=2"}
4:(clockRate: 90000,mimeType:"video/H264",sdpFmtpLine: "level-asymmetry-
allowed=l;packetization-mode=l;profile-level-id=42001f"}
5:{clockRate:90000,mimeType:"video/H264",sdpFmtpLine:"level-asymmetry-
allowed=l;packetization-mode=0;profile-level-id=42001f"}
6:{clockRate:90000,mimeType:"video/H264",sdpFmtpLine:"level-asymmetry-
allowed=l;packetization-mode=l;profile-level-id=42e01f" }
7:(clockRate: 90000,mimeType:"video/H264",sdpFmtpLine:"level-asymmetry-
allowed=l;packetization-mode=0;profile-level-id=42e01f"}
8:(clockRate: 90000,mimeType:"video/H264",sdpFmtpLine:"level-asymmetry-
allowed=1;packetization-mode=l;profile-level-id=4d0032"}
9:(clockRate: 90000,mimeType:"video/H264", sdprmtprine: "level-asymmetry-
allowed=1;packetization-mode=l;profile-level-id-640032"}
10:{clockRate:90000,mimeType:"video/red"}
11:(clockRate:90000, mimerype: "video/ulpfea"}
在输出结果中,"video/rtx"是重传入口,"video/red"是冗余编码入口,"video/ulpfec"是错误重定向入口,它们都不是可用的编码格式。
9.设置编码格式
获取当前平台支持的编码格式列表后,如何指定编码格式呢?这时候只须调整一下列表顺序,把我们想要的编码格式放在最前面,然后再告诉WebRTC就可以了。
下面的代码清单针对每个媒体轨道应用编码格式mimeType,该示例展示了如何获取当前浏览器的视频编码能力,并将与mimeType匹配的编码能力优先级调整为最高(数组最前面),然后调用 setCodecPreferences 进行设置。
//指定编码格式示例
function changeVideoCodec(mimeType) {
const transceivers = pc.getTransceivers();
transceivers.forEach(transceiver => {
const kind = transceiver.sender.track.kind;
let sendCodecs = RTCRtpSender.getCapabilities(kind).codecs;
let recvCodecs = RTCRtpReceiver.getCapabilities(kind).codecs;
if (kind === "video") {
sendCodecs = preferCodec(sendCodecs,mimeType);
recvCodecs = preferCodec(recvCodecs,mimeType);
transceiver.setCodecPreferences([...sendCodecs, ...recvCodecs]);
}
});
pc.onnegotiationneeded();
}
function preferCodec(codecs, mimeType) {
let otherCodecs = [];
let sortedCodecs = [];
codecs.forEach(codec => {
if (codec.mimeType === mimeType) {
sortedCodecs.push(codec);
} else {
otherCodecs.push(codec);
}
});
return sortedCodecs.concat(otherCodecs);
}
10.查询当前使用的编码
我们给 WebRTC 提供了包含多个编码格式的数组,并按照优先级做了排序,WebRTC 从最高优先级开始,遍历这个数组,逐一尝试应用编码格式,如果不支持,则尝试下一个。
这时就产生了一个问题,WebRTC最终使用了哪个编码格式呢?要回答这个问题就要使用 getParameters() 方法进行査询,如下面的代码清单所示。
//查询当前使用的编码格式
const senders = peerConnection.getSenders();
senders.forEach((sender) => {
if(sender.track.kind === "video") {
codecList = sender.getParameters().codecs;
return;
}
});
上面的代码清单中的codecList是一个包含 RTCRtpCodecParameters 的数组,代表了当前使用的编码格式。
标签: Unity3d
日历
最新文章
随机文章
热门文章
分类
存档
- 2024年10月(2)
- 2024年9月(3)
- 2024年8月(3)
- 2024年7月(11)
- 2024年6月(3)
- 2024年5月(9)
- 2024年4月(10)
- 2024年3月(11)
- 2024年2月(24)
- 2024年1月(12)
- 2023年12月(3)
- 2023年11月(9)
- 2023年10月(7)
- 2023年9月(2)
- 2023年8月(7)
- 2023年7月(9)
- 2023年6月(6)
- 2023年5月(7)
- 2023年4月(11)
- 2023年3月(6)
- 2023年2月(11)
- 2023年1月(8)
- 2022年12月(2)
- 2022年11月(4)
- 2022年10月(10)
- 2022年9月(2)
- 2022年8月(13)
- 2022年7月(7)
- 2022年6月(11)
- 2022年5月(18)
- 2022年4月(29)
- 2022年3月(5)
- 2022年2月(6)
- 2022年1月(8)
- 2021年12月(5)
- 2021年11月(3)
- 2021年10月(4)
- 2021年9月(9)
- 2021年8月(14)
- 2021年7月(8)
- 2021年6月(5)
- 2021年5月(2)
- 2021年4月(3)
- 2021年3月(7)
- 2021年2月(2)
- 2021年1月(8)
- 2020年12月(7)
- 2020年11月(2)
- 2020年10月(6)
- 2020年9月(9)
- 2020年8月(10)
- 2020年7月(9)
- 2020年6月(18)
- 2020年5月(4)
- 2020年4月(25)
- 2020年3月(38)
- 2020年1月(21)
- 2019年12月(13)
- 2019年11月(29)
- 2019年10月(44)
- 2019年9月(17)
- 2019年8月(18)
- 2019年7月(25)
- 2019年6月(25)
- 2019年5月(17)
- 2019年4月(10)
- 2019年3月(36)
- 2019年2月(35)
- 2019年1月(28)
- 2018年12月(30)
- 2018年11月(22)
- 2018年10月(4)
- 2018年9月(7)
- 2018年8月(13)
- 2018年7月(13)
- 2018年6月(6)
- 2018年5月(5)
- 2018年4月(13)
- 2018年3月(5)
- 2018年2月(3)
- 2018年1月(8)
- 2017年12月(35)
- 2017年11月(17)
- 2017年10月(16)
- 2017年9月(17)
- 2017年8月(20)
- 2017年7月(34)
- 2017年6月(17)
- 2017年5月(15)
- 2017年4月(32)
- 2017年3月(8)
- 2017年2月(2)
- 2017年1月(5)
- 2016年12月(14)
- 2016年11月(26)
- 2016年10月(12)
- 2016年9月(25)
- 2016年8月(32)
- 2016年7月(14)
- 2016年6月(21)
- 2016年5月(17)
- 2016年4月(13)
- 2016年3月(8)
- 2016年2月(8)
- 2016年1月(18)
- 2015年12月(13)
- 2015年11月(15)
- 2015年10月(12)
- 2015年9月(18)
- 2015年8月(21)
- 2015年7月(35)
- 2015年6月(13)
- 2015年5月(9)
- 2015年4月(4)
- 2015年3月(5)
- 2015年2月(4)
- 2015年1月(13)
- 2014年12月(7)
- 2014年11月(5)
- 2014年10月(4)
- 2014年9月(8)
- 2014年8月(16)
- 2014年7月(26)
- 2014年6月(22)
- 2014年5月(28)
- 2014年4月(15)
友情链接
- Unity官网
- Unity圣典
- Unity在线手册
- Unity中文手册(圣典)
- Unity官方中文论坛
- Unity游戏蛮牛用户文档
- Unity下载存档
- Unity引擎源码下载
- Unity服务
- Unity Ads
- wiki.unity3d
- Visual Studio Code官网
- SenseAR开发文档
- MSDN
- C# 参考
- C# 编程指南
- .NET Framework类库
- .NET 文档
- .NET 开发
- WPF官方文档
- uLua
- xLua
- SharpZipLib
- Protobuf-net
- Protobuf.js
- OpenSSL
- OPEN CASCADE
- JSON
- MessagePack
- C在线工具
- 游戏蛮牛
- GreenVPN
- 聚合数据
- 热云
- 融云
- 腾讯云
- 腾讯开放平台
- 腾讯游戏服务
- 腾讯游戏开发者平台
- 腾讯课堂
- 微信开放平台
- 腾讯实时音视频
- 腾讯即时通信IM
- 微信公众平台技术文档
- 白鹭引擎官网
- 白鹭引擎开放平台
- 白鹭引擎开发文档
- FairyGUI编辑器
- PureMVC-TypeScript
- 讯飞开放平台
- 亲加通讯云
- Cygwin
- Mono开发者联盟
- Scut游戏服务器引擎
- KBEngine游戏服务器引擎
- Photon游戏服务器引擎
- 码云
- SharpSvn
- 腾讯bugly
- 4399原创平台
- 开源中国
- Firebase
- Firebase-Admob-Unity
- google-services-unity
- Firebase SDK for Unity
- Google-Firebase-SDK
- AppsFlyer SDK
- android-repository
- CQASO
- Facebook开发者平台
- gradle下载
- GradleBuildTool下载
- Android Developers
- Google中国开发者
- AndroidDevTools
- Android社区
- Android开发工具
- Google Play Games Services
- Google商店
- Google APIs for Android
- 金钱豹VPN
- TouchSense SDK
- MakeHuman
- Online RSA Key Converter
- Windows UWP应用
- Visual Studio For Unity
- Open CASCADE Technology
- 慕课网
- 阿里云服务器ECS
- 在线免费文字转语音系统
- AI Studio
- 网云穿
- 百度网盘开放平台
- 迅捷画图
- 菜鸟工具
- [CSDN] 程序员研修院
- 华为人脸识别
- 百度AR导航导览SDK
- 海康威视官网
- 海康开放平台
- 海康SDK下载
交流QQ群
-
Flash游戏设计: 86184192
Unity游戏设计: 171855449
游戏设计订阅号