多鏈路傳輸技術(shù)在火山引擎 RTC 的探索和實踐

傳統(tǒng)的數(shù)據(jù)傳輸方式大多是利用一個鏈路、選擇設(shè)備的默認(rèn)網(wǎng)卡進(jìn)行傳輸,使用這種方式實現(xiàn)實時音視頻通話時,如果默認(rèn)網(wǎng)絡(luò)出現(xiàn)問題(如斷網(wǎng)、弱網(wǎng)等),用戶的通信就會發(fā)生中斷或者卡頓,影響用戶體驗。
多鏈路傳輸,顧名思義,就是使用多個鏈路進(jìn)行傳輸數(shù)據(jù)的一種技術(shù)。近年來,單設(shè)備上支持多個可用網(wǎng)卡的技術(shù)越來越普遍,比如我們的手機(jī)就同時支持無線網(wǎng)卡和 4G/5G 網(wǎng)卡,有些雙卡手機(jī)還能同時支持兩個 4G/5G 網(wǎng)卡。而多鏈路技術(shù)就是充分利用用戶設(shè)備上的多個網(wǎng)絡(luò)資源進(jìn)行數(shù)據(jù)傳輸,當(dāng)某一個網(wǎng)絡(luò)出現(xiàn)問題時,其他可用網(wǎng)絡(luò)可以繼續(xù)不間斷地傳輸數(shù)據(jù),避免因單一網(wǎng)絡(luò)問題導(dǎo)致通話中斷或者卡頓,提升用戶通話的可用性和流暢性。
目前,多鏈路傳輸技術(shù)已經(jīng)在火山引擎 RTC 打磨基本成熟,并在抖音和飛書會議等業(yè)務(wù)場景落地,有效地降低了用戶的通話卡頓率,提升了用戶的體驗。
1. 行業(yè)現(xiàn)狀和挑戰(zhàn)
多鏈路技術(shù)在一些行業(yè)已經(jīng)實現(xiàn)了應(yīng)用,如 Apple 的 MPTCP(Multi-Path TCP) 就是一種多鏈路技術(shù),Apple 把它用在了 Siri、Apple Maps、Apple Music 等應(yīng)用上,用來解決用戶在戶外移動時,系統(tǒng)網(wǎng)絡(luò)經(jīng)常在 Wifi 和蜂窩網(wǎng)絡(luò)之間切換導(dǎo)致的應(yīng)用使用不流暢的問題。我們在使用微信的音視頻通話功能時,微信也會開啟音頻雙發(fā)功能,即使用 Wifi 網(wǎng)絡(luò)和蜂窩網(wǎng)絡(luò)同時發(fā)送音頻數(shù)據(jù),以提高用戶的通話體驗。
使用多鏈路傳輸技術(shù)讓數(shù)據(jù)傳輸多了一層“可靠性”的保障,還能讓網(wǎng)絡(luò)切換變得更加絲滑,當(dāng)然,在享受多個網(wǎng)絡(luò)傳輸帶來的好處時,我們也需要解決一些多鏈路技術(shù)實現(xiàn)上的問題。
一是多鏈路傳輸?shù)募軜?gòu)比單鏈路傳輸復(fù)雜,比如需要考慮多個鏈路傳輸帶來的數(shù)據(jù)包冗余、去重問題,多個鏈路的帶寬、質(zhì)量如何評估準(zhǔn)確問題等;二是需要 平衡用戶體驗和流量、電量消耗,利用多個鏈路傳輸數(shù)據(jù)時,不可避免地會引起流量消耗變大,尤其是用戶蜂窩流量變大,而流量消耗變大不僅會影響到帶寬消耗和擠占,還會影響用戶手機(jī)的功耗消耗,嚴(yán)重影響用戶的使用體驗。
業(yè)界目前的多鏈路使用方式主要有兩種:一種是完全冗余的雙鏈路傳輸,即,只要開啟雙鏈路,無論在什么情況下,都會傳輸雙份數(shù)據(jù)。這種方式的缺點是明顯的,它不判斷 用戶網(wǎng)絡(luò)的好壞 “無腦”進(jìn)行雙鏈路傳輸 ,會明顯帶來流量和功耗的增長,可能導(dǎo)致 用戶 手機(jī)發(fā)熱等問題,影響用戶體驗;另外一種是 在 兩條鏈路之間切換使用,這種方式能避免第一種完全冗余傳輸方式帶來的功耗和流量增加,但這種方式也有缺點,比如兩條鏈路在切換使用時,可能造成不平滑和卡頓,并且這種 傳輸 方式也不能充分利用兩條鏈路 資源帶來的“增加可靠保障”的好處。
火山引擎 RTC 在完全冗余模式基礎(chǔ)上,研發(fā)了一個兼顧用戶體驗和流量、功耗消耗的傳輸模式:弱網(wǎng)冗余傳輸。弱網(wǎng)冗余傳輸,顧名思義,就是在 RTC 系統(tǒng)檢測到弱網(wǎng)時才開啟雙鏈路的能力進(jìn)行傳輸數(shù)據(jù)。這種模式既能在用戶弱網(wǎng)時充分利用兩條鏈路傳輸數(shù)據(jù),使用戶體驗基本不會受弱網(wǎng)影響;又能在用戶網(wǎng)絡(luò)正常時使用單鏈路傳輸,減少對用戶流量和功耗的消耗。
2. 多鏈路傳輸技術(shù)演進(jìn)
2.1 完全冗余傳輸
完全冗余傳輸是指數(shù)據(jù),包含音視頻、信令、消息等數(shù)據(jù),通過兩條獨立的路徑在客戶端和服務(wù)端之間傳輸,主鏈路的數(shù)據(jù)會完全復(fù)制一份到備選鏈路。完全冗余傳輸依靠多路徑架構(gòu)、多徑協(xié)議、去重算法實現(xiàn),其中多徑協(xié)議和去重算法是關(guān)鍵部分。完全冗余傳輸可以有效地避免因單個路徑產(chǎn)生問題而導(dǎo)致的通信中斷問題,從而提升用戶通話的可用性。
2.1.1 架構(gòu)設(shè)計
架構(gòu)設(shè)計上,完全冗余傳輸只存在于 SDK 連接模塊和邊緣媒體節(jié)點之間。在發(fā)送端,SDK 傳輸模塊負(fù)責(zé)把上層的數(shù)據(jù)進(jìn)行冗余,并通過兩個通道同時發(fā)送出去,邊緣媒體節(jié)點負(fù)責(zé)在接收到數(shù)據(jù)時,把數(shù)據(jù)進(jìn)行去重還原,然后交給上層的服務(wù)。在接收端,邊緣媒體節(jié)點負(fù)責(zé)對數(shù)據(jù)進(jìn)行冗余發(fā)送,而 SDK 傳輸模塊則負(fù)責(zé)對接收數(shù)據(jù)進(jìn)行去重和還原,并把數(shù)據(jù)交給上層模塊。

完全冗余的多鏈路傳輸架構(gòu)
2.1.2 多徑協(xié)議
多徑協(xié)議的設(shè)計至少要滿足兩個要求,一是能區(qū)分冗余多徑包和正常數(shù)據(jù)包(如 RTP/RTCP 包、STUN 包等),二是能對冗余包進(jìn)行去重。
于是我們設(shè)計了如上 4 個字節(jié)的多徑包頭部:Packet Type 字段用來識別冗余的多徑包,并和正常的 RTP/RTCP、STUN 包進(jìn)行區(qū)分;Packet Sequence Number 則用來對多徑包進(jìn)行編號,用于去重;最后一個為保留字段。
例如,一個多徑下的 RTP 包格式如下:
0                   1                   2                   3
       0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |      0xc8     |   packet sequence number      | default to 0  |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |V=2|P|1|  CC   |M|     PT      |       sequence number         |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |                           timestamp                           |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |           synchronization source (SSRC) identifier            |
      +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
      |       0x10    |    0x00       |           length=0            |
      +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
      |                         RTP payload                           |
      |                             ....                              |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+2.1.3 去重算法
我們利用傳輸模塊保存一個 65536(16bit) 長度的 bit 數(shù)組 bitArrary,初始化狀態(tài)為 0,采用滑動窗口的方式過濾重復(fù)序號的數(shù)據(jù)包。

去重算法圖示
如上圖,resetSeq 為窗口最左端值,latestSeq 為窗口最右端值,resetSeq 到 latestSeq 之間為有效判斷窗口,即windowSize,設(shè)置為 30000。當(dāng)模塊收到一個包時,記此包 seqNum 為 curSeq,做如下處理:
- 如果此包是模塊收到的第一個包,則置 latestSeq = seqNum,resetSeq = latestSeq - windowSize,并通知上層收到一個新包;
 - 如果此包不是模塊收到的第一個包,則判斷 curSeq 與 latestSeq 之間的距離,如果大于 windowSize,則認(rèn)為此包為一個無效包(sequence number跳變太大),進(jìn)行丟棄;如果不大于 windowSize,則認(rèn)為是一個有效包;
 - 接第二步,如果 curSeq < latestSeq,判斷 bitArray 中 curSeq 對應(yīng)的 bit 位是否為 1。如果不是,則說明我們收到了一個新包,置此位為 1,并告知上層;如果已經(jīng)為 1,則表示我們收到了一個重復(fù)包,直接丟棄。如果curSeq > latestSeq,則也認(rèn)為是收到新包,告知上層,并移動窗口,置 latestSeq = seqNum,resetSeq = latestSeq - windowSize。
 
2.1.4 效果
我們模擬了各種網(wǎng)絡(luò)環(huán)境來測試完全冗余的多鏈路傳輸(以下簡稱“完全雙發(fā)”)對音視頻質(zhì)量、設(shè)備性能、功耗的影響。
以下測試數(shù)據(jù)為在 Wifi 和蜂窩雙鏈路網(wǎng)絡(luò)均開啟的情況下,對主鏈路(Wifi)增加弱網(wǎng)時的音視頻通話測試結(jié)果。
用戶體驗
整體來看,當(dāng)開啟完全雙發(fā)后,單個路徑的弱網(wǎng)對整體音畫質(zhì)、端到端延時表現(xiàn)基本沒有影響,用戶仍然能獲得高質(zhì)量的音視頻通話體驗;關(guān)閉完全雙發(fā)后,單個路徑的弱網(wǎng)會導(dǎo)致明顯的卡頓和延時問題。

開啟/關(guān)閉完全雙發(fā)后,單路徑弱網(wǎng)對音畫質(zhì)的影響
如上圖,開啟完全雙發(fā)后,音質(zhì)(MOS 分)、畫質(zhì)(視頻幀率)在不同弱網(wǎng)環(huán)境下的表現(xiàn)穩(wěn)定,音質(zhì)、畫質(zhì)基本不受弱網(wǎng)影響。關(guān)閉完全雙發(fā)后,音質(zhì)、畫質(zhì)會隨著弱網(wǎng)場景的不同受到不同程度的影響,特別是在 200kbps 限速時,音質(zhì)、畫質(zhì)下降嚴(yán)重。

開啟/關(guān)閉完全雙發(fā)后,單路徑弱網(wǎng)對音視頻端到端延時的影響
如上圖,開啟完全雙發(fā)后,端到端延時在不同弱網(wǎng)環(huán)境下的表現(xiàn)良好且穩(wěn)定,基本不受弱網(wǎng)影響。關(guān)閉完全雙發(fā)后,當(dāng)出現(xiàn)高丟包、高延時弱網(wǎng)時,端到端延時明顯增加,用戶體驗明顯下降。
CPU 和內(nèi)存性能
在各種網(wǎng)絡(luò)環(huán)境下,開啟或關(guān)閉完全雙發(fā)對 CPU 和內(nèi)存的消耗沒有太大差別。

開啟/關(guān)閉完全雙發(fā)后,單路徑弱網(wǎng)對音視頻端到端延時的影響
功耗
測試結(jié)果顯示,開啟完全雙發(fā)會對設(shè)備功耗造成一定影響,增加通話的電量消耗。

開啟/關(guān)閉完全雙發(fā)對手機(jī)電量消耗的影響(圖為使用 iphone 11 的測試結(jié)果)
我們使用同款手機(jī)進(jìn)行持續(xù)的音視頻通話,開啟完全雙發(fā)比關(guān)閉雙發(fā)消耗的電量更多、更快,在通話 1 小時后,開啟雙發(fā)比關(guān)閉雙發(fā)多消耗了 4% 的電量。
2.1.5 方案優(yōu)劣
完全冗余的多鏈路傳輸可以有效解決因單一網(wǎng)絡(luò)出現(xiàn)問題而造成的音視頻卡頓、延時問題,提升用戶體驗,并且它的實現(xiàn)方式比較簡單。然而,它的缺點也很明顯,一是對流量消耗大,特別是在視頻場景,會消耗比較多的用戶移動流量;二是對功耗的開銷也較大。因此,完全雙發(fā)并不符合實際業(yè)務(wù)上的需求和用戶體驗,我們需要在盡量減少流量消耗和功耗消耗的情況下來提升用戶通話體驗。
2.2 弱網(wǎng)冗余傳輸
完全冗余傳輸是無論在什么情況下,數(shù)據(jù)都會被復(fù)制一份到另外一個鏈路上傳輸,這么做會導(dǎo)致消耗用戶比較多的流量和功耗。實際上,用戶大部分情況下的網(wǎng)絡(luò)是正常的,并不需要開啟冗余傳輸,對于正常網(wǎng)絡(luò)來說,開啟冗余傳輸反而是一種浪費(fèi),效果是負(fù)面的。因此,我們需要更加有針對性地來開啟多鏈路傳輸,這樣既能提升用戶的通話體驗,也能節(jié)省流量和功耗。
弱網(wǎng)冗余傳輸,顧名思義,就是在完全冗余傳輸?shù)幕A(chǔ)上加上弱網(wǎng)的判斷,即,只有在弱網(wǎng)時才開啟多鏈路傳輸,它的關(guān)鍵在于對弱網(wǎng)判斷的及時性和精準(zhǔn)性,系統(tǒng)需要準(zhǔn)確判斷出現(xiàn)弱網(wǎng)并及時開啟多鏈路傳輸(以下簡稱“弱網(wǎng)雙發(fā)”),這樣才能有效避免網(wǎng)絡(luò)卡頓問題。
2.2.1 架構(gòu)設(shè)計
弱網(wǎng)雙發(fā)使用的多徑協(xié)議、去重算法和完全雙發(fā)基本相同,不同點主要在于,弱網(wǎng)雙發(fā)在完全雙發(fā)的基礎(chǔ)上添加了弱網(wǎng)條件的判斷,只有當(dāng)檢測到主鏈路發(fā)生弱網(wǎng)時系統(tǒng)才會開啟雙發(fā)(使用移動網(wǎng)絡(luò)發(fā)送數(shù)據(jù)),否則不開啟,這樣既保證了正常網(wǎng)絡(luò)下不額外消耗流量和電量,又做到了弱網(wǎng)下提升用戶體驗。

完全冗余與弱網(wǎng)冗余的多鏈路傳輸流程比較
2.2.2 效果
我們比較了不同弱網(wǎng)下,采用完全雙發(fā)、弱網(wǎng)雙發(fā)和關(guān)閉雙發(fā)對對音視頻質(zhì)量、設(shè)備性能、功耗的影響。
用戶體驗
整體來看,無論是完全雙發(fā)還是弱網(wǎng)雙發(fā),單個路徑的弱網(wǎng)對整體音質(zhì)、端到端延時表現(xiàn)基本沒有影響,而關(guān)閉雙發(fā)后,單個路徑的弱網(wǎng)對音質(zhì)、延時表現(xiàn)影響較大,音質(zhì)明顯下降,延時明顯升高。在相同弱網(wǎng)條件下,完全雙發(fā)的端到端延時比弱網(wǎng)雙發(fā)更低。

完全雙發(fā)、弱網(wǎng)雙發(fā)、關(guān)閉雙發(fā)時單路徑弱網(wǎng)對音畫質(zhì)的影響

完全雙發(fā)、弱網(wǎng)雙發(fā)、關(guān)閉雙發(fā)時單路徑弱網(wǎng)對端到端延時的影響
CPU 和內(nèi)存性能
在各種網(wǎng)絡(luò)環(huán)境下,完全雙發(fā)、弱網(wǎng)雙發(fā)、關(guān)閉雙發(fā)對 CPU 和內(nèi)存的消耗并沒有太大差別。
功耗
不管是完全雙發(fā)還是弱網(wǎng)雙發(fā),都會增加通話的電量消耗,但弱網(wǎng)雙發(fā)的耗電量比完全雙發(fā)小,能比較有效地降低功耗消耗。

完全雙發(fā)、弱網(wǎng)雙發(fā)、關(guān)閉雙發(fā)對手機(jī)電量消耗的影響
2.2.3 方案優(yōu)劣
相比完全冗余傳輸,弱網(wǎng)冗余傳輸只有在檢測到主鏈路弱網(wǎng)時才開啟對應(yīng)數(shù)據(jù)的雙發(fā),因此更節(jié)省流量;同時,因減少了在移動網(wǎng)絡(luò)的數(shù)據(jù)發(fā)送,相應(yīng)地也就減少了電量消耗。不過,由于判斷弱網(wǎng)本身需要時間,弱網(wǎng)判斷的準(zhǔn)確性也會影響效果,因此,弱網(wǎng)雙發(fā)的端到端延時比完全雙發(fā)略大一些,但在一般的實時音視頻使用場景中,這種延時差異對用戶來說體驗不大。
3. 多鏈路傳輸技術(shù)的實踐與收益
目前,弱網(wǎng)雙發(fā)已經(jīng)在飛書會議、抖音社交等業(yè)務(wù)上線,以下是抖音社交業(yè)務(wù)開啟弱網(wǎng)雙發(fā)后較對照組的表現(xiàn):

可以看到,開啟音頻弱網(wǎng)雙發(fā)策略后,線上的音頻卡頓率有了明顯的下降,且性能指標(biāo)幾乎不受影響。
4. 未來展望
以上是多鏈路傳輸技術(shù)在火山引擎 RTC 的演進(jìn)和實踐。
不過,上文提到的兩種多鏈路設(shè)計方式均是在連接底層實現(xiàn)的多鏈路傳輸模式,這種多鏈路傳輸模式對于上層的模塊完全透明,上層的擁塞控制、重傳、FEC、PACER、編解碼等模塊,并不“知道”底層是單鏈路還是多鏈路的傳輸模式,因此會帶來兩個問題:
(1)上層的擁塞控制模塊不感知底層的鏈路,無法獨立評估每一個鏈路的帶寬和擁塞情況,也就無法根據(jù)每個鏈路的質(zhì)量來更精確的分配數(shù)據(jù);
(2)數(shù)據(jù)的冗余發(fā)送在連接層實現(xiàn),連接層無法感知數(shù)據(jù)更多的屬性,也就無法實現(xiàn)更豐富的傳輸策略,比如如果我們只想用備用鏈路來傳輸關(guān)鍵幀、FEC 等數(shù)據(jù),上面兩種架構(gòu)就較難實現(xiàn)這種策略。
未來,我們還會使用一種更進(jìn)階的架構(gòu)來代替弱網(wǎng)冗余傳輸架構(gòu),并持續(xù)優(yōu)化音頻、視頻的多鏈路傳輸策略,做到使用最小的額外帶寬和功耗,最大限度地提升用戶的音視頻通話體驗。
加入我們
火山引擎 RTC,致力于提供全球互聯(lián)網(wǎng)范圍內(nèi)高質(zhì)量、低延時的實時音視頻通信能力,幫助開發(fā)者快速構(gòu)建語音通話、視頻通話、互動直播、轉(zhuǎn)推直播等豐富場景功能,目前已覆蓋互娛、教育、會議、游戲、汽車、金融、IoT 等豐富實時音視頻互動場景,服務(wù)數(shù)億用戶。















 
 
 













 
 
 
 