標籤:

WebRTC內置debug工具,詳細參數解讀

為了確保這篇文章所寫內容儘可能的準確,我決定請來Philipp Hancke來作為此篇文章的共同作者。

當你想要找到你WebRTC產品中的問題時,webrtc-internals是一個非常棒的工具,因為你需要用它測試WebRTC以及debug,或者你需要對你的配置進行微調。

如何獲得webrtc-internals的數據轉儲(statsdump)?

如果你對這個工具不熟悉的話,那麼打開你Chrome瀏覽器里的WebRTC段,在這段里打開另一個表單並且將其指向這個內部(internal)URL:chrome://webrtc-internals/

webrtc-internals允許將軌道作為大型的JSON下載下來,這樣你就可以一層一層地來看它了,但是當你這麼做的時候,你會看到類似這樣的東西:

查看webrtc-internals數據

人們通常問到的第一件事是—這些數字到底代表什麼?一位我們自己的測試人員將這些值放入時序圖表裡並且將其輸出出來。這就給了我們要比直接從webrtc-internals中取出的300×140的圖片要大的多的圖表。

這些圖表是使用HighCharts庫得到的,並且有很多十分方便的特性,比如隱藏線條,放大所需區域,或者停靠在特定點處並顯示精確值。這比用JSON轉儲(像上面一樣)要方便的多。

回到基礎的webrtc-internals頁中。在此頁頂端,我們可以考到一系列的表單,一個是給getUserMedia調用的,剩下的兩個分別給每個RTCPeerConnection。

在GetUserMedia請求表單中,我們可以看到每次的getUserMedia調用,以及相關約束。不幸的是,我們不能看到結果或者MediaStreams中有的ids。

RTCPeerConnection數據

對於每個peerconnection,我們可以在這裡看到這四點:

  1. RTCPeerConnection是如何配置的,也就是STUN和TURN伺服器是如何被使用的,以及如何配置
  2. PeerConnection API的軌跡被調用顯示在左邊。這些API軌跡展現了所有的RTCPeerConnection調用和他們的參數(例如createOffer),以及回調和類似於onicecandidate的事件觸發器
  3. 從getStats() API採集的數據在右側被顯示出來
  4. 由getStats() API產生的圖表在底部顯示

RTCPeerConnection API軌跡是非常強大的工具,可以幫助你完成很多的事情,比如分析造成ICE失敗的原因,或者幫你找到適合部署TURN伺服器的地方。我們會在以後的博文中來談這些。

webrtc-internals所給出的統計數據是Chrome的內部格式。這意味著其與目前的規範略有不同步,一些名稱和結構體會有改變。在較高層,我們在webrtc-internals頁上看到的與我們調用這個函數所得到的結果相近:

下面是RTCStatsReport對象的隊列,其中有很多秘鑰和數值,可以這樣讀取:

要記住的是在這些統計數據和規範之間有一些區別。這裡面有一個經驗法則,任意一個名稱以「Id」結尾的秘鑰都包含一個指向不同的報告,其id屬性與秘鑰的值對應。所以全部這些報告都是彼此相連的。還要注意,這些值都是字元型的,儘管它們看起來像布爾值那樣的數字。

RTCStatsReport中最重要的屬性是報告的種類,下面是其中的幾種:

  • googTrack
  • googLibjingleSession
  • googCertificate
  • googComponent
  • googCandidatePare
  • localCandidate
  • remoteCandidate
  • ssrc
  • VideoBWE

讓我們來深入探討一下這些報告型

googTrack與googLibjingleSession報告

googTrack和googLibjingleSession沒包含什麼信息,所以我們跳過它不做分析。

googCertificate報告

googCertificate報告包括了一些有關近端和對等端所使用的DTLS證書的信息,以及指紋和哈希演算法。這些都在RTCCertificateStats字典中有詳細說明。

googComponent報告

googComponent報告的作用就像是認證數據與連接之間的膠水。它包含了一個紙箱當前活躍的候選項對的指針,以及有關用語DTLS和SRTP加密的加密套接字。

googCandidatePair報告

googCandidatePair對一對ICE候選做了描述,也就是低層次的連接。從這個報告中,你可以得到這些信息:

  • 發送和接收的數據包以及位元組數總數(bytesSent,bytesReceived,packetsSent;因為不明原因丟失的packetsReceived)。這是一個包含RTP報頭的UDP或者TCP位元組。
  • 如何判斷這是否是一個活躍的連接,googActiveConnection的值是真則為活躍,否則為假。大多數時間你都會只對活躍的候選對感興趣。對等的規範可以在這裡找到。
  • 被發送和接收的STUN請求和應答數量是計算在ICE進程中輸入和輸出的STUN請求數量。
  • googRtt是最新的STUN請求的往返時間。這與ssrc報告上的googRtt是不一樣的,我們稍後會說。
  • localCandidateId和remoteCandidateId指向localCandidate型和remoteCandidate型。localCandidate和remoteCandidate描述了本地和遠端的ICE候選項。你可以在googLocalAddress型上面找到絕大多數信息。
  • googTr以及googLocalCandidateType的值。
  • googTransportType規定了傳輸的類型。注意這些數據的值通常是「udp」的,即便是在TCP上的TURN被用於連接TURN伺服器的情況下。只有當ICE-TCP被使用時,此值才會是「tcp」的。

從下面這張圖上可以比較直觀地看到一些數據,如發送和接收的位元組數等等:

localCandidate和remoteCandidate報告

感謝上天localCandidate和remoteCandidate與規範中所描述的是一模一樣的,告訴我們ip地址,埠號,以及候選項的類型。對於TURN候選來說,其會告訴我們候選被分配在哪個埠上了。

Ssrc報告

ssrc報告是這裡面最重要的報告之一。每一個音頻或者視頻軌道發送或接收都有一個ssrc報告。在舊版本的規範中,這些叫做MediaStreamTrackStats和RTPStreamStats。其內容決定於這是音頻還是視頻軌道,以及這是發送還是接收。讓我們先來描述下一些其中基本的元素:

  • mediaType表示我們在觀察的是音頻數據還是視頻數據
  • ssrc屬性指定了媒體是發送ssrc還是接收
  • googTrackId會識別這些數據描述的軌跡。這個id可以在SDP中,以及本地或遠端媒體流軌道中被找到。事實上,這違背了以「Id」為後綴的命名法則,通常以「Id」結束的都是一個指向其他報告的指針。Google把goog stats給搞錯了。
  • googRtt表示的是往返時間。與之前說過的往返時間不同,這個往返時間是從RTCP測量的時間。
  • transportId,是指向被用於傳送RTP流的部分。通常用於音頻和視頻流的transportId是一樣的。
  • googCodecName規定了編解碼器的名稱。典型的音頻編解碼器是opus,對於視頻來說,使用的是VP8,VP9或者使用H264。你還可以看到在codecImplementationName統計數據中使用的實施方案的有關信息。
  • bytesSent,bytesReceived,packetsSent以及packetsReceived的值可以讓你計算出總的位元組數。這些數字是累加的,所以你需要在你最後一次詢問getStats之後要將其按時間分開。規定中的示例代碼寫的還不錯,單是要注意Chrome有事會將這些計數器重置,所以你有可能得到一個負數的速率。
  • packetsLost讓你知道有多少包在傳輸過程中丟失了。對於發送端來說,丟包來自RTCP,對於接收端來說,丟包是在本地測量的。當你在檢查一個質量不好的通話時,這個參數可能是你想要查看的最直接的數據。

音頻特性

對於音軌來說,我們有audioInputLevel和audioOutputLevel(在規範中叫做audioLevel)可以告訴我們音頻信號是來與麥克風,還是通過揚聲器播出的。這個特性可以用來探測Chrome里不受歡迎的音頻bug。我們還可以通過googJitterReceived和googJitterBufferReceived得知有多少抖動被接收,以及jitter buffer的狀態。

視頻特性

對於視頻軌道來說,我們有兩大信息需要關注。第一個是被送入googNacksSent,googPLIsSent和googFirsSent中,NACK,PLI和FIR數據包的數量差別。這可以讓我們知道丟包會如何影響視頻質量。

更重要的是,我們得知了框架大小和速率是作為輸入(googFrameWidthInput,googFrameHeightInput,googFrameRateInput)並且實時上是發送到網路之上(googFrameWidthSent,googFrameHeightSent,googFrameRateSent)。

相似的數據可以在接收端被收集到存在googFrameWidthReceived,googFrameHeightReceived中。對於框架速率來說我們甚至可以將其從googFrameRateReceived,googFrameRateDecoded和GOOGFrameRateOutput中分開來。

在編碼端我們可以看到這些值之間的差別,還能知道為什麼圖片會被縮小。通常這些事情發生不是因為沒有足夠大的CPU,就是沒有足夠大的帶寬來傳送完整的圖片。另外,想要降低框架速率(其可以從對比googFrameRateInput和googFrameRateSent之間的差距得到),我們需要得到額外的信息:解析度是否因為CPU的問題而得到適應,以及是否是因為帶寬不夠使得googBandwidthLimitedResolution的值是真。無論是上述哪個情況發生了改變,googAdaptionChanges計數器都會增加。

我們可以從這張圖表上看到這些變化:

這裡的丟包是人為產生的。作為反應,Chrome在t=184時第一次嘗試降低解析度,這是綠線代表的googFrameWidthSent開始偏離黑線代表的googFrameWidthInput。接下來在t=186時,框架開始下降,輸入框架速率(淺藍色線條所示)大約是30fps,與發出的框架速率(藍色線條所示)產生區別,後者幾乎是0.

另外,Chrome在ssrc報告中公開了大量關於音頻和視頻堆棧的表現的數據。我們會在未來的博文中進行討論。

VideoBWE報告

最後,但並不是不重要,我們來分析一下VideoBWE報告。就像它名字所表達的,它包括有關帶寬估計的信息。但是還有一些其他的有用信息包含在這個報告里:

  • googAvailableReceiveBandwidth—對於接收視頻數據可用的帶寬。
  • googAvailableSendBandwidth—對於發送視頻數據可用的帶寬。
  • googTargetEncBitrate—視頻編碼器的目標比特率。這項指標會嘗試填滿可用的帶寬。
  • googActualEncBitrate—視頻編碼器輸出的比特率。通常這與目標比特率是匹配的。
  • googTansmitBitrate—這個比特率是實際傳輸的比特率。如果此數值與實際編碼比特率有較大的差別,那麼可能是因為前向錯誤糾正造成的。
  • googRetransmitBitrate—如果RTX被使用的話,這項允許測量重傳的比特率。此數據通常代表丟包率。
  • googBucketDelay—是Google為了處理大框架速率的策略表示。通常是很小的數值。

正如你看到的,這個報告會給你視頻質量最重要的信息—可用帶寬。查看發送和接收的可用帶寬通常都是在深入分析ssrc報告之前做的最重要的事。因為有時你可能會發現這樣的情況,這解釋了用戶所抱怨的「質量差」:

在這種情況下,「在所有時間裡,帶寬估計都在下降」是對質量問題的一個比較好的解釋。

原作者:Levent-Levi

翻譯:劉通

原文鏈接:What do the Parameters in webrtc-internals Really Mean? ? testRTC

推薦閱讀:

網頁端實時音視頻服務架構與實踐
WebRTC有前途嗎?
18個實時音視頻開發中會用到開源項目
webRTC : HTML5 視頻 直播 技術
教你如何結合WebRTC與TensorFlow實現圖像檢測(上篇)

TAG:WebRTC |