通话中质量监测
更新时间: 2024/08/05 15:02:55
在通话场景中,开发者经常需要了解当前通话的通话质量、设备状态等信息,监测通话的整体体验;也可将部分质量数据在 UI 层面展示给用户,使用户能够及时了解当前通话的整体质量。
功能介绍
NERTC SDK 支持将关键的音视频状况、网络状况、设备状态的相关指标实时回调给 APP 应用层,应用层可以将收到的数据进行展示或统计。
方法或回调 | 功能描述 |
---|---|
network-quality 事件 | 获取本地用户的上下行网络质量相关的统计数据。 |
connection-state-change 事件 | 获取SDK与服务器的连接状态。 |
exception 事件 | 获取应用房间内的异常事件。 |
getTransportStats | 获取获取网络相关数据。 |
getLocalAudioStats | 获取本地发布流的音频统计数据。 |
getLocalVideoStats | 获取本地发布流的视频统计数据。 |
getRemoteAudioStats | 获取远端订阅流的音频统计数据。 |
getRemoteVideoStats | 获取远端订阅流的视频统计数据。 |
getSessionStats | 获取会话的连接状况统计数据。 |
示例项目
网易云信在 GitHub 上提供通话统计的开源示例项目 MediaStats,您可以前往下载体验,也可以在线体验此功能。
实现方法
上下行网络质量同步
云信 Web SDK 通过 client.on 中的 network-quality
回调向 App 同步房间里所有成员的上下行网络质量。每当网络质量发生变化的时候触发该回调,以数组的形式返回相应参数,参数说明如下表所示。
参数 | 描述 |
---|---|
downlinkNetworkQuality | 下行网络质量打分。 |
uplinkNetworkQuality | 上行网络质量打分。 |
uid | 网络质量对应的用户的 uid。 |
示例代码:
jsclient.on('network-quality', stats => {
console.log('=====房间里所有成员的网络状况:', stats)
let status = null
stats.forEach(item => {
status = 'uid: ' + item.uid + ',上行: ' + item.uplinkNetworkQuality + ',下行: ' + item.downlinkNetworkQuality
console.log(status)
})
})
参数说明:
质量打分数值 | 说明 |
---|---|
0 | 网络质量未知 |
1 | 网络质量极好 |
2 | 用户主观感觉和极好差不多,但码率可能略低于极好 |
3 | 能沟通但不顺畅 |
4 | 网络质量差 |
5 | 完全无法沟通 |
SDK与服务器的连接状态
云信 Web SDK 通过 client.on 中的 connection-state-change
回调向 App 同步sdk与服务器之间的连接状态发生改变。该回调每当发生变化的时候触发,返回的参数(对象格式),其中的元素包括:
- prevState:上一次的状态。
- curState:当前状态。
示例代码:
jsclient.on('connection-state-change', evt => {
console.log(evt.prevState, evt.curState);
})
SDK与服务器的连接状态参数说明:
类型 | 说明 |
---|---|
DISCONNECTED | 连接断开 |
CONNECTING | 正在连接中 |
CONNECTED | 已连接 |
DISCONNECTING | 正在断开连接 |
异常事件同步
该回调通知应用房间内的异常事件。 异常事件不是错误,但是往往会引起通话质量问题。 发生异常事件后,如果恢复正常,也会收到该回调通知。
示例代码:
jsclient.on("exception", function(evt) {
console.log(evt.code, evt.msg, evt.uid);
});
异常事件说明:
msg | code | 说明 |
---|---|---|
FRAMERATE_SENT_TOO_LOW | 1002 | 视频发送帧率过低 |
FRAMERATE_VIDEO_BITRATE_TOO_LOW | 1003 | 视频发送码率过低 |
RECV_VIDEO_DECODE_FAILED | 1005 | 接收视频解码失败 |
AUDIO_INPUT_LEVEL_TOO_LOW | 2001 | 发送音量过低 |
AUDIO_OUTPUT_LEVEL_TOO_LOW | 2002 | 接收音量过低 |
SEND_AUDIO_BITRATE_TOO_LOW | 2003 | 音频发送码率过低 |
RECV_AUDIO_DECODE_FAILED | 2005 | 接收音频解码失败 |
系统信息同步
该功能处于测试阶段,浏览器兼容信息请参考 Battery Status API。
调用 client.getSystemStats
方法获取系统信息。目前只能获取系统电量信息。
示例代码:
jssetInterval(async () => {
const systemStats = await rtc.client.getSystemStats();
if (systemStats){
console.log(`Current battery level: ${systemStats}`);
}
},1000);
网络相关数据
调用 client.getTransportStats 方法获取网络类型和网络连接状况统计数据。参数说明如下表所示。
参数 | 描述 |
---|---|
NetworkType | 网络类型,如 Wi-Fi、蜂窝移动数据网络、蓝牙网络等。 |
OutgoingAvailableBandwidth | 上行可用带宽估计(Kbps)。 |
txRtt | NERTC SDK到 NERTC 服务端的平均往返延时(RTT,Round-Trip Time),单位 ms。 |
示例代码:
jssetInterval(async () => {
const transportStats = await rtc.client.getTransportStats();
if (transportStats){
console.log(`Current Transport txRtt: ${transportStats.txRtt}`);
console.log(`Current Network Type: ${transportStats.NetworkType}`);
console.log(`Current Transport OutgoingAvailableBandwidth: ${transportStats.OutgoingAvailableBandwidth}`);
}
}, 1000)
获取当前会话的统计数据
本方法仅支持 Chrome 浏览器。
调用 client.getSessionStats 方法获取与当前会话相关的统计数据,参数说明如下表所示。
参数 |
描述 |
---|---|
Duration | 在当前房间内的时长(秒)。 |
RecvBitrate | 音视频总接收码率(Kbps),瞬间值。 |
RecvBytes | 接收字节数,累计值。 |
SendBitrate | 音视频总发送码率(Kbps),瞬间值。 |
SendBytes | 发送字节数,累计值。 |
UserCount | 通信场景下,该值为当前房间内的用户人数。 直播场景下,如果本地用户为主播,该值为当前房间内的主播人数;如果本地用户为观众,该值为当前房间内的主播人数 + 1。 |
示例代码:
jssetInterval(async() => {
const sessionStats = await rtc.client.getSessionStats();
if (sessionStats){
console.log(`Current Session Duration: ${sessionStats.Duration}`);
console.log(`Current Session UserCount: ${sessionStats.UserCount}`);
console.log(`Current Session SendBytes: ${sessionStats.SendBytes}`);
console.log(`Current Session RecvBytes: ${sessionStats.RecvBytes}`);
console.log(`Current Session SendBitrate: ${sessionStats.SendBitrate}`);
console.log(`Current Session RecvBitrate: ${sessionStats.RecvBitrate}`);
}
}, 1000)
音视频质量同步
本方法仅支持 Chrome 浏览器。
调用以下方法获取本地发布流的音频和视频统计数据。
本地流音频统计信息
client.getLocalAudioStats 方法提供本地发布流的音频统计数据,参数说明如下表所示。
参数 | 描述 |
---|---|
CodecType | 音频编码类型。 |
MuteState | 音频是否静音。 |
RecordingLevel | 音频采集能量。 |
SamplingRate | 音频采样率(kHz)。 |
SendBitrate | 音频发送码率(Kbps)。 |
SendLevel | 音频发送能量。 |
rtt | 音频上行的网络延时。即 NERTC SDK 发送数据包到 RTC 服务端,再从服务端返回到 NERTC SDK 的总耗时,单位为 ms。 |
示例代码:
jssetInterval(async () => {
const localAudioStats = await rtc.client.getLocalAudioStats();
if (localAudioStats[0]){
console.log(`===== localAudioStats =====`);
console.log(`Audio CodecType: ${localAudioStats[0].CodecType}`);
console.log(`Audio MuteState: ${localAudioStats[0].MuteState}`);
console.log(`Audio RecordingLevel: ${localAudioStats[0].RecordingLevel}`);
console.log(`Audio SamplingRate: ${localAudioStats[0].SamplingRate}`);
console.log(`Audio SendBitrate: ${localAudioStats[0].SendBitrate}`);
console.log(`Audio SendLevel: ${localAudioStats[0].SendLevel}`);
}
}, 1000)
本地流视频统计信息
本方法仅支持 Chrome 浏览器。
client.getLocalVideoStats 方法提供本地发布流的视频统计数据,一个 uid 对应一组数据,参数说明如下表所示。
参数 | 描述 |
---|---|
CaptureFrameRate | 视频采集帧率(fps)。 |
CaptureResolutionHeight | 视频采集分辨率高度,单位为像素。 |
+ CaptureResolutionWidth | 视频采集分辨率宽度,单位为像素。 |
示例代码:
jssetInterval(async () => {
const localVideoStats = await rtc.client.getLocalVideoStats();
if (localVideoStats[0]){
console.log(`Video CaptureFrameRate from : ${localVideoStats[0].CaptureFrameRate}`);
console.log(`Video CaptureResolutionHeight from : ${localVideoStats[0].CaptureResolutionHeight}`);
console.log(`Video CaptureResolutionWidth from : ${localVideoStats[0].CaptureResolutionWidth}`);
console.log(`Video EncodeDelay from : ${localVideoStats[0].EncodeDelay}`);
console.log(`Video MuteState from : ${localVideoStats[0].MuteState}`);
console.log(`Video SendBitrate from : ${localVideoStats[0].SendBitrate}`);
console.log(`Video SendFrameRate from : ${localVideoStats[0].SendFrameRate}`);
console.log(`Video SendResolutionHeight from : ${localVideoStats[0].SendResolutionHeight}`);
console.log(`Video SendResolutionWidth from : ${localVideoStats[0].SendResolutionWidth}`);
console.log(`Video TargetSendBitrate from : ${localVideoStats[0].TargetSendBitrate}`);
console.log(`Video TotalDuration from : ${localVideoStats[0].TotalDuration}`);
console.log(`Video TotalFreezeTime from : ${localVideoStats[0].TotalFreezeTime}`);
}
}, 1000)
远端流音频统计信息
本方法仅支持 Chrome 浏览器。
Client.getRemoteAudioStats 方法提供远端订阅流的音频统计数据,一个 uid 对应一组数据,参数说明如下表所示。
参数 | 描述 |
---|---|
CodecType | 音频编码类型。 |
End2EndDelay | 端到端延时(ms),从远端采集音频到本地播放音频的延时。 |
MuteState | 音频是否静音。 |
PacketLossRate | 远端音频的丢包率(%)。 |
RecvBitrate | 音频接收码率(Kbps)。 |
RecvLevel | 接收音频的音量。 |
TotalFreezeTime | 音频卡顿总时间(s)。 |
TotalPlayDuration | 音频播放总时长(s)。 |
TransportDelay | 传输延时(ms),从远端发送音频到本地接收音频的延时。 |
示例代码:
jssetInterval(async () => {
const remoteAudioStats = await rtc.client.getRemoteAudioStats();
if (remoteAudioStats){
console.log(`Audio CodecType from ${uid}: ${remoteAudioStatsMap[uid].CodecType}`);
console.log(`Audio End2EndDelay from ${uid}: ${remoteAudioStatsMap[uid].End2EndDelay}`);
console.log(`Audio MuteState from ${uid}: ${remoteAudioStatsMap[uid].MuteState}`);
console.log(`Audio PacketLossRate from ${uid}: ${remoteAudioStatsMap[uid].PacketLossRate}`);
console.log(`Audio RecvBitrate from ${uid}: ${remoteAudioStatsMap[uid].RecvBitrate}`);
console.log(`Audio RecvLevel from ${uid}: ${remoteAudioStatsMap[uid].RecvLevel}`);
console.log(`Audio TotalFreezeTime from ${uid}: ${remoteAudioStatsMap[uid].TotalFreezeTime}`);
console.log(`Audio TotalPlayDuration from ${uid}: ${remoteAudioStatsMap[uid].TotalPlayDuration}`);
console.log(`Audio TransportDelay from ${uid}: ${remoteAudioStatsMap[uid].TransportDelay}`);
}
}, 1000)
远端流视频统计信息
本方法仅支持 Chrome 浏览器。
client.getRemoteVideoStats 方法提供远端订阅流的视频统计数据,一个 uid 对应一组数据,参数说明如下表所示。
参数 | 描述 |
---|---|
End2EndDelay | 端到端延时(ms),从远端采集视频到本地播放视频的延时。 |
MuteState | 视频画面是否开启。 |
PacketLossRate | 远端视频的丢包率(%)。 |
RecvBitrate | 视频接收码率(Kbps)。 |
RecvResolutionHeight | 视频接收分辨率高度,单位为像素。 |
RecvResolutionWidth | 视频接收分辨率宽度,单位为像素。 |
RenderFrameRate | 渲染帧率(fps),视频解码输出帧率。 |
RenderResolutionHeight | 视频渲染分辨率高度,单位为像素。 |
RenderResolutionWidth | 视频渲染分辨率宽度,单位为像素。 |
TotalFreezeTime | 视频卡顿总时间,单位为秒。 |
TotalPlayDuration | 视频播放总时间,单位为秒。 |
TransportDelay | 传输延时(ms),从远端发送视频到本地接收视频的延时。 |
示例代码:
jssetInterval(async () => {
const remoteVideoStats = await rtc.client.getRemoteVideoStats();
if (remoteVideoStats){
console.log(`Video End2EndDelay from ${uid}: ${remoteVideoStatsMap[uid].End2EndDelay}`);
console.log(`Video MuteState from ${uid}: ${remoteVideoStatsMap[uid].MuteState}`);
console.log(`Video PacketLossRate from ${uid}: ${remoteVideoStatsMap[uid].PacketLossRate}`);
console.log(`Video RecvBitrate from ${uid}: ${remoteVideoStatsMap[uid].RecvBitrate}`);
console.log(`Video RecvResolutionHeight from ${uid}: ${remoteVideoStatsMap[uid].RecvResolutionHeight}`);
console.log(`Video RecvResolutionWidth from ${uid}: ${remoteVideoStatsMap[uid].RecvResolutionWidth}`);
console.log(`Video RenderFrameRate from ${uid}: ${remoteVideoStatsMap[uid].RenderFrameRate}`);
console.log(`Video RenderResolutionHeight from ${uid}: ${remoteVideoStatsMap[uid].RenderResolutionHeight}`);
console.log(`Video RenderResolutionWidth from ${uid}: ${remoteVideoStatsMap[uid].RenderResolutionWidth}`);
console.log(`Video TotalFreezeTime from ${uid}: ${remoteVideoStatsMap[uid].TotalFreezeTime}`);
console.log(`Video TotalPlayDuration from ${uid}: ${remoteVideoStatsMap[uid].TotalPlayDuration}`);
console.log(`Video TransportDelay from ${uid}: ${remoteVideoStatsMap[uid].TransportDelay}`);
}
}, 1000)