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

示例原始碼
參考 下載示例原始碼 獲取原始碼,
相關原始碼請查看 “/ZegoExpressExample/AdvancedStreaming/src/main/java/im/zego/streammonitoring” 目錄下的檔案,
前提條件
在監測通話質量之前,請確保:
- 已在專案中集成 ZEGO Express SDK,實作基本的實時音視頻功能,詳情請參考 快速開始 - 集成 和 快速開始 - 實作流程,
- 已在 ZEGO 控制臺 創建專案,并申請有效的 AppID,詳情請參考 控制臺 - 專案管理 中的“專案資訊”,
基礎網路質量報告
可以通過監聽 onNetworkQuality 回呼,收到房間內用戶(包括自己)的上下行網路質量,此回呼每隔兩秒會收到一次,網路質量等級請參考 ZegoStreamQualityLevel,
不同版本的 onNetworkQuality 回呼邏輯有所不同:
-
對于使用 2.14.0 及以上版本 ZEGO Express SDK 的用戶,
onNetworkQuality回呼的邏輯為:- 只要推流或者拉流,就能收到自己的網路質量回呼,
- 當拉取了其他用戶推送的音視頻流并且該用戶在房間內時,才會收到該用戶的網路質量回呼,
- 當 “userID” 為 “null” 時,代表本次是自己的網路質量,當 “userID” 不為 “null” 時,代表是房間內其他用戶的報告,
-
對于使用 2.10.0 至 2.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://www.uj5u.com/yidong/471854.html
標籤:Android
上一篇:日呼叫量超600億次,HMS Core HiAI Foundation助力AI應用高效開發
下一篇:iOS 組件化及二進制化的探索
