即時傳輸協議 (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",表示它應恢復傳送和接收音訊。
從現在開始,麥克風重新啟用,遠端使用者可以再次聽到本地使用者,並與他們交談。