1. 程式人生 > >實現Jitsi SFU自動關閉/啟動視訊層

實現Jitsi SFU自動關閉/啟動視訊層

本文來自Jitsi Videobridge SFU的後端開發人員之一Brian Baldino,他過去在思科和Highfive工作過,擁有豐富的視訊會議產品研發經驗。他分享了在Jitsi實現自動減少轉發視訊層,從而降低客戶端CPU和頻寬使用。LiveVideoStack對原文進行了摘譯。

文 / Brian Baldino

譯 / 元寶

審校 / Ant

原文 https://webrtchacks.com/suspending-simulcast-streams/

640?wx_fmt=png

對高流量的流控制(來源:usbr.gov)

大多數人可能都熟悉典型的SFU風格的使用者介面,該介面最初是在Google Hangouts的消費者市場中推廣的,並由Jitsi Meet和其他服務部門使用。絕大多數螢幕空間的正面和中心是當前活躍的演講者的視訊。所有其他參與者都可以在他們自己的縮圖中看到,通常在右側或底部。我們想讓活躍的演講者的視訊在中間看起來很棒,因此解析度很高。底部/右側的縮圖會很小,因此高解析度會浪費頻寬。為了優化這些不同的模式,我們需要每個傳送者視訊的多個解析度。值得慶幸的是,這已經是一個用聯播解決了的問題!

通過聯播,所有傳送者編碼3種不同的解析度並將其傳送到SFU。SFU決定將哪些流轉發到每個接收器。如果參與者是活躍的發言者,我們會嘗試並將他們傳送給其他人的最高質量的流轉發到他們的主介面上。如果要在右側的縮圖中看到參與者,那麼我們就會轉發他們的最低質量的流。

640?wx_fmt=png

聯播權衡

聯播是優化下載頻寬的絕佳機制。然而,與生活中的大多數事情一樣,聯播涉及權衡——編碼3個流比編碼單個流需要佔用更多CPU。您可以在下面的chrome:// webrtc-internals統計資訊中看到這一點,其中使用聯播的CPU使用率提高了幾個百分點:

640?wx_fmt=png

沒有聯播的CPU使用率   

640?wx_fmt=png

使用聯播的CPU使用率

它還涉及傳送更多位元數:

640?wx_fmt=png

在沒有使用聯播時的傳送位元率(~2,5M位元/秒)

640?wx_fmt=png

   使用聯播時的傳送位元率〜(3M位元/秒)

這些圖表是由chrome:// webrtc-internals自動縮放的,因此請注意y軸刻度可能不同。請檢視實際的y軸值。

流暫停

那麼這是否意味著聯播對使用者來說效率較低呢?相反,由於我們可以單獨控制聯播的流,因此聯播使我們有機會通過關閉不使用的層來節省CPU和位元數。如果你不是活躍的發言者,則根本不需要3層中的2層!  

讓我們看看當我們關閉前2層時的使用率:

CPU使用率

640?wx_fmt=png

沒有使用聯播的CPU使用率基線

640?wx_fmt=png

具有3個聯播流的CPU使用率

640?wx_fmt=png

禁用前兩個層的聯播的CPU使用率

每秒位元數

640?wx_fmt=png

沒有使用聯播的傳送位元率基線

640?wx_fmt=png

使用3個聯播流的位元率

640?wx_fmt=png

禁用前兩個層的聯播的位元率

對於客戶端和SFU上的負載來說,這是一個巨大的勝利!  

實施暫停

現在讓我們看看我們是否可以將其整合到實際程式碼中。這裡有兩個問題需要解決:

1.在SFU上——弄清楚何時沒有使用流並讓客戶知道

2.在客戶端——在不使用流時關閉流,並在需要時再次啟動它們

SFU

第一個問題很容易解決——當客戶成為活躍的發言人時,客戶端會明確地請求參與者提供高質量的流,這樣我們就可以告訴傳送者何時使用高質量的流以及何時不通過資料訊息通道。

客戶端

第一次嘗試

我們也想到了第二個問題。我們知道Chrome會在可用頻寬下降時暫停聯播流的傳輸,那麼如果我們只限制可用頻寬會發生什麼呢?我們可以通過在遠端SDP中設定頻寬限制來實現此目的:

640?wx_fmt=png

使用SDP限制最大發送頻寬

在 b = AS 的那一行將可用頻寬限制到200kbps。讓我們試一試,看看會是什麼樣子:

640?wx_fmt=png

SDP限制頻寬後的CPU使用率

640?wx_fmt=png

SDP限制頻寬後的傳送位元率

太棒了!這正是我們所希望的:它與我們之前的測試結果相匹配!現在讓我們移除上限以模擬某個人成為活躍的發言者並且我們想要他們的高質量流:

640?wx_fmt=png

移除上限的CPU使用率

640?wx_fmt=png

移除上限的傳送位元率

640?wx_fmt=png

移除上限的傳送幀的高度

話說回來,還有一個問題......整個過程需要30秒才能恢復到高質量。這意味著當某人成為活躍發言人時,他們在主舞臺上的低視訊質量將至少持續30秒。這不行,那麼為什麼這麼慢呢?

如果你曾經使用Chrome進行過網路損傷測試,那麼你知道它會應用大量邏輯來防止監控。由於擔心丟失資料包,因此提高發送位元率是非常謹慎的。我們基本上通過我們的SDP引數完成的工作是讓Chrome認為網路的資料包容量非常低(200 kbps),因此當我們刪除它時,Chrome會小心地提高位元率,同時計算實際傳送的數量。當網路出現問題時,這很有意義,但對於我們的用例,這是一個阻礙因素。

Google Meet測試

我們注意到當Google Meet正在使用時,我們首先開始討論聯播流暫停。我們來看看Google Meet電話會議的圖表:

640?wx_fmt=png

Google Meet上的CPU使用率上升

640?wx_fmt=png

Google Meet上的傳送位元率上升

640?wx_fmt=png

Google Meet上的傳送幀的高度

哇!它們下降並且非常快速地增加。他們是如何做到的呢?我們看了他們的SDP,他們正在使用b = AS上限。我們知道這不會讓我們快速上升(正如我們在第一次嘗試中看到的那樣),所以他們肯定還做了其他事情。

我們看了一下chrome:// webrtc-internals並注意到了這一點:

640?wx_fmt=png

使用webrtc-internals調查Google Meet

這個addStream可能看起來沒有什麼作用,但它不是在呼叫的開始,它在中間的位置,當我們希望流恢復時,那麼這裡發生了什麼呢?正在新增另一個視訊流,但沒有一個被刪除,這是如何工作的呢?它與位元率快速上升有關嗎?  

所以我們仔細看了一下,發現了一些細節。這是參與者首先將其媒體流新增到 peerConnection的位置:

640?wx_fmt=png

以下是當我們想要提高位元率時的addStream:

640?wx_fmt=png

所以我們在這裡可以看到軌道ID是相同的但是流ID是不同的。這讓我們想起了Chrome如何為新建立的流提供一個免費的時間段,其位元率可以很快提升; 這樣,當你加入通話時,你可以快速開始傳送高清視訊。我們懷疑,新流的自由上升期是這裡所利用的,當參與者成為活躍的演講者時,讓流看起來是新的。

嘗試2

根據對Meet的調查,我們開始使用獨立的WebRTC演示應用程式嘗試重現其中的行為。通過這樣做,我們能夠在我們的測試環境中重現相同的行為:

  • 複製媒體流

  • 將複製的媒體流新增到對等連線

  • Munge SDP從新流中刪除新的ssrcs / stream資訊並將其替換為原始資訊。

但我們還沒有在實際的Jitsi呼叫中嘗試它,測試環境是點對點的,並沒有使用聯播,所以我們不確定它能移植到Jitsi並工作。曾經我們嘗試或,我們發現我們沒有得到快速上升。它很慢,就像以前一樣只有頻寬上限。我們開始對此進行除錯,並認為它可能與我們在SFU上的速率控制中的某些因素有關,這會阻止位元率快速上升。

在我們進一步發展之前,出現了一種新的可能性。

嘗試3

WebRTC團隊最近推出了關於RTCRtpSender的PSA。支援修改登陸Chrome 69的編碼引數。這有一個API,可讓我們控制各個聯播編碼,包括它們是否已啟用!所以,當我們發現我們不能進入主介面時,客戶端可以這樣做:

640?wx_fmt=png

應該禁用前2層,讓我們看看它的表現:

640?wx_fmt=png

CPU通過RtpSender引數丟棄沒有使用的層

640?wx_fmt=png

通過RtpSender引數丟棄沒有使用層的傳送位元率

我們沒有像以前那樣下降,但它仍然是一個很大的進步!但是,讓我們看看當我們重啟它們時如何提升:

640?wx_fmt=png

CPU使用率上升

640?wx_fmt=png

傳送位元率上升

640?wx_fmt=png

傳送幀高度上升

哇!位元率立即上升了!這將完全適用於有源揚聲器切換。我們不會在Chrome 69之前獲得此功能,但它是一個好的解決方案,併為我們提供了我們想要的東西:當流不使用時快速降低位元率,並在我們再次需要時快速恢復。  

今天就試試看Jitsi Meet,將#config.enableLayerSuspension = true新增到你的URL(只要你使用Chrome v69 +)或檢視Jitsi Github中程式碼。

640?wx_fmt=jpeg