我們來到了一個新世紀,屬于音視頻的世紀,很高興大家選對了方向,站在了音視頻的風口上。移動網絡的快速發展,音視頻必然成為更方便快捷的溝通方式。就像十幾年前的互聯網,有一天,音視頻也會成為一項基礎服務,極大地改變我們的生活方式。
自我介紹一下吧,我叫伍倡輝,07年入職騰訊,做過大數據分析、兩人音視頻系統、多人音視頻系統、PSTN以及直播系統,目前為直播系統總架構師。這次主要分享騰訊在做音視頻時的一些相關技術,不是炫耀騰訊技術多牛逼,而是來相互學習,打造行業技術氛圍。
獨立日2里,男女主角用QQ實現地月通話,且不說植入廣告是否欠維和,QQ能上好萊塢大片,我個人還是覺得很自豪的。為什么QQ音視頻能上月?有人說這個是通信商解決的問題,只要網絡通了就行,其實還真跟音視頻技術有一些關系,比如距離遠了之后,時延、丟包率都會大很多,怎么處理好是有挑戰的。這些都是我們自己心里YY,現在來看看做2人音視頻都需要哪些技術吧。
電影里的場景,就是男主角要跟女友視頻聊天。
從技術層面表達,就是把上行方攝像頭里實時采集的畫面,一幀一幀傳到對方,在顯示器上展示,再把上行方麥克風里的聲波,采集傳到對方,在外放或耳機里播放。事情聽起來很簡單,我們來看看騰訊都做了啥。
這是騰訊兩人音視頻的基本架構,其中任何一塊,都可以作為一個課題,深入研究。
視頻,我們可以采集攝像頭、屏幕等畫面,做降噪、縮放等前處理,進入編碼。音頻可以通過麥克風、或HOOK系統獲取系統聲音,等等,做降噪、回聲抵消、自動增益等前處理,進入編碼。編碼最主要的算法就是DCT變換,損失掉一些人感知弱的部分,然后經過網絡傳輸。網絡傳輸主要有直連打洞、中轉、路由管理等模塊。下行客戶端主要就是上行客戶端的逆過程。
騰訊2人音視頻,每天傳輸量約1P左右。為了方便直觀的感受一下,如果是DVD,估計需要21萬張來存儲。
所以,我們首先要考慮的是壓縮傳輸。就是用編碼器來將原始數據壓縮,例如H264、silk等等,這些都是壓縮算法。壓縮算法本身,我們并沒有深入研究,這些在一些專門做編解碼算法公司里面,已經快做到極致了,我們主要是對其中的參數做一些適配,作一些優缺點互補。
即使壓縮傳輸,一路視頻也需要幾百k或幾兆流量。我們服務器帶寬成本,為幾萬1G,成本很高,所以必須考慮直連。WebRTC里面的直連打洞做得已經很不錯了。騰訊的打洞過程也是參考的WebRTC,做了一些小優化,例如用戶和就近同運營商的打洞服務器相連,打洞服務器雙機走專線提供服務,可以讓用戶連接打洞服務器的成功率更高。
大家都知道,NAT并不能都成功,或者直連成功了,直連網絡也可能很差。因此必須要有中轉,那就涉及到多通道的管理上了。騰訊有直連、單中轉、雙中轉、動態路由等通道,能通過歷史情況自我學習,再配合現有具體情況靈活控制。
中轉機器部署會很廣泛,機器量非常龐大,必然涉及到海量集群的機器管理。我們不能全依賴人工解決所有服務器問題,要考慮容災、柔性、灰度發布、負載均衡、就近調度等等。
用戶的網絡,什么情況都有,不是我們能控制的。怎么樣才能合理的,盡可能的利用用戶帶寬,就涉及到帶寬預測。
即使帶寬曲線模擬得再好,不代表網絡不丟包。為了減少延時,我們音視頻傳輸用的都是UDP,丟包不能影響音視頻使用,所以怎么抗丟包而由延時小就顯得很關鍵。
前兩項,業界有很多文章,技術也都比較成熟,這里就不細講。第三項,是一些慢工細活,暫時不講,這次主要講一下后面有騰訊特色的三項技術。
騰訊的接入點,在全球都有很多點。這么多的機器怎么管理呢?這里主要介紹一下騰訊經典的負載均衡算法。上一周,我面試了一個人,他做的系統,用的是最小分配算法,系統跑得很好,因為請求量不大,只是機器利用率低一點而已,浪費也不大。然而在騰訊,服務是海量的,再用這種算法就會出問題了。
這是一個典型的案例。在做群視頻的時候,有新同事誤用最小分配算法實現負載均衡,結果所有單機負載出現了鋸齒狀的曲線,后來改為騰訊經典的加權隨機負載均衡算法,曲線就平滑多了。最小分配為什么會出現鋸齒狀曲線?是因為調度系統的單機負載,并不是每次用戶接入或退出就實時更新,而是集群機器定時統計上報。前者會使得系統耦合度很高,后者實現更簡單。在一個上報周期中,調度系統里記錄的單機負載不會變。所有請求都會分配到這個周期里負載最低的機器上。導致單機負載突然暴漲,變成負載最高的機器。然后在未來若干個周期中都不會分配,等待用戶自然流失。跌到最低點時又會再分配。
騰訊經典的負載均衡算法,在每次機器負載上報時,會計算每臺機器的空余度,然后將所有空余度加起來,例如這里總和為37。
每次用戶請求,計算一個1到37之間的隨機數,這個隨機數屬于哪臺機器,就選哪臺機器。例如這里的隨機數為18,就選第4臺機器。
這種算法,實現簡單,處理用戶請求部分只需要幾行代碼就搞定了:算一個隨機數模總空余度,逐臺機器減空余度,減到哪臺小于0,就選哪臺。效率也很高,時間復雜度不到n。分配上,負載輕的,分配概率大,負載重的,分配概率小。從單次分配來看,有概率可能分配到負載較重的機器。但從宏觀統計看,整體負載會比較平均。如果新增加一臺機器,新機器的負載增加也會是比較平滑的,而不是突然達到負載平衡點。
騰訊經典的負載均衡算法,一般會和其他算法配合,例如就近、容災等。可以通過權值控制就近接入,使得就近機器分配概率比別的機器大,這樣如果某地機器全部故障(例如IDC停電、專線被挖),或負載滿,可以自動就近調度到其他接入點,而不需要人工干預。機器故障,也會調整權值,使得分配概率極小。一旦機器恢復,有用戶嘗試成功,馬上就可以激活機器。所以機器故障,不需要人工禁用和啟用機器,全自動處理。
接下來分享一下帶寬預測。如果用UDP線性增加發送速率,接收速率曲線會是什么樣子的?
這是我們實測的效果。為什么會這樣呢?主要是路由器要維持公平性。TCP傳輸是很友好的,當遇到網絡擁塞的時候,會自動縮小發送窗口,減少發送量。但UDP是自己實現的,如果UDP不做這么友好,豈不是我發越多,搶占帶寬就越多?這樣TCP還能傳輸嗎?所以路由器做了一個策略,如果我告訴你網絡擁塞,你不減少發送量,我就懲罰你。于是就出現了這樣的接收曲線。所以,我們不能盡最大能力的發送數據,必須要預測帶寬,保證不要超過帶寬(不要長時間超帶寬)。我們先看看TCP是怎么做的。
這是TCP的經典擁塞控制算法,現有用得最廣泛的算法。可以看到,帶寬估計在窗口大小24左右。接近帶寬的地方,有很多三角形區域,是用不上的。
QQ音視頻帶寬預測,一開始做秒高清,在1秒內粗獷的預測一下帶寬情況,然后從預測的帶寬開始,逐漸增加,達到帶寬瓶頸后,回調一個周期,然后持續傳輸一段時間。如果持續的過程中,路由器繼續提示擁塞,會繼續向下回調。如果傳輸沒有異常,會隔段時間向上探測帶寬是否增加。
這個預測算法究竟怎么樣呢?我們來和競品對比一下吧:
從圖中可以看出,在網絡限制總帶寬以及設置固定丟包率的情況下,QQ的帶寬波動都很小,而競品要么波動大,要么不斷往下調傳輸量。
丟包的原因都有哪些?
我們列舉丟包原因,不僅僅是列出來,還要分析其中的規律。
我們發現,左邊的這類丟包,丟的比例跟我們數據發多發少,關系不大,而右邊這類,發得越多,丟的比例越大。我們稱左邊的這類叫固有丟包,右邊這類叫擁塞丟包。分類也不是目的,而是思考怎么更好的抗丟包。
通常抗丟包有兩種方式,FEC和ARQ。FEC是前向冗余,舉個例子,發送數據A和B,增加發送一個數據C等于A和B的異或。接收方接到這3個包的任意2個包,異或一下就可以得到第3個包。當然,實際的FEC沒這么簡單,通常會有比較復雜的矩陣運算。ARQ就是接收方發現丟包后,去發送方請求重傳。
FEC傳遞簡單,只需要單向傳輸就可以支持,延時小,缺點就是丟包率波動大時,抗丟包能力差。ARQ的優點是網絡攜帶率高,但延遲大,當延時大或擁塞丟包的情況,不能使用ARQ。擁塞丟包時,使用ARQ會加大傳輸量,導致擁塞更嚴重。
音視頻質量評估,是比較麻煩的事情。很多東西都是比較主觀的,人的關注點有差異,對視頻好壞的判斷也就有了差異。業界常見的評分體系有很多,都比較客觀。騰訊也有自己的無參考評分,會偏主觀一些,是通過對兩千多人對不同質量視頻主觀評價,擬合而形成的。得到通過各種參數評估音視頻主觀質量的公式,擬合的公式有點龐大,但外界不一定認可,所以對外,我們還是主要用業界常用的評分體系評估,對內才使用無參考評分。
舉個例子,我們用POLQA評分來衡量我們的音質:
可以看到,騰訊的音視頻,在丟包率30%的情況評分還比較好。從主觀體驗來說,騰訊的在丟包30%的環境,還能聽得清楚說話,而競品基本聽不清楚了。
這些數據是怎么來的?
這就是騰訊的音視頻實驗室,有專門的隔音音頻實驗室、網絡損傷儀等等。
下一篇為大家帶來【多人音視頻及直播互動】的詳細學習資料,敬請期待。
更多資料可關注官方公眾號:編風網(微信ID:befoio)或 WebRTC編風網(微信ID:webrtcorgcn)