Publier : Diagnostics
Ce guide explique comment obtenir des diagnostics pour les éditeurs et résoudre les problèmes les plus courants.
Obtenir des statistiques sur le flux d'un éditeur
Le SDK Video de Vonage expose des mesures détaillées de la qualité du flux par le biais d'une API de statistiques de haut niveau - recommandée pour la plupart des cas d'utilisation - qui fournit des statistiques audio, vidéo, réseau et côté expéditeur sous une forme unifiée et consciente de la session, qui reste stable lors des transitions de connexion entre pairs. Pour le débogage avancé, le SDK permet également d'accéder au rapport de statistiques WebRTC brut, qui reflète les données de connexion entre pairs non traitées.
Se référer à le guide du développeur de l'observabilité du client pour obtenir des informations détaillées.
Flux d'essai
Vous pouvez publier un flux de test et vérifier ses statistiques audio et vidéo afin de déterminer le type de flux (haute résolution ou audio uniquement) pris en charge par votre connexion.
Pour obtenir des statistiques sur un flux publié par le client local, vous devez utiliser une session qui utilise le routeur de médias (sessions dont le mode média est défini sur routé) et vous devez définir l'attribut testNetwork à la propriété true dans le options que vous passez dans l'objet Session.subscribe() méthode. Vous pouvez alors utiliser la méthode getStats() de l'objet Subscriber pour obtenir des statistiques audio et vidéo pour le flux que vous publiez.
Vous pouvez utiliser le SubscriberKit.setAudioStatsListener(AudioStatsListener listener) et SubscriberKit.setVideoStatsListener(VideoStatsListener listener) de l'objet Subscriber pour obtenir des statistiques audio et vidéo pour le flux que vous publiez.
Voir ce sujet pour plus d'informations.
Vous pouvez utiliser le networkStatsDelegate de l'objet OTSubscriberKit pour obtenir des statistiques audio et vidéo pour le flux que vous publiez.
Les vonage-video-api-network-test-samples comprend un exemple de code montrant comment utiliser les statistiques d'un flux de test avant de le publier dans une session.
Vous pouvez utiliser le networkStatsDelegate de l'objet OTSubscriberKit pour obtenir des statistiques audio et vidéo pour le flux que vous publiez.
Les vonage-video-api-network-test-samples comprend un exemple de code montrant comment utiliser les statistiques d'un flux de test avant de le publier dans une session.
Vous pouvez ensuite vous abonner au flux et utiliser la fonction Subscriber.AudioStatsUpdated et Subscriber.VideoStatsUpdated pour obtenir des statistiques audio et vidéo pour le flux que vous publiez.
Bonnes pratiques de publication
Cette section contient des conseils pour publier des flux avec succès.
Autoriser l'accès aux appareils
La meilleure pratique consiste à informer vos utilisateurs qu'ils devront autoriser l'accès à leur caméra et à leur microphone.
Nous constatons que le plus grand nombre d'échecs de publication est dû au fait que les utilisateurs ont cliqué sur le bouton "refuser" ou n'ont pas du tout cliqué sur le bouton "autoriser". Nous vous fournissons tous les événements dont vous avez besoin pour guider vos utilisateurs tout au long de ce processus :
publisher.on({
accessDialogOpened: function (event) {
// Show allow camera message
pleaseAllowCamera.style.display = 'block';
},
accessDialogClosed: function (event) {
// Hide allow camera message
pleaseAllowCamera.style.display = 'none';
}
});
C'est également une bonne idée d'utiliser le protocole SSL pour votre site web. En effet, Chrome ne demande aux utilisateurs de cliquer sur l'autorisation d'accès aux appareils qu'une seule fois par domaine si ce dernier est desservi par SSL. Cela signifie que vos utilisateurs (s'ils utilisent Chrome) n'ont pas à faire face à cette boîte de dialogue d'autorisation ou de refus à chaque fois qu'ils chargent la page.
Séparer OT.initPublisher() et Session.publish()
Nous recommandons également de diviser le OT.initPublisher() et Session.publish() étapes. Cela accélère le temps de connexion initial car vous vous connectez à la session en attendant que l'utilisateur clique sur le bouton d'autorisation. Ainsi, au lieu de :
session.connect(token, function (err) {
{... your error handling code ...}
if (!err) {
var publisher = OT.initPublisher();
session.publish(publisher);
}
});
Déplacer le OT.initPublisher() avant de vous connecter, comme dans l'exemple suivant :
var publisher = OT.initPublisher();
session.connect(token, function (err) {
{... your error handling code ...}
if (!err) {
session.publish(publisher);
}
});
Résolution et fréquence d'images
Vous pouvez définir la résolution et la fréquence d'images de l'éditeur lorsque vous l'initialisez :
OT.initPublisher(divId, {
resolution: '320x240',
frameRate: 15
});
Par défaut, la résolution d'un éditeur est de 640x480, mais vous pouvez également la régler sur 1920x1080, 1280x720 ou 320x240. Il est préférable d'essayer de faire correspondre la résolution à la taille d'affichage de la vidéo. Si vous n'affichez la vidéo qu'à 320x240 pixels, il est inutile de la diffuser à 1280x720 ou 1920x1080. La réduction de la résolution permet d'économiser de la bande passante et de réduire les encombrements et les interruptions de connexion.
Par défaut, la fréquence d'images de la vidéo est de 30 images par seconde, mais vous pouvez également la régler sur 15, 7 ou 1. La réduction de la fréquence d'images permet de réduire la bande passante requise. Les vidéos à faible résolution peuvent avoir une fréquence d'images plus faible sans que l'utilisateur perçoive une différence notable. Par conséquent, si vous utilisez une faible résolution, vous pouvez également envisager d'utiliser une faible fréquence d'images.
Dépannage
Suivez les conseils de cette section pour éviter les problèmes de connectivité lors de la publication. Pour des informations générales sur le dépannage, voir Débogage - Web.
Traitement des erreurs
Il existe des méthodes de rappel pour les deux Session.publish() et OT.initPublisher(). Nous recommandons de gérer les réponses d'erreur à ces deux méthodes. Comme nous l'avons déjà mentionné, il est préférable de séparer ces étapes et d'appeler OT.initPublisher() avant d'avoir commencé à vous connecter à votre session. Il est également plus facile de gérer les erreurs si vous n'appelez pas ces deux méthodes en même temps. En effet, les deux gestionnaires d'erreurs se déclenchent en cas de publication d'une erreur. Il est préférable d'attendre que OT.initPublisher() à compléter et Session.connect() et appeler ensuite Session.publish(). De cette façon, vous pouvez traiter tous les problèmes liés au matériel dans l'espace de travail. OT.initPublisher() et tous les problèmes liés au réseau dans le Session.publish() rappel.
var connected = false,
publisherInitialized = false;
var publisher = OT.initPublisher(function(err) {
if (err) {
// handle error
} else {
publisherInitialized = true;
publish();
}
});
var publish = function() {
if (connected && publisherInitialized) {
session.publish(publisher);
}
};
session.connect(token, function(err) {
if (err) {
// handle error
} else {
connected = true;
publish();
}
});
Accès refusé
Le plus grand nombre d'échecs de OT.initPublisher() sont dues au fait que l'utilisateur final refuse l'accès à la caméra et au microphone. Il est possible d'y remédier en écoutant le message accessDenied ou en écoutant une réponse d'erreur à la méthode OT.initPublisher() avec une valeur de code fixée à 1500 et un message avec la valeur "Publisher Access Denied :". Nous vous recommandons de traiter ce cas et d'envoyer un message à l'utilisateur pour lui indiquer qu'il doit réessayer de publier et autoriser l'accès à la caméra.
publisher.on({
'accessDenied': function() {
showMessage('Please allow access to the Camera and Microphone and try publishing again.');
}
});
Accès au dispositif
Une autre raison pour OT.initPublisher() L'échec d'OpenTok est dû au fait qu'il ne peut pas accéder à une caméra ou à un microphone. Cela peut se produire s'il n'y a pas de caméra ou de microphone attaché à la machine, s'il y a un problème avec le pilote de la caméra ou du microphone, ou si une autre application utilise la caméra ou le microphone (cela ne se produit que sous Windows). Vous pouvez essayer de minimiser l'occurrence de ces problèmes en utilisant notre composant de configuration du matériel ou en appelant la fonction OT.getDevices() directement. Cependant, vous devez également gérer toute erreur lors de l'appel de la méthode OT.initPublisher() car un problème peut toujours survenir. Par exemple, l'utilisateur peut avoir refusé l'accès à la caméra ou au microphone. Dans ce cas, le error.name est fixée à "OT_USER_MEDIA_ACCESS_DENIED":
publisher = OT.initPublisher('publisher', {}, function (err) {
if (err) {
if (err.name === 'OT_USER_MEDIA_ACCESS_DENIED') {
// Access denied can also be handled by the accessDenied event
showMessage('Please allow access to the Camera and Microphone and try publishing again.');
} else {
showMessage('Failed to get access to your camera or microphone. Please check that your webcam'
+ ' is connected and not being used by another application and try again.');
}
publisher.destroy();
publisher = null;
}
});
Erreurs de réseau
Les autres raisons des échecs de publication sont généralement dues à une défaillance du réseau. Nous les gérons dans le rappel à Session.publish(). Si l'utilisateur n'est pas connecté au réseau, la fonction de rappel reçoit un objet d'erreur avec la valeur name est définie comme étant la propriété "OT_NOT_CONNECTED". Si l'utilisateur dispose d'une connexion réseau très restrictive qui n'autorise pas les connexions WebRTC, l'éditeur ne parvient pas à se connecter et l'élément Publisher affiche une roue qui tourne. Cette erreur a une name est définie comme étant la propriété "OT_CREATE_PEER_CONNECTION_FAILED". Dans ce cas, nous vous recommandons d'envoyer un message à l'utilisateur pour lui indiquer qu'il n'a pas réussi à publier et qu'il doit vérifier sa connexion réseau. La gestion de ces erreurs se fait de la manière suivante :
session.publish(publisher, function(err) {
if (err) {
switch (err.name) {
case "OT_NOT_CONNECTED":
showMessage("Publishing your video failed. You are not connected to the internet.");
break;
case "OT_CREATE_PEER_CONNECTION_FAILED":
showMessage("Publishing your video failed. This could be due to a restrictive firewall.");
break;
default:
showMessage("An unknown error occurred while trying to publish your video. Please try again later.");
}
publisher.destroy();
publisher = null;
}
});
Perte de connectivité
Votre éditeur peut également perdre sa connexion après avoir réussi à se connecter. Le plus souvent, la Session perd également sa connexion, mais ce n'est pas toujours le cas. Vous pouvez gérer la déconnexion de l'éditeur en écoutant la commande streamDestroyed avec un reason à "networkDisconnected" comme suit :
publisher.on({
streamDestroyed: function (event) {
if (event.reason === 'networkDisconnected') {
showMessage('Your publisher lost its connection. Please check your internet connection and try publishing again.');
}
}
});
Mise en œuvre des tentatives de publication de session
Les échecs temporaires de publication constituent un phénomène connu et récurrent dans le SDK JS de la Video API, en particulier sur les navigateurs mobiles. Lorsque session.publish() En cas d'échec, le SDK renvoie une erreur via la fonction de rappel de son gestionnaire de fin d'exécution. Il est recommandé de mettre en place une logique de nouvelle tentative au niveau de l'application, en prévoyant un délai entre chaque tentative.
Remarque : Prise en charge intégrée des tentatives de reconnexion pour session.publish() Cela figure dans la feuille de route du SDK. En attendant sa sortie, vous devrez l'implémenter vous-même.
Comment session.publish() Œuvres
session.publish() peut être appelée de deux façons :
- Avec un éditeur pré-initialisé :
session.publish(publisher, callback)— tu appellesOT.initPublisher()Tout d'abord, transmettez ensuite l'instance d'éditeur obtenue àsession.publish(). Il s'agit du approche recommandée car cela permet de dissocier l'acquisition des médias de la création du flux, ce qui rend la gestion des erreurs plus claire. - Sans instance d'éditeur :
session.publish(targetElement, options, callback)— le SDK appelle en interneOT.initPublisher()pour vous. Dans ce cas, les erreurs d’acquisition de médias et les erreurs de création de flux apparaissent toutes deux via le mêmesession.publish()rappel.
Bonnes pratiques : Split OT.initPublisher() et session.publish() en étapes distinctes. Cela vous permet de gérer les erreurs matérielles ou liées aux supports dans le OT.initPublisher() erreurs de rappel et d' réseau/de signalisation dans le session.publish() callback — ce qui simplifie considérablement la logique de réessai et la rend plus ciblée.
// Recommended: split initialization from publishing
let publisherReady = false;
let sessionConnected = false;
const publisher = OT.initPublisher('publisher-container', publisherOptions, (err) => {
if (err) {
handleInitPublisherError(err); // hardware/media errors — see OT.initPublisher() errors below
return;
}
publisherReady = true;
maybePublish();
});
session.connect(token, (err) => {
if (err) { /* handle connection error */ return; }
sessionConnected = true;
maybePublish();
});
function maybePublish() {
if (sessionConnected && publisherReady) {
publishWithRetry(session, publisher);
}
}
Pourquoi les échecs de publication se produisent-ils ?
Les causes principales les plus courantes des échecs de publication temporaires sont les suivantes :
- Dépassement du délai d'attente de StreamCreateRequest (erreur 1500) : L'éditeur n'a pas réussi à finaliser la création du flux dans un délai raisonnable — ce qui est généralement dû à des retards réseau lors de la négociation ICE/SDP.
mediaStoppedévénements survenant au cours du processus de publication, où l'accès aux périphériques multimédias peut être interrompu.- Réutilisation d'un objet « Publisher » sans nettoyage approprié — réutiliser une instance d'éditeur initialisée avec des contraintes différentes sans appeler
unpublishet la réinitialisation. OT_NOT_CONNECTED— tentative de publication avant que la session ne soit entièrement établie.OT_PERMISSION_DENIED— Le jeton ne dispose pas du rôle « publish » (erreur irréversible).
Erreurs provenant de OT.initPublisher()
Lorsque vous pré-initialisez un éditeur avec OT.initPublisher(), toutes les erreurs matérielles et d'acquisition de données multimédia sont transmises à son gestionnaire de fin d'exécution — avant session.publish() est appelée. Traitez-les dans cette fonction de rappel à l'aide des actions spécifiques à chaque type d'erreur décrites ci-dessous : certaines nécessitent une intervention de l'utilisateur ou une correction du code, tandis que les erreurs temporaires liées aux médias peuvent être résolues en réinitialisant l'éditeur.
Remarque : Si vous appelez session.publish() Sans éditeur pré-initialisé, ces mêmes erreurs apparaîtront via le session.publish() utiliser plutôt une fonction de rappel.
error.name |
Description | Action recommandée |
|---|---|---|
OT_HARDWARE_UNAVAILABLE |
Le matériel existe, mais n'a pas pu être accédé (par exemple, car il est utilisé par une autre application). | Demander à l'utilisateur de fermer les autres applications en cours d'exécution sur l'appareil, puis appeler OT.initPublisher() encore une fois. |
OT_INVALID_PARAMETER |
Un ou plusieurs paramètres transmis à OT.initPublisher() étaient invalides. |
Corriger l'objet « options » transmis à OT.initPublisher(). |
OT_MEDIA_ENDED |
Les ended événement déclenché sur l'élément vidéo lors de l'initialisation. |
Réinitialisez l'éditeur. |
OT_MEDIA_ERR_ABORTED |
La récupération du flux pour l'élément vidéo a été interrompue. | Réinitialisez l'éditeur après un court délai. |
OT_MEDIA_ERR_DECODE |
Une erreur de décodage s'est produite lors de la lecture du flux dans l'élément vidéo. | Réinitialisez l'éditeur après un court délai. |
OT_MEDIA_ERR_NETWORK |
Une erreur réseau a entraîné l'interruption du téléchargement du flux. | Réinitialisez l'éditeur après un court délai. |
OT_MEDIA_ERR_SRC_NOT_SUPPORTED |
Le flux a été identifié comme non compatible avec la lecture. | Vérifiez la configuration de la source vidéo/audio du diffuseur, puis réinitialisez-la. |
OT_NOT_SUPPORTED |
Un élément de la requête multimédia de l'utilisateur n'est pas pris en charge par le navigateur. | Informer l'utilisateur et ne pas réessayer. |
OT_NO_DEVICES_FOUND |
Aucun périphérique d'entrée audio ou vidéo n'a été détecté. | Demander à l'utilisateur de connecter un périphérique avant de réessayer. |
OT_NO_VALID_CONSTRAINTS |
La vidéo et l'audio étaient tous deux désactivés — l'un des deux doit être activé. | Garantir publishAudio ou publishVideo est true dans les options de l'éditeur. |
OT_PROXY_URL_ALREADY_SET_ERROR |
Les proxyUrl a déjà été défini. Le redéfinir n'aura aucun effet. |
Définissez l'URL du proxy une seule fois, avant d'initialiser tout objet Session ou Publisher. |
OT_REQUESTED_DEVICE_PERMISSION_DENIED |
Le périphérique audio demandé ne dispose pas des autorisations nécessaires pour être utilisé. | Demander à l'utilisateur d'accorder les autorisations nécessaires à l'appareil. |
OT_USER_MEDIA_ACCESS_DENIED |
L'utilisateur a refusé l'accès à la caméra, au microphone ou à l'écran. | Demander à l'utilisateur d'autoriser l'accès dans les paramètres du navigateur ; ne pas réessayer automatiquement. |
OT_SCREEN_SHARING_NOT_SUPPORTED |
Le partage d'écran n'est pas pris en charge par le navigateur utilisé actuellement. | Informer l'utilisateur et ne pas réessayer. |
OT_UNABLE_TO_CAPTURE_SCREEN |
Le partage d'écran a été demandé, mais cette fonctionnalité n'est pas prise en charge (par exemple : videoSource fixé à "screen", "application"ou "window"). |
Appeler OT.checkScreenSharingCapability() avant d'initialiser un éditeur de partage d'écran. |
OT_SCREEN_SHARING_EXTENSION_NOT_REGISTERED |
Le partage d'écran nécessite une extension de navigateur, mais aucune n'a été enregistrée. | Enregistrez l'extension avant de passer l'appel OT.initPublisher(). |
OT_SCREEN_SHARING_EXTENSION_NOT_INSTALLED |
Le partage d'écran nécessite une extension de navigateur, mais celle-ci n'est pas installée. | Invitez l'utilisateur à installer l'extension requise. |
const publisher = OT.initPublisher('publisher-container', publisherOptions, (err) => {
if (!err) {
publisherReady = true;
maybePublish();
return;
}
// Hardware/media errors — handle before session.publish() is called
switch (err.name) {
case 'OT_REQUESTED_DEVICE_PERMISSION_DENIED':
showMessage('Please allow access to your camera and microphone and try again.');
break;
case 'OT_HARDWARE_UNAVAILABLE':
case 'OT_NO_DEVICES_FOUND':
showMessage('Could not access your camera or microphone. Please check your devices.');
break;
case 'OT_SCREEN_SHARING_NOT_SUPPORTED':
case 'OT_UNABLE_TO_CAPTURE_SCREEN':
case 'OT_SCREEN_SHARING_EXTENSION_NOT_REGISTERED':
case 'OT_SCREEN_SHARING_EXTENSION_NOT_INSTALLED':
showMessage('Screen sharing is not available. Please check your browser settings.');
break;
default:
showMessage('Could not initialize the publisher. Please try again.');
}
publisher.destroy();
});
Erreurs récupérables et non récupérables provenant de session.publish()
Pas tous session.publish() les erreurs ne se valent pas toutes. Avant de mettre en place une logique de réessai, il est essentiel de classer correctement les erreurs : tenter un réessai en cas d’erreur irrémédiable fait perdre du temps, nuit à l’expérience utilisateur et peut masquer de véritables défaillances qui nécessitent une réponse différente.
Remarque : Code d'erreur 1500 est obsolète en tant que mécanisme de classification. Utilisez toujours le error.name propriété permettant d'identifier les erreurs par programmation, car elle correspond à un scénario d'échec spécifique.
Remarque : Quand session.publish() s'appelle sans un éditeur pré-initialisé, des erreurs d'acquisition de médias provenant de OT.initPublisher() (énumérés ci-dessus) peuvent également se manifester par le biais de la session.publish() rappel. Dans ce cas, considérez-les comme ne pouvant faire l'objet d'aucune nouvelle tentative et appliquez la même procédure que celle décrite ci-dessus.
Erreurs irrémédiables — Ne pas réessayer
Ces erreurs sont dues à des erreurs de programmation, à des contraintes strictes en matière d'autorisations ou à un contexte d'appel non valide. Une nouvelle tentative ne permettra pas de les résoudre. Il convient plutôt d'afficher un message clair à l'utilisateur ou de corriger la logique de l'application.
error.name |
Description | Action recommandée |
|---|---|---|
OT_NOT_CONNECTED |
session.publish() a été appelée avant que la session ne soit établie. |
Garantir session.connect() a été menée à bien avant la publication. |
OT_PERMISSION_DENIED |
Le rôle de ce jeton ne permet pas la publication (il doit être publisher ou moderator). |
Indiquez à l'utilisateur qu'il ne dispose pas des autorisations de publication. Ne réessayez pas : générez un jeton avec le rôle approprié. |
OT_INVALID_PARAMETER |
L'éditeur fourni n'est pas valide, a déjà été publié ou est déjà associé à une autre session. | Corrigez la logique de l'application : appelez session.unpublish(publisher) avant de republier, ou de créer un nouvel éditeur. |
OT_USER_MEDIA_ACCESS_DENIED |
L'utilisateur a refusé l'accès à la caméra ou au microphone (ou à l'écran, dans le cas des diffusions avec partage d'écran). | Demandez à l'utilisateur d'autoriser l'accès à l'appareil dans les paramètres de son navigateur, puis réessayez. Ne réessayez pas automatiquement. |
OT_CHROME_MICROPHONE_ACQUISITION_ERROR |
Le navigateur n'a pas pu accéder au microphone en raison d'un bug connu. L'utilisateur doit redémarrer le navigateur et recharger la page pour résoudre ce problème. | Informer l'utilisateur et ne pas réessayer. |
OT_SCREEN_SHARING_NOT_SUPPORTED |
Le partage d'écran n'est pas pris en charge par le navigateur utilisé actuellement. | Informer l'utilisateur et ne pas réessayer. |
OT_SCREEN_SHARING_EXTENSION_NOT_REGISTERED |
Le partage d'écran nécessite une extension de navigateur, mais aucune n'a été enregistrée. | Enregistrez l'extension avant de tenter de publier un flux de partage d'écran. |
OT_SCREEN_SHARING_EXTENSION_NOT_INSTALLED |
Le partage d'écran nécessite une extension de navigateur, mais celle-ci n'est pas installée. | Invitez l'utilisateur à installer l'extension requise. |
OT_CONSTRAINTS_NOT_SATISFIED |
Le navigateur n'a pas pu respecter les contraintes multimédias demandées (résolution, fréquence d'images, appareil). | Modifiez les contraintes de l'éditeur et réinitialisez-le. |
OT_NO_VALID_CONSTRAINTS |
La vidéo et l'audio étaient tous deux désactivés — l'un des deux doit être activé. | Garantir publishAudio ou publishVideo est true avant d'appeler session.publish(). |
OT_NOT_SUPPORTED |
Un élément de la requête multimédia de l'utilisateur n'est pas pris en charge par le navigateur. | Informer l'utilisateur et ne pas réessayer. |
OT_STREAM_CREATE_FAILED |
L'utilisateur a tenté de publier dans une session avec chiffrement de bout en bout (E2EE) activé sans spécifier de clé de chiffrement ; ou bien le flux n'a pas pu être créé dans le modèle serveur. | Pour les sessions E2EE, assurez-vous qu'un secret de chiffrement est défini via session.setEncryptionSecret() avant la publication. |
OT_INVALID_AUDIO_OUTPUT_SOURCE |
L'identifiant du périphérique de sortie audio fourni n'est pas valide. | Verify que l'identifiant du périphérique correspond bien à un périphérique de sortie audio valide avant de réessayer. |
OT_UNABLE_TO_CAPTURE_MEDIA |
Impossible de capturer le contenu multimédia — une erreur inconnue s'est produite. | Informer l'utilisateur et lui demander de vérifier la disponibilité de l'appareil. |
Erreurs récupérables — On peut réessayer en toute sécurité
Ces erreurs sont généralement dues à des perturbations passagères du réseau, à des délais d'attente de signalisation ou à une indisponibilité temporaire de la plateforme. Elles constituent la cible principale de la logique de réessai.
error.name |
Description | Action recommandée |
|---|---|---|
OT_TIMEOUT (code 1500) |
session.publish() délai d'attente écoulé — le StreamCreateRequest n'a pas été achevée à temps. Cela est le plus souvent dû à des retards dans la négociation ICE/SDP ou mediaStopped événements. |
Réessayer avec un délai d'attente exponentiel (jusqu'à 3 tentatives). Réutiliser la même instance d'éditeur si celle-ci n'a pas été détruite. |
OT_ICE_WORKFLOW_FAILED |
Échec de la négociation ICE : la connexion entre pairs n'a pas pu être établie. Ce phénomène est fréquent sur les réseaux restrictifs. | Réessayez. Si le problème persiste malgré toutes ces tentatives, informez l'utilisateur d'un éventuel problème lié au réseau ou au pare-feu. |
OT_CREATE_PEER_CONNECTION_FAILED |
La connexion entre pairs WebRTC n'a pas pu être établie. Cela peut être dû à un pare-feu trop restrictif ou à un problème temporaire lié à la plateforme. | Réessayez. Si le problème persiste, affichez un message invitant l'utilisateur à vérifier sa connexion réseau. |
OT_MEDIA_ERR_ABORTED / OT_MEDIA_ERR_NETWORK |
L'acquisition du fichier multimédia a été annulée ou interrompue en raison d'une erreur réseau. | Réessayez après un court délai. |
OT_MEDIA_ERR_DECODE |
Une erreur de décodage s'est produite lors de la lecture du flux dans l'élément vidéo. | Réessayez après un court délai. Si le problème persiste, il se peut que le format du support ne soit pas compatible. |
OT_MEDIA_ERR_SRC_NOT_SUPPORTED |
Le flux a été identifié comme non compatible avec la lecture. | Réessayez une fois. Si le problème persiste, vérifiez la configuration des sources vidéo/audio de l'éditeur. |
OT_SET_REMOTE_DESCRIPTION_FAILED |
La connexion WebRTC a échoué pendant setRemoteDescription. Il s'agit généralement d'un problème de signalisation temporaire. |
Réessayez en respectant un délai d'attente. Si le problème persiste après toutes les tentatives, informez l'utilisateur d'un éventuel problème de réseau. |
OT_UNEXPECTED_SERVER_RESPONSE |
Une erreur inattendue s'est produite côté serveur. | Réessayez une fois après un court délai. Si le problème persiste, consignez l'erreur et informez l'utilisateur. |
Erreurs nécessitant une action différente (autre qu'une simple nouvelle tentative)
Certaines erreurs ne peuvent être ni simplement réessayées ni définitivement interrompues : elles nécessitent une action corrective spécifique avant toute nouvelle tentative.
error.name |
Description | Action recommandée |
|---|---|---|
OT_HARDWARE_UNAVAILABLE |
La caméra ou le microphone n'est pas disponible (par exemple, il est utilisé par une autre application ou n'est pas connecté). | Demandez à l'utilisateur de fermer les autres applications en cours d'exécution sur l'appareil, puis réinitialisez l'éditeur à l'aide de OT.initPublisher() avant de réessayer. |
OT_NO_DEVICES_FOUND |
Aucun périphérique d'entrée audio ou vidéo n'a été détecté. | Demander à l'utilisateur de connecter un appareil. Ne pas réessayer tant que l'utilisateur n'a pas confirmé qu'un appareil est disponible. |
Synthèse : modèle de nouvelle tentative recommandé avec classification des erreurs
async function publishWithRetry(session, publisher, attempt = 1) {
const MAX_RETRIES = 3;
const RETRY_DELAY_MS = 2000;
const error = await new Promise((resolve) => {
session.publish(publisher, resolve);
});
if (!error) {
console.log('Publishing started successfully.');
return;
}
// Non-recoverable: programmer error or hard permission constraint
const nonRetryable = [
'OT_NOT_CONNECTED',
'OT_PERMISSION_DENIED',
'OT_INVALID_PARAMETER',
'OT_USER_MEDIA_ACCESS_DENIED',
'OT_CHROME_MICROPHONE_ACQUISITION_ERROR',
'OT_SCREEN_SHARING_NOT_SUPPORTED',
'OT_SCREEN_SHARING_EXTENSION_NOT_REGISTERED',
'OT_SCREEN_SHARING_EXTENSION_NOT_INSTALLED',
'OT_CONSTRAINTS_NOT_SATISFIED',
'OT_NO_VALID_CONSTRAINTS',
'OT_NOT_SUPPORTED',
'OT_STREAM_CREATE_FAILED',
'OT_INVALID_AUDIO_OUTPUT_SOURCE',
'OT_UNABLE_TO_CAPTURE_MEDIA',
];
// Requires corrective action before retrying
const requiresAction = [
'OT_HARDWARE_UNAVAILABLE',
'OT_NO_DEVICES_FOUND',
];
if (nonRetryable.includes(error.name)) {
console.error('Non-retryable error — user action or code fix required:', error.name);
handleNonRecoverableError(error);
return;
}
if (requiresAction.includes(error.name)) {
console.warn('Device error — prompting user before retrying:', error.name);
handleDeviceError(error);
return;
}
// Recoverable: retry with backoff
if (attempt < MAX_RETRIES) {
console.warn(`Publish attempt ${attempt} failed (${error.name}), retrying...`);
await delay(RETRY_DELAY_MS * attempt);
await publishWithRetry(session, publisher, attempt + 1);
} else {
console.error('All publish attempts failed. Disconnecting user.');
handlePublishFailure(session);
}
}
function handleNonRecoverableError(error) {
// Surface a meaningful message to the user based on error.name
// e.g. for OT_USER_MEDIA_ACCESS_DENIED: "Please allow camera/mic access"
}
function handleDeviceError(error) {
// Prompt the user to check their device, then allow them to retry manually
}
function handlePublishFailure(session) {
session.disconnect();
}
Utilisation :
const publisher = OT.initPublisher('publisher-container', publisherOptions);
// Wait for session to be connected before publishing
session.connect(token, (err) => {
if (err) { /* handle connection error */ return; }
publishWithRetry(session, publisher);
});
Important : nettoyage de l'éditeur avant de réessayer
Dans la plupart des scénarios de défaillance — notamment OT_TIMEOUT / OT_ICE_WORKFLOW_FAILED — l'instance de l'éditeur peut être réutilisé directement pour le prochain session.publish() appel. Vous n'avez pas besoin de le réinitialiser.
Lorsqu'une tentative de publication échoue, le SDK interrompt le flux qu'il tentait de créer et génère un streamDestroyed événement sur l'éditeur avec reason: "reset". Il s'agit d'un nettoyage prévu qui pas vous obligent à réinitialiser l'éditeur — vous pouvez réessayer avec la même instance. Notez que "reset" Il s'agit d'un motif général indiquant que « le flux de l'éditeur a été interrompu » (il est également généré lorsque vous appelez publisher.destroy()), considérez-le donc comme un signal de nettoyage plutôt que comme un indicateur spécifique d'échec de publication ; utilisez la error.name de la session.publish() fonction de rappel permettant de décider s'il faut réessayer.
Le SDK permet de pas réessayer automatiquement session.publish() en votre nom — la logique de nouvelle tentative doit être mise en œuvre au niveau de l'application, comme indiqué ci-dessus.
Le seul cas où vous devez réinitialiser l'éditeur avec OT.initPublisher() Avant de réessayer, c'est lorsque l'éditeur lui-même destroyed L'événement se déclenche. Cet événement est définitif et indique que l'objet émetteur lui-même n'est plus utilisable.
publisher.on('destroyed', () => {
// Publisher object is no longer usable — reinitialize before retrying
publisher = OT.initPublisher('publisher-container', publisherOptions);
});
// A streamDestroyed event with reason 'reset' is emitted by the SDK when it tears
// down the stream (during a failed publish attempt, or when you call publisher.destroy()).
// A 'reset' during a failed publish does NOT require reinitializing the publisher.
publisher.on('streamDestroyed', (event) => {
if (event.reason === 'reset') {
// Expected cleanup — reuse the same publisher instance
return;
}
// Handle other streamDestroyed reasons as appropriate for your application
});
Ce qu'il ne faut PAS faire
- Faire pas appel
OT.initPublisher()deux fois sur le même objet « publisher » avec des contraintes différentes sans avoir effectué de nettoyage au préalable (session.unpublish()→ attendrestreamDestroyed→ puis réinitialiser). - Faire pas réessayer le
OT_PERMISSION_DENIED(l'utilisateur a refusé l'accès à la caméra/au micro) — cela nécessite une intervention de l'utilisateur, et non une nouvelle tentative. - Faire pas réessayer le
OT_NOT_CONNECTED— assurez-vous que la session est bien connectée avant de publier. - Faire pas réessayer indéfiniment — limiter à 3 tentatives et gérer l'échec de manière appropriée.
Gestion de la mediaStopped Événement
La lecture du fichier multimédia peut être interrompue en cours de publication. Surveillez cet événement et considérez-le comme un déclencheur pour relancer la publication :
publisher.on('mediaStopped', async () => {
console.warn('Media stopped during publish — retrying...');
// Unpublish if already publishing, then retry
try { session.unpublish(publisher); } catch (e) { /* ignore */ }
await delay(2000);
publishWithRetry(session, publisher);
});
Résumé des paramètres recommandés
| Paramètres | Valeur recommandée | Notes |
|---|---|---|
| Nombre maximal de tentatives | 3 | Trouve le juste équilibre entre la résilience et le temps d'attente des utilisateurs |
| Délai avant nouvelle tentative | 2 s × essai (2 s, 4 s, 6 s) | Cela laisse à la plateforme le temps de se rétablir |
| En cas d'échec de toutes les tentatives de réessai | Déconnecter l'utilisateur | Évite l'état de « participant fantôme » |
| Erreurs ne pouvant pas faire l'objet d'une nouvelle tentative | OT_NOT_CONNECTED, OT_PERMISSION_DENIED |
Échouez rapidement sur ces points |
Résolution des problèmes liés à la capture audio : audioAcquisitionProblem et audioAcquisitionProblemResolved
Au-delà des tentatives de publication, il existe une autre catégorie de problèmes audio pouvant affecter un éditeur actif : le périphérique audio du client peut ne pas parvenir à transmettre les données audio, même après une publication réussie. Le SDK JS de la Video API propose deux événements spécialement conçus pour ce cas de figure.
Causes courantes
Les audioAcquisitionProblem Cet événement est déclenché lorsque le SDK détecte — via les statistiques de l'éditeur — que la piste audio a cessé d'envoyer des octets à la connexion entre pairs, même si getUserMedia L'opération a abouti et l'éditeur semble actif. Les causes principales les plus courantes sont les suivantes :
- Appareil audio Bluetooth connecté ou déconnecté en cours de session : Lorsqu'un utilisateur branche ou débranche des écouteurs, ou connecte un casque Bluetooth (par exemple, des AirPods) au cours d'une session active, le système d'exploitation peut changer de périphérique audio par défaut. Il peut arriver que le pipeline audio du navigateur ne parvienne pas à reconnecter le microphone sur le nouveau périphérique, ce qui entraîne l'absence totale d'envoi d'octets audio.
- Changement de périphérique audio au démarrage de la session : Le fait de changer d'entrée audio très tôt dans la session — dans les 1 à 2 premières secondes suivant la publication — est particulièrement susceptible de déclencher ce problème.
- Piste audio interrompue par le navigateur ou le système d'exploitation (
trackEndedEvent) : Le navigateur peut interrompre la piste audio sous-jacente indépendamment de toute action de l'utilisateur. Le SDK détecte cela via untrack.endedévénement et soulèveaudioAcquisitionProblemavecmethod: trackEndedEvent. - Détection basée sur les statistiques (absence de flux d'octets audio) : Une fois que la connexion entre pairs est établie, le SDK interroge les statistiques de l'éditeur toutes les quelques secondes environ. Si la piste audio sortante
bytesSentn'augmente pas d'un sondage à l'autre,audioAcquisitionProblemest soulevée (avecmethod: getStats). LorsquebytesSentcommence à augmenter à nouveau,audioAcquisitionProblemResolvedest soulevée.
Remarque : Cet événement ne signifie pas toujours une défaillance irrémédiable. Dans certaines sessions, le son revient tout seul (et audioAcquisitionProblemResolved est déclenché) ; dans d'autres cas, le flux audio ne se rétablit jamais et les abonnés en aval peuvent finir par dépasser le délai d'attente.
Les événements
Ces événements sont émis sur l'instance de l'éditeur :
audioAcquisitionProblem— déclenché lorsque le SDK détecte que l'éditeur a cessé d'envoyer du contenu audio (d'après les statistiques de l'éditeur), ou lorsque la piste audio sous-jacente déclenche unendedévénement. Cela ne signifie pas nécessairement que la diffusion va échouer, mais cela indique que la capture audio a été interrompue.audioAcquisitionProblemResolved— déclenché lorsque la transmission audio est rétablie après uneaudioAcquisitionProblem. Si cet événement se produit, aucune mesure corrective n'est nécessaire.
Remarque : Ces événements ont actuellement lieu ne fait pas partie de l'API publique documentée/définie par écrit (ils ne sont pas déclarés dans les définitions TypeScript du SDK). Considérez-les comme des signaux fournis « au mieux » susceptibles de changer d’une version à l’autre, et vérifiez leur disponibilité par rapport à la version de votre SDK avant de vous y fier en production. Lorsqu’ils sont émis par l’éditeur, ils incluent un method propriété indiquant comment le problème a été détecté ('getStats' ou 'trackEndedEvent').
Remarque : Les vérifications d'acquisition audio s'appuient sur les statistiques fournies par les éditeurs ; il peut donc y avoir un léger décalage entre le moment où l'audio est effectivement interrompu et celui où l'événement est déclenché.
Modèle de récupération recommandé
Lancer un minuteur court dès la réception audioAcquisitionProblem. Si audioAcquisitionProblemResolved Si le problème disparaît avant la fin du délai, cela signifie que le son s'est rétabli de lui-même et qu'aucune intervention n'est nécessaire. Si le délai expire sans que le problème ne soit résolu, changez de source audio pour rétablir le son.
publisher.on('audioAcquisitionProblem', () => {
// Start a 3-second timer
const timeout = setTimeout(() => {
// Problem not resolved — attempt recovery by switching audio source
publisher.setAudioSource(newDeviceId);
}, 3000);
publisher.on('audioAcquisitionProblemResolved', () => {
// Audio recovered — clear the timer, no action needed
clearTimeout(timeout);
});
});
Éléments clés à prendre en compte
- Ce n'est pas un indicateur d'échec certain :
audioAcquisitionProblemCela n'entraîne pas systématiquement l'échec de l'abonnement. Considérez-le comme un signal précoce permettant de surveiller la situation et, le cas échéant, d'intervenir, et non comme un échec définitif. - Suivre les statistiques audio de l'éditeur : Après avoir reçu
audioAcquisitionProblem, vous pouvez également suivre les statistiques audio de l'éditeur (par exemple, viapublisher.getStats()) afin de vérifier si la transmission audio a bien cessé avant d'intervenir. - Mesures de rétablissement : Appel
publisher.setAudioSource(newDeviceId)Il s'agit du principal mécanisme de récupération. Cela permet de changer de périphérique d'entrée audio sans avoir à passer par un cycle complet de désactivation puis de réactivation. - Lien avec les délais d'expiration des abonnements : Si le flux audio n'est pas rétabli et que l'éditeur continue de ne pas envoyer de paquets audio, les abonnés risquent à terme de se retrouver face à
OT_TIMEOUT(1501). Gestion proactive deaudioAcquisitionProblempeut permettre d’éviter cette défaillance en aval.