# In-call quality monitoring (/en/realtime-media/broadcast-streaming/build/optimize-quality-and-connection/in-call-quality-monitoring/web)

> For AI agents: see the complete documentation index at [llms.txt](/llms.txt).

During a call, Video SDK triggers callbacks related to the video calling quality. These callbacks enable you to monitor your users' experience, troubleshoot issues, and optimize their overall experience

      
  
      
  
      
  
      
    Try out the [online demo](https://webdemo-global.agora.io/index.html) for displaying [In-call Statistics](https://webdemo-global.agora.io/example/advanced/displayCallStats/index.html).

    ## Understand the tech [#understand-the-tech-3]

    After a user joins a channel, Video SDK triggers a series of callbacks every 2 seconds, reporting information such as uplink and downlink network quality, real-time interaction statistics, and statistics of local and remote audio and video streams.

    When there is a change in the audio or video state of a user, Video SDK triggers a callback to report the latest state and the reason for the change. The following figure shows the audio transmission process between app clients:

    **Audio transmission process**

    ![Audio transmission process](https://assets-docs.agora.io/images/video-sdk/in-call-quality.svg)

    To monitor the call quality, Agora provides the following call quality notifications:

    **Network quality**

    The network quality callback provides insight into the uplink and downlink last mile network quality for each participant in the channel. Last mile refers to the network from your device to Agora server. The [Network quality scores](#network-quality-score) are calculated based on factors such as sending or receiving bitrate, network packet loss rate, round-trip delay, and network jitter.

    **Statistics**

    The statistics callback, triggered every 2 seconds, reports key metrics such as call duration and the number of participants.

    **Audio quality**

    Callbacks related to audio quality cover both local and remote audio streams. You monitor statistics and status changes, to gain insights into the quality of audio streams and any related reasons for status changes.

    **Video quality**

    Video quality callbacks provide information on both local and remote video streams. You receive statistics and status change notifications, that enable you to understand the quality of video streams and any related reasons for status changes.

    ## Prerequisites [#prerequisites-3]

    Ensure that you have implemented the [SDK quickstart](../../index) in your project.

    ## Implement in-call quality monitoring [#implement-in-call-quality-monitoring-3]

    Implement the following real-time interaction quality statistics methods and audio or video state monitoring methods to understand user interaction experience:

    * `network-quality`: Reports uplink and downlink last mile network quality.
    * `getRTCStats`: Reports real-time interaction statistics.
    * `getLocalAudioStats`: Reports statistics for the sent audio stream.
    * `getRemoteAudioStats`: Reports statistics for the received remote audio stream.
    * `getLocalVideoStats`: Reports statistics for the sent video stream.
    * `getRemoteVideoStats`: Reports statistics for the received remote video stream.

    In your app, add the following code:

    ```javascript
    // Subscribe to the "network-quality" event to receive uplink network conditions
    agoraEngine.on("network-quality", (quality) => {
     console.log("Network quality:", quality);
    });

    // Get remote network quality
    const remoteNetworkQuality = client.getRemoteNetworkQuality();

    // Get local audio and video statistics
    const localStats = {
     video: client.getLocalVideoStats(),
     audio: client.getLocalAudioStats()
    };

    // Get overall channel statistics
    const rtcStats = agoraEngine.getRTCStats();
    console.log("Channel statistics:", rtcStats);

    // Get remote user's audio statistics using the remote UID
    const remoteAudioStats = agoraEngine.getRemoteAudioStats(remoteUID);
    console.log("Remote user audio statistics:", remoteAudioStats);

    // Get remote user's video statistics using the remote UID
    const remoteVideoStats = agoraEngine.getRemoteVideoStats(remoteUID);
    console.log("Remote user video statistics:", remoteVideoStats);

    ```

    The SDK reports abnormal events in the channel through the `AgoraRTCClient.on("exception")` callback. Unusual events are not errors, but often cause call quality issues. After an abnormal event occurs, if the situation returns to normal, you receive this callback again.

    ```js
    client.on("exception", function(evt) {
     console.log(evt.code, evt.msg, evt.uid);
    })
    ```

    This callback returns:

    * `code`: event code.
    * `msg`: Prompt message.
    * `uid`: UID of the user where exception or recovery has occurred.

    Each abnormal event has a corresponding recovery event, as described in the following table:

    | Event code | Message and description                                              | Event code | Recovery message and description                                                     |
    | :--------- | :------------------------------------------------------------------- | :--------- | :----------------------------------------------------------------------------------- |
    | 1001       | `FRAMERATE_INPUT_TOO_LOW` <br /> Video capture frame rate is too low | 3001       | `FRAMERATE_INPUT_TOO_LOW_RECOVER` <br /> Video capture frame rate returns to normal  |
    | 1002       | `FRAMERATE_SENT_TOO_LOW` <br /> Video sending bitrate is too low     | 3002       | `FRAMERATE_SENT_TOO_LOW_RECOVER` <br /> Video sending frame rate returns to normal   |
    | 1003       | `SEND_VIDEO_BITRATE_TOO_LOW` <br /> Video sending bitrate is too low | 3003       | `SEND_VIDEO_BITRATE_TOO_LOW_RECOVER` <br /> Video sending bitrate returns to normal  |
    | 1005       | `RECV_VIDEO_DECODE_FAILED` <br /> Receiving video decoding failed    | 3005       | `RECV_VIDEO_DECODE_FAILED_RECOVER` <br /> Receiving video decoding returns to normal |
    | 2001       | `AUDIO_INPUT_LEVEL_TOO_LOW` <br /> Send volume too low               | 4001       | `AUDIO_INPUT_LEVEL_TOO_LOW_RECOVER` <br /> Send volume back to normal                |
    | 2002       | `AUDIO_OUTPUT_LEVEL_TOO_LOW` <br /> Receive volume too low           | 4002       | `AUDIO_OUTPUT_LEVEL_TOO_LOW_RECOVER` <br /> Receiving volume returns to normal       |
    | 2003       | `SEND_AUDIO_BITRATE_TOO_LOW` <br /> Audio sending bitrate is too low | 4003       | `SEND_AUDIO_BITRATE_TOO_LOW_RECOVER` <br /> Audio sending bitrate returns to normal  |
    | 2005       | `RECV_AUDIO_DECODE_FAILED` <br /> Failed to decode received audio    | 4005       | `RECV_AUDIO_DECODE_FAILED_RECOVER` <br /> Received audio decoding returns to normal  |

    ## Reference [#reference-3]

    ### Network quality score [#network-quality-score-3]

    | Value | Description                                                                    |
    | :---: | :----------------------------------------------------------------------------- |
    |   0   | The network quality is unknown.                                                |
    |   1   | The network quality is excellent.                                              |
    |   2   | The network quality is good, but the bitrate is slightly lower than excellent. |
    |   3   | Users can feel the communication is slightly impaired.                         |
    |   4   | Users cannot communicate smoothly.                                             |
    |   5   | The quality is so bad that users can barely communicate.                       |
    |   6   | The network is down and users cannot communicate at all.                       |

    ### API reference [#api-reference-3]

    * [`network-quality`](https://api-ref.agora.io/en/video-sdk/web/4.x/interfaces/iagorartcclient.html#event_network_quality)

    * [`getRTCStats`](https://api-ref.agora.io/en/video-sdk/web/4.x/interfaces/iagorartcclient.html#getrtcstats)

    * [`getLocalAudioStats`](https://api-ref.agora.io/en/video-sdk/web/4.x/interfaces/iagorartcclient.html#getlocalaudiostats)

    * [`getRemoteAudioStats`](https://api-ref.agora.io/en/video-sdk/web/4.x/interfaces/iagorartcclient.html#getremoteaudiostats)

    * [`getLocalVideoStats`](https://api-ref.agora.io/en/video-sdk/web/4.x/interfaces/iagorartcclient.html#getlocalvideostats)

    * [`getRemoteVideoStats`](https://api-ref.agora.io/en/video-sdk/web/4.x/interfaces/iagorartcclient.html#getremotevideostats)

    
  
      
  
      
  
      
  
      
  
      
  
      
  
