如何基于 ZEGO SDK 实现 Android 通话质量监测
功能简介
在进行视频通话过程中,用户有时候会出现网络不好的情况,比如在进行多人视频通话或者多人唱歌时,我们需要实时显示用户的网络质量。
示例源码
参考 下载示例源码 获取源码。
相关源码请查看 “/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. 拉流分辨率变更通知
@@@Pull_stream_resolution_change_notification@@@
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开发者帐号,快速开始。
如何基于 ZEGO SDK 实现 Android 通话质量监测的更多相关文章
- 如何基于 ZEGO SDK 实现 Android 一对一音视频聊天应用
疫情期间,很多线下活动转为线上举行,实时音视频的需求剧增,在视频会议,在线教育,电商购物等众多场景成了"生活新常态". 本文将教你如何通过即构ZEGO sdk在Android端搭建 ...
- 如何基于ZEGO SDK 实现通话质量监测
如何基于ZEGO SDK 实现通话质量监测 1 功能简介 在进行视频通话过程中,用户有时候会出现网络不好的情况,比如在进行多人视频通话或者多人唱歌时,我们需要实时显示用户的网络质量. 示例源码 请参考 ...
- 如何基于 ZEGO SDK 实现 Flutter 一对一音视频聊天应用?
之前的文章发布了ZEGO SDK实现Android端音视频通话应用的开发教程,不少开发者反馈很实用,能不能也出一版Flutter的教程. 有求必应,这不小编来了- 我们封装了ZEGO Flutter ...
- 如何基于 ZEGO SDK 实现 Windows 一对一音视频聊天应用
互联网发展至今,实时视频和语音通话越来越被大众所依赖. 今天,我们将会继续介绍如何基于ZEGO SDK实现音视频通话功能,前两篇文章分别介绍了Android,Flutter平台的实现方式,感兴趣的小伙 ...
- 点聚合功能---基于ARCGIS RUNTIME SDK FOR ANDROID
一直不更新博客的原因,如果一定要找一个,那就是忙,或者说懒癌犯了. 基于ArcGIS RunTime SDK for Android的点聚合功能,本来是我之前做过的一个系统里面的一个小部分,今天抽出一 ...
- 《ArcGIS Runtime SDK for Android开发笔记》——(4)、基于Android Studio构建ArcGIS Android开发环境
1.前言 2015年1月15日,发布ArcGIS Runtime SDK for Android v10.2.5版本.从该版本开始默认支持android studio开发环境,示例代码的默认开发环境也 ...
- 《ArcGIS Runtime SDK for Android开发笔记》——(5)、基于Android Studio构建ArcGIS Android开发环境(离线部署)(转)
1.前言 在上一篇的内容里我们介绍了基于Android Studio构建ArcGIS Runtime SDK for Android开发环境的基本流程,流程中我们采用的是基于Gradle的构建方式,在 ...
- 《ArcGIS Runtime SDK for Android开发笔记》——(6)、基于Android Studio的ArcGIS Android工程结构解析
1.前言 Android Studio 是第一个Google官方的 Android 开发环境.其他工具,例如 Eclipse,在 Android Studio 发布之前已经有了大规模的使用.为了帮助开 ...
- 在Android上实现使用Facebook登录(基于Facebook SDK 3.5)
准备工作: 1. Facebook帐号,国内开发者需要一个vpn帐号(网页可以浏览,手机可以访问) 2. 使用Facebook的SDK做应用需要一个Key Hashes值. 2 ...
随机推荐
- remote debug 的详细配置
一.remote debug 的简单介绍 何为远程debug,项目写完后就需要进入到测试环节,将代码打包发布到测试环境(服务器)上.这时候测试人员测试出一个缺陷(bug).由于代码已经发布到测试环境, ...
- Matplotlib is currently using agg, which is a non-GUI backend 和 ImportError: No module named 'Tkinter' [closed]
跑maskrcnn报错:UserWarning: Matplotlib is currently using agg, which is a non-GUI backend, so cannot sh ...
- 全面系统讲解CSS工作应用+面试一步搞定
[TOC] 一.课程介绍 二.HTML基础强化 html常见元素和理解 html常见元素分类 head区元素:(不会在页面上留下元素) * meta * title * style * link * ...
- 【Android开发】【布局】各种TabLayout样式
Demo
- CCF201409-2 画图
问题描述 在一个定义了直角坐标系的纸上,画一个(x1,y1)到(x2,y2)的矩形指将横坐标范围从x1到x2,纵坐标范围从y1到y2之间的区域涂上颜色. 下图给出了一个画了两个矩形的例子.第一个矩形是 ...
- mysql8.0.13本地安装忘记密码解决办法
之前一直用图形化界面,加上考研期间也没动,竟然把我的数据库密码给忘了,无地自容....... 找了找教程,问题如下: MySQL从低版本向高版本迭代变化的过程,越来越严谨的安全性是其一大特点之一,在版 ...
- audio小记
写H5活动页的需要音频,图标旋转停止保持当时的旋转角度,这样视觉体验效果好: 之前写法是点击pause()就直接停止动画,后来发现了animation有个比较好的属性animation-play-st ...
- Thinkphp3.2.3 where注入 浅分析漏洞原理及修复
0x01引子 0x02分析 找到截断方法 找到_parseType的入口 找到生成sql语句的代码 0x03 poc链 0x04 利用示范 payload: http://localhost:3000 ...
- C#多线程下的调优
一.原子操作 先看一段问题代码 /// <summary> /// 获取自增 /// </summary> public static void GetIncrement() ...
- CPU乱序执行问题
CPU为了提高执行效率,会在一条指令执行的过程中(比如去内存读数据,读数据的过程相较于CPU的执行速度慢100倍以上,cpu处于等待状态),这个时候cpu会分析接下来的指令是否正在执行的指令相关联,如 ...