Observabilidade do cliente: iOS (Swift)
O SDK de vídeo da Vonage disponibiliza métricas detalhadas sobre a qualidade do fluxo por meio de uma API de estatísticas de alto nível — recomendada para a maioria dos casos de uso —, que fornece estatísticas de áudio, vídeo, rede e do lado do remetente de forma unificada e sensível à sessão, mantendo-se estável durante as transições entre conexões entre pares. Para depuração avançada, o SDK também oferece acesso ao relatório bruto de estatísticas do WebRTC, que reflete dados não processados das conexões entre pares.
O SDK também disponibiliza métricas de condição de rede que oferecem uma avaliação geral do estado da conexão, tanto para emissores quanto para assinantes. Essas métricas incluem uma pontuação de condição de rede, o motivo por trás dessa pontuação e — para os assinantes — uma fonte de degradação que indica qual lado da conexão é responsável por quaisquer problemas observados. Consulte Condição da rede e fonte de degradação para mais detalhes.
API de estatísticas de links de áudio, vídeo e mídia
O SDK do Vonage Video para iOS envia estatísticas periódicas de áudio, vídeo e links de mídia tanto para editores quanto para assinantes. Essas estatísticas incluem contagem de pacotes, taxas de bits, dados de taxa de quadros, métricas de pausa/congelamento, informações sobre codecs e métricas de rede no nível de transporte, como estimativa de largura de banda e pontuação das condições da rede.
As estatísticas são disponibilizadas por meio de:
-
OTPublisherKitNetworkStatsDelegate— estatísticas do lado do editor (áudio, vídeo) -
OTSubscriberKitNetworkStatsDelegate— estatísticas do lado do assinante (áudio, vídeo)
Para recebê-los, habilite o delegado apropriado no editor ou no assinante.
Ativação das estatísticas para editores
Anexe uma classe que adote a interface `OTPublisherKitNetworkStatsDelegate`:
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
}
}
Implemente os callbacks:
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)")
}
}
Para um editor em uma sessão roteada (aquela que utiliza o Roteador de mídia de vídeo da Vonage), a matriz `stats` inclui um objeto, definindo as estatísticas para o fluxo único de mídia de áudio ou vídeo enviado ao Vonage Video Media Router. Em uma sessão retransmitida, a matriz `stats` inclui um objeto para cada assinante do fluxo publicado.
Recebimento de eventos de qualidade de vídeo nos editores
Se você também estiver interessado em eventos relacionados à qualidade do vídeo, implemente esta função de retorno de chamada:
func publisher(_ publisher: OTPublisherKit, videoQualityChanged stats: OTPublisherKitVideoNetworkStats, reason: OTPublisherVideoEventReason) {
print("Publisher video quality event: \(reason.rawValue)")
}
Recebimento de eventos de condição de rede nos editores
Para receber eventos de alteração nas condições da rede para o editor, implemente o publisher(_:networkConditionChanged:mediaLinkStats:reason:) função de retorno:
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)")
}
}
Essa função de retorno de chamada é acionada quando é detectada uma alteração significativa nas condições de rede do editor. Ela inclui as estatísticas atuais do link de mídia, juntamente com as métricas de transporte. Consulte Condição da rede e fonte de degradação para obter mais detalhes sobre como interpretar as pontuações e os motivos relativos às condições da rede.
Ativação de estatísticas para assinantes
Anexe uma classe que adote 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!)
}
}
Implemente os callbacks:
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)")
}
Recebimento de eventos de qualidade de vídeo nos assinantes
Além disso, tratar os eventos relacionados à alteração da qualidade de vídeo dos assinantes:
func subscriber(_ subscriber: OTSubscriberKit, videoQualityChanged stats: OTSubscriberKitVideoNetworkStats, reason: OTSubscriberVideoEventReason) {
print("Subscriber video quality event: \(reason.rawValue)")
}
Recebimento de eventos de condição da rede nos assinantes
Para receber eventos de alteração nas condições da rede para o assinante, implemente o subscriber(_:networkConditionChanged:mediaLinkStats:reason:) função de retorno:
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)")
}
Essa função de retorno de chamada é acionada quando é detectada uma alteração significativa nas condições da rede para o assinante ou para o editor remoto. Ela inclui as estatísticas atuais do link de mídia, com métricas de transporte locais e remotas e a origem da degradação. Consulte Condição da rede e fonte de degradação para obter mais detalhes sobre como interpretar as pontuações e os motivos relativos às condições da rede.
Estatística e Estruturas de Dados
Esta seção descreve as estruturas e propriedades fornecidas pela API de estatísticas de áudio e vídeo do iOS. Embora todas as plataformas do SDK de vídeo apresentem o mesmo conjunto de estatísticas, pode haver pequenas diferenças na forma como cada plataforma estrutura ou nomeia os campos individuais. Essas variações refletem convenções de design do SDK específicas de cada plataforma, e não diferenças nas métricas subjacentes.
Para obter uma explicação independente de plataforma sobre as estatísticas disponíveis e o que elas representam, consulte Visão geral da observabilidade do cliente.
OTTransportStats
Representa métricas compartilhadas no nível do transporte.
connectionEstimatedBandwidth– Largura de banda estimada disponível para conexão (bps).networkCondition– Pontuação atual do estado da rede (OTNetworkConditionUnknown,OTNetworkConditionCritical,OTNetworkConditionWarning,OTNetworkConditionFair,OTNetworkConditionGood, ouOTNetworkConditionExcellent).networkConditionReason– Principal motivo que afeta o estado da rede (OTNetworkReasonNone,OTNetworkReasonUnknown,OTNetworkReasonBandwidth, ouOTNetworkReasonPacketLoss).
OTPublisherKitVideoNetworkStats
Fornece estatísticas sobre a trilha de vídeo de um editor. Inclui:
connectionId– Em uma sessão retransmitida, o ID de conexão do cliente que está assinando o fluxo. Não definido em uma sessão roteada.subscriberId– Em uma sessão retransmitida, o ID de assinatura do cliente que está assinando o fluxo. Não definido em uma sessão roteada.videoPacketsLost– Estimativa de pacotes de vídeo perdidos.videoPacketsSent– Pacotes de vídeo enviados.videoBytesSent– Bytes de vídeo enviados.timestamp– Carimbo de data/hora do Unix, em milissegundos, no momento em que as estatísticas foram coletadas.startTime– O carimbo de data e hora, em milissegundos desde a época Unix, a partir do qual os totais acumulados começaram a ser calculados.videoLayers– A matriz de estatísticas da camada de vídeo (consulteOTPublisherKitVideoLayerStats).transport– Estatísticas de transporte.
OTPublisherKitAudioNetworkStats
Fornece estatísticas sobre a faixa de áudio de um editor. Inclui:
connectionId– Em uma sessão retransmitida, o ID de conexão do cliente que está assinando o fluxo. Não definido em uma sessão roteada.subscriberId– Em uma sessão retransmitida, o ID de assinatura do cliente que está assinando o fluxo. Não definido em uma sessão roteada.audioPacketsLost– Estimativa de pacotes perdidos.audioPacketsSent– Pacotes de áudio enviados.audioBytesSent– Trechos de áudio enviados.timestamp– Carimbo de data/hora do Unix em milissegundos.startTime– O carimbo de data e hora, em milissegundos desde a época Unix, a partir do qual os totais acumulados começaram a ser calculados.transport– Estatísticas de transporte.
OTPublisherKitVideoLayerStats
Representa uma camada de transmissão simultânea ou uma camada SVC.
width– Largura do quadro codificado.height– Altura do quadro codificado.encodedFrameRate– Quadros codificados por segundo.bitrate– Taxa de bits da camada (bps).totalBitrate– Taxa de bits da camada, incluindo a sobrecarga do RTP (bps).scalabilityMode– Descritor SVC/escalabilidade (por exemplo, “L3T3”).qualityLimitationReason– Motivo da limitação de qualidade (largura de banda, CPU, codec, resolução ou mudança de camada).codec– O codec utilizado por essa camada de vídeo.
OTSenderStats
Métricas de estimativa do lado do remetente (aplicadas tanto ao áudio quanto ao vídeo).
connectionMaxAllocatedBitrate– Taxa de bits máxima estimada para a conexão do remetente.connectionEstimatedBandwidth– Estimativa da largura de banda atual (bps).
OTSubscriberKitVideoNetworkStats
Fornece estatísticas sobre a trilha de vídeos de um assinante. Inclui:
videoPacketsLost– Estimativa de pacotes de vídeo perdidos.videoPacketsReceived– Pacotes de vídeo recebidos.videoBytesReceived– Bytes de vídeo recebidos.timestamp– Carimbo de data/hora do Unix, em milissegundos, no momento em que as estatísticas foram coletadas.senderStats– Métricas do lado do remetente (opcional).width– Largura do quadro decodificado em pixels.height– Altura do quadro decodificado em pixels.decodedFrameRate– Quadros por segundo decodificados.bitrate– Taxa de bits do vídeo (bps).totalBitrate– Taxa de bits, incluindo a sobrecarga do RTP (bps).pauseCount– Número de pausas (mais de 5 s desde o último quadro). Inclui desativações intencionais e casos de recurso alternativo de áudio.totalPausesDuration– Duração total da pausa (ms).freezeCount– Contagem de congelamentos (evento de congelamento definido pelo WebRTC).totalFreezesDuration– Duração total do congelamento (ms).codec– Codec atual do decodificador.
OTSubscriberKitAudioNetworkStats
Fornece estatísticas sobre a trilha de áudio de um assinante. Inclui:
audioPacketsLost– Estimativa de pacotes perdidos.audioPacketsReceived– Pacotes recebidos.audioBytesReceived– Bytes recebidos.timestamp– Carimbo de data/hora do Unix em milissegundos.senderStats– Métricas do lado do remetente (opcional).
OTPublisherKitMediaLinkStats
Fornece estatísticas no nível do transporte para as conexões de um provedor.
transport— Estatísticas de tráfego para a conexão de uplink desta editora (verOTTransportStats)
OTSubscriberKitMediaLinkStats
Fornece estatísticas no nível de transporte para as conexões de um assinante, incluindo visibilidade do desempenho da rede do editor remoto. Isso permite que as Applications diagnostiquem se os problemas de conexão se originam do downlink do assinante ou do uplink do editor.
transport— Estatísticas de transporte para a conexão de downlink deste assinante (consulteOTTransportStats)remotePublisherTransport— Estatísticas de transporte para a conexão de uplink do editor remoto (obtidas por meio de estatísticas do lado do remetente, consulteOTTransportStats). Essas estatísticas podem ser limitadas caso as estatísticas do remetente não estejam ativadas.networkDegradationSource— Indica a origem da degradação da rede (OTNetworkDegradationSourceLocal,OTNetworkDegradationSourceRemote,OTNetworkDegradationSourceBothOrUnclear, ouOTNetworkDegradationSourceUnknown)
Estatísticas do lado do remetente
Veja o Visão geral das estatísticas do lado do remetente.
Ativação das estatísticas do remetente
As estatísticas do remetente são recebidas pelos assinantes. Para receber essas estatísticas, habilite-as para o editor do fluxo definindo o senderStatsTrack propriedade para true para o OTPublisherKitSettings objeto usado para criar o editor.
let settings = OTPublisherKitSettings()
settings.senderStatsTrack = true
let publisher = OTPublisher(delegate: self, settings: settings)
Se senderStatsTrack Se não estiver habilitado, nenhum canal de estatísticas do remetente será publicado para esse editor. O valor padrão é NO.
Recebimento de estatísticas do lado do remetente
Se o editor tiver ativado as estatísticas do remetente, os assinantes as recebem automaticamente por meio do OTSubscriberKitNetworkStatsDelegate callbacks descrito acima. O senderStats propriedade em ambos OTSubscriberKitVideoNetworkStats e OTSubscriberKitAudioNetworkStats apresenta duas métricas:
connectionMaxAllocatedBitrate— A taxa de bits máxima que pode ser estimada para a conexãoconnectionEstimatedBandwidth— A largura de banda estimada atual para a conexão
Essas métricas são calculadas por pacote de áudio e vídeo; portanto, os mesmos valores aparecem tanto nas estatísticas de vídeo quanto nas de áudio.
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)")
}
}
Condição da rede e fonte da degradação
O SDK fornece métricas em tempo real sobre as condições da rede tanto para editores quanto para assinantes, incluindo uma pontuação de condição, o motivo por trás dessa pontuação e a origem da degradação para os assinantes. Para obter uma explicação completa sobre o modelo de condições da rede, as pontuações, os motivos e como ativá-lo, consulte o Visão geral da observabilidade do cliente.
Os dados sobre o estado da rede estão disponíveis por meio de dois canais:
- Estatísticas periódicas: O
transportAs propriedades dos objetos de estatísticas do editor e do assinante incluemnetworkConditionenetworkConditionReason. As estatísticas dos assinantes também revelamremotePublisherTransportenetworkDegradationSource. Veja Estruturas estatísticas para mais detalhes. - Eventos relacionados a alterações nas condições da rede: Callbacks dedicados em ambos editora e assinante são acionados quando é detectada uma mudança significativa nas condições da rede.
O exemplo a seguir mostra como usar os dados de condição da rede do assinante para identificar a origem da degradação:
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
}
}
Relatório de Estatísticas da RTC
Para obter estatísticas de fluxo de baixo nível, use o getRtcStatsReport() método em OTPublisherKit. Isso fornece relatórios de estatísticas de RTC para o fluxo de mídia de forma assíncrona.
Antes de chamar esse método, defina o rtcStatsReportDelegate propriedade do seu publisher e implemente o método delegado publisher(_:rtcStatsReport:) de OTPublisherKitRtcStatsReportDelegate. Quando as estatísticas estiverem disponíveis, esse método é chamado com um array de OTPublisherRtcStats objetos. Cada objeto contém um jsonArrayOfReports propriedade, que é um array JSON de relatórios de estatísticas do RTC, semelhante ao formato utilizado pelo WebRTC nos navegadores da web.
Exemplo
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)")
}
}
}
Veja esses documentos da Mozilla. Veja também esta documentação do W3C.
Exemplo
O Aplicativo de exemplo de observabilidade do cliente do Vonage Video Client SDK para iOS demonstra os recursos de observabilidade do cliente em um aplicativo móvel desenvolvido com o Client SDK para iOS.