After joining the channel, the SDK triggers the following callbacks related to the call quality once every two seconds. You can see the last mile network quality, local statistics, audio quality, and video quality of the current call.
We provide an open-source OpenLive-Windows demo project.
Agora provides an open-source sample project on GitHub that implements the in-call statistics monitoring function. You can download the sample project to try it out or view the source code.
The onNetworkQuality
callback reports the uplink and downlink last mile network quality of each user/host in the current call, see Quality Rating for details. Last mile refers to the network from your device to Agora’s edge server. The uplink last mile quality rating is based on the actual transmission bitrate, the uplink network packet loss rate, the average round-trip delay, and the uplink network jitter; while the downlink last mile quality rating is based on the downlink network packet loss rate, the average round-trip delay, and the downlink network jitter.
Note:
COMMUNICATION
profile, you receive network quality reports of all the users (including yours) in the channel once every two seconds.LIVE_BROADCASTING
profile, if you are the host, you receive network quality reports of all hosts (including yours) in the channel once every two seconds; if you are the audience, you receive the report of all hosts and yourself once every two seconds.virtual void onNetworkQuality(uid_t uid, int txQuality, int rxQuality)override {
;
}
The onRtcStats
callback reports call statistics. You can see the duration, the number of users in the channel, the system CPU usage, the application CPU usage, and the following parameters of the current call.
Parameter | Description | Comment |
---|---|---|
txBytes /rxBytes |
The total number of bytes sent/received. | The number of bytes accumulated since joining the channel. |
txAudioBytes /rxAudioByte |
The total number of audio bytes sent/received. | The number of bytes accumulated since joining the channel. |
txVideoBytes /rxVideoBytes |
The total number of video bytes sent/received. | The number of bytes accumulated since joining the channel. |
txKBitRate /rxKBitRate |
The bitrate sent/received. | The actual bitrate sent/received in the reported interval. |
txAudioKBitRate /rxAudioKBitRate |
The bitrate sent/received of the audio packet. | The actual bitrate sent/received in the reported interval. |
txVideoKBitRate /rxVideoKBitRate |
The bitrate sent/received of the video packet. | The actual bitrate sent/received in the reported interval. |
lastmileDelay |
The network delay from the local client to Agora’s edge server. | |
txPacketLossRate |
The packet loss rate from the local client to Agora’s edge server. | |
rxPacketLossRate |
The packet loss rate from Agora’s edge server to the local client. |
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;
}
The onLocalAudioStats
callback reports the statistics of the audio streams sent. You can see the number of channels (mono or dual), the sample rate, and the average sending bitrate in the reported interval.
Note:
The SDK triggers this callback once every two seconds. The sample rate refers to the actual sample rate of the audio streams sent in the reported interval.
virtual void onLocalAudioStats(const LocalAudioStats& stats) {
(void)stats;
}
When the state of the local audio stream changes (including the state of the audio recording and encoding), the SDK triggers the onLocalAudioStateChanged
callback to report the current state. You can troubleshoot with the error code when exceptions occur.
virtual void onLocalAudioStateChanged(LOCAL_AUDIO_STREAM_STATE state, LOCAL_AUDIO_STREAM_ERROR error) {
(void)state;
(void)error;
}
The onRemoteAudioStats
callback reports the audio statistics of each remote user/host in the current call. You can see the quality of the audio stream sent by each remote user/host (see Quality Rating), the number of channels (mono or dual), and the following parameters.
Parameter | Description | Comment |
---|---|---|
networkTransportDelay |
The network delay from the sender to the receiver. | Stages 2 + 3 + 4 in the figure above |
jitterBufferDelay |
The network delay from the receiver to the network jitter buffer. | Stage 5 in the figure above |
audioLossRate |
The frame loss rate of the received remote audio streams in the reported interval. | |
receivedSampleRate |
The sample rate of the received remote audio streams in the reported interval. | |
receivedBitrate |
The average bitrate of the received remote audio streams in the reported interval. | |
totalFrozenTime |
The total freeze time (ms) of the remote audio streams after the remote user joins the channel. | totalFrozenTime = The number of times the audio freezes × 2 × 1000 (ms). |
frozenRate |
The total audio freeze time is a percentage of the total time when the audio is available. | When the remote user/host neither stops sending the audio stream nordisables the audio module after joining the channel, the audio is available. |
qoeQuality |
Quality of experience (QoE) of the local user when receiving a remote audio stream. | |
qualityChangedReason |
The reason for poor QoE of the local user when receiving a remote audio stream. | |
mosValue |
The quality of the remote audio stream as determined by the Agora real-time audio MOS (Mean Opinion Score) measurement system in the reported interval. |
The onRemoteAudioStats
callback reports statistics more closely linked to the real-user experience of the audio transmission quality. Even if network packet loss occurs, users may find the overall audio quality acceptable because the audio frame loss rate of the received audio streams may not be high due to the anti-packet-loss and congestion control methods, such as forward error correction (FEC), retransmissions and bandwidth estimation.
Note:
COMMUNICATION
profile, you receive the audio stream statistics of all the remote users (excluding yours) in the channel once every two seconds.LIVE_BROADCASTING
profile, if you are the host, you receive the audio stream statistics of all remote hosts (excluding yours) in the channel once every two seconds; if you are the audience, you receive the statistics of all hosts in the channel once every two seconds.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;
}
When the state of remote audio stream changes, the SDK triggers the onRemoteAudioStateChanged
callback to report the current state and the reason for the state change.
Note:
COMMUNICATION
profile, this callback reports to you the audio stream state information of all the remote users (excluding yours) in the channel once every two seconds.LIVE_BROADCASTING
profile, if you are the host, this callback reports to you the audio stream state information of all the remote hosts(excluding yours) in the channel once every two seconds; if you are the audience, this callback reports to you the audio stream state information of all the remote hosts in the channel once every two seconds.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;
}
The onLocalVideoStats
callback reports the statistics of the video streams sent. You can see the dimensions of the encoding frame and the following parameters.
Note:
If you have called the enableDualStreamMode
method to enable dual-stream mode, this callback reports the statistics of the high-video streams sent.
Parameter | Description | Comment |
---|---|---|
rendererOutputFrameRate |
The output frame rate of the local video renderer. | |
encoderOutputFrameRate |
The output frame rate of the local video encoder. | |
targetBitrate |
The target bitrate of the current encoder. | This value is estimated by the SDK based on current network conditions. |
targetFrameRate | The target frame rate of the current encoder. | |
encodedBitrate |
The bitrate of the encoding video. | Does not include the bitrate of the retransmission videos. |
sentBitrate |
The bitrate of the video sent in the reported interval. | Does not include the bitrate of the retransmission videos. |
sentFrameRate |
The frame rate of the video sent in the reported interval. | Does not include the frame rate of the retransmission videos. |
encodedFrameCount |
The total frames of the video sent. | The number of frames accumulated since joining the channel. |
codecType |
The codec type of the local video. | VIDEO_CODEC_VP8 = 1 : VP8VIDEO_CODEC_H264 = 2 : (Default) H.264 |
qualityAdaptIndication |
The local video quality change in terms of targetBitrate and targetFrameRate in thisreported interval. |
Compared to the video quality in the last statistics (two seconds ago), the video quality change in this reported interval: |
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;
}
When the state of the local video changes, the SDK triggers the onLocalVideoStateChanged
callback to report the current state. You can troubleshoot with the error code when exceptions occur.
virtual void onLocalVideoStateChanged(LOCAL_VIDEO_STREAM_STATE localVideoState, LOCAL_VIDEO_STREAM_ERROR error) {
(void)localVideoState;
(void)error;
}
The onRemoteVideoStats
callback reports the video statistics of each remote user/host in the current call. You can see their video dimensions and the following parameters.
Parameter | Description | Comment |
---|---|---|
rxStreamType |
The type of video streams. | High-video streams or low-video streams, see dual-stream mode. |
receivedBitrate |
The bitrate of the video received in the reported interval. | |
packetLossRate |
The packet loss rate of the video received in the reported interval. | |
decoderOutputFrameRate |
The output frame rate of the remote video decoder. | |
rendererOutputFrameRate |
The output frame rate of the remote video renderer. | |
totalFrozenTime |
The total freeze time (ms) of the remote video stream after the remote user joins the channel. | In a video call or interactive video streaming session where the frame rate is set to no less than 5 fps, video freeze occurs when the time interval between two adjacent renderable video frames is more than 500 ms. |
frozenRate |
The total video freeze time is a percentage of the total time when the video is available. | When the remote user/host neither stops sending the video stream nor disables the video module after joining the channel, the video is available. |
Note:
COMMUNICATION
profile, you receive video stream statistics of all the remote users (excluding yours) in the channel once every two seconds.LIVE_BROADCASTING
profile, if you are the host, you receive video stream statistics of all the remote hosts (excluding yours) in the channel once every two seconds; if you are the audience, you receive the statistics for all the hosts in the channel once every two seconds.virtual void onLocalVideoStateChanged(LOCAL_VIDEO_STREAM_STATE localVideoState, LOCAL_VIDEO_STREAM_ERROR error) {
(void)localVideoState;
(void)error;
}
When the state of remote video streams changes, the SDK triggers the onRemoteVideoStateChanged
callback to report the current state and the reason for the state change.
Note:
COMMUNICATION
profile, this callback reports to you the video stream state information of all the remote users (excluding yours) in the channel once every two seconds.LIVE_BROADCASTING
profile, if you are the host, this callback reports to you the video stream state information of all the remote hosts (excluding yours) in the channel once every two seconds; if you are the audience, this callback reports to you the video stream state information of all the remote hosts in the channel once every two seconds.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
The SDK does not trigger the onLocalAudioStateChanged
, onRemoteAudioStateChanged
, onLocalVideoStateChanged
, and onRemoteVideoStateChanged
callbacks once every two seconds. See their respective trigger conditions on this page.