Copyright © 2024 World Wide Web Consortium. W3C® liability, trademark and permissive document license rules apply.
本文档定义了一组以 WebIDL 编写的 ECMAScript API,用于扩展 WebRTC 规范,以支持可伸缩视频编码(SVC)编码参数的配置。SVC 编码器和解码器能力的发现 由 Media Capabilities 规范处理。
本节描述的是本文档 在其发布时的状态。当前 W3C 出版物列表以及本技术报告的最新修订版,可在 https://www.w3.org/TR/ 的 W3C 技术 报告索引中找到。
此 API 基于 W3C ORTC 社区组中完成的初步工作。
本文档由 Web 实时 通信工作组作为 工作草案发布,使用 推荐标准轨道。
作为工作草案发布并不 表示 W3C 及其成员认可。
这是一份草案文档,可能随时被其他 文档更新、替换或废弃。除非作为正在进行的工作, 否则不宜引用本文档。
本文档由一个依据 W3C 专利 政策运作的工作组制作。 W3C 维护了一个 与该工作组可交付成果有关的任何专利披露的公开列表; 该页面还包括 披露专利的说明。实际知晓某项专利,并且该个人认为该专利包含 必要权利要求 的个人,必须依照 W3C 专利政策第 6 节披露该信息。
本文档受 2023年11月03日 W3C 流程文档约束。
本节为非规范性内容。
本规范扩展了 WebRTC 规范 [WEBRTC],以 支持可伸缩视频编码(SVC)编码参数的配置。 SVC 编码器和解码器能力的发现由 Media Capabilities API [Media-Capabilities] 处理。
本规范不会改变 WebRTC 对象和方法的行为。
因此,与 Offer/Answer 协商和编码参数有关的限制
仍然保留,如 [WEBRTC] 第
5.2 节所述:
“setParameters()
不会导致 SDP 重新协商,并且
只能用于在 Offer/Answer 所协商的包络内,改变媒体栈正在发送或接收的内容。”
因此,本规范可以为 不在 Offer/Answer 中协商 SVC 支持的编解码器配置编码参数,例如 VP8 [RFC6386]、VP9 [VP9] 和 AV1 [AV1] 编解码器。 也可以支持 H.264 [ITU-T-REC-H.264] 和 H.265 [ITU-T-REC-H.265] 编解码器的时间可伸缩性配置。
除标记为非规范性的各节外,本规范中的所有编写指南、图表、示例和注释均为非规范性内容。除此之外,本规范中的所有内容均为规范性内容。
本文档中的关键词 MAY、MUST 和 SHOULD 应按 BCP 14 [RFC2119] [RFC8174] 中的描述来解释,但仅当它们像这里这样以全大写形式出现时才如此。
本规范定义的符合性准则适用于单一 产品:实现其中所含接口的用户代理。
以算法或具体步骤表述的符合性要求可以 以任何方式实现,只要最终结果等价即可。特别是, 本规范中定义的算法旨在易于遵循,并不旨在具备高性能。
使用 ECMAScript 实现本规范所定义 API 的实现 MUST 以符合 Web IDL 规范 [WEBIDL] 中定义的 ECMAScript 绑定的方式实现这些 API,因为 本规范使用了该规范及其术语。
术语“simulcast envelope”定义于 [WEBRTC] 第 5.4.1 节。
本规范引用了 [WEBRTC] 中定义的对象、方法、内部槽 和字典。
对于可伸缩视频编码(SVC),术语“single-session transmission” (SST)和“multi-session transmission”(MST) 定义于 [RFC6190]。本规范仅 支持 SST,但 不支持 MST。
术语“Single Real-time Transport Protocol stream Single Transport” (SRST),定义于 [RFC7656] 第 3.7 节,指的是将所有层在单一传输内发送、 使用单个实时传输协议(RTP)流和 同步源(SSRC)的 SVC 实现。术语“Multiple RTP stream Single Transport”(MRST),也 定义于 [RFC7656] 第 3.7 节, 指的是将所有层在单一传输内发送、 使用多个 RTP 流且每层具有不同 SSRC 的实现。 本规范仅支持 SRST,不支持 MRST。支持 SRST 的 RTP 载荷规范的编解码器包括 VP8 [RFC7741]、VP9 [VP9-PAYLOAD]、AV1 [AV1-RTP-SPEC]、H.264 [RFC6184] 和 H.265 [RFC7798]。
术语“S mode”指的是一种可伸缩性模式,其中多个
编码在同一 SSRC 上发送。这包括 "S2T1"、"S2T1h"、
"S2T2"、
"S2T2h"、"S2T3"、"S2T3h"、"S3T1"、"S3T1h"、"S3T2"、"S3T2h"、
"S3T3"
和 "S3T3h" scalabilityMode 值。
术语 选择性转发中间盒 (SFM)定义于 [RFC7667] 第 3.7 节。
本规范通过扩展 RTCRtpEncodingParameters
字典,支持 SVC 编码参数的配置。
RTCRtpEncodingParameters
字典扩展WebIDLpartial dictionary RTCRtpEncodingParameters {
DOMString scalabilityMode;
};
RTCRtpEncodingParameters
成员scalabilityMode,类型为 DOMString要用于此流的可伸缩性模式的区分大小写的标识符。 可伸缩性模式定义于第 5 节。
[WEBRTC] 描述了
addTransceiver()
(第 5.1 节)和 setParameters()
(第 5.2 节)中的错误处理,
包括使用 RTCError 来指示由于
不受支持的编码参数导致的
“hardware-encoder-error”,
以及其他错误。
当向
setParameters()
或 addTransceiver()
提供无效的
scalabilityMode 值时,
实现会按规定方式使用 RTCError 和其他错误。
addTransceiver()
[WEBRTC] 第 5.1 节描述了
sendEncodings
在
addTransceiver()
中的验证。
若要验证
scalabilityMode,
请在
addTransceiver
sendEncodings validation steps 的第 3 步之后添加
以下步骤:
RTCRtpEncodingParameters.codec
值 codec 存在,并且同一编码的 scalabilityMode
值不受 codec 支持,则抛出一个 OperationError。
scalabilityMode
值不受 kind 的
已实现
发送编解码器列表中的任何编解码器支持,则抛出一个 OperationError。
RTCRtpEncodingParameters
包含多个
active
成员值为 true 的编码,并且
sendEncodings 包含任何编码,其
scalabilityMode
值表示“S mode”,且其
active
成员值为
true,则抛出一个
OperationError。
当
addTransceiver()
和
setCodecPreferences()
方法在 Offer/Answer 协商完成之前被调用时,
协商后的编解码器及其能力可能尚未知晓。在这种情况下,
在 sendEncodings
中配置的
scalabilityMode
值可能不受最终协商的编解码器支持。
但是,只有在请求的 scalabilityMode
值对任何支持的编解码器都无效,或者请求了混合联播传输时,
才会产生错误。
为确保所需的 scalabilityMode
值能够被应用,可以使用
setCodecPreferences()
来优先选择或仅包含支持所需配置的编解码器。
例如,如果希望在空间联播的同时使用时间可伸缩性,
则在调用
addTransceiver()
时,可以将
sendEncodings
配置为发送多个具有不同分辨率的
联播流,每个流都使用时间可伸缩性。如果只有 VP8、VP9 和 AV1 编解码器实现
支持时间可伸缩性,则可以使用 setCodecPreferences()
从 Offer 中移除 H.264/AVC 编解码器,从而提高
协商到支持时间可伸缩性的编解码器的机会。
当使用 sendEncodings
来请求通过
addTransceiver()
发送多个联播流时,
不能请求“S mode”。浏览器只能被配置为发送
具有多个 SSRC 和 RID 的联播编码,或者
另一种方式是,在单个 RTP 流上发送所有联播编码。
不允许同时使用这两种联播传输技术。
setParameters()
[WEBRTC] 第 5.2 节描述了
parameters
在 setParameters()
中的验证。
将以下会导致操作以
InvalidModificationError
拒绝 promise 的条件,插入到
setParameters validation
steps 的
第 4 步中:
RTCRtpEncodingParameters.codec
值 codec,且同一编码的
scalabilityMode
值不受 codec 支持。
[[SendCodecs]] 为空
且 encodings 包含任何编码,其
scalabilityMode
值不受 kind 的
已实现
发送编解码器列表中的任何编解码器支持。
[[SendCodecs]] 不为空
且 encodings 包含某个编码,其
scalabilityMode
值不受用于该编码 RTP 流的编解码器支持。
RTCRtpEncodingParameters
包含多个
active
成员值为 true 的编码,并且
encodings 包含任何编码,其
scalabilityMode
值表示“S mode”,且其
active
成员值为
true。
"L1T1" 可伸缩性模式允许使用
setParameters()
关闭 SVC 编码。
如果使用
setParameters()
设置了 "L1T1",
那么它将在对
getParameters()
的响应中返回。
getParameters()
在初始协商完成之前,
getParameters()
会返回 encodings 中每个
编码的
scalabilityMode
值,也就是最近由
addTransceiver()
或
setParameters()
设置的值。
如果没有为 encodings 中的某个编码提供
scalabilityMode
值,
或者某个值未被成功设置,那么
getParameters()
将不会为该编码返回
scalabilityMode
值。
在初始协商完成后,getParameters()
会返回 encodings 中每个在
初始协商前具有值的编码当前配置的
scalabilityMode
值。此值 MAY 与
addTransceiver()
或 setParameters()
中请求的值不同。
例如,如果协商期间选择的编解码器不包括
支持所需 scalabilityMode
值的编码器,则用户代理 MAY 选择另一个值。如果配置
不令人满意,则可以使用 setParameters()
来更改它。
如果
addTransceiver()
或 setParameters()
没有为 encodings 中的某个编码提供
scalabilityMode
值,则在初始协商
完成后,getParameters()
将不会返回
scalabilityMode
值,编码器将使用
该编码 RTP 流的编解码器默认
scalabilityMode。
每个编解码器的默认
scalabilityMode
取决于实现。默认的
scalabilityMode
SHOULD 是
时间可伸缩性模式之一(例如 "L1T1"、"L1T2"、"L1T3" 等)。
本节为非规范性内容。
SVC 最常用于视频会议,其中会议 服务器(例如 SFM) 会根据参与者的设备特性和可用带宽 选择性地转发各层。在这样的环境中, 应用将与会议服务器协商要发送和接收的编解码器。 但是,由于可伸缩性模式不会在 Offer/Answer 中协商, 应用需要通过其他方式确定浏览器和会议服务器 支持哪些可伸缩性模式。
[Media-Capabilities] API 支持发现可伸缩视频编码的
编码器和解码器支持情况。scalabilityMode
用于查询编码器是否支持某个
scalabilityMode
值,指示其是否
“supported”、“smooth” 和 “power efficient”。
[Media-Capabilities] API 还提供
空间可伸缩性模式的解码器支持信息。spatialScalability
指示解码器是否有能力支持空间预测,
这需要能够使用与当前分辨率不同的分辨率的帧
作为依赖项。如果 spatialScalability
设置为 true,则解码器可以解码编码器支持的任何
scalabilityMode
值。
如果 spatialScalability
设置为 false
或不存在,则解码器不能解码空间可伸缩性模式,但可以
解码编码器支持的所有其他
scalabilityMode
值。
一旦应用确定了可供其使用的编解码器和
scalabilityMode
值组合,它还需要确定这些组合中哪些受 SFM 支持。
处理这一点的一种方式是让 SFM 以接收器能力的形式
指示其能够转发的编解码器和可伸缩性模式组合。
在收到 SFM 的能力后,应用可以计算
浏览器的 RTCRtpSender 和
SFM 接收器所支持的编解码器和
scalabilityMode
值的交集。这
可用于确定传递给浏览器的
addTransceiver()
和 setParameters()
方法的参数。
以下是一些示例:
在某些情况下,计算浏览器和 SFM 能力的交集时
需要考虑 RTP 头扩展。如果
SFM 无法解析编解码器载荷
(要么因为它并非设计为这样做,要么因为载荷已加密),
那么可能需要协商 RTP 头扩展(例如 [AV1-RTP-SPEC] 附录 A 中定义的 AV1 Dependency
Descriptor),
以便
SFM 转发特定编解码器。
为了考虑这一点,可以将转发某个
编解码器所需的 RTP 头扩展添加到 SFM 的接收器能力中。随后,应用可以
计算浏览器的 RTCRtpSender 和
SFM 接收器所支持的编解码器、头扩展和
scalabilityMode
值的交集。
下表给出了本规范支持的
scalabilityMode 值,
以及它们关联的标识符和特性。表中给出了
scalabilityMode 值
的名称(区分大小写),以及 [AV1] 第 6.7.5 节中分配的
可伸缩性模式标识符,并链接到第 9 节中提供的依赖关系图。
虽然 [AV1] 和 VP9 [VP9] 规范支持
表中定义的所有
scalabilityMode 值,
其他编解码器规范则并非如此。例如,VP8 [RFC6386]、H.264 [RFC6184] 和
H.265 [RFC7798] 仅支持
时间可伸缩性(例如 "L1T2"、"L1T3")。
此外,VP8 [RFC6386]、H.264 [RFC6184] 和 H.265 [RFC7798] 只允许
在不同 SSRC 上传输
联播,因此不支持“S”模式(其中多个编码
在单个 RTP 流上传输)。
| 可伸缩性模式标识符 | 空间层 | 分辨率比 | 时间层 | 层间依赖 | AV1 scalability_mode_idc |
|---|---|---|---|---|---|
| "L1T1" | 1 | 1 | 不适用 | ||
| "L1T2" | 1 | 2 | SCALABILITY_L1T2 | ||
| "L1T3" | 1 | 3 | SCALABILITY_L1T3 | ||
| "L2T1" | 2 | 2:1 | 1 | 是 | SCALABILITY_L2T1 |
| "L2T2" | 2 | 2:1 | 2 | 是 | SCALABILITY_L2T2 |
| "L2T3" | 2 | 2:1 | 3 | 是 | SCALABILITY_L2T3 |
| "L3T1" | 3 | 2:1 | 1 | 是 | SCALABILITY_L3T1 |
| "L3T2" | 3 | 2:1 | 2 | 是 | SCALABILITY_L3T2 |
| "L3T3" | 3 | 2:1 | 3 | 是 | SCALABILITY_L3T3 |
| "L2T1h" | 2 | 1.5:1 | 1 | 是 | SCALABILITY_L2T1h |
| "L2T2h" | 2 | 1.5:1 | 2 | 是 | SCALABILITY_L2T2h |
| "L2T3h" | 2 | 1.5:1 | 3 | 是 | SCALABILITY_L2T3h |
| "L3T1h" | 3 | 1.5:1 | 1 | 是 | |
| "L3T2h" | 3 | 1.5:1 | 2 | 是 | |
| "L3T3h" | 3 | 1.5:1 | 3 | 是 | |
| "S2T1" | 2 | 2:1 | 1 | 否 | SCALABILITY_S2T1 |
| "S2T2" | 2 | 2:1 | 2 | 否 | SCALABILITY_S2T2 |
| "S2T3" | 2 | 2:1 | 3 | 否 | SCALABILITY_S2T3 |
| "S2T1h" | 2 | 1.5:1 | 1 | 否 | SCALABILITY_S2T1h |
| "S2T2h" | 2 | 1.5:1 | 2 | 否 | SCALABILITY_S2T2h |
| "S2T3h" | 2 | 1.5:1 | 3 | 否 | SCALABILITY_S2T3h |
| "S3T1" | 3 | 2:1 | 1 | 否 | SCALABILITY_S3T1 |
| "S3T2" | 3 | 2:1 | 2 | 否 | SCALABILITY_S3T2 |
| "S3T3" | 3 | 2:1 | 3 | 否 | SCALABILITY_S3T3 |
| "S3T1h" | 3 | 1.5:1 | 1 | 否 | SCALABILITY_S3T1h |
| "S3T2h" | 3 | 1.5:1 | 2 | 否 | SCALABILITY_S3T2h |
| "S3T3h" | 3 | 1.5:1 | 3 | 否 | SCALABILITY_S3T3h |
| "L2T2_KEY" | 2 | 2:1 | 2 | 是 | SCALABILITY_L3T2_KEY |
| "L2T2_KEY_SHIFT" | 2 | 2:1 | 2 | 是 | SCALABILITY_L3T2_KEY_SHIFT |
| "L2T3_KEY" | 2 | 2:1 | 3 | 是 | SCALABILITY_L3T3_KEY |
| "L2T3_KEY_SHIFT" | 2 | 2:1 | 3 | 是 | SCALABILITY_L3T3_KEY_SHIFT |
| "L3T1_KEY" | 3 | 2:1 | 1 | 是 | |
| "L3T2_KEY" | 3 | 2:1 | 2 | 是 | SCALABILITY_L4T5_KEY |
| "L3T2_KEY_SHIFT" | 3 | 2:1 | 2 | 是 | SCALABILITY_L4T5_KEY_SHIFT |
| "L3T3_KEY" | 3 | 2:1 | 3 | 是 | SCALABILITY_L4T7_KEY |
| "L3T3_KEY_SHIFT" | 3 | 2:1 | 3 | 是 | SCALABILITY_L4T7_KEY_SHIFT |
scalabilityMode
值的指南
在提议一个 scalabilityMode 值时,
应遵循以下原则:
scalabilityMode
MUST 在第 5 节的表中定义条目,
包括可伸缩性模式标识符、空间层和
时间层、分辨率比、层间依赖以及对应的
AV1 scalability_mode_idc 值(如果已分配)。
LxTy 表示具有 x
个空间层、使用 2:1 分辨率比并具有 y 个时间层的
scalabilityMode。
LxTyh 表示具有 x 个空间层、1.5:1 分辨率
比和
y 个时间层。SxTy 表示一个 scalabilityMode,
其中有 x 个联播编码,分辨率比为 2:1,且每个
联播编码包含 y 个时间层。SxTyh
表示
1.5:1 分辨率比。LxTy_KEY 表示一个 scalabilityMode,
其中有 x 个空间层,使用 2:1 分辨率比和 y 个时间层,
且空间层仅
在关键帧处依赖较低空间层。LxTy_KEY_SHIFT
模式表示一个
scalabilityMode,
其中有 x 个空间层,使用 2:1 分辨率比和
y 个时间层,且空间层仅在关键
帧处依赖较低空间层,并且后续
帧的时间标识符向上偏移。
本节为非规范性内容。
此示例扩展了 [WEBRTC] 第 7.1 节(示例 1), 用于演示发送三个空间 联播层,每个层具有三个时间层,并为每个联播 层使用一个 SSRC 和 RID。只有 "sendEncodings" 属性相对于原始示例发生了变化。
const signaling = new SignalingChannel(); // handles JSON.stringify/parse
const constraints = {audio: true, video: true};
const configuration = {'iceServers': [{'urls': 'stun:stun.example.org'}]};
let pc;
// call start() to initiate
async function start() {
pc = new RTCPeerConnection(configuration);
// let the "negotiationneeded" event trigger offer generation
pc.onnegotiationneeded = async () => {
try {
await pc.setLocalDescription();
// send the offer to the other peer
signaling.send({description: pc.localDescription});
} catch (err) {
console.error(err);
}
};
try {
// get a local stream, show it in a self-view and add it to be sent
const stream = await navigator.mediaDevices.getUserMedia(constraints);
selfView.srcObject = stream;
pc.addTransceiver(stream.getAudioTracks()[0], {direction: 'sendonly'});
pc.addTransceiver(stream.getVideoTracks()[0], {
direction: 'sendonly',
sendEncodings: [
{rid: 'q', scaleResolutionDownBy: 4.0, scalabilityMode: 'L1T3'},
{rid: 'h', scaleResolutionDownBy: 2.0, scalabilityMode: 'L1T3'},
{rid: 'f', scalabilityMode: 'L1T3'}
]
});
} catch (err) {
console.error(err);
}
}
signaling.onmessage = async ({data: {description, candidate}}) => {
try {
if (description) {
await pc.setRemoteDescription(description);
// if we got an offer, we need to reply with an answer
if (description.type == 'offer') {
await pc.setLocalDescription();
signaling.send({description: pc.localDescription});
}
} else if (candidate) {
await pc.addIceCandidate(candidate);
}
} catch (err) {
console.error(err);
}
};
这是一个具有两个空间层(比例为 2:1)和三个时间层的示例。
let sendEncodings = [
{scalabilityMode: 'L2T3'}
];
这是一个混合编解码器联播的示例,其中每个联播层都有 3 个时间层。
let sendEncodings = [
{rid: 'q', codec: {clockRate: 90000, mimeType: 'video/AV1'}, scaleResolutionDownBy: 4.0, scalabilityMode: 'L1T3'},
{rid: 'h', codec: {clockRate: 90000, mimeType: 'video/VP8'}, scaleResolutionDownBy: 2.0, scalabilityMode: 'L1T3'},
{rid: 'f', codec: {clockRate: 90000, mimeType: 'video/VP8'}, scalabilityMode: 'L1T3'}
];
这是一个在单个 SSRC 上具有三个空间联播层,且每个层有三个时间层的示例。
let sendEncodings = [
{scalabilityMode: 'S3T3'}
]
本节为非规范性内容。
这是由实现 [WEBRTC] 和 [Media-Capabilities] 的浏览器返回的
encodingInfo(configuration)
的一个示例。
const contentType = 'video/VP9';
const configuration = {
type: 'webrtc',
video: {
contentType,
width: 640,
height: 480,
bitrate: 10000,
framerate: 29.97,
scalabilityMode: 'L3T3_KEY'
}
};
try {
const info = await navigator.mediaCapabilities.encodingInfo(configuration);
if (!info.supported) {
console.log(`${contentType} is unsupported.`);
return;
}
console.log(`${contentType} is ${info.smooth || 'NOT '}smooth, and ` +
`${info.powerEfficient || 'NOT '}power efficient`);
} catch (err) {
console.error(err, ' caused encodingInfo to fail');
}
本节为非规范性内容。
这是由一个仅支持转发 VP8、VP9 和 AV1 时间可伸缩性模式的 SFM 返回的接收器能力示例。
"codecs": [
{
"clockRate": 90000,
"mimeType": "video/VP8",
"scalabilityModes": [
"L1T1",
"L1T2",
"L1T3"
]
},
{
"clockRate": 90000,
"mimeType": "video/VP9",
"scalabilityModes": [
"L1T1",
"L1T2",
"L1T3"
]
},
{
"clockRate": 90000,
"mimeType": "video/AV1",
"scalabilityModes": [
"L1T1",
"L1T2",
"L1T3"
]
}
]
本节为非规范性内容。
本节为非规范性内容;它没有规定新的行为,而是 概述了本规范其他部分中已经存在的信息。 WebRTC API 的隐私考量 描述于 [WEBRTC] 第 13 节。
在 WebRTC 中,可伸缩编码工具的使用不会
在对等方之间协商,因此支持的
scalabilityMode 值
以及
对空间预测的解码器支持都不会暴露在 SDP 中。
通过尝试使用
scalabilityMode 值
为
每个编解码器调用 setParameters()
API 进行设置,
应用可以通过记录哪些配置尝试成功
以及哪些失败,来确定编码器支持的值。
但是,这并不能表明某个
scalabilityMode
值是由硬件编码器还是软件编码器
支持(或二者均支持)。由于
setParameters()
不支持用于 RTCRtpReceiver,因此无法运行等价
实验来确定解码器支持情况。
由于软件编码器支持的
scalabilityMode
值通常
是硬件所支持值的超集,因此这些实验
可获得的信息与正在使用的浏览器
具有高度相关性,而该浏览器信息已经可供
网页获取。一旦媒体开始流动,就可以获得
有关性能特征的信息,或者确定
某个
scalabilityMode 值
是否可由正在使用的编解码器解码,
从而提供更多关于硬件能力的信息。
如 [Media-Capabilities] 第 3.1 节所述,Media Capabilities API “will likely provide more accurate and consistent information”,相比本 规范可获得的信息更准确且更一致。如 [Media-Capabilities] 第 3.1 节所述,“This information is expected to have a high correlation with other information already available to the web pages as a given class of device is expected to have very similar decoding/encoding capabilities.”
本节为非规范性内容。
本节为非规范性内容;它没有规定新的行为,而是 概述了本规范其他部分中已经存在的信息。 WebRTC 协议安全考量描述于 [RFC8827],而 WebRTC API 的安全和隐私考量 描述于 [WEBRTC] 第 13 节。
下方提供了本规范中定义的可伸缩性模式的依赖关系图。
编辑者感谢 Robin Raymond、Michael Horowitz、Harald Alvestrand、 Chris Cunningham、Danil Chapovalov、Florent Castelli、Erik Språng 和 Henrik Boström 对本规范作出的贡献,本规范源自 W3C ORTC CG 中开发的 ORTC API。
Referenced in:
Referenced in: