加入频道后,SDK 会每隔 2 秒自动触发通话质量相关的下述回调,你可以了解当前通话的网络质量、本地统计信息、音频质量和视频质量。
我们在 GitHub 提供一个开源的 OpenLive-Windows 示例项目。
我们在 GitHub 上提供已实现通话中质量监测功能的开源示例项目。你可以下载体验并参考源代码
onNetworkQuality
回调向你报告当前通话中每个用户/主播的上下行 last mile 网络质量,详见质量打分。其中,last mile 是指你的设备到声网边缘服务器的网络。上行 last mile 网络质量打分基于实际发送码率、上行网络丢包率、平均往返时延和上行网络抖动计算;下行 last mile 网络质量打分基于下行网络丢包率、平均往返时延和下行网络抖动计算。
virtual void onNetworkQuality(uid_t uid, int txQuality, int rxQuality)override {
;
}
onRtcStats
回调向你报告本地通话统计信息。你可以了解到通话时长、当前通话频道中的人数、当前系统的 CPU 使用率、当前 App 的 CPU 使用率和以下重要参数。
参数 | 描述 | 备注 |
---|---|---|
txBytes /rxBytes |
累计发送/接收字节数。 | 自加入频道后累计的字节数。 |
txAudioBytes /rxAudioByte |
累计发送/接收音频字节数。 | 自加入频道后累计的字节数。 |
txVideoBytes /rxVideoBytes |
累计发送/接收视频字节数。 | 自加入频道后累计的字节数。 |
txKBitRate /rxKBitRate |
发送/接收码率。 | 统计周期内实际发送/接收的码率。 |
txAudioKBitRate /rxAudioKBitRate |
音频发送/接收码率。 | 统计周期内实际发送/接收的码率。 |
txVideoKBitRate /rxVideoKBitRate |
视频发送/接收码率。 | 统计周期内实际发送/接收的码率。 |
lastmileDelay |
本地客户端到声网边缘服务器的网络延迟。 | |
txPacketLossRate |
本地客户端到声网边缘服务器的丢包率。 | |
rxPacketLossRate |
声网边缘服务器到本地客户端的丢包率。 |
virtual void onRtcStats(const RtcStats& stats) {
if (m_hMsgHanlder)
::PostMessage(m_hMsgHanlder, WM_MSGID(EID_RTC_STATS),(WPARAM)new RtcStats(stats), 0);
}
LRESULT CAgoraReportInCallDlg::OnEIDRtcStats(WPARAM wParam, LPARAM lParam)
{
RtcStats *p = reinterpret_cast<RtcStats *>(wParam);
if (p)
{
CString tmp;
tmp.Format(_T("%dKbps/%dKbps"), p->txKBitRate, p->rxKBitRate);
m_staTotalBitrateVal.SetWindowText(tmp);
tmp.Format(_T("%.2fMB/%.2fMB"), p->txBytes ? p->txBytes / 1024.0 / 1024 : 0, p->rxBytes ? p->rxBytes / 1024.0 / 1024 : 0);
m_staTotalBytesVal.SetWindowText(tmp);
delete p;
}
return TRUE;
}
onLocalAudioStats
回调向你报告本地设备发送音频流的统计信息。你可以了解到当前通话声道数(单声道或双声道)、发送音频的采样率和发送音频的码率。
SDK 会每隔 2 秒自动触发本回调,发送音频的采样率指统计周期内发送音频的实际采样率,发送音频的码率指统计周期内发送音频码率的平均值。
virtual void onLocalAudioStats(const LocalAudioStats& stats) {
(void)stats;
}
本地音频的状态发生改变时(包括本地麦克风录制状态和音频编码状态),SDK 会触发 onLocalAudioStateChanged
回调向你报告当前本地音频状态。当本地音频出现故障时,你可以通过错误码排查问题。
virtual void onLocalAudioStateChanged(LOCAL_AUDIO_STREAM_STATE state, LOCAL_AUDIO_STREAM_ERROR error) {
(void)state;
(void)error;
}
onRemoteAudioStats
回调向你报告当前通话中每个远端用户/主播音频流的统计信息。你可以了解到每个远端用户/主播发送的音频流质量(详见质量打分)、声道数(单声道或双声道)和以下重要参数信息。
参数 | 描述 | 备注 |
---|---|---|
networkTransportDelay |
音频发送端到接收端的网络延迟。 | 图中阶段 2 + 3 + 4 |
jitterBufferDelay |
接收端到网络抖动缓冲端的网络延迟。 | 图中阶段 5 |
audioLossRate |
统计周期内,实际接收到的远端音频流丢帧率。 | |
receivedSampleRate |
统计周期内,接收到的远端音频流的采样率。 | |
receivedBitrate |
统计周期内,接收到的远端音频流的平均码率。 | |
totalFrozenTime |
远端用户/主播在加入频道后发生音频卡顿的累计时长。 | totalFrozenTime = 音频卡顿次数 × 2 × 1000 (毫秒)。 |
frozenRate |
远端用户/主播音频卡顿累计时长占音频总有效时长的百分比。 | 音频总有效时长指的是远端用户/主播加入频道后,既没有停止发送音频流,也没有禁用音频模块的通话时长。 |
qoeQuality |
接收远端音频时,本地用户的主观体验质量。 | |
qualityChangedReason |
接收远端音频时,本地用户主观体验质量较差的原因。 | |
mosValue |
统计周期内,声网实时音频 MOS(平均主观意见分)评估系统对接收到的远端音频流的质量评分。 |
onRemoteAudioStats
侧重报告远端音频流的全链路音频质量,更贴近你的主观感受。即使网络发生丢包,因为 FEC(Forward Error Correction)、重传恢复和带宽估计等抗丢包和拥塞控制技术,最终在接收端的音频丢帧率也可能不高,所以你感知到的音频质量也可能较好。
- 在通信场景下,每隔 2 秒你会收到频道内所有远端用户(不包括你自己)的音频流统计信息。
- 在直播场景下,如果你是主播,每隔 2 秒你会收到频道内所有远端主播(不包括你自己)的音频流统计信息;如果你是观众,每隔 2 秒你会收到频道内所有远端主播的音频流统计信息。
- 声网音频模块指音频处理过程,而不是 SDK 中的模块实物。发送音频流时,音频模块指音频采样、前处理、编码等处理过程;接收音频流时,音频模块指音频解码、后处理、播放等处理过程。
- 用户只能开启/禁用自己的音频模块。
- 声网默认一个统计周期内的的音频卡顿不会多于 1 次。
virtual void onRemoteAudioStats(const RemoteAudioStats& stats) {
if (m_hMsgHanlder)
::PostMessage(m_hMsgHanlder, WM_MSGID(EID_REMOTE_AUDIO_STATS), (WPARAM)new RemoteAudioStats(stats), 0);
}
LRESULT CAgoraReportInCallDlg::OnEIDRemoteAudioStats(WPARAM wParam, LPARAM lParam)
{
RemoteAudioStats *p = reinterpret_cast<RemoteAudioStats *>(wParam);
if (p)
{
CString tmp;
tmp.Format(_T("%dms"), p->networkTransportDelay);
m_staAudioNetWorkDelayVal.SetWindowText(tmp);
tmp.Format(_T("%dKbps"), p->receivedBitrate);
m_staAudioRecvBitrateVal.SetWindowText(tmp);
delete p;
}
return TRUE;
}
远端用户/主播音频状态发生改变时,SDK 会触发 onRemoteAudioStateChanged
回调向你报告远端音频流当前状态和状态改变的原因。
- 在通信场景下,本回调向你报告频道内所有远端用户(不包括你自己)的音频流状态信息。
- 在直播场景下,如果你是主播,本回调向你报告频道内所有远端主播(不包括你自己)的音频流状态信息;如果你是观众,本回调向你报告频道内所有远端主播的音频流状态信息。
virtual void onRemoteAudioStateChanged(uid_t uid, REMOTE_AUDIO_STATE state, REMOTE_AUDIO_STATE_REASON reason, int elapsed) {
(void)uid;
(void)state;
(void)reason;
(void)elapsed;
}
onLocalVideoStats
回调向你报告本地设备发送视频流的统计信息。你可以了解视频编码宽/高和以下重要参数信息。
如果你此前调用
enableDualStreamMode
方法开启双流模式,则本回调描述本地设备发送的视频大流的统计信息。
参数 | 描述 | 备注 |
---|---|---|
rendererOutputFrameRate |
本地视频渲染器的输出帧率。 | |
encoderOutputFrameRate |
本地视频编码器的输出帧率。 | |
targetBitrate |
当前编码器的目标编码码率。 | 该码率为 SDK 根据当前网络状况预估的一个值。 |
targetFrameRate |
当前编码器的目标编码帧率。 | |
encodedBitrate |
视频编码码率。 | 不包含丢包后重传视频等的视频码率。 |
sentBitrate |
统计周期内,实际发送视频码率。 | 不包含丢包后重传视频等的视频码率。 |
sentFrameRate |
统计周期内,实际发送视频帧率。 | 不包含丢包后重传视频等的视频帧率。 |
encodedFrameCount |
视频发送的累计帧数。 | 自加入频道后的累计值。 |
codecType |
视频的编码类型。 | VIDEO_CODEC_VP8 = 1 : VP8VIDEO_CODEC_H264 = 2 : (默认值)H.264 |
qualityAdaptIndication |
本次统计的视频质量自适应情况。 | 相比上次统计(2 秒前)视频质量(基于目标码率/targetBitrate 和目标帧率/targetFrameRate ),本次视频质量的情况: |
virtual void onLocalVideoStats(const LocalVideoStats& stats) {
if (m_hMsgHanlder)
::PostMessage(m_hMsgHanlder, WM_MSGID(EID_LOCAL_VIDEO_STATS), (WPARAM)new LocalVideoStats(stats), 0);
}
LRESULT CAgoraReportInCallDlg::OnEIDLocalVideoStats(WPARAM wParam, LPARAM lParam)
{
LocalVideoStats *p = reinterpret_cast<LocalVideoStats *>(wParam);
if (p)
{
CString tmp;
tmp.Format(_T("%d fps"), p->sentFrameRate);
m_staLocalVideoFPSVal.SetWindowText(tmp);
tmp.Format(_T("%d X %d"), p->encodedFrameWidth, p->encodedFrameHeight);
m_staLocalVideoResoultionVal.SetWindowText(tmp);
delete p;
}
return TRUE;
}
本地视频的状态发生改变时,SDK 会触发 onLocalVideoStateChanged
回调向你报告当前本地视频状态。当本地视频出现故障时,你可以通过错误码排查问题。
virtual void onLocalVideoStateChanged(LOCAL_VIDEO_STREAM_STATE localVideoState, LOCAL_VIDEO_STREAM_ERROR error) {
(void)localVideoState;
(void)error;
}
onRemoteVideoStats
回调向你报告当前通话中每个远端用户/主播的视频流的统计信息。你可以了解到每个远端用户/主播的视频宽/高和以下重要参数信息。
参数 | 描述 | 备注 |
---|---|---|
rxStreamType |
视频流类型。 | 视频大流或小流,详见双流模式。 |
receivedBitrate |
统计周期内,实际接收到的远端视频码率。 | |
packetLossRate |
统计周期内,实际接收到的远端视频流丢包率。 | |
decoderOutputFrameRate |
远端视频解码器的输出帧率。 | |
rendererOutputFrameRate |
远端视频渲染器的输出帧率。 | |
totalFrozenTime |
远端用户/主播在加入频道后发送视频卡顿的累计时长。 | 通话过程中,视频帧率设置不低于 5 fps 时,连续渲染的两帧视频之间间隔超过 500 ms,则计为一次视频卡顿。 |
frozenRate |
远端用户/主播卡顿累计时长占视频有效时长的百分比。 | 视频有效时长指远端用户/主播加入频道后,既没有停止发送视频流,也没有禁用视频模块的通话时长。 |
- 在通信场景下,每隔 2 秒你会收到频道内所有远端用户(不包括你自己)的视频流统计信息。
- 在直播场景下,如果你是主播,每隔 2 秒你会收到频道内所有远端主播(不包括你自己)的视频流统计信息;如果你是观众,每隔 2 秒你会收到频道内所有远端主播的视频流统计信息。
- 声网视频模块指视频处理过程,而不是 SDK 中的模块实物。发送视频流时,视频模块指视频采集、前处理、编码等处理过程;接收视频流时,视频模块指视频解码、后处理、渲染/播放等处理过程。
- 用户只能开启/禁用自己的视频模块。
virtual void onLocalVideoStateChanged(LOCAL_VIDEO_STREAM_STATE localVideoState, LOCAL_VIDEO_STREAM_ERROR error) {
(void)localVideoState;
(void)error;
}
远端用户/主播的视频流状态改变时,SDK 会触发 onRemoteVideoStateChanged
回调向你报告远端视频流当前状态和状态改变的原因。
- 在通信场景下,本回调向你报告频道内所有远端用户(不包括你自己)的视频流状态信息。
- 在直播场景下,如果你是主播,本回调向你报告频道内所有远端主播(不包括你自己)的视频流状态信息;如果你是观众,本回调向你报告频道内所有远端主播的视频流状态信息。
virtual void onRemoteVideoStateChanged(uid_t uid, REMOTE_VIDEO_STATE state, REMOTE_VIDEO_STATE_REASON reason, int elapsed) override
{
if (m_hMsgHanlder) {
PVideoStateStateChanged stateChanged = new VideoStateStateChanged;
stateChanged->uid = uid;
stateChanged->reason = reason;
stateChanged->state = state;
::PostMessage(m_hMsgHanlder, WM_MSGID(EID_REMOTE_VIDEO_STATE_CHANED), (WPARAM)stateChanged, 0);
}
}
onNetworkQuality
onRtcStats
onLocalAudioStats
onLocalAudioStateChanged
onRemoteAudioStats
onRemoteAudioStateChanged
onLocalVideoStats
onLocalVideoStateChanged
onRemoteVideoStats
onRemoteVideoStateChanged
onLocalAudioStateChanged
、onRemoteAudioStateChanged
、onLocalVideoStateChanged
和 onRemoteVideoStateChanged
状态监控回调不会每 2 秒被 SDK 自动触发,各自触发条件详见正文。