The Vonage Video SDK exposes detailed stream-quality metrics through a high-level statistics API—recommended for most use cases—which provides audio, video, network, and sender-side statistics in a unified, session-aware form that remains stable across peer-connection transitions. For advanced debugging, the SDK also offers access to the raw WebRTC stats report, which reflects unprocessed peer-connection data.

Audio and video statistics API

The Vonage Video Linux SDK sends periodic audio and video network statistics for both publishers and subscribers. These include packet counts, bitrates, frame rate data, pause/freeze metrics, codec information, and optional sender-side network estimation.

Statistics are delivered through:

  • otc_publisher_callbacks — publisher-side stats

  • otc_subscriber_callbacks — subscriber-side stats

To receive them, enable the appropriate callback on the publisher or subscriber.

Enabling statistics for publishers

Use the on_audio_stats() and on_video_stats() callback functions of the otc_publisher_callbacks to monitor statistics for a publisher's stream. To register callbacks methods for periodic reports of audio and video statistics for a publisher, set the on_audio_stats() and on_video_stats() callback functions when you initialize the otc_publisher_callbacks struct to be used by the publisher.

Register a otc_publisher_callbacks struct when creating the publisher:

struct otc_publisher_callbacks pub_callbacks;
pub_callbacks.on_audio_stats = handle_publisher_audio_stats;
pub_callbacks.on_video_stats = handle_publisher_video_stats;
pub_callbacks.on_video_quality_changed = handle_publisher_quality_change;

And implement the callbacks:

void handle_publisher_audio_stats(otc_publisher* publisher,
                                  void* user_data,
                                  struct otc_publisher_audio_stats audio_stats[],
                                  size_t number_of_stats) {
    printf("Audio bytes sent: %lld\n", (long long)audio_stats[0].bytes_sent);
}

void handle_publisher_video_stats(otc_publisher* publisher,
                                  void* user_data,
                                  struct otc_publisher_video_stats video_stats[],
                                  size_t number_of_stats) {
    printf("Video packets sent: %lld\n", (long long)video_stats[0].packets_sent);
}

These callback functions are called periodically to report audio and video statistics for the publisher. Each function is passed in the following: A pointer to the publisher struct, A pointer to the user_data you set for the publisher, an array of stats, and the number of stats in the array. The stats parameter is defined by the otc_publisher_audio_stats and otc_publisher_video_stats structs. For a publisher in a routed session (one that uses the OpenTok Media Router), the array includes one object, defining the statistics for the single audio or video media stream that is sent to the Vonage Video Media Router. In a relayed session, the array includes an object for each subscriber to the published stream.

Receiving video quality events on the publishers

For publisher video quality events:

void handle_publisher_quality_change(otc_publisher* publisher,
                                     void* user_data,
                                     const struct otc_publisher_video_stats* stats,
                                     enum otc_video_reason reason) {
    printf("Publisher video quality event: %d\n", reason);
}

Enabling statistics for subscribers

Use the on_audio_stats() and on_video_stats() callback functions of the otc_subscriber_callbacks to monitor statistics for a subscriber's stream.

Register a otc_subscriber_callbacks struct when creating the subscriber:

struct otc_subscriber_callbacks sub_callbacks;
sub_callbacks.on_audio_stats = handle_subscriber_audio_stats;
sub_callbacks.on_video_stats = handle_subscriber_video_stats;
sub_callbacks.on_video_quality_changed = handle_subscriber_quality_change;

otc_subscriber* subscriber = otc_subscriber_new(stream, sub_callbacks, user_data);

Implement the callbacks:

void handle_subscriber_audio_stats(otc_subscriber* subscriber,
                                   void* user_data,
                                   struct otc_subscriber_audio_stats audio_stats) {
    printf("Audio packets received: %llu\n", audio_stats.packets_received);
}

void handle_subscriber_video_stats(otc_subscriber* subscriber,
                                   void* user_data,
                                   struct otc_subscriber_video_stats video_stats) {
    printf("Video bytes received: %llu\n", video_stats.bytes_received);
}

Receiving video quality events on the subscribers

For publisher video quality events:

void handle_subscriber_quality_change(otc_subscriber* subscriber,
                                      void* user_data,
                                      const struct otc_subscriber_video_stats* stats,
                                      enum otc_video_reason reason) {
    printf("Subscriber video quality event: %d\n", reason);
}

Statistics data structures

This section outlines the structs and fields provided by the C SDK audio and video statistics API. While all Video SDK platforms expose the same set statistics, there may be minor differences in how each platform structures or names individual fields. These variations reflect platform-specific SDK design conventions rather than differences in the underlying metrics.

otc_transport_stats

Represents shared transport-level estimation.

  • connection_estimated_bandwidth — Estimated available connection bandwidth (bps)

otc_publisher_video_stats

Provides statistics about a publisher’s video track:

  • connection_id — In a relayed session, the connection ID of the client subscribing to the stream
  • subscriber_id — In a relayed session, the subscriber ID of the client subscribing to the stream
  • packets_lost — Estimated video packets lost
  • packets_sent — Video packets sent
  • bytes_sent — Video bytes sent
  • timestamp — Unix timestamp in milliseconds
  • start_time — The timestamp, in milliseconds since the Unix epoch, from which the cumulative totals started accumulating
  • video_layers — Array of video layer statistics (see otc_publisher_video_layer_stats)
  • transport — Transport stats for this publisher

otc_publisher_audio_stats

Provides statistics about a publisher’s audio track:

  • connection_id — In a relayed session, the connection ID of the client subscribing to the stream
  • subscriber_id — In a relayed session, the subscriber ID
  • packets_lost — Estimated audio packets lost
  • packets_sent — Audio packets sent
  • bytes_sent — Audio bytes sent
  • timestamp — Unix timestamp in milliseconds
  • start_time — The timestamp, in milliseconds since the Unix epoch, from which the cumulative totals started accumulating
  • transport — Transport stats for this publisher

otc_publisher_video_layer_stats

Represents one simulcast or SVC layer:

  • width — Encoded frame width
  • height — Encoded frame height
  • encoded_frame_rate — Encoded fps
  • bitrate — Layer bitrate (bps)
  • total_bitrate — Layer bitrate including RTP overhead (bps)
  • scalability_mode — SVC/scalability descriptor (e.g., "L3T3")
  • quality_limitation_reason — Reason for quality limitation (bandwidth, CPU, codec, resolution, or layer change)
  • codec — Codec used for this video layer

otc_subscriber_video_stats

Provides statistics about a subscriber’s video track:

  • packets_lost — Estimated video packets lost
  • packets_received — Video packets received
  • bytes_received — Video bytes received
  • timestamp — Unix timestamp in milliseconds
  • sender_connection_max_allocated_bitrate — Optional sender-side max bitrate
  • sender_connection_estimated_bandwidth — Optional sender-side estimated bandwidth
  • width — Decoded frame width in pixels
  • height — Decoded frame height in pixels
  • decoded_frame_rate — Decoded frames per second
  • bitrate — Video bitrate (bps)
  • total_bitrate — Bitrate including RTP overhead (bps)
  • pause_count — Number of pauses (>5s since last frame)
  • total_pauses_duration — Total pause duration (ms)
  • freeze_count — Number of freezes
  • total_freezes_duration — Total freeze duration (ms)
  • codec — Current decoder codec

otc_subscriber_audio_stats

Provides statistics about a subscriber’s audio track:

  • packets_lost — Estimated packets lost
  • packets_received — Packets received
  • bytes_received — Bytes received
  • audio_level — Audio level (0–1.0)
  • timestamp — Unix timestamp in milliseconds
  • sender_connection_max_allocated_bitrate — Optional sender-side max bitrate
  • sender_connection_estimated_bandwidth — Optional sender-side estimated bandwidth

Sender-side

See the sender-side statistics overview.

Enabling sender-side statistics

Sender-side statistics are received on the subscribers. To receive sender-side statistics, enable them for the stream’s publisher by calling otc_publisher_settings_set_sender_stats_track() function before constructing the publisher:

otc_publisher_settings* settings = otc_publisher_settings_new();
otc_publisher_settings_set_sender_stats_track(settings, OTC_TRUE);

otc_publisher* publisher = otc_publisher_new_with_settings( &publisher_callbacks, settings);

If the sender stats track is not enabled, no sender statistics channel will be published for this publisher. The default value is OTC_FALSE.

Subscribing to sender-side statistics

Subscribers automatically receive sender statistics when you register for the subscriber’s video or audio statistics callbacks and the publisher is sending them.

Receiving statistics events

Sender-side statistics are delivered as part of the existing subscriber stats callbacks. Specific fields are included in the otc_subscriber_video_stats and otc_subscriber_audio_stats structures:

  • sender_connection_max_allocated_bitrate — The maximum bitrate that can be estimated for the connection
  • sender_connection_estimated_bandwidth — The current estimated bandwidth for the connection

These two metrics are calculated per audio-video bundle, so the same values appear in both video and audio statistics. Because they reflect the transport rather than individual tracks, the metrics are shared across both audio and video.

void handle_subscriber_video_stats(otc_subscriber* subscriber,
                                   void* user_data,
                                   struct otc_subscriber_video_stats stats) {
    printf("Timestamp: %llu ms\n", (unsigned long long)stats.timestamp);
    printf("Connection max allocated bitrate: %lld bps\n", (long long)stats.sender_connection_max_allocated_bitrate);
    printf("Connection estimated bandwidth: %lld bps\n", (long long)stats.sender_connection_estimated_bandwidth);
}

RTC stats report

To get low-level peer connection statistics for a publisher, use the otc_publisher_get_rtc_stats_report() function. This provides RTC stats reports for the media stream. This is an asynchronous operation. Create an otc_publisher_rtc_stats_report_cb struct and pass it into the otc_publisher_set_rtc_stats_report_cb function prior to calling otc_publisher_get_rtc_stats_report(). When the stats are available, the otc_publisher_rtc_stats_report_cb.on_rtc_stats_report() callback function is called. This function includes a stats parameter, which is a pointer to an array of otc_publisher_rtc_stats structs. This struct includes a json_array_of_reports property. This is a JSON array of RTC stats reports, which are similar to the format the RtcStatsReport object implemented in web browsers (see these Mozilla docs).

To get low-level peer connection statistics for a subscriber, To get more detailed stream statistics, use the otc_subscriber_get_rtc_stats_report() function. This provides an RTC stats report for the media stream.

This is an asynchronous operation. Create an otc_subscriber_rtc_stats_report_cb struct and pass it into the otc_subscriber_set_rtc_stats_report_cb function prior to calling otc_subscriber_get_rtc_stats_report(). When the stats are available, the otc_subscriber_rtc_stats_report_cb.on_rtc_stats_report callback function is called.

This callback function includes a json_array_of_reports parameter. This is a JSON array of RTC stats reports, which are similar to the format the RtcStatsReport object implemented in web browsers (see these Mozilla docs).

Also see this W3C documentation.