追求極致,揭祕抖音背後的RTC技術

語言: CN / TW / HK

直播、社交、線上教育等行業催生了實時音視訊技術(RTC) 的興起和發展。反過來, RTC 的發展和應用也為這些行業帶來了巨大的增長。隨著 RTC 對應用場景的不斷滲透,業務夥伴關於場景體驗的要求也越來越高,比如更低延時、更加順暢、更高畫質。LiveVideoStackCon 2021 北京站,火山引擎視訊雲 RTC 產品負責人 Julian,為大家分享火山引擎視訊雲 RTC 是怎樣在抖音、西瓜、頭條等產品的場景實踐中,不斷地追求極致的。

大家好,我是來自火山引擎 RTC 團隊的 Julian,很高興今天能跟大家學習交流。今天我帶來的分享是抖音背後的 RTC 是如何追求極致的。

1. 簡介

首先,我先簡單介紹一下火山引擎 RTC 團隊。

我們並不是來自抖音,我們來自火山引擎,抖音也是火山引擎服務的一個客戶。我所在的團隊是火山引擎的 RTC 團隊,已經為抖音服務了 4 年時間。在 4 年中,抖音不斷增長,擁有 6 億 DAU,而火山引擎 RTC 團隊的能力也有跨越式的提升。

我們先看一下抖音上的 RTC 應用場景。

最經典的是連麥 PK。兩個抖音主播通過 RTC 進行連麥,轉碼生成兩路音視訊流,推到 CDN,分別給各自直播間的觀眾進行直播。在這個過程中,主播 PK,看誰收到的禮物更多。有些 PK 場景還會有主播和觀眾的互動:這邊,主播和觀眾的互動也是通過 RTC 進行的。

抖音上也有一些很有意思,但是大家可能瞭解不是特別多的場景,比如一起看好友私聊

一起看就是我們在抖音上可以幾個好友連線,一起看同一個視訊,其中有一個人是房主,房主的視訊刷到哪,其他人自動跟著刷到哪,大家還能通過語音實時交流視訊內容。這裡面除了語音聊天是用 RTC 實現之外,短視訊的訊息同步也是用 RTC 的低延時訊息做的。

一起看就是幾個好友連線,在抖音上同時看同一個視訊。其中有一個房主,房主看到哪,其他人的視訊也自動播放到哪。大家通過語音進行實時交流。這個場景下,除了語音聊天是用 RTC 實現的以外,視訊播放進度的訊息同步也是用 RTC 的低延時訊息功能實現的。

還有一個場景是好友私聊。一些抖音重度使用者知道,抖音現在也支援視訊和語音通話,體驗也非常不錯。我自己和朋友用其他軟體通話比較卡的時候,就會換抖音。經常換了抖音就不卡了,大家有興趣也可以試一下。抖音上的視訊通話還自帶美顏,因此視訊通話相對語音通話的比例會更高一點。

抖音上的通話效果好是有指標支援的。經過長期的合作,我們打磨出了一套指標體系。這個圖中摘錄了部分核心指標。左邊是 RTC 的技術指標,包括卡頓率、端到端延遲、首幀時長、清晰度。右邊是與 RTC 質量相關的抖音業務指標,包括使用者反饋率、使用者滲透率、使用者使用時長以及業務營收。RTC 的優化都是在資料指標指導下進行的。優化過程中,我們做了很多 AB 實驗和歸因分析,通過優化技術指標,來優化業務指標。全量上線的標準是能夠達成最優的業務指標。

2. 面臨的挑戰

下面說說我們的挑戰是什麼。

如果對 RTC 的核心指標進行歸總的話,可以劃分成清晰、流程、實時三個核心要求。但對 RTC 熟悉的同學都知道:這三個核心要求之間,有時是無法得兼的。網路好的時候沒什麼問題,網路比較差的時候,就要犧牲其中一個或兩個指標。

舉個簡單的例子,當網路不好,視訊有卡頓時,增加緩衝延時是最簡單的優化手段。緩衝延時太高,會引起兩個人搶話,嚴重影響通話體驗。如果同時需要流暢和實時,那隻能降低清晰度。抖音上有很多顏值主播,讓主播的臉能被看清楚,又是一件優先順序挺高的事情。

業務面對這樣的選擇題時,通常可以接受一點指標上的妥協,但總是會提出持續優化的要求。換句話說,就是“我全都要”。業務的需求都是合理的。接下來我們就來講一下我們是如何應對這樣的挑戰的。

3. 最佳實踐

3.1 流暢度

首先,講一下流暢度。流暢度對應的指標是卡頓率。卡頓其實對於交流的影響是最大的,即使只卡掉一個字,你也會明顯感覺到交流不暢。

卡頓是因為弱網。那弱網又是什麼引起的呢?

我們建立一個最簡單的 RTC 傳輸模型,終端 A 到終端 B,中間是 RTC 的雲端傳輸網路。其實雲端傳輸網路的傳輸質量現在已經非常好了。我們會監控 QoS 指標。

監控結果可以發現:雲端丟包基本上是不存在的。國內雲端傳輸延遲基本在 50ms 以內,全球範圍基本都在 250ms 以內。

主要的弱網其實是在接入網,也是我們常說的 FirstMile 和 LastMile,也就是使用者自己的客戶端接入 RTC 網路的這一段。資料統計後發現,大概 30% 的使用者會碰到弱網的情況,其中 26.8% 是輕度弱網,中度和重度都在4%左右。

這邊弱網使用者等級,是按瞬時網路指標進行區分的,分為好、輕度、中度和嚴重4個等級。

這邊我們找了一個極端的線上 case,看看 RTC 能力的極限如何。

這是一個丟包率和延時引數的示意圖,我們看到,最初比較平穩;突然發生弱網,持續了一段時間,丟包率最高達到了 49%。隨著抗丟包策略的接入,延遲從 88ms 升到 700ms。經過優化,抗丟包策略的卡頓時長基本都控制在 1.2 秒以內。

要適應突發的極端弱網情況,我們的演算法也會實時自動調節。

針對不同的場景,其實會使用不同的演算法。比如 1v1 通訊時,除了根據傳送端的上下行網路調整發送策略外,也要關注接收端的下行網路情況。接收端下行網路不佳時,傳送高規格的音視訊資料並不會帶來什麼收益。多人通訊時,我們會採用大小流(Simulcast)的方法。應用大小流時,大家常常會關注接收端。但其實發送端上行可能也會有壓力,上行如果出現弱網的時候,也要考慮發大小流是否合適。

這些場景都在我們的演算法考慮範圍內。我們會通過對使用者 QoS 資料的洞察,針對不同場景,自動下發對應的策略。演算法的訓練資料來自線上海量的真實使用者網路環境。上面舉的例子是抗丟包。真實的線上弱網環境非常複雜,純丟包的場景幾乎是不存在的,一定會疊加抖動、延時等網路問題。我們把線上使用者真實的情況不斷的加到訓練庫裡,不斷優化演算法的應對。

另外,應對網路從好到差的過程要敏感,但恢復的過程要有一定的弛豫。有時候網路波動發生,消失的過程很快。多等待 3、4 秒,確定網路真的平穩了,演算法才會把使用者的位元速率恢復上去。

我們準備了一段視訊進行弱網對抗的演示。是團隊成員自己錄製的,不涉及使用者隱私。

演示中模擬了弱網情況,並且限制了最高可用頻寬,分別降到三個弱網等級。網路從好的狀態到輕度弱網的情況,位元速率和幀率有所下降;中度弱網時,網路丟包比較嚴重,解析度也有所下降;重度弱網時,位元速率 500fps 都不到了。極差的情況下引入了一個 1 秒的卡頓,然後網路有所恢復,突然又到了極差的情況,最後恢復。

可以看到在極差的情況下,雖然有1秒的卡頓,但並沒有漏字,在適應弱網之後,會把之前漏掉的音訊用比較小的倍速去追上進度,不會影響內容。

3.2 實時性

實時性有兩個指標,端到端延遲和首幀渲染速度。對通話場景來說,端到端延遲控制在 400ms 以內,使用者體驗都是沒問題的。當然,也有對延遲要求更高的場景,比如雲遊戲,它對延遲要求極高,從使用者觸發指令開始,到收到首幀響應,來回需要在 100ms 以內。本次分享時間有限,就不展開了。

我們主要分享首幀渲染速度。

我們可以思考一下。為什麼 CDN 的延時比 RTC 大很多,反而首幀響應又快更穩定?其實,CDN 會在邊緣節點把命中率高的視訊加入快取,使用者在拉流的時候可以從邊緣節點直接拉,這樣就比較快。因為業務特性的原因,RTC 不可能去做這樣的快取策略。但我們會去借鑑這樣的思路。多人場景下,比如剛開始是兩個人通話,後來第三個人進來,之前兩個人的通話就已經在邊緣節點上了。火山引擎 RTC 有一種策略是把最近 1 個 GOP 的音視訊流快取到邊緣,加快新的音視訊通話參與者開啟首幀的速度。

GOP 是兩個視訊關鍵幀之間的時間間隔。大家對視訊處理比較熟悉,就知道這個概念。業內 GOP 採用 1s、2s 的都有。

我們無法預測碼流的請求什麼時候來。如果沒有快取,只要不是落在 GOP 剛開始的時候,請求者就必須等到下一個 I 幀時,才能拉到首幀。很顯然,這個等待時間根據 GOP 的大小有一個預期分佈。而應用快取策略之後,不管請求什麼時候到,都可以即時獲取到首幀。

這裡錄了個Demo,主要看的是每進一個房,3個流的載入速度。可以像抖音一樣做上滑下滑的切換房間,最後是一個上麥的速度,這種情況下都是需要更快的首幀。這個 Demo 裡面開啟首幀的時長都在100ms 到 200ms 之間。,我們也檢測了線上首幀的速度,基本都在700ms以內,有的業務形態好的,會控制在400ms以內,我們管這個叫瞬開。

3.3 清晰度

第三個優化方向是清晰度,清晰度提升的是使用者體驗的上限。前面的優化,使用者感知起來是非常直接的,而清晰度的感知是潛移默化的。視訊沒有那麼清晰,你一開始並不會有很明顯的感覺,但看的時間長了以後,就可能不想繼續看了。所以這個指標最後會影響使用者使用時長。

清晰度是沒有上限的。RTC 需要解決的問題是如何在有限的頻寬下,讓實時傳輸****的視訊質量更高。

  • BVC1 - 位元組跳動自研編碼演算法

這個視訊裡面顯示的是自研的 BVC1 編碼器,和主流的 H.264 和 H.265 在編碼效率的對比。右側的 RD-plot 曲線圖裡顯示 BVC1 編碼器能比主流的 H.265 編碼器再提升 0.6dB。一般我們評價一個 Codec 演算法好不好,會看它節省了多少頻寬。但具體到 RTC 中,使用者的頻寬是平穩的,解析度也是業務上所決定的,不需要把頻寬用足,把解析度變得更高。所以火山引擎 RTC 選擇在頻寬和解析度不變的情況下,把編碼效率用到畫質提升上。

重點可以看背景上的粉色條。

  • ROI(感興趣區域)編碼

ROI(感興趣區域)編碼我們也在廣泛地使用,基本上連麥場景下都會使用。用白話講,就是針對中間的人臉進行編碼。在同樣的幀率和位元速率之下,經過 ROI 編碼後的效果,在臉部細節上更清晰。正好前面有同學問到,我們怎麼去評測 ROI 的效果。ISO 提供了一種通過盲測得票比率對映 JND 的方式評測畫質。我們通過內測邀請了 100+ 同學對比評測,得到了 2.3 分。這是一個比較高的分數了。

  • 超解析度 Super Resolution

最後我們也用到了超分演算法。

可以看一下頭髮絲的細節。超分提升解析度。這邊把原本 360P 的視訊超分到 720P。這邊盲測的評分就更高一些,是 2.55 分。

不同場景下的優化策略

有了硬核的演算法能力之後。我們也會針對每個場景適配最合適的優化策略。

比如在 PK 場景,運用的是最佳解析度策略。

先簡單介紹一下這個策略。PK 時,RTC 畫面會佔據畫面的四分之一(長、寬各一半)。現在隨著使用者的手機越來越好,有些手機能支援 1080P 的音視訊通話,有些只能支援 540P 等等。比如你作為一個主播,拿著 1080P 的收集和 720P 的主播進行 PK 連麥的話,其實你看到的,對面主播發過來的視訊也就是 540P。對面主播採集 720P 的視訊也沒什麼用;反過來也是一樣的。最佳解析度策略就是說,RTC 會自動根據對面主播的裝置解析度情況,來選擇最合適的解析度,而不是無腦用最高清的解析度。

我們接收另外一個在 PK 連麥場景上應用的轉推 CDN 的策略。大部分 RTC 都是在雲端做轉碼,然後轉推 CDN 的。這其實會引入多一次的編解碼和傳輸。PK 場景是兩個人,對端視訊流一定是從遠端過來的,這個沒辦法。但其實主播自己的畫面轉推 CDN 時,經過服務端轉推的二次編解碼,它的畫質一定會有點受損,所以我們會碰到很多業務方提出要用客戶端轉碼的方案。

但客戶端轉碼也會來其他的問題:雖然減少了一次編解碼傳輸,但是會帶來裝置效能消耗的提升。我們提出了端雲一體轉推 CDN 的方案。如果這個主播的裝置,其效能和網路足夠在客戶端做轉碼,我們就在客戶端做;如果不足,就降級到服務端進行。這樣,裝置效能高時,能享受到更好的清晰度;裝置效能低,我們能保證正常使用。目前這個策略應用於線上超過 60% 的使用者。

這就涉及了怎麼去判斷使用者裝置的效能的問題。

火山引擎 RTC 在後臺維護了一個很大的機型資料庫,裝置總數達到 2w+,並且不斷增加中。這邊是部分截圖。我們會保證每一款機型在對應場景下,都有經過打磨驗證的推薦引數和推薦策略。

3.4 美顏特效

最後單獨提一下 RTC 和美顏特效的結合。美顏特效其實對於 CPU 和記憶體的消耗是更大的,有這麼大的一個模型在那邊跑,對於 RTC 自適應演算法帶來了新的挑戰。

我們在測試過程中碰到過美顏特效影響編碼演算法效率的事情。所以我們思考,怎麼儘可能避免這樣的影響?

先看一下現在主流的做法,RTC 和 CV 是分開的,開發者需要先自己採集,送到美顏特效的 SDK 處理,拿到處理後的視訊流,再在本地回顯,並送到 RTC SDK 做編碼,然後傳輸。這個邏輯很順,但缺點在於, RTC 編碼時會考慮弱網和裝置效能的降級,如果因為弱網或裝置效能不夠,RTC 編碼是會降級的。你想編碼時候編的是一個 360P 的視訊,採集和美顏用 1080P 就沒什麼意義,一點都不低碳。如果 RTC 的降級能夠影響到採集和美顏,整體的效能消耗會更優。

火山引擎 RTC 就把美顏特效的 SDK 和 RTC 統一排程了。採集就用的 RTC SDK 的能力,再通過 RTC SDK 調 CV 相關的介面。這樣,採集和提交到美顏 SDK 的視訊解析度都是一個解析度。再也不會出現採集、美顏 1080P,傳輸 360P 的情況了。

總結

雖然今天介紹的是我們為抖音做的優化,但這實際上是一套針對場景特點優化的方法論,不侷限於抖音。

目前我們除了服務抖音以外,還服務著位元組內外部的其他客戶。現在月均通話分鐘數已經超過了 150億。龐大的基數帶來的巨大的資料,也是我們優化的著力點。

我們的態度是追求極致,我們的目標是成就合作伙伴。大家有興趣的話可以做進一步的交流。

感謝大家!