Client-Beobachtbarkeit: iOS (Swift)
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.
Das SDK stellt auch Netzwerkzustandsmetriken zur Verfügung, die eine umfassende Bewertung des Verbindungszustands sowohl für Herausgeber als auch für Abonnenten ermöglichen. Diese Metriken umfassen eine Bewertung des Netzwerkzustands, den Grund für diese Bewertung und - für Abonnenten - eine Verschlechterungsquelle, die angibt, welche Seite der Verbindung für die beobachteten Probleme verantwortlich ist. Siehe Netzzustand und Ursache der Verschlechterung für Einzelheiten.
Audio-, Video- und Medienlink-Statistik-API
Das Vonage Video iOS SDK sendet regelmäßig Audio-, Video- und Media-Link-Statistiken sowohl für Publisher als auch für Abonnenten. Dazu gehören die Anzahl der Pakete, Bitraten, Frame-Rate-Daten, Pausen-/Freeze-Metriken, Codec-Informationen und Netzwerkmetriken auf Transportebene, wie z. B. Bandbreitenschätzung und Netzwerkzustandsbewertung.
Die Statistiken werden durch geliefert:
OTPublisherKitNetworkStatsDelegate- Statistiken auf der Verlagsseite (Audio, Video)OTSubscriberKitNetworkStatsDelegate- Statistiken auf der Abonnentenseite (Audio, Video)
Um sie zu empfangen, aktivieren Sie den entsprechenden Delegaten auf dem Verleger oder Abonnenten.
Aktivieren von Statistiken für Verleger
Fügen Sie eine Klasse hinzu, die das OTPublisherKitNetworkStatsDelegate übernimmt:
class MyViewController: UIViewController, OTPublisherKitDelegate, OTPublisherKitNetworkStatsDelegate {
var publisher: OTPublisher?
func setupPublisher() {
let settings = OTPublisherSettings()
// Configure settings as needed
publisher = OTPublisher(delegate: self, settings: settings)
publisher?.networkStatsDelegate = self
}
}
Implementieren Sie die Rückrufe:
func publisher(_ publisher: OTPublisherKit, videoNetworkStatsUpdated stats: [OTPublisherKitVideoNetworkStats]) {
let first = stats.first
// For routed sessions, stats.first is enough.
// For relayed sessions (one object per subscriber), you would iterate all elements.
let connectionId = first.connectionId.isEmpty ? "<none>" : first.connectionId
let subscriberId = first.subscriberId.isEmpty ? "<none>" : first.subscriberId
print("Publisher Video Stats for connectionId: \(connectionId), subscriberId: \(subscriberId)")
print("Video bytes sent: \(first.videoBytesSent)")
print("Video packets sent: \(first.videoPacketsSent)")
print("Video packets lost: \(first.videoPacketsLost)")
print("Current average frame rate: \(first.videoFrameRate) fps")
for layer in first.videoLayers {
print("Layer: \(layer.width)x\(layer.height)")
print(" Encoded FPS: \(layer.encodedFrameRate)")
print(" Bitrate: \(layer.bitrate) bps")
print(" Total bitrate (incl. RTP overhead): \(layer.totalBitrate) bps")
print(" Codec: \(layer.codec ?? "<none>")")
print(" Scalability mode: \(layer.scalabilityMode ?? "<none>")")
print(" Quality limitation: \(layer.qualityLimitationReason.rawValue)")
}
}
func publisher(_ publisher: OTPublisherKit, audioNetworkStatsUpdated stats: [OTPublisherKitAudioNetworkStats]) {
let first = stats.first
// For routed sessions, stats.first is enough.
// For relayed sessions (one object per subscriber), you would iterate all elements.
let connectionId = first.connectionId.isEmpty ? "<none>" : first.connectionId
let subscriberId = first.subscriberId.isEmpty ? "<none>" : first.subscriberId
print("Publisher Audio Stats for connectionId: \(connectionId), subscriberId: \(subscriberId)")
print("Audio bytes sent: \(first.audioBytesSent)")
print("Audio packets sent: \(first.audioPacketsSent)")
print("Audio packets lost: \(first.audioPacketsLost)")
}
func publisher(_ publisher: OTPublisherKit, mediaLinkStatsUpdated mediaLinkStats: [OTPublisherKitMediaLinkStats]) {
if let stats = mediaLinkStats.first {
print("Publisher uplink bandwidth: \(stats.transport.connectionEstimatedBandwidth) bps")
print("Network condition: \(stats.transport.networkCondition.rawValue)")
print("Condition reason: \(stats.transport.networkConditionReason.rawValue)")
}
}
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 Videoqualitätsereignissen bei den Herausgebern
Wenn Sie auch an Videoqualitätsereignissen interessiert sind, implementieren Sie diesen Callback:
func publisher(_ publisher: OTPublisherKit, videoQualityChanged stats: OTPublisherKitVideoNetworkStats, reason: OTPublisherVideoEventReason) {
print("Publisher video quality event: \(reason.rawValue)")
}
Empfang von Netzwerkzustandsereignissen auf den Publishern
Um Ereignisse zur Änderung von Netzwerkbedingungen für den Herausgeber zu empfangen, implementieren Sie die publisher(_:networkConditionChanged:mediaLinkStats:reason:) Rückruf:
func publisher(_ publisher: OTPublisherKit, networkConditionChanged mediaLinkStats: OTPublisherKitMediaLinkStats, reason: OTNetworkReason) {
if let transport = mediaLinkStats.transport {
print("Publisher network condition changed: \(transport.networkCondition.rawValue)")
print("Reason: \(transport.networkConditionReason.rawValue)")
}
}
Dieser Rückruf wird ausgelöst, wenn eine signifikante Änderung der Netzbedingungen für den Herausgeber festgestellt wird. Er enthält die aktuelle Medienverbindungsstatistik mit Transportmetriken. Siehe Netzzustand und Ursache der Verschlechterung für Einzelheiten zur Interpretation der Netzzustandsnoten und Gründe.
Aktivieren von Statistiken für Abonnenten
Anhängen einer Klasse, die die OTSubscriberKitNetworkStatsDelegate:
class MyViewController: UIViewController, OTSubscriberKitDelegate, OTSubscriberKitNetworkStatsDelegate {
var subscriber: OTSubscriber?
func setupSubscriber(stream: OTStream, session: OTSession) {
subscriber = OTSubscriber(stream: stream, delegate: self)
subscriber?.networkStatsDelegate = self
try? session.subscribe(subscriber!)
}
}
Implementieren Sie die Rückrufe:
func subscriber(_ subscriber: OTSubscriberKit, videoNetworkStatsUpdated stats: OTSubscriberKitVideoNetworkStats) {
print("Video bytes received: \(stats.videoBytesReceived)")
}
func subscriber(_ subscriber: OTSubscriberKit, audioNetworkStatsUpdated stats: OTSubscriberKitAudioNetworkStats) {
print("Audio packets received: \(stats.audioPacketsReceived)")
}
func subscriber(_ subscriber: OTSubscriberKit, mediaLinkStatsUpdated mediaLinkStats: OTSubscriberKitMediaLinkStats) {
print("Local downlink bandwidth: \(mediaLinkStats.transport.connectionEstimatedBandwidth) bps")
print("Remote publisher uplink bandwidth: \(mediaLinkStats.remotePublisherTransport.connectionEstimatedBandwidth) bps")
print("Degradation source: \(mediaLinkStats.networkDegradationSource.rawValue)")
}
Empfang von Videoqualitätsereignissen bei den Abonnenten
Zusätzlich können Sie Ereignisse mit geänderter Videoqualität für Abonnenten behandeln:
func subscriber(_ subscriber: OTSubscriberKit, videoQualityChanged stats: OTSubscriberKitVideoNetworkStats, reason: OTSubscriberVideoEventReason) {
print("Subscriber video quality event: \(reason.rawValue)")
}
Empfang von Netzwerkzustandsereignissen bei den Teilnehmern
Um Ereignisse zur Änderung von Netzbedingungen für den Teilnehmer zu empfangen, implementieren Sie die subscriber(_:networkConditionChanged:mediaLinkStats:reason:) Rückruf:
func subscriber(_ subscriber: OTSubscriberKit, networkConditionChanged mediaLinkStats: OTSubscriberKitMediaLinkStats, reason: OTNetworkReason) {
if let transport = mediaLinkStats.transport {
print("Local network condition: \(transport.networkCondition.rawValue)")
}
if let remoteTransport = mediaLinkStats.remotePublisherTransport {
print("Remote publisher network condition: \(remoteTransport.networkCondition.rawValue)")
}
print("Degradation source: \(mediaLinkStats.networkDegradationSource.rawValue)")
}
Dieser Rückruf wird ausgelöst, wenn eine signifikante Änderung der Netzbedingungen für den Teilnehmer oder den entfernten Herausgeber festgestellt wird. Er enthält die aktuelle Medienverbindungsstatistik mit lokalen und entfernten Transportmetriken und der Degradationsquelle. Siehe Netzzustand und Ursache der Verschlechterung für Einzelheiten zur Interpretation der Netzzustandsnoten und Gründe.
Statistik-Datenstrukturen
In diesem Abschnitt werden die Strukturen und Eigenschaften beschrieben, die von der iOS-Audio- und Videostatistik-API bereitgestellt werden. Während alle Video-SDK-Plattformen denselben Satz von Statistiken bereitstellen, kann es geringfügige Unterschiede in der Strukturierung oder Benennung einzelner Felder auf den einzelnen Plattformen 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.
OTTransportStats
Stellt gemeinsame Metriken auf Transportebene dar.
connectionEstimatedBandwidth- Geschätzte verfügbare Verbindungsbandbreite (bps).networkCondition- Aktuelle Netzzustandsbewertung (OTNetworkConditionUnknown,OTNetworkConditionCritical,OTNetworkConditionWarning,OTNetworkConditionFair,OTNetworkConditionGood, oderOTNetworkConditionExcellent).networkConditionReason- Hauptgrund für die Beeinträchtigung des Netzzustandes (OTNetworkReasonNone,OTNetworkReasonUnknown,OTNetworkReasonBandwidth, oderOTNetworkReasonPacketLoss).
OTPublisherKitVideoNetworkStats
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.
OTPublisherKitAudioNetworkStats
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.
OTPublisherKitVideoLayerStats
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.
OTSenderStats
Abschätzungsmetriken auf der Senderseite (gespiegelt auf Audio und Video).
connectionMaxAllocatedBitrate- Geschätzte maximale Bitrate für die Senderverbindung.connectionEstimatedBandwidth- Aktuelle Bandbreitenabschätzung (bps).
OTSubscriberKitVideoNetworkStats
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.
OTSubscriberKitAudioNetworkStats
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).
OTPublisherKitMediaLinkStats
Liefert Statistiken auf Transportebene für die Verbindungen eines Verlags.
transport- Transportstatistiken für die Uplink-Verbindung dieses Verlags (sieheOTTransportStats)
OTSubscriberKitMediaLinkStats
Liefert Statistiken auf Transportebene für die Verbindungen eines Teilnehmers, einschließlich Einblick in die Netzwerkleistung des entfernten Herausgebers. So können Applications diagnostizieren, ob Verbindungsprobleme vom Downlink des Teilnehmers oder vom Uplink des Publishers ausgehen.
transport- Transportstatistiken für die Downlink-Verbindung dieses Teilnehmers (sieheOTTransportStats)remotePublisherTransport- Transportstatistiken für die Uplink-Verbindung des entfernten Herausgebers (erhalten über Statistik der Absender-SeitesieheOTTransportStats). Diese Statistiken können eingeschränkt sein, wenn die absenderseitigen Statistiken nicht aktiviert sind.networkDegradationSource- Zeigt die Quelle der Netzverschlechterung an (OTNetworkDegradationSourceLocal,OTNetworkDegradationSourceRemote,OTNetworkDegradationSourceBothOrUnclear, oderOTNetworkDegradationSourceUnknown)
Statistik auf der Absenderseite
Siehe die Übersicht der Absenderstatistiken.
Aktivieren der absenderseitigen Statistik
Senderstatistiken werden von den Abonnenten empfangen. Um absenderseitige Statistiken zu erhalten, aktivieren Sie sie für den Herausgeber des Streams, indem Sie die Option senderStatsTrack Eigenschaft zu true für die OTPublisherKitSettings Objekt, das zur Erstellung des Verlags verwendet wird.
let settings = OTPublisherKitSettings()
settings.senderStatsTrack = true
let publisher = OTPublisher(delegate: self, settings: settings)
Wenn senderStatsTrack nicht aktiviert ist, wird kein Absenderstatistikkanal für diesen Verlag veröffentlicht. Der Standardwert ist NO.
Empfangen von absenderseitigen Statistiken
Wenn der Herausgeber die Absenderstatistik aktiviert hat, erhalten die Abonnenten diese automatisch über die OTSubscriberKitNetworkStatsDelegate Rückrufe oben beschrieben. Die senderStats Eigenschaft auf beiden OTSubscriberKitVideoNetworkStats und OTSubscriberKitAudioNetworkStats liefert zwei Metriken:
connectionMaxAllocatedBitrate- Die maximale Bitrate, die für die Verbindung geschätzt werden kannconnectionEstimatedBandwidth- Die aktuell geschätzte Bandbreite für die Verbindung
Diese Metriken werden pro Audio-Video-Bündel berechnet, so dass in den Video- und Audiostatistiken dieselben Werte erscheinen.
func subscriber(_ subscriber: OTSubscriberKit, videoNetworkStatsUpdated stats: OTSubscriberKitVideoNetworkStats) {
if let sender = stats.senderStats {
print("Connection max allocated bitrate: \(sender.connectionMaxAllocatedBitrate)")
print("Connection current estimated bandwidth: \(sender.connectionEstimatedBandwidth)")
}
}
Netzzustand und Verschlechterung Quelle
Das SDK liefert sowohl für Publisher als auch für Abonnenten Echtzeit-Netzwerkzustandsmetriken, einschließlich einer Zustandsbewertung, des Grundes für diese Bewertung und einer Verschlechterungsquelle für Abonnenten. Eine vollständige Erläuterung des Netzwerkzustandsmodells, der Bewertungen, der Gründe und der Aktivierung finden Sie in der Übersicht über die Beobachtbarkeit der Kunden.
Netzzustandsdaten sind über zwei Kanäle verfügbar:
- Regelmäßige Statistiken: Die
transportEigenschaft von Publisher- und Subscriber-Stats-Objekten umfasstnetworkConditionundnetworkConditionReason. Die Abonnentenstatistiken geben auch Aufschluss überremotePublisherTransportundnetworkDegradationSource. Siehe Strukturen der Statistik für Einzelheiten. - Ereignisse, bei denen sich der Netzzustand ändert: Dedizierte Rückrufe auf beiden Herausgeber und Teilnehmer werden ausgelöst, wenn eine signifikante Änderung der Netzbedingungen festgestellt wird.
Das folgende Beispiel zeigt, wie die Daten über den Zustand des Teilnehmernetzes verwendet werden können, um die Ursache der Verschlechterung zu ermitteln:
func subscriber(_ subscriber: OTSubscriberKit, networkConditionChanged videoStats: OTSubscriberKitVideoNetworkStats, audioStats: OTSubscriberKitAudioNetworkStats, reason: OTNetworkReason) {
let localCondition = videoStats.transport?.networkCondition ?? .unknown
let remoteCondition = videoStats.remotePublisherTransport?.networkCondition ?? .unknown
let source = videoStats.networkDegradationSource
switch source {
case .local:
print("Local network is degraded (condition: \(localCondition.rawValue))")
case .remote:
print("Remote publisher network is degraded (condition: \(remoteCondition.rawValue))")
case .bothOrUnclear:
print("Degradation source unclear — local: \(localCondition.rawValue), remote: \(remoteCondition.rawValue)")
default:
break
}
}
RTC-Statistikbericht
Um Low-Level-Stream-Statistiken zu erhalten, verwenden Sie die getRtcStatsReport() Methode auf OTPublisherKit. Dadurch werden RTC-Statistikberichte für den Medienstrom asynchron bereitgestellt.
Bevor Sie diese Methode aufrufen, setzen Sie die rtcStatsReportDelegate Eigenschaft Ihres Verlegers und implementieren Sie die Delegate-Methode publisher(_:rtcStatsReport:) von OTPublisherKitRtcStatsReportDelegate. Wenn die Statistiken verfügbar sind, wird diese Methode mit einem Array von OTPublisherRtcStats Objekte. Jedes Objekt enthält eine jsonArrayOfReports Eigenschaft, bei der es sich um ein JSON-Array mit RTC-Statistiken handelt, die dem von WebRTC in Webbrowsern verwendeten Format ähneln.
Beispiel
class MyViewController: UIViewController, OTPublisherKitRtcStatsReportDelegate {
var publisher: OTPublisher?
func setupPublisher() {
// Create and configure the publisher
publisher = OTPublisher(delegate: self, settings: OTPublisherKitSettings())
publisher?.rtcStatsReportDelegate = self
}
func fetchRtcStats() {
publisher?.getRtcStatsReport()
}
// Delegate method called when stats are ready
func publisher(_ publisher: OTPublisherKit, rtcStatsReport stats: [OTPublisherRtcStats]) {
for stat in stats {
print("RTC Stats JSON: \(stat.jsonArrayOfReports)")
}
}
}
Siehe diese Mozilla-Dokumente. Siehe auch diese W3C-Dokumentation.
Muster
Die Vonage Video iOS SDK Client SDK Beobachtbarkeit Beispielanwendung demonstriert die Funktionen zur Beobachtung von Clients in einer mobilen Anwendung, die mit dem iOS Client SDK erstellt wurde.