Das Vonage Video SDK stellt detaillierte Metriken zur Stream-Qualität über eine High-Level-Statistik-API zur Verfügung, die für die meisten Anwendungsfälle empfohlen wird und die Audio-, Video-, Netzwerk- und Absenderstatistiken in einer einheitlichen, sitzungsspezifischen Form bereitstellt, die über Peer-Verbindungsübergänge hinweg stabil bleibt. Für fortgeschrittenes Debugging bietet das SDK auch Zugriff auf den rohen WebRTC-Statistikbericht, der unverarbeitete Peer-Verbindungsdaten wiedergibt.
Audio- und Videostatistik-API
Das Vonage Video Android SDK sendet regelmäßig Audio- und Videonetzwerkstatistiken sowohl für Anbieter als auch für Teilnehmer. Dazu gehören die Anzahl der Pakete, Bitraten, Frame-Rate-Daten, Pausen-/Freeze-Metriken, Codec-Informationen und optionale senderseitige Netzwerkschätzungen.
Die Statistiken werden durch geliefert:
PublisherKit.NetworkStatsListener- verlagsseitige StatistikenSubscriberKit.NetworkStatsListener- Statistiken auf der Abonnentenseite
Um sie zu empfangen, aktivieren Sie den entsprechenden Listener auf dem Herausgeber oder Abonnenten.
Freigabe von Statistiken für Verleger
Hängen Sie einen Listener für Verlagsstatistiken an:
publisher.setNetworkStatsListener(new PublisherKit.NetworkStatsListener() {
@Override
public void onVideoStats(PublisherKit publisher, PublisherKit.PublisherVideoStats[] statsArray) {
if (statsArray != null && statsArray.length > 0) {
// For routed sessions, first element is sufficient.
// For relayed sessions, iterate all statsArray elements to get per-subscriber info.
PublisherKit.PublisherVideoStats stats = statsArray[0];
String connectionId = (stats.connectionId != null && !stats.connectionId.isEmpty())
? stats.connectionId
: "<none>";
String subscriberId = (stats.subscriberId != null && !stats.subscriberId.isEmpty())
? stats.subscriberId
: "<none>";
Log.d("VideoStats", "Publisher Video Stats for connectionId: " + connectionId
+ ", subscriberId: " + subscriberId);
Log.d("VideoStats", "Video bytes sent: " + stats.videoBytesSent);
Log.d("VideoStats", "Video packets sent: " + stats.videoPacketsSent);
Log.d("VideoStats", "Video packets lost: " + stats.videoPacketsLost);
Log.d("VideoStats", "Stats timestamp: " + stats.timeStamp + " ms");
if (stats.videoLayers != null) {
for (PublisherKit.VideoLayerStats layer : stats.videoLayers) {
Log.d("VideoStats", "Layer: " + layer.width + "x" + layer.height);
Log.d("VideoStats", " Encoded FPS: " + layer.encodedFrameRate);
Log.d("VideoStats", " Bitrate: " + layer.bitrate + " bps");
Log.d("VideoStats", " Total bitrate (incl. RTP overhead): " + layer.totalBitrate + " bps");
Log.d("VideoStats", " Codec: " + (layer.codec != null ? layer.codec : "unknown"));
Log.d("VideoStats", " Scalability mode: " + (layer.scalabilityMode != null ? layer.scalabilityMode : "none"));
Log.d("VideoStats", " Quality limitation: " + layer.qualityLimitationReason);
}
}
if (stats.transport != null) {
Log.d("VideoStats", "Estimated uplink bandwidth: " + stats.transport.getConnectionEstimatedBandwidth() + " bps");
}
}
}
@Override
public void onAudioStats(PublisherKit publisher, PublisherKit.PublisherAudioStats[] statsArray) {
if (statsArray != null && statsArray.length > 0) {
// For routed sessions, first element is sufficient.
// For relayed sessions, iterate all statsArray elements to get per-subscriber info.
PublisherKit.PublisherAudioStats stats = statsArray[0];
String connectionId = (stats.connectionId != null && !stats.connectionId.isEmpty())
? stats.connectionId
: "<none>";
String subscriberId = (stats.subscriberId != null && !stats.subscriberId.isEmpty())
? stats.subscriberId
: "<none>";
Log.d("AudioStats", "Publisher Audio Stats for connectionId: " + connectionId
+ ", subscriberId: " + subscriberId);
Log.d("AudioStats", "Audio bytes sent: " + stats.audioBytesSent);
Log.d("AudioStats", "Audio packets sent: " + stats.audioPacketsSent);
Log.d("AudioStats", "Audio packets lost: " + stats.audioPacketsLost);
Log.d("AudioStats", "Stats timestamp: " + stats.timeStamp + " ms");
if (stats.transport != null) {
Log.d("AudioStats", "Estimated uplink bandwidth: " + stats.transport.getConnectionEstimatedBandwidth() + " bps");
}
}
}
});
Für einen Verleger in einer gerouteten Sitzung (eine, die die Vonage Video-Media-Router), enthält das Array stats ein Objekt, das die Statistiken für den einzelnen Audio- oder Video-Medienstrom, der an den Vonage Video Media Router gesendet wird. In einer weitergeleiteten Sitzung enthält das stats-Array ein Objekt für jeden Teilnehmer des des veröffentlichten Streams.
Empfang von Ereignissen in Videoqualität bei den Herausgebern
Für Ereignisse in Videoqualität, implementieren:
@Override
public void onPublisherVideoQualityChanged(PublisherKit.PublisherVideoStats stats, String reason) {
Log.d("Stats", "Publisher video quality event: " + reason);
}
Aktivieren von Statistiken für Abonnenten
Anhängen eines Hörers, der SubscriberKit.SubscriberKitNetworkStatsListener:
Subscriber subscriber = new Subscriber(stream);
subscriber.setNetworkStatsListener(new SubscriberKit.SubscriberKitNetworkStatsListener() {
@Override
public void onSubscriberVideoStatsUpdated(SubscriberKit.SubscriberVideoStats stats) {
Log.d("Stats", "Video bytes received: " + stats.videoBytesReceived);
}
@Override
public void onSubscriberAudioStatsUpdated(SubscriberKit.SubscriberAudioStats stats) {
Log.d("Stats", "Audio packets received: " + stats.audioPacketsReceived);
}
});
Empfang von Videoqualitätsereignissen bei den Abonnenten
Für Ereignisse in Videoqualität, implementieren:
@Override
public void onSubscriberVideoQualityChanged(SubscriberKit.SubscriberVideoStats stats, String reason) {
Log.d("Stats", "Subscriber video quality event: " + reason);
}
Statistik-Datenstrukturen
In diesem Abschnitt werden die Strukturen und Eigenschaften beschrieben, die von der Android-Audio- und Videostatistik-API bereitgestellt werden. Während alle Video-SDK-Plattformen die gleichen Statistiken bereitstellen, kann es geringfügige Unterschiede bei der Strukturierung oder Benennung einzelner Felder geben. Diese Unterschiede spiegeln eher plattformspezifische SDK-Designkonventionen als Unterschiede in den zugrunde liegenden Metriken wider.
Eine plattformunabhängige Erläuterung der verfügbaren Statistiken und ihrer Bedeutung finden Sie unter Übersicht über die Beobachtbarkeit der Kunden.
TransportStats
Stellt eine gemeinsame Schätzung auf Transportebene dar.
connectionEstimatedBandwidth- Geschätzte verfügbare Uplink-Verbindungsbandbreite (bps).
PublisherKit.PublisherVideoStats
Liefert Statistiken über die Videospur eines Herausgebers. Sie umfasst:
connectionId- In einer weitergeleiteten Sitzung die Verbindungs-ID des Clients, der den Stream abonniert. Undefiniert in einer gerouteten Sitzung.subscriberId- In einer weitergeleiteten Sitzung die abonnierte ID des Clients, der den Stream abonniert. Undefiniert in einer gerouteten Sitzung.videoPacketsLost- Geschätzte verlorene Videopakete.videoPacketsSent- Gesendete Videopakete.videoBytesSent- Video-Bytes gesendet.timeStamp- Unix-Zeitstempel in Millisekunden, als die Statistiken erfasst wurden.startTime- Der Zeitstempel in Millisekunden seit der Unix-Epoche, ab dem die kumulativen Summen zu kumulieren begannen.videoLayers- Das Array der Video-Layer-Statistiken (sieheOTPublisherKitVideoLayerStats).transport- Verkehrsstatistik.
PublisherKit.PublisherAudioStats
Liefert Statistiken über den Audiotrack eines Verlags. Sie umfasst:
connectionId- In einer weitergeleiteten Sitzung die Verbindungs-ID des Clients, der den Stream abonniert. Undefiniert in einer gerouteten Sitzung.subscriberId- In einer weitergeleiteten Sitzung die abonnierte ID des Clients, der den Stream abonniert. Undefiniert in einer gerouteten Sitzung.audioPacketsLost- Geschätzte verlorene Pakete.audioPacketsSent- Audio-Pakete gesendet.audioBytesSent- Gesendete Audio-Bytes.timeStamp- Unix-Zeitstempel in Millisekunden.startTime- Der Zeitstempel in Millisekunden seit der Unix-Epoche, ab dem die kumulativen Summen zu kumulieren begannen.transport- Verkehrsstatistik.
PublisherKit.VideoLayerStats
Steht für eine Simulcast- oder SVC-Schicht.
width- Kodierte Bildbreite.height- Kodierte Rahmenhöhe.encodedFrameRate- Kodierte Bilder pro Sekunde.bitrate- Bitrate der Schicht (bps).totalBitrate- Bitrate der Schicht einschließlich RTP-Overhead (bps).scalabilityMode- SVC/Skalierbarkeitsdeskriptor (z. B. "L3T3").qualityLimitationReason- Grund für die Qualitätseinschränkung (Bandbreite, CPU, Codec, Auflösung oder Ebenenwechsel).codec- Der von dieser Videoebene verwendete Codec.
SubscriberKit.SenderStats
Abschätzungsmetriken auf der Senderseite (gespiegelt auf Audio und Video).
connectionMaxAllocatedBitrate- Geschätzte maximale Bitrate für die Senderverbindung.connectionEstimatedBandwidth- Aktuelle Bandbreitenabschätzung (bps).
SubscriberKit.SubscriberVideoStats
Liefert Statistiken über die Videospur eines Abonnenten. Sie umfasst:
videoPacketsLost- Geschätzte verlorene Videopakete.videoPacketsReceived- Empfangene Videopakete.videoBytesReceived- Empfangene Videobytes.timeStamp- Unix-Zeitstempel in Millisekunden, als die Statistiken erfasst wurden.senderStats- Metriken auf der Absenderseite (optional).width- Dekodierte Bildbreite in Pixel.height- Dekodierte Bildhöhe in Pixel.decodedFrameRate- Dekodierte Bilder pro Sekunde.bitrate- Video-Bitrate (bps).totalBitrate- Bitrate einschließlich RTP-Overhead (bps).pauseCount- Numbers of pauses (>5s seit dem letzten Frame). Einschließlich absichtlicher Deaktivierungen und Audio-Fallback-Fälle.totalPausesDuration- Gesamte Pausendauer (ms).freezeCount- Freeze Count (von WebRTC definiertes Freeze-Ereignis).totalFreezesDuration- Gesamtdauer des Einfrierens (ms).codec- Aktueller Decoder-Codec.
SubscriberKit.SubscriberAudioStats
Liefert Statistiken über den Audiotrack eines Abonnenten. Sie umfasst:
audioPacketsLost- Geschätzte verlorene Pakete.audioPacketsReceived- Empfangene Pakete.audioBytesReceived- Empfangene Bytes.timeStamp- Unix-Zeitstempel in Millisekunden.senderStats- Metriken auf der Absenderseite (optional).
Statistik auf der Absenderseite
Siehe die Übersicht der Absenderstatistiken.
Aktivieren von Statistiken auf der Absenderseite
Senderstatistiken werden von den Abonnenten empfangen. Um absenderseitige Statistiken zu erhalten, aktivieren Sie sie für den Herausgeber des Streams, indem Sie die Option senderStatisticsTrack Eigenschaft zu true bei der Erstellung des Verlags:
Publisher publisher = new Publisher.Builder(context)
.senderStatsTrack(true) // Enable sender-side stats
.build();
Wenn senderStatsTrack nicht aktiviert ist, wird kein Absenderstatistikkanal für diesen Verlag veröffentlicht. Der Standardwert ist false.
Abonnieren von Statistiken auf der Absenderseite
Abonnenten erhalten nur dann automatisch Absenderstatistiken, wenn der Herausgeber diese aktiviert hat und der Abonnent einen Listener für Netzwerkstatistik-Ereignisse registriert hat.
Empfang von Statistikereignissen
Die absenderseitigen Statistiken werden über die SubscriberKit.VideoStatsListener und SubscriberKit.AudioStatsListener Rückrufe für Video und Audio. Die SubscriberKit.SubscriberVideoStats und SubscriberKit.SubscriberAudioStats Klassen enthalten jeweils diese Eigenschaften:
connectionMaxAllocatedBitrate- Die maximale Bitrate, die für die Verbindung geschätzt werden kannconnectionEstimatedBandwidth- Die aktuelle geschätzte Bitrate für die Verbindung
Diese beiden Metriken werden pro Audio-Video-Bündel berechnet, so dass sowohl in der Video- als auch in der Audiostatistik die gleichen Werte erscheinen. Da sie den Transport und nicht einzelne Tracks widerspiegeln, werden die Metriken sowohl für Audio als auch für Video verwendet.
Die stats Objekt enthält ein optionales senderStats das die Statistik auf der Absenderseite liefert. Zum Beispiel, wenn Sie SubscriberKit.setVideoStatsListener()die stats Parameter ist ein SubscriberKit.SubscriberVideoStats Objekt:
subscriber.setVideoStatsListener((subscriber, stats) -> {
if (stats.senderStats != null) {
Log.d(TAG, "Connection max allocated bitrate: " + stats.senderStats.connectionMaxAllocatedBitrate);
Log.d(TAG, "Connection current estimated bandwidth: " + stats.senderStats.connectionEstimatedBandwidth);
} else {
Log.d(TAG, "Sender stats not available yet.");
}
});
Das Gleiche gilt für Audiostatistiken mit SubscriberKit.AudioStatsListener.
RTC-Statistikbericht
Um Low-Level-Peer-Verbindungsstatistiken für einen Publisher zu erhalten, verwenden Sie die PublisherKit.getRtcStatsReport() Methode. Sie liefert RTC-Statistikberichte für den Medienstrom. Dies ist ein asynchroner Vorgang. Rufen Sie die PublisherKit.setRtcStatsReportListener(PublisherKit.PublisherRtcStatsReportListener listener) Methode, und implementieren Sie dann die PublisherKit.PublisherRtcStatsReportListener.onRtcStatsReport(PublisherKit publisher, PublisherKit.PublisherRtcStats[] stats) Methode vor dem Aufruf PublisherKit.getRtcStatsReport().
Wenn die Statistiken verfügbar sind, wird die Implementierung der PublisherKit.PublisherRtcStatsReportListener.onRtcStatsReport(PublisherKit publisher, PublisherKit.PublisherRtcStats[] stats) Methode aufgerufen wird.
Eine Reihe von PublisherRtcStats Objekte an diese Methode übergeben wird. Die PublisherRtcStats Objekt enthält eine jsonArrayOfReports Eigenschaft. Dies ist ein JSON-Array mit RTC-Statistikberichten, die dem Format des in Webbrowsern implementierten RtcStatsReport-Objekts ähneln (siehe diese Mozilla-Dokumente).
Um Low-Level-Peer-Verbindungsstatistiken für einen Teilnehmer zu erhalten, verwenden Sie die SubscriberKit.getRtcStatsReport() Methode. Dies liefert einen RTC-Statistikbericht für den Medienstrom.
Dies ist ein asynchroner Vorgang. Rufen Sie die SubscriberKit.setRtcStatsReportListener(SubscriberKit.SubscriberRtcStatsReportListener listener) Methode, und implementieren Sie dann die SubscriberKit.SubscriberRtcStatsReportListener.onRtcStatsReport(SubscriberKit subscriber, java.lang.String jsonArrayOfReports) Methode vor dem Aufruf SubscriberKit.getRtcStatsReport().
Wenn die Statistiken verfügbar sind, wird die Implementierung der SubscriberKit.SubscriberRtcStatsReportListener.onRtcStatsReport(SubscriberKit subscriber, java.lang.String jsonArrayOfReports) Methode aufgerufen wird. Die jsonArrayOfReports ist ein JSON-Array von RTC-Statistikberichten, die dem Format des in Webbrowsern implementierten RtcStatsReport-Objekts ähneln (siehe diese Mozilla-Dokumente).
Siehe auch diese W3C-Dokumentation.