另请参见 翻译。
本规范的初始作者为 Ian Hickson,Google Inc.,其版权声明如下:
© 版权 2004-2011 Apple Computer, Inc.、Mozilla Foundation 和 Opera
Software ASA。您被授予使用、复制和创建
本文档衍生作品的许可证。自2011年7月26日以来,W3C WebRTC 工作组所做的所有后续更改均根据以下
版权:
版权 © 2011-2024 万维网联盟。
W3C® 责任、商标和 许可文件许可证规则适用。
本文件定义了一组在 WebIDL 中的 ECMAScript API,以允许媒体和通用应用程序数据发送到并从另一个实现适当实时协议集的浏览器或设备接收。此规范是与 IETF RTCWEB 组开发的协议规范以及访问本地媒体设备的 API 规范一起开发的。
本节描述了此文档在发布时的状态。当前的 W3C 发布和此技术报告的最新修订版可以在 W3C 技术报告索引中找到 https://www.w3.org/TR/。
本文件 包括对当前的 W3C 推荐,日期为 2021 年 1 月 26 日的建议修正和候选修正。
其 相关测试套件 被用于构建在其作为推荐初始发布时的 实现报告。该测试套件已被更新,以整合大多数修正,并且针对这些修正的实现状态的更新实现报告已被用来选择具有双重实现的特性作为建议修正。
本文件由Web 实时通信工作组作为推荐发布,使用 推荐跟踪。它包括 建议修正,自上一个推荐以来引入了实质性变化和新特性。
W3C 建议广泛部署此规范作为 Web 的标准。
W3C 推荐是经过广泛共识建立后,由 W3C 及其成员支持的规范,并 得到工作组成员的承诺,提供免版税许可 用于实现。 对此推荐的未来更新可能会纳入 新特性。
候选补充内容在文档中标记。
候选修正内容在文档中标记。
提议的补充内容在文档中标记。
提议的修正内容在文档中标记。
W3C 会员及其他相关方被邀请 审查提议的补充内容,并在 2024 年 12 月 08 日之前发送评论。顾问委员会代表 应咨询他们的 WBS 问卷。
本文件由一个 根据W3C 专利政策运作的组生成。 W3C 保持着 任何与该组交付物相关的专利披露的公开列表; 该页面还包含 披露专利的说明。个人如果实际 知道某项专利,且认为该专利包含 基本权利要求 ,必须按照《W3C专利政策》第6节披露该信息。
本文件受 2023 年 11 月 03 日 W3C 过程文件的管理。
本节为非规范性内容。
本规范涵盖了 HTML 中点对点通信和视频会议的多个方面:
本文档定义了用于这些功能的 API。本规范与由 IETF RTCWEB 小组 开发的协议规范以及由 WebRTC 工作组开发的访问本地媒体设备的 API 规范 [GETUSERMEDIA] 一同进行开发。系统概述可以在 [RFC8825] 和 [RFC8826] 中找到。
除了标记为非规范性的部分外,本规范中的所有作者指导原则、图示、示例和注释均为非规范性。其余内容均为规范性。
本文档中的关键词 MAY、MUST、MUST NOT 和 SHOULD 应按照 BCP 14 [RFC2119] [RFC8174] 的说明进行解释,并且仅在它们以全大写字母形式出现时,如这里所示。
本规范定义了适用于单个产品的符合性标准:用户代理,它实现了本规范所包含的接口。
以算法或具体步骤措辞的符合性要求可以以任何方式实现,只要最终结果是等效的。(尤其是,本规范中定义的算法旨在易于遵循,而不一定追求高性能。)
使用 ECMAScript 实现本规范中定义的 API 的实现 MUST 以与 Web IDL 规范中定义的 ECMAScript 绑定一致的方式实现它们 [WEBIDL], 因为本规范使用了该规范和术语。
EventHandler
接口表示用于事件处理程序的回调,定义在 [HTML] 中。
术语 事件、事件处理程序 和 事件处理程序事件类型 定义在 [HTML] 中。
Performance
.timeOrigin
和 Performance
.now
()
定义在
[hr-time] 中。
术语 可序列化对象、序列化步骤 和 反序列化步骤 定义在 [HTML] 中。
术语 MediaStream
、
MediaStreamTrack
,
和
MediaStreamConstraints
定义在 [GETUSERMEDIA] 中。请注意
MediaStream
在
9.2
MediaStream
本文档中被扩展,而 MediaStreamTrack
在 9.3
MediaStreamTrack 本文档中被扩展。
术语 媒体描述 定义在 [RFC4566] 中。
术语 媒体传输 定义在 [RFC7656] 中。
术语 代 定义在 [RFC8838] 第 2 节。
术语 统计对象 和 监控对象 定义 在 [WEBRTC-STATS] 中。
在提到异常时,术语 抛出 和 创建 定义在 [WEBIDL] 中。
回调 VoidFunction
定义在
[WEBIDL] 中。
术语 "抛出" 的使用如 [INFRA] 中所述:它终止当前的处理步骤。
术语 已实现、 已拒绝、已解决 和 已结算 在 Promise 的上下文中定义在 [ECMASCRIPT-6.0] 中。
算法标识符 在 [WebCryptoAPI] 中定义。
JavaScript API 的一般原则适用,包括 运行至完成
和 [API-DESIGN-PRINCIPLES] 中定义的无数据竞争原则。也就是说,
在一个任务运行时,外部事件不会影响 JavaScript 应用程序可见的内容。例如,在执行 JavaScript 时,
数据通道上缓冲的数据量会因 "发送" 调用而增加,而发送数据包导致的减少将在任务检查点之后可见。
用户代理有责任确保呈现给应用程序的值集合是一致的——例如,getContributingSources()(它是同步的)返回所有在同一时间测量的源的值。
本节为非规范性。
一个 RTCPeerConnection
实例允许应用程序与另一个 RTCPeerConnection
实例建立点对点通信,或者与另一个实现所需协议的端点进行通信。通信通过控制消息的交换(称为信令协议)进行协调,这些消息通过信令通道传递,信令通道的提供方式未作说明,但通常通过页面中的脚本与服务器进行,例如使用
WebSocket
或 XMLHttpRequest
。
RTCConfiguration
字典
RTCConfiguration
定义了一组
参数,用于配置通过 RTCPeerConnection
建立或重新建立的点对点通信。
dictionary RTCConfiguration { sequence<RTCIceServer>iceServersiceServers = []; RTCIceTransportPolicyiceTransportPolicyiceTransportPolicy = "all"; RTCBundlePolicybundlePolicybundlePolicy = "balanced"; RTCRtcpMuxPolicyrtcpMuxPolicyrtcpMuxPolicy = "require"; sequence<RTCCertificate>certificatescertificates = []; [EnforceRange] octet iceCandidatePoolSize = 0; };
RTCConfiguration
成员
RTCConfiguration
成员
iceServers
类型为 sequence<RTCIceServer
>,默认为 []
。
描述可用于 ICE 的服务器的对象数组,例如 STUN 和 TURN 服务器。 如果 ICE 服务器的数量超过实现定义的限制,则忽略超出阈值的 ICE 服务器。此实现定义的限制 MUST 至少为 32。
iceTransportPolicy
类型为
RTCIceTransportPolicy
,默认为 "all"
。
指示 ICE Agent 被允许使用哪些候选项。
bundlePolicy
类型为 RTCBundlePolicy
,默认为 "balanced"
。
指示在收集 ICE 候选时使用哪个 媒体捆绑策略。
rtcpMuxPolicy
类型为 RTCRtcpMuxPolicy
,默认为 "require"
。
指示在收集 ICE 候选时使用哪个 rtcp-mux 策略。
certificates
类型为 sequence<RTCCertificate
>,默认为 []
。
一组 RTCPeerConnection
用于认证的证书。
此参数的有效值是通过调用 generateCertificate
()
函数创建的。
尽管每个 DTLS 连接将只使用一个证书,但此属性允许调用者提供多个支持不同算法的证书。
最终证书将在 DTLS 握手中选择,握手确定允许哪些证书。RTCPeerConnection
实现选择用于特定连接的证书;如何选择证书超出了本规范的范围。
现有实现仅使用提供的第一个证书;其他证书被忽略。
如果此值缺失,则为每个 RTCPeerConnection
实例生成一组默认证书。
此选项允许应用程序建立密钥连续性。RTCCertificate
可以在
[INDEXEDDB] 中持久化并重用。持久性
和重用还避免了密钥生成的成本。
此配置选项的值在最初选择后无法更改。
iceCandidatePoolSize
类型为
octet,默认为
0
RTCIceCredentialType
枚举
enum RTCIceCredentialType { "password" };
枚举描述 | |
---|---|
password
|
凭据是长期身份验证的用户名和密码,如 [RFC5389] 第 10.2 节中所述。 |
RTCIceServer
字典
RTCIceServer
字典用于描述
可被 ICE Agent 用于与对等体建立连接的
STUN 和 TURN 服务器。
dictionary RTCIceServer { required (DOMString or sequence<DOMString>) urls; DOMString username; DOMString credential;RTCIceCredentialType credentialType = "password";};
RTCIceServer
成员
RTCIceServer
成员
urls
类型为 (DOMString 或
sequence<DOMString>),必需
username
类型为 DOMString
如果此 RTCIceServer
对象表示
TURN 服务器,
且 则此
为
"credentialType
",
password
属性
属性 指定用于
该 TURN 服务器的 该 TURN 服务器的
用户名。
credential
类型为 DOMString
如果此 RTCIceServer
对象表示
TURN 服务器,
则此属性指定用于
该 TURN 服务器的凭据。
如果 credentialType
为
"
",
password
credential
表示长期 身份验证 身份验证
密码,如 [RFC5389]
第 10.2 节中所述。
为了支持
的额外值,
credentialType
可能会在未来演变为联合类型。
credential
credentialType
类型为
RTCIceCredentialType,
默认值为
"
password
"
如果此
对象表示 TURN 服务器,
则此属性指定如何在该 TURN 服务器请求
授权时使用 credential。
RTCIceServer
一组 RTCIceServer
对象的示例数组为:
[
{urls: 'stun:stun1.example.net'},
{urls: ['turns:turn.example.org', 'turn:turn.example.net'],
username: 'user',
credential: 'myPassword',
credentialType: 'password'},
];
如 [RFC9429] (第 4.1.1 节) 中所述,如果
iceTransportPolicy
成员在
RTCConfiguration
中指定,它定义了
ICE 候选策略 [RFC9429] (第 3.5.3 节)
浏览器用于向应用程序显示允许的候选者;仅这些候选者将用于连接性检查。
WebIDLenum RTCIceTransportPolicy
{
"relay
",
"all
"
};
枚举值 | 描述 |
---|---|
relay
|
ICE Agent 仅使用 媒体中继候选者,例如通过 TURN 服务器的候选者。 注意
这可以用于防止远程端点了解用户的 IP
地址,这在某些用例中可能是所需的。例如,在基于“通话”的应用程序中,应用程序可能希望防止未知的呼叫者在某种方式上获得被叫者的 IP
地址,直到被叫者以某种方式同意。
|
all
|
ICE Agent 可以在 指定此值时使用任何类型的候选者。
注意
实现仍然可以使用自己的候选过滤策略,以限制暴露给应用程序的 IP 地址,如
RTCIceCandidate
的描述中所述。
address 。
|
如 [RFC9429] (第 4.1.1 节) 中所述, 打包策略影响在远程端点不支持打包的情况下协商哪些媒体轨道,以及收集哪些 ICE 候选者。如果远程端点支持打包,则所有媒体轨道和数据通道都将打包到同一传输上。
WebIDLenum RTCBundlePolicy
{
"balanced
",
"max-compat
",
"max-bundle
"
};
枚举值 | 描述 |
---|---|
balanced
|
为每种使用中的媒体类型(音频、视频和数据)收集 ICE 候选者。如果远程端点不支持打包,则仅在不同的传输上协商一条音频和一条视频轨道。 |
max-compat
|
为每个轨道收集 ICE 候选者。如果远程端点不支持打包,则在不同的传输上协商所有媒体轨道。 |
max-bundle
|
仅为一条轨道收集 ICE 候选者。如果远程端点不支持打包,则仅协商一条媒体轨道。 |
如 [RFC9429] (第 4.1.1 节) 中所述,
RTCRtcpMuxPolicy
影响收集哪些 ICE 候选者
以支持非多路复用的 RTCP。本规范中定义的唯一值是 "require
"。
WebIDLenum RTCRtcpMuxPolicy
{
"require
"
};
枚举值 | 描述 |
---|---|
require
|
仅为 RTP 收集 ICE 候选者,并在 RTP 候选者上多路复用 RTCP。如果远程端点不支持 rtcp-mux,则会导致会话协商失败。 |
这些字典描述了可以用来控制提供/应答创建过程的选项。
WebIDLdictionary RTCOfferAnswerOptions
{};
WebIDLdictionary RTCOfferOptions
: RTCOfferAnswerOptions
{
boolean iceRestart
= false;
};
iceRestart
类型为 boolean,默认为
false
当该字典成员的值为
true
,或相关的 RTCPeerConnection
对象的 [[LocalIceCredentialsToReplace]]
槽不为空时,生成的描述将具有与当前凭据不同的 ICE
凭据(在 currentLocalDescription
属性的 SDP 中可见)。应用生成的描述将重新启动 ICE,
如 [RFC5245]
第 9.1.1.1 节中所述。
当该字典成员的值为
false
,并且相关的 RTCPeerConnection
对象的 [[LocalIceCredentialsToReplace]]
槽为空,并且
currentLocalDescription
属性具有有效的 ICE 凭据时,生成的描述将
具有与 currentLocalDescription
属性的当前值相同的 ICE 凭据。
当 iceConnectionState
转变为
"failed
"
时,建议执行 ICE
重启。应用程序还可以选择监听 iceConnectionState
转变为
"disconnected
"
然后使用其他信息来源(例如使用 getStats
来测量在接下来的几秒钟内发送或接收的字节数是否增加)来确定是否建议进行 ICE 重启。
RTCAnswerOptions
字典描述了特定于类型为
"answer
"
的会话描述的选项(在本版本的规范中没有)。
WebIDLdictionary RTCAnswerOptions
: RTCOfferAnswerOptions
{};
WebIDLenum RTCSignalingState
{
"stable
",
"have-local-offer
",
"have-remote-offer
",
"have-local-pranswer
",
"have-remote-pranswer
",
"closed
"
};
枚举值 | 描述 |
---|---|
stable
|
没有正在进行的offer/answer交换。这也是初始状态,此时本地和远程描述为空。 |
have-local-offer
|
已成功应用类型为 "offer " 的本地描述。
|
have-remote-offer
|
已成功应用类型为 "offer " 的远程描述。
|
have-local-pranswer
|
已成功应用类型为 "offer " 的远程描述,并已成功应用类型为
"pranswer " 的本地描述。
|
have-remote-pranswer
|
已成功应用类型为 "offer " 的本地描述,并已成功应用类型为
"pranswer " 的远程描述。
|
closed
|
RTCPeerConnection 已关闭;
它的
[[IsClosed]] 槽为
true 。
|
示例状态转换集如下:
stable
"
have-local-offer
"
have-remote-pranswer
"
stable
"
stable
"
have-remote-offer
"
have-local-pranswer
"
stable
"
WebIDLenum RTCIceGatheringState
{
"new
",
"gathering
",
"complete
"
};
枚举值 | 描述 |
---|---|
new
|
任意 RTCIceTransport
处于
"new "
状态且没有任何传输在
"gathering "
状态,或没有传输。
|
gathering
|
任意 RTCIceTransport
处于
"gathering "
状态。
|
complete
|
至少存在一个 RTCIceTransport ,且所有
RTCIceTransport
均处于
"complete "
状态。
|
被考虑的传输集是 PeerConnection 的传输集一个
当前被 PeerConnectionRTCPeerConnection
的
传输装置集以及 RTCPeerConnection
的
[[SctpTransport]]
内部槽(如果不为null
)。
WebIDLenum RTCPeerConnectionState
{
"closed
",
"failed
",
"disconnected
",
"new
",
"connecting
",
"connected
"
};
|
|
---|---|
枚举值 | 描述 |
closed
|
对象的 [[IsClosed]]
插槽为 true 。
|
closed
|
[[IceConnectionState]]
的值为 "
closed
"。
|
failed
|
先前的状态不 都在[[IceConnectionState]] 中"failed
RTCDtlsTransport 都在"failed "状态。
|
disconnected
|
之前的状态都不RTCIceTransport
处于[[IceConnectionState]]
的值为 "disconnected |
new
|
之前的状态 处于
[[IceConnectionState]]
是
"new "
状态RTCDtlsTransport 处于
"new "或
"closed "
状态,或者没有任何传输。
|
connecting
|
的状态为
"
"
状态,或任何
的状态为
"
"
状态。
|
connected
|
之前的状态都不RTCIceTransport
处于 "connected "[[IceConnectionState]]
的值为
"completed "
或者
connected "closed "
状态RTCDtlsTransport
处于 "connected "
或 "closed "
状态。
|
connecting
|
之前的状态都不适用。 |
在 "connecting
"
状态下,一个或多个
RTCIceTransport
处于 "new
"
或 "checking
"
状态,或者一个或多个
RTCDtlsTransport
处于 "new
"
或 "connecting
"
状态。
被考虑的传输集合是当前引用的传输集合
一个,由
PeerConnection的
RTCPeerConnection
的
转接器集合
以及
RTCPeerConnection
的
[[SctpTransport]]
内部槽位,如果不为
null
。
WebIDLenum RTCIceConnectionState
{
"closed
",
"failed
",
"disconnected
",
"new
",
"checking
",
"completed
",
"connected
"
};
枚举值 | 描述 |
---|---|
closed
|
RTCPeerConnection
对象的 [[IsClosed]] 槽位为
true 。
|
failed
|
前一个状态不适用,且任何
RTCIceTransport
的状态为
"failed "。
|
disconnected
|
前一个状态不适用,且任何
RTCIceTransport
的状态为
"disconnected "。
|
new
|
前一个状态不适用,且所有
RTCIceTransport
的状态为
"new " 或
"closed ",
或者没有任何传输。
|
checking
|
前一个状态不适用,且任何
RTCIceTransport
的状态为
"new " 或
"checking "。
|
completed
|
前一个状态不适用,且所有
RTCIceTransport
的状态为
"completed "
或
"closed "。
|
connected
|
前一个状态不适用,且所有
RTCIceTransport
的状态为
"connected ",
"completed ",
或
"closed "。
|
考虑的传输集合为 传输集合
当前引用的传输,由
RTCPeerConnection
的
转换器集合
和 RTCPeerConnection
的
[[SctpTransport]]
内部槽位(如果不为
null
)。
请注意,如果一个
RTCIceTransport
因信令(例如
RTCP mux 或 bundling)被丢弃,或者因信令而创建(例如添加新的
媒体描述),状态可能会直接从一个状态转移到另一个状态。
[RFC9429] 规范整体描述了
RTCPeerConnection
的工作方式。
根据需要提供了对 [RFC9429] 的特定小节的引用。
调用
new
会创建一个
RTCPeerConnection
(configuration)RTCPeerConnection
对象。
configuration.iceServers
包含用于查找和访问 ICE
使用的服务器的信息。
应用程序可以提供多种类型的服务器,任何 TURN 服务器也可以用作 STUN 服务器,以用于收集服务器反射候选项。
一个 RTCPeerConnection
对象具有
[[SignalingState]]
,以及聚合状态
[[ConnectionState]]
,
[[IceGatheringState]]
,
和
[[IceConnectionState]]
。
这些状态在对象创建时初始化。
一个 RTCPeerConnection
的 ICE 协议实现由一个
ICE 代理
[RFC5245] 表示。
某些
RTCPeerConnection
方法涉及与
ICE 代理 的交互,即
addIceCandidate
,
setConfiguration
,
setLocalDescription
,
setRemoteDescription
和
close
。
这些交互在本文档和 [RFC9429] 的相关章节中有所描述。
ICE 代理 还向用户代理提供
其内部对
RTCIceTransport
状态发生变化时的指示,
如 5.6
RTCIceTransport
接口 中所述。
本节列出的任务的任务源是 网络任务源。
SDP 协商的状态由内部变量
[[SignalingState]]
,
[[CurrentLocalDescription]]
,
[[CurrentRemoteDescription]]
,
[[PendingLocalDescription]]
和
[[PendingRemoteDescription]]
表示。
这些变量只在 setLocalDescription
和
setRemoteDescription
操作中设置,并由
addIceCandidate
操作和
表面候选项 程序修改。
在每种情况下,所有对这五个变量的修改在过程触发任何事件或调用任何回调之前完成,因此修改在一个时间点上可见。
作为 卸载文档清理步骤 之一,执行以下步骤:
令 window 为 document 的 相关全局对象。
对于每个
RTCPeerConnection
对象
connection,其 相关全局对象 是 window,
关闭连接,并使用 connection 和值
true
。
当调用 RTCPeerConnection.constructor()
时,用户代理 必须 执行以下步骤:
如果以下步骤中的任何步骤由于此处未指定的原因而失败,抛出一个
UnknownError
,并将
message
属性设置为适当的描述。
令 connection 为新创建的
RTCPeerConnection
对象。
令 connection 拥有一个 [[DocumentOrigin]] 内部槽,初始化为 相关设置对象 的 origin。
如果 configuration 中的 certificates
值不为空,为每个证书 certificate 执行以下步骤:
如果 certificate.expires
的值小于当前时间,
抛出一个
InvalidAccessError
。
如果 certificate.[[Origin]]
与
connection.[[DocumentOrigin]]
不同源,
抛出一个
InvalidAccessError
。
存储 certificate。
否则,生成一个或多个新的 RTCCertificate
实例,使用该 RTCPeerConnection
实例并存储它们。这可以异步地发生,并且在后续步骤中 certificates
的值保持
undefined
。正如 [RFC8826] 的 4.3.2.3
节中所述,WebRTC 使用自签名证书而不是公钥基础设施 (PKI) 证书,因此过期检查是为了确保密钥不会被无限期使用,并且不需要额外的证书检查。
初始化 connection 的 ICE 代理。
令 connection 拥有一个 [[Configuration]] 内部槽,初始化为 null
。
设置由 configuration 指定的配置。
令 connection 拥有一个 [[IsClosed]] 内部槽,初始化为 false
。
令 connection 拥有一个 [[NegotiationNeeded]] 内部槽,初始化为 false
。
令 connection 拥有一个 [[SctpTransport]] 内部槽,初始化为 null
。
令 connection 拥有一个 [[DataChannels]] 内部槽,初始化为一个空的 有序集合。
令 connection 拥有一个 [[Operations]] 内部槽,表示一个 操作链,初始化为一个空列表。
令 connection 拥有一个 [[UpdateNegotiationNeededFlagOnEmptyChain]] 内部槽,初始化为
false
。
令 connection 拥有一个 [[LastCreatedOffer]] 内部槽,初始化为 ""
。
令 connection 拥有一个 [[LastCreatedAnswer]] 内部槽,初始化为 ""
。
令 connection 拥有一个 [[EarlyCandidates]] 内部槽,初始化为一个空列表。
令 connection 拥有一个 [[SignalingState]] 内部槽,初始化为 "stable
"。
令 connection 拥有一个 [[IceConnectionState]] 内部槽,初始化为 "new
"。
令 connection 拥有一个 [[IceGatheringState]] 内部槽,初始化为 "new
"。
令 connection 拥有一个 [[ConnectionState]] 内部槽,初始化为 "new
"。
令 connection 拥有一个 [[PendingLocalDescription]] 内部槽,初始化为
null
。
令 connection 拥有一个 [[CurrentLocalDescription]] 内部槽,初始化为
null
。
令 connection 拥有一个 [[PendingRemoteDescription]] 内部槽,初始化为
null
。
令 connection 拥有一个 [[CurrentRemoteDescription]] 内部槽,初始化为
null
。
令 connection 拥有一个 [[LocalIceCredentialsToReplace]] 内部槽,初始化为一个空集合。
返回 connection。
RTCPeerConnection
对象具有一个 操作链,[[Operations]]
,它确保链中的异步操作只能一个接一个地执行。如果在前一个调用返回的
Promise 尚未 解决 时进行后续调用,它们会被添加到链中,等到所有前面的调用完成并它们的 Promise 已 解决 后再执行。
要将操作 链接 到 RTCPeerConnection
对象的 操作链 时,请执行以下步骤:
设 connection 为 RTCPeerConnection
对象。
如果 connection 的 [[IsClosed]]
为 true
,则返回一个
被拒绝的 Promise,携带一个新创建的 InvalidStateError
。
设 operation 为要链接的操作。
设 p 为一个新的 Promise。
将 operation 添加到 [[Operations]]
。
如果 [[Operations]]
的长度正好为 1,则执行
operation。
在 operation 返回的 Promise 完成或 被拒绝后,执行以下步骤:
如果 connection 的 [[IsClosed]]
为
true
,则中止这些步骤。
如果 connection 的 [[IsClosed]]
为
true
,则中止这些步骤。
移除 [[Operations]]
的第一个元素。
如果 [[Operations]]
非空,则执行
[[Operations]]
的第一个元素表示的操作,并中止这些步骤。
如果 connection 的 [[UpdateNegotiationNeededFlagOnEmptyChain]]
为 false
,则中止这些步骤。
将 connection 的 [[UpdateNegotiationNeededFlagOnEmptyChain]]
设置为 false
。
返回 p。
RTCPeerConnection
对象具有一个聚合的 [[ConnectionState]]
。每当 RTCDtlsTransport
的状态发生变化时,用户代理 必须 排队执行以下步骤的任务:
设 connection 为与状态发生变化的 RTCDtlsTransport
对象相关联的 RTCPeerConnection
对象。
如果 connection 的 [[IsClosed]]
为
true
,则中止这些步骤。
设 newState 为根据 RTCPeerConnectionState
枚举得出的新状态值。
如果 connection 的 [[ConnectionState]]
等于
newState,则中止这些步骤。
将 connection 的 [[ConnectionState]]
设置为
newState。
触发一个名为 connectionstatechange
的事件,目标是 connection。
要在 RTCPeerConnection
对象
connection 上 设置本地会话描述
description,需在 connection 上
设置会话描述
description,并附加值 false
。
要设置远程会话描述 description在一个RTCPeerConnection
对象connection上,设置会话描述description在connection上,附加值为true
。
要在
RTCPeerConnection
对象connection上设置
会话描述
description,给定一个
remote 布尔值,执行以下步骤:
令 p 为一个新的 promise。
如果 description.type
是 "rollback
",且
connection.[[SignalingState]]
为 "stable
","have-local-pranswer
",或
"have-remote-pranswer
",则
拒绝 p 并生成一个新的 InvalidStateError
,然后终止这些步骤。
令 jsepSetOfTransceivers 为 connection 的 转接器集合 的浅拷贝。
并行,按照 [RFC9429] (第5.5节 和 第5.6节) 中的描述,开始应用 description 的过程,具有以下额外的限制:
使用 jsepSetOfTransceivers 作为关于存在哪些“RtpTransceivers”的真实性来源,并将它们的 [[JsepMid]]
内部槽作为它们的“mid 属性”。
如果 remote 为 false
,并且这触发了 [RFC9429] (第 5.9
节) 中的 ICE 候选收集过程,则 ICE 代理 不得
收集那些会被 管理上禁止 的候选。
如果 remote 为 true
,并且这触发了 [RFC9429] (第 5.10
节) 中的 ICE 连接性检查,则 ICE 代理 不得
尝试连接那些被 管理上禁止 的候选。
如果 remote 为
true
,则验证背靠背的提议,仿佛在其间应用了答案,通过运行后续提议的检查,仿佛它处于稳定状态。
如果应用 description 导致修改了传输器 transceiver,并且 transceiver.[[Sender]].[[SendEncodings]] 非空且不等于处理 description 所得到的编码,则应用 description 的过程会失败。本规范不允许远程发起的 RID 重协商。
如果应用 description 的过程因任何原因失败,则用户代理 必须 排队执行以下步骤的任务:
如果 connection.[[IsClosed]]
为
true
,则中止这些步骤。
如果 description.type
对于当前的 connection.[[SignalingState]]
是无效的,如在
[RFC9429]
(第 5.5
节 和 第 5.6
节)
中描述的那样,则 拒绝 p,
生成一个新的 创建的 InvalidStateError
并中止这些步骤。
如果 description 的内容不是有效的 SDP 语法,则 拒绝 p,并以
RTCError
(其 errorDetail
设置为
"sdp-syntax-error
",且
sdpLineNumber
属性设置为
SDP 中检测到语法错误的行号) 并中止这些步骤。
如果 remote 为 true
,且
connection 的 RTCRtcpMuxPolicy
是
require
,且描述不使用
RTCP
mux,则 拒绝 p
并以新创建的 异常 InvalidAccessError
中止这些步骤。
如果描述试图重新协商 RID,如上述描述,则 拒绝 p,并以新创建的 异常 InvalidAccessError
中止这些步骤。
如果 description 的内容无效,则 拒绝 p 并以新创建的 异常 InvalidAccessError
中止这些步骤。
对于所有其他错误,拒绝 p
并以新创建的 异常 OperationError
。
如果 description 成功应用,用户代理 必须 排队执行以下步骤的任务:
如果 connection.[[IsClosed]]
为
true
,则中止这些步骤。
如果 remote 为 true
且 description 的类型为
"offer
",
并且在应用 description 的过程中,connection 的任何
addTrack
()
方法成功,则中止这些步骤并重新开始该过程,
将额外的传输器纳入过程。
如果 connection 关联的 RTCRtpSender
的
setParameters
方法的任何 promise 尚未
解决,
则中止这些步骤并重新开始过程。
如果 description 的类型为
"offer
",
并且 connection 的 [[SignalingState]]
为
"stable
",
则对 connection 的 传输器集合 中的每个
transceiver 运行以下步骤:
将 transceiver.[[Sender]]
.[[LastStableStateSenderTransport]]
设置为 transceiver.[[Sender]]
.[[SenderTransport]]
。
如果 transceiver.[[Sender]]
.[[SendEncodings]]
.length
为
1
,且唯一的编码不包含rid
成员,则将
transceiver.[[Sender]]
.[[LastStableRidlessSendEncodings]]
设置为 transceiver.[[Sender]]
.[[SendEncodings]]
;
否则,将 transceiver.[[Sender]]
.[[LastStableRidlessSendEncodings]]
设置为 null
。
将 transceiver.[[Receiver]]
.[[LastStableStateReceiverTransport]]
设置为 transceiver.[[Receiver]]
.[[ReceiverTransport]]
。
将 transceiver.[[Receiver]]
.[[LastStableStateAssociatedRemoteMediaStreams]]
设置为 transceiver.[[Receiver]]
.[[AssociatedRemoteMediaStreams]]
。
将 transceiver.[[Receiver]]
.[[LastStableStateReceiveCodecs]]
设置为 transceiver.[[Receiver]]
.[[ReceiveCodecs]]
。
如果 remote 是 false
,则执行以下步骤之一:
如果 description 的类型是 "offer
",则将
connection.[[PendingLocalDescription]]
设置为一个新的 RTCSessionDescription
对象,该对象是从 description 构造的,将
connection.[[SignalingState]]
设置为 "have-local-offer
",
并且 释放早期候选者。
如果 description 的类型是 "answer
",
则这完成了一个
提供者的应答协商。将
connection.[[CurrentLocalDescription]]
设置为一个新的 RTCSessionDescription
对象,该对象是从 description 构造的,并将
connection.[[CurrentRemoteDescription]]
设置为
connection.[[PendingRemoteDescription]]
。
将
connection.[[PendingRemoteDescription]]
和
connection.[[PendingLocalDescription]]
设置为 null
。将
connection.[[LastCreatedOffer]]
和
connection.[[LastCreatedAnswer]]
设置为 ""
,将
connection.[[SignalingState]]
设置为
"stable
",
并且 释放早期候选者。
最后,如果
connection.[[LocalIceCredentialsToReplace]]
中没有任何ICE凭证在 description 中,则将
connection.[[LocalIceCredentialsToReplace]]
设置为空集。
如果 description 的类型是 "pranswer
",
则将
connection.[[PendingLocalDescription]]
设置为一个新的 RTCSessionDescription
对象,该对象是从 description 构造的,将
connection.[[SignalingState]]
设置为
"have-local-pranswer
",
并且 释放早期候选者。
否则(如果 remote 为 true
),执行以下步骤之一:
如果 description 的类型是
"offer
",
将 connection.[[PendingRemoteDescription]]
属性设置为一个新的 RTCSessionDescription
对象,该对象是从 description 构造的,
并将 connection.[[SignalingState]]
设置为 "have-remote-offer
"。
如果 description 的类型是
"answer
",
则这完成了一个提案-应答的协商。将
connection.[[CurrentRemoteDescription]]
设置为一个新的 RTCSessionDescription
对象,该对象是从 description 构造的,并将
connection.[[CurrentLocalDescription]]
设置为
connection.[[PendingLocalDescription]]
。
将
connection.[[PendingRemoteDescription]]
和
connection.[[PendingLocalDescription]]
设置为 null
。将
connection.[[LastCreatedOffer]]
和
connection.[[LastCreatedAnswer]]
设置为 ""
,将
connection.[[SignalingState]]
设置为
"stable
"。
最后,如果 connection.[[LocalIceCredentialsToReplace]]
中没有任何ICE凭证在新设置的
connection.[[CurrentLocalDescription]]
中,则将
connection.[[LocalIceCredentialsToReplace]]
设置为空集。
如果 description 的类型是
"pranswer
",
则将
connection.[[PendingRemoteDescription]]
设置为一个新的 RTCSessionDescription
对象,该对象是从 description 构造的,并将
connection.[[SignalingState]]
设置为
"have-remote-pranswer
"。
如果 description 的类型是
"answer
",并且
它启动了现有 SCTP 关联的关闭,如
[RFC8841]
的第 10.3 和 10.4 节所定义,将 connection.[[SctpTransport]]
的值设为
null
。
让 trackEventInits、 muteTracks、addList、 removeList 和 errorList 成为空列表。
如果 description 的类型是
"answer
" 或 "pranswer
",
那么执行以下步骤:
如果 description 启动了新的 SCTP 关联的建立,如在 [RFC8841],
第 10.3 节和第 10.4 节中所定义,创建一个
RTCSctpTransport,
初始状态为 "connecting
"
并将结果分配给 [[SctpTransport]]
槽位。
否则,如果 SCTP 关联已经建立,但 max-message-size
SDP 属性被更新,更新
connection.[[SctpTransport]]
的数据最大消息大小。
如果 description 协商了 SCTP 传输的 DTLS 角色,那么对于每个
RTCDataChannel
,
channel,具有
null
的 id
,
执行以下步骤:
[[ReadyState]]
设置为
"closed
",
并将
channel 添加到 errorList。
如果 description 的类型不是
"rollback
",
那么执行以下步骤:
如果 remote 是 false
,那么
对 description 中的每个 媒体描述
执行以下步骤:
如果 媒体描述 尚未与
RTCRtpTransceiver
对象 关联,
那么执行以下步骤:
让 transceiver 为用于创建
媒体描述
的
RTCRtpTransceiver
。
将 transceiver.[[Mid]]
设置为
transceiver.[[JsepMid]]
。
如果
transceiver.[[Stopped]]
为 true
,则中止这些子步骤。
如果 媒体描述
被指示为使用现有的 媒体
媒体
传输 根据 [RFC8843],
让 transport 为表示该传输的 RTP/RTCP 组件的
RTCDtlsTransport
对象。
否则,让 transport 为具有新的基础
RTCIceTransport
的新创建
RTCDtlsTransport
对象。
将
transceiver.[[Sender]]
.[[SenderTransport]]
设置为 transport。
将
transceiver.[[Receiver]]
.[[ReceiverTransport]]
设置为 transport。
设 transceiver 为与
RTCRtpTransceiver
关联的
媒体描述。
如果 transceiver.[[Stopped]]
为 true
,则中止这些子步骤。
让 direction 为表示来自
媒体
媒体描述
的方向的 RTCRtpTransceiverDirection
值。
如果 direction 是
"sendrecv
"
或
"recvonly
",
则将
transceiver.[[Receptive]]
设置为 true
,否则设置为
false
。
将
transceiver.[[Receiver]]
.[[ReceiveCodecs]]
设置为 description 为接收协商的编码以及用户代理当前准备接收的编码。
如果 description 的类型是
"answer
"
或
"pranswer
",
那么执行以下步骤:
如果 transceiver.[[Sender]]
.[[SendEncodings]]
.length 大于 1
,则执行以下步骤:
如果 description 缺少
所有之前协商的
层,则从
transceiver.[[Sender]]
.[[SendEncodings]]
中移除所有字典,
除第一个外,并跳过
下一步。
如果 description 缺少
任何
之前协商的层,
则从
transceiver.[[Sender]]
.[[SendEncodings]]
中移除与
缺失层对应的字典。
将
transceiver.[[Sender]]
.[[SendCodecs]]
设置为 description
为发送协商的编码以及用户代理当前能够发送的编码,
并将
transceiver.[[Sender]]
.[[LastReturnedParameters]]
设置为 null
。
如果 direction 是
"sendonly
"
或
"inactive
",
并且
transceiver.[[FiredDirection]]
是
"sendrecv
"
或
"recvonly
",
那么执行以下步骤:
设置
关联的远程流
给定
transceiver.[[Receiver]]
,
一个空列表,另一个空列表,
以及 removeList。
处理
远程
远程
轨道的移除,对于 媒体
描述,给定
transceiver 和
muteTracks。
将
transceiver.[[CurrentDirection]]
和
transceiver.[[FiredDirection]]
设置为 direction。
否则,如果 remote 为 true
,则对
description 中的每个 媒体描述
执行以下步骤:
如果 description 的类型是
"offer
"
并且 的 媒体描述
包含接收
simulcast 的请求,使用 simulcast 属性中指定的 rid 值的顺序为每个 simulcast
层创建一个
RTCRtpEncodingParameters
字典,按照相应的 rid valuevalue
(如果存在以逗号分隔的替代项,则仅使用第一个值) 填充
rid
成员,
并让 sendEncodingsproposedSendEncodings
为 列表列表 包含创建的字典。
否则,让 sendEncodingsproposedSendEncodings
为 一个一个 空列表。
对于 proposedSendEncodings 中的每个编码
encoding,按相反顺序,
如果 encoding 的
rid
与 proposedSendEncodings 中的另一个编码匹配,则从
proposedSendEncodings 中移除
encoding。
scaleResolutionDownBy
为 2^(长度 of sendEncodingsproposedSendEncodings -
编码索引 - 1)
。
如 [RFC8829RFC9429]
(第
5.10 节。) 所描述的,
尝试找到一个现有的
RTCRtpTransceiver
对象,
transceiver,以表示 媒体描述。
如果找到合适的 transceiver(transceiver 已设置), 且
sendEncodingsproposedSendEncodings
非空,则将
transceiver.[[Sender]].[[SendEncodings]]
设置为
sendEncodings,并将
transceiver.[[Sender]].[[LastReturnedParameters]]
设置为 执行以下步骤:
null
。
如果 transceiver.[[Sender]]
.[[SendEncodings]]
的长度为 1
,并且唯一的编码中不
包含任何
rid
成员,则将
transceiver.[[Sender]]
.[[SendEncodings]]
设置为
proposedSendEncodings,并将
transceiver.[[Sender]]
.[[LastReturnedParameters]]
设置为
null
。
如果没有找到合适的转发器(transceiver 未设置),请执行以下步骤:
创建一个
RTCRtpSender,
sender,从 媒体媒体描述
使用
sendEncodingsproposedSendEncodings。
创建一个
RTCRtpReceiver,
receiver,从 媒体媒体描述。
创建一个
RTCRtpTransceiver,使用
sender、receiver 和 RTCRtpTransceiverDirection
的值为 "recvonly
",
并将 transceiver 设为结果。
将 transceiver 添加到
connection 的 转发器集合 中中。
如果 description 的类型为
"answer
"
或
"pranswer
",
并且 transceiver.[[Sender]]
.[[SendEncodings]]
.length
大于 1
,则执行以下步骤:
如果 description 表明不支持或不需要同时播送,或者
description 缺少所有先前协商的层, 则移除
transceiver.[[Sender]]
.[[SendEncodings]]
中的所有字典,除了第一个,并中止这些子步骤。
如果 description 拒绝缺少 任何
提供的先前协商的
层,则则 从
transceiver.[[Sender]]
.[[SendEncodings]]
中移除与缺失层对应的字典。
根据 [RFC8853]
的指示,更新每个同时播送层的暂停状态,通过将 active
成员设置为对应字典中 transceiver.[[Sender]].[[SendEncodings]]
的 true
(未暂停)或
false
(已暂停)。
将 transceiver.[[Mid]]
设置为
transceiver.[[JsepMid]]
。
让 direction 成为一个
RTCRtpTransceiverDirection
值,表示来自 媒体媒体描述
的方向,但将发送和接收方向反转,以表示此对等体的视角。如果 媒体描述
被拒绝,则将 direction 设置为 "inactive
"。
如果 direction 为 "sendrecv
"
或 "recvonly
",让
msids 成为媒体描述指示的与 transceiver.[[Receiver]]
.[[ReceiverTrack]]
关联的 MSID 列表。否则,让 msids 为一个空列表。
处理远程轨道,与 transceiver、direction、msids、addList、removeList 和 trackEventInits 一起进行。
将 transceiver.[[Receiver]]
.[[ReceiveCodecs]]
设置为 description 协商的接收编解码器,以及用户代理当前准备接收的编解码器。
如果 description 的类型为
"answer
"
或
"pranswer
",
那么执行以下步骤:
将 transceiver.[[Sender]]
.[[SendCodecs]]
设置为 description
协商的发送编解码器,以及用户代理当前能够发送的编解码器。
将 transceiver.[[CurrentDirection]]
和
transceiver.[[Direction]]s
设置为 direction。
让 transport 成为表示 RTCDtlsTransport
对象的
RTP/RTCP 组件的 媒体媒体传输,用于
transceiver 的 关联的 媒体描述,根据
[RFC8843]。
将 transceiver.[[Sender]]
.[[SenderTransport]]
设置为 transport。
将 transceiver.[[Receiver]]
.[[ReceiverTransport]]
设置为 transport。
根据 [RFC8445]
的规则,设置 transport 的 [[IceRole]]
。
[[IceRole]]
不是 unknown
,则不修改
[[IceRole]]
。
controlling
。
a=ice-lite
,则将
[[IceRole]]
设置为 controlling
。
a=ice-lite
,则将
[[IceRole]]
设置为 controlled
。
[[IceRole]]
始终具有值。
如果 媒体描述
被拒绝,并且 transceiver.[[Stopped]]
为 false
,则 停止
该该RTCRtpTransceiver
transceiver。
否则(如果 description 的类型是 "rollback
)执行以下步骤:
让 pendingDescription 为 connection.[[PendingLocalDescription]]
或 connection.[[PendingRemoteDescription]]
,取决于哪一个不为
null
。
对于 connection 的 转接器集合 中的每个 transceiver,执行以下步骤:
如果 transceiver 在设置
pendingDescription 之前没有与
关联 一个
媒体描述,
则解除关联并将 transceiver.[[JsepMid]]
和 transceiver.[[Mid]]
设置为
null
。
将
transceiver.[[Sender]]
.[[SenderTransport]]
设置为
transceiver.[[Sender]]
.[[LastStableStateSenderTransport]]
。
如果 transceiver.[[Sender]]
.[[LastStableRidlessSendEncodings]]
不是 null
,并且 transceiver.[[Sender]]
.[[SendEncodings]]
中的任何编码包含一个 rid
成员,则将 transceiver.[[Sender]]
.[[SendEncodings]]
设置为 transceiver.[[Sender]]
.[[LastStableRidlessSendEncodings]]
。
将 transceiver.[[Receiver]]
.[[ReceiverTransport]]
设置为 transceiver.[[Receiver]]
.[[LastStableStateReceiverTransport]]
。
将 transceiver.[[Receiver]]
.[[ReceiveCodecs]]
设置为 transceiver.[[Receiver]]
.[[LastStableStateReceiveCodecs]]
。
如果 connection.[[SignalingState]]
是 "have-remote-offer
",则运行以下子步骤:
让 msids 成为 transceiver.[[Receiver]]
.[[LastStableStateAssociatedRemoteMediaStreams]]
中所有 id
的 MediaStream
对象的列表,或者如果没有,则为空列表。
使用
transceiver、transceiver.[[CurrentDirection]]
、msids、addList、removeList
和 trackEventInits 处理远程轨道。
如果 transceiver 是在设置
pendingDescription 时创建的,并且从未通过 addTrack
()
附加任何轨道,则 停止
RTCRtpTransceiver transceiver,并将其从
connection 的 转发器集合 中移除。
将 connection.[[PendingLocalDescription]]
和 connection.[[PendingRemoteDescription]]
设置为 null
,并将 connection.[[SignalingState]]
设置为 "stable
"。
如果 description 的类型是 "answer
",则执行以下步骤:
对于 connection 的 传输器集合 中的每个 transceiver,执行以下步骤:
如果 transceiver 是 stopped
,并且与一个
m= 部分 相关联,且关联的 m= 部分在
connection.[[CurrentLocalDescription]]
或 connection.[[CurrentRemoteDescription]]
中被拒绝,则从 connection 的 传输器集合 中移除
transceiver。
如果 connection.[[SignalingState]]
现在是 "stable
",
则执行以下步骤:
对于在之前步骤中从 传输器集合 中移除的任何
transceiver,
如果它的任何传输 (transceiver.[[Sender]]
.[[SenderTransport]]
或
transceiver.[[Receiver]]
.[[ReceiverTransport]]
)
仍然没有关闭且不再被非停止的传输器引用,则关闭 RTCDtlsTransport
和它们关联的 RTCIceTransport
。
这将导致这些对象在排队任务中触发事件。
对于 connection 的 传输器集合 中的每个 transceiver:
让 codecs 为 transceiver.[[Sender]]
.[[SendCodecs]]
。
如果 codecs 不是空列表:
对于 transceiver.[[Sender]]
.[[SendEncodings]]
中的每个 encoding,
如果 encoding.codec
没有
匹配
codecs 中的任何条目,
移除
encoding[codec
]。
如果 connection.[[SignalingState]]
在上方更改了,触发一个名为
signalingstatechange
的事件于 connection。
对于 errorList 中的每个 channel,
触发一个名为
error
的事件,使用 RTCErrorEvent
接口,将 errorDetail
属性设置为
"data-channel-failure
"
于 channel。
对于 muteTracks 中的每个 track,
设置
track
的静音状态为 true
。
对于 removeList 中的每个 stream 和 track 对, 移除 stream 中的 track。
对于 addList 中的每个 stream 和 track 对, 添加 track 到 stream。
对于 trackEventInits 中的每个 entry,
触发一个名为
track
的事件,使用 RTCTrackEvent
接口,将其 receiver
属性初始化为 entry.receiver
,
track
属性初始化为
entry.track
,
streams
属性初始化为
entry.streams
,
以及 transceiver
属性初始化为
entry.transceiver
于 connection 对象上。
以
undefined
解析 p。
返回 p。
要 设置配置,使用 configuration,请执行以下步骤:
令 configuration 为要处理的
字典。
RTCConfiguration
令 connection 为目标 RTCPeerConnection
对象。
令 oldConfig 为 connection.[[Configuration]]
。
如果 configuration.oldConfig 不是
certificates
null
,执行以下步骤:,如果有任何步骤失败,则 抛出
InvalidModificationError
异常:
如果 configuration.certificates
的长度与
connectionoldConfig.[[Configuration]].certificates
的长度不同,则失败。
令 index 初始化为 0。
令 size 初始化为 configuration.
的长度。
certificates
当 index 小于 size
时,执行以下步骤::将
configuration.
certificates
中的每一个元素执行以下步骤:
如果 configuration.certificates
中
index 位置的 ECMAScript 对象与
connectionoldConfig 中 [[Configuration]].certificates
中
index 位置的 ECMAScript 对象不同,则失败。
将 index 增加 1。
如果 configuration.bundlePolicy
的值与
oldConfig.bundlePolicy
不同,则失败。
如果 configuration.rtcpMuxPolicy
的值与
oldConfig.rtcpMuxPolicy
不同,则失败。
如果 configuration.iceCandidatePoolSize
的值与
oldConfig.iceCandidatePoolSize
不同,且已经调用了
setLocalDescription
,则失败。
如果 configuration.bundlePolicy
的值
被设置并且与 connection 的捆绑策略不同,则 抛出 一个
InvalidModificationError
。
如果 configuration.rtcpMuxPolicy
的值
被设置并且与 connection 的 rtcpMux 策略不同,则 抛出 一个
InvalidModificationError
。
如果 configuration.iceCandidatePoolSize
的值
被设置并且与 connection 之前设置的 iceCandidatePoolSize
不同,
并且 setLocalDescription
已经被调用,则 抛出 一个
InvalidModificationError
。
让 iceServers 为 configuration.iceServers
。
将 iceServers 截断到最大支持元素的数量。
对于 iceServers 中的每个 server, 执行以下步骤:
让 urls 为
server.urls
。
如果 urls 是一个字符串,则将 urls 设置为仅包含该字符串的列表。
如果 urls 为空,则 抛出 一个
"SyntaxError
" DOMException
。
对于 urls 中的每个 url,执行 验证 ICE 服务器 URL 算法。
将 ICE Agent 的 ICE 传输设置
设置为
configuration.iceTransportPolicy
。
如[RFC8829RFC9429]
(第 4.1.18
节)中定义,如果新的 ICE
ICE 传输设置更改了
现有设置,则在下一个收集阶段之前不会采取任何行动。如果脚本希望立即发生这种情况,它应该进行 ICE 重启。
将 ICE Agent 的预取 ICE 候选池大小 设置为[RFC8829RFC9429]
(第 3.5.4 节
和 第 4.1.1
节)的值
configuration.iceCandidatePoolSize
。
如果新的ICE
候选池大小更改了现有设置,则这可能导致立即收集新的池候选者,或丢弃现有的池候选者,如[RFC8829RFC9429]
(第 4.1.18
节)。
让 validatedServers 为空列表。
如果 configuration.
已定义,则对每个元素执行以下步骤:
iceServers
让 server 为当前列表元素。
让 urls 为
server.
。
urls
如果 urls 是一个字符串,则将 urls 设置为仅包含该字符串的列表。
如果 urls 为空,则 抛出 一个
SyntaxError
。
对于 urls 中的每个 url,执行 [=验证 ICE 服务器 URL=] 算法。
将 server 添加到 validatedServers。
将 ICE Agent 的 ICE
服务器列表 设置为
validatedServers设置为
iceServers。
如[RFC8829RFC9429]
(第 4.1.18
节)中定义,如果新服务器列表替换了ICE
Agent 的现有 ICE 服务器列表ICE
服务器列表,将不会采取任何行动,直到下一个收集阶段。如果脚本希望立即发生这种情况,它应该进行 ICE 重启。然而,如果 ICE
ICE 候选池 的大小非零,则任何 现有 现有
的候选者将被丢弃,并将从新服务器收集新的候选者。
将 configuration 存储在
[[Configuration]]
内部槽中。
要 验证 ICE 服务器 URL url,执行以下步骤:
使用 [RFC3986]
中定义的通用 URI 语法解析 url,并获取 scheme name。如果根据
[RFC3986] 中定义的语法解析失败,抛出
一个 SyntaxError
。
如果 scheme name 未被浏览器实现,抛出
一个 NotSupportedError
。
如果 scheme name 是 turn
或 turns
,并且使用 [RFC7065] 中定义的语法解析
url 失败,抛出 一个 SyntaxError
。
如果 scheme name 是 stun
或
stuns
,并且使用 [RFC7064] 中定义的语法解析
url 失败,抛出 一个
SyntaxError
。
让 parsedURL 为 解析 url 的结果。
如果以下任何条件适用,则 抛出 一个
"SyntaxError
" DOMException
:
如果 parsedURL 的 scheme 未被用户代理实现,则 抛出 一个 NotSupportedError
。
让 hostAndPortURL 为结果
解析 字符串
"https://"
和 parsedURL 的 path 的拼接结果。
如果 hostAndPortURL 解析失败,则 抛出 一个
"SyntaxError
" DOMException
。
如果 scheme nameparsedURL 的 scheme 是 turn
"turn"
或 或
turns
"turns"
,并且 server.username
或
server.credential
被省略不存在,则 抛出 一个
InvalidAccessError
。
如果 scheme name 是 turn
或 turns
,并且
server.
是
"credentialType
",
并且
server.password
不是
DOMString,则
抛出 一个 credential
InvalidAccessError
。
本节中呈现的 RTCPeerConnection
接口通过本规范中的多个部分接口进行了扩展。特别是,RTP 媒体 API 部分添加了发送和接收 MediaStreamTrack
对象的 API。
WebIDL[Exposed=Window]
interface RTCPeerConnection
: EventTarget {
constructor
(optional RTCConfiguration
configuration = {});
Promise<RTCSessionDescriptionInit
> createOffer
(optional RTCOfferOptions
options = {});
Promise<RTCSessionDescriptionInit
> createAnswer
(optional RTCAnswerOptions
options = {});
Promise<undefined> setLocalDescription
(optional RTCLocalSessionDescriptionInit
description = {});
readonly attribute RTCSessionDescription
? localDescription
;
readonly attribute RTCSessionDescription
? currentLocalDescription
;
readonly attribute RTCSessionDescription
? pendingLocalDescription
;
Promise<undefined> setRemoteDescription
(RTCSessionDescriptionInit
description);
readonly attribute RTCSessionDescription
? remoteDescription
;
readonly attribute RTCSessionDescription
? currentRemoteDescription
;
readonly attribute RTCSessionDescription
? pendingRemoteDescription
;
Promise<undefined> addIceCandidate
(optional RTCIceCandidateInit
candidate = {});
readonly attribute RTCSignalingState
signalingState
;
readonly attribute RTCIceGatheringState
iceGatheringState
;
readonly attribute RTCIceConnectionState
iceConnectionState
;
readonly attribute RTCPeerConnectionState
connectionState
;
readonly attribute boolean? canTrickleIceCandidates
;
undefined restartIce
();
RTCConfiguration
getConfiguration
();
undefined setConfiguration
(optional RTCConfiguration
configuration = {});
undefined close
();
attribute EventHandler onnegotiationneeded
;
attribute EventHandler onicecandidate
;
attribute EventHandler onicecandidateerror
;
attribute EventHandler onsignalingstatechange
;
attribute EventHandler oniceconnectionstatechange
;
attribute EventHandler onicegatheringstatechange
;
attribute EventHandler onconnectionstatechange
;
// 旧版接口扩展
// 支持本节中的方法是可选的。
// 如果支持这些方法,
// 必须按照“旧版接口扩展”一节中的定义实现它们。
Promise<undefined> createOffer
(RTCSessionDescriptionCallback
successCallback,
RTCPeerConnectionErrorCallback
failureCallback,
optional RTCOfferOptions
options = {});
Promise<undefined> setLocalDescription
(RTCLocalSessionDescriptionInit
description,
VoidFunction successCallback,
RTCPeerConnectionErrorCallback
failureCallback);
Promise<undefined> createAnswer
(RTCSessionDescriptionCallback
successCallback,
RTCPeerConnectionErrorCallback
failureCallback);
Promise<undefined> setRemoteDescription
(RTCSessionDescriptionInit
description,
VoidFunction successCallback,
RTCPeerConnectionErrorCallback
failureCallback);
Promise<undefined> addIceCandidate
(RTCIceCandidateInit
candidate,
VoidFunction successCallback,
RTCPeerConnectionErrorCallback
failureCallback);
};
localDescription
类型为 RTCSessionDescription
,
只读,
可为空
localDescription
属性 必须 返回
[[PendingLocalDescription]]
如果其值不为
null
,否则 必须 返回
[[CurrentLocalDescription]]
。
注意
[[CurrentLocalDescription]]
.sdp
和
[[PendingLocalDescription]]
.sdp
不必与传递给相应的
setLocalDescription
调用中的
sdp
值字符串完全相同
(即 SDP 可能会被解析和重新格式化,并且可能会添加 ICE 候选者)。
currentLocalDescription
类型为 RTCSessionDescription
,
只读,
可为空
currentLocalDescription
属性 必须 返回
[[CurrentLocalDescription]]
。
它表示最后一次成功协商的本地描述,该描述是在 RTCPeerConnection
转换为稳定状态时,以及在创建提供或应答后由 ICE 代理
生成的任何本地候选者。
pendingLocalDescription
类型为 RTCSessionDescription
,
只读,
可为空
pendingLocalDescription
属性 必须 返回
[[PendingLocalDescription]]
。
它表示正在协商的本地描述,加上在创建提供或应答后由 ICE 代理 生成的任何本地候选者。
如果 RTCPeerConnection
处于稳定状态,则值为 null
。
remoteDescription
类型为 RTCSessionDescription
,
只读,
可为空
remoteDescription
属性 必须 返回
[[PendingRemoteDescription]]
如果其值不为
null
,否则 必须 返回
[[CurrentRemoteDescription]]
。
注意
[[CurrentRemoteDescription]]
.sdp
和
[[PendingRemoteDescription]]
.sdp
不必与传递给相应的
setRemoteDescription
调用中的
sdp
值字符串完全相同
(即 SDP 可能会被解析和重新格式化,并且可能会添加 ICE 候选者)。
currentRemoteDescription
类型为 RTCSessionDescription
,
只读,
可为空
currentRemoteDescription
属性 必须 返回
[[CurrentRemoteDescription]]
。
它表示最后一次成功协商的远程描述,最后一次
RTCPeerConnection
转换为稳定状态,以及自从创建了
提供的远程候选者的任何内容,通过
addIceCandidate
()
方法。
pendingRemoteDescription
类型为 RTCSessionDescription
,
只读,
可为空
pendingRemoteDescription
属性 必须 返回
[[PendingRemoteDescription]]
。
它表示正在协商的远程描述,包含通过
addIceCandidate
()
方法提供的任何远程候选者。如果 RTCPeerConnection
处于稳定状态,则值为 null
。
signalingState
类型为
RTCSignalingState
,
只读
signalingState
属性 必须 返回
RTCPeerConnection
对象的
[[SignalingState]]
。
iceGatheringState
类型为 RTCIceGatheringState
,
只读
iceGatheringState
属性 必须 返回
RTCPeerConnection
对象的
[[IceGatheringState]]
。
iceConnectionState
类型为 RTCIceConnectionState
,
只读
iceConnectionState
属性 必须 返回
RTCPeerConnection
对象的
[[IceConnectionState]]
。
connectionState
类型为 RTCPeerConnectionState
,
只读
connectionState
属性 必须 返回
RTCPeerConnection
对象的
[[ConnectionState]]
。
canTrickleIceCandidates
类型为
boolean,只读,可为空
canTrickleIceCandidates
属性指示远程对等方是否能够接受增量 ICE 候选者
[RFC8838].
该值是根据远程描述是否指示支持增量 ICE 而确定的,如
[RFC9429]
(第 4.1.17
节)。
在
setRemoteDescription
完成之前,
此值为
null
。
onnegotiationneeded
类型为
EventHandler
negotiationneeded
。
onicecandidate
类型为 EventHandler
icecandidate
。
onicecandidateerror
类型为
EventHandler
icecandidateerror
。
onsignalingstatechange
类型为
EventHandler
signalingstatechange
。
oniceconnectionstatechange
类型为
EventHandler
iceconnectionstatechange
onicegatheringstatechange
类型为
EventHandler
icegatheringstatechange
。
onconnectionstatechange
类型为
EventHandler
connectionstatechange
。
createOffer
createOffer
方法生成包含支持的会话配置的 SDP blob,这些配置符合 RFC 3264 中的 offer 规范,包括附加到此 RTCPeerConnection
的本地 MediaStreamTrack
的描述、该实现支持的
codec/RTP/RTCP 能力,以及 ICE 代理 和 DTLS 连接的参数。可以提供
options 参数,以对生成的 offer 提供额外控制。
如果系统资源有限(例如,解码器数量有限),createOffer
需要返回反映系统当前状态的提议,以便在尝试获取这些资源时
setLocalDescription
会成功。会话描述 必须 在返回的 Promise 的
fulfillment 回调结束之前保持可用,以便
setLocalDescription
不会导致错误。
生成的 SDP 必须 遵循 [RFC9429]
中描述的生成提议的适当流程,除了用户代理 必须
将标记为 stopping
的转发器视为
stopped
,以便符合 RFC9429 的要求。
作为提议,生成的 SDP 将包含会话支持或首选的编解码器/RTP/RTCP 能力的完整集
(与仅包括用于的特定协商子集的应答不同)。如果在建立会话后调用
createOffer
,
createOffer
将生成与当前会话兼容的提议,结合自上次完整提议-应答交换以来对会话所做的任何更改,例如添加或删除轨道。如果没有进行更改,提议将包括当前本地描述的能力,以及可以在更新提议中协商的任何额外能力。
生成的 SDP 还将包含 ICE
代理的
usernameFragment
,
password
和 ICE
选项(如 [RFC5245]
第 14 节所定义)并且可能还包含由代理收集的任何本地候选者。
configuration中
的certificates
值为
RTCPeerConnection
配置的证书,这些证书由应用程序为
RTCPeerConnection
提供。这些证书以及任何默认证书用于生成一组
证书指纹。这些证书指纹
用于构建SDP。
生成SDP的过程暴露了底层系统的部分媒体能力,这些能力提供了设备上 一般持久的跨源信息。因此,它增加了应用程序的指纹识别面。在隐私敏感的上下文中,浏览器可以考虑 缓解措施,例如生成仅匹配能力的常见子集的SDP。
当调用该方法时,用户代理必须执行以下步骤:
让 connection 成为调用该方法的 RTCPeerConnection
对象。
如果 connection.[[IsClosed]]
为
true
,则返回一个被 拒绝
的承诺,附带一个新创建的
InvalidStateError
。
要 创建提议 ,给定 connection 执行以下步骤:
如果 connection.[[SignalingState]]
既不是 "stable
"
也不是
"have-local-offer
",
则返回一个 Promise 拒绝,并带有一个新创建的
InvalidStateError
。
将 p 设置为一个新的 Promise。
返回 p。
创建提议的并行步骤给定 connection 和一个 Promise p 如下:
如果 connection 不是通过一组证书构造的,并且尚未生成证书, 则等待证书生成。
如果此检查因任何原因失败,则拒绝
p,并生成一个新创建的OperationError
,并中止这些步骤。
排队一个任务以执行 创建提议的最终步骤,给定 connection 和 p。
创建提议的最终步骤给定 connection 和一个 Promise p 如下:
如果 connection.[[IsClosed]]
为
true
,则中止这些步骤。
如果 connection 被修改到需要额外检查 发起者的系统状态, 则并行地开始 创建报价的并行步骤, 以 connection 和 p 为基础,并中止这些步骤。
RTCRtpTransceiver
被添加到 connection 时调用了
createOffer
,
但在执行 创建提议的并行步骤
时,
添加了一个视频 RTCRtpTransceiver
,
需要对视频系统资源进行额外检查。
根据从先前检查中获得的信息,当前的 connection 状态及其 RTCRtpTransceiver
,生成一个
SDP 提议,
sdpString,如[RFC9429]
(第 5.2
节) 中所述。
如 [RFC8843]
(第 7 节)所述,如果使用捆绑(参见 RTCBundlePolicy
),
必须选择一个带标签的 m= 段,以便协商 BUNDLE 组。用户代理 必须
选择与 转发器集合
中第一个非停止的转发器相对应的 m=
段,作为带标签的提议者的 m= 段。
这允许远端预测哪个转发器是带标签的 m= 段,而无需解析 SDP。
编解码器优先级 的 媒体描述的
相关 转发器
transceiver 被称为
transceiver.[[PreferredCodecs]]
的值,过滤条件如下(或在
transceiver.[[PreferredCodecs]]
为空时
不设置):
将 kind 设置为 transceiver 的
[[Receiver]]
的
[[ReceiverTrack]]
的
kind
。
如果
transceiver.direction
为 "sendonly
"
或 "sendrecv
",
则排除不包含在 已实现的发送编解码器列表
中的任何编解码器,适用于 kind。
如果
transceiver.direction
为 "recvonly
"
或 "sendrecv
",
则排除不包含在 已实现的接收编解码器列表
中的任何编解码器,适用于 kind。
过滤条件 不得 更改编解码器优先级的顺序。
如果 [[SendEncodings]]
插槽
的 RTCRtpSender
长度大于 1,
则对于在 [[SendEncodings]]
中给出的每个编码
的 RTCRtpSender
,
向相应的媒体部分添加一行 a=rid send
,
并添加一行 a=simulcast:send
,提供与
encodings
字段中给出的 RIDs 相同的顺序。
没有设置 RID 限制。
[RFC8853] 第 5.2 节规定了 a=simulcast 行中 RIDs 的顺序建议了一种 提议的偏好顺序。如果浏览器 决定不传输所有编码,则应该 期望它首先停止发送列表中的最后一个编码。
将 offer 设置为新创建的 RTCSessionDescriptionInit
字典,其
type
成员初始化为字符串 "offer
",其
sdp
成员初始化为 sdpString。
将 [[LastCreatedOffer]]
内部槽设置为 sdpString。
解析 p 与 offer。
createAnswer
createAnswer
方法生成一个 [SDP]
答复,带有与远程配置参数兼容的支持配置。
类似于 createOffer
,
返回的 SDP blob 包含有关附加到此RTCPeerConnection
的本地
MediaStreamTrack
的描述,
该会话的编解码器/RTP/RTCP 选项,以及由ICE Agent 收集的任何候选项。
options 参数可以提供,以提供对生成的答案的附加控制。
像createOffer
,
返回的描述 SHOULD
反映系统的当前状态。会话描述 MUST 保持可用于 setLocalDescription
而不会在返回的承诺的 履行 回调结束之前导致错误。
作为答案,生成的 SDP 将包含特定的 编解码器/RTP/RTCP 配置,这与相应的提议一起指定了如何建立媒体平面。 生成 SDP 的过程 MUST 遵循[RFC9429] 中描述的生成答案的适当过程。
生成的 SDP 还将包含ICE
agent的
usernameFragment
,
password
和 ICE
选项(如定义在[RFC5245],
第 14 节)并可能包含代理收集的任何本地候选者。
certificates
值在
configuration 为RTCPeerConnection
提供了应用程序为RTCPeerConnection
配置的证书。
这些证书以及任何默认证书用于生成一组证书指纹。
这些证书指纹用于构造 SDP。
答复可以标记为临时的,如下所述
[RFC9429]
(第 4.1.10.1
节),
方法通过将type
设置为"pranswer
"来实现。
当调用该方法时,用户代理 MUST 执行以下步骤:
让 connection 成为调用该方法的 RTCPeerConnection
对象。
如果 connection.[[IsClosed]]
是
true
,则返回一个拒绝的承诺,使用新创建的InvalidStateError
。
为 创建答案 给定 connection 运行以下步骤:
如果 connection.[[SignalingState]]
既不是"have-remote-offer
"
也不是"have-local-pranswer
",
则返回一个拒绝的承诺,
使用新创建的InvalidStateError
。
让 p 成为一个新创建的承诺。
返回 p。
创建答案的并行步骤 给定 connection 和承诺 p 如下:
如果 connection 不是用一组证书构造的,并且尚未生成一个,则等待生成。
如果此检查因任何原因失败,拒绝
p 使用新创建的创建的
OperationError
并中止这些步骤。
排队一个任务运行创建答案的最终步骤给定p。
创建答案的最终步骤给定 承诺 p 如下:
如果 connection.[[IsClosed]]
是
true
,则中止这些步骤。
如果 connection 被修改,以至于需要额外检查回答者的系统状态, 则并行再次开始创建答案的并行步骤, 给定connection和p,并中止这些步骤。
这可能是必要的,例如,当createAnswer
在一个RTCRtpTransceiver
的方向
是"recvonly
",
但在执行创建答案的并行步骤时,
方向更改为"sendrecv
",
需要对视频编码资源进行额外检查。
根据从先前检查中获得的信息以及当前状态的connection和它的
RTCRtpTransceiver
,
生成一个 SDP 答复sdpString,如
[RFC9429]
(第 5.3
节)中所述。
m= 部分的 编解码器偏好 的
关联的转发器关联的
转发器,
transceiver, 被称为
的
transceiver.RTCRtpTransceiver
[[PreferredCodecs]]
具有以下过滤(如果 transceiver.[[PreferredCodecs]]
是空的):
如果 direction
为 "sendrecv
",
排除任何不在
RTCRtpSender
.getCapabilities
(kind)。codecs
和
RTCRtpReceiver
.getCapabilities
(kind)。codecs
。
让 kind 为 transceiver 的
[[Receiver]]
的
[[ReceiverTrack]]
的
kind
。
如果 如果
transceiver.direction
为
为 "sendonly
"
或 "sendrecv
",
排除任何不在的
在
已实现的发送
编解码器 对于
kind。
RTCRtpSender
.getCapabilities
(kind)。
如果 如果
transceiver.direction
为
为 "recvonly
"
或 "sendrecv
",
排除任何不在的
在
已实现的接收
编解码器 对于
kind。
RTCRtpReceiver
.getCapabilities
(kind)。
过滤 MUST NOT 更改编解码器优先级的顺序。
如果 [[SendEncodings]]
槽的长度大于 1,则对于 RTCRtpSender
中给定的每个编码,在相应的媒体部分添加 a=rid send
行,并添加
a=simulcast:send
行,以 encodings
字段中给定的顺序提供 RID。未设置 RID 限制。
如果这是对接收 simulcast 的提议的回应,则对于请求接收 simulcast 的每个媒体部分,执行以下步骤:
如果 a=simulcast
属性包含以逗号分隔的 RIDs 替代方案,则只保留第一个。
如果 a=simulcast
属性中存在同名的 RIDs,
则只保留第一个。没有设置 RID 限制。
在答案中从媒体部分排除任何在相应的转发器的
[[Sender]]
.[[SendEncodings]]
。
当 setRemoteDescription
(offer)
建立发送者的 提议信封时,
发送者的 [[SendEncodings]]
会在 "have-remote-offer
"
中更新,使其可回滚。然而,一旦为发送者建立了
simulcast
信封,在使用 setLocalDescription
设置此答案时,发送者的
[[SendEncodings]]
会在后续修剪中发生变化。
让 answer 成为一个新创建的
RTCSessionDescriptionInit
字典,其
type
成员初始化为字符串 "answer
",其
sdp
成员初始化为 sdpString。
将 [[LastCreatedAnswer]]
内部槽设置为 sdpString。
解析 p 与 answer。
setLocalDescription
setLocalDescription
方法指示 RTCPeerConnection
将提供的 RTCLocalSessionDescriptionInit
应用为本地描述。
此 API 更改本地媒体状态。为了成功处理应用程序希望将一种媒体格式更改为另一种不兼容格式的情况,RTCPeerConnection
必须能够同时支持使用当前和待定本地描述(例如,支持两种描述中存在的编解码器),直到收到最终答案,此时RTCPeerConnection
可以完全采用待定本地描述,或者如果远程方拒绝更改,则回滚到当前描述。
传递描述是可选的。如果不提供,则setLocalDescription
将隐式地创建一个邀请或创建一个答案,视需要而定。如[RFC9429](第 5.4
节) 中所述,如果传入的描述包含 SDP,则该 SDP 不允许在从createOffer
或createAnswer
返回时发生更改。
当调用该方法时,用户代理必须执行以下步骤:
让description成为方法的第一个参数。
让connection成为RTCPeerConnection
对象。
让sdp为description.sdp
。
返回将以下步骤链式 连接到 connection 的 操作链 的结果:
让type为description.type
(如有),或如果未提供,则为"offer
",并且connection.[[SignalingState]]
要么是"stable
",要么是"have-local-offer
",或"have-remote-pranswer
";否则为"answer
"。
如果type为"offer
",并且sdp不是空字符串且不等于connection.[[LastCreatedOffer]]
,则返回一个被拒绝的
promise,带有一个新创建的异常InvalidModificationError
,并中止这些步骤。
如果type为"answer
"或"pranswer
",并且sdp不是空字符串且不等于connection.[[LastCreatedAnswer]]
,则返回一个被拒绝的
promise,带有一个新创建的异常InvalidModificationError
,并中止这些步骤。
如果sdp为空字符串,并且type为"offer
",则运行以下子步骤:
将sdp设置为connection.[[LastCreatedOffer]]
的值。
如果 sdp 是空字符串,或者它不再准确代表 发起者的系统状态, 则让 p 是通过 创建一个提议 的结果, 并返回对 p 的反应结果,其中包含一个履行步骤,该步骤设置本地会话描述, 该描述由其第一个参数指示。
如果sdp为空字符串,并且type为"answer
"或"pranswer
",则运行以下子步骤:
将sdp设置为connection.[[LastCreatedAnswer]]
的值。
如果sdp为空字符串,或者如果它不再准确地表示connection的回答者的系统状态,那么让p为与connection一起创建一个答案的结果,并返回与p的反应结果,该反应结果包含以下履行步骤:
返回由 设置本地会话描述 指示的结果,格式为
{type, sdp}
。
setRemoteDescription
setRemoteDescription
方法指示
RTCPeerConnection
应用提供的
RTCSessionDescriptionInit
作为远程的邀请或答案。此 API 会改变本地媒体状态。
当调用该方法时,用户代理 必须 执行以下步骤:
让 description 为方法的第一个参数。
让 connection 为调用该方法的
RTCPeerConnection
对象。
addIceCandidate
addIceCandidate
方法为 ICE Agent 提供一个远程候选者。此方法也可以用来
指示远程候选者的结束,当传入的 candidate
成员为空字符串时。
该方法使用的唯一成员是
candidate
、sdpMid
、
sdpMLineIndex
,
和
usernameFragment
;
其余的则被忽略。
当该方法被调用时,用户代理 必须 执行以下步骤:
让 candidate 为方法的参数。
让 connection 为调用该方法的
RTCPeerConnection
对象。
如果 candidate.candidate
不是空字符串并且 candidate.sdpMid
和
candidate.sdpMLineIndex
都是 null
,则返回一个 promise 拒绝
并附上一个新创建的 TypeError
。
如果 remoteDescription
为 null
,则返回一个 promise 拒绝
并附上一个新创建的 创建的 InvalidStateError
。
如果 candidate.sdpMid
不是 null
,则执行以下步骤:
如果
candidate.sdpMid
与 remoteDescription
中的任意媒体描述的 mid 不相等,则返回一个 promise 拒绝
并附上一个新创建的 创建的 OperationError
。
否则,如果
candidate.sdpMLineIndex
不是 null
,运行以下步骤:
如果
candidate.sdpMLineIndex
等于或大于
remoteDescription
中的媒体描述数量,
返回一个 promise 拒绝,并附带一个新创建的 异常 OperationError
。
如果任一
candidate.sdpMid
或
candidate.sdpMLineIndex
指示在
remoteDescription
中的媒体描述,该描述
关联的传输器是 stopped
,则返回一个
promise 解析 为
undefined
。
如果
candidate.usernameFragment
不是 null
,并且不等于在相应的 媒体描述 中存在的任何用户名片段,
返回一个 promise 拒绝,并附带一个
新创建的 异常 OperationError
。
让 p 是一个新的 promise。
并行执行,如果候选者不是 行政禁止,则按照
[RFC9429]
(第
4.1.19 节)。
使用
candidate.usernameFragment
来识别 ICE 生成;如果
usernameFragment
为 null
,则处理
candidate 以获得最新的 ICE 生成。
如果candidate.candidate
是一个空字符串,则将candidate作为对应的媒体描述和ICE候选生成的结束候选指示进行处理。如果candidate.sdpMid
和candidate.sdpMLineIndex
都为null
,则此结束候选指示适用于所有媒体描述。
如果 candidate 无法成功添加,用户代理 必须 排队一个任务,执行以下步骤:
如果
connection.[[IsClosed]]
为 true
,则中止这些步骤。
拒绝
p,附上一个新创建的 创建的 OperationError
并中止这些步骤。
如果 candidate 成功添加,或者候选者被 行政禁止,用户代理 必须 排队一个任务,执行以下步骤:
如果
connection.[[IsClosed]]
为 true
,则中止这些步骤。
如果
connection.[[PendingRemoteDescription]]
不是 null
,并表示处理的 ICE 生成,则将
candidate 添加到
connection.[[PendingRemoteDescription]]
.sdp。
如果
connection.[[CurrentRemoteDescription]]
不是 null
,并表示处理的 ICE 生成,则将
candidate 添加到
connection.[[CurrentRemoteDescription]]
.sdp。
解析
p 为
undefined
。
如果候选者 被行政禁止,则用户代理已决定不允许对该 地址进行连接尝试。
出于隐私原因,开发者无法得知某个地址/端口是否被阻止;它的表现方式完全如同该地址没有 响应一样。
用户代理 必须 禁止连接到 [Fetch] 阻止坏端口 列表中的地址,并 可以 选择禁止连接到其他地址。
如果 iceTransportPolicy
成员属于
RTCConfiguration
的值为
relay
,
则需要外部解析的候选项,例如 mDNS 候选项和 DNS 候选项,必须 被禁止。
由于 WebIDL 处理,
addIceCandidate
(null
)
被解释为带有默认字典的调用,这在上面的算法中表示所有媒体描述和 ICE
候选者生成的结束候选者。这是为了兼容旧版的设计。
restartIce
restartIce
方法告诉 RTCPeerConnection
应该重新启动 ICE。后续对 createOffer
的调用将创建描述来重新启动 ICE,如 [RFC5245]
第9.1.1.1节所述。
当调用此方法时,用户代理 必须 执行以下步骤:
让 connection 为调用此方法的 RTCPeerConnection
。
清空 connection.[[LocalIceCredentialsToReplace]]
,
并使用在 connection.[[CurrentLocalDescription]]
中找到的所有 ICE 凭据(ice-ufrag 和 ice-pwd,定义在 [RFC5245]
第15.4节)以及在 connection.[[PendingLocalDescription]]
中找到的所有 ICE 凭据填充它。
更新谈判需要标志 对于 connection。
getConfiguration
返回一个RTCConfiguration
对象,
该对象表示当前的RTCPeerConnection
对象的配置。
当调用此方法时,用户代理 必须 返回存储在
[[Configuration]]
内部槽中的
RTCConfiguration
对象。
setConfiguration
setConfiguration
方法更新此RTCPeerConnection
对象的配置。
这包括更改ICE Agent的配置。如[RFC9429]
(第3.5.1节)所述,
当ICE配置以需要新的收集阶段的方式发生变化时,必须进行ICE重启。
当调用setConfiguration
方法时,用户代理 必须 执行以下步骤:
让 connection 为调用此方法的 RTCPeerConnection
。
如果 connection.[[IsClosed]]
为
true
,则抛出一个
InvalidStateError
。
设置配置由 configuration指定。
close
当调用close
方法时,用户代理
必须 执行以下步骤:
让 connection 为调用此方法的RTCPeerConnection
对象。
false
。
关闭连接 算法给定一个connection和一个disappear布尔值,步骤如下:
如果 connection.[[IsClosed]]
为
true
,则中止这些步骤。
将 connection.[[IsClosed]]
设置为
true
。
将 connection.[[SignalingState]]
设置为
"closed
"。
这不会触发任何事件。
让 transceivers 为执行CollectTransceivers
算法的结果。对于每个RTCRtpTransceiver
transceiver在transceivers中,执行以下步骤:
如果 transceiver.[[Stopped]]
为
true
,中止这些子步骤。
停止RTCRtpTransceiver 使用transceiver和disappear。
将每个 connection 的 [[ReadyState]]
槽设置为
RTCDataChannel
的
"closed
"。
RTCDataChannel
将会被
突然关闭,并且关闭程序不会被调用。
如果 connection.[[SctpTransport]]
不为
null
,通过发送SCTP ABORT块来拆除基础SCTP关联,并将
[[SctpTransportState]]
设置为"closed
"。
将每个 connection 的 RTCDtlsTransport
的 [[DtlsTransportState]]
槽设置为
"closed
"。
销毁connection的ICE Agent, 突然结束任何活动的ICE处理并释放任何相关资源(例如,TURN权限)。
将每个
connection 的 RTCIceTransport
的
[[IceTransportState]]
插槽设置为
"closed
"。
将connection.[[IceConnectionState]]
设置为"closed
"。
这不会触发任何事件。
将connection.[[ConnectionState]]
设置为"closed
"。
这不会触发任何事件。
RTCPeerConnection
接口的主要定义中,
因为不允许在部分接口中定义重载函数。
支持本节中的方法是可选的。然而,如果支持这些方法,则必须根据这里指定的内容进行实现。
RTCPeerConnection
上的
addStream
方法
可以轻松地用以下方式进行 polyfill:
RTCPeerConnection.prototype.addStream = function(stream) {
stream.getTracks().forEach((track) => this.addTrack(track, stream));
};
createOffer
当调用 createOffer
方法时,用户代理 必须 执行以下步骤:
让 successCallback 成为方法的第一个 参数。
让 failureCallback 成为方法的第二个 参数所指示的回调。
让 options 成为方法的第三个参数所指示的回调。
运行由 RTCPeerConnection
的
createOffer
()
方法,参数为
options,并让
p 成为结果
的 Promise。
当 完成 p,其值为 offer 时,调用 successCallback 并将 offer 作为参数传入。
当 拒绝 p,理由为 r 时,调用 failureCallback 并 将 r 作为参数传入。
返回一个 Promise,该 Promise 解析 为
undefined
。
setLocalDescription
当调用 setLocalDescription
方法时,用户代理 必须 执行以下步骤:
让 description 为方法的第一个 参数。
让 successCallback 为方法的第二个参数 指定的回调。
让 failureCallback 为方法的第三个参数 指定的回调。
执行由 RTCPeerConnection
的
setLocalDescription
方法,使用
description 作为唯一参数,并让
p 为结果承诺。
当 实现
p 时,调用
successCallback,并将
undefined
作为参数传递。
当 拒绝 p,原因是 r,调用 failureCallback,并将 r 作为参数传递。
返回一个承诺 已解决
为 undefined
。
createAnswer
当调用 createAnswer
方法时,用户代理 必须 执行以下步骤:
让 successCallback 成为方法的第一个 参数。
让 failureCallback 成为方法的第二个 参数所指示的回调。
运行由 RTCPeerConnection
的
createAnswer
()
方法指定的步骤,无
参数,并让 p 成为结果
的 Promise。
当 完成 p,其值为 answer 时,调用 successCallback 并将 answer 作为参数传入。
当 拒绝 p,理由为 r 时,调用 failureCallback 并 将 r 作为参数传入。
返回一个 Promise,该 Promise 解析 为
undefined
。
setRemoteDescription
当调用 setRemoteDescription
方法时,用户代理 必须 执行以下步骤:
让 description 为方法的第一个 参数。
让 successCallback 为方法的第二个 参数所指示的回调。
让 failureCallback 为方法的第三个 参数所指示的回调。
执行由 RTCPeerConnection
的
setRemoteDescription
方法
,将 description 作为唯一参数,并
让 p 为结果承诺。
当 履行
p 时,调用
successCallback,以
undefined
作为参数。
当 拒绝 p,原因是 r,调用 failureCallback,以 r 作为参数。
返回一个 解析 的承诺,
以 undefined
作为结果。
addIceCandidate
当调用 addIceCandidate
方法时,用户代理 必须 执行以下步骤:
让 candidate 为方法的第一个参数。
让 successCallback 为方法的第二个参数指示的回调。
让 failureCallback 为方法的第三个参数指示的回调。
运行由 RTCPeerConnection
的
addIceCandidate
()
方法,参数为 candidate,并让
p 为结果的承诺。
当 实现
p 时,调用
successCallback,并以
undefined
作为参数。
当 拒绝 p,理由为 r,调用 failureCallback,并以 r 作为参数。
返回一个以 解析
的承诺,结果为 undefined
。
这些回调仅用于旧版 API。
WebIDLcallback RTCPeerConnectionErrorCallback
= undefined (DOMException error);
error
类型为
DOMException
WebIDLcallback RTCSessionDescriptionCallback
= undefined (RTCSessionDescriptionInit
description);
description
类型为 RTCSessionDescriptionInit
本节描述了一组旧版扩展,可用于影响如何创建提议,此外还有添加到RTCPeerConnection
中的媒体。建议开发者改为使用RTCRtpTransceiver
API。
当调用createOffer
时,
如果指定了本节中的任何旧版选项,则执行以下步骤,而不是常规的createOffer
步骤:
让 options 为方法的第一个参数。
让 connection 为当前的RTCPeerConnection
对象。
对于 offerToReceive<Kind>
中的每个成员,在options中具有类型kind,执行以下步骤:
对于每个未停止的
"sendrecv
"
转换器
转换器类型
kind,将
transceiver.[[Direction]]
设置为
"sendonly
".
对于每个未停止的
"recvonly
"
转换器
转换器类型
kind,将
transceiver.[[Direction]]
设置为
"inactive
".
如果有下一个选项,则继续处理下一个选项。
如果 connection 有任何未停止的
"sendrecv
"
或
"recvonly
"
传输器的
transceiver kind
kind,继续处理下一个选项(如果有的话)。
让transceiver为调用connection.addTransceiver
(kind)的结果,
但此操作不得 更新协商所需标志。
如果transceiver因上一个操作抛出错误而未设置,则中止这些步骤。
设置transceiver.[[Direction]]
为
"recvonly
"。
按照createOffer
指定的步骤创建提议。
WebIDLpartial dictionary RTCOfferOptions
{
boolean offerToReceiveAudio
;
boolean offerToReceiveVideo
;
};
offerToReceiveAudio
类型为
boolean
此设置提供对音频方向性的额外控制。例如,它可以确保音频可以被接收,无论是否发送音频。
offerToReceiveVideo
类型为
boolean
此设置提供对视频方向性的额外控制。例如,它可以确保视频可以被接收,无论是否发送视频。
RTCPeerConnection
对象 必须 在
任何事件可能导致事件处理程序在该对象上被触发时不被垃圾收集。当对象的 [[IsClosed]]
内部槽为
true
时,不能触发任何此类事件处理程序,因此可以安全地垃圾收集该对象。
所有 RTCDataChannel
和 MediaStreamTrack
对象
与一个 RTCPeerConnection
连接,拥有对
RTCPeerConnection
对象的强引用。
所有返回承诺的方法都遵循承诺的标准错误处理规则。那些不返回承诺的方法可能会抛出异常来指示错误。
RTCSdpType
枚举描述
一个 RTCSessionDescriptionInit
、RTCLocalSessionDescriptionInit
,
或 RTCSessionDescription
实例的类型。
WebIDLenum RTCSdpType
{
"offer
",
"pranswer
",
"answer
",
"rollback
"
};
枚举值 | 描述 |
---|---|
offer
|
一个 |
pranswer
|
一个 |
answer
|
一个 |
rollback
|
一个 |
RTCSessionDescription
类用于
RTCPeerConnection
来
暴露本地和远程会话描述。
WebIDL[Exposed=Window]
interface RTCSessionDescription
{
constructor
(RTCSessionDescriptionInit
descriptionInitDict);
readonly attribute RTCSdpType
type
;
readonly attribute DOMString sdp
;
[Default] RTCSessionDescriptionInit
toJSON
();
};
constructor()
RTCSessionDescription
()
构造函数接受一个字典参数,
description,其内容用于初始化
新的 RTCSessionDescription
对象。这个构造函数
已被弃用;它仅存在于向后兼容的原因。
type
类型为 RTCSdpType
,只读
sdp
类型为 DOMString,只读,默认为
""
toJSON()
WebIDLdictionary RTCSessionDescriptionInit
{
required RTCSdpType
type
;
DOMString sdp
= "";
};
type
类型为 RTCSdpType
,必需
sdp
类型为 DOMString
type
为 "rollback
",
则该成员未使用。
WebIDLdictionary RTCLocalSessionDescriptionInit
{
RTCSdpType
type
;
DOMString sdp
= "";
};
type
类型为 RTCSdpType
setLocalDescription
将根据 RTCPeerConnection
的
[[SignalingState]]
推断类型。
sdp
类型为 DOMString
type
为
"rollback
",该成员未使用。
对于一个 RTCPeerConnection
的许多状态更改
将需要通过信令通道与远程端进行通信,以产生所需的效果。应用程序可以通过监听
negotiationneeded
事件,保持了解何时需要进行信令。
此事件根据连接的 协商需求标志 的状态触发,
该标志由一个 [[NegotiationNeeded]]
内部槽表示。
本节为非规范性。
如果对一个 RTCPeerConnection
执行了
需要信令的操作,则连接将被标记为需要协商。这类操作的示例包括添加或停止
一个 RTCRtpTransceiver
,或者添加第一个
RTCDataChannel
。
实现内部的变化也可能导致连接被标记为需要协商。
请注意,更新 协商需求标志 的确切程序在下文中进行了说明。
本节为非规范性。
当会话描述为 "answer
" 类型,并且成功设置时,negotiation-needed 标志将被清除。
提供的描述需要与当前在 RTCRtpTransceiver
和
RTCDataChannel
实例的状态一致。
特别是,这意味着所有非 stopped
的 transceiver
必须在本地描述中有一个带有匹配属性的
关联部分,
如果创建了任何数据通道,本地描述中也应存在数据部分,以代表 RTCPeerConnection
实例中的数据通道。
请注意,更新 协商需求标志 的确切程序在下文中进行了说明。
以下过程在本文件的其他地方引用时发生。它也可能由于影响协商的实现内部更改而发生。 如果发生此类更改,用户代理 必须 更新协商需求标志。
要 更新协商需求标志, 对于 connection,运行以下步骤:
如果 connection.[[Operations]]
的长度不为 0
,则将
connection.[[UpdateNegotiationNeededFlagOnEmptyChain]]
设置为 true
,并中止这些步骤。
排队一个任务以运行以下步骤:
如果 connection.[[IsClosed]]
为
true
,则终止这些步骤。
如果 connection.[[Operations]]
的长度不是
0
,则将
connection.[[UpdateNegotiationNeededFlagOnEmptyChain]]
设置为 true
,并终止这些步骤。
如果 connection.[[SignalingState]]
不是
"stable
",则终止这些步骤。
如果 检查是否需要协商 的结果为
false
,
清除协商需要标志,通过将
connection.[[NegotiationNeeded]]
设置为
false
,并终止这些步骤。
如果 connection.[[NegotiationNeeded]]
已经是
true
,则终止这些步骤。
将 connection.[[NegotiationNeeded]]
设置为
true
。
触发一个事件,其名称为 negotiationneeded
,在
connection 上触发。
任务排队防止 negotiationneeded
过早触发,
在多个
对 connection 进行修改的常见情况中。
此外,我们通过仅在 操作链 为空时
触发 negotiationneeded
,避免与
协商方法发生竞争。
要 检查是否需要协商 对于 connection,执行以下检查:
如果需要任何特定于实现的协商,如本节开头所述,返回
true
。
如果
connection.[[LocalIceCredentialsToReplace]]
不为空,返回 true
。
让 description 为
connection.[[CurrentLocalDescription]]
。
如果 connection 创建了任何 RTCDataChannel
,
并且在 description 中尚未协商任何 m= 部分,返回 true
。
对于 connection 的 转发器集合 中的每个 transceiver,执行以下检查:
如果 transceiver.[[Stopping]]
为
true
并且
transceiver.[[Stopped]]
为
false
,返回 true
。
如果 transceiver 不是 stopped
并且尚未与 description
中的 m= 部分
关联,返回 true
。
如果 transceiver 不是 stopped
并且与 description
中的 m= 部分
关联,则执行以下检查:
如果 transceiver.[[Direction]]
是
"sendrecv
"
或
"sendonly
",
并且 关联 的 m=
部分在 description 中
要么不包含单个 a=msid
行,要么
该 m=
部分中的 a=msid
行的数量,
或者 MSID 值
本身,与 transceiver.sender.[[AssociatedMediaStreamIds]]
中的
不同,则返回 true
。
如果 description 的类型为
"offer
",并且 associated m=
部分在 connection.[[CurrentLocalDescription]]
和
connection.[[CurrentRemoteDescription]]
中均不匹配 transceiver.[[Direction]]
,
则返回 true
。在此步骤中,当方向与
[[CurrentRemoteDescription]]
中的方向进行比较时,
描述的方向必须被反转,以代表对等方的观点。
如果 description 的类型为
"answer
",并且
description 中的
associated m=
段的方向与
transceiver.[[Direction]]
与提供的方向相交(如在
[RFC9429]
(第 5.3.1
节)中所述),
则返回 true
。
如果 transceiver 是 stopped
并且与 m= 部分 相关联,但
相关的 m= 部分在 connection.[[CurrentLocalDescription]]
或
connection.[[CurrentRemoteDescription]]
,
返回 true
。
如果所有先前的检查都已执行且未返回 true
,则没有剩余的协商内容;返回 false
。
此接口描述了一个 ICE 候选者,如 [RFC5245]
第 2 节所述。除了 candidate
、
sdpMid
、
sdpMLineIndex
和
usernameFragment
,剩余的属性
是通过解析 candidate
成员在 candidateInitDict 中获得的(如果其格式正确)。
[Exposed=Window] interface RTCIceCandidate { constructor(optional RTCIceCandidateInit candidateInitDict = {}); readonly attribute DOMString candidate; readonly attribute DOMString? sdpMid; readonly attribute unsigned short? sdpMLineIndex; readonly attribute DOMString? foundation; readonly attribute RTCIceComponent? component; readonly attribute unsigned long? priority; readonly attribute DOMString? address; readonly attribute RTCIceProtocol? protocol; readonly attribute unsigned short? port; readonly attribute RTCIceCandidateType? type; readonly attribute RTCIceTcpCandidateType? tcpType; readonly attribute DOMString? relatedAddress; readonly attribute unsigned short? relatedPort; readonly attribute DOMString? usernameFragment; readonly attribute RTCIceServerTransportProtocol? relayProtocol; readonly attribute DOMString? url; RTCIceCandidateInit toJSON(); };
constructor()
RTCIceCandidate()
构造函数
接受一个字典参数 candidateInitDict,
其内容用于初始化新的
RTCIceCandidate
对象。
当调用时,运行以下步骤:
sdpMid
和
sdpMLineIndex
的成员
candidateInitDict 为 null
,则 抛出 一个 TypeError
。
返回 创建一个 RTCIceCandidate 的结果,使用 candidateInitDict。
要 创建一个 RTCIceCandidate 使用 candidateInitDict 字典,运行以下步骤:
RTCIceCandidate
对象。
null
:
foundation
,
component
, priority
, address
,
protocol
, port
, type
, tcpType
,
relatedAddress
,
和 relatedPort
。
candidate
, sdpMid
,
sdpMLineIndex
,
usernameFragment
。
candidate
字典成员的 candidateInitDict。如果 candidate 为
非空字符串,运行以下步骤:
candidate-attribute
语法解析 candidate。
candidate-attribute
的解析失败,
中止这些步骤。
RTCIceCandidate
的构造函数
仅对 candidateInitDict 中的字典成员进行基本解析和类型检查。对
candidate
、
sdpMid
、
sdpMLineIndex
、
usernameFragment
与对应会话描述的详细验证是在将 RTCIceCandidate
对象传递给
addIceCandidate
()
时进行的。
为了保持向后兼容,任何解析 candidate 属性的错误都会被忽略。在这种情况下,candidate
属性保留原始
candidate
字符串,该字符串在 candidateInitDict 中给出,但导出属性
如 foundation
、
priority
等则被设置为
null
。
大多数属性在 [RFC5245] 的第 15.1 节中定义。
candidate
类型为 DOMString,只读
candidate-attribute
。
如果此 RTCIceCandidate
表示候选结束指示或对等体反射远程候选,candidate
是一个空字符串。
sdpMid
类型为 DOMString,只读,允许为 null
null
,则此属性包含该候选与之关联的媒体组件的 媒体流 "识别标签",该标签在 [RFC5888]
中定义。
sdpMLineIndex
类型为
unsigned short,只读,允许为 null
null
,则表示与此候选者关联的 SDP 中的 媒体描述 的索引(从零开始)。
foundation
类型为 DOMString,只读,允许为 null
RTCIceTransport
中出现的候选。
component
类型为 RTCIceComponent
,
只读,允许为 null
rtp
" 或 "rtcp
")。
这对应于 component-id
字段在 candidate-attribute
中,解码为字符串表示,具体定义见 RTCIceComponent
。
priority
类型为 unsigned long,只读,允许为 null
address
类型为 DOMString,只读,允许为 null
候选的地址,允许 IPv4 地址、IPv6 地址和完全合格的域名(FQDN)。这对应于 connection-address
字段,在 candidate-attribute
中。
远程候选可能会被暴露,例如通过 [[SelectedCandidatePair]]
.remote
。默认情况下,用户代理必须将任何暴露的远程候选的 address
属性设置为
null
。一旦 RTCPeerConnection
实例通过 Web 应用程序使用 addIceCandidate
学习到一个地址,用户代理可以在该 RTCPeerConnection
实例中代表该新学到地址的远程候选的任何 RTCIceCandidate
中暴露 address
属性值。
通过 ICE 收集的候选中暴露的地址,并在
RTCIceCandidate
实例中向应用程序公开的地址可以揭示有关设备和用户的更多信息(例如位置、本地网络拓扑),
而这些信息可能是非 WebRTC 启用浏览器用户未曾预期的。
这些地址始终暴露给应用程序,并可能暴露给通信方,并且可以在没有特定用户同意的情况下暴露(例如用于数据通道的对等连接,或仅用于接收媒体)。
这些地址也可以用作临时或持久的跨域状态,因此会增加设备的指纹识别表面。
应用程序可以通过强制 ICE 代理 仅报告
relay 候选地址,从而避免将地址暴露给通信方,无论是暂时还是永久。这可以通过 iceTransportPolicy
成员在 RTCConfiguration
中设置来实现。
为了限制暴露给应用程序自身的地址,浏览器可以根据 [RFC8828] 为用户提供不同的本地地址共享政策。
protocol
类型为 RTCIceProtocol
,
只读,允许为 null
udp
”/“tcp
”)。
这对应于 transport
字段,在 candidate-attribute
中。
port
类型为 unsigned short,只读,允许为 null
type
类型为 RTCIceCandidateType
,
只读,允许为 null
candidate-types
字段,在 candidate-attribute
中。
tcpType
类型为 RTCIceTcpCandidateType
,
只读,允许为 null
protocol
为 "tcp
",
tcpType
表示 TCP 候选的类型。否则,tcpType
为 null
。这对应于 tcp-type
字段在 candidate-attribute
中。
relatedAddress
类型为
DOMString,只读,允许为 null
relatedAddress
是它所来源候选的 IP 地址。对于主机候选,relatedAddress
为 null
。这对应于 rel-address
字段
在 candidate-attribute
中。
relatedPort
类型为 unsigned short,只读,允许为 null
relatedPort
是它所来源候选的端口。
对于主机候选,relatedPort
为 null
。这对应于 rel-port
字段
在 candidate-attribute
中。
usernameFragment
类型为 DOMString,只读,允许为 null
ufrag
。
relayProtocol
类型为 RTCIceServerTransportProtocol,只读,
允许为 null
relay
"
的本地候选,此属性表示
终端与 TURN 服务器通信所使用的协议。对于所有其他候选,它的值为 null
。
toJSON()
toJSON
()
操作的
RTCIceCandidate
接口,执行以下步骤:
RTCIceCandidateInit
字典。
candidate
,sdpMid
,
sdpMLineIndex
,
usernameFragment
»:
RTCIceCandidate
对象的结果。
json[attr]
设置为 value。
WebIDLdictionary RTCIceCandidateInit
{
DOMString candidate
= "";
DOMString? sdpMid
= null;
unsigned short? sdpMLineIndex
= null;
DOMString? usernameFragment
= null;
};
candidate
类型为 DOMString,默认值为
""
candidate-attribute
,
如[RFC5245]
第15.1节所定义。如果这表示候选项结束的指示,candidate
为
空字符串。
sdpMid
类型为 DOMString,可空,默认值为
null
null
,则包含与此候选者关联的媒体组件的媒体流“识别标签”,该标签在[RFC5888]中定义。
sdpMLineIndex
类型为 unsigned short,可空,默认值
为 null
null
,则表示该候选者关联的SDP中媒体描述的索引(从零开始)。
usernameFragment
类型为 DOMString,可空,默认值为
null
null
,该属性携带了在[RFC5245]
第15.4节中定义的ufrag
。
candidate-attribute
语法用于解析
candidate
成员
的candidateInitDict中的值,属于RTCIceCandidate
()
构造函数。
candidate-attribute
的主要语法在
[RFC5245]
第15.1节中定义。此外,浏览器必须支持
[RFC6544]
第4.5节中定义的ICE TCP语法扩展。
浏览器 可能 支持其他 RFC 中定义的 candidate-attribute
的语法扩展。
RTCIceProtocol
表示
ICE候选项的协议。
WebIDLenum RTCIceProtocol
{
"udp
",
"tcp
"
};
枚举值 | 描述 |
---|---|
udp
|
一个UDP候选项,如[RFC5245]中所述。 |
tcp
|
一个TCP候选项,如[RFC6544]中所述。 |
RTCIceTcpCandidateType
表示
ICE TCP候选项的类型,如[RFC6544]中所定义的。
WebIDLenum RTCIceTcpCandidateType
{
"active
",
"passive
",
"so
"
};
枚举值 | 描述 |
---|---|
active
|
一个"active "
TCP候选项是指传输将尝试打开一个出站连接,但不会接收入站连接请求。
|
passive
|
一个"passive "
TCP候选项是指传输将接收入站连接尝试,但不会尝试建立连接。
|
so
|
一个"so "候选项
是指传输将尝试与其对等方同时建立连接。
|
用户代理通常只会收集active
ICE TCP
候选项。
RTCIceCandidateType
表示
ICE候选项的类型,如[RFC5245]
第15.1节所定义。
RTCIceServerTransportProtocol
表示
客户端与服务器之间使用的传输协议类型,如[RFC8656]
第3.1节所定义。
WebIDLenum RTCIceServerTransportProtocol
{
"udp
",
"tcp
",
"tls
",
};
枚举值 | 描述 |
---|---|
udp
|
TURN客户端使用UDP作为与服务器的传输协议。 |
tcp
|
TURN客户端使用TCP作为与服务器的传输协议。 |
tls
|
TURN客户端使用TLS作为与服务器的传输协议。 |
icecandidate
事件的
RTCPeerConnection
使用
RTCPeerConnectionIceEvent
接口。
当触发一个包含
RTCIceCandidate
对象的
RTCPeerConnectionIceEvent
事件时,
它 必须 包含 sdpMid
和 sdpMLineIndex
的值。
如果 RTCIceCandidate
的类型为
"srflx
" 或类型
"relay
",则事件的
url
属性 必须 被设置为从候选项获取的 ICE 服务器的 URL。
icecandidate
事件用于三种不同类型的指示:
已收集到一个候选。事件的
candidate
成员将正常填充。它应该被传递给
远程对等方,并传递到
addIceCandidate
。
一个 RTCIceTransport
已
完成对候选的 生成,
并提供了一个候选结束指示,如[RFC8838]
第8.2节定义的那样。这
通过
candidate
.candidate
设置为空字符串来指示。事件的
candidate
对象应该被
传递给远程对等方,并传递到
addIceCandidate
像典型的 ICE
候选一样,以向远程对等方提供候选结束指示。
所有 RTCIceTransport
已
完成候选收集,
并且 RTCPeerConnection
的 RTCIceGatheringState
已
过渡到 "complete
"。
这通过
candidate
成员设置为 null
来指示。这个事件仅
出于向后兼容的目的而存在,不需要向远程对等方发出信号。这相当于一个
icegatheringstatechange
事件,状态为
"complete
"。
WebIDL[Exposed=Window]
interface RTCPeerConnectionIceEvent
: Event {
constructor
(DOMString type, optional RTCPeerConnectionIceEventInit
eventInitDict = {});
readonly attribute RTCIceCandidate
? candidate
;
readonly attribute DOMString? url
;
};
RTCPeerConnectionIceEvent.constructor()
candidate
的类型 RTCIceCandidate
,
只读,可为 null
candidate
属性是与此次事件相关的新 ICE 候选项的 RTCIceCandidate
对象。
当生成指示结束候选项收集的事件时,该属性设置为 null
。
即使存在多个媒体组件,只有一个事件包含 null
候选项会被触发。
url
的类型 DOMString,只读,可为 null
url
属性
是用于识别收集此候选项的 STUN 或 TURN 服务器的 STUN 或 TURN URL。
如果候选项不是从 STUN 或 TURN 服务器收集的,则该参数将设置为
null
。
此属性已不推荐使用;它仅用于向后兼容。
请优先使用候选项url
。
WebIDLdictionary RTCPeerConnectionIceEventInit
: EventInit {
RTCIceCandidate
? candidate
;
DOMString? url
;
};
candidate
类型 RTCIceCandidate
,
可为 null
请参阅candidate
属性
的RTCPeerConnectionIceEvent
接口。
url
类型 DOMString,可为 null
url
属性
是用于识别收集此候选项的 STUN 或 TURN 服务器的 STUN 或 TURN URL。
icecandidateerror
事件
属于 RTCPeerConnection
接口,
并使用 RTCPeerConnectionIceErrorEvent
接口。
WebIDL[Exposed=Window]
interface RTCPeerConnectionIceErrorEvent
: Event {
constructor
(DOMString type, RTCPeerConnectionIceErrorEventInit
eventInitDict);
readonly attribute DOMString? address
;
readonly attribute unsigned short? port
;
readonly attribute DOMString url
;
readonly attribute unsigned short errorCode
;
readonly attribute USVString errorText
;
};
RTCPeerConnectionIceErrorEvent.constructor()
address
类型 DOMString,只读,可为 null
address
属性是用于与 STUN 或 TURN 服务器通信的本地 IP 地址。
在多宿主系统上,可能会使用多个接口来联系服务器,而该属性允许应用程序确定在哪个接口上发生了故障。
如果本地 IP 地址值尚未作为本地候选项的一部分暴露,则 address
属性将被设置为 null
。
port
类型 unsigned
short,只读,可为 null
port
属性是用于与 STUN 或 TURN 服务器通信的端口。
url
类型 DOMString,只读
url
属性是 STUN 或 TURN URL,用于识别发生故障的 STUN 或 TURN 服务器。
errorCode
类型 unsigned short,只读
errorCode
属性是 STUN 或 TURN 服务器返回的数值 STUN 错误代码 [STUN-PARAMETERS]。
如果没有主机候选项可以到达服务器,errorCode
将设置为值 701,该值超出 STUN 错误代码范围。此错误在 RTCIceGatheringState
的
"gathering
"
状态下
仅触发一次,每个服务器 URL 触发一次。
errorText
类型 USVString,只读
errorText
属性是 STUN 或 TURN 服务器返回的 STUN 理由文本 [STUN-PARAMETERS]。
如果无法到达服务器,errorText
将设置为提供有关错误的实现特定值。
WebIDLdictionary RTCPeerConnectionIceErrorEventInit
: EventInit {
DOMString? address
;
unsigned short? port
;
DOMString url
;
required unsigned short errorCode
;
USVString errorText
;
};
address
类型 DOMString,可为 null
用于与 STUN 或 TURN 服务器通信的本地地址,或 null
。
port
类型 unsigned short,可为 null
用于与 STUN 或 TURN 服务器通信的本地端口,或 null
。
url
类型 DOMString
标识发生故障的 STUN 或 TURN 服务器的 STUN 或 TURN URL。
errorCode
类型 unsigned short,必需
STUN 或 TURN 服务器返回的数值 STUN 错误代码。
errorText
类型 USVString
STUN 或 TURN 服务器返回的 STUN 理由文本。
RTCPeerConnection
实例用于
与对等方进行身份验证的证书使用 RTCCertificate
接口。这些
对象可以通过应用程序使用 generateCertificate
方法
显式生成,并且可以在构造新的 RTCConfiguration
时提供
在 RTCPeerConnection
实例。
这里提供的显式证书管理功能是可选的。如果应用程序在构建 RTCPeerConnection
时未提供 certificates
配置选项,则 MUST 由 用户代理 生成一组新的证书。该组证书 MUST 包括一个具有 P-256
曲线上的私钥的 ECDSA 证书,以及使用 SHA-256 哈希的签名。
WebIDLpartial interface RTCPeerConnection
{
static Promise<RTCCertificate
>
generateCertificate
(AlgorithmIdentifier keygenAlgorithm);
};
generateCertificate
, static
generateCertificate
函数使 用户代理 创建一个 X.509 证书 [X509V3]
和相应的私钥。通过 RTCCertificate
接口提供的信息句柄。
返回的 RTCCertificate
可用于控制
在 RTCPeerConnection
建立的 DTLS
会话中提供的证书。
keygenAlgorithm 参数用于控制与证书关联的私钥的生成方式。keygenAlgorithm 参数使用 WebCrypto [WebCryptoAPI] AlgorithmIdentifier 类型。
以下值 必须 被一个 用户代理 支持: { name: "RSASSA-PKCS1-v1_5",
modulusLength: 2048, publicExponent: new Uint8Array([1, 0,
1]), hash: "SHA-256" }
,以及 { name:
"ECDSA", namedCurve:
"P-256"
}
。
预计 用户代理 将具有一小组 或者甚至固定的值供其接受。
此过程生成的证书还包含一个签名。此签名的有效性仅与兼容性相关。RTCPeerConnection
仅使用公钥和
结果证书指纹,但如果证书格式良好,则更可能接受证书。浏览器选择用于签署证书的算法;浏览器 SHOULD 选择 SHA-256
[FIPS-180-4]
如果需要哈希算法。
生成的证书 MUST NOT 包含可以与用户或 用户代理 关联的信息。应使用随机值作为区分名和序列号。
当调用该方法时,用户代理 MUST 运行以下步骤:
将 keygenAlgorithm 设置为 generateCertificate
的第一个参数。
将 expires 设置为 2592000000(30*24*60*60*1000)
这意味着证书将在从 generateCertificate
调用的时间起默认到期 30 天。
如果 keygenAlgorithm 是一个对象,运行以下步骤:
让 certificateExpiration 成为将
转换
的结果,将表示为
keygenAlgorithm 的 ECMAScript 对象转换为
RTCCertificateExpiration
字典。
如果转换失败并产生一个 error, 则返回一个被 拒绝 的 promise, 原因是 error。
如果
certificateExpiration.expires
不是 undefined
,则将 expires
设置为
certificateExpiration.expires
。
如果 expires 大于 31536000000, 则将 expires 设置为 31536000000。
这意味着证书不能在
generateCertificate
调用时有效超过 365 天。
用户代理 可以 进一步限制 expires 的值。
将 normalizedKeygenAlgorithm 设置为执行 标准化算法
的结果,该操作名称为 generateKey
,并为
支持的算法
提供特定于生成证书的值
RTCPeerConnection
。
如果上述标准化步骤失败并出现 error,返回一个被 拒绝 的 promise,附带 error。
如果 normalizedKeygenAlgorithm 参数标识了 用户代理 无法或不愿用于生成 RTCPeerConnection
证书的算法,则返回一个 被拒绝的
Promise
,并附带一个类型为 DOMException
的 NotSupportedError
。尤其是,
normalizedKeygenAlgorithm 必须
是一个可以用于生成签名的非对称算法,以认证 DTLS 连接。
将 p 设置为一个新的 promise。
以 并行方式 运行以下步骤:
执行由 normalizedKeygenAlgorithm 指定的生成密钥操作。
将 generatedKeyingMaterial 和 generatedKeyCertificate 设置为通过上述步骤生成的私钥材料和证书。
将 certificate 设置为一个新的
RTCCertificate
对象。
将 certificate.[[Expires]] 设置为当前时间加上 expires 值。
将 certificate.[[Origin]]
设置为
相关设置对象 的
origin。
将生成的密钥材料存储在安全模块中,并让 handle 成为对其的引用标识符。
将 certificate.[[KeyingMaterialHandle]]
设置为 handle。
将 certificate.[[Certificate]]
设置为
generatedCertificate。
解决 p 为 certificate。
返回 p。
RTCCertificateExpiration
字典
RTCCertificateExpiration
用于
设置由
generateCertificate
生成的
证书的到期日期。
dictionary RTCCertificateExpiration { [EnforceRange]DOMTimeStampunsigned long long expires; };
expires
,
类型为 DOMTimeStamp
可选的 expires
属性
MAY 被添加到传递给
generateCertificate
的算法定义中。
如果该参数存在,则表示
以毫秒为单位 最大时间
RTCCertificate
是有效的 相对于 从
证书创建的
当前时间时间。
RTCCertificate
接口
RTCCertificate
接口
代表用于
认证 WebRTC 通信的证书。除了可见属性外,内部槽包含指向生成的
私钥材料的句柄([[KeyingMaterialHandle]]),一个
证书([[Certificate]]),
RTCPeerConnection
使用它来
与对等方进行身份验证,以及创建该对象的
来源([[Origin]])。
[Exposed=Window, Serializable] interface RTCCertificate { readonly attributeDOMTimeStampEpochTimeStamp expires; sequence<RTCDtlsFingerprint> getFingerprints(); };
expires
类型为 EpochTimeStamp
,只读
expires 属性指示相对于 1970-01-01T00:00:00Z 的时间(以毫秒为单位),
之后浏览器将视该证书为无效。此时间之后,尝试使用此证书构建
RTCPeerConnection
将失败。
请注意,该值可能不会反映在证书本身的
notAfter
参数中。
getFingerprints
返回证书指纹列表,其中一个指纹是使用证书签名中使用的摘要算法计算的。
对于此 API 的目的,[[Certificate]]
插槽
包含非结构化的二进制数据。未提供机制让应用程序访问
[[KeyingMaterialHandle]]
内部槽或其引用的密钥材料。实现
MUST 支持应用程序从持久存储中存储和检索 RTCCertificate
对象,同时还保留
由 [[KeyingMaterialHandle]]
引用的密钥材料。
实现 SHOULD 将敏感的密钥材料存储在安全模块中,以防止同一进程内存攻击。这允许
私钥被存储和使用,但不容易通过
内存攻击读取。
RTCCertificate
对象
是 可序列化的对象
[HTML]. 它们的 序列化步骤,给定
value
和 serialized,为:
expires
属性的值。
[[Certificate]]
中的非结构化二进制数据的副本。
[[Origin]]
中非结构化二进制数据的副本。
[[KeyingMaterialHandle]]
中句柄的序列化(而不是私钥材料本身)。
它们的 反序列化步骤,给定 serialized 和 value,为:
expires
属性以包含 serialized.[[Expires]]。
[[Certificate]]
设置为
serialized.[[Certificate]] 的副本[[Origin]]
设置为
serialized.[[Origin]] 的副本[[KeyingMaterialHandle]]
设置为私钥材料句柄的结果,
该句柄来自反序列化
serialized.[[KeyingMaterialHandle]]
以这种方式支持结构化克隆使得
RTCCertificate
实例
可以持久化到存储中。它还允许实例通过像
postMessage
(message, options)
[html] 传递给其他来源。然而,该对象不能被任何其他来源使用,除非是最初创建它的来源。
RTP 媒体 API
允许 Web 应用程序通过点对点连接发送和接收
MediaStreamTrack
s。
当将轨道添加到 RTCPeerConnection
时,会产生信令;当此
信令被转发到远程对等体时,会在远程端创建相应的轨道。
发送方的一个 RTCPeerConnection
和接收方的轨道之间并没有严格的 1:1
对应关系。首先,发送轨道的 ID 与接收轨道的 ID 没有映射关系。此外,replaceTrack
会更改由
RTCRtpSender
发送的轨道,但不会在接收方创建新的轨道;相应的 RTCRtpReceiver
只会有一个轨道,
该轨道可能表示多个来源的媒体拼接在一起。
addTransceiver
和
replaceTrack
都可以用于多次发送同一个轨道,在接收方将观察到多个接收器,每个接收器都有自己独立的轨道。因此,更准确地说,可以认为一方的 RTCRtpSender
与另一方的 RTCRtpReceiver
的轨道之间存在 1:1
关系,
可在必要时通过 RTCRtpTransceiver
的
mid
来匹配发送方和接收方。
在发送媒体时,发送方可能需要重新调整或重新采样媒体,以满足各种要求,包括 SDP 协商的信封、编码器的对齐限制,甚至 CPU 过载检测或带宽估算。
遵循 [RFC9429] (第 3.6 节) 的规则, 视频 可能 被缩小。媒体 不得 被放大以创建未出现在输入源中的伪数据,媒体 不得 被裁剪,除非满足像素计数的约束,且宽高比 不得 被更改。
WebRTC 工作组正在寻求有关更复杂处理这种情况的需求和时间表的实施反馈。一些可能的设计已在 GitHub issue 1283 中进行了讨论。
当 每当 视频
被 重新缩放,例如对于某些宽度或高度的组合和 由于
scaleResolutionDownBy
值,
当结果的宽度或高度不是整数时可能会发生。在这种情况下,用户代理 必须必须
不 使用 传输大于
整数 部分的
结果部分
从 scaleResolutionDownBy
,
除非是为了遵循编码器的最小分辨率。如果缩放后宽度 或 或 高度的整数部分为零,该如何传输 则取决于实现由实现定义。
对于每个MediaStreamTrack
的实际编码和传输由称为RTCRtpSender
的对象进行管理。
同样,接收和解码MediaStreamTrack
由称为RTCRtpReceiver
的对象进行管理。
每个RTCRtpSender
最多与一条轨道相关联,
每条要接收的轨道与一个RTCRtpReceiver
完全关联。
每个MediaStreamTrack
的编码和传输应
应确保其特征(宽度
、高度
和 帧率
用于视频轨道;样本大小
、样本率
和 通道数
用于音频轨道)在远端创建的轨道中合理程度上得以保留。
有些情况下,这种情况并不适用,例如,在任一端或网络中可能存在资源限制,或者可能有应用于 RTCRtpSender
设置的指示实现以不同方式进行处理。
RTCPeerConnection
对象包含一个
一组
RTCRtpTransceiver
,表示带有一些共享状态的配对发送器和接收器。
该集合在创建时初始化为空集合
RTCPeerConnection
对象。
RTCRtpSender
和 RTCRtpReceiver
总是与一个 RTCRtpTransceiver
相关联,并保持其生命周期。
RTCRtpTransceiver
在应用程序通过 addTrack
()
方法将 MediaStreamTrack
附加到 RTCPeerConnection
时隐式创建,或当应用程序使用
addTransceiver
方法时显式创建。
当应用程序应用包含新媒体描述的远程描述时,也会创建它们。此外,当应用于表示远程端点具有要发送的媒体的远程描述时,相关的 MediaStreamTrack
和 RTCRtpReceiver
通过 track
事件暴露给应用程序。
为了使一个 RTCRtpTransceiver
能够与另一个端点发送和/或接收媒体,
必须通过 SDP 进行协商,以确保两个端点都有一个 RTCRtpTransceiver
对象,该对象与相同的 关联 的 媒体描述。
创建报价时,将生成足够的媒体描述以覆盖该端的所有传输器。当该报价被设置为本地描述时,任何未关联的传输器都将与报价中的媒体描述相关联。
当将报价设置为远程描述时,报价中的任何媒体描述(尚未与传输器关联)都将与新传输器或现有传输器关联。在这种情况下,仅可以与通过 addTrack
()
方法创建的未关联传输器关联。
但是,通过 addTransceiver
()
方法创建的未关联传输器将不会关联,即使远程报价中存在可用的媒体描述。
相反,如果没有足够的addTrack
()
-创建的传输器,将创建新传输器并与媒体描述相关联。
这将使通过 addTrack
()
-创建和
addTransceiver
()
-创建的传输器在某种关键方式上分开,这从检查它们的属性是不可观察的。
创建答案时,仅在报价中存在的媒体描述才能列入答案。因此,当设置远程报价时未关联的任何传输器在设置本地答案后将保持未关联。可以通过答案者创建后续报价来解决此问题,发起另一个报价/答案交换,或者在使用 addTrack
()
-创建的传输器时,确保在初始交换中提供足够的媒体描述。
RTP 媒体 API 扩展了 RTCPeerConnection
接口,如下所述。
WebIDL partial interface RTCPeerConnection
{
sequence<RTCRtpSender
> getSenders
();
sequence<RTCRtpReceiver
> getReceivers
();
sequence<RTCRtpTransceiver
> getTransceivers
();
RTCRtpSender
addTrack
(MediaStreamTrack track, MediaStream... streams);
undefined removeTrack
(RTCRtpSender
sender);
RTCRtpTransceiver
addTransceiver
((MediaStreamTrack or DOMString) trackOrKind,
optional RTCRtpTransceiverInit
init = {});
attribute EventHandler ontrack
;
};
ontrack
的类型为 事件处理程序
此事件处理程序的事件类型为 track
。
getSenders
返回一个 RTCRtpSender
对象的序列,表示属于非停止状态的
RTCRtpTransceiver
对象,这些对象当前附加到此
RTCPeerConnection
对象。
当调用 getSenders
方法时,用户代理
必须返回执行 CollectSenders
算法的结果。
我们将 CollectSenders 算法定义如下:
CollectTransceivers
算法的结果。
[[Stopped]]
为
false
,则将
transceiver.[[Sender]]
添加到
senders。
getReceivers
返回一个 RTCRtpReceiver
对象的序列,表示属于非停止状态的
RTCRtpTransceiver
对象,这些对象当前附加到此
RTCPeerConnection
对象。
当调用 getReceivers
方法时,用户代理
必须执行以下步骤:
CollectTransceivers
算法的结果。
[[Stopped]]
为
false
,则将
transceiver.[[Receiver]]
添加到
receivers。
getTransceivers
返回一个 RTCRtpTransceiver
对象的序列,表示当前附加
到此 RTCPeerConnection
对象的 RTP
转发器。
getTransceivers
方法 必须 返回执行
CollectTransceivers
算法的结果。
我们将 CollectTransceivers 算法定义为 如下:
RTCRtpTransceiver
对象组成,这些对象
在此 RTCPeerConnection
对象的 转发器集合 中,按插入顺序。
addTrack
向 RTCPeerConnection
添加新轨道,并指明
它包含在指定的 MediaStream
中。
当调用 addTrack
方法时,用户代理
必须 执行以下步骤:
让 connection 成为此方法被调用的 RTCPeerConnection
对象。
让 track 成为方法第一个参数指示的 MediaStreamTrack
对象。
让 kind 为 track.kind。
让 streams 成为从方法其余参数构造的 MediaStream
对象的列表,或者如果方法只用一个参数调用,则为空列表。
如果 connection.[[IsClosed]]
为
true
,抛出 InvalidStateError
。
让 senders 成为执行 CollectSenders
算法的结果。
如果 track 的 RTCRtpSender
已经存在于
senders 中,则 抛出 InvalidAccessError
。
以下步骤描述如何确定是否可以重用现有的发送器。这样做将导致将来对
createOffer
和
createAnswer
的对应 媒体描述 标记为
sendrecv
或 sendonly
并添加发送者流的
MSID,如
[RFC9429]
(第 5.2.2
节 和 第
5.3.2 节)。
如果 senders 中的任何 RTCRtpSender
对象匹配所有以下标准,则让
sender 为该对象,否则为 null
:
发送器的轨道为 null。
与发送者关联的 传输器类型 的
RTCRtpTransceiver
,
与 kind 匹配。
发送者关联的 [[Stopping]]
插槽
的 RTCRtpTransceiver
的值为 false
。
发送器从未用于发送。更准确地说,[[CurrentDirection]]
槽与发送器关联的 RTCRtpTransceiver
从未具有
值为
"sendrecv
"
或
"sendonly
"。
如果 sender 不是 null
,则执行以下步骤以使用该发送器:
将 sender.[[SenderTrack]]
设置为
track。
将 sender.[[AssociatedMediaStreamIds]]
设置为空集合。
对于 streams 中的每个 stream,如果不在其中,则将
stream.id 添加到
[[AssociatedMediaStreamIds]]
。
让 transceiver 成为与 sender 关联的
RTCRtpTransceiver
。
如果 transceiver.[[Direction]]
为
"recvonly
",
将 transceiver.[[Direction]]
设置为
"sendrecv
"。
如果 transceiver.[[Direction]]
为
"inactive
",
将 transceiver.[[Direction]]
设置为
"sendonly
"。
如果 sender 为 null
,则执行以下步骤:
创建一个 RTCRtpSender ,使用 track、kind 和 streams,并让 sender 为结果。
创建一个 RTCRtpReceiver,使用 kind,并让 receiver 为结果。
创建一个
RTCRtpTransceiver,使用 sender、receiver 和
RTCRtpTransceiverDirection
值为
"sendrecv
",
并让 transceiver 为结果。
将 transceiver 添加到 connection 的 转发器集合。
一条轨道可能包含应用程序无法访问的内容。这可能是由于任何会使轨道 CORS
跨域。这些轨道可以提供给 addTrack
()
方法,并为它们创建一个 RTCRtpSender
,但内容 不得
被传输。发送静音(音频)、黑帧(视频)或等效的缺失内容代替轨道内容。
请注意,这种属性可能会随时间变化。
返回 sender。
removeTrack
停止从 sender 发送媒体。RTCRtpSender
仍然会出现在 getSenders
中。
这样做会导致未来对 createOffer
的调用将相应的传输器的 媒体描述 标记为
"recvonly
" 或
"inactive
",如
[RFC9429]
(section
5.2.2.) 中定义的。
当另一方以这种方式停止发送轨道时,该轨道将从最初在 track
事件中揭示的任何远程 MediaStream
中移除,如果 MediaStreamTrack
尚未被静音,
则在该轨道上会触发 mute
事件。
removeTrack
()
具有相同效果,可以通过设置对应转发器的
RTCRtpTransceiver
.direction
属性,并调用 RTCRtpSender
.replaceTrack
(null)
来实现。
一个小的不同之处在于 replaceTrack
()
是异步的,而 removeTrack
()
是同步的。
当调用 removeTrack
方法时,
用户代理 必须 执行以下步骤:
让 sender 为传递给 removeTrack
的参数。
让 connection 为调用该方法的 RTCPeerConnection
对象。
如果 connection.[[IsClosed]]
为
true
,则 抛出 一个
InvalidStateError
。
如果 sender 不是由
connection 创建的,则 抛出 一个
InvalidAccessError
。
让 transceiver 为与 sender 对应的 RTCRtpTransceiver
对象。
如果 transceiver.[[Stopping]]
为
true
,则中止这些步骤。
让
让 senders 为执行
CollectSenders
算法的结果。
如果 sender 不在 senders 中(这
表明其转接器由于
设置会话描述 被停止或移除
type
为"rollback
"), 则
中止这些步骤。
如果 sender.[[SenderTrack]]
为 null,
则中止这些步骤。
将 sender.[[SenderTrack]]
设置为 null。
让 transceiver 为与 sender 对应的
对象。
RTCRtpTransceiver
如果 transceiver.[[Direction]]
为
"sendrecv
",
将 transceiver.[[Direction]]
设置为
"recvonly
"。
如果 transceiver.[[Direction]]
为
"sendonly
",
将 transceiver.[[Direction]]
设置为
"inactive
"。
更新 negotiation-needed 标志 对于 connection。
addTransceiver
创建一个新的 RTCRtpTransceiver
并将其添加
到 转发器集合 中。
添加转发器将导致未来对 createOffer
的调用添加
对应转发器的 媒体描述,如 [RFC9429]
(第 5.2.2
节) 中定义的。
mid
的初始值为 null。
设置会话描述 可能会将其更改为非 null 值。
sendEncodings
参数可用于指定提供的模拟播编码的数量,并可选择性地指定其 RIDs 和编码参数。
当调用此方法时,用户代理 必须 执行以下步骤:
让 init 为第二个参数。
让 streams 为
init.streams
。
让 sendEncodings 为
init.sendEncodings
。
让 direction 为
init.direction
。
如果第一个参数是字符串,令 kind 为第一个参数并运行以下步骤:
如果第一个参数是 MediaStreamTrack
,令
track 为第一个参数,并令 kind 为
track.kind
。
如果 connection.[[IsClosed]]
是
true
,抛出 一个
InvalidStateError
。
通过运行以下 addTransceiver sendEncodings
验证步骤 来验证 sendEncodings,
其中每个 RTCRtpEncodingParameters
字典都是“编码”:
验证 sendEncodings 中的每个 rid
值是否符合 [RFC8851]
第 10 节中的语法要求。如果有一个 rid 不满足这些要求,抛出 TypeError
。
TypeError
:
如果任何编码包含一个非 rid
的只读参数,抛出 InvalidAccessError
。
如果任何编码包含一个 codec
成员,其值未
与
RTCRtpSender
.
getCapabilities
(kind)
.codecs
中的任何编解码器匹配,
抛出 OperationError
。
如果用户代理不支持在没有协商的情况下更改编解码器,或者不支持为单个编码设置编解码器,则返回一个带有 rejected 状态的新
创建的 OperationError
的
promise。
如果 kind 是 "audio"
,则从包含 scaleResolutionDownBy
和 maxFramerate
的编码中移除这些成员。
如果任何编码包含 scaleResolutionDownBy
成员且其值小于 1.0
,则抛出 RangeError。
验证 sendEncodings 中每个定义的 maxFramerate
成员的值是否大于 0.0。如果其中一个 maxFramerate
值不满足此要求,抛出一个 RangeError
。
创建一个 RTCRtpSender,使用 track、kind、streams 和 sendEncodings,令 sender 为结果。
如果设置了 sendEncodings,则后续调用
createOffer
将被配置为根据 [RFC9429]
(第 5.2.2
节 和 第
5.2.1 节) 发送多个 RTP 编码。
当调用 setRemoteDescription
,且对应的远程描述能够接收多个 RTP 编码时,如 [RFC9429]
(第 3.7
节) 定义,
RTCRtpSender
可能会发送多个 RTP
编码,且通过转发器的
sender
.getParameters
()
将反映协商的编码。
创建一个 RTCRtpReceiver ,使用 kind,令 receiver 为结果。
创建一个 RTCRtpTransceiver,使用 sender、receiver 和 direction,令 transceiver 为结果。
将 transceiver 添加到 connection 的 转发器集合 中。
返回 transceiver。
WebIDLdictionary RTCRtpTransceiverInit
{
RTCRtpTransceiverDirection
direction
= "sendrecv";
sequence<MediaStream> streams
= [];
sequence<RTCRtpEncodingParameters
> sendEncodings
= [];
};
direction
类型为 RTCRtpTransceiverDirection
,
默认为 "sendrecv
"
RTCRtpTransceiver
的方向。
streams
类型为 sequence<MediaStream
>
当远程 RTCPeerConnection
的轨道事件触发时
对应于 RTCRtpReceiver
被添加,这些
是将被放入事件中的流。
sendEncodings
类型为 sequence<RTCRtpEncodingParameters
>
一个包含媒体发送 RTP 编码的参数的序列。
WebIDLenum RTCRtpTransceiverDirection
{
"sendrecv
",
"sendonly
",
"recvonly
",
"inactive
",
"stopped
"
};
枚举值 | 描述 |
---|---|
sendrecv
|
RTCRtpTransceiver 的
RTCRtpSender
sender 将提供发送 RTP 的能力,如果远程对等方接受并且
sender.getParameters () .encodings [i].active
是 true 对于任何值的 i。该
RTCRtpTransceiver 的 RTCRtpReceiver 将提供接收 RTP 的能力,
并且如果远程对等方接受,将接收 RTP。
|
sendonly
|
RTCRtpTransceiver 的 RTCRtpSender
sender 将提供发送 RTP 的能力,如果远程对等方接受并且
sender.getParameters () .encodings [i].active
是 true 对于任何值的 i。该
RTCRtpTransceiver 的 RTCRtpReceiver 将不提供接收 RTP 的能力,
并且不会接收 RTP。
|
recvonly
|
RTCRtpTransceiver 的 RTCRtpSender 将不提供发送 RTP 的能力,
并且不会发送 RTP。该
RTCRtpTransceiver 的 RTCRtpReceiver 将提供接收 RTP 的能力,
并且如果远程对等方接受,将接收 RTP。
|
inactive
|
RTCRtpTransceiver 的 RTCRtpSender 将不提供发送 RTP 的能力,
并且不会发送 RTP。该
RTCRtpTransceiver 的 RTCRtpReceiver 将不提供接收 RTP 的能力,
并且不会接收 RTP。
|
stopped
|
RTCRtpTransceiver 将
既不发送也不接收 RTP。
它将在报价中生成零端口。在回答中,其
RTCRtpSender 将不提供发送 RTP 的能力,
而其
RTCRtpReceiver 将不提供接收 RTP 的能力。
这是一个
终止状态。
|
应用程序可以通过将传输器的方向设置为
"inactive
" 暂时关闭
两个方向,或者设置为
"sendonly
" 仅拒绝
传入的一方。要以一种使 m-line 可供重用的方式永久拒绝 m-line,应用程序需要调用
RTCRtpTransceiver
.stop
()
,然后从其端发起协商。
要处理远程轨道
,给定一个 RTCRtpTransceiver
transceiver、
direction、msids、addList、
removeList 和 trackEventInits,运行以下步骤:
设置与远程流关联的内容 使用
transceiver.[[Receiver]]
、msids、
addList 和 removeList。
如果 direction 是
"sendrecv
" 或
"recvonly
" 并且
transceiver.[[FiredDirection]]
既不是
"sendrecv
" 也不是
"recvonly
",或者
上一步增加了 addList 的长度,处理远程轨道的添加 使用
transceiver
和 trackEventInits。
如果 direction 是
"sendonly
" 或
"inactive
",将
transceiver.[[Receptive]]
设置为
false
。
如果 direction 是
"sendonly
" 或
"inactive
",并且
transceiver.[[FiredDirection]]
是
"sendrecv
" 或
"recvonly
",处理远程轨道的移除 对于 媒体描述,
使用 transceiver 和 muteTracks。
将 transceiver.[[FiredDirection]]
设置为
direction。
要处理远程轨道的添加,给定一个 RTCRtpTransceiver
transceiver 和 trackEventInits,运行以下步骤:
让 receiver 为
transceiver.[[Receiver]]
。
让 track 为
receiver.[[ReceiverTrack]]
。
让 streams 为
receiver.[[AssociatedRemoteMediaStreams]]
。
创建一个新的 RTCTrackEventInit
字典,其中包含
receiver、track、streams 和
transceiver 作为成员,并将其添加到
trackEventInits 中。
要处理远程轨道的移除,使用一个 RTCRtpTransceiver
transceiver 和 muteTracks,运行以下步骤:
让 receiver 为
transceiver.[[Receiver]]
。
让 track 为
receiver.[[ReceiverTrack]]
。
如果 track.muted 为 false
,将
track 添加到 muteTracks 中。
要设置关联的远程流,给定 RTCRtpReceiver
receiver、
msids、addList 和 removeList,
运行以下步骤:
让 connection 为与 receiver 关联的 RTCPeerConnection
对象。
对于 msids 中的每个 MSID,除非已为该 connection 创建了一个具有该 id
的 MediaStream
对象,否则创建一个
MediaStream
对象,使用该 id
。
让 streams 为为该 connection 创建的与 msids 对应的 id
的 MediaStream
对象列表。
让 track 为
receiver.[[ReceiverTrack]]
。
对于 receiver.[[AssociatedRemoteMediaStreams]]
中的每个 stream,如果它不在 streams 中,则将 stream 和
track 作为一对添加到 removeList 中。
对于 streams 中的每个 stream,如果它不在
receiver.[[AssociatedRemoteMediaStreams]]
中,
将 stream 和 track 作为一对添加到 addList 中。
将
receiver.[[AssociatedRemoteMediaStreams]]
设置为
streams。
RTCRtpSender
接口允许
应用程序控制如何将给定的 MediaStreamTrack
编码并传输到远程
对等方。当在一个
RTCRtpSender
对象上调用
setParameters
时,
编码会相应更改。
要 创建一个 RTCRtpSender,使用一个 MediaStreamTrack
,
track,一个字符串 kind,一个
MediaStream
对象列表 streams,以及可选的
RTCRtpEncodingParameters
对象列表
sendEncodings,执行以下步骤:
让 sender 成为一个新的 RTCRtpSender
对象。
让 sender 拥有一个 [[SenderTrack]] 内部槽,初始化为 track。
让 sender 拥有一个 [[SenderTransport]]
内部槽,初始化为 null
。
让 sender 拥有一个
[[LastStableStateSenderTransport]] 内部槽
初始化为 null
。
让 sender 拥有一个 [[Dtmf]]
内部槽
初始化为 null
。
如果 kind 是 "audio"
,那么 创建一个
RTCDTMFSender dtmf,并将 [[Dtmf]]
内部槽设置为 dtmf。
让 sender 拥有一个
[[AssociatedMediaStreamIds]] 内部槽,
代表此发送器要关联的 MediaStream
对象的 ID 列表。该
[[AssociatedMediaStreamIds]]
槽在 SDP 中使用,如
[RFC9429] (第 5.2.1 节)。
将 sender.[[AssociatedMediaStreamIds]]
设置为
一个空集。
对于 streams 中的每个 stream,如果
stream.id 不在 [[AssociatedMediaStreamIds]]
中,添加
stream.id。
让 sender 拥有一个 [[SendEncodings]]
内部槽,代表一系列
RTCRtpEncodingParameters
字典。
如果 sendEncodings 作为输入给此算法,
且非空,则将 [[SendEncodings]]
槽设置为
sendEncodings。否则,将其设置为一个包含
一个新的RTCRtpEncodingParameters
,其
字典, active
设置
如果
kind 是 "video"
,则添加一个
scaleResolutionDownBy
成员,值为 1.0
到 该字典。
true
RTCRtpEncodingParameters
字典包含
active
成员
其值默认为
true
。
让 sender 拥有一个
[[LastStableRidlessSendEncodings]] 内部槽
初始化为 null
。
让 sender 拥有一个 [[SendCodecs]] 内部槽,代表一系列 RTCRtpCodecParameters
字典,并初始化为空列表。
让 sender 拥有一个
[[LastReturnedParameters]] 内部槽,用于匹配 getParameters
和
setParameters
事务。
返回 sender。
WebIDL[Exposed=Window]
interface RTCRtpSender
{
readonly attribute MediaStreamTrack? track
;
readonly attribute RTCDtlsTransport
? transport
;
static RTCRtpCapabilities
? getCapabilities
(DOMString kind);
Promise<undefined> setParameters
(RTCRtpSendParameters
parameters,
optional RTCSetParameterOptions
setParameterOptions = {});
RTCRtpSendParameters
getParameters
();
Promise<undefined> replaceTrack
(MediaStreamTrack? withTrack);
undefined setStreams
(MediaStream... streams);
Promise<RTCStatsReport
> getStats
();
};
track
类型为 MediaStreamTrack
,只读,
可为 null
track
属性是与此
RTCRtpSender
对象关联的轨道。如果 track
已结束,或如果
轨道的输出被禁用,即轨道被禁用和/或静音,则 RTCRtpSender
必须 发送黑帧
(视频),并且 不得 发送(音频)。在视频的情况下,RTCRtpSender
应 每秒发送一帧黑色。如果 track
为
null
,则 RTCRtpSender
不发送。在获取时,
该属性 必须 返回
[[SenderTrack]]
槽的值。
transport
类型为 RTCDtlsTransport
,
只读,可为 null
transport
属性是
媒体从 track
发送的 RTP 数据包的
传输。在构造 RTCDtlsTransport
对象之前,
transport
属性将为
null。当使用捆绑时,
多个 RTCRtpSender
对象将共享一个
transport
,并将通过同一
传输发送 RTP 和 RTCP。
在获取时,该属性 必须 返回
[[SenderTransport]]
槽的值。
getCapabilities
,静态
静态 RTCRtpSender
.getCapabilities
()
方法提供了一种发现用户代理支持的发送给定类型媒体的能力的方法,而不保留任何资源、端口或其他状态。
当调用 getCapabilities
方法时,用户代理 必须 执行以下步骤:
让 kind 为方法的第一个参数。
如果 kind 既不是 "video"
也不是 "audio"
,则返回
null
。
返回一个新的 RTCRtpCapabilities
字典,其
codecs
成员
初始化为
已实现发送编解码器的列表,并且
headerExtensions
成员初始化为
发送的已实现头扩展的列表,与
kind 相关。
给定 kind 的 已实现发送编解码器的列表 是一个 实现定义的 列表,包含 RTCRtpCodec
字典,代表用户代理支持发送给定 kind(视频或音频)的编解码器的最乐观视图。
给定 kind 的 发送的已实现头扩展的列表 是一个 实现定义的 列表,包含
RTCRtpHeaderExtensionCapability
字典,代表用户代理支持发送给定 kind(视频或音频)媒体的头扩展的最乐观视图。
这些能力提供了一般持久的跨域信息,增加了 应用程序的指纹识别表面。在 隐私敏感的上下文中,用户代理 可能 考虑采用 缓解措施,例如仅报告一组常见的能力。
返回的编解码器能力会影响
setCodecPreferences
()
算法和
它抛出的输入 InvalidModificationError
,并且还应与
createOffer
()
和 createAnswer
()
关于协商发送的编解码器保持一致,以确保任何隐私缓解措施有效。
setParameters
setParameters
方法
更新 track
的编码
和传输方式到远程对等方。
当调用 setParameters
方法时,用户代理
必须 执行以下步骤:
RTCRtpSender
对象,
在其上调用 setParameters
。
RTCRtpTransceiver
对象
(即 sender 是
transceiver.[[Sender]]
)。
true
,返回一个承诺 被拒绝
,并带有一个新创建的 InvalidStateError
。
[[LastReturnedParameters]]
为
null
,返回一个承诺 被拒绝
,并带有一个新创建的 InvalidStateError
。
encodings
。
codecs
。
让 choosableCodecs 为 codecs。
如果 choosableCodecs 是空列表,将
choosableCodecs
设置为 transceiver.[[PreferredCodecs]]
。
如果 choosableCodecs 仍然是空列表,将 choosableCodecs 设置为 已实现的发送编解码器列表 用于 transceiver 的类型。
RTCRtpEncodingParameters
存储在
sender.[[SendEncodings]]
的数量。
InvalidModificationError
:
encodings.length
与 N 不同。
[[LastReturnedParameters]]
中对应的参数值不同。
注意,这也适用于 transactionId。
如果 transceiver 的类型 为
"audio"
,从所有 encodings 中移除
scaleResolutionDownBy
和
maxFramerate
成员。
如果 transceiver 的类型 为
"video"
,则对于每个在 encodings 中的编码,如果不
包含 scaleResolutionDownBy
成员,则添加一个 scaleResolutionDownBy
成员,值为 1.0
。
验证每个 如果 transceiver 的类型 为
"video"
,
且任何 编码在 encodings
包含 有
一个 一个
scaleResolutionDownBy
成员,其值为 大于小于
或等于 1.0。如果其中一个
值不满足该要求scaleResolutionDownBy
1.0
,返回一个承诺 被拒绝,并带有一个新创建的 RangeError
。
验证 encodings 中的每个编码都有
maxFramerate
成员,其值大于或等于 0.0。如果其中一个
maxFramerate
值不满足该要求,返回一个承诺 被拒绝,并带有一个新创建的
RangeError
。
如果用户代理不支持为任何编码设置编解码器或混合不同编码值于不同的编码中,返回一个承诺
被拒绝
,并带有一个新创建的 OperationError
。
[[SenderTrack]]
。
[[LastReturnedParameters]]
设置为 null
。
[[SendEncodings]]
设置为
parameters.encodings
。
undefined
。
RTCError
,其
errorDetail
被设置为
"hardware-encoder-not-available
"
并中止这些步骤。
RTCError
,其
errorDetail
被设置为
"hardware-encoder-error
"
并且中止这些步骤。
OperationError
。
setParameters
不会
导致 SDP 重新协商,并且只能用于更改媒体堆栈在
Offer/Answer 协商的封装内发送或接收的内容。RTCRtpSendParameters
字典中的属性
旨在不启用此功能,因此像
cname
这样的属性
不能被更改。
其他事项,如比特率,通过限制来控制,例如
maxBitrate
,
用户代理需要确保不超过
maxBitrate
中指定的最大比特率,
同时确保满足其他地方(如 SDP)中指定的比特率限制。
getParameters
getParameters
()
方法返回 RTCRtpSender
对象当前的参数,表示 track
的编码和
传输到远程 RTCRtpReceiver
的方式。
当调用 getParameters
时,
用户代理 必须 执行以下步骤:
让 sender 为调用此 getter 的 RTCRtpSender
对象。
如果 sender.[[LastReturnedParameters]]
不是 null
,返回
sender.[[LastReturnedParameters]]
,
并中止这些步骤。
让 result 为一个新的 RTCRtpSendParameters
字典,构造如下:
transactionId
被设置为一个新的唯一标识符。
encodings
被设置为
sender.[[SendEncodings]]
内部槽的值。
headerExtensions
序列根据已经协商的用于发送的头部扩展进行填充。
codecs
被
设置为
sender.[[SendCodecs]]
内部
槽的值。
rtcp
.cname
被
设置为关联的 RTCPeerConnection
的
CNAME。
rtcp
.reducedSize
被设置为 true
如果已协商发送减少大小的 RTCP,否则为 false
。
将 sender.[[LastReturnedParameters]]
设置为 result。
排队一个任务,将
sender.[[LastReturnedParameters]]
设置为
null
。
返回 result。
getParameters
可与 setParameters
一起使用,以如下方式更改参数:
async function updateParameters() {
try {
const params = sender.getParameters();
// ... 修改参数
params.encodings[0].active = false;
await sender.setParameters(params);
} catch (err) {
console.error(err);
}
}
在对 setParameters
的调用完成后,
后续对 getParameters
的调用
将返回修改后的参数集。
replaceTrack
尝试用提供的另一个轨道(或 null
轨道)替换 RTCRtpSender
当前的 track
,而无需重新协商。
当调用 replaceTrack
方法时,
用户代理 必须 执行以下步骤:
让 sender 为调用 RTCRtpSender
的 replaceTrack
对象。
让 transceiver 为与 sender 关联的 RTCRtpTransceiver
对象。
让 connection 为与 sender 关联的 RTCPeerConnection
对象。
让 withTrack 为此方法的参数。
如果 withTrack 不是 null 并且
withTrack.kind
与 transceiver 的 传输者种类 不同,
则返回一个 拒绝 的 promise,
并创建一个新的 TypeError
。
返回将以下步骤链式调用 到connection的操作链的结果:
如果 transceiver.[[停止正在停止]] 为
true
,则返回一个 promise 拒绝,
并创建一个新的 异常
InvalidStateError
。
让 p 为一个新的 promise。
让 sending 为 true
如果
transceiver.[[CurrentDirection]]
为 "sendrecv
"
或
"sendonly
"
,否则为 false
。
以 并行方式 执行以下步骤:
如果 sending 为 true
,并且
withTrack 为 null
,让发送者停止发送。
如果 sending 为 true
,并且
withTrack 不是 null
,
确定发送者是否可以立即发送 withTrack,
而不违反发送者已协商的封装,如果不能,则 拒绝 p,
并创建一个新的 异常
InvalidModificationError
,
并中止这些步骤。
如果 sending 为 true
,并且
withTrack 不是 null
,
让发送者无缝切换到发送 withTrack,
而不是发送者的现有轨道。
排队一个任务,执行以下步骤:
如果 connection.[[IsClosed]]
为 true
,则中止这些步骤。
将 sender.[[SenderTrack]]
设置为 withTrack。
解析 p
为
undefined
。
返回 p。
更改维度和/或帧速率可能不需要重新协商。可能需要重新协商的情况包括:
setStreams
设置与该发送者的轨道关联的 MediaStream
。
当调用 setStreams
方法时,
用户代理 必须 执行以下步骤:
让 sender 为调用此方法的 RTCRtpSender
对象。
让 connection 为调用此方法的 RTCPeerConnection
对象。
如果 connection.[[IsClosed]]
为
true
,则 抛出 一个
InvalidStateError
。
让 streams 为从方法参数构造的 MediaStream
对象列表,如果方法未提供参数,则为空列表。
将
sender.[[AssociatedMediaStreamIds]]
设置为空集。
对于 streams 中的每个 stream,将
stream.id 添加到
[[AssociatedMediaStreamIds]]
中,前提是它尚不存在。
更新 协商所需标志 对于 connection。
getStats
收集此发送者的统计信息,并异步报告结果。
当调用 getStats
()
方法时,用户代理
必须 执行以下步骤:
让 selector 为调用该方法的 RTCRtpSender
对象。
让 p 为一个新的 promise,并并行运行以下步骤:
根据 selector 收集统计信息,遵循 统计选择算法。
解析
p 为结果
RTCStatsReport
对象,包含收集到的统计信息。
返回 p。
WebIDLdictionary RTCRtpParameters
{
required sequence<RTCRtpHeaderExtensionParameters
> headerExtensions
;
required RTCRtcpParameters
rtcp
;
required sequence<RTCRtpCodecParameters
> codecs
;
};
RTCRtpParameters
成员
headerExtensions
类型为 sequence<RTCRtpHeaderExtensionParameters
>,
必需
一个包含 RTP 头扩展参数的序列。 只读参数。
rtcp
类型为 RTCRtcpParameters
,
必需
用于 RTCP 的参数。 只读参数。
codecs
类型为 sequence<RTCRtpCodecParameters
>,
必需
一个包含 RTCRtpSender
将选择的媒体编码器的序列,
以及 RTX、RED 和 FEC 机制的条目。与启用通过 RTX 进行重传的每个媒体编解码器对应,
在 codecs
中将有一个条目,
其中的 mimeType
属性指示
通过 audio/rtx
或
video/rtx
进行重传,并且有一个
sdpFmtpLine
属性(提供 "apt" 和 "rtx-time" 参数)。 只读参数。
WebIDLdictionary RTCRtpSendParameters
: RTCRtpParameters
{
required DOMString transactionId
;
required sequence<RTCRtpEncodingParameters
> encodings
;
};
RTCRtpSendParameters
成员
transactionId
类型为 DOMString,必需
应用的最后一组参数的唯一标识符。
确保 setParameters
只能在之前调用 getParameters
的基础上进行,
并且没有干扰性更改。 只读参数。
encodings
类型为 sequence<RTCRtpEncodingParameters
>,
必需
一个包含媒体的 RTP 编码参数的序列。
WebIDLdictionary RTCRtpReceiveParameters
: RTCRtpParameters
{
};
WebIDLdictionary RTCRtpCodingParameters
{
DOMString rid
;
};
RTCRtpCodingParameters
成员
rid
类型为 DOMString
如果设置,则此 RTP 编码将通过 RID 标头扩展发送,具体定义见 [RFC9429]
(第 5.2.1
节)。
RID 不能通过 setParameters
修改。它只能在发送端通过 addTransceiver
进行设置或修改。只读参数。
dictionary RTCRtpEncodingParameters : RTCRtpCodingParameters { boolean active = true; RTCRtpCodec codec; unsigned long maxBitrate; double maxFramerate; double scaleResolutionDownBy; };
RTCRtpEncodingParameters
成员
active
类型为 boolean,默认为
true
表示该编码正在积极发送。将其设置为 false
将导致此编码不再被发送。
将其设置为 true
将导致该编码被发送。由于将值设置为
false
不会导致 SSRC 被移除,因此不会发送 RTCP BYE。
codec
类型为 RTCRtpCodec
可选值,选择用于此编码的 RTP 流的编解码器。如果缺失,用户代理可以选择使用任何协商的编解码器。
maxBitrate
类型为 unsigned long
当存在时,指示用于发送此编码的最大比特率。用户代理可以自由分配编码之间的带宽,只要不超过
maxBitrate
的值。编码还可能受到其他限制(例如每传输或每会话的带宽限制)的进一步约束,这些限制低于此处指定的最大值。
maxBitrate
的计算方式与[RFC3890]
第 6.2.2 节中定义的传输独立应用程序特定最大带宽 (TIAS) 相同,即不计算 IP 或其他传输层(如 TCP 或 UDP)所需的最大带宽。
maxBitrate
的单位是每秒比特数。
比特率的实现方式依赖于媒体和编码。对于视频,帧将始终以最快的速度发送,但帧可能会被丢弃,直到比特率降到足够低。因此,即使比特率为零,也将允许发送一帧。对于音频,可能需要停止播放,如果比特率不足以为所选择的编码提供足够的带宽。
maxFramerate
类型为 double
此成员仅在发送者的 kind
为
"video"
时存在。
当存在时,指示可以用于发送此编码的最大帧率,以每秒帧数表示。用户代理
可以自由分配编码之间的带宽,只要不超过
user
agent 的
maxFramerate
的值。
如果通过 setParameters
()
修改,
新的帧率在当前画面完成后生效;因此将最大帧率设置为零将导致视频在下一个
帧上冻结。
scaleResolutionDownBy
类型为
double
此成员仅在发送端的 kind
为
"video"
时出现。视频将在发送之前在每个维度上按给定值缩小分辨率。例如,如果值为
2.0,则视频将按 2 的因子缩小,导致发送的图像为四分之一大小。如果值为 1.0,则视频不会受到影响。值必须大于或等于
1.0。默认情况下,缩放按因子二的相反顺序应用,以产生从较小到较高分辨率的顺序,例如 4:2:1。如果只有一个层,发送端默认不会应用任何缩放(即
scaleResolutionDownBy
将为 1.0)。
WebIDLdictionary RTCRtcpParameters
{
DOMString cname
;
boolean reducedSize
;
};
RTCRtcpParameters
成员
WebIDLdictionary RTCRtpHeaderExtensionParameters
{
required DOMString uri
;
required unsigned short id
;
boolean encrypted
= false;
};
RTCRtpHeaderExtensionParameters
字典使应用程序能够确定头扩展是否已配置
以便在 RTCRtpSender
或 RTCRtpReceiver
中使用。对于一个
RTCRtpTransceiver
transceiver,应用程序可以
确定头扩展的“方向”参数(在 [RFC5285]
第 5 节中定义)如下,无需解析 SDP:
sender
.getParameters
()
.headerExtensions
。
receiver
.getParameters
()
.headerExtensions
。
sender
.getParameters
()
.headerExtensions
和
transceiver.receiver
.getParameters
()
.headerExtensions
。
sender
.getParameters
()
.headerExtensions
也不包含在
transceiver.receiver
.getParameters
()
.headerExtensions
。
WebIDLdictionary RTCRtpCodec
{
required DOMString mimeType
;
required unsigned long clockRate
;
unsigned short channels
;
DOMString sdpFmtpLine
;
};
RTCRtpCodec
成员
RTCRtpCodec
字典提供
有关编解码器对象的信息。
mimeType
类型为 DOMString,必需
编解码器的 MIME 媒体类型/子类型。有效的媒体类型和 子类型列在 [IANA-RTP-2] 中。
clockRate
类型为 unsigned long,必需
编解码器的时钟频率,以赫兹为单位。
channels
类型为 unsigned short
如果存在,表示最大频道数 (单声道=1,立体声=2)。
sdpFmtpLine
类型为 DOMString
SDP 中与编解码器对应的 "格式特定参数" 字段
的 a=fmtp
行,如果存在,按照
[RFC9429]
(第 5.8
节) 所定义。
RTCRtpCodecParameters
字典
dictionary RTCRtpCodecParameters { required octet payloadType; required DOMString mimeType; required unsigned long clockRate; unsigned short channels; DOMString sdpFmtpLine; };
RTCRtpCodecParameters
成员
payloadType
类型为 octet,必需
用于识别此编解码器的 RTP 有效负载类型。 只读参数。
mimeType
类型为 DOMString,必需
编解码器的 MIME 媒体类型/子类型。有效的媒体类型和 子类型列在 [IANA-RTP-2] 中。 只读 参数。
clockRate
类型为 unsigned long,必需
编解码器的时钟频率,以赫兹为单位。 只读 参数。
channels
类型为 unsigned short
如果存在,指示通道数(单声道=1, 立体声=2)。 只读 参数。
sdpFmtpLine
类型为 DOMString
编码器对应的 SDP 中的 “格式特定参数” 字段,来自于
a=fmtp
行,如果存在的话,定义如
[RFC8829]
(第 5.8
节)。对于
RTCRtpSender
,
这些参数来自于远端描述,对于 RTCRtpReceiver
,
这些参数来自于本地描述。只读参数。
dictionary RTCRtpCodecParameters : RTCRtpCodec { required octet payloadType; };
RTCRtpCodecParameters
成员
RTCRtpCodecParameters
字典提供有关已协商编解码器的信息。继承自
RTCRtpCodec
的字段 必须 全部为 只读参数。
对于一个 RTCRtpSender
,sdpFmtpLine
参数
来自
[[CurrentRemoteDescription]]
,
而对于一个
RTCRtpReceiver
,它们来自
本地描述(如果不为 null
,则来自
[[PendingLocalDescription]]
,否则来自
[[CurrentLocalDescription]]
)。
payloadType
类型为 octet,必需
用于识别此编解码器的 RTP 有效负载类型。 只读参数。
WebIDLdictionary RTCRtpCapabilities
{
required sequence<RTCRtpCodec
> codecs
;
required sequence<RTCRtpHeaderExtensionCapability
> headerExtensions
;
};
RTCRtpCapabilities
成员
codecs
类型为 sequence<RTCRtpCodec
>,
必需
支持的媒体编解码器以及 RTX、RED 和 FEC 机制的条目。 仅提供将利用 生成的 SDP 提供中的不同有效负载类型的组合。例如:
必须 仅在codecs
中有一个条目
用于通过 RTX 进行重传,并且sdpFmtpLine
不得
出现。
headerExtensions
类型为 sequence<RTCRtpHeaderExtensionCapability
>,
必需
支持的 RTP 头扩展。
dictionary RTCRtpHeaderExtensionCapability { required DOMString uri; };
uri
类型为 DOMString,必需
RTP 头扩展的 URI,如 [RFC5285] 中定义。
WebIDLdictionary RTCSetParameterOptions
{
};
RTCSetParameterOptions
成员RTCSetParameterOptions 被定义为空字典,以允许可扩展性。
RTCRtpReceiver
接口
允许应用程序检查接收的MediaStreamTrack
。
要用字符串 kind 创建一个 RTCRtpReceiver,请执行以下步骤:
让 receiver 成为一个新的 RTCRtpReceiver
对象。
让 track 成为一个新的 MediaStreamTrack
对象
[GETUSERMEDIA]. track 的源是
远程
源,由 receiver 提供。请注意
track.id
是
由用户代理生成的,并且与远程端的任何轨道
ID 无法映射。
将 track.kind 初始化为 kind。
将 track.label 初始化为将字符串 "remote "
与 kind 连接的结果。
将 track.readyState 初始化为 live
。
将 track.muted 初始化为 true
。请参阅
MediaStreamTrack
部分了解 muted
属性如何反映 MediaStreamTrack
是否接收媒体数据。
让 receiver 具有一个 [[ReceiverTrack]] 内部槽,初始化为 track。
让 receiver 具有一个 [[ReceiverTransport]]
内部槽,初始化为 null
。
让 receiver 具有一个
[[LastStableStateReceiverTransport]] 内部槽
初始化为 null
。
让 receiver 具有一个
[[AssociatedRemoteMediaStreams]] 内部槽,
表示与此接收器的 MediaStream
对象列表相关联,
初始化为空列表。
让 receiver 具有一个 [[LastStableStateAssociatedRemoteMediaStreams]] 内部槽,初始化为空列表。
让 receiver 具有一个 [[ReceiveCodecs]]
内部槽,表示 RTCRtpCodecParameters
字典的列表,初始化为空列表。
让 receiver 具有一个 [[LastStableStateReceiveCodecs]] 内部槽并 初始化为空列表。
让 receiver 具有一个 [[JitterBufferTarget]]
内部槽初始化为 null
。
返回 receiver。
[Exposed=Window] interface RTCRtpReceiver { readonly attribute MediaStreamTrack track; readonly attribute RTCDtlsTransport? transport; static RTCRtpCapabilities? getCapabilities(DOMString kind); RTCRtpReceiveParameters getParameters(); sequence<RTCRtpContributingSource> getContributingSources(); sequence<RTCRtpSynchronizationSource> getSynchronizationSources(); Promise<RTCStatsReport> getStats(); attribute DOMHighResTimeStamp? jitterBufferTarget; };
track
类型为
MediaStreamTrack
,只读
track
属性是与此
RTCRtpReceiver
对象 receiver 相关联的轨道。
请注意,track
.stop()
是最终的,
尽管克隆不会受到影响。由于
receiver.track
.stop()
不会隐式停止 receiver,接收器报告将继续发送。在获取时,属性 MUST
返回 [[ReceiverTrack]]
槽的值。
transport
类型为 RTCDtlsTransport
,
只读,nullable
transport
属性
是接收器的 track
的媒体通过 RTP 包接收的传输。
在构建
RTCDtlsTransport
对象之前,
transport
属性将
为 null
。 当使用捆绑时,多个
RTCRtpReceiver
对象将共享一个
transport
,并将通过同一传输接收
RTP 和 RTCP。
在获取时,属性 MUST 返回 [[ReceiverTransport]]
槽的值。
jitterBufferTarget
类型为 DOMHighResTimeStamp
,nullable
此属性允许应用程序指定 RTCRtpReceiver
的抖动缓冲区应保持的目标持续时间(以毫秒为单位)。这影响了 用户代理
的缓冲量,从而影响重传和丢包恢复。改变目标值允许应用程序控制播放延迟与因网络抖动而导致音频或视频帧耗尽的风险之间的权衡。
用户代理 必须 具有一个 最小允许目标 和一个 最大允许目标,反映 用户代理 根据网络条件和内存限制所能够或愿意提供的内容,这些条件可以随时变化。
这是一个目标值。所导致的延迟变化可以随着时间的推移逐渐观察到。接收器的平均抖动缓冲区延迟可以通过计算
jitterBufferDelay
与
jitterBufferEmittedCount
的增量来测量。
即使使用 DTX,也期望有一个平均延迟。例如,如果使用 DTX 且数据包在静默后开始流动,较大的目标可以影响 用户代理 缓冲这些数据包,而不是播放它们。
在获取时,此属性 必须 返回
[[JitterBufferTarget]]
内部插槽的值。
在设置时,用户代理 必须 执行以下步骤:
让 receiver 为调用设置器的
RTCRtpReceiver
对象。
让 target 为设置器的参数。
如果 target 为负值或大于 4000 毫秒,则
抛出 一个 RangeError
。
将 receiver 的 [[JitterBufferTarget]]
设置为 target。
让 track 为 receiver 的
[[ReceiverTrack]]
。
并行,开始执行以下步骤:
更新底层系统关于新的 target,或者如果 target
为
null
,则表示没有应用偏好。
如果 track 与另一
RTCRtpReceiver
的
轨道同步以实现
音频/视频
同步,
则 用户代理
应 使用两个接收器中较大的
[[JitterBufferTarget]]
进行设置。
当底层系统应用抖动缓冲目标时,它将 持续确保实际抖动缓冲目标限制在 最小允许目标 和 最大允许目标 之间。
如果 用户代理
最终使用的目标与请求的目标不同(例如,由于网络条件或物理内存限制),这不会反映在 [[JitterBufferTarget]]
内部槽中。
修改底层系统的抖动缓冲目标 应 逐渐影响内部音频或视频缓冲,以避免影响用户体验。音频样本或视频帧 应 在播放之前加速或减速,类似于音频/视频同步或响应拥塞控制。
加速或减速的速度可能会根据网络条件或接收到的音频类型(例如语音或背景噪声)而有所不同。它 可能 需要几秒钟才能达到 1 秒的缓冲,但 应 不超过 30 秒,假设数据包正在接收。速度 可能 在音频和视频之间不同。
对于音频,加速和减速可以通过 insertedSamplesForDeceleration
和 removedSamplesForAcceleration
来测量。对于视频,这可能导致同一帧被多次渲染,或者帧可能被丢弃。
getCapabilities
,静态
静态 RTCRtpReceiver
.getCapabilities
()
方法提供了一种发现用户代理支持接收特定类型媒体的能力的方法,而不保留任何资源、端口或其他状态。
当调用 getCapabilities
方法时,用户代理 MUST 执行以下步骤:
让 kind 成为方法的第一个参数。
如果 kind 既不是 "video"
也不是 "audio"
则返回 null
。
返回一个新的 RTCRtpCapabilities
字典,其
codecs
成员
初始化为
已实现接收编解码器的列表,并且
headerExtensions
成员初始化为
已实现的接收头扩展列表。
给定 kind 的 已实现的接收编解码器列表 是
实现定义的 RTCRtpCodec
字典的列表
代表用户代理支持接收特定 kind(视频或音频)媒体的最乐观的视图。
给定 kind 的 已实现的接收头扩展列表 是
实现定义的 RTCRtpHeaderExtensionCapability
字典的列表,代表用户代理支持接收特定 kind(视频或音频)媒体的乐观视图。
这些能力提供了通常持久的跨源设备信息,从而增加了应用程序的指纹识别表面。在 隐私敏感的上下文中,用户代理 MAY 考虑采取 仅报告常见的能力子集等缓解措施。
返回的编解码器能力会影响 setCodecPreferences
()
算法及其抛出 InvalidModificationError
的输入,并且还应与通过
createOffer
()
和 createAnswer
()
揭示的编解码器协商一致,以确保任何隐私缓解措施有效。
getParameters
getParameters
()
方法返回 RTCRtpReceiver
对象当前的解码参数,用于解码 track
。
当调用 getParameters
时,
RTCRtpReceiveParameters
字典按如下方式构造:
headerExtensions
序列填充为接收器当前准备接收的头扩展。
codecs
被设置为
[[ReceiveCodecs]]
内部
槽的值。
getParameters
返回所有编解码器。但如果远程端只用两个响应,缺失的编解码器将不再由 getParameters
返回,因为接收器不再需要准备接收它。
rtcp
.reducedSize
被设置为 true
如果接收器当前准备接收减少大小的 RTCP 数据包,否则为 false
。
rtcp
.cname
被省略。
getContributingSources
返回一个 RTCRtpContributingSource
对于在过去 10 秒内由该 RTCRtpReceiver
接收到的每个唯一 CSRC
标识符,按 timestamp
的降序排列。
getSynchronizationSources
返回一个 RTCRtpSynchronizationSource
对于每个唯一的
SSRC 标识符,由此 RTCRtpReceiver
在过去 10 秒内接收,
按照降序的 timestamp
顺序。
getStats
仅为此接收器收集统计信息,并异步报告结果。
当调用 getStats
()
方法时,用户代理
MUST 执行以下步骤:
让 selector 成为调用该方法的 RTCRtpReceiver
对象。
让 p 成为一个新承诺,并按以下步骤 并行 执行:
根据 selector 收集统计信息 按照 统计选择算法。
解析
p 与结果
RTCStatsReport
对象,包含收集到的统计信息。
返回 p。
RTCRtpContributingSource
和
RTCRtpSynchronizationSource
字典包含
有关来自给定贡献源 (CSRC) 或同步源 (SSRC) 的信息。当一个或多个 RTP 包中的音频或视频帧交付到
RTCRtpReceiver
的 MediaStreamTrack
时,用户代理 MUST 排队
一个任务以更新有关该包的
RTCRtpContributingSource
和 RTCRtpSynchronizationSource
字典的信息。与 SSRC 标识符对应的 RTCRtpSynchronizationSource
字典每次都会更新,如果 RTP 包包含 CSRC 标识符,则与这些 CSRC 标识符对应的 RTCRtpContributingSource
字典
也会更新。用户代理 MUST 按照升序 RTP 时间戳的顺序处理 RTP 包。用户代理 MUST
保留交付到 RTCRtpReceiver
的 MediaStreamTrack
的 RTP 包的先前 10 秒的信息。
MediaStreamTrack
未连接到任何用于播放的接收端,
getSynchronizationSources
和
getContributingSources
返回最新的信息,只要轨道未结束;接收端并不是解码 RTP 数据包的前提条件。
RTCRtpSynchronizationSource
和
RTCRtpContributingSource
字典对于特定的
RTCRtpReceiver
包含
来自 RTP 流中单一时间点的信息。
WebIDLdictionary RTCRtpContributingSource
{
required DOMHighResTimeStamp timestamp
;
required unsigned long source
;
double audioLevel
;
required unsigned long rtpTimestamp
;
};
timestamp
类型为
DOMHighResTimeStamp
,必需
timestamp
表示来自该源的 RTP 数据包中,最近一帧被送达
RTCRtpReceiver
的 MediaStreamTrack
的时间。
timestamp
定义为
Performance
.timeOrigin
+
Performance
.now
()
在该时间点的值。
source
类型为 unsigned long,必需
贡献源的 CSRC 或 SSRC 标识符。
audioLevel
类型为 double
仅在音频接收器中出现。这是一个介于 0..1 之间的值(线性),其中 1.0 表示 0 dBov,0 表示静音,0.5 表示大约 6 dBSPL 的声压级变化。
对于 CSRC,这 MUST 从 RFC 6465 中定义的水平值转换,如果 RFC 6465 头扩展存在,则此成员 MUST 缺失。
对于 SSRC,这 MUST 从 RFC 6464 中定义的水平值转换。如果接收到的包中没有 RFC 6464 头扩展(例如,如果另一个端点不是用户代理或是遗留端点),则此值 SHOULD 缺失。
两个 RFC 都将该级别定义为从 0 到 127 的整数值,表示相对于系统可能编码的最响信号的音频级别。因此,0 表示系统可能编码的最响信号,127 表示静音。
要将这些值转换为线性 0..1 范围,值 127 转换为 0,所有其他值通过以下方程转换: 10^(-rfc_level/20)
。
rtpTimestamp
类型为 unsigned long,必需
媒体播放时间的 RTP 时间戳,如 [RFC3550] 第 5.1 节定义。
WebIDLdictionary RTCRtpSynchronizationSource
: RTCRtpContributingSource
{};
预期 RTCRtpSynchronizationSource
字典作为规范的扩展点,以显示仅在 SSRC 中可用的数据。
RTCRtpTransceiver
接口表示一个
RTCRtpSender
和一个 RTCRtpReceiver
的组合,它们共享一个
公共的 媒体流
“识别标签”。如在 [RFC9429] (第 3.4.1 节) 中定义,一个 RTCRtpTransceiver
被称为
关联
一个 媒体描述 如果它的
"mid" 属性非空并且与 媒体流 “识别标签” 匹配
在 媒体描述 中;否则,它
被称为与该 媒体描述 失去关联。
一个 RTCRtpTransceiver
可能会与新的待处理
描述关联,同时仍与当前描述解除关联。这可能发生在 检查是否需要协商。
传输器种类 的 RTCRtpTransceiver
由所关联的 RTCRtpReceiver
的 MediaStreamTrack
对象的种类定义。
要 创建一个 RTCRtpTransceiver,并指定一个 RTCRtpReceiver
对象 receiver、一个 RTCRtpSender
对象 sender,以及一个 RTCRtpTransceiverDirection
值
direction,
运行以下步骤:
让 transceiver 成为一个新的 RTCRtpTransceiver
对象。
让 transceiver 拥有一个 [[Sender]] 内部槽,初始化为 sender。
让 transceiver 拥有一个 [[Receiver]] 内部槽,初始化为 receiver。
让 transceiver 拥有一个 [[Stopping]] 内部槽,初始化为 false
。
让 transceiver 拥有一个 [[Stopped]] 内部槽,初始化为 false
。
让 transceiver 拥有一个 [[Direction]] 内部槽,初始化为 direction。
让 transceiver 拥有一个 [[Receptive]] 内部槽,初始化为 false
。
让 transceiver 拥有一个 [[CurrentDirection]] 内部槽,初始化为 null
。
让 transceiver 拥有一个 [[FiredDirection]] 内部槽,初始化为 null
。
让 transceiver 拥有一个 [[PreferredCodecs]] 内部槽,初始化为空列表。
让 transceiver 拥有一个 [[JsepMid]] 内部槽,初始化为 null
。这是
"RtpTransceiver mid 属性",定义在 [RFC9429] (第 5.2.1 节 和 第 5.3.1 节),
仅在那儿被修改。
让 transceiver 拥有一个 [[Mid]]
内部槽,初始化为 null
。
返回 transceiver。
WebIDL[Exposed=Window]
interface RTCRtpTransceiver
{
readonly attribute DOMString? mid
;
[SameObject] readonly attribute RTCRtpSender
sender
;
[SameObject] readonly attribute RTCRtpReceiver
receiver
;
attribute RTCRtpTransceiverDirection
direction
;
readonly attribute RTCRtpTransceiverDirection
? currentDirection
;
undefined stop
();
undefined setCodecPreferences
(sequence<RTCRtpCodec
> codecs);
};
mid
类型为 DOMString,只读,可为空
mid
属性是协商并存在于本地和远程描述中的 媒体流
"识别标签"。在获取时,该属性 必须 返回 [[Mid]]
槽的值。
sender
类型为 RTCRtpSender
,只读
sender
属性暴露了对应于可能发送的
RTP 媒体的 RTCRtpSender
,其 mid = [[Mid]]
。在获取时,该属性 必须
返回 [[Sender]]
槽的值。
receiver
类型为 RTCRtpReceiver
,只读
receiver
属性是对应于可能接收的
RTP 媒体的 RTCRtpReceiver
,其 mid = [[Mid]]
。在获取时,该属性 必须
返回 [[Receiver]]
槽的值。
direction
类型为 RTCRtpTransceiverDirection
如 [RFC9429](第 4.2.4
节) 定义,direction 属性指示此转发器的首选方向,将在调用 createOffer
和 createAnswer
时使用。方向性更新不会立即生效。相反,将来对 createOffer
和 createAnswer
的调用将对应的 媒体描述 标记为 sendrecv
、sendonly
、recvonly
或 inactive
,如 [RFC9429](第 5.2.2 节 和 第 5.3.2
节) 中定义。
在获取时,用户代理 必须 执行以下步骤:
让 transceiver 成为调用获取器的 RTCRtpTransceiver
对象。
如果 transceiver.[[Stopping]]
为
true
,则返回
"stopped
"。
否则,返回 [[Direction]]
槽的值。
在设置时,用户代理 必须 执行以下步骤:
让 transceiver 成为调用设置器的 RTCRtpTransceiver
对象。
让 connection 成为与 transceiver 关联的 RTCPeerConnection
对象。
如果 transceiver.[[Stopping]]
为
true
,则 抛出 一个 InvalidStateError
。
让 newDirection 为设置器的参数。
如果 newDirection 等于 transceiver.[[Direction]]
,则中止这些步骤。
将 transceiver.[[Direction]]
设置为
newDirection。
更新 negotiation-needed 标志 以适用于 connection。
currentDirection
类型为 RTCRtpTransceiverDirection
,
只读,可为 null
如 [RFC9429]
(第 4.2.5
节) 所定义,currentDirection
属性指示此转发器的当前协商方向。currentDirection 的值与 RTCRtpEncodingParameters
.active
的值是独立的,因为两者不能相互推断。如果此转发器从未在提议/应答交换中表示,则值为 null
。如果转发器为 stopped
,则值为
"stopped
"。
在获取时,用户代理 必须 执行以下步骤:
让 transceiver 成为调用获取器的 RTCRtpTransceiver
对象。
如果 transceiver.[[Stopped]]
为
true
,则返回
"stopped
"。
否则,返回 [[CurrentDirection]]
槽的值。
stop
不可逆地将转发器标记为 stopping
,除非它已经是 stopped
。这将立即导致转发器的发送者不再发送,其接收者不再接收。调用 stop
()
还会 更新协商需要标志,适用于与 RTCRtpTransceiver
关联的 RTCPeerConnection
。
一个 stopping 转发器将在未来调用 createOffer
时生成一个零端口
对于相应转发器的 媒体描述,如 [RFC9429]
(第 4.2.1
节) 所定义(用户代理 必须 将 stopping
转发器视为 stopped
的目的仅在于此)。然而,为了避免与 [RFC8843]
发生问题,一个处于 stopping
状态但不
stopped
的转发器将不会影响
createAnswer
。
一个 stopped 转发器将在未来调用 createOffer
或 createAnswer
时生成一个零端口
对于相应转发器的 媒体描述,如 [RFC9429]
(第 4.2.1
节) 所定义。
转发器将保持在 stopping
状态,除非
它被 stopped
,通过
setRemoteDescription
处理远程报价或应答中的拒绝 m-line。
当调用 stop
方法时,用户代理 必须 执行以下步骤:
让 transceiver 成为调用该方法的 RTCRtpTransceiver
对象。
让 connection 成为与 transceiver 关联的 RTCPeerConnection
对象。
如果 connection.[[IsClosed]]
为
true
,则 抛出 一个
InvalidStateError
。
如果 transceiver.[[Stopping]]
为
true
,则中止这些步骤。
停止发送和接收 与 transceiver。
更新协商需要标志 对于 connection。
停止发送和接收 算法给定一个
transceiver 和一个可选的 disappear 布尔值,默认为
false
,如下:
让 sender 为
transceiver.[[Sender]]
。
让 receiver 为
transceiver.[[Receiver]]
。
并行进行,停止与 sender 的媒体发送,并 为每个由 sender 发送的 RTP 流发送 RTCP BYE,如 [RFC3550] 中所述。
并行进行,停止与 receiver 的媒体接收。
如果 disappear 为 false
,则执行步骤
receiver.[[ReceiverTrack]]
被
结束。
这会触发一个事件。
将 transceiver.[[Direction]]
设置为
"inactive
"。
将 transceiver.[[Stopping]]
设置为
true
。
停止 RTCRtpTransceiver 算法给定一个
transceiver 和一个可选的 disappear 布尔值,默认为
false
,如下:
如果 transceiver.[[Stopping]]
为
false
,则 停止发送和接收
与 transceiver 和 disappear。
将 transceiver.[[Stopped]]
设置为
true
。
将 transceiver.[[Receptive]]
设置为
false
。
将 transceiver.[[CurrentDirection]]
设置为 null
。
setCodecPreferences
setCodecPreferences
方法覆盖了默认的
接收 编解码器偏好,用于 用户代理。在生成会话描述时,无论使用
createOffer
还是
createAnswer
,
用户代理
必须 按照
codecs 参数中指定的顺序使用指明的编解码器,适用于与此 RTCRtpTransceiver
。
此方法允许应用程序禁用特定编解码器的协商(包括 RTX/RED/FEC)。它还允许应用程序使远程对等方优先选择列表中第一个出现的编解码器用于发送。
编解码器偏好在所有包含此 RTCRtpTransceiver
的 createOffer
和 createAnswer
调用中保持有效,直到再次调用此方法。
将 codecs 设置为空序列将重置编解码器偏好为任何默认值。
编解码器在 SDP 的每个 m= 部分下列出,定义了有效负载类型与编解码器之间的映射。这些有效负载类型由 m=video 或 m=audio
行按优先级顺序引用,而未协商的编解码器不会出现在此列表中,如 [RFC8829RFC9429
第 5.2.1 节定义。
之前协商的编解码器随后被移除并从 m=video 或 m=audio
行中消失,尽管它的编解码器有效负载类型在未来的提议或应答中不会被重新使用,但其有效负载类型也可能从 SDP 中的有效负载类型映射中移除。
传递给
将拒绝设置 codecs 的尝试
setCodecPreferences
的 codecs 序列只能包含由
.RTCRtpSender
getCapabilities
(kind)
或
不匹配 在
RTCRtpReceiver
.getCapabilities
(kind),
其中 kind 是调用该方法的 RTCRtpTransceiver
的类型。此外,
字典成员不能被修改。如果 codecs 不满足这些要求,用户代理 必须
抛出 RTCRtpCodecCapability
InvalidModificationError
.
根据 [SDP]
的建议,
对
的调用 应该 仅使用编解码器偏好的公共子集和出现在提议中的编解码器。例如,如果编解码器偏好为 "C,
B, A",但只有编解码器 "A, B" 被提议,答复应仅包含编解码器 "B, A"。但是,[RFC8829]
(第 5.3.1
节) 允许添加未在提议中的编解码器,因此实现可以表现出不同的行为。
createAnswer
当 setCodecPreferences
()
在被调用时,用户代理
必须 执行以下步骤:
让 transceiver 成为调用该方法的 RTCRtpTransceiver
对象。
让 codecs 为第一个参数。
如果 codecs 是一个空列表,则将 transceiver.[[PreferredCodecs]]
设置为
codecs 并中止这些步骤。
移除 codecs 中的任何重复值。从列表的后面开始,以确保优先级顺序保持不变;列表中每个编解码器的第一次出现的索引在此步骤之前和之后都是相同的。
移除 重复 值在 codecs 中,确保每个值的第一次出现保持不变。
让 kind 为 transceiver 的 转发器类型。
如果 codecs 与
.RTCRtpSender
getCapabilities
(kind).
或 codecs 与
codecs
.RTCRtpReceiver
(kind).getCapabilities
仅包含 RTX、RED 或 FEC 编解码器,或是一个空集,
则抛出 codecs
InvalidModificationError
。
这确保我们
始终有东西可以提供,无论 transceiver 的
direction
。
让 codecCapabilities 成为
成为
.RTCRtpSender
(kind).getCapabilities
和
codecs
RTCRtpReceiver
.getCapabilities
(kind).codecs
。
对于 codecs 中的每个 codec,
InvalidModificationError
。
对于 codecs 中的每个 codec,
如果 codec 不 匹配 任何
codecCapabilities 中的编解码器,则抛出 InvalidModificationError
。
如果 codecs 仅包含 RTX、RED、FEC 或舒适噪声的条目或是一个空集合,
抛出 InvalidModificationError
。
这确保我们始终有东西可提供,而不管 transceiver.direction
。
将 transceiver.[[PreferredCodecs]]
设置为
codecs。
编解码器字典匹配 算法 给定两个 RTCRtpCodec
字典
first 和 second 如下:
如果 first.mimeType
不是 second.mimeType
的
ASCII 不区分大小写 匹配,则返回
false
。
如果 first.channels
和 second.channels
之一(但不是两者)缺失,或者如果它们都 存在,且 first.channels
与 second.channels
不同,则返回
false
。
如果 first.sdpFmtpLine
和 second.sdpFmtpLine
之一(但不是两者)缺失,或者如果它们都 存在,且 first.sdpFmtpLine
与 second.sdpFmtpLine
不同,则返回
false
。
返回 true
。
如果设置,则提议者的接收编解码器偏好将决定提议中的编解码器顺序。如果应答者没有任何编解码器偏好,则将使用相同的顺序作为答复。然而,如果应答者也有编解码器偏好,则这些偏好会覆盖答复中的顺序。在这种情况下,提议者的偏好将影响提议中的编解码器,但不会影响最终顺序。
模拟广播 发送 功能 通过由
addTransceiver
方法
的通过其
sendEncodings
参数,或者
setRemoteDescription
方法与远程报价一起接收模拟广播,这两种方法都是
RTCPeerConnection
对象和 对象。此外,
the setParameters
方法 的在每个
RTCRtpSender
对象
对象可以用于检查和修改功能。
The An
method establishes the
addTransceiver
RTCRtpSender
's simulcast envelope which
是
在首次成功协商时建立,涉及发送模拟广播而不是单播,并且 包括可以发送的模拟广播流的最大数量,以及 其
其
encodings
。 While characteristics 这个 模拟广播信封
可以在后续重新协商中缩小(减少层数),但不能重新扩展。特性 的
单个模拟广播流可以使用
setParameters
方法,
但 the 模拟广播信封
本身 不能被 changed通过该方法更改。
该模型的一个含义是,addTrack
()
方法无法提供simulcast功能,因为它不接受
作为参数,因此无法配置sendEncodings
以发送simulcast。
RTCRtpTransceiver
另一个含义是应答者无法直接设置simulcast envelope。在调用setRemoteDescription
方法的
对象上,simulcast envelope会在RTCPeerConnection
上配置为包含指定会话描述中描述的层。一旦确定了
envelope,层无法被移除。可以通过将RTCRtpTransceiver
成员设置为active
false
来标记它们为非活动状态,从而有效禁用该层。
配置模拟广播的一种方法是使用
sendEncodings
选项传递给
addTransceiver
()
。
虽然
addTrack
()
方法缺少
sendEncodings
参数,因此无法配置模拟广播,发送者可以在用户代理作为回答者时提升为
模拟广播。调用
setRemoteDescription
方法并带有远程
报价以接收模拟广播时,
建议的信封 被
配置在一个 RTCRtpSender
上,以包含指定会话描述中描述的层。
只要这个
描述没有被回滚,
建议的信封 就会在协商完成时成为
RTCRtpSender
的 模拟广播信封。如上所述,这个
模拟广播信封 可以在后续重新协商中缩小,
但不会重新扩展。
当 setParameters
不能
修改 simulcast
simulcast envelope,, 仍然可以控制
发送的流数量及其特征。使用 setParameters
,可以通过将
active
成员
设置为 false
,使得 simulcast 流可以变为不活动,或者通过将
active
成员
设置为 true
以重新激活。
[RFC7728] (RTP 暂停/恢复) 不被支持,也不支持
通过 SDP Offer/Answer 进行暂停/恢复的信令。
使用 setParameters
,可以通过修改
属性如 maxBitrate
来改变流的特征。
Simulcast 通常用于将多个编码发送到 SFU,随后 SFU 将其中一个 simulcast 流转发给最终用户。因此,用户代理预期将在编码之间分配带宽,使所有 simulcast
流都能单独使用;例如,如果两个 simulcast 流具有相同的 maxBitrate
,人们预期
两个流的比特率相似。如果带宽不允许以可用的形式发送所有 simulcast 流,则用户代理预期停止发送某些 simulcast 流。
如
[RFC9429] (第3.7节。) 中定义,来自用户代理的报价将在
a=simulcast
行中仅包含 "send" 描述,而不包含 "recv" 描述。不支持 [RFC8853]
中描述的替代方案和限制。
本规范未定义如何通过 createOffer
、
createAnswer
或
addTransceiver
配置接收
多个 RTP 编码。然而,当
setRemoteDescription
被调用,并提供了能够发送多个 RTP 编码的相应远程描述,如 [RFC9429] 中定义,并且
浏览器支持接收多个 RTP 编码,那么 RTCRtpReceiver
可能
接收多个 RTP 编码,且通过传输器的
receiver
.getParameters
()
将反映谈判的编码。
一个 RTCRtpReceiver
可以在选择性转发单元(SFU)从用户代理接收模拟广播流并在其之间切换的场景中接收多个 RTP 流。如果 SFU 没有重写 RTP 头以将切换后的流安排成单个 RTP 流再转发,
RTCRtpReceiver
将
接收来自不同 RTP 流的数据包,每个流都有自己的 SSRC 和序列号空间。虽然 SFU 可能在任何给定时间只转发单个 RTP 流,但由于重排序,来自多个 RTP
流的数据包可能会在接收端混合。具备接收多个 RTP 流能力的
RTCRtpReceiver
因此需要能够正确排序接收的数据包,识别潜在的丢包事件并对其做出反应。在这种情况下的正确操作并非易事,因此对于本规范的实现来说是可选的。
本节为非规范性。
实现模拟广播场景的编码参数示例:
// 3层空间模拟广播的示例,所有但最低分辨率的层都被禁用
var encodings = [
{rid: 'q', active: true, scaleResolutionDownBy: 4.0}
{rid: 'h', active: false, scaleResolutionDownBy: 2.0},
{rid: 'f', active: false},
];
本节为非规范性。
direction
属性和
replaceTrack
方法使开发人员能够实现
“保持”场景。
要向对等方发送音乐并停止渲染接收到的音频(保持音乐):
async function playMusicOnHold() {
try {
// 假设我们有一个音频转发器和一个名为 musicTrack 的音乐轨道
await audio.sender.replaceTrack(musicTrack);
// 静音接收到的音频
audio.receiver.track.enabled = false;
// 将方向设置为仅发送(需要协商)
audio.direction = 'sendonly';
} catch (err) {
console.error(err);
}
}
要响应远程对等方的“仅发送”提议:
async function handleSendonlyOffer() {
try {
// 首先应用 sendonly 提议,
// 确保接收方已准备好 ICE 候选。
await pc.setRemoteDescription(sendonlyOffer);
// 停止发送音频
await audio.sender.replaceTrack(null);
// 将我们的方向对齐以避免进一步协商
audio.direction = 'recvonly';
// 调用 createAnswer 并发送 recvonly 答复
await doAnswer();
} catch (err) {
// 处理信令错误
}
}
要停止发送音乐并发送来自麦克风捕获的音频,以及渲染接收到的音频:
async function stopOnHoldMusic() {
// 假设我们有一个音频转发器和一个名为 micTrack 的麦克风轨道
await audio.sender.replaceTrack(micTrack);
// 取消静音接收到的音频
audio.receiver.track.enabled = true;
// 将方向设置为 sendrecv(需要协商)
audio.direction = 'sendrecv';
}
要响应远程对等方将其从保持状态中移除:
async function onOffHold() {
try {
// 首先应用 sendrecv 提议,以确保接收方已准备好 ICE 候选。
await pc.setRemoteDescription(sendrecvOffer);
// 开始发送音频
await audio.sender.replaceTrack(micTrack);
// 将方向设置为 sendrecv(正好在回答之前)
audio.direction = 'sendrecv';
// 调用 createAnswer 并发送 sendrecv 答复
await doAnswer();
} catch (err) {
// 处理信令错误
}
}
RTCDtlsTransport
接口允许应用程序访问
有关数据报传输层安全性(DTLS)传输的信息,通过该传输 RTP 和 RTCP 数据包由
RTCRtpSender
和 RTCRtpReceiver
对象发送和接收,以及
其他数据,如通过数据通道发送和接收的 SCTP 数据包。特别是,DTLS 为底层传输添加安全性,
而 RTCDtlsTransport
接口
允许访问有关底层传输和所添加安全性的信息。RTCDtlsTransport
对象是通过调用
setLocalDescription
()
和
setRemoteDescription
()
生成的。
每个
RTCDtlsTransport
对象
表示 RTP 或 RTCP 的 DTLS 传输层
component
的特定
RTCRtpTransceiver
,或
如果通过 [RFC8843]
协商了这样的
组,则是一组 RTCRtpTransceiver
。
一个 RTCDtlsTransport
具有 [[DtlsTransportState]]
内部槽,初始化为 "new
" 和一个
[[RemoteCertificates]] 槽
初始化为空列表。
当底层 DTLS 传输遇到错误时,例如证书验证失败或致命警报(请参见 [RFC5246] 第 7.2 节),用户代理 必须 排队一个任务,运行以下步骤:
让 transport 成为接收状态更新和错误通知的 RTCDtlsTransport
对象。
如果 transport 的状态已经是
"failed
",则中止这些步骤。
将 transport.[[DtlsTransportState]]
设置为
"failed
"。
触发一个事件 名为 error
使用 RTCErrorEvent
接口,其 errorDetail 属性设置为
"dtls-failure
" 或
"fingerprint-failure
",
视情况而定,其他字段设置如 RTCErrorDetailType
枚举描述中的说明,在 transport 上。
触发一个事件 名为 statechange
在
transport 上。
当底层 DTLS 传输因任何其他原因需要更新相应的 RTCDtlsTransport
对象的状态时,
用户代理 必须 排队一个任务,运行以下步骤:
让 transport 成为接收状态更新的 RTCDtlsTransport
对象。
让 newState 为新状态。
将 transport.[[DtlsTransportState]]
设置为
newState。
如果 newState 是 connected
,则让 newRemoteCertificates 为远程端使用的证书链,链中每个证书以
二进制区分编码规则(DER) [X690]
编码,并将
transport.[[RemoteCertificates]]
设置为
newRemoteCertificates。
触发一个事件 名为 statechange
在
transport 上。
WebIDL[Exposed=Window]
interface RTCDtlsTransport
: EventTarget {
[SameObject] readonly attribute RTCIceTransport
iceTransport
;
readonly attribute RTCDtlsTransportState
state
;
sequence<ArrayBuffer> getRemoteCertificates
();
attribute EventHandler onstatechange
;
attribute EventHandler onerror
;
};
iceTransport
类型为 RTCIceTransport
,
只读
iceTransport
属性是用于发送和接收数据包的底层传输。
底层传输可能不会在多个活动的 RTCDtlsTransport
对象之间共享。
state
类型为 RTCDtlsTransportState
,
只读
state
属性 必须 在获取时返回
[[DtlsTransportState]]
槽的值。
onstatechange
类型为 EventHandler
statechange
。
onerror
类型为 EventHandler
error
。
getRemoteCertificates
返回 [[RemoteCertificates]]
的值。
WebIDLenum RTCDtlsTransportState
{
"new
",
"connecting
",
"connected
",
"closed
",
"failed
"
};
枚举值 | 描述 |
---|---|
new
|
DTLS 尚未开始协商。 |
connecting
|
DTLS 正在协商安全连接并验证远程指纹。 |
connected
|
DTLS 已完成安全连接的协商并验证了远程指纹。 |
closed
|
传输因接收到 close_notify 警报或调用
close ()
而被故意关闭。
|
failed
|
传输由于错误(如接收到错误警报或未能验证远程指纹)而失败。 |
RTCDtlsFingerprint
字典包括
哈希函数
算法和证书指纹,如 [RFC4572]
所述。
WebIDLdictionary RTCDtlsFingerprint
{
DOMString algorithm
;
DOMString value
;
};
algorithm
类型为 DOMString
在 '哈希函数文本名称' 注册表中定义的哈希函数算法之一 [IANA-HASH-FUNCTION]。
value
类型为 DOMString
证书指纹的值,采用小写十六进制字符串表示,按照 [RFC4572] 第 5 节中的 'fingerprint' 语法表达。
RTCIceTransport
接口
允许应用程序访问有关 ICE 传输的信息,通过该传输发送和接收数据包。
特别是,ICE 管理对等连接,其中包含应用程序可能想要访问的状态。
RTCIceTransport
对象是
通过调用
setLocalDescription
()
和
setRemoteDescription
()
创建的。
基础 ICE
状态由 ICE
agent 管理;因此,RTCIceTransport
的状态在 ICE Agent 提供指示时会发生变化,如下所述。每个
RTCIceTransport
对象
表示特定
RTCRtpTransceiver
的 RTP 或 RTCP
component
,或如果
通过 [RFC8843]
协商的
组,则代表一组 RTCRtpTransceiver
。
当ICE Agent 表示它开始为一代候选人收集相关的RTCIceTransport
transport 关联到 RTCPeerConnection
connection,用户代理必须排队一个任务,执行以下步骤:
让 connection 为与此 ICE Agent 关联的 RTCPeerConnection
对象。
如果 connection.[[IsClosed]]
是 true
,则中止这些步骤。
让 transport 为正在进行候选人收集的 RTCIceTransport
。
将 transport.[[IceGathererState]]
设置为 gathering
.
.
将 connection.[[IceGatheringState]]
设置为根据RTCIceGatheringState
枚举描述的衍生新状态值。
让 connectionIceGatheringStateChanged 为 true
,如果
connection.[[IceGatheringState]]
在上一步中发生了变化,否则为 false
。
不要在此点读取或修改状态。
触发一个名为 gatheringstatechange
事件在 transport 上。
如果 connectionIceGatheringStateChanged 为 true
,触发一个名为 icegatheringstatechange
事件在 connection 上。
当 ICE Agent 完成收集一组 候选者,用于一个 RTCIceTransport
transport 关联到一个 RTCPeerConnection
connection,并且这些候选者已被呈现给应用程序,用户代理 必须 排队一个任务 以运行来运行 以下以下 步骤:
让connection成为与此ICE Agent关联的RTCPeerConnection
对象。
如果connection.[[IsClosed]]
是true
,则中止这些步骤。
让transport成为正在完成候选人收集的RTCIceTransport
。
如果connection.[[PendingLocalDescription]]
不为null
,并且代表ICE一代的候选人收集已完成,则在connection.[[PendingLocalDescription]]
.sdp中添加a=end-of-candidates
。
如果connection.[[CurrentLocalDescription]]
不为null
,并且代表ICE一代的候选人收集已完成,则在connection.[[CurrentLocalDescription]]
.sdp中添加a=end-of-candidates
。
让newCandidateendOfGatheringCandidate为通过创建一个一个RTCIceCandidate获得的结果,使用一个新字典,其中sdpMid
和sdpMLineIndex
被设置为与此RTCIceTransport
相关的值,并且usernameFragment
被设置为与候选人收集完成的一代关联的用户名片段,并且candidate
被设置为空字符串""
。
触发一个名为 icecandidate
的事件,使用RTCPeerConnectionIceEvent
接口,在connection上将候选人属性设置为newCandidateendOfGatheringCandidate。
如果另一代候选人仍在收集, 中止这些步骤。
将transport.[[IceGathererState]]
设置为
。
complete
触发一个名为
的事件在transport上。
gatheringstatechange
更新 connection 的ICE收集状态。
当ICE代理已排队上述任务,并且没有其他候选人的代正在收集时,用户代理必须也排队第二个任务以运行以下步骤:
如果connection.[[IsClosed]]
为true
,则中止这些步骤。
将transport.[[IceGathererState]]
设置为complete
。
将connection.[[IceGatheringState]]
设置为根据RTCIceGatheringState
枚举描述的派生新状态值。
如果connection.[[IceGatheringState]]
在前一步中发生变化,则令connectionIceGatheringStateChanged为true
,否则为false
。
此时不要读取或修改状态。
触发一个名为 gatheringstatechange
的事件在transport上。
如果connectionIceGatheringStateChanged为true
,则触发一个名为 icegatheringstatechange
的事件在connection上。
触发一个名为 icecandidate
的事件,使用RTCPeerConnectionIceEvent
接口,候选人属性设置为null
,在connection上。
RTCIceTransport
和/或RTCPeerConnection
的收集状态。
当 ICE Agent 指示有一个新的 ICE 候选者可用于 RTCIceTransport
,无论是从ICE 候选者池中获取,还是从头开始收集,用户代理 必须
排队一个任务来运行以下步骤:
让candidate为可用的ICE候选人。
让connection为与此RTCPeerConnection
对象相关联的ICE代理。
如果connection.[[IsClosed]]
为true
,则中止这些步骤。
如果connection.[[PendingLocalDescription]]
或connection.[[CurrentLocalDescription]]
不为null
,并且表示ICE代,用于收集candidate,则用candidate和connection进行展示候选人,并中止这些步骤。
否则,将candidate附加到connection.[[EarlyCandidates]]
。
当ICE Agent 指示由于根据 [RFC8445]
第 7.3.1.1 节的角色冲突而发生 ICE 角色变化时,用户代理将排队一个任务,以将
[[IceRole]]
的值设置为新值。
要对释放早期候选人,请执行以下步骤:
对于connection.[[EarlyCandidates]]
中的每个候选人candidate,
排队一个任务以表面候选人,使用candidate和connection。
将connection.[[EarlyCandidates]]
设置为空列表。
要对表面候选人 使用candidate和connection,请执行以下步骤:
如果connection.[[IsClosed]]
为
true
,则中止这些步骤。
让transport为与candidate相关的RTCIceTransport
。
如果connection.[[PendingLocalDescription]]
不为
null
,并且表示ICE代,用于收集candidate,
则将candidate添加到connection.[[PendingLocalDescription]]
.sdp。
如果connection.[[CurrentLocalDescription]]
不为
null
,并且表示ICE代,用于收集candidate,
则将candidate添加到connection.[[CurrentLocalDescription]]
.sdp。
让newCandidate为创建一个RTCIceCandidate的结果使用一个新字典,该字典的
sdpMid
和
sdpMLineIndex
设置为
与此RTCIceTransport
相关的值,
usernameFragment
设置为候选人的用户名片段,
并且candidate
设置为使用candidate-attribute
语法编码的字符串,以表示candidate。
将newCandidate添加到transport的本地候选人集合中。
触发一个名为 icecandidate
的事件,使用RTCPeerConnectionIceEvent
接口,候选人属性设置为newCandidate,在connection上。
一个RTCIceTransportState
的RTCIceTransport
可能会发生变化,
因为找到了可用连接的候选对并选择了它,或者它可能在未改变所选候选对的情况下发生变化。
选定的对和RTCIceTransportState
是相关的,并在同一任务中处理。
当ICE代理表示一个RTCIceTransport
已经更改了所选候选对、RTCIceTransportState
或两者时,用户代理必须排队一个任务,运行以下步骤以更改所选候选对和状态:
让connection为与此RTCPeerConnection
对象
关联的ICE代理。
如果connection.[[IsClosed]]
为
true
,则中止这些步骤。
让transport为其状态正在更改的RTCIceTransport
。
让selectedCandidatePairChanged为
false
。
让transportIceConnectionStateChanged为
false
。
让connectionIceConnectionStateChanged为
false
。
让connectionStateChanged为false
。
如果transport的选定候选对已更改,则执行以下步骤:
让newCandidatePair为创建一个RTCIceCandidatePair的结果,
其包含本地和远程,表示所指对的本地和远程候选人(如果选择了其中一个),否则为null
。
将transport.[[SelectedCandidatePair]]
设置为newCandidatePair。
将selectedCandidatePairChanged设置为
true
。
如果transport的RTCIceTransportState
已更改,
执行以下步骤:
将transport.[[IceTransportState]]
设置为
新的所指RTCIceTransportState
。
将transportIceConnectionStateChanged设置为
true
。
将connection.[[IceConnectionState]]
设置为
通过RTCIceConnectionState
枚举
描述的新状态值。
如果connection.[[IceConnectionState]]
在上一
步中更改,则将connectionIceConnectionStateChanged设置为
true
。
将connection.[[ConnectionState]]
设置为
通过RTCPeerConnectionState
枚举
描述的新状态值。
如果connection.[[ConnectionState]]
在上一步骤中更改,
则将connectionStateChanged设置为true
。
如果selectedCandidatePairChanged为true
,
触发一个名为 selectedcandidatepairchange
的事件,使用transport。
如果transportIceConnectionStateChanged为true
,
触发一个名为 statechange
的事件,使用transport。
如果connectionIceConnectionStateChanged为true
,则触发一个名为
触发一个名为 iceconnectionstatechange
的事件,使用connection。
如果connectionStateChanged为true
,则触发一个名为
触发一个名为 connectionstatechange
的事件,使用connection。
一个RTCIceTransport
对象具有以下内部插槽:
new
"
new
"
null
unknown
"
WebIDL[Exposed=Window]
interface RTCIceTransport
: EventTarget {
readonly attribute RTCIceRole
role
;
readonly attribute RTCIceComponent
component
;
readonly attribute RTCIceTransportState
state
;
readonly attribute RTCIceGathererState
gatheringState
;
sequence<RTCIceCandidate
> getLocalCandidates
();
sequence<RTCIceCandidate
> getRemoteCandidates
();
RTCIceCandidatePair
? getSelectedCandidatePair
();
RTCIceParameters
? getLocalParameters
();
RTCIceParameters
? getRemoteParameters
();
attribute EventHandler onstatechange
;
attribute EventHandler ongatheringstatechange
;
attribute EventHandler onselectedcandidatepairchange
;
};
role
类型为 RTCIceRole
,只读
role
属性 必须 在获取时返回
[[IceRole]] 内部插槽的值。
component
类型为
RTCIceComponent
,只读
component
属性 必须 返回
该传输的 ICE 组件。当使用 RTCP 多路复用时,单个
RTCIceTransport
同时传输 RTP 和
RTCP,
并且
component
设置为 "rtp
"。
state
类型为
RTCIceTransportState
,
只读
state
属性 必须 在获取时返回
[[IceTransportState]]
插槽的值。
gatheringState
类型为 RTCIceGathererState
,
只读
gatheringState
属性 必须 在获取时返回
[[IceGathererState]]
插槽的值。
onstatechange
类型为 EventHandler
statechange
,必须 在每次 RTCIceTransport
的
state
更改时触发。
ongatheringstatechange
类型为
EventHandler
gatheringstatechange
,
必须 在每次
RTCIceTransport
的
[[IceGathererState]]
更改时触发。
onselectedcandidatepairchange
类型为
EventHandler
selectedcandidatepairchange
,
必须 在每次
RTCIceTransport
的选定
候选对更改时触发。
getLocalCandidates
返回描述本 RTCIceTransport
收集的本地 ICE
候选项的序列,并在
onicecandidate
中发送。
getRemoteCandidates
返回描述通过 RTCIceTransport
接收到的远程 ICE
候选项的序列,
通过 addIceCandidate
()
。
getSelectedCandidatePair
返回用于发送数据包的选定候选对。此方法 必须 返回
[[SelectedCandidatePair]]
插槽的值。当
RTCIceTransport
.state
为
"new
" 或
"closed
"
getSelectedCandidatePair
返回 null
。
getLocalParameters
返回通过 RTCIceTransport
接收到的本地 ICE 参数,
通过 setLocalDescription
,
或者如果参数尚未接收,则返回 null
。
getRemoteParameters
返回通过 RTCIceTransport
接收到的远程 ICE 参数,
通过 setRemoteDescription
,
或者如果参数尚未接收,则返回 null
。
WebIDLdictionary RTCIceParameters
{
DOMString usernameFragment
;
DOMString password
;
};
RTCIceParameters
成员
RTCIceCandidatePair
字典
此接口表示一个 ICE 候选对,描述在 [RFC8445] 第 4 节中。
一个 RTCIceCandidatePair
是
本地和远程 RTCIceCandidate
的配对。
要 创建一个 RTCIceCandidatePair,使用 RTCIceCandidate
对象,
local 和 remote,
执行以下步骤:
RTCIceCandidatePair
对象。
dictionary[Exposed=Window] interface RTCIceCandidatePair { [SameObject] readonly attribute RTCIceCandidate local; [SameObject] readonly attribute RTCIceCandidate remote; };
RTCIceCandidatePair
成员
local
类型
RTCIceCandidate本地 ICE 候选。
remote
类型
RTCIceCandidate远程 ICE 候选。
remote
属性必须在获取时返回 [[Remote]]
内部槽的值。
WebIDLenum RTCIceGathererState
{
"new
",
"gathering
",
"complete
"
};
枚举值 | 描述 |
---|---|
new
|
RTCIceTransport 刚刚被创建,
尚未开始收集候选者。
|
gathering
|
RTCIceTransport 正在收集
候选者的过程中。
|
complete
|
RTCIceTransport 已完成收集,
并且此传输的候选结束指示已发送。
在 ICE 重启导致其重启之前,它不会再次收集候选者。
|
WebIDLenum RTCIceTransportState
{
"closed
",
"failed
",
"disconnected
",
"new
",
"checking
",
"completed
",
"connected
"
};
枚举值 | 描述 |
---|---|
closed
|
RTCIceTransport 已关闭,
不再响应 STUN 请求。
|
failed
|
RTCIceTransport
已完成收集,收到指示没有更多远程候选者,完成检查所有候选对,并且所有对都未能通过连接性检查或失去同意,且要么没有收集到本地候选者,要么 PAC 计时器已过期
[RFC8863]。
这是一个终止状态,直到 ICE 被重新启动。由于 ICE 重新启动可能会导致连接恢复,进入 "failed "
状态不会导致 DTLS 传输、SCTP 关联或其上运行的数据通道关闭,也不会静音轨道。
|
disconnected
|
ICE Agent 已确定此 RTCIceTransport 当前失去连接。
这是一个暂时状态,可能会间歇性触发(并在无操作的情况下自行解决)在不稳定的网络上。此状态的确定方式依赖于实现。
示例包括:
RTCIceTransport
已完成检查所有现有候选对并未找到连接(或同意检查 [RFC7675]
一旦成功,现在已失败),但它仍在收集和/或等待其他远程候选者。
|
new
|
RTCIceTransport 正在收集候选者和/或
等待提供远程候选者,尚未开始检查。
|
checking
|
RTCIceTransport
已收到至少一个远程候选者(通过addIceCandidate ()
或在接收 STUN 绑定请求时发现的对等反射候选者),并正在检查候选对,尚未找到连接或同意检查 [RFC7675]
已在所有之前成功的候选对上失败。
除了检查外,它可能仍在收集。
|
completed
|
RTCIceTransport
已完成收集,收到指示没有更多远程候选者,完成检查所有候选对并找到连接。如果同意检查 [RFC7675]
随后在所有成功的候选对上失败,状态转变为 "failed "。
|
connected
|
RTCIceTransport 已找到可用连接,但
仍在检查其他候选对,以查看是否有更好的连接。它可能仍在收集和/或
等待其他远程候选者。如果同意检查 [RFC7675]
在使用的连接上失败,并且没有其他成功的候选对可用,则状态转变为 "checking "
(如果还有候选对待检查)或 "disconnected "
(如果没有候选对可检查,但对等体仍在收集和/或等待其他远程候选者)。
|
成功通话最常见的状态转换为 new -> checking -> connected ->
completed,但在特定情况下(只有最后检查的候选者成功,且在成功之前收集和没有更多候选者的指示均发生),状态可以直接从
"checking
" 转换为
"completed
"。
ICE 重启会导致候选收集和连通性检查重新开始,如果在 "completed
" 状态下开始,则会导致状态转换为
"connected
"。如果在暂态的 "disconnected
"
状态下开始,则会导致状态转换为
"checking
",有效地忘记之前的连通性丢失。
"failed
" 和
"completed
"
状态需要指示没有额外的远程候选者。这可以通过调用 addIceCandidate
,其候选值的 candidate
属性设置为空字符串,或通过将 canTrickleIceCandidates
设置为
false
。
一些示例状态转换为:
RTCIceTransport
第一次创建,作为
setLocalDescription
或
setRemoteDescription
的结果): "new
"
new
",
收到远程候选者):
"checking
"
checking
", 找到可用连接):
"connected
"
checking
", 检查失败但仍在收集中):
"disconnected
"
checking
", 放弃):
"failed
"
disconnected
",
新本地候选者):
"checking
"
connected
", 完成所有检查):
"completed
"
completed
", 丢失连接):
"disconnected
"
disconnected
" 或
"failed
",
发生 ICE 重启):
"checking
"
completed
", 发生 ICE 重启):
"connected
"
RTCPeerConnection
.close
()
:
"closed
"
WebIDLenum RTCIceRole
{
"unknown
",
"controlling
",
"controlled
"
};
枚举值 | 描述 |
---|---|
unknown
|
根据 [RFC5245], 第 3 节,代理的角色尚未确定。 |
controlling
|
根据 [RFC5245], 第 3 节,控制代理。 |
controlled
|
根据 [RFC5245], 第 3 节,受控代理。 |
WebIDLenum RTCIceComponent
{
"rtp
",
"rtcp
"
};
枚举值 | 描述 |
---|---|
rtp
|
ICE 传输用于 RTP(或 RTCP 复用),
根据 [RFC5245],
第 4.1.1.1 节。与 RTP 复用的协议(例如数据通道)共享其
组件 ID。当编码在 candidate-attribute 时,
这表示 component-id 值 1 。
|
rtcp
|
ICE 传输用于 RTCP,根据 [RFC5245],
第 4.1.1.1 节。当编码在 candidate-attribute 时,
这表示 component-id 值 2 。
|
track
事件使用 RTCTrackEvent
接口。
WebIDL[Exposed=Window]
interface RTCTrackEvent
: Event {
constructor
(DOMString type, RTCTrackEventInit
eventInitDict);
readonly attribute RTCRtpReceiver
receiver
;
readonly attribute MediaStreamTrack track
;
[SameObject] readonly attribute FrozenArray<MediaStream> streams
;
readonly attribute RTCRtpTransceiver
transceiver
;
};
RTCTrackEvent.constructor()
receiver
类型为
RTCRtpReceiver
,只读
receiver
属性
表示与事件关联的 RTCRtpReceiver
对象。
track
类型为 MediaStreamTrack
,只读
track
属性表示
与 MediaStreamTrack
对象关联的 RTCRtpReceiver
,由 receiver
标识。
streams
类型为 FrozenArray<MediaStream
>,
只读
streams
属性返回
一个 MediaStream
对象的数组,表示此事件的 MediaStream
对象的数组,
track
是其中一部分。
transceiver
类型为
RTCRtpTransceiver
,
只读
transceiver
属性
表示与事件关联的
RTCRtpTransceiver
对象。
WebIDLdictionary RTCTrackEventInit
: EventInit {
required RTCRtpReceiver
receiver
;
required MediaStreamTrack track
;
sequence<MediaStream> streams
= [];
required RTCRtpTransceiver
transceiver
;
};
receiver
类型为 RTCRtpReceiver
,必填
receiver
成员
表示与事件关联的 RTCRtpReceiver
对象。
track
类型为 MediaStreamTrack
,必填
track
成员表示
与 MediaStreamTrack
对象关联的 RTCRtpReceiver
,由 receiver
标识。
streams
类型为
sequence<MediaStream
>,
默认值为 []
streams
成员是一个
MediaStream
对象的数组,
表示此事件的 MediaStream
对象的数组,
track
是其中一部分。
transceiver
类型为 RTCRtpTransceiver
,
必填
transceiver
属性表示与事件关联的
RTCRtpTransceiver
对象。
点对点数据 API 允许 Web 应用程序点对点地发送和接收通用应用数据。发送和接收数据的 API 模拟了 Web 套接字 的行为。
点对点数据 API 扩展了 RTCPeerConnection
接口,如下所述。
WebIDL partial interface RTCPeerConnection
{
readonly attribute RTCSctpTransport
? sctp
;
RTCDataChannel
createDataChannel
(USVString label,
optional RTCDataChannelInit
dataChannelDict = {});
attribute EventHandler ondatachannel
;
};
sctp
的类型为 RTCSctpTransport
,
只读,允许为空
SCTP 数据发送和接收的 SCTP 传输。
如果未协商 SCTP,则值为 null。此属性 必须 返回
RTCSctpTransport
对象,
存储在
[[SctpTransport]]
内部插槽中。
ondatachannel
的类型为 事件处理程序
datachannel
。
createDataChannel
创建一个新的 RTCDataChannel
对象,使用给定的标签。
RTCDataChannelInit
字典可用于
配置底层通道的属性,例如数据可靠性。
当调用 createDataChannel
方法时,用户代理 必须 执行以下步骤。
让 connection 成为调用该方法的 RTCPeerConnection
对象。
如果 connection.[[IsClosed]]
为
true
,则 抛出 一个
InvalidStateError
。
创建一个 RTCDataChannel,channel。
初始化
channel.[[DataChannelLabel]]
为
第一个参数的值。
如果
[[DataChannelLabel]]
的
UTF-8 表示
长于 65535 字节,则 抛出 一个 TypeError
。
让 options 为第二个参数。
初始化
channel.[[MaxPacketLifeTime]]
为
option.maxPacketLifeTime
,
如果存在,则为 null
。
初始化 channel.[[MaxRetransmits]]
为
option.maxRetransmits
,
如果存在,则为 null
。
初始化 channel.[[Ordered]]
为
option.ordered
。
初始化
channel.[[DataChannelProtocol]]
为
option.protocol
。
如果
[[DataChannelProtocol]]
的 UTF-8 表示
长于 65535 字节,则 抛出 一个 TypeError
。
初始化 channel.[[Negotiated]]
为
option.negotiated
。
初始化 channel.[[DataChannelId]]
为
option.id
,如果存在且 [[Negotiated]]
为 true,
否则为 null
。
如果 [[Negotiated]]
为
true
且 [[DataChannelId]]
为
null
,抛出 一个 TypeError
。
如果 [[MaxPacketLifeTime]]
和 [[MaxRetransmits]]
属性都被设置(非 null),抛出 一个 TypeError
。
如果某个设置,[[MaxPacketLifeTime]]
或 [[MaxRetransmits]]
被设置为指示不可靠模式,且该值超过用户代理支持的最大值,则该值 必须 设置为
用户代理的最大值。
如果 [[DataChannelId]]
等于
65535,
这大于最大允许的 ID 65534,但仍然
符合 无符号短整型,抛出 一个 TypeError
。
如果 [[DataChannelId]]
槽为
null
(因为没有 ID 被传入
createDataChannel
,
或 [[Negotiated]]
为 false),且
SCTP 传输的 DTLS 角色已
被协商,那么初始化
[[DataChannelId]]
为
用户代理生成的值,按照 [RFC8832],
并跳到下一步。如果无法生成可用 ID,或者
[[DataChannelId]]
槽的值已被一个
已存在的 RTCDataChannel
使用,抛出 一个
OperationError
异常。
让 transport 为
connection.[[SctpTransport]]
。
如果 [[DataChannelId]]
槽
不为 null
,且 transport 处于
"connected
"
状态,并且 [[DataChannelId]]
大于或等于
transport.[[MaxChannels]]
,抛出 一个 OperationError
。
如果 channel 是在 connection 上创建的第一个 RTCDataChannel
,则 更新
negotiation-needed 标志 对于 connection。
附加 channel 到
connection.[[DataChannels]]
。
返回 channel 并继续以下步骤 并行。
创建 channel 的关联 基础数据传输 并 根据 channel 的相关属性配置它。
RTCSctpTransport
接口允许应用程序访问
与特定 SCTP 关联绑定的 SCTP 数据通道的信息。
要 创建一个
RTCSctpTransport
,并具有初始状态 initialState,请执行以下步骤:
让 transport 成为一个新的 RTCSctpTransport
对象。
让 transport 拥有一个 [[SctpTransportState]] 内部槽,初始化为 initialState。
让 transport 拥有一个 [[MaxMessageSize]] 内部槽,并执行 标记为 更新数据最大消息大小 的步骤来初始化它。
让 transport 拥有一个 [[MaxChannels]]
内部槽,初始化为 null
。
返回 transport。
要 更新数据最大消息大小 的
RTCSctpTransport
,执行以下步骤:
让 transport 为要更新的 RTCSctpTransport
对象。
让 remoteMaxMessageSize 为从远程描述中读取的
max-message-size
SDP 属性的值,如 [RFC8841]
(第 6 节) 所述,如果缺少该属性则为 65536。
让 canSendSize 为该客户端可以发送的字节数(即本地发送缓冲区的大小),如果实现可以处理任何大小的消息,则为 0。
如果 remoteMaxMessageSize 和 canSendSize 都为 0,则将 [[MaxMessageSize]]
设置为正无穷大值。
否则,如果 remoteMaxMessageSize 或 canSendSize 为 0,则将 [[MaxMessageSize]]
设置为两者中较大的一个。
否则,将 [[MaxMessageSize]]
设置为
remoteMaxMessageSize 或 canSendSize 中较小的一个。
一旦 SCTP 传输连接,即 RTCSctpTransport
的 SCTP 关联已建立,执行以下步骤:
让 transport 为 RTCSctpTransport
对象。
让 connection 为与 transport 相关的 RTCPeerConnection
对象。
将 [[MaxChannels]]
设置为协商的
传入和传出 SCTP 流的最小数量。
对于 connection 的每个 RTCDataChannel
:
让 channel 为 RTCDataChannel
对象。
如果 channel.[[DataChannelId]]
为
null
,则将 [[DataChannelId]]
初始化为由基础 SCTP 数据通道生成的值,按照 [RFC8832]。
如果 channel.[[DataChannelId]]
大于或等于
transport.[[MaxChannels]]
,或者前一步未能分配
ID,关闭
channel 由于失败。否则,宣布通道为开放。
触发一个事件,名为 statechange
,在
transport 上。
WebIDL[Exposed=Window]
interface RTCSctpTransport
: EventTarget {
readonly attribute RTCDtlsTransport
transport
;
readonly attribute RTCSctpTransportState
state
;
readonly attribute unrestricted double maxMessageSize
;
readonly attribute unsigned short? maxChannels
;
attribute EventHandler onstatechange
;
};
transport
类型为 RTCDtlsTransport
,只读
所有数据通道的 SCTP 数据包将通过此传输发送和接收。
state
类型为 RTCSctpTransportState
,
只读
SCTP 传输的当前状态。获取时,此属性 必须 返回
[[SctpTransportState]]
槽的值。
maxMessageSize
类型为 unrestricted double,只读
可以传递给
RTCDataChannel
的 send
()
方法的最大数据大小。此属性 必须 在获取时返回
[[MaxMessageSize]]
槽的值。
maxChannels
类型为 unsigned short,只读,可空
可以同时使用的 RTCDataChannel
的最大数量。
此属性 必须 在获取时返回
[[MaxChannels]]
槽的值。
connected
"
状态之前将为 null
。
onstatechange
类型为 EventHandler
此事件处理程序的事件类型为
statechange
。
RTCSctpTransportState
表示 SCTP
传输的状态。
WebIDLenum RTCSctpTransportState
{
"connecting
",
"connected
",
"closed
"
};
枚举值 | 描述 |
---|---|
connecting
|
|
connected
|
当一个关联的协商完成时,任务被排队以更新 [[SctpTransportState]] 插槽
为 " |
closed
|
当任务被排队以更新 [[SctpTransportState]]
插槽为 "
请注意,最后的转换是逻辑上的,因为 SCTP 关联需要建立的 DTLS 连接 - [RFC8261] 第 6.1 节规定,SCTP 通过 DTLS 是单主机的 - 并且此 API 中未定义切换到备用传输的任何方法。 |
RTCDataChannel
接口
代表两个对等方之间的双向数据通道。一个 RTCDataChannel
通过
一个 RTCPeerConnection
对象上的工厂方法创建。浏览器之间发送的消息在
[RFC8831] 和
[RFC8832] 中描述。
建立与 RTCDataChannel
的连接有两种方式。
第一种方式是简单地在一个对等方上创建一个 RTCDataChannel
,将
negotiated
RTCDataChannelInit
字典成员未设置或
设置为其默认值 false。这将在通道中宣布新通道并触发
一个 RTCDataChannelEvent
,并在另一方
创建相应的 RTCDataChannel
对象。第二种方式是让应用程序协商 RTCDataChannel
。为此,创建一个
RTCDataChannel
对象,使用
negotiated
RTCDataChannelInit
字典成员设置为
true,并通过带外信号(例如通过 Web 服务器)通知另一方它 SHOULD
创建一个对应的 RTCDataChannel
,其
negotiated
RTCDataChannelInit
字典
成员设置为 true,以及相同的 id
。这将
连接两个分别创建的 RTCDataChannel
对象。
第二种方式使得可以创建具有不对称属性的通道,并通过指定匹配的 id
s 以声明的方式创建通道。
每个 RTCDataChannel
都有一个
相关的 基础数据传输,用于将实际数据传输到另一个对等方。在使用 RTCSctpTransport
的 SCTP
数据通道的情况下
(它表示 SCTP 关联的状态),基础数据传输是 SCTP 流对。基础数据传输的传输属性,如
顺序交付设置和可靠性模式,都是在创建通道时由对等方配置的。通道的属性在通道创建后无法更改。对等方之间的实际传输协议由
WebRTC 数据通道协议规范 [RFC8831] 指定。
一个 RTCDataChannel
可以被配置为在不同的
可靠性模式下操作。可靠通道确保数据通过重传送达另一对等方。一个不可靠的通道被配置为限制重传的数量(
maxRetransmits
)或设置在
传输(包括重传)允许的时间(
maxPacketLifeTime
)。这些
属性不能同时使用,尝试这样做将导致错误。不设置任何这些属性将导致通道为可靠通道。
一个 RTCDataChannel
,通过
createDataChannel
创建或通过
RTCDataChannelEvent
分发,
MUST 最初处于
"connecting
" 状态。当
RTCDataChannel
对象的 基础数据传输 准备好时,
用户代理 MUST 宣布 RTCDataChannel 已打开。
要 创建一个 RTCDataChannel
,
请按照以下步骤操作:
让 channel 成为一个新创建的 RTCDataChannel
对象。
让 channel 有一个 [[ReadyState]]
内部槽,初始化为
"connecting
"。
让 channel 有一个 [[BufferedAmount]]
内部槽,初始化为 0
。
让 channel 有内部槽,命名为 [[DataChannelLabel]]、[[Ordered]]、 [[MaxPacketLifeTime]]、 [[MaxRetransmits]]、 [[DataChannelProtocol]]、 [[Negotiated]],以及 [[DataChannelId]]。
true
。
[[IsTransferable]]
设置为
false
。
该任务需要在任何通过 在数据通道上接收消息
算法为 channel 排队的任务之前运行。这确保在传输 RTCDataChannel
时不会丢失消息。
返回 channel。
当用户代理要 宣布一个 RTCDataChannel
为
打开状态 时,用户代理 必须 排队一个任务以运行以下
步骤:
如果关联的 RTCPeerConnection
对象的
[[IsClosed]]
槽为
true
,则中止这些步骤。
让 channel 成为要宣布的 RTCDataChannel
对象。
如果 channel.[[ReadyState]]
为
"closing
" 或
"closed
",则中止这些
步骤。
将 channel.[[ReadyState]]
设置为
"open
"。
当要宣布一个 基础数据传输 时(另一个对等方创建了一个 negotiated
未设置或设置为 false),未启动创建过程的对等方的用户代理 必须 排队一个任务以运行以下步骤:
让 connection 成为与 RTCPeerConnection
对象相关联的
基础数据传输。
如果 connection.[[IsClosed]]
为
true
,则中止这些步骤。
创建一个 RTCDataChannel, channel。
让 configuration 成为从另一对等方接收的信息包,作为建立 基础数据传输 过程的一部分,该过程由 WebRTC 数据通道协议规范 [RFC8832] 描述。
初始化 channel.[[DataChannelLabel]]
,
[[Ordered]]
,[[MaxPacketLifeTime]]
,
[[MaxRetransmits]]
,[[DataChannelProtocol]]
,
和 [[DataChannelId]]
内部槽设置为 configuration 中的相应值。
将 channel.[[Negotiated]]
设置为
false
。
附加
channel 到
connection.[[DataChannels]]
。
将 channel.[[ReadyState]]
设置为
"open
"
(但暂时不触发 open
事件)。
datachannel
事件处理程序中开始发送消息,优先于 open
事件被触发。
触发一个事件,名称为 datachannel
,使用 RTCDataChannelEvent
接口
以及 channel
属性设置为
channel 在 connection 上。
RTCDataChannel
对象的 基础数据传输 可以通过运行 关闭程序 以非突然的方式拆除。当发生这种情况时,用户代理 必须 排队一个任务以运行以下步骤:
让 channel 成为 RTCDataChannel
对象,其 基础数据传输 已关闭。
让 connection 成为与 channel 相关联的 RTCPeerConnection
对象。
移除
channel 从 connection.[[DataChannels]]
。
除非该程序是由 channel.close
启动的,否则将
channel.[[ReadyState]]
设置为
"closing
" 并 触发一个事件,名称为
closing
在 channel
上。
运行以下步骤 并行并行:
当一个 RTCDataChannel
对象的 基础数据传输
已被 关闭,用户代理 必须 排队一个任务以运行以下步骤:
让 channel 成为 RTCDataChannel
对象,其
基础数据传输 已关闭。
[[ReadyState]]
为
"closed
",
则中止这些步骤。
将 channel.[[ReadyState]]
设置为
"closed
"。
移除
channel 从 connection.[[DataChannels]]
如果它仍然存在。
如果 传输 是以
错误 关闭的,则 触发一个事件,名称为 error
,使用 RTCErrorEvent
接口,其 errorDetail
属性设置为
"sctp-failure
" 在
channel 上。
给定 value 和 dataHolder 的 RTCDataChannel
转移步骤如下:
如果 value.[[IsTransferable]]
是
false
,抛出一个 DataCloneError
DOMException。
将 dataHolder.[[ReadyState]]
设置为
value.[[ReadyState]]
。
将 dataHolder.[[DataChannelLabel]]
设置为
value.[[DataChannelLabel]]
。
将 dataHolder.[[Ordered]]
设置为 value.[[Ordered]]
。
将 dataHolder.[[MaxPacketLifeTime]]
设置为
value..[[MaxPacketLifeTime]]
将 dataHolder.[[MaxRetransmits]]
设置为
value.[[MaxRetransmits]]
。
将 dataHolder.[[DataChannelProtocol]]
设置为
value.[[DataChannelProtocol]]
。
将 dataHolder.[[Negotiated]]
设置为
value.[[Negotiated]]
。
将 dataHolder.[[DataChannelId]]
设置为
value.[[DataChannelId]]
。
将 value.[[IsTransferable]]
设置为
false
。
将 value.[[ReadyState]]
设置为 "closed"。
给定 dataHolder 和 channel,RTCDataChannel
传输接收步骤如下:
将 channel.[[ReadyState]]
初始化为
dataHolder.[[ReadyState]]
。
将 channel.[[DataChannelLabel]]
初始化为
dataHolder.[[DataChannelLabel]]
。
将 channel.[[Ordered]]
初始化为
dataHolder.[[Ordered]]
。
将 channel.[[MaxPacketLifeTime]]
初始化为
dataHolder.[[MaxPacketLifeTime]]
。
将 channel.[[MaxRetransmits]]
初始化为
dataHolder.[[MaxRetransmits]]
。
将 channel.[[DataChannelProtocol]]
初始化为 dataHolder.[[DataChannelProtocol]]
。
将 channel.[[Negotiated]]
初始化为
dataHolder.[[Negotiated]]
。
将 channel.[[DataChannelId]]
初始化为
dataHolder.[[DataChannelId]]
。
上述步骤不需要传输 [[BufferedAmount]]
,因为它的值将始终等于
0
。
原因是 RTCDataChannel
只能在其 send() 算法 在传输之前未被调用的情况下进行传输。
如果在 底层数据传输 关闭时进行 传输接收步骤,
则 RTCDataChannel
对象将通过运行 宣布数据通道关闭
算法立即关闭。
在某些情况下,用户代理可能无法创建 RTCDataChannel 的 底层数据传输。
例如,数据通道的 id
可能超出
[RFC8831] 在 SCTP 握手中协商的范围。当用户代理确定
RTCDataChannel
的 底层数据传输 无法创建时,用户代理 必须
排队一个任务以执行以下步骤:
让 channel 成为无法为其创建RTCDataChannel
对象的用户代理的
底层数据传输。
将 channel.[[ReadyState]]
设置为
"closed
"。
触发一个事件,名为 error
,使用
RTCErrorEvent
接口,errorDetail
属性设置为 "data-channel-failure
"
在 channel 上。
当接收到通过 RTCDataChannel
传输的消息时,
该消息通过 基础数据传输 进行传输,
其类型为 type,数据为 rawData,用户代理
必须 队列一个任务以运行以下步骤:
让 channel 为用户代理接收到消息的 RTCDataChannel
对象。
让 connection 为与 channel 关联的 RTCPeerConnection
对象。
如果 channel.[[ReadyState]]
不是
"open
",
则中止这些步骤并丢弃 rawData。
执行子步骤,依据 type 和 channel.binaryType
进行切换:
如果 type 表示 rawData 是一个
string
:
让 data 为一个 DOMString,表示将 rawData 解码为 UTF-8 的结果。
如果 type 表示 rawData 是二进制且 binaryType
是 "blob"
:
让 data 为一个新的 Blob
对象,包含 rawData 作为其原始数据源。
如果 type 表示 rawData 是二进制且 binaryType
是 "arraybuffer"
:
让 data 为一个新的 ArrayBuffer
对象,包含 rawData
作为其原始数据源。
触发事件 名称为 message
,使用 MessageEvent
接口,其 origin
属性初始化为 序列化的来源,来自
connection.[[DocumentOrigin]]
,以及 data
属性初始化为 data 在 channel 上。
[Exposed=WindowExposed=(Window,DedicatedWorker), Transferable] interface RTCDataChannel : EventTarget { readonly attribute USVString label; readonly attribute boolean ordered; readonly attribute unsigned short? maxPacketLifeTime; readonly attribute unsigned short? maxRetransmits; readonly attribute USVString protocol; readonly attribute boolean negotiated; readonly attribute unsigned short? id; readonly attribute RTCDataChannelState readyState; readonly attribute unsigned long bufferedAmount; [EnforceRange] attribute unsigned long bufferedAmountLowThreshold; attribute EventHandler onopen; attribute EventHandler onbufferedamountlow; attribute EventHandler onerror; attribute EventHandler onclosing; attribute EventHandler onclose; undefined close(); attribute EventHandler onmessage; attribute BinaryType binaryType; undefined send(USVString data); undefined send(Blob data); undefined send(ArrayBuffer data); undefined send(ArrayBufferView data); };
label
类型为
USVString,只读
label
属性表示一个标签,
可用于区分此 RTCDataChannel
对象与其他
RTCDataChannel
对象的区别。
脚本允许创建多个具有相同标签的 RTCDataChannel
对象。
在获取时,属性 MUST 返回
[[DataChannelLabel]]
槽的值。
ordered
类型为
boolean,只读
ordered
属性如果
RTCDataChannel
是有序的,则返回 true,
如果允许无序传输,则返回 false。
在获取时,属性 MUST 返回
[[Ordered]]
槽的值。
maxPacketLifeTime
类型为
unsigned short,只读,
可空
maxPacketLifeTime
属性返回在不可靠模式下,传输和重传可能发生的时间窗口(以毫秒为单位)。
在获取时,属性 MUST 返回
[[MaxPacketLifeTime]]
槽的值。
maxRetransmits
类型为 unsigned short,
只读,可空
maxRetransmits
属性返回在不可靠模式下尝试的最大重传次数。
在获取时,属性 MUST 返回
[[MaxRetransmits]]
槽的值。
protocol
类型为
USVString,只读
protocol
属性返回此
RTCDataChannel
使用的子协议名称。
在获取时,属性 MUST 返回
[[DataChannelProtocol]]
槽的值。
negotiated
类型为
boolean,只读
negotiated
属性
如果此 RTCDataChannel
是由应用程序协商的,则返回
true,
否则返回 false。 在获取时,属性 MUST 返回
[[Negotiated]]
槽的值。
id
类型为 unsigned
short,只读,可空
id
属性返回此
RTCDataChannel
的 ID。
如果在通道创建时未提供 ID,则初始值为 null;如果 SCTP 传输的 DTLS 角色尚未协商,则返回 null。
否则,将返回由脚本选择或由用户代理根据 [RFC8832] 生成的 ID。
一旦 ID 设置为非空值,它将保持不变。 在获取时,属性 MUST 返回
[[DataChannelId]]
槽的值。
readyState
类型为
RTCDataChannelState
,
只读
readyState
属性
表示 RTCDataChannel
对象的状态。
在获取时,属性 MUST
返回 [[ReadyState]]
槽的值。
bufferedAmount
类型为 unsigned long,
只读
bufferedAmount
属性 MUST 在获取时返回
[[BufferedAmount]]
槽的值。
该属性暴露了使用
send
()
队列的应用数据(UTF-8 文本和二进制数据)的字节数。
尽管数据传输可以 并行进行,返回的值 MUST
NOT 在当前任务返回事件循环之前减少,以防止竞争条件。
该值不包括协议引起的封装开销或操作系统或网络硬件进行的缓冲。
[[BufferedAmount]]
槽的值只会随着
每次调用 send
()
方法而增加,只要
[[ReadyState]]
槽的状态为 "open
";但是,
槽在通道关闭后不会重置为零。当 底层数据传输 从其队列发送数据时,用户代理
MUST 队列一个任务,减少 [[BufferedAmount]]
的字节数。
bufferedAmountLowThreshold
类型为
unsigned long
bufferedAmountLowThreshold
属性设置了
bufferedAmount
被视为低的阈值。当
bufferedAmount
从高于此阈值减少到等于或低于此阈值时,bufferedamountlow
事件会触发。
bufferedAmountLowThreshold
在每个新的
RTCDataChannel
上最初为零,但应用程序可以随时更改其值。
onopen
类型为 EventHandler
open
。
onbufferedamountlow
类型为 EventHandler
bufferedamountlow
。
onerror
类型为 EventHandler
此事件处理程序的事件类型为 RTCErrorEvent
。
errorDetail
包含
"sctp-failure",
sctpCauseCode
包含
SCTP原因码值,并且 message
包含SCTP特定信息,可能带有附加文本。
onclosing
类型为 EventHandler
此事件处理程序的事件类型为 closing
。
onclose
类型为 EventHandler
此事件处理程序的事件类型为 close。
onmessage
类型为 EventHandler
此事件处理程序的事件类型为 message
。
binaryType
类型为
BinaryType
binaryType
属性 必须,在获取时,返回
返回最后设置的值。 在设置时,如果新值
是字符串 当
"blob"
或字符串 "arraybuffer"
,则将ID
L属性设置为此新值。否则,抛出一个 SyntaxError
。
RTCDataChannel
对象被创建时,binaryType
属性
必须 初始化为字符串 ""blob"
arraybuffer
"。
此属性控制二进制数据如何暴露给
脚本。请参见Web Socket的 binaryType
。
close()
关闭 RTCDataChannel
。无论
RTCDataChannel
对象是由
此对等方还是远程对等方创建的,都可以调用此方法。
当调用 close
方法时,用户代理 必须
执行以下步骤:
让 channel 成为即将关闭的 RTCDataChannel
对象。
如果 channel.[[ReadyState]]
是
"closing
" 或
"closed
",则
中止这些步骤。
将 channel.[[ReadyState]]
设置为
"closing
"。
如果尚未启动 关闭程序,则启动它。
send
执行由 send()
算法 描述的步骤,参数类型为 string
对象。
send
send
执行由 send()
算法 描述的步骤,参数类型为 ArrayBuffer
对象。
send
执行由 send()
算法 描述的步骤,参数类型为 ArrayBufferView
对象。
send()
方法被重载以处理不同的数据参数类型。当调用该方法的任何版本时,用户代理 必须 执行以下步骤:
让 channel 成为要发送数据的 RTCDataChannel
对象。
将 channel.[[IsTransferable]]
设置为
false
。
如果 channel.[[ReadyState]]
不是
"open
",则
抛出 一个
InvalidStateError
。
执行与方法参数类型相对应的子步骤:
string
对象:
让 data 成为表示将方法的参数编码为 UTF-8 的字节缓冲区。
Blob
对象:
让 data 成为 Blob
对象所表示的原始数据。
ArrayBuffer
对象:
让 data 成为 ArrayBuffer
对象中存储的数据。
ArrayBufferView
对象:
让 data 成为 ArrayBuffer
对象中
ArrayBufferView
对象所引用的缓冲区部分中存储的数据。
如果 data 的字节大小超过 channel 关联的
RTCSctpTransport
上的
maxMessageSize
的值,抛出 一个
TypeError
。
将 data 排队以便在 channel 的 基础数据传输 上发送。如果
因为没有足够的缓冲空间而无法排队 data,则 抛出 一个
OperationError
。
将 data 的字节大小增加到 [[BufferedAmount]]
槽的值。
WebIDLdictionary RTCDataChannelInit
{
boolean ordered
= true;
[EnforceRange] unsigned short maxPacketLifeTime
;
[EnforceRange] unsigned short maxRetransmits
;
USVString protocol
= "";
boolean negotiated
= false;
[EnforceRange] unsigned short id
;
};
ordered
类型为 boolean,默认值为 true
如果设置为 false,则允许数据无序传递。默认值为 true,保证数据将按顺序传递。
maxPacketLifeTime
类型为 unsigned short
限制通道在未确认的情况下传输或重传数据的时间(以毫秒为单位)。如果超过用户代理支持的最大值,则该值可能会被限制。
maxRetransmits
类型为 unsigned short
限制通道在未成功传递的情况下重传数据的次数。如果超过用户代理支持的最大值,则该值可能会被限制。
protocol
类型为 USVString,默认值为 ""
用于此通道的子协议名称。
negotiated
类型为 boolean,默认值为
false
默认值为 false,告诉用户代理在带内宣布通道,并指示另一方调度相应的 RTCDataChannel
对象。如果设置为
true,应用程序必须协商通道并创建具有相同
id
的 RTCDataChannel
对象。
id
类型为
unsigned short
当 negotiated
为
true 时设置通道 ID。当 negotiated
为
false 时被忽略。
WebIDLenum RTCDataChannelState
{
"connecting
",
"open
",
"closing
",
"closed
"
};
枚举值 | 描述 |
---|---|
connecting
|
用户代理正在尝试建立 基础数据传输。这是一个
|
open
|
基础数据传输已建立, 可以进行通信。 |
closing
|
|
closed
|
datachannel
事件使用
RTCDataChannelEvent
接口。
WebIDL[Exposed=Window]
interface RTCDataChannelEvent
: Event {
constructor
(DOMString type, RTCDataChannelEventInit
eventInitDict);
readonly attribute RTCDataChannel
channel
;
};
RTCDataChannelEvent.constructor()
channel
类型为
RTCDataChannel
,只读
channel
属性
代表与事件关联的 RTCDataChannel
对象。
WebIDLdictionary RTCDataChannelEventInit
: EventInit {
required RTCDataChannel
channel
;
};
channel
类型为 RTCDataChannel
,必需
要通过事件宣布的 RTCDataChannel
对象。
一个 RTCDataChannel
对象 必须 不会被垃圾回收,如果其
[[ReadyState]]
插槽为
"connecting
" 且至少
注册了一个事件监听器用于 open
事件、message
事件、
error
事件、closing
事件,或 close 事件。
[[ReadyState]]
插槽为
"open
" 且
至少注册了一个事件监听器用于
message
事件、error
事件、closing
事件,或
close 事件。
[[ReadyState]]
插槽为
"closing
"
且至少注册了一个事件监听器用于
error
事件,或 close
事件。
底层数据传输 已建立且数据被排队 以进行传输。
本节描述了在 RTCRtpSender
上的接口,以在
RTCPeerConnection
上发送 DTMF
(电话键盘)值。如何将 DTMF 发送到其他对等体的详细信息见 [RFC7874].
点对点 DTMF API 扩展了 RTCRtpSender
接口,如下所述。
WebIDL partial interface RTCRtpSender
{
readonly attribute RTCDTMFSender
? dtmf
;
};
dtmf
类型为 RTCDTMFSender
,只读,
可为 null
当获取时,dtmf
属性返回
[[Dtmf]]
内部槽的值,表示可以用于
发送 DTMF 的 RTCDTMFSender
,如果未设置则为
null
。当一个 RTCRtpSender
的
[[SenderTrack]]
的类型为 "audio"
时,[[Dtmf]]
内部槽被设置。
要 创建一个 RTCDTMFSender,用户代理 必须 执行以下步骤:
让 dtmf 成为一个新创建的 RTCDTMFSender
对象。
让 dtmf 具有一个 [[Duration]] 内部槽。
让 dtmf 具有一个 [[InterToneGap]] 内部槽。
让 dtmf 具有一个 [[ToneBuffer]] 内部槽。
WebIDL[Exposed=Window]
interface RTCDTMFSender
: EventTarget {
undefined insertDTMF
(DOMString tones, optional unsigned long duration = 100, optional unsigned long interToneGap = 70);
attribute EventHandler ontonechange
;
readonly attribute boolean canInsertDTMF
;
readonly attribute DOMString toneBuffer
;
};
ontonechange
类型为 EventHandler
此事件处理程序的事件类型为 tonechange
。
canInsertDTMF
类型为 boolean,只读
RTCDTMFSender
dtmfSender 是否能够发送 DTMF。获取时,用户代理 必须
返回运行 确定是否可以发送
DTMF
的结果,针对 dtmfSender。
toneBuffer
类型为
DOMString,只读
toneBuffer
属性
必须 返回待播放的音调列表。有关此列表的语法、内容和解释,请参见 insertDTMF
。
insertDTMF
RTCDTMFSender
对象的 insertDTMF
方法用于发送 DTMF
音调。
tones 参数被视为一系列字符。字符 0 到 9、A 到 D、# 和 * 生成相应的 DTMF 音调。字符 a 到 d 必须 在输入时转换为大写,并且等同于 A 到 D。如 [RTCWEB-AUDIO] 第 3 节所述,必须支持字符 0 到 9、A 到 D、# 和 *。字符 ',' 必须 被支持,并表示在处理 tones 参数中的下一个字符之前延迟 2 秒。所有其他字符(仅限于这些字符)必须 被视为 无法识别。
duration 参数表示每个通过 tones 参数传递的字符的持续时间(毫秒)。持续时间不得超过 6000 毫秒或少于 40 毫秒。默认持续时间为每个音调 100 毫秒。
interToneGap 参数表示音调之间的间隔(毫秒)。用户代理将其限制为至少 30 毫秒,至多 6000 毫秒。默认值为 70 毫秒。
浏览器 可能 增加 duration 和 interToneGap 的时间,以使 DTMF 开始和停止的时间与 RTP 数据包的边界对齐,但 不得 增加其中任何一个超过单个 RTP 音频数据包的持续时间。
当调用 insertDTMF
()
方法时,用户代理 必须 执行以下步骤:
RTCRtpSender
。
让 transceiver 成为与 sender 关联的 RTCRtpTransceiver
对象。
RTCDTMFSender
。
false
,则 抛出 一个 InvalidStateError
。
unrecognized
字符,则 抛出 一个 InvalidCharacterError
。
[[ToneBuffer]]
槽设置为
tones。
[[Duration]]
设置为
duration 的值。
[[InterToneGap]]
设置为
interToneGap 的值。
[[Duration]]
设置为 40 毫秒。
[[Duration]]
设置为 6000 毫秒。
[[InterToneGap]]
设置为 30 毫秒。
[[InterToneGap]]
设置为 6000 毫秒。
sendrecv
"
或 "sendonly
"false
,则中止这些步骤。
[[ToneBuffer]]
插槽
包含空字符串,触发一个事件,名为 tonechange
使用
RTCDTMFToneChangeEvent
接口,其
tone
属性设置为空字符串,位于 RTCDTMFSender
对象
并终止这些步骤。
[[ToneBuffer]]
槽中移除第一个字符,并让该字符为 tone。
","
,则在相关的 RTP 媒体流上延迟发送音调 2000 毫秒,并排队一个将在
2000 毫秒后执行的任务,运行 DTMF 播放任务步骤。
","
,则开始在相关的 RTP 媒体流上播放 tone,持续
[[Duration]]
毫秒,使用适当的编解码器,然后排队一个将在 [[Duration]]
+ [[InterToneGap]]
毫秒后执行的任务,运行 DTMF 播放任务步骤。
tonechange
使用 RTCDTMFToneChangeEvent
接口,tone
属性设置为 tone 的值,使用 RTCDTMFSender
对象。
由于 insertDTMF
会替换音调缓冲区,因此,为了
添加正在播放的 DTMF 音调,必须调用
insertDTMF
,并提供一个字符串,该字符串包含
剩余音调(存储在 [[ToneBuffer]]
槽中)和新的音调连接在一起。调用 insertDTMF
,并提供空的音调参数可以用于
取消所有排队将在当前播放的音调之后播放的音调。
要 确定是否可以发送 DTMF 针对一个 RTCDTMFSender
实例 dtmfSender,用户代理 必须 排队一个任务,该任务运行 运行
以下步骤:
RTCRtpSender
相关联的
dtmfSender。
RTCRtpTransceiver
相关联的
sender。
RTCPeerConnection
相关联的
transceiver。
RTCPeerConnectionState
不是
"connected
" 则返回
false
。
[[Stopping]]
为
true
则返回 false
。
[[SenderTrack]]
为 null
则返回 false
。
[[CurrentDirection]]
既不是
"sendrecv
" 也不是
"sendonly
"
则返回 false
。
[[SendEncodings]]
[0]
.active
为 false
则返回 false
。
"audio/telephone-event"
谈判的编解码器可用于此
sender 发送,则返回 false
。
true
。
tonechange
事件使用 RTCDTMFToneChangeEvent
接口。
WebIDL[Exposed=Window]
interface RTCDTMFToneChangeEvent
: Event {
constructor
(DOMString type, optional RTCDTMFToneChangeEventInit
eventInitDict = {});
readonly attribute DOMString tone
;
};
RTCDTMFToneChangeEvent.constructor()
tone
类型为 DOMString,只读
tone
属性包含
刚开始播放的音调字符(包括 ","
),
(参见 insertDTMF
)。
如果值为空字符串,则表示 [[ToneBuffer]]
插槽是空字符串,
先前的音调已经完成播放。
WebIDL dictionary RTCDTMFToneChangeEventInit
: EventInit {
DOMString tone
= "";
};
tone
类型为 DOMString,默认为 ""
tone
属性包含
刚开始播放的音调字符(包括 ","
),
(参见 insertDTMF
)。
如果值为空字符串,则表示 [[ToneBuffer]]
插槽是
空字符串,先前的音调已经完成播放。
基本统计模型是浏览器维护一组 被监测对象 的统计信息,形式为 统计对象。
一组相关的对象可以通过 选择器
引用。例如,选择器可以是
MediaStreamTrack
。要使轨道成为有效选择器,必须
是
一个由 MediaStreamTrack
发送或接收的
RTCPeerConnection
对象
上发出的统计请求。调用的 Web 应用程序提供选择器给
getStats
()
方法,浏览器会根据 统计选择算法 产生与选择器相关的统计信息。
请注意,该算法会考虑选择器的发送方或接收方。
返回的 统计对象 设计为
使重复查询可以通过 RTCStats
id
字典成员链接。因此,Web 应用程序可以
在给定的时间段内进行测量,通过在该时间段开始和结束时请求测量。
除了少数例外,被监测对象 一旦创建,
就会在其相关的 RTCPeerConnection
存在期间。这
确保统计信息可以在
getStats
()
的结果中获得,即使相关的对等连接被 close
。
只有少数被监测对象的 生命周期较短。 这些对象的统计信息在随后的 getStats() 结果中不再可用。 [WEBRTC-STATS] 中的对象描述 说明了何时删除这些被监测对象。
统计 API 扩展了 RTCPeerConnection
接口,如下所述。
WebIDL partial interface RTCPeerConnection
{
Promise<RTCStatsReport
> getStats
(optional MediaStreamTrack? selector = null);
};
getStats
收集给定 选择器 的统计信息,并异步报告结果。
当 getStats
()
方法被调用时,用户代理 必须 执行以下步骤:
让 selectorArg 为方法的第一个参数。
让 connection 为调用该方法的 RTCPeerConnection
对象。
如果 selectorArg 为 null
,则让 selector 为
null
。
如果 selectorArg 为 MediaStreamTrack
,则让
selector 为
RTCRtpSender
或
RTCRtpReceiver
,该对象在
connection 上,其
track
属性
匹配 selectorArg。如果没有符合该条件的发送者或接收者,或者如果有多个符合该条件的发送者或接收者,则返回一个被拒绝的新创建的 异常 InvalidAccessError
的承诺。
让 p 为一个新的承诺。
按照以下步骤 并行执行:
根据 selector 收集由 统计选择算法 指示的统计信息。
解析
p 为结果 RTCStatsReport
对象,包含收集到的统计信息。
返回 p。
getStats
()
方法返回成功结果,形式为 RTCStatsReport
对象。RTCStatsReport
对象是一个字符串与被检查对象的映射(在 RTCStats
实例中的 id
属性),以及它们对应的 RTCStats
-派生字典的映射。
一个 RTCStatsReport
可能由几个 RTCStats
-派生字典组成,每个字典报告一个底层对象的统计信息,该对象在实现中被认为与 选择器 相关。通过对某种类型的所有统计信息进行求和,可以得到该 选择器 的总和;例如,如果一个 RTCRtpSender
使用多个 SSRC 通过网络传输其轨道,则
RTCStatsReport
可能包含一个
RTCStats
-派生字典,每个 SSRC 对应一个字典(可通过
ssrc
统计属性的值进行区分)。
一个 RTCStats
字典表示通过检查特定的 被监测对象 构建的 统计对象。RTCStats
字典是一个基本类型,它指定了一组默认属性,例如 timestamp
和
type
。特定统计信息通过扩展 RTCStats
字典而添加。
注意,虽然统计名称是标准化的,但任何给定的实现可能使用实验性值或尚未为 Web 应用程序所知的值。因此,应用程序 必须 准备处理未知的统计信息。
统计数据需要彼此同步,以便在计算中产生合理的值;例如,如果 bytesSent
和
packetsSent
都被报告,它们都需要在同一时间间隔内报告,以便可以计算“平均数据包大小”为“字节 / 数据包”——如果间隔不同,将会产生错误。因此,实现 必须
为所有统计信息返回同步值,在 RTCStats
派生字典中。
WebIDLdictionary RTCStats
{
required DOMHighResTimeStamp timestamp
;
required RTCStatsType type
;
required DOMString id
;
};
RTCStats
成员
timestamp
类型 DOMHighResTimeStamp
与此对象相关联的
时间戳以
,
类型为
timestamp
DOMHighResTimeStamp
表示,
时间是相对于 UNIX 纪元(1970 年 1 月 1 日)
[HIGHRES-TIME],
定义为
Performance
.timeOrigin
UTC
+
Performance
.now
()
收集信息时的值。 对于来自远程源(例如接收到的 RTCP 数据包)的统计信息,
timestamp
表示信息到达本地终端的时间。远程时间戳可以在
RTCStats
衍生字典中的额外字段中找到(如果适用)。
type
类型 RTCStatsType
此对象的类型。
id
类型 DOMString
一个与生成此RTCStats
对象的被检查对象相关联的唯一id
。两个RTCStats
对象,如果它们是从两个不同的RTCStatsReport
对象中提取的,必须具有相同的id,如果它们是通过检查同一基础对象生成的。
统计 id 不得 可预测。这样可以防止应用程序依赖于特定用户代理生成 id 的方式,因为这会阻止应用程序通过 id 获取统计对象,除非它们已经读取了该特定统计对象的 id。
用户代理可以自由选择任何格式的 id,只要它满足上述要求。
用户代理可以通过使用唯一于对等连接的哈希函数将可预测生成的字符串转换为不可预测的字符串。这允许实现内部使用可预测的 id,从而可能更容易确保在 getStats() 调用中统计对象具有稳定的 id。
RTCStatsType
的有效值集合,以及它们所指示的从 RTCStats 派生的字典,记录在 [WEBRTC-STATS] 中。
统计选择算法 如下:
RTCStatsReport
。
null
,
收集整个 connection 的统计数据,将其添加到
result,并返回 result,然后中止这些步骤。
RTCRtpSender
,收集统计数据并将以下对象添加到
result:
RTCOutboundRtpStreamStats
对象。
RTCOutboundRtpStreamStats
添加。
RTCRtpReceiver
,收集统计数据并将以下对象添加到
result:
RTCInboundRtpStreamStats
对象。
RTCInboundRtpStreamStats
添加。
在 [WEBRTC-STATS] 中列出的统计数据旨在覆盖广泛的用例。并非所有统计数据都必须由每个 WebRTC 实现来支持。
实现 必须 支持生成以下 type
的统计数据,当相应对象存在于 RTCPeerConnection
上时,并且在有效的情况下,除了在 RTCStats
字典中定义的通用字段外,还包括列出的字段:
实现 MAY 支持生成在 [WEBRTC-STATS] 中定义的任何其他统计数据,并且 MAY 生成未记录的统计数据。
考虑一个用户经历糟糕声音的情况,应用程序想要确定问题是否由数据包丢失引起。以下示例代码可能会被使用:
async function gatherStats(pc) {
try {
const [sender] = pc.getSenders();
const baselineReport = await sender.getStats();
await new Promise(resolve => setTimeout(resolve, aBit)); // 等待一会儿
const currentReport = await sender.getStats();
// 比较当前报告中的元素与基线
for (const now of currentReport.values()) {
if (now.type != 'outbound-rtp') continue;
// 从基线报告中获取相应的统计数据
const base = baselineReport.get(now.id);
if (!base) continue;
const remoteNow = currentReport.get(now.remoteId);
const remoteBase = baselineReport.get(base.remoteId);
const packetsSent = now.packetsSent - base.packetsSent;
const packetsReceived = remoteNow.packetsReceived -
remoteBase.packetsReceived;
const fractionLost = (packetsSent - packetsReceived) / packetsSent;
if (fractionLost > 0.3) {
// 如果丢失比例大于 0.3,我们可能找到了罪魁祸首
}
}
} catch (err) {
console.error(err);
}
}
MediaStreamTrack
接口,如 [GETUSERMEDIA]
规范中所定义,通常表示音频或视频的数据流。一个或多个 MediaStreamTrack
可以被收集在一个 MediaStream
中(严格来说,按照 [GETUSERMEDIA] 的定义,一个 MediaStream
可以包含零个或多个 MediaStreamTrack
对象)。
一个 MediaStreamTrack
可以扩展为表示来自或发送到远程对等方的媒体流(而不仅仅是本地摄像头等)。使这种能力在 MediaStreamTrack
对象上可用的扩展将在本节中描述。媒体如何传输到对等方将在 [RFC8834], [RFC7874] 和
[RFC8835] 中描述。
发送到另一对等方的 MediaStreamTrack
在接收方将只显示为一个 MediaStreamTrack
。对等方被定义为支持本规范的用户代理。此外,发送端应用程序可以指示 MediaStream
对象的成员。接收方将相应创建(如果尚未存在)并填充相应的 MediaStream
对象。
如本文档前面所述,应用程序可以使用 RTCRtpSender
和 RTCRtpReceiver
来获得对 MediaStreamTrack
的传输和接收的更细粒度控制。
通道是媒体捕获与流规范中考虑的最小单元。通道旨在作为 RTP 载荷类型一起编码进行传输。编解码器所需的所有通道 MUST 在同一个 MediaStreamTrack
中,编解码器 SHOULD
能够编码或丢弃轨道中的所有通道。
给定 MediaStreamTrack
的输入和输出的概念在通过网络传输的 MediaStreamTrack
对象中也适用。由 RTCPeerConnection
对象创建的 MediaStreamTrack
对象(如本文档前面所述)将以来自远程对等方接收到的数据为输入。同样,来自本地源(例如通过 [GETUSERMEDIA] 的摄像头)的 MediaStreamTrack
将具有一个输出,表示如果该对象与 RTCPeerConnection
对象一起使用,则发送到远程对等方的内容。
复制 MediaStream
和
MediaStreamTrack
对象的概念,如 [GETUSERMEDIA]
中所述也适用。此功能可以用于例如在视频会议场景中在本地监视器上显示用户的摄像头和麦克风的本地视频,而只将音频传输到远程对等方(例如响应用户使用“视频静音”功能)。将不同的 MediaStreamTrack
对象组合成新的 MediaStream
对象在某些情况下是有用的。
在本文档中,我们仅指定与 RTCPeerConnection
一起使用时相关的以下对象的方面。有关使用
MediaStream
和
MediaStreamTrack
的一般信息,请参阅 [GETUSERMEDIA]
文档的原始定义。
id
属性在 MediaStream
中指定,返回一个唯一的
id,用于识别此流,以便在 RTCPeerConnection
API 的远程端进行识别。
当创建一个 MediaStream
来表示从远程对等方获取的流时,id
属性将从远程源提供的信息进行初始化。
id
的 MediaStream
对象是唯一的,取决于流的源,但这并不意味着不可能出现重复。例如,来自一个用户代理的本地生成流的轨道可以通过 RTCPeerConnection
发送给远程对等方,然后以相同方式发送回原始用户代理,在这种情况下,原始用户代理将拥有多个具有相同 id 的流(一个是本地生成的,另一个是从远程对等方接收的)。
MediaStreamTrack
对象在非本地媒体源情况下(RTP 源,正如每个与 MediaStreamTrack
相关的 RTCRtpReceiver
)始终强引用其 MediaStream
。
每当一个 RTCRtpReceiver
接收到的 RTP 源
的对应 MediaStreamTrack
被静音但未结束时,
且 [[Receptive]]
插槽的 RTCRtpTransceiver
对象的
RTCRtpReceiver
是该对象的成员,
且该插槽的值为 true
时,必须 排队一个任务以
设置 对应的
MediaStreamTrack
的静音状态为 false
。
当一个由 RTCRtpReceiver
接收到的 RTP
源媒体流的
一个 SSRC 因接收到 BYE 或超时而被移除时,它 必须 排队一个任务以
设置 相应的
MediaStreamTrack
的静音状态为 true
。请注意,
setRemoteDescription
也可以导致
设置
track
的静音状态为 true
。
过程 添加轨道、移除轨道 和 设置轨道的静音状态 在 [GETUSERMEDIA] 中指定。
当由 RTCRtpReceiver
receiver 生成的 MediaStreamTrack
轨道已 结束
[GETUSERMEDIA](例如通过调用 receiver.track
.stop
),用户代理
可以 选择释放为接收流分配的资源,例如关闭 receiver 的解码器。
约束和可约束属性的概念,包括 MediaTrackConstraints
(MediaStreamTrack
.getConstraints()
,MediaStreamTrack
.applyConstraints()
),以及 MediaTrackSettings
(MediaStreamTrack
.getSettings()
)在 [GETUSERMEDIA]
中进行了概述。然而,由对等连接提供的轨道的可约束属性与通过 getUserMedia()
提供的不同;从 远程源 提供的 MediaStreamTrack
的约束和设置在此处定义。远程轨道的设置代表最近接收到的帧。
MediaStreamTrack
.getCapabilities()
必须 始终返回空集合,而 MediaStreamTrack
.applyConstraints()
必须 始终因此处定义的约束而拒绝。
下列可约束属性被定义为适用于从 远程源 来源的音频 MediaStreamTrack
:
属性名称 | 值 | 备注 |
---|---|---|
宽度 |
ConstrainULong
|
作为设置,这是最新接收到的帧的宽度(以像素为单位)。 |
高度 |
ConstrainULong
|
作为设置,这是最新接收到的帧的高度(以像素为单位)。 |
帧率 |
ConstrainDouble
|
作为设置,这是基于最近接收到的帧的帧率估计。 |
宽高比 |
ConstrainDouble
|
作为设置,这是最新帧的宽高比;即宽度(以像素为单位)除以高度(以像素为单位)的值,精确到小数点后十位。 |
本文档未定义适用于从 远程源 来源的音频 MediaStreamTrack
的可约束属性。
本节为非规范性内容。
当两个对等体决定要建立连接时,他们都要经过这些步骤。STUN/TURN 服务器配置描述了他们可以使用的服务器,以获取诸如公共 IP 地址或设置 NAT 穿越之类的信息。他们还必须使用最初用于建立通信的同一带外机制向对方发送信令通道的数据。
const signaling = new SignalingChannel(); // 处理 JSON.stringify/parse
const constraints = {audio: true, video: true};
const configuration = {iceServers: [{urls: 'stun:stun.example.org'}]};
const pc = new RTCPeerConnection(configuration);
// 将任何 ice 候选发送给另一个对等体
pc.onicecandidate = ({candidate}) => signaling.send({candidate});
// 让“negotiationneeded”事件触发报价生成
pc.onnegotiationneeded = async () => {
try {
await pc.setLocalDescription();
// 将报价发送给另一个对等体
signaling.send({description: pc.localDescription});
} catch (err) {
console.error(err);
}
};
pc.ontrack = ({track, streams}) => {
// 一旦收到远程轨道的媒体,便在远程视频元素中显示
track.onunmute = () => {
// 如果已经设置了 srcObject,则不要再次设置。
if (remoteView.srcObject) return;
remoteView.srcObject = streams[0];
};
};
// 调用 start() 以启动
function start() {
addCameraMic();
}
// 将相机和麦克风添加到连接
async function addCameraMic() {
try {
// 获取本地流,在自视图中显示并添加到发送流中
const stream = await navigator.mediaDevices.getUserMedia(constraints);
for (const track of stream.getTracks()) {
pc.addTrack(track, stream);
}
selfView.srcObject = stream;
} catch (err) {
console.error(err);
}
}
signaling.onmessage = async ({data: {description, candidate}}) => {
try {
if (description) {
await pc.setRemoteDescription(description);
// 如果我们收到了报价,需要回复一个应答
if (description.type == 'offer') {
if (!selfView.srcObject) {
// 阻止在权限上的协商(不推荐在生产代码中使用)
await addCameraMic();
}
await pc.setLocalDescription();
signaling.send({description: pc.localDescription});
}
} else if (candidate) {
await pc.addIceCandidate(candidate);
}
} catch (err) {
console.error(err);
}
};
当两个对等体决定要建立连接并希望将 ICE、DTLS 和媒体连接“预热”,使其能够立即发送和接收媒体时,他们都要经过这些步骤。
const signaling = new SignalingChannel(); // 处理 JSON.stringify/parse
const constraints = {audio: true, video: true};
const configuration = {iceServers: [{urls: 'stun:stun.example.org'}]}};
let pc;
let audio;
let video;
let started = false;
// 在媒体准备好之前调用 warmup(),以预热 ICE、DTLS 和媒体。
async function warmup(isAnswerer) {
pc = new RTCPeerConnection(configuration);
if (!isAnswerer) {
audio = pc.addTransceiver('audio');
video = pc.addTransceiver('video');
}
// 将任何 ice 候选发送给另一个对等体
pc.onicecandidate = ({candidate}) => signaling.send({candidate});
// 让“negotiationneeded”事件触发报价生成
pc.onnegotiationneeded = async () => {
try {
await pc.setLocalDescription();
// 将报价发送给另一个对等体
signaling.send({description: pc.localDescription});
} catch (err) {
console.error(err);
}
};
pc.ontrack = async ({track, transceiver}) => {
try {
// 一旦远程轨道的媒体到达,在视频元素中显示它
event.track.onunmute = () => {
// 如果已经设置了 srcObject,则不要再次设置。
if (!remoteView.srcObject) {
remoteView.srcObject = new MediaStream();
}
remoteView.srcObject.addTrack(track);
}
if (isAnswerer) {
if (track.kind == 'audio') {
audio = transceiver;
} else if (track.kind == 'video') {
video = transceiver;
}
if (started) await addCameraMicWarmedUp();
}
} catch (err) {
console.error(err);
}
};
try {
// 获取本地流,在自视图中显示并添加到发送流中
selfView.srcObject = await navigator.mediaDevices.getUserMedia(constraints);
if (started) await addCameraMicWarmedUp();
} catch (err) {
console.error(err);
}
}
// 在 warmup() 后调用 start() 以开始从两端传输媒体
function start() {
signaling.send({start: true});
signaling.onmessage({data: {start: true}});
}
// 向已经预热的连接添加相机和麦克风
async function addCameraMicWarmedUp() {
const stream = selfView.srcObject;
if (audio && video && stream) {
await Promise.all([
audio.sender.replaceTrack(stream.getAudioTracks()[0]),
video.sender.replaceTrack(stream.getVideoTracks()[0]),
]);
}
}
signaling.onmessage = async ({data: {start, description, candidate}}) => {
if (!pc) warmup(true);
try {
if (start) {
started = true;
await addCameraMicWarmedUp();
} else if (description) {
await pc.setRemoteDescription(description);
// 如果我们得到了报价,我们需要回复一个答案
if (description.type == 'offer') {
await pc.setLocalDescription();
signaling.send({description: pc.localDescription});
}
} else {
await pc.addIceCandidate(candidate);
}
} catch (err) {
console.error(err);
}
};
客户端希望向服务器发送多个 RTP 编码(并行广播)。
const signaling = new SignalingChannel(); // 处理 JSON.stringify/parse
const constraints = {audio: true, video: true};
const configuration = {'iceServers': [{'urls': 'stun:stun.example.org'}]}};
let pc;
// 调用 start() 以启动
async function start() {
pc = new RTCPeerConnection(configuration);
// 让“negotiationneeded”事件触发报价生成
pc.onnegotiationneeded = async () => {
try {
await pc.setLocalDescription();
// 将报价发送给另一个对等体
signaling.send({description: pc.localDescription});
} catch (err) {
console.error(err);
}
};
try {
// 获取本地流,在自视图中显示并添加到发送流中
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},
{rid: 'h', scaleResolutionDownBy: 2.0},
{rid: 'f'},
]
});
} catch (err) {
console.error(err);
}
}
signaling.onmessage = async ({data: {description, candidate}}) => {
try {
if (description) {
await pc.setRemoteDescription(description);
// 如果我们得到了报价,我们需要回复一个答案
if (description.type == 'offer') {
await pc.setLocalDescription();
signaling.send({description: pc.localDescription});
}
} else if (candidate) {
await pc.addIceCandidate(candidate);
}
} catch (err) {
console.error(err);
}
};
此示例展示了如何创建一个 RTCDataChannel
对象,并执行连接
渠道所需的报价/应答交换。RTCDataChannel
在一个简单的聊天应用程序中使用,
该应用程序使用 input
字段接收用户输入。
const signaling = new SignalingChannel(); // 处理 JSON.stringify/parse
const configuration = {iceServers: [{urls: 'stun:stun.example.org'}]}};
let pc, channel;
// 调用 start() 以启动
function start() {
pc = new RTCPeerConnection(configuration);
// 将任何 ice 候选者发送到另一个对等体
pc.onicecandidate = ({candidate}) => signaling.send({candidate});
// 让“negotiationneeded”事件触发报价生成
pc.onnegotiationneeded = async () => {
try {
await pc.setLocalDescription();
// 将报价发送给另一个对等体
signaling.send({description: pc.localDescription});
} catch (err) {
console.error(err);
}
};
// 创建数据通道并使用“negotiated”模式设置聊天
channel = pc.createDataChannel('chat', {negotiated: true, id: 0});
channel.onopen = () => input.disabled = false;
channel.onmessage = ({data}) => showChatMessage(data);
input.onkeydown = ({key}) => {
if (key != 'Enter') return;
channel.send(input.value);
}
}
signaling.onmessage = async ({data: {description, candidate}}) => {
if (!pc) start();
try {
if (description) {
await pc.setRemoteDescription(description);
// 如果我们得到了报价,我们需要回复一个答案
if (description.type == 'offer') {
await pc.setLocalDescription();
signaling.send({description: pc.localDescription});
}
} else if (candidate) {
await pc.addIceCandidate(candidate);
}
} catch (err) {
console.error(err);
}
};
这展示了两个浏览器之间可能的通话流程示例。 此示例并未展示获取本地媒体的程序或每个回调,但试图将内容简化到仅显示关键事件和消息。
示例假设 sender 是一个 RTCRtpSender
。
发送 DTMF 信号 "1234",每个音调持续 500 毫秒:
if (sender.dtmf.canInsertDTMF) {
const duration = 500;
sender.dtmf.insertDTMF('1234', duration);
} else {
console.log('DTMF 功能不可用');
}
发送 DTMF 信号 "123",并在发送 "2" 后中止。
async function sendDTMF() {
if (sender.dtmf.canInsertDTMF) {
sender.dtmf.insertDTMF('123');
await new Promise(r => sender.dtmf.ontonechange = e => e.tone == '2' && r());
// 清空缓冲区以避免在 "2" 之后播放任何音调
sender.dtmf.insertDTMF('');
} else {
console.log('DTMF 功能不可用');
}
}
发送 DTMF 信号 "1234",并在音调播放时使用
lightKey(key)
点亮活动键(假设 lightKey("")
将熄灭所有键):
const wait = ms => new Promise(resolve => setTimeout(resolve, ms));
if (sender.dtmf.canInsertDTMF) {
const duration = 500; // 毫秒
sender.dtmf.insertDTMF(sender.dtmf.toneBuffer + '1234', duration);
sender.dtmf.ontonechange = async ({tone}) => {
if (!tone) return;
lightKey(tone); // 播放开始时点亮键
await wait(duration);
lightKey(''); // 音调持续后关闭灯光
};
} else {
console.log('DTMF 功能不可用');
}
在音调播放开始之前和期间追加到音调缓冲区始终是安全的。此示例在音调播放开始之前和期间追加。
if (sender.dtmf.canInsertDTMF) {
sender.dtmf.insertDTMF('123');
// 在播放开始之前向音调缓冲区添加更多音调
sender.dtmf.insertDTMF(sender.dtmf.toneBuffer + '456');
sender.dtmf.ontonechange = ({tone}) => {
// 当播放开始时添加更多音调
if (tone != '1') return;
sender.dtmf.insertDTMF(sender.dtmf.toneBuffer + '789');
};
} else {
console.log('DTMF 功能不可用');
}
发送 1 秒的 "1" 音调,然后发送 2 秒的 "2" 音调:
if (sender.dtmf.canInsertDTMF) {
sender.dtmf.ontonechange = ({tone}) => {
if (tone == '1') {
sender.dtmf.insertDTMF(sender.dtmf.toneBuffer + '2', 2000);
}
};
sender.dtmf.insertDTMF(sender.dtmf.toneBuffer + '1', 1000);
} else {
console.log('DTMF 功能不可用');
}
完美协商是一种推荐的模式,用于透明地管理协商,将这一不对称任务抽象化,避免与应用程序的其他部分混淆。与单方始终作为发起者相比,这种模式的优势在于,它允许应用程序同时操作两个对等连接对象,而不会出现“stable
”状态之外的信号碰撞。应用程序的其他部分可以使用所有修改方法和属性,而无需担心信号状态竞态。
它为两个对等方指定了不同的角色,并规定了解决它们之间信号冲突的行为:
有礼的对等方使用回滚来避免与传入的提议发生冲突。
无礼的对等方在与其自己的提议发生冲突时忽略传入的提议。
这样,它们以一种不会导致死锁的方式管理应用程序的其余部分的信号。示例假设一个 polite 布尔变量指示指定的角色:
const signaling = new SignalingChannel(); // 处理 JSON.stringify/parse
const constraints = {audio: true, video: true};
const configuration = {iceServers: [{urls: 'stun:stun.example.org'}]};
const pc = new RTCPeerConnection(configuration);
// 在任一端调用 start() 以将摄像头和麦克风添加到连接中
async function start() {
try {
const stream = await navigator.mediaDevices.getUserMedia(constraints);
for (const track of stream.getTracks()) {
pc.addTrack(track, stream);
}
selfView.srcObject = stream;
} catch (err) {
console.error(err);
}
}
pc.ontrack = ({track, streams}) => {
// 一旦接收到远程轨道的媒体,在远程视频元素中显示它
track.onunmute = () => {
// 如果 srcObject 已经设置,则不要再次设置。
if (remoteView.srcObject) return;
remoteView.srcObject = streams[0];
};
};
// - 完美协商逻辑,与应用程序的其他部分分开 ---
// 记录一些协商状态以防止竞态和错误
let makingOffer = false;
let ignoreOffer = false;
let isSettingRemoteAnswerPending = false;
// 将任何 ice 候选发送给另一个对等方
pc.onicecandidate = ({candidate}) => signaling.send({candidate});
// 让 "negotiationneeded" 事件触发提议生成
pc.onnegotiationneeded = async () => {
try {
makingOffer = true;
await pc.setLocalDescription();
signaling.send({description: pc.localDescription});
} catch (err) {
console.error(err);
} finally {
makingOffer = false;
}
};
signaling.onmessage = async ({data: {description, candidate}}) => {
try {
if (description) {
// 在我们忙于处理 SRD(answer)时,提议可能会进来。
// 在这种情况下,我们将在处理提议时处于 "stable" 状态
// 因此,现在可以安全地将其链接到我们的操作链。
const readyForOffer =
!makingOffer &&
(pc.signalingState == "stable" || isSettingRemoteAnswerPending);
const offerCollision = description.type == "offer" && !readyForOffer;
ignoreOffer = !polite && offerCollision;
if (ignoreOffer) {
return;
}
isSettingRemoteAnswerPending = description.type == "answer";
await pc.setRemoteDescription(description); // SRD 根据需要回滚
isSettingRemoteAnswerPending = false;
if (description.type == "offer") {
await pc.setLocalDescription();
signaling.send({description: pc.localDescription});
}
} else if (candidate) {
try {
await pc.addIceCandidate(candidate);
} catch (err) {
if (!ignoreOffer) throw err; // 抑制被忽略提议的候选错误
}
}
} catch (err) {
console.error(err);
}
}
请注意,这对时序敏感,并且故意使用 setLocalDescription
(不带参数)和
setRemoteDescription
(隐式回滚)来避免与正在处理的其他信号消息发生竞态。
ignoreOffer 变量是必要的,因为无礼一方的 RTCPeerConnection
对象从未被告知忽略的提议。因此,我们必须抑制来自此类提议的传入候选的错误。
一些操作会抛出或触发 RTCError
。这是一种扩展
DOMException
的错误,携带额外的 WebRTC 特定信息。
WebIDL[Exposed=Window]
interface RTCError
: DOMException {
constructor
(RTCErrorInit
init, optional DOMString message = "");
readonly attribute RTCErrorDetailType
errorDetail
;
readonly attribute long? sdpLineNumber
;
readonly attribute long? sctpCauseCode
;
readonly attribute unsigned long? receivedAlert
;
readonly attribute unsigned long? sentAlert
;
};
errorDetail
类型为 RTCErrorDetailType,只读
WebRTC特定的错误代码,表示发生的错误类型。
sdpLineNumber
类型为 long,只读,可为null
如果 errorDetail
是
"sdp-syntax-error
",
则这是检测到错误的行号(第一行的行号为1)。
sctpCauseCode
类型为 long,只读,可为null
如果 errorDetail
是
"sctp-failure
",
则这是失败的SCTP协商的SCTP原因代码。
receivedAlert
类型为 unsigned long,只读,可为null
如果 errorDetail
是
"dtls-failure
" 且接收到
一个致命的 DTLS 警报,
这是接收到的 DTLS 警报的值。
sentAlert
类型为 unsigned
long,只读,可为null
如果 errorDetail
是
"dtls-failure
" 并且发送了
一个致命的 DTLS 警报,
这是发送的 DTLS 警报的值。
在 RTCError
中定义的所有属性因缺乏实现而被标记为有风险(errorDetail
,
sdpLineNumber
, sctpCauseCode
, receivedAlert
和
sentAlert
)。这不包括从
DOMException
继承的属性。
WebIDLdictionary RTCErrorInit
{
required RTCErrorDetailType
errorDetail
;
long sdpLineNumber
;
long sctpCauseCode
;
unsigned long receivedAlert
;
unsigned long sentAlert
;
};
errorDetail
、sdpLineNumber
、sctpCauseCode
、
receivedAlert
和 sentAlert
成员的 RTCErrorInit
与 RTCError
中相同名称的属性具有相同的定义。
WebIDLenum RTCErrorDetailType
{
"data-channel-failure
",
"dtls-failure
",
"fingerprint-failure
",
"sctp-failure
",
"sdp-syntax-error
",
"hardware-encoder-not-available
",
"hardware-encoder-error
"
};
枚举值 | 描述 |
---|---|
data-channel-failure
|
数据通道已失败。 |
dtls-failure
|
DTLS协商已失败或连接因致命错误而终止。message
包含有关错误性质的信息。如果收到致命的DTLS警报,receivedAlert
属性设置为收到的DTLS警报的值。如果发送了致命的DTLS警报,则sentAlert 属性
设置为发送的DTLS警报的值。
|
fingerprint-failure
|
RTCDtlsTransport 的远程
证书与SDP中提供的指纹不匹配。如果远程对等方无法根据提供的
指纹与本地证书匹配,则不会生成此错误。相反,可能会收到来自远程对等方的
“bad_certificate”(42)DTLS警报,导致生成
"dtls-failure "。
|
sctp-failure
|
SCTP协商已失败或连接因致命错误而终止。sctpCauseCode
属性设置为SCTP原因代码。
|
sdp-syntax-error
|
SDP语法无效。sdpLineNumber
属性设置为检测到语法错误的SDP中的行号。
|
hardware-encoder-not-available
|
所请求操作所需的硬件编码器资源不可用。 |
hardware-encoder-error
|
硬件编码器不支持提供的参数。 |
RTCErrorEvent
接口用于
当发生 RTCError
时作为事件触发:
WebIDL[Exposed=Window]
interface RTCErrorEvent
: Event {
constructor
(DOMString type, RTCErrorEventInit
eventInitDict);
[SameObject] readonly attribute RTCError
error
;
};
constructor()
构造一个新的 RTCErrorEvent
。
error
类型为 RTCError
,
只读
描述触发事件的 RTCError
。
WebIDL dictionary RTCErrorEventInit
: EventInit {
required RTCError
error
;
};
error
类型为
RTCError
描述与事件相关的 RTCError
(如果有)。
本节为非规范性。
以下事件在 RTCDataChannel
对象上触发:
事件名称 | 接口 | 触发时... |
---|---|---|
open |
Event
|
RTCDataChannel 对象的 底层数据传输
已建立(或重新建立)。
|
message |
MessageEvent
[html]
|
消息已成功接收。 |
bufferedamountlow |
Event
|
RTCDataChannel 对象的 bufferedAmount
从超过其
bufferedAmountLowThreshold
下降到小于或等于其 bufferedAmountLowThreshold 。
|
error |
RTCErrorEvent
|
数据通道上发生错误。 |
closing |
Event
|
RTCDataChannel 对象转换到
"closing "
状态
|
close |
Event
|
RTCDataChannel 对象的 底层数据传输
已关闭。
|
以下事件在 RTCPeerConnection
对象上触发:
事件名称 | 接口 | 触发时... |
---|---|---|
track |
RTCTrackEvent
|
为特定的 RTCRtpReceiver 协商了新的传入媒体,并且该接收器的 track
已被添加到任何相关的远程 MediaStream 中。
|
negotiationneeded |
Event
|
浏览器希望通知应用程序需要进行会话协商(即需要调用 createOffer 然后调用 setLocalDescription)。 |
signalingstatechange |
Event
|
连接的 [[SignalingState]]
已改变。
此状态变化是由于调用了 setLocalDescription
或 setRemoteDescription
被调用。
|
iceconnectionstatechange |
Event
|
RTCPeerConnection 的 [[IceConnectionState]] 已改变。
|
icegatheringstatechange |
Event
|
RTCPeerConnection 的 [[IceGatheringState]] 已改变。
|
icecandidate |
RTCPeerConnectionIceEvent
|
一个新的 RTCIceCandidate 可用于脚本。
|
connectionstatechange |
Event
|
RTCPeerConnection .connectionState
已改变。
|
icecandidateerror |
RTCPeerConnectionIceErrorEvent
|
收集 ICE 候选时发生错误。 |
datachannel |
RTCDataChannelEvent
|
新的 RTCDataChannel 被调度到脚本中,
以响应另一方创建通道。
|
以下事件在 RTCDTMFSender
对象上触发:
事件名称 | 接口 | 触发时... |
---|---|---|
tonechange |
RTCDTMFToneChangeEvent
|
RTCDTMFSender 对象要么刚刚开始播放一个音调(返回为tone 属性),
要么刚刚结束了在toneBuffer 中播放音调(返回为
tone 属性中的空值)。
|
以下事件在 RTCIceTransport
对象上触发:
事件名称 | 接口 | 触发时... |
---|---|---|
statechange |
Event
|
RTCIceTransport 状态发生变化。
|
gatheringstatechange |
Event
|
RTCIceTransport 收集状态发生变化。
|
selectedcandidatepairchange |
Event
|
RTCIceTransport 的选定候选对发生变化。
|
以下事件在 RTCDtlsTransport
对象上触发:
事件名称 | 接口 | 触发时... |
---|---|---|
statechange |
Event
|
RTCDtlsTransport 状态发生变化。
|
error |
RTCErrorEvent
|
RTCDtlsTransport 上发生错误(可以是
"dtls-failure "
或 "fingerprint-failure ")。
|
以下事件在 RTCSctpTransport
对象上触发:
事件名称 | 接口 | 触发时... |
---|---|---|
statechange |
Event
|
RTCSctpTransport 状态发生变化。
|
本节为非规范性内容。
本节为非规范性内容;不指定任何新行为,而是总结了已在其他部分中存在的信息。WebRTC中使用的一组API和协议的总体安全考虑在 [RFC8827]中进行了描述。
本文档扩展了Web平台,使其能够在浏览器与其他设备(包括其他浏览器)之间建立实时、直接的通信。
这意味着可以在不同浏览器中运行的应用程序之间,或在同一浏览器中运行的应用程序与非浏览器的某些事物之间共享数据和媒体,打破了Web模型中对不同来源实体之间传递数据的通常限制。
WebRTC规范不提供用户提示或Chrome指示来进行通信;它假设一旦网页获得了对媒体的访问,就可以自由地与其他实体共享该媒体。因此,WebRTC数据通道的点对点数据交换可以在没有用户明确同意或参与的情况下进行,类似于通过WebSocket进行的服务器中介交换。
即使没有WebRTC,提供Web应用程序的Web服务器也会知道将应用程序交付到的公共IP地址。建立通信会向Web应用程序公开关于浏览器网络环境的附加信息,可能包括可供WebRTC使用的(可能是私有的)IP地址集合。为了建立通信会话,必须将这些信息传递给对应方。
泄露IP地址可能会泄漏位置和连接方式;这可能是敏感信息。根据网络环境,这也可能增加指纹识别的表面,并创建无法轻易被用户清除的持久跨来源状态。
连接将始终向对应方揭示提议用于通信的IP地址。应用程序可以通过使用RTCIceTransportPolicy
字典中暴露的设置,选择不使用某些地址,从而限制这种暴露,并通过使用中继(例如TURN服务器)而非参与者之间的直接连接来实现。这些选择可以由应用程序根据用户是否表示同意开始与另一方建立媒体连接而作出。
限制IP地址暴露给应用程序本身需要限制可以使用的IP地址,这将影响在端点之间通过最直接路径进行通信的能力。鼓励浏览器提供适当的控制,以决定向应用程序公开哪些IP地址,基于用户期望的安全姿态。选择暴露哪些地址由本地策略控制(详见[RFC8828])。
由于浏览器是在受信网络环境(防火墙内部)中执行的活跃平台,因此重要的是限制浏览器对本地网络上其他元素造成的损害,并保护数据不被不受信的参与者截获、操纵和修改。
缓解措施包括:
这些措施在相关IETF文档中进行了规范。
通信的发生无法向能够观察网络的对手隐藏,因此这必须被视为公开信息。
通信证书可以通过postMessage
(message, options)
以适应未来的需要而不透明地共享。强烈建议用户代理将这些对象所持有的私钥材料与访问RTCCertificate
对象的进程隔离,以减少内存攻击表面。
如上所述,通过WebRTC API暴露的IP地址列表可以作为持久跨来源状态。
除IP地址外,WebRTC API还通过RTCRtpSender
.getCapabilities
和
RTCRtpReceiver
.getCapabilities
方法,暴露了关于底层媒体系统的信息,包括系统能够产生和消费的编解码器的详细和有序信息。这些信息在大多数情况下是持久的,跨越时间和来源,并增加了特定设备的指纹识别表面。
在建立DTLS连接时,WebRTC API可以生成证书,应用程序可以持久保存(例如在IndexedDB中)。这些证书不跨来源共享,并在为源清除持久存储时被清除。
setRemoteDescription
会通过抛出异常来防止不良和无效的SDP,但并不尝试防止应用程序意外的SDP。设置远程描述可能会导致分配显著的资源(包括图像缓冲区和网络端口),媒体开始流动(这可能有隐私和带宽的影响),以及其他事情。未对恶意SDP进行防护的应用程序可能面临资源剥夺、无意中允许传入媒体或未能触发某些事件(如ontrack
)的风险,如果另一端没有协商发送。应用程序需要警惕恶意SDP。
本节为非规范性内容。
WebRTC 1.0规范提供了控制协议的API(在IETF中定义),以建立实时音频、视频和数据交换。
为听力或语言障碍人士(以及其他人士)提供的电信设备(TDD/TTY)使他们能够通过电话线路进行沟通。实时文本(Real-Time Text),定义在 [RFC4103],利用T.140封装在RTP中,使TDD/TTY设备过渡到基于IP的通信,包括与 公共安全接入点(PSAP)的紧急通信。
由于实时文本需要近实时地发送和接收数据,因此可以通过WebRTC 1.0数据通道API得到最佳支持。根据IETF定义,数据通道协议利用SCTP/DTLS/UDP协议栈,支持可靠和不可靠的数据通道。IETF选择标准化SCTP/DTLS/UDP,而不是依赖SRTP密钥管理并专注于不可靠通信的RTP数据通道提案。
由于IETF选择了一种与WebRTC协议套件中RTP数据通道不同的方法,截至本出版时,没有标准化的方式使WebRTC APIs直接支持根据IETF定义并在美国(FCC)法规中实施的实时文本。WebRTC工作组将评估这一领域正在发展的IETF协议是否值得在浏览器API中直接公开,并寻求相关用户社区对此潜在差距的反馈。
在IETF MMUSIC工作组中,正在进行使 实时文本通过WebRTC数据通道发送的工作,从而允许部署网关在SCTP数据通道协议和RFC 4103实时文本之间进行转换。这项工作完成后,预计将实现统一和互操作的方法,将实时文本集成到WebRTC用户代理(包括浏览器)中,无论是通过网关还是其他方式。
在本出版时,能够在WebRTC客户端中有效支持RTT的网关可以通过自定义WebRTC数据通道开发。这被认为足够,直到未来通过IETF协议(如SCTP数据通道协议和RFC 4103实时文本)启用标准化网关。这将需要在IETF中定义,并结合与W3C小组的相关工作,以有效和一致地国际标准化RTT支持。
自从2021年1月作为W3C 推荐发布以来,以下提议的修正案已被纳入本文档。
RTCConfiguration
字典的默认值,使其与当前实现保持一致 - 第4.2.1节 RTCConfiguration字典 (PR #2691) -
对Web平台测试的更改: #43166
RTCConfiguration
字典的默认值,使其与当前实现保持一致 - 第4.4.1.6节 设置配置 (PR #2691) -
对Web平台测试的更改: #43166
RTCIceGatheringState
以明确其表示的相关传输 - 第4.3.2节 RTCIceGatheringState枚举 (PR #2680)
(测试中不需要更改)RTCPeerConnectionState
以明确其表示的相关传输 - 第4.3.3节 RTCPeerConnectionState枚举 (PR #2680)
(测试中不需要更改)RTCIceConnectionState
以明确其表示的相关传输 - 第4.3.4节 RTCIceConnectionState枚举 (PR #2680)
(测试中不需要更改)connecting
- 第4.3.3节 RTCPeerConnectionState枚举 (PR #2687) -
对Web平台测试的更改: #43171
RTCCertificateExpiration.expires
和RTCCertificate.expires
的定义中替换DOMTimeStamp
,并将其来源更改为证书创建时间
- 第4.9.1节 RTCCertificateExpiration字典
(PR #2686, PR #2700)
(不可测试)RTCCertificateExpiration.expires
和RTCCertificate.expires
的定义中替换DOMTimeStamp
,并将其来源更改为证书创建时间
- 第4.9.2节 RTCCertificate接口 (PR #2686, PR #2700)
(不可测试)failed
状态 - 第5.6.4节 RTCIceTransportState枚举 (PR #2704)
(不可测试)自2021年1月作为W3C 推荐标准发布以来,以下候选修正案已被整合进本文档。
RTCRtpEncodingParameters
成员 (PR #2985) -
对Web平台测试的更改: #47663
编辑们感谢工作组主席和团队联系人, Harald Alvestrand、Stefan Håkansson、Erik Lagerway 和 Dominique Hazaël-Massieux 的支持。本规范中的大量文本由许多人提供,包括 Martin Thomson、 Harald Alvestrand、Justin Uberti、Eric Rescorla、Peter Thatcher、 Jan-Ivar Bruaroey 和 Peter Saint-Andre。Dan Burnett 特别感谢 Voxeo 和 Aspect 在本规范开发过程中给予的重大支持。
RTCRtpSender
和 RTCRtpReceiver
对象最初
描述于 W3C ORTC
CG,并已适用于本规范。
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in: