從直播在線上抓娃娃,不斷變化的是玩法的創新,始終不變的是對超低延遲的苛求。實時架構是超低延遲的基石,如何在信源編碼、信道編碼和實時傳輸整個鏈條來構建實時架構?在實時架構的基礎之上,若是經過優化採集、編碼、傳輸、解碼和渲染中的關鍵環節來下降延遲?本文將會介紹即構在這方面的思考與實踐。php
學習交流:html
- 即時通信開發交流羣:320837163 [推薦]web
- 移動端IM開發入門文章:《新手入門一篇就夠:從零開發移動端IM》算法
(本文同步發佈於:http://www.52im.net/thread-1465-1-1.html)跨域
關旭:即構科技音視頻引擎核心專家,碩士畢業於南開大學數學系,前後就任於中興通信、騰訊等公司負責音視頻相關的研發工做,在實時音視頻技術上有多年積累,當前在即構科技主要負責音視頻引擎核心開發。服務器
《實現延遲低於500毫秒的1080P實時音視頻直播的實踐分享》微信
《移動端實時視頻直播技術實踐:如何作到實時秒開、流暢不卡》websocket
《首次披露:快手是如何作到百萬觀衆同場看直播仍能秒開且不卡頓的?》
《七牛雲技術分享:使用QUIC協議實現實時視頻直播0卡頓!》
圖 1 展現了實時音視頻兩種不一樣的應用場景——連麥互動直播和線上娃娃機。雖然這兩種都是互動,可是對於實時音視頻的要求卻不一樣。第一個實時連麥是語音視頻流的互動,例如其中一個說了一句話,另一我的聽到了,再回復一句話,這個實時性只是對語音視頻流的實時性要求很高。而第二種線上抓娃娃則對信令的延遲提出了更高的要求,操縱者無需說話,看到的是娃娃機傳回來的視頻流結果。
若是考量互動直播是用實時音視頻的延遲,那麼線上抓娃娃則是用信令和視頻流的延時。隨着時代的發展,咱們對實時語音視頻的定義會慢慢有一些不一樣,未來可能還有更多的因素須要考慮。
圖 2 是咱們互動直播的實時架構圖,咱們把互動直播分爲兩部分,一個是主播側,須要更低的延遲,另外一側是普通觀衆,對延時不太敏感,但對流暢性敏感,中間經過一些旁路的服務把這兩個集羣(一個集羣叫超低延遲集羣,另一個集羣叫圍觀集羣)鏈接起來。
在超低延時部分,咱們提供的服務包括流狀態更新、房間管理等,以及一些流媒體服務,主要起到分發的做用。咱們經過超低延遲服務器集羣(和觀衆側不太同樣),提供實時分發的功能。
此外還提供了動態調度的服務,幫助咱們在現有的資源網絡上找到更好的鏈路。後面的觀衆集羣是另一個集羣,把它們分開是出於一些業務方和咱們本身成本上的考慮,另外會提供存儲、PCB 加速、分發的功能。
中間的旁路服務包括混流、轉格式(主要是轉碼)、轉協議等。爲何要混流?舉一個比較簡單的例子:當主播一側有 9 我的連麥,若是沒有混流服務,觀衆端就會同時拉 9 路音視頻,這樣對帶寬壓力很大。
普通觀衆是經過圍觀服務器集羣(延遲相對大的集羣)去拉這些流的,這個集羣的延遲可控性相對比較弱,有可能會出現這 9 路畫面之間的不一樣步現象,經過混流服務,觀衆拉的都是合成好的音視頻流,就不會出現各路流之間的不一樣步問題。
還有轉格式轉碼的服務,前面集羣提供的是很低延遲的服務,裏面一些,好比說編碼碼流,不可以在傳統的 CDN 網絡分發,若是想在傳統的 CDN 網絡上分發,就要服務端的轉碼。還有就是轉協議,由於前面提供一個更低延時的服務,後面要在 CDN 網絡上分發,因此協議也須要轉。
圖 3 是線上娃娃機的 APP 版本的架構圖,這裏的是特點是線上娃娃機能夠實時推兩路視頻流,上機玩家能夠隨時任意去切其中一路畫面去看。這兩路視頻流首先經過咱們超低延時服務器集羣,同時上機玩家也能夠推一路流上去,能夠給圍觀觀衆方看到這我的在抓娃娃時候的一些表情、反應、語言,增長一種互動性。此外,玩家須要經過手機遠程操控娃娃機,所以還須要實時信令的分發。
接下來是娃娃機的 H5 架構圖(圖4)。在推流方面和 APP 版本沒有太大的區別,娃娃機一側仍是走的私有協議。不一樣的地方是由於私有協議沒有辦法直接讓 H5 拉到流,因此中間會加入一個媒體網關,做用是把咱們的私有協議翻譯成 H5 能夠識別的碼流格式,而後 H5 端經過 websocket 方式把這路流拉下來,這裏須要媒體網關作到超低延時的轉換。
簡單來看,這裏的網關服務器只是作了一個分發服務,好像不會引入延時,實際上否則。
由於 websocket 拉的是 TCP 的流,可是咱們推的是 UDP 的,當視頻幀很大的時候,一個幀數據就要切割成不少 UDP 包上行,服務器須要將這些 UDP 包攢起來,湊成一個完整的幀後才下發給 H5,這樣才能保證不花屏,才能跑得通,因此這個攢包組幀的過程是會有延遲的。信令部分和 APP 部分基本是類似的。
剛纔介紹了實時音視頻的兩種場景,下面提出一點思考:
1)實時音視頻有什麼樣的特徵?
2)怎麼樣去架構一個實時音視頻系統?
這是仁者見仁,智者見智的問題。你能夠經過不少方式把這個系統架構起來,都會達到相對不錯的效果。可是我認爲,不管怎樣,實時音視頻都有繞不過以下幾個點,只有把它們作好了,纔可以在業界有更高的知名度、更好的技術儲備。
第一是實時音視頻是不能等的:
由於等了就不是實時音視頻了。 不能等,這裏會引入一個矛盾。既然不能等,例如你把實時音視頻也看做一個消費模型來看,那是提早生產仍是按需生產?字面上理解很簡單,確定是按需生產,須要的時候才生產,若是提早生產就是延時了。可是並非每個點都作成按需生產是合理的。
舉一個例子,好比你要去播放一段音頻,最好的作法是系統或者驅動告訴你,它須要數據了,而後去解一幀塞給它,這就是按需生產。可是爲何還有提早生產一說呢?就是系統告訴你它要數據的時候,實際上它有一個對響應週期的要求。
你現去生產可能就要等去解完一幀,可是這個時候來得及嗎?若是你只有一路下行,可能就來得及。可是如今要求不少路下行,在很短的時間週期內解不少幀,對硬件性能有很高的要求。一般來說,並不可取。這只是實時音視頻中一個簡單的例子。提早生產會引入延遲的,那麼到底要提早多久生產,怎麼樣動態估計咱們何時應該生產?這是一個開放性的問題,也是一個你們在設計系統時要重點考慮的。
第二是實時音視頻不能久等:
實時音視頻中有些等待是避免不了的,例如你要作音頻編碼,它原本必定要 20 毫秒一幀或者 40 毫秒一幀去作,給一個採樣點點是編不了的。這裏既然有些延遲和等待避免不了,咱們固然但願系統處理的粒度越低越好,這樣可能會帶來更低的延時。可是處理的粒度越低,整個系統在頻繁跑的時候,你能夠認爲它是一套循環,當循環的東西不多,這個循環就會跑不少次,對系統來講就是一個很大的開銷和負擔。
因此不能久等的時候,咱們固然但願它處理粒度小。另外處理粒度小還有一個優點,在整個系統中並不能保證每個環節的處理粒度是一致的。例如這個節點可能要求是 10 毫秒,下一個結點要求 15 毫秒,這是因爲算法的限制,可能沒有辦法避免。若是在整個系統內選一個相對小的粒度,在粒度拼接的時候,例如 10-15 毫秒,要兩個 10 毫秒纔可以 15 毫秒,還剩下 5 毫秒,剩的就比較少。
若是粒度很粗,可能剩下的東西就不少。在粒度拼接的時候,這個剩餘的量表明瞭整個鏈路中的延遲。因此咱們但願處理粒度儘可能小,可是又不能小到整個系統沒有辦法接受的粒度。
第三是實時音視頻不能死等:
例如你須要接收一個網絡包的時候,這個包遲遲不到,這個時候你不能徹底不等,徹底不等就會卡。可是在等的時候有一個超時的機制,例如這個音頻包就是好久不到,就把它跳過去作一個糾幀補償,當包最終仍是到了的時候,我也只能把它扔掉,而不該該把它利用起來。
此外,實時音視頻在服務器端還須要深刻考慮這樣幾個問題:
第一是負載均衡;
第二是就近接入;
第三是質量評估;
第四是動態路由;
第五是算法流控。
負載均衡:是說讓整個服務器的每個節點都承擔相對均勻的服務,不至於使得某一個節點負載太高形成一些丟包,形成網絡往返時的增大,這樣對任何的網絡損傷來說,對實時音視頻都會形成比較大的延遲增長。
就近接入:這裏的「近」並非指地域上的近,而是「網絡上的近」。很簡單的例子,咱們在深圳作推流,香港離得很近,能夠推到香港的服務器,但實際上這畢竟是一個跨域的網絡,有不穩定的因素在裏面,因此咱們寧願推遠一點。這個近指的應該是在網絡質量評估意義上的近,例如網絡往返時很小、往返時很平穩、分佈在延遲比較大的時刻不會還具備很大的機率,丟包率很低等。
要作到就近接入,這個近要有一個很好的質量評估體系,質量評估方法有兩種:
過後質量評估:在覆盤的時候,例如這個網絡平穩的運行了一個月,覆盤看一下整個月中的質量怎麼樣,這樣的質量評估能夠認爲是一個相對離線的評估,它可以給咱們提供一個指標,最近一個月的網絡和上個月相比是否有所改善。咱們能夠從中學習到一些經驗,例如這個月和上個月的調度上有些策略上的不一樣。這是一個系統化的經驗總結和優化的方法。
實時質量評估:更重要的應該是一個實時上的評估,例如我如今推流,可以實時監控到當前的質量是怎麼樣的,就能夠作到實時動態路由。實時動態路由是說某我的推流從北京推到迪拜,有不少鏈路能夠選,他可能根據以前的一些經驗,假如他以前經驗告訴你,直接推到迪拜,這個鏈路是很好的,可是畢竟有個例。有動態實時的質量評估,就知道這個時候推迪拜是否好,若是很差,能夠在用戶無感知的狀況下更換,隨時增減整個鏈路中一些路由的節點。這就是動態路由的思路。
實時動態路由:是說某我的推流從北京推到迪拜,有不少鏈路能夠選,他可能根據以前的一些經驗,假如他以前經驗告訴你,直接推到迪拜,這個鏈路是很好的,可是畢竟有個例。有動態實時的質量評估,就知道這個時候推迪拜是否好,若是很差,能夠在用戶無感知的狀況下更換,隨時增減整個鏈路中一些路由的節點。這就是動態路由的思路。
實際狀況中是結合前面這 4 個點,在咱們的網絡和服務器資源集中,去選出質量最優或者近似最優的鏈路來保證明時音視頻的服務的。可是資源集是有限的,沒有人能夠保證你的資源集中必定能夠選出的這個最優具備很好的鏈路特徵。保證不了就要考慮第五點,我即便選出了一個認爲是整個資源集中最優的鏈路,可是它的質量還達不到很好的標準,就要經過一些算法才能彌補。這些算法包括在一個不可靠的網絡中怎麼樣進行可靠的音視頻傳輸的技術,這些技術在接下來咱們會和你們稍微分享一下,也包括整個鏈路的一些擁塞控制。
信源編碼是爲了減小網絡中的負擔,把大量的數據壓縮成比較小的網絡數據,來減小網絡負擔的方式。壓縮方式有不少種,咱們先以音頻來看,上面畫了一些圖(圖 6)。
咱們重點看 Opus 編碼器,它有幾種模式在裏面:
一種是線性預測模式;
還有一種是混合模式;
另外一種是頻域編碼模式。
混合模式是把兩種編碼模式混合在一塊兒,根據不一樣的狀況進行選擇。
圖 6 是一個編碼器,橫軸是碼率,縱軸是它的質量,中間是各類音頻編解碼器的表現。你會發現線性預測的方式可以在低碼率上提供比較好的質量,可是在 20K 左右的時候就沒有曲線了,由於它不支持那麼高的碼率。而後看 MDCT 編碼,它能夠在比較高的碼率上達到近似透明的音質。音頻編碼器是有不一樣的編碼原理在裏面的,像這種 LP Mode 是模擬人的發聲模型,既然有了數學建模,它的特徵是可以在一個比較低的碼率上提供一個比較可靠的質量。
可是它的特色是容易達到一種質量上的飽和,也就是說當你碼率給它很高的時候,實際上它也就編的效果仍是那樣,由於它畢竟是一種參數化的編碼。因此根據業務場景,當你須要一個很高的音質,又須要音樂場景的時候,選擇它明顯不合適。MDCT MODE 沒有任何的模型在裏面,實際上就是把信號轉換成頻域,直接去量化。既然沒有模型化,它是比較消耗碼率的,可是它能夠在一個較高的碼率上提供很好的質量,但是低碼率的表現遠遠不如模型化的方法。
總體總結起來,音頻包括語音和音樂兩種,所以有適合語音的 codec 和適合音樂的 codec:
第一種 codec 適合語音,語音能夠模型化,適用於語音的 codec 可以在低碼率上提供很好的質量,提供一個相對高的壓縮比, 可是它容易達到飽和,不可以提供一個近似於透明的音質;
另一種 codec 的編碼原理不同,可以把音樂、語音都編得很好,可是特色是不可以提供過高的壓縮比,期望它可以在低碼率下提供很高的編碼質量是作不到的。
關於視頻編碼,最簡單的幾個點有 I 幀、P 幀、B 幀。I 幀是自參考,P 幀是向前參考,它會參考歷史幀的特性進行編碼。B 幀是雙向參考,它能夠參考前面的幀,也能夠參考後面的幀。B 幀能夠帶來更高的壓縮比,提供更好的質量。可是由於它會參考未來的幀,因此會引入延遲,所以咱們在實時音視頻系統中是不多用到 B 幀的。
想要作好實時的音視頻系統,流控是必定要作的,流控對視頻的編解碼有什麼要求?至少有一點,編解碼器的碼控必定要很穩定。爲何?舉例說,我如今有一個很好的擁塞控制策略,帶寬估計作得很好,一點差錯都沒有,估計出某一個時刻可分配視頻的帶寬就是 500kbps,就可讓視頻編碼器設置成 500kbps。可是,若是碼控不是很穩定,你設置 500kbps 的時候,視頻編碼器可能就跑到 600kbps 了,這樣就會帶來一些阻塞和延遲。所以,咱們但願選擇的 codec 具備很好的碼控策略。
實際上一些開源代碼都是有作碼控的,可是直接拿來用並非適合你的場景,由於這些開源代碼作起來,可能或多或少的考慮其餘的場景,並不僅是實時音視頻場景。好比說某個 codec 是用來壓片的,但願半個小時或者一個小時以內達到預約的碼率就能夠,不會管這一秒鐘或者下一秒是什麼樣子的,可是實時音視頻就是要求要把時間窗作得很小。
另外咱們但願 codec 有分層編碼的能力。什麼是分層編碼?爲何要有分層編碼?分層編碼也分兩種,一種是時域上的分層,一種是空域上的分層。前者是編碼的時候是當前幀不參考上一幀,而是有隔幀參考的策略;後者能夠認爲使用較低的碼率先編碼一個小的畫面,而後使用剩餘的碼率編碼增量的部分,獲得更高分辨率的畫面。
爲何要這樣作?實時音視頻中並非不少場景都是一對一的,當不是一對一,要作流控的時候,不可能由於某一路觀衆的下行很差,就把主播上行推流的碼率降下來,由於可能還有一千個觀衆的網絡很好,這些網絡好的觀衆也會由於個別觀衆網絡很差,而只能看到不那麼清晰的畫面。因此要分層,能夠在服務器端選擇給用戶到底下發哪一層的,由於有分層策略,若是這我的線路很差,只要選擇其中一個比較小的層次發給他就能夠了,例如核心層,這樣能夠牢牢利用核心層把整個視頻還原,可能會損傷一些細節或者幀率偏低,可是至少總體可用。
最後,我想說一下,不少人認爲,視頻的數據量很大,視頻的延時比音頻應該更高才對,實際上不是。由於不少的延遲其實是編解碼自有的延遲,若是編解碼中沒有 B 幀的話,你能夠理解爲視頻編碼是沒有任何延遲的。可是音頻編碼或多或少都會參考一些未來的數據,也就是說音頻編碼器的延時必定是存在的。所以,一般來說,音頻的延時比視頻的延時更高才對。
信道編碼分幾個部分:一種是根據先驗知識的網絡冗餘編碼技術——前向糾錯技術。以 RS(4,6)編碼爲例,我要發一個分組,這個分組有六個包,其中有四個包是實際媒體數據,有兩個包是冗餘包。那麼在解碼端收到六個包中任意的四個,就能夠徹底恢復全部攜帶媒體內容的包。
例如這裏 二、3 都丟了,收到了 一、四、r一、r2,也可以徹底恢復 2 和 3。這樣看來很好,任意兩個丟掉均可以徹底恢復。可是這樣的算法也有它的弱點,不太適合突發性的丟包。由於這個分組不宜太大,若是分組很大,分組就有很大的延時。分組若是很小,極可能整個分組都丟掉了。
實際上這種作法就沒有任何意義。因此它不太適合突發性丟包,並且它畢竟是根據先驗知識去作的一種冗餘,也就是說它永遠是根據上一時刻網絡的狀態做出的判斷,下一時刻網絡是什麼樣的,是預測的東西。網絡是實時發生變化的,這種預測的東西並不徹底可靠。
因此它恢復的效率在實際網絡中相對比較低,並且這樣的算法複雜度相對比較高。固然它也有優點,例如咱們是提早算好的,一次性發過去,不須要等到你發現丟包時我再作怎樣的冗餘傳輸,因此不受網絡往返的影響。並且這種分組能夠任意、隨機調整大小冗餘度,比較適合均勻丟包的場景。
另一項技術是丟包重傳技術:相對來講,丟包重傳相對 RS 來說,更有針對性,因此恢復效率比較高。第一個 Go Back N 技術是相似於 TCP 的傳輸技術,發送端在不斷的發包,接收端要負責告訴發送端我如今收到包的狀況是怎麼樣,收到的連續的幀的是序列號什麼樣的。發送端發現發了 10 個幀,接收端只正確收到 8,無論 9 號包或者 10 號包是否收到,都會丟包重傳。因此 Go Back N 技術有必定的目的性,維護的是丟包狀態,它知道哪些包是沒有收到的,可是並不精準。
接下來是自動選擇重傳技術(Selective ARQ):選擇性的重傳,是在接收端發現了哪一個包丟了,而後纔會讓發送端從新發送這個包。聽起來是很是好的一個技術,效率很高,丟了哪一個包就重傳哪一個包。可是它的弱點在於,你必需要假定這個包是頻密的發送才能夠。例如發送端發出 一、二、三、4 這樣的包,可是一秒鐘才發一個包,何時發現 2 丟了呢?收到 3 的時候。若是 2 做爲最後一包,永遠發現不了丟掉了。也就是若是發包不頻密,至少須要 1 秒鐘才發現它丟。這個時候再讓它重傳,就很晚了。
因此在一個真實的系統中,選擇性重傳是首選,由於音視頻的大部分場景是頻密的,可是可能也要結合一些 Go-Back -N 的作法。發一些確認機制,這樣才能把重傳作得更加完備。另外全部的重傳都要至少等一個網絡往還時,由於不管是確認丟包仍是反饋收包狀況,都須要一個網絡往返時,因此它的弱點是,它受網絡往返時影響比較大,若是控制很差,有可能形成重傳風暴。優點是算法計算複雜比較低,且容易實現。另外,由於它有很大的針對性,無效的重傳包會比較少,針對突發性的丟包會有比較好的效果。
剛纔講了針對不可靠網絡的兩種傳輸技術,前向糾錯和丟包重傳,它們都有各自的優勢和缺點。實際上一個好的網絡分發技術應該是將這兩種結合在一塊兒的,根據不一樣的信道狀況把這兩種技術結合在一塊兒。
圖 11 來自於網絡,首先從左下角藍色部分看起,當網絡往返時很小,丟包率不高的時候就用重傳。可是當網絡 RTT 很高的時候,在這個圖裏面去看,就沒有選用重傳策略。從我我的的角度來看,我認爲這並非一個很是合理的作法。由於剛纔提到了,FEC 是一個無目的性的、根據先驗知識去作的一種冗餘技術,雖然當 RTT 很高,重傳很耗時,但若是沒有重傳,要加不少冗餘包,才能把丟掉的包徹底恢復,實際就會帶來很大的資源浪費。並且當你丟包率很高的時候,可能還並不可以徹底恢復全部包。視頻只要丟幀就會很卡,視頻丟包率應該控制在千分之幾如下,才能夠達到順暢的能夠觀看的水平。
關於信道編碼的思考:信道編碼和網絡吞吐呈反比關係。不管是重傳性編碼仍是冗餘性編碼,都會佔用帶寬,從而減低實際媒體信息的吞吐量。現實的生活中,信道都有限制。當你傳輸的時候,就要根據信道的特徵去作一些策略。信道若是有擁塞,咱們就須要有一個擁塞控制的算法,去估計應該把整個信道怎麼樣作合理分配。
另外,在作一個系統的時候,想清楚如何去評價一個系統的效果是很重要的一個點:在信道編碼的時候,一個很重要的指標是,信道編碼的有效性是什麼樣子的。有效性分爲兩種,一種是重傳或者冗餘可否真的把丟掉的包補回來,這是一個有效性。即便這個包補回來了,可是若是通過一個信道編碼策略以後,還有一些丟包。
例如原來的丟包是 20%,補回來變成 1%,那麼這個重傳在咱們的評價當中其實是沒有效果的,由於 1% 的丟包對音頻來說是無所謂的,可是對視頻來說是很卡的。在這樣的評價系統中,補回來還有 1% 的丟包,那麼全部的編碼都是沒有太大意義的。舉這個例子,若是在這時信道也發生擁塞,再進行這樣的信道編碼,就不會達到很好的效果。這個時候是否應該中止全部的信道編碼呢?
還有信道編碼有效性的判斷:衡量它是否好,就是加了多少冗餘,冗餘中有多少沒有被利用好,若是這些冗餘像剛纔那個例子那樣,6 包帶 2 包的冗餘,恰好丟掉 2 包,整個包都恢復出來了都使用到了,那就是百分之百的冗餘都有效。若是 4 包信息丟了 1 包,卻帶了 2 包榮譽,其中 1 包就沒有效果。因此想要作一個好的系統,應該先想到如何評價這個系統的好壞。
延遲的引入主要分三部分。
1)一個是採集 / 渲染:這好像是很簡單一個部分,可是它引入延遲多是最大的,多是整個分發過程當中最大的環節。
有不少人不是特別理解,但實際上在咱們現有的網絡結構中,網絡往返時的延遲都控制在 50 毫秒之內,可是渲染和採集,尤爲是渲染,幾乎沒有任何移動端系統能夠保證它百分之百的 50 毫秒,這是一些硬件上的限制。如何去下降這些延遲?剛纔我已經舉了一個生產消費模型的思路,究竟是按需生產仍是提早生產,這些都是能夠仔細去考慮的。
2)還有編解碼會帶來一些延遲,尤爲是音頻會帶來一些延遲:這些延遲中有些是避免不了的,咱們就要根據實際的使用場景去減小這些延遲,這些都是要在具體形態上作一些權衡的東西。還有處理粒度上的考慮,也會影響整個系統的延遲。
3)還有一個延遲,你們都能看到的,就是網絡分發延遲:如何去減少?除了在資源集中找到一個最優子集以外,還有信道編碼的東西,要作一個很好的信道編碼系統,咱們如何評價信道編碼系統的好壞。有了這些思路以後,能夠指導咱們去作更好的下一步的開發工做。
[1] 開源實時音視頻技術WebRTC的文章:
《訪談WebRTC標準之父:WebRTC的過去、如今和將來》
《良心分享:WebRTC 零基礎開發者教程(中文)[附件下載]》
《新手入門:到底什麼是WebRTC服務器,以及它是如何聯接通話的?》
《[觀點] WebRTC應該選擇H.264視頻編碼的四大理由》
《基於開源WebRTC開發實時音視頻靠譜嗎?第3方SDK有哪些?》
《開源實時音視頻技術WebRTC中RTP/RTCP數據傳輸協議的應用》
《開源實時音視頻技術WebRTC在Windows下的簡明編譯教程》
《網頁端實時音視頻技術WebRTC:看起來很美,但離生產應用還有多少坑要填?》
>> 更多同類文章 ……
[2] 實時音視頻開發的其它精華資料:
《即時通信音視頻開發(五):認識主流視頻編碼技術H.264》
《即時通信音視頻開發(九):實時語音通信的迴音及迴音消除概述》
《即時通信音視頻開發(十):實時語音通信的迴音消除技術詳解》
《即時通信音視頻開發(十一):實時語音通信丟包補償技術詳解》
《即時通信音視頻開發(十三):實時視頻編碼H.264的特色與優點》
《即時通信音視頻開發(十五):聊聊P2P與實時音視頻的應用狀況》
《即時通信音視頻開發(十六):移動端實時音視頻開發的幾個建議》
《即時通信音視頻開發(十七):視頻編碼H.26四、VP8的前世此生》
《學習RFC3550:RTP/RTCP實時傳輸協議基礎知識》
《基於RTMP數據傳輸協議的實時流媒體技術研究(論文全文)》
《還在靠「喂喂喂」測試實時語音通話質量?本文教你科學的評測方法!》
《實現延遲低於500毫秒的1080P實時音視頻直播的實踐分享》
《技術揭祕:支持百萬級粉絲互動的Facebook實時視頻直播》
《理論聯繫實際:實現一個簡單地基於HTML5的實時視頻直播》
《首次披露:快手是如何作到百萬觀衆同場看直播仍能秒開且不卡頓的?》
《騰訊音視頻實驗室:使用AI黑科技實現超低碼率的高清實時視頻聊天》
《七牛雲技術分享:使用QUIC協議實現實時視頻直播0卡頓!》
>> 更多同類文章 ……
(本文同步發佈於:http://www.52im.net/thread-1465-1-1.html)