通话中质量监测

更新时间: 2024/09/18 16:26:13

在通话场景中,开发者经常需要了解当前通话的通话质量、设备状态等信息,监测通话的整体体验;也可将部分质量数据在 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 视频采集分辨率宽度,单位为像素。
EncodeDelay 本地视频从采集到编码的延时(ms)。
MuteState 视频画面是否开启。
SendBitrate 视频发送码率(Kbps)。
SendFrameRate 视频发送帧率(fps)。
SendResolutionHeight 视频发送分辨率高度,单位为像素。
SendResolutionWidth 视频发送分辨率宽度,单位为像素。
TotalDuration 从视频流发布到当前时间的总时长,单位为秒。
TotalFreezeTime 视频编码卡顿总时间,单位为秒。

示例代码:

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 remoteAudioStatsMap = await rtc.client.getRemoteAudioStats();
  for(var uid in remoteAudioStatsMap){
      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 remoteVideoStatsMap = await rtc.client.getRemoteVideoStats();
   for(var uid in remoteVideoStatsMap){
     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)
此文档是否对你有帮助?
有帮助
去反馈
  • 功能介绍
  • 示例项目
  • 实现方法
  • 上下行网络质量同步
  • SDK与服务器的连接状态
  • 异常事件同步
  • 系统信息同步
  • 网络相关数据
  • 获取当前会话的统计数据
  • 音视频质量同步
  • 本地流音频统计信息
  • 本地流视频统计信息
  • 远端流音频统计信息
  • 远端流视频统计信息