Inscreva-se: Diagnósticos
Use este guia para verificar os detalhes das transmissões, detectar quando elas terminam e resolver problemas comuns dos assinantes. Ele também inclui orientações para lidar com problemas de conectividade na interface do usuário.
Informações sobre a transmissão
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.
Consulte Guia do desenvolvedor sobre observabilidade do cliente para obter informações detalhadas.
Você também pode obter detalhes de diagnóstico das transmissões ativas para auxiliar na depuração e na análise.
Para obter estatísticas de áudio e vídeo dos assinantes, adicione manipuladores de eventos para o audioNetworkStats e videoNetworkStats evento disparado pelo OTSubscriber. Esses eventos fornecem informações sobre o fluxo do assinante, incluindo o seguinte:
- O número total de pacotes de áudio e vídeo perdidos.
- O número total de pacotes de áudio e vídeo recebidos.
- O número total de bytes de áudio e vídeo recebidos.
- A taxa média atual de quadros do vídeo.
<OTSubscriber
eventHandlers={{
audioNetworkStats: event => {
console.log('subscriber audioNetworkStats event', event);
},
videoNetworkStats: event => {
console.log('subscriber videoNetworkStats event', event);
},
}}
/>
Para obter estatísticas mais detalhadas sobre a transmissão, use o Subscriber.getRtcStatsReport() método do objeto OTSubscriber. Ele retorna uma promessa que, em caso de sucesso, é resolvida com uma representação em JSON de um RtcStatsReport objeto para o fluxo assinado:
<OTSubscriber
eventHandlers={{
connected: event => {
setTimeout(() => {
this.subscriber.getRtcStatsReport();
}, 4000);
},
rtcStatsReport: event => {
console.log('subscriber rtcStatsReport event', event);
},
}}
/>
O objeto Stream possui as seguintes propriedades que definem o fluxo:
connection— O objeto Connection correspondente à conexão que está publicando o fluxo. Você pode comparar isso com a propriedade connection do objeto Session para verificar se o fluxo está sendo publicado pela página da web local.creationTime— O carimbo de data/hora (um número) correspondente à criação do fluxo. Esse valor é calculado em milissegundos. É possível converter esse valor em um objeto Date chamandonew Date(stream.creationTime).hasAudio— (Booleano) Indica se o stream possui áudio. Essa propriedade pode mudar se o editor ativar ou desativar o áudio (chamando Publisher.publishAudio()). Quando isso ocorre, o Sessão o objeto despacha umstreamPropertyChangedevento.hasVideo— (Booleano) Se a transmissão contém vídeo. iniciais—(Booleano) As iniciais da transmissão (caso tenham sido definidas quando o editor da transmissão foi inicializado).name— (String) O nome do fluxo. Por padrão, ele é exibido quando o usuário passa o mouse sobre o Assinante no DOM HTML. No entanto, é possível personalizar a interface do usuário para ocultar o nome ou exibi-lo sem precisar passar o mouse sobre ele.videoDimensions— Este objeto possui duas propriedades:widtheheight. Ambos são números. OwidthA propriedade é a largura do fluxo codificado; oheightEssa propriedade representa a altura do fluxo codificado. (Esses valores são independentes da largura real dos objetos Publisher e Subscriber correspondentes ao fluxo.) Essa propriedade pode mudar se um fluxo publicado a partir de um dispositivo iOS for redimensionado, devido a uma mudança na orientação do dispositivo.videoType— O tipo de vídeo: “câmera”, “tela”, “personalizado” ou indefinido. Um vídeo do tipo “tela” utiliza o compartilhamento de tela no editor como fonte de vídeo; um vídeo do tipo “personalizado” utiliza um elemento VideoTrack como fonte de vídeo no editor. OvideoTypeéundefinedquando uma transmissão é apenas de voz (consulte o Guia apenas por voz). Essa propriedade pode mudar se uma transmissão publicada a partir de um dispositivo móvel passar de um tipo de vídeo capturado pela câmera para um tipo de vídeo de compartilhamento de tela. Para obter mais informações, consulte Compartilhamento de tela — Web.
O hasAudio, hasVideo, videoDimensions, e videoType as propriedades podem sofrer alterações (por exemplo, quando o editor ativa ou desativa o vídeo). Quando isso ocorre, o objeto Session dispara um evento streamPropertyChanged (consulte StreamPropertyChangedEvent).
O objeto Stream possui os seguintes métodos que retornam valores que definem o fluxo:
getConnection()— (Connection) Retorna o objeto Connection correspondente à conexão que está publicando o fluxo. É possível comparar esse valor com o valor retornado pelagetConnection()método do objeto Session para verificar se o fluxo está sendo publicado pelo seu cliente.getCreationTime()— (Data) O carimbo de data e hora correspondente ao momento da criação do fluxo.hasAudio()— (booleano) Se o stream possui áudio.hasVideo()— (booleano) Se o stream contém vídeo.getName()— (String) Retorna o nome do fluxo. Esse nome é definido ao inicializar o Publisher do fluxo (consulte Inicializando um objeto Publisher).getStreamId()— (String) O ID exclusivo do stream.getVideoHeight()— (int) A altura do fluxo, em pixels.getVideoType()— (StreamVideoType) Se a transmissão utiliza uma fonte de vídeo de câmera (StreamVideoTypeCamera.StreamVideoTypeCamera), uma fonte de vídeo para compartilhamento de tela (StreamVideoTypeScreen.StreamVideoTypeScreen), ou uma fonte de vídeo personalizada (StreamVideoTypeScreen.StreamVideoTypeScreen).
Veja Compartilhamento de tela.
getVideoWidth()— (int) A largura do fluxo, em pixels.
O objeto OTStream possui as seguintes propriedades que definem o fluxo:
connection—O objeto OTConnection correspondente à conexão que está publicando o fluxo. Você pode comparar isso com oconnectionpropriedade do objeto OTSession para verificar se o fluxo está sendo publicado pelo seu cliente.creationTime—O carimbo de data e hora correspondente à data de criação do stream.hasAudio—(Bool) Se o stream possui áudio.hasVideo—(Bool) Se a transmissão contém vídeo.name—(String?) O nome do fluxo. Esse valor é definido ao inicializar o Publisher do fluxo (consulte Inicializando um objeto OTPublisher).session—(OTSession) A sessão de vídeo da Vonage à qual o fluxo está vinculado.streamId—(String) O ID exclusivo do fluxo.videoDimensions—Um objeto CGSize que define as dimensões atuais da trilha de mídia de vídeo neste fluxo.videoType—(OTStreamVideoType) Se a transmissão utiliza uma fonte de vídeo de câmera (OTStreamVideoTypeCamera), uma fonte de vídeo para compartilhamento de tela (OTStreamVideoTypeScreen), ou uma fonte de vídeo personalizada (OTStreamVideoTypeCustom).
Veja Compartilhamento de tela.
O objeto OTStream possui as seguintes propriedades que definem o fluxo:
connection—O objeto OTConnection correspondente à conexão que está publicando o fluxo. Você pode comparar isso com oconnectionpropriedade do objeto OTSession para verificar se o fluxo está sendo publicado pelo seu cliente.creationTime—O carimbo de data e hora NSDate correspondente à data de criação do fluxo.hasAudio—(Booleano) Se o stream possui áudio.hasVideo—(Booleano) Se a transmissão contém vídeo.name—(NSString) O nome do fluxo. Esse valor é definido ao inicializar o Publisher do fluxo (consulte Inicializando um objeto OTPublisher).session—(OTSession) A sessão de vídeo da Vonage à qual o fluxo está vinculado.streamId—(NSString) O ID exclusivo do fluxo.videoDimensions—Um objeto CGSize que define as dimensões atuais da trilha de mídia de vídeo neste fluxo.videoType—(OTStreamVideoType) Se a transmissão utiliza uma fonte de vídeo de câmera (OTStreamVideoTypeCamera), uma fonte de vídeo para compartilhamento de tela (OTStreamVideoTypeScreen), ou uma fonte de vídeo personalizada (OTStreamVideoTypeCustom).
Veja Compartilhamento de tela.
O objeto Stream possui as seguintes propriedades que definem o fluxo:
Connection— (Conexão) O objeto Connection correspondente à conexão que está publicando o fluxo. Você pode comparar isso com oConnectionpropriedade do objeto Session para verificar se o fluxo está sendo publicado pelo seu cliente.CreationTime— (DateTime) O carimbo de data e hora (DateTime) correspondente ao momento da criação do fluxo.HasAudio— (bool) Se o stream possui áudio.HasVideo— (bool) Indica se a transmissão contém vídeo.Name— (string) O nome do fluxo. Esse valor é definido ao inicializar o Publisher do fluxo (consulte Inicializando um objeto Publisher).Id— (string) O ID exclusivo do stream.Height— (int) A altura do fluxo, em pixels.VideoSourceType— (VideoSourceType) Se a transmissão utiliza uma fonte de vídeo de câmera (VideoSourceType.StreamVideoTypeCamera), uma fonte de vídeo para compartilhamento de tela (VideoSourceType.StreamVideoTypeScreen), ou uma fonte de vídeo personalizada (VideoSourceType.StreamVideoTypeCustom).
Veja Compartilhamento de tela.
Width— (int) A largura do fluxo, em pixels.
Chame as seguintes funções para obter informações sobre um fluxo:
otc_stream_get_connection()— Retorna ootc_connectioninstância correspondente à conexão que está publicando o fluxo. Você pode comparar o ID dessa conexão com o ID da conexão para ootc_connectioninstância retornada pelootc_session_get_connection()função para verificar se o stream está sendo publicado pelo seu cliente.otc_stream_get_creation_time()— Retorna o timestamp correspondente à hora de criação do stream.otc_stream_has_audio()— Se a transmissão está transmitindo áudio no momento.otc_stream_has_video()— Se a transmissão está exibindo vídeo no momento.otc_stream_has_audio_track()— Se a transmissão possui uma trilha de áudio.otc_stream_has_video_track()— Se a transmissão possui uma trilha de vídeo.otc_stream_get_name()— Retorna o nome do fluxo. Esse nome é definido quando você inicializa o Publisher do fluxo (consulte Inicializando uma estrutura `otc_publisher` e definindo callbacks do publisher).otc_stream_get_id()— Retorna o ID exclusivo do stream.otc_stream_get_video_height()— A altura do fluxo, em pixels.otc_stream_get_video_type()— Se a transmissão utiliza uma fonte de vídeo de câmera (OTC_STREAM_VIDEO_TYPE_CAMERA) ou uma fonte de vídeo de compartilhamento de tela (OTC_STREAM_VIDEO_TYPE_SCREEN).otc_stream_get_video_width()— A largura do stream, em pixels.
Detectar o fim da transmissão e quando o vídeo está desativado
Detecte quando um fluxo termina para que você possa realizar a limpeza e ajustar a interface do usuário.
Quando o vídeo de um assinante é desativado, o objeto OTSubscriber dispara um videoDisabled evento:
<OTSubscriber
eventHandlers={{
videoDisabled: (event) => {
console.log('stream video disabled -- stream ID:', event.streamId);
// Display a user interface notification.
},
}}/>
Quando o Media Router desativa o vídeo de um assinante, talvez seja necessário ajustar a interface do usuário relacionada a esse assinante.
O reason propriedade do videoDisabled O objeto de evento define o motivo pelo qual o vídeo foi desativado. Ele pode ser definido com um dos seguintes valores:
-
"PublisherPropertyChanged"— A editora deixou de publicar vídeos. -
"QualityChanged"— O Media Router interrompeu o envio de vídeo ao assinante devido a alterações na qualidade do stream. Esse recurso do Media Router faz com que o assinante interrompa o stream de vídeo quando a conectividade se deteriora. (O assinante continua recebendo o stream de áudio, caso haja um.)
Antes de enviar esse evento, quando a qualidade do stream do assinante se deteriora a um nível tão baixo que o stream de vídeo corre o risco de ser desativado, o OTSubscriber o objeto envia um videoDisableWarning evento.
Se a conectividade melhorar a ponto de permitir novamente a exibição de vídeos, o OTSubscriber o objeto despacha um videoEnabled evento, e o assinante volta a receber o vídeo.
Esse recurso está disponível apenas em sessões que utilizam o Roteador de mídia (sessões com o modo de mídia definido como “roteado”), e não em sessões com o modo de mídia definido como “retransmitido”.
Ao publicar uma transmissão, você pode evitar que o vídeo seja desativado devido à qualidade da transmissão. Defina audioFallbackEnabled para false no properties passar o prop para o componente OTPublisher.
-
"SubscriberPropertyChanged"— O assinante iniciou ou interrompeu a assinatura do vídeo, definindo `subscribeToVideo` como `false` na propriedade `prop` passada para oOTSubscribercomponente. -
"CodecNotSupported"— O assinante interrompeu a assinatura do vídeo devido a um codec incompatível (consulte o Guia para desenvolvedores de codecs de vídeo).
O OTSubscriber despachos de objetos videoEnabled evento quando o vídeo for retomado:
A propriedade `reason` do objeto do evento `videoEnabled` define o motivo pelo qual o vídeo foi ativado. Ela pode ser definida com um dos seguintes valores:
-
"PublisherPropertyChanged"— A editora retomou a publicação de vídeos. -
"QualityChanged"— O Media Router retomou o envio do vídeo ao assinante com base nas mudanças na qualidade do stream. Esse recurso do Media Router faz com que o assinante interrompa o stream de vídeo quando a conectividade piora e, em seguida, retome o stream caso a qualidade melhore.
Esse recurso está disponível apenas em sessões que utilizam o Media Router (sessões com o modo de mídia definido como “routed”), e não em sessões com o modo de mídia definido como “relayed”.
-
"SubscriberPropertyChanged"— O assinante iniciou ou cancelou a assinatura do vídeo, ao definirsubscribeToVideopara “false” na propriedade prop passada ao componente OTSubscriber. -
"CodecNotSupported"— O vídeo para assinantes foi habilitado após uma mudança de codec, que antes era incompatível (consulte o Guia para desenvolvedores de codecs de vídeo).
Quando um stream, que não seja o seu, sai de uma sessão, o objeto Session dispara um streamDestroyed evento:
session.on("streamDestroyed", function (event) {
console.log("Stream stopped. Reason: " + event.reason);
});
Quando um fluxo publicado sai de uma sessão, o objeto Publisher dispara um streamDestroyed evento:
var publisher = OT.initPublisher();
publisher.on("streamDestroyed", function (event) {
console.log("Stream stopped. Reason: " + event.reason);
});
O streamDestroyed O evento é definido pela classe StreamEvent. O evento inclui um reason propriedade, que explica por que a transmissão foi encerrada. Esses motivos incluem "clientDisconnected", "forceDisconnected", "forceUnpublished", ou "networkDisconnected". Para mais detalhes, consulte StreamEvent.
Por padrão, quando um streamDestroyed Quando um evento é disparado para um fluxo ao qual você está inscrito, os objetos Subscriber correspondentes (pode haver mais de um) são destruídos e removidos do DOM HTML. Você pode impedir esse comportamento padrão chamando o preventDefault() método do objeto StreamEvent:
session.on("streamDestroyed", function (event) {
event.preventDefault();
var subscribers = session.getSubscribersForStream(event.stream);
// Now you can adjust the DOM elements around each
// subscriber to the stream, and then delete it yourself.
});
Observe que o getSubscribersForStream() O método de um objeto Session retorna todos os objetos Subscriber de um Stream.
Talvez você queira impedir o comportamento padrão e manter o Subscriber, caso deseje ajustar os elementos DOM relacionados antes de excluir o Subscriber por conta própria. Em seguida, você pode excluir o objeto Subscriber (e seu elemento DOM) chamando o destroy() método do objeto Subscriber.
Um objeto Subscriber despacha um destroyed evento que ocorre quando o objeto é removido do DOM HTML. Em resposta a esse evento, você pode optar por ajustar (ou remover) os elementos do DOM relacionados ao assinante que foi removido.
Quando os fluxos publicados por outros clientes saem de uma sessão, o onStreamDropped(Session session, Stream stream) é chamado o método do objeto Session.SessionListener. Quando um fluxo é encerrado, a visualização de qualquer objeto Subscriber associado a esse fluxo é removida de sua supervisualização.
Detectar quando o vídeo de um assinante está desativado
O Vonage Video Media Router interrompe o envio de vídeo ao assinante quando detecta que a conectividade está se deteriorando. O assinante continua recebendo o fluxo de áudio, caso haja algum. O onVideoDisabled(assinante, assinante) O método do objeto SubscriberKit.VideoListener é chamado quando o Vonage Video Media Router interrompe o envio de vídeo:
@Override
public void onVideoDisabled(subscriber, reason) {
// Video is disabled for the subscriber
}
O reason O parâmetro identifica o motivo pelo qual o assinante interrompeu a transmissão do vídeo.
Quando o Vonage Video Media Router desativa o vídeo de um assinante, talvez seja necessário ajustar a interface do usuário relacionada a esse assinante.
O onVideoEnabled(assinante, motivo) O método do objeto SubscriberKit.VideoListener é chamado quando o vídeo retoma a reprodução:
@Override
public void onVideoEnabled(subscriber, reason) {
// Video is resumes for the subscriber
}
O reason O parâmetro identifica o motivo pelo qual o vídeo do assinante foi retomado.
Ao publicar uma transmissão, você pode evitar que o vídeo seja desativado devido à qualidade da transmissão. Antes de chamar a função Session.publish(publisher) método, chame o setAudioFallbackEnabled(boolean enabled) método do objeto Publisher (ou do objeto PublisherKit) e passar false.
Quando os streams saem de uma sessão, o OTSession session(_:streamDestroyed:) A mensagem é enviada. Quando um stream é descartado, a visualização de qualquer objeto OTSubscriber associado a esse stream é removida de sua superview. Verifique se o stream não foi publicado pelo seu próprio cliente e remova sua visualização da superview.
func session(_ session: OTSession, streamDestroyed stream: OTStream) {
print("Session streamDestroyed: \(stream.streamId)")
if subscriber?.stream?.streamId == stream.streamId {
subscriber?.view?.removeFromSuperview()
subscriber = nil
}
}
Detectar quando o vídeo de um assinante está desativado
O representante do assinante envia o OTSubscriberDelegate subscriberVideoDisabled(_:reason:) mensagem exibida quando o vídeo do assinante está desativado:
func subscriberVideoDisabled(_ subscriber: OTSubscriberKit, reason: OTSubscriberVideoEventReason) {
print("subscriber video disabled.")
}
O reason O parâmetro pode ser definido como uma das seguintes constantes definidas na enumeração OTSubscriberVideoEventReason:
OTSubscriberVideoEventPublisherPropertyChanged— O problema com o vídeo ocorreu porque o autor da transmissão interrompeu a transmissão.OTSubscriberVideoEventQualityChanged— O problema no vídeo foi causado por uma alteração na qualidade do fluxo de vídeo. A qualidade do fluxo pode variar devido às condições da rede ou ao uso da CPU, tanto no lado do assinante quanto no do emissor. Esse motivo é utilizado apenas em sessões cujo modo de mídia esteja definido como “roteado”. (Consulte O Roteador de Mídia de Vídeo da Vonage e os modos de mídia.) Esse recurso do Vonage Video Media Router faz com que o assinante interrompa a transmissão de vídeo quando a qualidade do sinal se deteriora, e a mensagem é enviada. Quando as condições melhoram, a transmissão de vídeo é retomada, e oOTSubscriberDelegate subscriberVideoEnabled(_:reason:)A mensagem é enviada. Quando o fluxo de vídeo é interrompido, o assinante continua recebendo o fluxo de áudio, caso haja um.OTSubscriberVideoEventSubscriberPropertyChanged— O problema com o vídeo foi causado por uma alteração na conta deste assinanteOTSubscriber subscribeToVideopropriedade.
Se a transmissão de vídeo for retomada, o OTSubscriberDelegate subscriberVideoEnabled(_:reason:) A mensagem é enviada.
Ao publicar uma transmissão, você pode evitar que o vídeo seja desativado devido à qualidade da transmissão. Antes de chamar a função OTSession publish(_:error:) método, defina o audioFallbackEnabled propriedade do objeto Publisher (ou do objeto PublisherKit) para “false”.
O [OTSessionDelegate session:streamCreated:] A mensagem é enviada quando um novo fluxo é criado em uma sessão. (Um fluxo é criado quando um cliente publica um fluxo para a sessão.) O Objeto OTStream possui propriedades que definem o fluxo. Compare o connection propriedade do objeto OTStream com o connection propriedade do objeto OTSession para determinar se o fluxo é aquele publicado pelo seu cliente:
- (void)session:(OTSession*)session streamCreated:(OTStream*)stream
{
NSLog(@"session streamCreated (%@)", stream.streamId);
// See the declaration of subscribeToSelf above.
if ([stream.connection.connectionId isEqualToString: session.connection.connectionId]) {
// This is my own stream
} else {
// This is a stream from another client.
}
}
Quando os fluxos publicados por outros clientes saem de uma sessão, o objeto Session envia um StreamDropped evento:
session.StreamDropped += Session_StreamDropped;
public void Session_StreamDropped(object sender, EventArgs e)
{
// Stream dropped
}
O objeto de argumentos de evento passado para esta função é definido pela classe OpenTok.Session.StreamEventArgs. Essa classe inclui um Stream propriedade. Compare isso Stream opor-se à Stream propriedade de cada objeto Subscriber para identificar o assinante da transmissão.
Detectar quando o vídeo de um assinante está desativado
O Vonage Video Media Router interrompe o envio de vídeo ao assinante quando detecta que a conectividade está se deteriorando. O assinante continua recebendo o fluxo de áudio, caso haja algum. Quando o Vonage Video Media Router interrompe o envio de vídeo, o objeto Assinante envia um VideoDisabled evento:
subscriber.VideoDisabled += Subscriber_VideoDisabled;
public void Subscriber_VideoDisabled(object sender)
{
// Display a user interface notification.
}
Quando o Vonage Video Media Router desativa o vídeo de um assinante, talvez seja necessário ajustar a interface do usuário relacionada a esse assinante.
O objeto Subscriber envia um VideoDisabled evento quando o vídeo for retomado:
subscriber.VideoEnabled += Subscriber_VideoEnabled;
public void Subscriber_VideoEnabled(object sender)
{
// Video resumes for the subscriber.
}
O on_stream_dropped função de retorno de chamada do otc_session_callbacks A função `struct` é chamada quando o stream de outro cliente é removido da sessão do Vonage Video. O stream O parâmetro passado para esta função é um ponteiro para um otc_stream estrutura para o fluxo. Chame a otc_stream_get_id() método, passando o otc_stream struct, para obter o ID do fluxo.
Detectar quando o vídeo de uma transmissão está desativado
O on_stream_has_video_changed função de retorno de chamada do otc_session_callbacks A função `struct` é chamada quando o stream de outro cliente é removido da sessão do Vonage Video. O stream O parâmetro passado para esta função é um ponteiro para um otc_stream estrutura para o fluxo. Chame a otc_stream_get_id() método, passando o otc_stream struct, para obter o ID do fluxo.
Solução de problemas (JavaScript)
Dicas para lidar com erros de assinatura e problemas de conectividade.
Para obter informações gerais sobre solução de problemas, consulte Inspecionador de Vídeos.
Tratamento de erros
Só há uma maneira de se inscrever — com Session.subscribe()—e a maioria dos erros está relacionada à rede. Se o Assinante não conseguir se conectar, será exibida uma mensagem de erro automática, mas é melhor você mesmo exibir uma mensagem clara:
session.subscribe(event.stream, 'subscriber', {insertMode: 'append'}, function (err) {
if (err) {
showMessage('Streaming connection failed. This could be due to a restrictive firewall.');
}
});
Perda de conectividade
Um assinante pode perder a conexão após ter se conectado. Trate o streamDestroyed evento na Sessão quando o motivo for networkDisconnected e informar o usuário sem excluir o assinante imediatamente:
session.on({
streamDestroyed: function (event) {
if (event.reason === 'networkDisconnected') {
event.preventDefault();
var subscribers = session.getSubscribersForStream(event.stream);
if (subscribers.length > 0) {
var subscriber = document.getElementById(subscribers[0].id);
subscriber.innerHTML = 'Lost connection. This could be due to your internet connection or because the other party lost their connection.';
event.preventDefault();
}
}
}
});
Para o tratamento de eventos de assinantes e ajustes em tempo de execução (áudio bloqueado, vídeo desativado, estatísticas), consulte Inscreva-se: Gestão e Eventos.
Implementação de novas tentativas de assinatura de sessão
Podem ocorrer falhas temporárias na assinatura quando session.subscribe() é chamado e a conexão WebRTC subjacente não pode ser estabelecida a tempo, ou quando uma falha momentânea na rede interrompe a negociação do ICE. Quando session.subscribe() Se falhar, o SDK retorna um erro por meio do callback do manipulador de conclusão. A abordagem recomendada é implementar uma lógica de repetição de tentativa no nível do aplicativo, com um intervalo entre as tentativas.
Observação: Suporte integrado para repetição de tentativas para session.subscribe() está no roteiro do SDK. Até que isso seja lançado, você precisará implementar isso por conta própria.
Por que ocorrem falhas nas assinaturas
As causas principais mais comuns para falhas transitórias na assinatura são:
OT_TIMEOUT(código 1501): A assinatura não foi concluída dentro do intervalo de tempo permitido (30 segundos). Esse é o equivalente, do lado da assinatura, ao tempo limite de publicação e é o erro mais comum que pode ser repetido.- Fracassos nas negociações do ICE (
OT_ICE_WORKFLOW_FAILED): Não foi possível estabelecer a conexão entre pares via WebRTC, geralmente devido a uma rede restritiva ou a um problema temporário de conectividade. - Falhas na criação de conexões entre pares (
OT_CREATE_PEER_CONNECTION_FAILED): Não foi possível criar o objeto de conexão entre pares do WebRTC, o que geralmente é causado por um problema temporário na plataforma ou na rede. - Problemas de rede durante o processo de assinatura: Uma breve interrupção na rede durante a negociação do ICE ou a vinculação de mídia pode fazer com que a assinatura expire sem que ocorra um erro grave.
Erros recuperáveis x erros não recuperáveis
Nem todos session.subscribe() nem todos os erros são iguais. É essencial classificar os erros corretamente antes de tentar novamente — tentar novamente em caso de um erro irrecuperável desperdiça tempo e pode mascarar falhas reais.
Observação: Sempre use o error.name propriedade para identificar erros programaticamente. O valor numérico error.code A propriedade está obsoleta.
Erros irrecuperáveis — Não tente novamente
Esses erros representam restrições rígidas, contexto de chamada inválido ou estados do fluxo do terminal. Repetir a tentativa não resolverá esses erros.
error.name |
Descrição | Ação recomendada |
|---|---|---|
OT_NOT_CONNECTED |
session.subscribe() foi chamada antes que a sessão fosse estabelecida. |
Certifique-se de que session.connect() tenha sido concluído com sucesso antes de se inscrever. |
OT_DISCONNECTED |
A ação falhou porque o cliente não está conectado à sessão. | Aguarde até que a sessão se reconecte antes de tentar novamente. |
OT_INVALID_PARAMETER |
Um ou mais parâmetros passados para session.subscribe() eram inválidos (por exemplo, fluxo nulo ou elemento de destino). |
Corrija a lógica da aplicação. Não tente novamente. |
OT_STREAM_DESTROYED |
A transmissão foi encerrada antes que fosse possível se inscrever nela. | Não tente novamente — o fluxo não existe mais. Remova qualquer estado de assinatura pendente para esse fluxo. |
OT_STREAM_NOT_FOUND |
Não foi possível localizar o stream na sessão. | Não tente novamente — o stream não está mais disponível. |
OT_STREAM_LIMIT_EXCEEDED |
A sessão ultrapassou o limite de transmissões simultâneas. | Informe o usuário. Não tente novamente até que um slot de fluxo fique disponível. |
OT_UNABLE_TO_SUBSCRIBE |
O usuário tentou se inscrever em uma sessão com criptografia de ponta a ponta (E2EE) ativada sem especificar um segredo de criptografia; ou um erro inesperado impediu a inscrição. | Para sessões com criptografia de ponta a ponta (E2EE), certifique-se de que um segredo de criptografia esteja definido por meio de session.setEncryptionSecret() antes de se inscrever. No caso geral, registre o erro e informe o usuário. |
Erros recuperáveis — É seguro tentar novamente
Esses erros são normalmente causados por condições transitórias da rede, tempo limite de sinalização ou indisponibilidade temporária da plataforma.
error.name |
Descrição | Ação recomendada |
|---|---|---|
OT_TIMEOUT (código 1501) |
A assinatura não foi concluída dentro de um prazo razoável. Esse é o erro mais comum na assinatura que pode ser repetido. | Cancele a inscrição e, em seguida, tente novamente com intervalo entre tentativas (até 3 tentativas). |
OT_ICE_WORKFLOW_FAILED |
A negociação ICE falhou — não foi possível estabelecer a conexão entre pares. Isso costuma ocorrer temporariamente em redes restritivas. | Cancele a inscrição e tente novamente. Se o problema persistir após todas as tentativas, informe o usuário sobre um possível problema de rede ou firewall. |
OT_CREATE_PEER_CONNECTION_FAILED |
Não foi possível estabelecer a conexão entre pares via WebRTC. Isso pode indicar um firewall restritivo ou um problema temporário na plataforma. | Cancele a inscrição e tente novamente. Se o problema persistir, sugira que o usuário verifique sua conexão de rede. |
OT_SET_REMOTE_DESCRIPTION_FAILED |
A conexão WebRTC falhou durante setRemoteDescription. Normalmente, trata-se de um problema temporário de sinalização. |
Cancele a inscrição e, em seguida, tente novamente com um intervalo. |
OT_MEDIA_ERR_ABORTED / OT_MEDIA_ERR_NETWORK |
A aquisição da mídia foi cancelada ou interrompida devido a um erro de rede. | Cancele a inscrição e tente novamente após um breve intervalo. |
OT_MEDIA_ERR_DECODE |
Ocorreu um erro de decodificação ao tentar reproduzir o stream no elemento de vídeo. | Cancele a inscrição e tente novamente após um breve intervalo. Se o problema persistir, o formato da mídia pode ser incompatível. |
OT_MEDIA_ERR_SRC_NOT_SUPPORTED |
Foi detectado que o stream não é adequado para reprodução. | Cancele a inscrição e tente novamente uma vez. Se o problema persistir, verifique a configuração do elemento de vídeo do assinante. |
Importante: sempre cancele a inscrição antes de tentar novamente
Ao contrário de session.publish(), onde a instância do editor muitas vezes pode ser reutilizada diretamente, session.subscribe() exige que você ligue session.unsubscribe() e descarte o objeto do assinante antes de tentar novamente. A tentativa de reutilizar uma instância de assinante com falha não funcionará.
async function subscribeWithRetry(session, stream, targetElement, options, attempt = 1) {
const MAX_RETRIES = 3;
const RETRY_DELAY_MS = 3000;
let subscriber = session.subscribe(stream, targetElement, options);
const error = await new Promise((resolve) => {
subscriber.on('subscribeComplete', (err) => resolve(err));
});
if (!error) {
console.log('Subscribed successfully.');
return subscriber;
}
// Always clean up the failed subscriber before retrying
try { session.unsubscribe(subscriber); } catch (e) { /* ignore */ }
// Non-recoverable: do not retry
const nonRetryable = [
'OT_NOT_CONNECTED',
'OT_DISCONNECTED',
'OT_INVALID_PARAMETER',
'OT_STREAM_DESTROYED',
'OT_STREAM_NOT_FOUND',
'OT_STREAM_LIMIT_EXCEEDED',
'OT_UNABLE_TO_SUBSCRIBE',
];
if (nonRetryable.includes(error.name)) {
console.error('Non-retryable subscribe error:', error.name);
handleNonRecoverableError(error);
return null;
}
// Recoverable: retry with backoff
if (attempt < MAX_RETRIES) {
console.warn(`Subscribe attempt ${attempt} failed (${error.name}), retrying...`);
await delay(RETRY_DELAY_MS * attempt);
return subscribeWithRetry(session, stream, targetElement, options, attempt + 1);
}
console.error('All subscribe attempts failed.');
handleSubscribeFailure(session, stream);
return null;
}
function delay(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
function handleNonRecoverableError(error) {
// Surface a meaningful message to the user based on error.name
}
function handleSubscribeFailure(session, stream) {
// Inform the user that the stream could not be loaded
}
Modo de uso:
session.on('streamCreated', (event) => {
subscribeWithRetry(session, event.stream, document.getElementById('subscriber'), {});
});
Cenários sensíveis ao tempo
O fluxo é encerrado durante uma tentativa de repetição
Se o fluxo for destruído enquanto uma nova tentativa estiver pendente, o streamDestroyed O evento de sessão será acionado. É necessário cancelar qualquer nova tentativa pendente para esse fluxo, a fim de evitar a assinatura de um fluxo que já não existe.
const pendingRetries = new Map(); // stream.id → timeout handle
session.on('streamDestroyed', (event) => {
const pending = pendingRetries.get(event.stream.id);
if (pending) {
clearTimeout(pending);
pendingRetries.delete(event.stream.id);
console.log(`Cancelled pending retry for destroyed stream: ${event.stream.id}`);
}
});
Reconexão da sessão durante uma nova tentativa de assinatura
Se a sessão estiver se reconectando (por exemplo, após uma queda na conexão de rede), adie a nova tentativa até que a sessão tenha se reconectado. Tentar fazer a assinatura enquanto a sessão estiver se reconectando resultará em falha imediata.
let isSessionReconnecting = false;
session.on('sessionReconnecting', () => { isSessionReconnecting = true; });
session.on('sessionReconnected', () => {
isSessionReconnecting = false;
// Re-trigger any deferred subscriptions here
});
// In your retry logic, check before retrying:
if (isSessionReconnecting) {
// Defer — wait for sessionReconnected before retrying
return;
}
O que NÃO fazer
- Faça não reutilizar uma instância de assinante com falha — sempre chamar
session.unsubscribe()e criar uma nova assinatura na nova tentativa. - Faça não tentar novamente em
OT_STREAM_DESTROYEDouOT_STREAM_NOT_FOUND— o stream não está mais disponível e qualquer nova tentativa sempre falhará. - Faça não tentar novamente em
OT_STREAM_LIMIT_EXCEEDED— trata-se de uma restrição de capacidade no nível da sessão, e não de um erro passageiro. - Faça não tentar novamente indefinidamente — limitar a 3 tentativas e informar o usuário caso todas falhem.
- Faça não tentar novamente enquanto a sessão está se reconectando — adiar até
sessionReconnectedincêndios.
Resumo dos parâmetros recomendados
| Parâmetro | Valor recomendado | Notas |
|---|---|---|
| Número máximo de tentativas | 3 | Em consonância com session.publish() orientações para nova tentativa |
| Atraso entre tentativas | 3 s × tentativa (3 s, 6 s, 9 s) | Um pouco mais longo do que as tentativas de reenvio de publicação — o tempo limite da assinatura é de 30 segundos |
| Em caso de falha em todas as tentativas de repetição | Informar o usuário | Evite encerrar a transmissão sem aviso prévio |
| Erros que não podem ser repetidos | OT_STREAM_DESTROYED, OT_STREAM_NOT_FOUND, OT_STREAM_LIMIT_EXCEEDED |
Falhe rápido nessas |
| Limpeza da lista de assinantes | Sempre session.unsubscribe() antes de tentar novamente |
Obrigatório — ao contrário dos editores, as instâncias de assinantes não podem ser reutilizadas |