如何基於 ZEGO SDK 實現 Android 通話質量監測

来源:https://www.cnblogs.com/zegodeveloper/archive/2022/05/09/16249570.html
-Advertisement-
Play Games

在進行視頻通話過程中,用戶有時候會出現網路不好的情況,比如在進行多人視頻通話或者多人唱歌時,我們需要實時顯示用戶的網路質量。 ...


功能簡介

在進行視頻通話過程中,用戶有時候會出現網路不好的情況,比如在進行多人視頻通話或者多人唱歌時,我們需要實時顯示用戶的網路質量。
在這裡插入圖片描述

示例源碼

參考 下載示例源碼 獲取源碼。

相關源碼請查看 “/ZegoExpressExample/AdvancedStreaming/src/main/java/im/zego/streammonitoring” 目錄下的文件。

前提條件

在監測通話質量之前,請確保:

基礎網路質量報告

可以通過監聽 onNetworkQuality 回調,收到房間內用戶(包括自己)的上下行網路質量。此回調每隔兩秒會收到一次,網路質量等級請參考 ZegoStreamQualityLevel

不同版本的 onNetworkQuality 回調邏輯有所不同:

  • 對於使用 2.14.0 及以上版本 ZEGO Express SDK 的用戶,onNetworkQuality 回調的邏輯為:

    • 只要推流或者拉流,就能收到自己的網路質量回調。
    • 當拉取了其他用戶推送的音視頻流並且該用戶在房間內時,才會收到該用戶的網路質量回調。
    • 當 “userID” 為 “null” 時,代表本次是自己的網路質量,當 “userID” 不為 “null” 時,代表是房間內其他用戶的報告。
  • 對於使用 2.10.02.13.1 版本 ZEGO Express SDK 的用戶,onNetworkQuality 回調的邏輯為:

    • 必須既推流又拉流,才會收到自身的網路質量回調。
    • 當拉取一條流時,推送該條流的用戶必須在同一房間內,且他也進行了拉流,才會收到該用戶的網路質量回調。
    • 當 “userID” 為 “null” 時,代表本次是自己的網路質量,當 “userID” 不為 “null” 時,代表是房間內其他用戶的報告。

onNetworkQuality 不適用於使用 CDN 進行直播的場景,可以參考 進階質量報告 - 推流質量報告 監測 CDN 的推流質量。

public void setEngineEventHandler(){
        engine.setEventHandler(new IZegoEventHandler() {
            @Override
            public void onNetworkQuality(String userID, ZegoStreamQualityLevel upstreamQuality, ZegoStreamQualityLevel downstreamQuality) {
                super.onNetworkQuality(userID, upstreamQuality, downstreamQuality);
                if (userID == null) {
                    // 代表本地用戶(我)的網路質量
                    //("我的上行網路質量是 %lu", (unsigned long)upstreamQuality);
                    //("我的下行網路質量是 %lu", (unsigned long)downstreamQuality);
                } else {
                    //代表房間內其他用戶的網路質量
                    //("用戶 %s 的上行網路質量是 %lu", userID, (unsigned long)upstreamQuality);
                    //("用戶 %s 的下行網路質量是 %lu", userID, (unsigned long)downstreamQuality);
                }

                /*
                ZegoStreamQualityLevel.EXCELLENT, 網路質量極好
                ZegoStreamQualityLevel.GOOD, 網路質量好
                ZegoStreamQualityLevel.MEDIUM, 網路質量正常
                ZegoStreamQualityLevel.BAD, 網路質量差
                ZegoStreamQualityLevel.DIE, 網路異常
                ZegoStreamQualityLevel.UNKNOWN, 網路質量未知
                */

            }
        });
           
    }

進階質量報告

如果上述的基礎網路質量報告不能滿足需求,ZEGO 還提供了更詳細的推流質量報告、拉流質量報告以及其他相關信息。

推流質量報告

推流質量報告指用戶把音視頻推送到 ZEGO 服務端這個過程的質量報告,包含了採集、編碼階段音視頻流的幀率,傳輸(發送)的音視頻流的幀率、碼率、延時及丟包率。

可以通過註冊 onPublisherQualityUpdate 接收推流質量回調,推流成功後每隔三秒會收到此回調。可根據 quality(ZegoPublishStreamQuality) 參數實時瞭解推送的音視頻流的健康情況。

  • 大多數情況下,只需關註 “quality” 的 “level” 參數,以 “level” 枚舉值來判斷推流的綜合質量,詳情可參考 ZegoStreamQualityLevel
  • 如果想關註更詳細的推流質量參數,可以參考 ZegoPublishStreamQuality
    engine.setEventHandler(new IZegoEventHandler() {

            // 開發者可以在此回調中監控具體的質量以上報到業務伺服器做監控,或者監控質量對象的某個欄位以給用戶友好的提示
            @Override
            public void onPublisherQualityUpdate(String streamID, ZegoPublishStreamQuality quality) {
                String networkQuality = "";
                // level 代表了推流質量的綜合分數,大部分情況下,開發者可以參考此分數展示上行網路的質量

                switch (quality.level) {
                    case EXCELLENT:
                        networkQuality = "非常好";
                        break;
                    case GOOD:
                        networkQuality = "好";
                        break;
                    case MEDIUM:
                        networkQuality = "一般";
                        break;
                    case BAD:
                        networkQuality = "差";
                        break;
                    case DIE:
                        networkQuality = "失敗";
                        break;
                    case UNKNOWN:
                        networkQuality = "未知";
                        break;
                    default:
                        break;
                }
                //("網路質量是:%s", networkQuality);
            }
        });

拉流質量報告

拉流質量報告指用戶拉取播放音視頻流這個過程的質量報告,包含了接收的音視頻流的幀率、碼率、延時和丟包率,解碼階段音視頻流的幀率,以及渲染階段的幀率、卡頓率、音視頻整體質量。

可以通過註冊 onPlayerQualityUpdate 接收拉流質量回調,拉流成功後每隔三秒會收到此回調。開發者可根據 quality(ZegoPlayStreamQuality) 參數實時瞭解拉取的音視頻流的健康情況。

  • 大多數情況下,只需關註 “quality” 的 “level” 參數,以 “level” 枚舉值來判斷拉流的綜合質量,詳情可參考 ZegoStreamQualityLevel
  • 如果想關註更詳細的拉流質量參數,可以參考 ZegoPlayStreamQuality
    engine.setEventHandler(new IZegoEventHandler() {
            // 開發者可以在此回調中監控具體的質量以上報到業務伺服器做監控,或者監控質量對象的某個欄位以給用戶友好的提示
            @Override
            public void onPlayerQualityUpdate(String streamID, ZegoPlayStreamQuality quality) {
                String networkQuality = "";
                // level 代表了拉流質量的綜合分數,大部分情況下,開發者可以參考此分數展示下行網路的質量

                switch (quality.level) {
                    case EXCELLENT:
                        networkQuality = "非常好";
                        break;
                    case GOOD:
                        networkQuality = "好";
                        break;
                    case MEDIUM:
                        networkQuality = "一般";
                        break;
                    case BAD:
                        networkQuality = "差";
                        break;
                    case DIE:
                        networkQuality = "失敗";
                        break;
                    case UNKNOWN:
                        networkQuality = "未知";
                        break;
                    default:
                        break;
                }
                //("網路質量是:%s", networkQuality);
            }
        });
}

MOS 音質評分

ZEGO Express SDK 2.16.0 版本開始,拉流質量回調 onPlayerQualityUpdate 中新增 "mos" 欄位,表示對拉流音質的評分。開發者對音頻質量比較關註時,可通過該欄位瞭解當前音頻的質量情況。

mos 欄位的取值範圍為 [-1, 5],其中 -1 表示未知(例如異常拉流時無法評分),[0, 5] 表示評分。實時音頻 MOS 評分對應的主觀音質感受如下:

MOS 值 評價標準
4.0~5.0 音質很好,清晰流暢,聽的清楚。
3.5~4.0 音質較好,偶有音質損傷,但依然清晰流暢,聽的清楚。
3.0~3.5 音質一般,偶有卡頓,需要一點註意力才能聽清。
2.5~3.0 音質較差,卡頓頻繁,需要集中註意力才能聽清。
2.0~2.5 音質很差,部分語義丟失,難以交流。
小於 2.0 音質極差,大量語義丟失,無法交流。
-1 未知。

其他信息監測

推流/拉流狀態變化通知

1. 推流狀態回調

在推流成功後,可以通過 onPublisherStateUpdate 獲取推流狀態變更的通知。

engine.setEventHandler(new IZegoEventHandler() {
    @Override
    public void onPublisherStateUpdate(String streamID, ZegoPublisherState state, int errorCode, JSONObject extendedData) {
        super.onPublisherStateUpdate(streamID, state, errorCode, extendedData);
        // 當 state 為 PUBLISHER_STATE_NO_PUBLISH 時,且 errcode 非 0,表示推流失敗,同時不會再進行重試推流了,此時可在界面作出推流失敗提示;    
        // 當 state 為 PUBLISHER_STATE_PUBLISH_REQUESTING 時,且 errcode 非 0,表示在重試推流,此時如果超出重試時間未成功推流會拋出推流失敗通知。
    }
}

可以根據回調內的 “state” 參數是否在 “正在請求推流狀態” 來大體判斷用戶的推流網路情況。“state” 參數的取值與用戶推流狀態對應如下:

枚舉值 說明
ZegoPublisherState.NO_PUBLISH 未推流狀態,在推流前處於該狀態。如果推流過程出現穩態的異常,例如 AppID 或 Token 不正確,或者如果其他用戶已經在推送流,推送相同流 ID 的流會失敗,都會進入未推流狀態。
ZegoPublisherState.PUBLISH_REQUESTING 正在請求推流狀態,推流操作執行成功後會進入正在請求推流狀態,通常通過該狀態進行 UI 界面的展示。如果因為網路質量不佳產生的中斷,SDK 會進行內部重試,也會回到正在請求推流狀態。
ZegoPublisherState.PUBLISHING 正在推流狀態,進入該狀態表明推流已經成功,用戶可以正常通信。

參數 “extendedData” 為狀態更新附帶的擴展信息。若使用 ZEGO 的 CDN 內容分髮網絡,在推流成功後,該參數的內容的鍵為 “flv_url_list”、“rtmp_url_list”、“hls_url_list”,分別對應 flv、rtmp、hls 協議的拉流 URL。

2. 拉流狀態變更回調

在拉流成功後,開發者可通過 onPlayerStateUpdate 獲取推流狀態變更的通知。

engine.setEventHandler(new IZegoEventHandler() {
    @Override
    public void onPlayerStateUpdate(String streamID, ZegoPlayerState state, int errorCode, JSONObject extendedData) {
        super.onPlayerStateUpdate(streamID, state, errorCode, extendedData);
        // 當 state 為 PLAYER_STATE_NO_PLAY 時,且 errcode 非 0,表示拉流失敗,同時不會再進行重試拉流了,此時可在界面作出拉流失敗提示;
        // 當 state 為 PLAYER_STATE_PLAY_REQUESTING 時,且 errcode 非 0,表示重試拉流,此時如果超出重試時間未成功拉到流會拋出拉流失敗通知。
    }
}

開發者可根據 “state” 參數是否在 “正在請求拉流狀態” 來大體判斷用戶的拉流網路情況。“state” 參數的取值與用戶拉流狀態對應如下:

枚舉值 說明
ZegoPlayerState.NO_PLAY 未拉流狀態,在拉流前處於該狀態。如果拉流過程出現穩態的異常,例如 AppID 或 Token 不正確,都會進入未拉流狀態。
ZegoPlayerState.PLAY_REQUESTING 正在請求拉流狀態,拉流操作執行成功後會進入正在請求拉流狀態,通常通過該狀態進行應用界面的展示。如果因為網路質量不佳產生的中斷,SDK 會進行內部重試,也會回到正在請求拉流狀態。
ZegoPlayerState.PLAYING 正在拉流狀態,進入該狀態表明拉流已經成功,用戶可以正常通信。

接收到音頻/視頻首幀的通知

1. 推流端音頻採集首幀回調

可以通過註冊 onPublisherCapturedAudioFirstFrame 接收音頻首幀回調。調用推流介面成功後,SDK 採集到第一幀音頻數據時會收到此回調。

在未推流或未預覽的情況下,首次推流或首次預覽,即 SDK 內部的音視頻模塊的引擎啟動時,會去採集本機設備的音頻數據,會收到該回調。開發者可根據該回調判斷 SDK 是否真的採集到音頻數據,若未收到該回調,說明音頻採集設備被占用或異常。

engine.setEventHandler(new IZegoEventHandler() {
    @Override
    public void onPublisherCapturedAudioFirstFrame() {
        super.onPublisherCapturedAudioFirstFrame();
    }
}

2. 推流端視頻採集首幀回調

可以通過註冊 onPublisherCapturedVideoFirstFrame 接收視頻首幀回調。調用推流介面成功後,SDK 採集到第一幀視頻數據時會收到此回調。

在未推流或未預覽的情況下,首次推流或首次預覽,即 SDK 內部的音視頻模塊的引擎啟動時,會去採集本機設備的視頻數據,會收到該回調。可以根據該回調判斷 SDK 是否真的採集到視頻數據,若未收到該回調,說明視頻採集設備被占用或異常。

engine.setEventHandler(new IZegoEventHandler() {
    @Override
    public void onPublisherCapturedVideoFirstFrame(ZegoPublishChannel channel) {
    super.onPublisherCapturedVideoFirstFrame(channel);
    }
}

3. 拉流端音頻接收首幀回調

開發者可通過註冊 onPlayerRecvAudioFirstFrame 監聽拉流端音頻接收首幀回調。調用拉流介面成功後,SDK 拉流拉到第一幀音頻數據時會收到此回調。

engine.setEventHandler(new IZegoEventHandler() {
    @Override
    public void onPlayerRecvAudioFirstFrame(String streamID) {
        super.onPlayerRecvAudioFirstFrame(streamID);
        AppLogger.getInstance().receiveCallback("onPlayerRecvAudioFirstFrame streamID:%s",streamID);
    }
}

4. 拉流端視頻接收首幀回調

可以通過註冊 onPlayerRecvVideoFirstFrame 監聽拉流端接收視頻首幀回調。調用拉流介面成功後,SDK 拉流拉到第一幀視頻數據時會收到此回調。

engine.setEventHandler(new IZegoEventHandler() {
    @Override
    public void onPlayerRecvVideoFirstFrame(String streamID) {
        super.onPlayerRecvVideoFirstFrame(streamID);
    }
}

5. 拉流端渲染完視頻首幀回調

可以通過註冊 onPlayerRenderVideoFirstFrame 監聽拉流端渲染完視頻首幀回調。調用拉流介面成功後,SDK 拉流並渲染完第一幀視頻數據後會收到此回調。

可以用該回調來統計首幀耗時或更新播放流的 UI 組件。

engine.setEventHandler(new IZegoEventHandler() {
    @Override
    public void onPlayerRenderVideoFirstFrame(String streamID){
        super.onPlayerRenderVideoFirstFrame(streamID);
    }
}

視頻解析度變化的回調

1. 採集視頻解析度變更回調

可以通過註冊 onPublisherVideoSizeChanged 監聽採集視頻大小變更回調。推流成功後,在推流中途如果視頻採集解析度發生變化將會收到此回調。

當在未推流或未預覽的情況下,首次推流或首次預覽,即 SDK 內部的音視頻模塊的引擎啟動時,會去採集本機設備的視頻數據,此時採集解析度會改變。

可以根據此回調來去除本地預覽的 UI 的遮蓋等類似操作。也可以根據該回調的解析度來動態調整預覽視圖的比例等。

engine.setEventHandler(new IZegoEventHandler() {
    @Override
    public void onPublisherVideoSizeChanged(int width, int height, ZegoPublishChannel channel) {
        super.onPublisherVideoSizeChanged(width, height, channel);
    }
}

2. 拉流解析度變更通知

您可以通過註冊 onPlayerVideoSizeChanged 獲取拉流解析度變更通知。拉流成功後,在拉流中途如果有視頻解析度發生變化將會收到此回調,用戶可根據流的最終解析度調整顯示。

  • 若拉的流只有音頻數據,會收不到該回調。
  • 若推流端由於網路問題觸發 SDK 內部的流量控制時,可能會動態減小推流端的編碼解析度,此時也會收到此回調。所拉的音視頻流真正渲染到所設置 UI 播放界面時會觸發此回調。開發者可利用該回調通知來更新或切換真正播放流的 UI 組件。
engine.setEventHandler(new IZegoEventHandler() {
    @Override
    public void onPlayerVideoSizeChanged(String streamID, int width, int height) {
    }
}

API 參考列表

方法 描述
onPublisherQualityUpdate 推流質量回調
onPlayerQualityUpdate 拉流質量更新回調
onPublisherStateUpdate 推流狀態回調
onPlayerStateUpdate 拉流狀態回調
onPublisherCapturedAudioFirstFrame 推流端音頻採集首幀回調
onPublisherCapturedVideoFirstFrame 推流端視頻採集首幀回調
onPlayerRecvAudioFirstFrame 拉流端音頻接收首幀回調
onPlayerRecvVideoFirstFrame 拉流端視頻接收首幀回調
onPlayerRenderVideoFirstFrame 拉流端渲染完視頻首幀回調
onPublisherVideoSizeChanged 採集視頻大小變更回調
onPlayerVideoSizeChanged 拉流解析度變更通知
onPublisherRelayCDNStateUpdate 添加/刪除轉推 CDN 地址狀態回調
onPlayerRecvSEI 收到遠端流的 SEI 內容

獲取Demo

獲取本文的Demo、開發文檔、技術支持。
獲取SDK的商務活動、熱門產品。
註冊即構ZEGO開發者帳號,快速開始。

音視頻場景解決方案分享,更多詳情可搜索官網(https://zegoguanwang.datasink.sensorsdata.cn/t/pB)
您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 五一5天小假期的結束大家休息好了嗎?上班了狀態回整的怎麼樣呢?阿裡云云發平臺給大家帶福利了呢,通過玩游戲把獎品帶回家。 雲開發平臺兩周年,0門檻部署上線4款熱門游戲,游戲暢玩還有AirPods耳機、筋膜槍等8種獎品任你挑啦!4款游戲只需要完成2個就可以抽獎呢,100%中獎;還額外有故事有獎徵集的板塊 ...
  • 6、 1 鍵盤消息 // 4_4_例子Sysmets.cpp : 定義應用程式的入口點。 // #include "pch.h" #include "framework.h" #include "4_4_例子Sysmets.h" #include "data.h" #define MAX_LOADS ...
  • 本文例子參考《STM32單片機開發實例——基於Proteus虛擬模擬與HAL/LL庫》 源代碼:https://github.com/LanLinnet/STM33F103R6 項目要求 通過定時器延時(阻塞)的方式,實現LED燈以1秒為周期閃爍。 硬體設計 在第一節的基礎上,在Proteus中添加 ...
  • 一、DataStream API概述 Flink 中的 DataStream 程式是對數據流(例如過濾、更新狀態、定義視窗、聚合)進行轉換的常規程式。數據流的起始是從各種源(例如消息隊列、套接字流、文件)創建的。結果通過 sink 返回,例如可以將數據寫入文件或標準輸出(例如命令行終端)。Flink ...
  • 推薦文章: eclipse導入JDBC MySQL詳細安裝 菜鳥java MySQL連接教程 步驟: 找到MySQL的連接Java的jar文件; 如下圖: 在eclipse項目文件下找到lib文件夾,沒有的話就自己創建一個,然後將上面找到的jar文件複製粘貼到lib文件夾的下麵; 如下圖: 給這個j ...
  • 業務上雲的大背景對彈性與可靠性的要求越來越高,傳統架構的單機資料庫或是分片資料庫已經很難支撐快速增長的業務,如何解決這些痛點呢?一起來聽聽百度雲原生資料庫資深技術專家邱學達怎麼說。 ...
  • SQL語言基礎 SQL (Structured Query Language:結構化查詢語言) 是用於管理關係資料庫管理系統(RDBMS)。 SQL 的範圍包括數據插入、查詢、更新和刪除,資料庫模式創建和修改,以及數據訪問控制。 本文主要記錄一些主要的SQL命令(比如 SELECT、UPDATE、D ...
  • 一、使用PIVOT實現行轉列 1、首先創建一個學生表 CREATE TABLE [dbo].[Students]( [stu_id] [int] IDENTITY(1,1) NOT NULL, [stu_name] [varchar](100) NULL, [stu_hobby] [varchar] ...
一周排行
    -Advertisement-
    Play Games
  • 背景 在瀏覽器中訪問本地靜態資源html網頁時,可能會遇到跨域問題如圖。 是因為瀏覽器預設啟用了同源策略,即只允許載入與當前網頁具有相同源(協議、功能變數名稱和埠)的內容。 WebView2預設情況下啟用了瀏覽器的同源策略,即只允許載入與主機相同源的內容。所以如果我們把靜態資源發佈到iis或者通過node ...
  • 最近看幾個老項目的SQL條件中使用了1=1,想想自己也曾經這樣寫過,略有感觸,特別拿出來說道說道。編寫SQL語句就像炒菜,每一種調料的使用都會影響菜品的最終味道,每一個SQL條件的加入也會影響查詢的執行效率。那麼 1=1 存在什麼樣的問題呢?為什麼又會使用呢? ...
  • 好久不見,我又回來了。 給大家分享一個我最近使用c#代碼操作ftp伺服器的代碼示例: 1 public abstract class FtpOperation 2 { 3 /// <summary> 4 /// FTP伺服器地址 5 /// </summary> 6 private string f ...
  • 一:背景 1. 講故事 過年喝了不少酒,腦子不靈光了,停了將近一個月沒寫博客,今天就當新年開工寫一篇吧。 去年年初有位朋友找到我,說他們的系統會偶發性崩潰,在網上也發了不少帖子求助,沒找到自己滿意的答案,讓我看看有沒有什麼線索,看樣子這是一個牛皮蘚的問題,既然對方有了dump,那就分析起來吧。 二: ...
  • 自己製作的一個基於Entity Framework Core 的資料庫操作攔截器,可以列印資料庫執行sql,方便開發調試,代碼如下: /// <summary> /// EF Core 的資料庫操作攔截器,用於在資料庫操作過程中進行日誌記錄和監視。 /// </summary> /// <remar ...
  • 本文分享自華為雲社區《Go併發範式 流水線和優雅退出 Pipeline 與 Cancellation》,作者:張儉。 介紹 Go 的併發原語可以輕鬆構建流數據管道,從而高效利用 I/O 和多個 CPU。 本文展示了此類pipelines的示例,強調了操作失敗時出現的細微之處,並介紹了乾凈地處理失敗的 ...
  • 在上篇文章中,我們介紹到在多線程環境下,如果編程不當,可能會出現程式運行結果混亂的問題。出現這個原因主要是,JMM 中主記憶體和線程工作記憶體的數據不一致,以及多個線程執行時無序,共同導致的結果。 ...
  • 1、下載安裝包首先、進入官網下載安裝包網址:https://www.python.org/downloads/windows/下載步驟:進入下載地址,根據自己的電腦系統選擇相應的python版本 選擇適配64位操作系統的版本(查看自己的電腦操作系統版本), 點擊下載安裝包 也可以下載我百度雲分享的安 ...
  • 簡介 git-commit-id-maven-plugin 是一個maven 插件,用來在打包的時候將git-commit 信息打進jar中。 這樣做的好處是可以將發佈的某版本和對應的代碼關聯起來,方便查閱和線上項目的維護。至於它的作用,用官方說法,這個功能對於大型分散式項目來說是無價的。 功能 你 ...
  • 序言 在數字時代,圖像生成技術正日益成為人工智慧領域的熱點。 本討論將重點聚焦於兩個備受矚目的模型:DALL-E和其他主流AI繪圖方法。 我們將探討它們的優勢、局限性以及未來的發展方向。通過比較分析,我們期望能夠更全面地瞭解這些技術,為未來的研究和應用提供啟示。 Q: 介紹一下 dall-e Ope ...