实时传输协议 (RTP) 简介
实时传输协议 (RTP),在 RFC 3550 中定义,是一个 IETF 标准协议,旨在实现实时连接,以交换需要实时优先级的数据。本文概述了 RTP 是什么以及它在 WebRTC 中的功能。
注意:WebRTC 实际上使用 SRTP (安全实时传输协议) 来确保交换数据的安全性和身份验证。
将延迟降至最低对于 WebRTC 尤其重要,因为面对面的通信需要尽可能低的 延迟。一个用户说话与另一个用户听到之间的时间延迟越大,就越容易出现交叉通话和其他形式的混乱。
RTP 的关键特性
在检查 RTP 在 WebRTC 中的使用之前,了解 RTP 的功能和不足之处很有帮助。RTP 是一种数据传输协议,其使命是在当前条件下尽可能高效地在两个端点之间传输数据。这些条件可能受到从网络堆栈的底层到物理网络连接、中间网络、远程端点的性能、噪声水平、流量水平等的各种因素的影响。
由于 RTP 是一个数据传输协议,它得到了密切相关的 RTP 控制协议 (RTCP) 的补充,RTCP 定义在 RFC 3550,第 6 部分。RTCP 增加了包括服务质量 (QoS) 监控、参与者信息共享等功能。它不足以完全管理用户、成员、权限等,但为不受限制的多用户通信会话提供了基本需求。
RTCP 与 RTP 在同一 RFC 中定义的事实,暗示了这两个协议之间紧密相关的程度。
RTP 的能力
RTP 在 WebRTC 方面的主要优势包括
- 通常较低的延迟。
- 数据包已进行序号和时间戳标记,以便在乱序到达时重新组装。这使得使用 RTP 发送的数据可以在不保证顺序甚至不保证交付的传输上进行传递。
- 这意味着 RTP 可以(但并非必须)在 UDP 之上使用,以获得其性能以及其多路复用和校验和特性。
- RTP 支持组播;虽然这对于 WebRTC 来说尚不重要,但随着 WebRTC 未来(希望)得到增强以支持多用户对话,它可能会变得重要。
- RTP 不仅限于视听通信。它可以用于任何形式的连续或活动数据传输,包括数据流、活动徽章或状态显示更新,或控制和测量信息传输。
RTP 的不足之处
RTP 本身并未提供所有可能的功能,这就是为什么 WebRTC 还使用其他协议。RTP 不包含的一些更值得注意的方面包括
- RTP 不保证服务质量 (QoS)。
- 尽管 RTP 旨在用于对延迟敏感的场景,但它本身并不提供任何确保 QoS 的功能。相反,它只提供允许在堆栈的其他地方实现 QoS 所需的信息。
- RTP 不处理可能需要的资源分配或预留。
在 WebRTC 的相关方面,这些问题在 WebRTC 基础架构的各个地方都有处理。例如,RTCP 处理 QoS 监控。
RTCPeerConnection 和 RTP
每个 RTCPeerConnection 都有方法可以访问服务于对等连接的 RTP 传输列表。这些对应于 RTCPeerConnection 支持的三种传输类型
RTCRtpSender-
RTCRtpSender负责将MediaStreamTrack数据编码并传输到远程对等节点。可以通过调用RTCPeerConnection.getSenders()来获取给定连接的发送器。 RTCRtpReceiver-
RTCRtpReceiver提供检查和获取有关传入MediaStreamTrack数据的信息的能力。可以通过调用RTCPeerConnection.getReceivers()来获取连接的接收器。 RTCRtpTransceiver-
RTCRtpTransceiver是一个 RTP 发送器和一个 RTP 接收器的组合,它们共享一个 SDPmid属性,这意味着它们共享相同的 SDP 媒体 m-line(代表双向 SRTP 流)。这些由RTCPeerConnection.getTransceivers()方法返回,每个mid和收发器共享一对一的关系,mid对于每个RTCPeerConnection都是唯一的。
利用 RTP 实现“保持”功能
由于 RTCPeerConnection 的流是通过 RTP 和上述接口实现的,因此您可以利用这些接口对流的内部进行访问和调整。您可以做的最简单的事情之一就是实现“保持”功能,即通话参与者可以点击一个按钮,关闭他们的麦克风,而是向另一个对等方发送音乐,并停止接收传入的音频。
在下面的示例中,我们将把启用和禁用“保持”模式的对等方称为本地对等方,而被保持的用户称为远程对等方。
激活保持模式
本地对等方
当本地用户决定启用保持模式时,将调用下面的 enableHold() 方法。它接受一个包含保持期间播放的音频的 MediaStream 作为输入。
async function enableHold(audioStream) {
try {
await audioTransceiver.sender.replaceTrack(audioStream.getAudioTracks()[0]);
audioTransceiver.receiver.track.enabled = false;
audioTransceiver.direction = "sendonly";
} catch (err) {
/* handle the error */
}
}
try 块中的三行代码执行以下步骤
- 用包含保持音乐的
MediaStreamTrack替换其传出音频轨道。 - 禁用传入音频轨道。
- 将音频收发器切换到仅发送模式。
这会通过发送 negotiationneeded 事件来触发 RTCPeerConnection 的重新协商,您的代码会通过使用 RTCPeerConnection.createOffer 生成 SDP 提议并将其通过信令服务器发送到远程对等方来响应。
audioStream(包含要播放的音频,而不是本地对等方的麦克风音频)可以来自任何地方。一种可能性是有一个隐藏的 <audio> 元素,并使用 HTMLAudioElement.captureStream() 来获取其音频流。
远程对等方
在远程对等方,当我们收到方向设置为 "sendonly" 的 SDP 提议时,我们使用 holdRequested() 方法来处理它,该方法接受 SDP 提议字符串作为输入。
async function holdRequested(offer) {
try {
await peerConnection.setRemoteDescription(offer);
await audioTransceiver.sender.replaceTrack(null);
audioTransceiver.direction = "recvonly";
await sendAnswer();
} catch (err) {
/* handle the error */
}
}
这里执行的步骤是
- 通过调用
RTCPeerConnection.setRemoteDescription()将远程描述设置为指定的offer。 - 将音频收发器的
RTCRtpSender的轨道替换为null,表示没有轨道。这会停止在收发器上发送音频。 - 将音频收发器的
direction属性设置为"recvonly",指示收发器仅接收音频而不发送任何音频。 - SDP 答案通过调用
sendAnswer()方法生成并发送,该方法使用createAnswer()生成答案,然后通过信令服务将生成的 SDP 发送到另一个对等方。
停用保持模式
本地对等方
当本地用户点击界面控件禁用保持模式时,将调用 disableHold() 方法来开始恢复正常功能的流程。
async function disableHold(micStream) {
await audioTransceiver.sender.replaceTrack(micStream.getAudioTracks()[0]);
audioTransceiver.receiver.track.enabled = true;
audioTransceiver.direction = "sendrecv";
}
这会按如下方式逆转 enableHold() 中执行的步骤
- 音频收发器的
RTCRtpSender轨道被替换为指定流的第一个音频轨道。 - 收发器的传入音频轨道被重新启用。
- 音频收发器的方向设置为
"sendrecv",表示它应恢复发送和接收流式音频,而不是仅发送。
就像在启用保持时一样,这会再次触发协商,导致您的代码向远程对等方发送新的提议。
远程对等方
当远程对等方收到 "sendrecv" 提议时,它会调用其 holdEnded() 方法
async function holdEnded(offer, micStream) {
try {
await peerConnection.setRemoteDescription(offer);
await audioTransceiver.sender.replaceTrack(micStream.getAudioTracks()[0]);
audioTransceiver.direction = "sendrecv";
await sendAnswer();
} catch (err) {
/* handle the error */
}
}
此处 try 块内执行的步骤是
- 通过调用
setRemoteDescription()将收到的提议存储为远程描述。 - 音频收发器的
RTCRtpSender的replaceTrack()方法用于将传出音频轨道设置为麦克风音频流的第一个轨道。 - 收发器的方向设置为
"sendrecv",表示它应恢复发送和接收音频。
从现在开始,麦克风重新激活,远程用户可以再次听到本地用户,并与他们交谈。