Streams abonnieren — Web

Sobald Sie mit einer Sitzung verbunden, können Sie Streams in der Sitzung abonnieren. Wenn Sie einen Stream abonnieren, wird dessen Videostream auf der Client-Seite angezeigt und der Ton wiedergegeben.

Dieses Thema umfasst die folgenden Abschnitte:

Erkennen, wann Streams in einer Sitzung erstellt werden

Das Session-Objekt sendet eine streamCreated Ereignis, wenn ein neuer Stream (ein anderer als der eigene) in einer Sitzung erstellt wird. Ein Stream wird erstellt, wenn ein Client veröffentlicht einen Stream zur Sitzung. Die streamCreated Ereignis wird auch für jeden vorhandenen Stream in der Sitzung ausgelöst, wenn Sie zum ersten Mal eine Verbindung herstellen. Dieses Ereignis wird durch das StreamEvent definiert, das über eine stream Eigenschaft, die den erstellten Stream darstellt:

session.on("streamCreated", function (event) {
   console.log("New stream in the session: " + event.stream.streamId);
});
// Replace with a valid token:
session.connect(token);

Sie können einen beliebigen Stream abonnieren. Siehe den nächsten Abschnitt.

Einen Stream abonnieren

Um einen Stream zu abonnieren, übergeben Sie das Stream-Objekt an die subscribe Methode des Session-Objekts:

session.subscribe(stream, replacementElementId);

Die subscribe() Methode nimmt die folgenden Parameter entgegen:

  • stream-Das Stream-Objekt.

  • targetElement- (Optional) Legt das DOM-Element fest, das durch das Abonnentenvideo ersetzt wird.

  • properties— (Optional) Eine Reihe von Eigenschaften, mit denen das Erscheinungsbild der Abonnentenansicht auf der HTML-Seite angepasst werden kann (siehe Anpassen der Benutzeroberfläche) und wählen Sie aus, ob Sie Audio- und Videoinhalte abonnieren möchten (siehe Einstellen von Audio und Video).

  • completionHandler- (Optional) Eine Funktion, die asynchron aufgerufen wird, wenn der Aufruf der subscribe() Methode erfolgreich abgeschlossen wird oder fehlschlägt. Wenn der Aufruf der Methode subscribe() Methode fehlschlägt, wird dem Completion-Handler ein Fehlerobjekt übergeben. Dieses Objekt hat eine code und message Eigenschaften, die den Fehler beschreiben.

Der folgende Code abonniert alle Streams, außer denen, die von Ihrem Client veröffentlicht werden:

session.on("streamCreated", function(event) {
    session.subscribe(event.stream);
});

// Replace with your API key and token:
session.connect(token, function (error) {
    if(error) {
        // failed to connect
    }
});

Die insertMode Eigenschaft der properties Parameter des Session.subscribe() Methode gibt an, wie das Publisher-Objekt in das HTML-DOM eingefügt wird, und zwar in Bezug auf die targetElement Parameter. Sie können diesen Parameter auf einen der folgenden Werte einstellen:

  • "replace" - Das Subscriber-Objekt ersetzt den Inhalt des targetElements. Dies ist der Standard.
  • "after" - Das Subscriber-Objekt ist ein neues Element, das nach dem targetElement im HTML-DOM eingefügt wird. (Sowohl das Subscriber- als auch das targetElement haben dasselbe übergeordnete Element).
  • "before" - Das Subscriber-Objekt ist ein neues Element, das vor dem targetElement im HTML-DOM eingefügt wird. (Sowohl das Subscriber- als auch das targetElement haben dasselbe übergeordnete Element).
  • "append" - Das Subscriber-Objekt ist ein neues Element, das als untergeordnetes Element des targetElements hinzugefügt wird. Wenn es weitere untergeordnete Elemente gibt, wird der Publisher als letztes untergeordnetes Element des targetElements angefügt.

Der folgende Code fügt zum Beispiel ein neues Subscriber-Objekt als untergeordnetes Objekt einer subscriberContainer DOM-Element:

session.on('streamCreated', function(event) {
  var subscriberProperties = {insertMode: 'append'};
  var subscriber = session.subscribe(event.stream,
    'subscriberContainer',
    subscriberProperties,
    function (error) {
      if (error) {
        console.log(error);
      } else {
        console.log('Subscriber added.');
      }
  });
});

Das Subscriber-Objekt hat eine element die auf das HTML-DOM-Element gesetzt wird, das sie enthält.

Wenn Sie die Standard-Benutzeroberfläche nicht verwenden möchten, rufen Sie die Video Element für den Abonnenten (siehe dieses Thema). Du kannst auch deine eigene verwenden Video Element, um das Video des Abonnenten anzuzeigen, und verwenden Sie das MediaStream-Objekt des Abonnenten als Medienquelle dafür Video Element (siehe dieses Thema).

Abmelden von einem Stream

Um die Wiedergabe eines Streams zu beenden, den Sie abonniert haben, übergeben Sie das Subscriber-Objekt an die unsubscribe() Methode des Session-Objekts:

session.unsubscribe(subscriber);

Das Subscriber-Objekt wird zerstört, und die Stream-Anzeige wird aus dem HTML-DOM entfernt.

Erkennen, wann Streams eine Sitzung verlassen

Wenn ein Stream, der nicht Ihr eigener ist, eine Sitzung verlässt, sendet das Sitzungsobjekt eine streamDestroyed Veranstaltung:

session.on("streamDestroyed", function (event) {
  console.log("Stream stopped. Reason: " + event.reason);
});

Wenn ein Stream, den Sie veröffentlichen, eine Sitzung verlässt, sendet das Publisher-Objekt eine streamDestroyed Veranstaltung:

var publisher = OT.initPublisher();
publisher.on("streamDestroyed", function (event) {
  console.log("Stream stopped. Reason: " + event.reason);
});

Die streamDestroyed Ereignis wird durch die Klasse StreamEvent definiert. Das Ereignis enthält eine reason die angibt, warum der Stream beendet wurde. Diese Gründe umfassen "clientDisconnected", "forceDisconnected", "forceUnpublished", oder "networkDisconnected". Für Einzelheiten siehe StreamEvent.

Standardmäßig, wenn ein streamDestroyed Ereignis für einen Stream ausgelöst wird, den Sie abonniert haben, werden die entsprechenden Abonnenten-Objekte (es kann mehr als eines geben) zerstört und aus dem HTML-DOM entfernt. Sie können dieses Standardverhalten verhindern, indem Sie die Funktion preventDefault() Methode des StreamEvent-Objekts:

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.
});

Beachten Sie, dass die getSubscribersForStream() Methode eines Session-Objekts gibt alle Subscriber-Objekte für einen Stream zurück.

Wenn Sie verwandte DOM-Elemente anpassen möchten, bevor Sie den Abonnenten selbst löschen, können Sie das Standardverhalten verhindern und den Abonnenten beibehalten. Sie können dann das Subscriber-Objekt (und sein DOM-Element) löschen, indem Sie die Funktion destroy() Methode des Subscriber-Objekts.

Ein Subscriber-Objekt sendet eine destroyed Ereignis, wenn das Objekt aus dem HTML-DOM entfernt wurde. Als Reaktion auf dieses Ereignis können Sie DOM-Elemente anpassen (oder entfernen), die sich auf den entfernten Teilnehmer beziehen.

Automatische Wiedereinschaltung

Wenn ein Client die Verbindung zu einem abonnierten Stream verliert (beispielsweise aufgrund einer Unterbrechung der Netzwerkverbindung bei einem der beiden Clients), versucht er, die Verbindung zum Stream automatisch wiederherzustellen. Wenn die Verbindung zum Stream unterbrochen wird und der Client versucht, die Verbindung wiederherzustellen, löst das „Subscriber“-Objekt ein disconnected Ereignis. Wenn der Stream wiederhergestellt ist, sendet das Subscriber-Objekt ein connected Ereignis. Wenn der Client den Stream nicht wiederherstellen kann, sendet das Subscriber-Objekt ein destroyed Veranstaltung.

Als Reaktion auf diese Ereignisse kann Ihre Anwendung (optional) Benachrichtigungen auf der Benutzeroberfläche anzeigen, die den Zustand der vorübergehenden Unterbrechung, der Wiederverbindung und der Zerstörung angeben:

subscriber.on(
  disconnected: function() {
    // Display a user interface notification.
  },
  connected: function() {
    // Adjust user interface.
  },
  destroyed: function() {
    // Adjust user interface.
  }
);

Einschränkung der Bildrate eines abonnierten Streams

Sie können auch die Bildrate des Videostreams eines Abonnenten begrenzen. Um die Bildrate eines Abonnenten zu begrenzen, rufen Sie die restrictFrameRate() Methode des Subscriber-Objekts, wobei true:

subscriber.restrictFrameRate(true);

Einreichen false und die Bildrate des Videostreams ist nicht begrenzt:

subscriber.restrictFrameRate(false);

Wenn die Bildrate eingeschränkt ist, wird das Videobild des Teilnehmers einmal oder weniger pro Sekunde aktualisiert.

Diese Funktion ist nur in Sitzungen verfügbar, die den OpenTok Media Router verwenden (Sitzungen mit dem Medienbetrieb (auf „routed“ gesetzt), jedoch nicht in Sitzungen, bei denen der Medienmodus auf „relayed“ gesetzt ist. In „relayed“-Sitzungen hat der Aufruf dieser Methode keine Auswirkung.

Die Begrenzung der Teilnehmerbildrate hat folgende Vorteile:

  • Es reduziert die CPU-Nutzung.
  • Dadurch wird die von der Anwendung verbrauchte Netzwerkbandbreite reduziert.
  • Damit können Sie mehrere Streams gleichzeitig abonnieren.

Die Reduzierung der Bildrate eines Teilnehmers hat keine Auswirkungen auf die Bildrate des Videos in anderen Clients.

Erkennen, wann der Ton eines Teilnehmers gesperrt oder freigegeben ist

Einige Browser blockieren automatisch die Audiowiedergabe und erfordern eine click Ereignis, bevor die Audiowiedergabe für Abonnenten beginnt. Zu diesen Browsern gehören Safari, Firefox 66+ und Chrome 71+.

Das „Subscriber“-Objekt zeigt eine Schaltfläche für die Audiowiedergabe an, wenn die Audiowiedergabe blockiert ist. Sie können die Standard-Schaltfläche für die Audiowiedergabe des „Subscriber“ deaktivieren und stattdessen ein eigenes UI-Element anzeigen, auf das der Benutzer klicken muss, um die Audiowiedergabe zu starten. Siehe Anzeige eines benutzerdefinierten UI-Elements, wenn Teilnehmer-Audio blockiert ist.

Wenn der Ton des Teilnehmers unterbrochen wird, löst das „Subscriber“-Objekt ein audioBlocked Ereignis, und es löst ein audioUnblocked Ereignis, wenn die Audioausgabe freigegeben wird:

subscriber.on({
  audioBlocked: function(event) {
   console.log("Subscriber audio is blocked.")
  },
  audioUnblocked: function(event) {
   console.log("Subscriber audio is unblocked.")
  }
});

Außerdem fügt der Abonnent ein isAudioBlocked() was Folgendes zurückgibt true falls der Ton blockiert ist oder false falls dies nicht der Fall ist.

Der Ton des Teilnehmers wird freigegeben, wenn einer der folgenden Fälle eintritt:

  • Der Benutzer klickt auf das Standardsymbol für die Audiowiedergabe des Teilnehmers
  • Die OT.unblockAudio() Die Methode wird aufgerufen, wenn ein HTML-Element ein Ereignis auslöst. click Ereignis (falls Sie das Standard-Symbol für die Audiowiedergabe deaktiviert haben)
  • Der lokale Client erhält Zugriff auf die Kamera oder das Mikrofon (beispielsweise als Reaktion auf einen erfolgreichen Aufruf von OT.initPublisher()).

Weitere Informationen finden Sie unter dieser Mozilla-Artikel über Autoplay in Firefox und dieser Google-Artikel über Autoplay in Chrome.

Erkennen, wenn das Video eines Abonnenten deaktiviert ist

Wenn das Video des Abonnenten deaktiviert wird, löst das „Subscriber“-Objekt ein videoDisabled Veranstaltung:

subscriber.on("videoDisabled", function(event) {
  // You may want to hide the subscriber video element:
  domElement = document.getElementById(subscriber.id);
  domElement.style["visibility"] = "hidden";

  // You may want to add or adjust other UI.
});

Wenn der OpenTok Media Router oder ein für Fallback aktivierter Publisher das Video eines Abonnenten deaktiviert, möchten Sie möglicherweise die Benutzeroberfläche für diesen Abonnenten anpassen.

Die reason Eigenschaft der videoDisabled Ereignisobjekt definiert den Grund, warum das Video deaktiviert wurde. Dieser kann auf einen der folgenden Werte gesetzt werden:

  • "publishVideo" — Der Verlag stellte die Veröffentlichung von Videos ein, indem er anrief publishVideo(false).

  • "quality" — Der OpenTok Media Router oder der Publishing-Client, falls Publisher Audio Fallback ist aktiviert, wird die Videoübertragung an den Teilnehmer aufgrund von Änderungen der Stream-Qualität unterbrochen. Diese Funktion des OpenTok Media Routers bewirkt, dass der Teilnehmer den Videostream trennt, wenn sich die Verbindungsqualität verschlechtert. (Der Teilnehmer empfängt weiterhin den Audiostream, sofern vorhanden.) Die Audio-Fallback-Funktion für den Publisher bewirkt, dass der Publisher die Veröffentlichung des Videostreams einstellt, wenn sich die Verbindung des Publishers verschlechtert, woraufhin der Abonnent den Videostream trennt.

    Bevor dieses Ereignis gesendet wird, sendet der Abonnent, sobald sich die Stream-Qualität des Abonnenten oder die eines Fallback-fähigen Publishers so weit verschlechtert, dass die Gefahr besteht, dass der Videostream deaktiviert wird, ein videoDisableWarning Veranstaltung.

    Sollte sich die Verbindung wieder so weit verbessern, dass die Wiedergabe von Videos möglich ist, löst das „Subscriber“-Objekt einen videoEnabled Ereignis, und der Abonnent empfängt wieder Videos.

    Standardmäßig zeigt der Abonnent eine Anzeige für deaktivierte Videos an, wenn ein videoDisabled Ein Ereignis mit diesem Grund wird ausgelöst und hebt die Markierung auf, wenn das videoDisabled Ein Ereignis mit diesem Grund wird ausgelöst. Sie können die Anzeige dieses Symbols steuern, indem Sie die Funktion setStyle() Methode des Abonnenten, wobei die videoDisabledDisplayMode Eigenschaft; oder Sie können den Stil beim Aufruf der Session.subscribe() Methode, wobei die style Eigenschaft der properties Parameter.

    Diese Funktion ist nur in Sitzungen verfügbar, die den OpenTok Media Router verwenden (Sitzungen mit dem Medienbetrieb (auf „routed“ gesetzt) oder in Sitzungen mit einem Publisher, bei dem das Fallback aktiviert ist. Siehe „Publisher-Fallback aktiviert“ Dokumente.

    Wenn Sie einen Stream veröffentlichen, können Sie verhindern, dass das Video aufgrund der Streamqualität deaktiviert wird. einstellen audioFallbackEnabled zu false im properties Objekt, das an die OT.initPublisher() Methode (diese Funktion wird nicht mehr unterstützt) oder legen Sie subscriber zu false im audioFallback Objekt, das als properties Parameter des OT.initPublisher() Methode.

  • "subscribeToVideo" — Der Abonnent hat das Video-Abonnement per Telefon abgeschlossen oder gekündigt, indem er subscribeToVideo(false).

  • "codecNotSupported" - Der Abonnent hat das Videoabonnement aufgrund eines inkompatiblen Codecs beendet (siehe die Video-Codecs Entwicklerhandbuch).

Der Abonnent versendet eine videoEnabled Ereignis, wenn das Video fortgesetzt wird:

subscriber.on("videoEnabled", function(event) {
  // You may want to display the subscriber video element,
  // if it was hidden:
  domElement = document.getElementById(subscriber.id);
  domElement.style["visibility"] = "visible";

  // You may want to add or adjust other UI.
});

Die reason Eigenschaft der videoEnabled Das Ereignisobjekt definiert den Grund, aus dem das Video aktiviert wurde. Es kann auf einen der folgenden Werte gesetzt werden:

  • "publishVideo" — Der Verlag begann mit der Veröffentlichung von Videos, indem er publishVideo(true).

  • "quality" — Der OpenTok Media Router – oder der „Fallback-fähige Publisher“ – hat die Videoübertragung an den Subscriber aufgrund von Änderungen der Stream-Qualität wieder aufgenommen. Diese Funktion des OpenTok Media Routers bewirkt, dass der Subscriber den Videostream unterbricht, wenn sich die Verbindung verschlechtert, und den Videostream wieder aufnimmt, sobald sich die Stream-Qualität verbessert. Die Audio-Fallback-Funktion des Publishers bewirkt, dass der Publisher die Übertragung des Videostreams unterbricht, wenn sich die Verbindung des Publishers verschlechtert, woraufhin der Abonnent den Videostream trennt.

    Diese Funktion ist nur in Sitzungen verfügbar, die den OpenTok Media Router verwenden (Sitzungen mit dem Medienbetrieb (auf „routed“ gesetzt) oder in Sitzungen mit einem Publisher, bei dem Fallback aktiviert ist.

  • "subscribeToVideo" — Der Abonnent hat das Video-Abonnement per Telefon abgeschlossen oder gekündigt, indem er subscribeToVideo(false).

  • "codecChanged" - Das Teilnehmervideo wurde nach einem Codec-Wechsel von einem inkompatiblen Codec aktiviert (siehe die Video-Codecs Entwicklerhandbuch).

Erkennen, wann sich die Videoabmessungen des Streams eines Abonnenten ändern

Die Abmessungen des Videostreams eines Abonnenten können sich ändern, wenn ein von einem Mobilgerät veröffentlichter Stream aufgrund einer Änderung der Geräteausrichtung in der Größe angepasst wird. Dies kann auch auftreten, wenn die Videoquelle ein Bildschirmfreigabefenster ist und der Nutzer, der den Stream veröffentlicht, die Größe des Fensters ändert, das als Quelle für den Stream dient. Wenn sich die Videoabmessungen ändern, löst das „Subscriber“-Objekt ein videoDimensionsChanged Veranstaltung.

Der folgende Code passt die Größe eines Abonnenten an, wenn sich die Videoabmessungen des Streams ändern:

subscriber.on('videoDimensionsChanged', function(event) {
  subscriber.element.style.width = event.newValue.width + 'px';
  subscriber.element.style.height = event.newValue.height + 'px';
  // You may want to adjust other UI.
});

Informationen zu einem Stream abrufen

Das Stream-Objekt hat die folgenden Eigenschaften, die den Stream definieren:

  • connection—Das „Connection“-Objekt, das der Verbindung entspricht, über die der Stream veröffentlicht wird. Man kann dies mit dem connection Eigenschaft des Session-Objekts, um zu prüfen, ob der Stream von der lokalen Webseite veröffentlicht wird.
  • creationTime—Der Zeitstempel (eine Zahl) für die Erstellung des Streams. Dieser Wert wird in Millisekunden berechnet. Sie können diesen Wert in ein Date-Objekt umwandeln, indem Sie new Date(stream.creationTime).
  • hasAudio—(Boolescher Wert) Gibt an, ob der Stream Audio enthält. Diese Eigenschaft kann sich ändern, wenn der Publisher das Audio ein- oder ausschaltet (durch Aufruf von Publisher.publishAudio()). Wenn dies geschieht, wird die Sitzung Objekt sendet eine streamPropertyChanged Veranstaltung.
  • hasVideo-(Boolean) Ob der Stream Video enthält.
  • initials—(Boolescher Wert) Die Initialen des Streams (sofern beim Veröffentlichen des Streams Initialen festgelegt wurden) wurde initialisiert).
  • name—(Zeichenkette) Der Name des Streams. Dieser wird standardmäßig angezeigt, wenn der Benutzer mit der Maus über den Abonnenten im HTML-DOM fährt. Sie können die Benutzeroberfläche jedoch so anpassen, dass der Name ausgeblendet wird oder auch ohne Mausbewegung angezeigt wird.
  • videoDimensions—Dieses Objekt hat zwei Eigenschaften: width und height. Beides sind Numbers. Die width ist die Breite des kodierten Streams; die Eigenschaft height Eigenschaft ist die Höhe des kodierten Streams. (Diese sind unabhängig von der tatsächlichen Breite der Publisher- und Subscriber-Objekte, die dem Stream entsprechen). Diese Eigenschaft kann sich ändern, wenn sich die Größe eines von einem iOS-Gerät veröffentlichten Streams aufgrund einer Änderung der Geräteausrichtung ändert.
  • videoType—Der Videotyp: entweder „camera“, „screen“, „custom“ oder undefiniert. Bei einem „screen“-Video wird die Bildschirmfreigabe auf dem Publisher als Videoquelle verwendet; bei einem „custom“-Video wird ein VideoTrack-Element auf dem Publisher als Videoquelle verwendet. Das videoType ist undefined wenn es sich um einen reinen Sprachstrom handelt (siehe die Anleitung nur mit Stimme). Diese Eigenschaft kann sich ändern, wenn ein von einem mobilen Gerät veröffentlichter Stream von einem Kamera- zu einem Bildschirmfreigabevideotyp wechselt. Für weitere Informationen, siehe Bildschirmfreigabe - Web.

Die hasAudio, hasVideo, videoDimensionsund videoType Eigenschaften können sich ändern (beispielsweise, wenn der Herausgeber das Video ein- oder ausschaltet). In diesem Fall wird die Sitzung Objekt sendet eine streamPropertyChanged Ereignis (siehe StreamPropertyChangedEvent.)

Die getStats() Die Methode eines „Subscriber“-Objekts liefert Ihnen Informationen zum Stream des Abonnenten. Um detaillierte Statistiken zur Peer-Verbindung abzurufen, verwenden Sie die Subscriber.getRtcStatsReport() Methode. Sie gibt ein Versprechen zurück, das im Erfolgsfall mit einer RtcStatsReport Objekt für den abonnierten Stream.

Siehe das Handbuch für Entwickler von Client Observability für detaillierte Informationen.

Einstellung der bevorzugten Bildrate und Auflösung

Beim Abonnieren eines Streams, der die Skalierbare Videofunktion, haben Sie die Möglichkeit, Folgendes festzulegen: preferredResolution zu "auto" um die Videoauflösung für Abonnenten automatisch entsprechend der gerenderten Größe anzupassen und so die Netzwerk- und CPU-Auslastung zu optimieren. Fortgeschrittene Benutzer können zudem die gewünschte Bildrate und Auflösung für den Stream, den der abonnierende Client vom OpenTok Media Router empfängt, manuell festlegen. Sie können diese als preferredFrameRate und preferredResolution Eigenschaften der options man gelangt in die [`Session.subscribe()`](/video/sdk-reference/js/Session.html#subscribe) Methode. Wir empfehlen, folgende Einstellung vorzunehmen: preferredResolution zu "auto". Mit dem "auto" Je nach Einstellung wählt OpenTok.js die bevorzugte Auflösung anhand der Abmessungen des Abonnentenvideos im Browser aus. Sie können die bevorzugte Bildrate und Auflösung auch nach dem Abonnieren eines Streams festlegen (siehe [`Subscriber.setPreferredFrameRate()`](/opentok/sdks/js/reference/Subscriber.html#setPreferredFrameRate) und Subscriber.setPreferredResolution()).

Anmerkung: Die "auto" Die Einstellung für die Auflösung gilt nur, wenn Sie das vom SDK erstellte Standard-„Subscriber Video“-Element verwenden. Sie funktioniert nicht, wenn Sie als Reaktion auf die videoElementCreated Ereignis (siehe dieses Thema).

Anmerkung: Diese Einstellungen setzen voraus, dass der Publisher das Standardlayout der Skalierbarkeitsschicht verwendet. Falls der Publisher einen vom Standard abweichenden Zielskalierbarkeitsmodus festgelegt hat (siehe Festlegen des Zielskalierbarkeitsmodus), stimmt die vom Media Router gewählte Ebene möglicherweise nicht mit der angeforderten Auflösung oder Bildrate überein. Siehe Anpassung an die vom Teilnehmer bevorzugte Auflösung und Bildfrequenz für Einzelheiten.

Filter und Effekte auf abonnierte Audio- und Videodateien anwenden

Sie können Filter und Effekte auf Audio- oder Videospuren eines abonnierten Streams anwenden – siehe dieses Thema.

Erkennung von Veränderungen der Audio- und Videoqualität

Wenn bei einem Kunden zeitweise eine beeinträchtigte Netzwerkverbindung auftritt, kann sich dies auf die Gesprächsqualität des Teilnehmers auswirken. Das „Subscriber“-Objekt sendet eine qualityScoreChanged Ereignis, bei dem sich die berechneten MOS-Werte für Audio und Video ändern. Diese Werte werden als Ganzzahlen zwischen 1 (am schlechtesten) und 5 (am besten) angegeben, was den Bewertungen „schlecht“, „mangelhaft“, „befriedigend“, „gut“ und „ausgezeichnet“ entspricht. Weitere Einzelheiten finden Sie unter „Teilnehmer“ qualityScoreChanged Veranstaltung.

Ein „Subscriber“-Objekt löst dieses Ereignis nur dann aus, wenn sich einer der Qualitätswerte geändert hat. Jeder „Subscribe“-Befehl löst Ereignisse mit seinen eigenen Audio- und Video-Qualitätswerten aus, je nachdem, ob er Audio, Video oder beides abonniert.

Als Reaktion auf diese Ereignisse kann Ihre Anwendung (optional) den Client über Netzwerkbedingungen informieren, die zu einer Verschlechterung der Gesprächsqualität führen:

subscriber.on('qualityScoreChanged', ({qualityScore}) => {
  if (qualityScore.audioQualityScore <= 3){
    // Alert the user that the remote party is experiencing degraded service
  }
  if (qualityScore.videoQualityScore <= 3){
    // Alert the user that the remote party is experiencing degraded service
  }
});

Fehlersuche

Befolgen Sie die Tipps in diesem Abschnitt, um Verbindungsprobleme beim Abonnieren zu vermeiden. Allgemeine Informationen zur Fehlerbehebung finden Sie unter Fehlerbehebung – Web.

Umgang mit Fehlern

Die Behandlung von Fehlern beim Abonnieren ist etwas einfacher als beim Veröffentlichen. Es gibt nur eine Möglichkeit, ein Abonnement abzuschließen – nämlich mit dem Session.subscribe() Methode – und so gut wie jeder Fehler, der beim Abonnieren auftritt, ist auf ein Netzwerkproblem zurückzuführen. Dies kann beispielsweise passieren, wenn der Nutzer eine sehr eingeschränkte Netzwerkverbindung nutzt, die keine WebRTC-Verbindungen zulässt (die WebSocket-Verbindung funktionierte jedoch). Wenn der Subscriber keine Verbindung herstellen kann, zeigt er lediglich eine eigene Fehlermeldung an. Diese sieht nicht besonders ansprechend aus und ist für den Endnutzer nicht sehr aussagekräftig. Wir empfehlen Ihnen, diesen Fall selbst zu behandeln und dem Nutzer eine Meldung anzuzeigen, die darauf hinweist, dass das Abonnieren fehlgeschlagen ist und er seine Netzwerkverbindung überprüfen sollte. Die Behandlung dieser Fehler sieht wie folgt aus:

session.subscribe(event.stream, 'subscriber', {insertMode: 'append'}, function (err) {
  if (err) {
    showMessage('Streaming connection failed. This could be due to a restrictive firewall.');
  }
});

Verlust der Konnektivität

Ihr Abonnent kann seine Verbindung auch verlieren, nachdem er sich bereits erfolgreich verbunden hat. In den meisten Fällen führt dies auch dazu, dass die Sitzung die Verbindung verliert, aber das ist nicht immer der Fall. Es kann auch sein, dass der Publisher auf der anderen Seite die Verbindung verloren hat und es sich nicht um einen lokalen Verbindungsabbruch handelt. Sie können die Trennung des Abonnenten behandeln, indem Sie auf das streamDestroyed Ereignis in der Sitzung mit einem reason Eigenschaft auf „networkDisconnected“ gesetzt, und zwar wie folgt:

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);
        // Display error message inside the Subscriber
        subscriber.innerHTML = 'Lost connection. This could be due to your internet connection '
          + 'or because the other party lost their connection.';
        event.preventDefault();   // Prevent the Subscriber from being removed
      }
    }
  }
});

Implementierung von Wiederholungsversuchen beim Abonnieren von Sitzungen

Vorübergehende Abonnementfehler können auftreten, wenn session.subscribe() aufgerufen wird und die zugrunde liegende WebRTC-Verbindung nicht rechtzeitig hergestellt werden kann oder wenn eine kurzzeitige Netzwerkstörung die ICE-Verhandlung unterbricht. Wenn session.subscribe() Schlägt der Vorgang fehl, gibt das SDK über den Callback des Completion-Handlers einen Fehler zurück. Es wird empfohlen, auf Anwendungsebene eine Wiederholungslogik mit einer Verzögerung zwischen den Versuchen zu implementieren.

Anmerkung: Integrierte Unterstützung für Wiederholungsversuche bei session.subscribe() steht auf der SDK-Roadmap. Bis es verfügbar ist, müssen Sie dies selbst implementieren.

Warum es zu Abonnementfehlern kommt

Die häufigsten Ursachen für vorübergehende Abonnementfehler sind:

  • OT_TIMEOUT (Code 1501): Die Abonnierung konnte nicht innerhalb des zulässigen Zeitfensters (30 Sekunden) abgeschlossen werden. Dies entspricht auf der Abonnentenseite dem Zeitlimit für die Veröffentlichung und ist der häufigste Fehler, bei dem ein erneuter Versuch möglich ist.
  • Gescheiterte ICE-Verhandlungen (OT_ICE_WORKFLOW_FAILED): Die WebRTC-Peer-Verbindung konnte nicht hergestellt werden, was in der Regel auf ein restriktives Netzwerk oder ein vorübergehendes Verbindungsproblem zurückzuführen ist.
  • Fehler beim Aufbau von Peer-Verbindungen (OT_CREATE_PEER_CONNECTION_FAILED): Das WebRTC-Peer-Verbindungsobjekt konnte nicht erstellt werden. Dies wird häufig durch ein vorübergehendes Problem mit der Plattform oder dem Netzwerk verursacht.
  • Netzwerkstörungen während des Abonnementvorgangs: Eine kurze Netzwerkunterbrechung während der ICE-Verhandlung oder der Medienbindung kann dazu führen, dass das Abonnement ohne einen schwerwiegenden Fehler ausläuft.

Behebbare vs. nicht behebbare Fehler

Nicht alle session.subscribe() Fehler sind nicht alle gleich. Es ist unerlässlich, Fehler vor einem erneuten Versuch korrekt zu klassifizieren – ein erneuter Versuch bei einem nicht behebbaren Fehler verschwendet Zeit und kann echte Fehler verschleiern.

Anmerkung: Verwenden Sie immer das error.name Eigenschaft zur programmgesteuerten Fehlererkennung. Der numerische error.code Die Eigenschaft ist veraltet.

Unbehebbare Fehler – Nicht erneut versuchen

Diese Fehler stehen für harte Einschränkungen, einen ungültigen Aufrufkontext oder Endzustände von Datenströmen. Ein erneuter Versuch kann diese Fehler nicht beheben.

error.name Beschreibung Empfohlene Maßnahme
OT_NOT_CONNECTED session.subscribe() wurde aufgerufen, bevor die Sitzung hergestellt wurde. Sicherstellen session.connect() vor dem Abonnieren erfolgreich abgeschlossen wurde.
OT_DISCONNECTED Die Aktion ist fehlgeschlagen, da der Client nicht mit der Sitzung verbunden ist. Warten Sie, bis die Sitzung wiederhergestellt ist, bevor Sie es erneut versuchen.
OT_INVALID_PARAMETER Ein oder mehrere Parameter, die an session.subscribe() waren ungültig (z. B. Null-Stream oder Zielelement). Korrigieren Sie die Anwendungslogik. Führen Sie keinen erneuten Versuch durch.
OT_STREAM_DESTROYED Der Stream wurde gelöscht, bevor er abonniert werden konnte. Bitte nicht erneut versuchen – der Stream existiert nicht mehr. Entfernen Sie alle ausstehenden Abonnementzustände für diesen Stream.
OT_STREAM_NOT_FOUND Der Stream konnte in der Sitzung nicht gefunden werden. Bitte nicht erneut versuchen – der Stream ist nicht mehr verfügbar.
OT_STREAM_LIMIT_EXCEEDED Die Sitzung hat die Obergrenze für gleichzeitige Streams überschritten. Informieren Sie den Benutzer. Versuchen Sie es erst erneut, wenn ein Stream-Slot frei wird.
OT_UNABLE_TO_SUBSCRIBE Der Benutzer hat versucht, sich in einer E2EE-fähigen Sitzung anzumelden, ohne ein Verschlüsselungsgeheimnis anzugeben; oder ein unerwarteter Fehler hat die Anmeldung verhindert. Stellen Sie bei E2EE-Sitzungen sicher, dass ein Verschlüsselungsschlüssel über session.setEncryptionSecret() vor dem Abonnieren. Im allgemeinen Fall sollte der Fehler protokolliert und der Benutzer darüber informiert werden.

Behebbare Fehler – Wiederholung des Versuchs ist unbedenklich

Diese Fehler werden in der Regel durch vorübergehende Netzwerkstörungen, Zeitüberschreitungen bei der Signalübertragung oder eine vorübergehende Nichtverfügbarkeit der Plattform verursacht.

error.name Beschreibung Empfohlene Maßnahme
OT_TIMEOUT (Code 1501) Das Abonnement wurde nicht innerhalb einer angemessenen Zeitspanne abgeschlossen. Der häufigste Fehler beim Abonnieren, der erneut versucht werden kann. Abmelden, dann mit Backoff erneut versuchen (bis zu 3 Versuche).
OT_ICE_WORKFLOW_FAILED Die ICE-Verhandlung ist fehlgeschlagen – die Peer-Verbindung konnte nicht hergestellt werden. Tritt häufig vorübergehend in Netzwerken mit Einschränkungen auf. Abmelden und es dann erneut versuchen. Sollte das Problem nach allen Versuchen weiterhin bestehen, weisen Sie den Nutzer auf ein mögliches Netzwerk- oder Firewall-Problem hin.
OT_CREATE_PEER_CONNECTION_FAILED Die WebRTC-Peer-Verbindung konnte nicht hergestellt werden. Dies kann auf eine restriktive Firewall oder ein vorübergehendes Plattformproblem hindeuten. Abmelden und es dann erneut versuchen. Sollte das Problem weiterhin bestehen, bitten Sie den Nutzer, seine Netzwerkverbindung zu überprüfen.
OT_SET_REMOTE_DESCRIPTION_FAILED Die WebRTC-Verbindung ist während setRemoteDescription. In der Regel handelt es sich um ein vorübergehendes Problem bei der Signalübertragung. Abmelden und es dann mit einer Wartezeit erneut versuchen.
OT_MEDIA_ERR_ABORTED / OT_MEDIA_ERR_NETWORK Die Medienübertragung wurde aufgrund eines Netzwerkfehlers abgebrochen oder unterbrochen. Melden Sie sich ab und versuchen Sie es nach einer kurzen Wartezeit erneut.
OT_MEDIA_ERR_DECODE Beim Versuch, den Stream im Video-Element abzuspielen, ist ein Dekodierungsfehler aufgetreten. Melden Sie sich ab und versuchen Sie es nach einer kurzen Wartezeit erneut. Sollte das Problem weiterhin bestehen, ist das Medienformat möglicherweise nicht kompatibel.
OT_MEDIA_ERR_SRC_NOT_SUPPORTED Der Stream wurde als für die Wiedergabe ungeeignet erkannt. Melden Sie sich ab und versuchen Sie es dann erneut. Sollte das Problem weiterhin bestehen, überprüfen Sie die Konfiguration des Video-Elements des Abonnenten.

Wichtig: Melden Sie sich immer ab, bevor Sie es erneut versuchen.

Im Gegensatz zu session.publish(), wobei die Publisher-Instanz oft direkt wiederverwendet werden kann, session.subscribe() erfordert, dass Sie anrufen session.unsubscribe() und das Abonnentenobjekt verwerfen, bevor ein erneuter Versuch unternommen wird. Der Versuch, eine ausgefallene Abonnenteninstanz erneut zu verwenden, schlägt fehl.

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
}

Verwendung:

session.on('streamCreated', (event) => {
  subscribeWithRetry(session, event.stream, document.getElementById('subscriber'), {});
});

Zeitkritische Szenarien

Der Stream wird während eines Wiederholungsversuchs beendet

Wird der Stream zerstört, während ein Wiederholungsversuch noch aussteht, wird der streamDestroyed Das Session-Ereignis wird ausgelöst. Sie müssen alle ausstehenden Wiederholungsversuche für diesen Stream abbrechen, um zu vermeiden, dass Sie einen Stream abonnieren, der nicht mehr existiert.

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}`);
  }
});

Wiederherstellung der Sitzung während eines erneuten Abonnementversuchs

Wenn die Verbindung neu hergestellt wird (z. B. nach einem Netzwerkausfall), sollte der erneute Versuch so lange aufgeschoben werden, bis die Verbindung wiederhergestellt ist. Der Versuch, ein Abonnement abzuschließen, während die Verbindung neu hergestellt wird, schlägt sofort fehl.

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;
}

Was man NICHT tun sollte

  • Do nicht Eine fehlgeschlagene Abonnenteninstanz wiederverwenden – immer aufrufen session.unsubscribe() und bei einem erneuten Versuch ein neues Abonnement erstellen.
  • Do nicht Erneut versuchen OT_STREAM_DESTROYED oder OT_STREAM_NOT_FOUND — Der Stream ist nicht mehr vorhanden, und jeder erneute Versuch wird immer fehlschlagen.
  • Do nicht Erneut versuchen OT_STREAM_LIMIT_EXCEEDED — Hierbei handelt es sich um eine Kapazitätsbeschränkung auf Sitzungsebene und nicht um einen vorübergehenden Fehler.
  • Do nicht Unbegrenzt wiederholen – auf maximal 3 Versuche beschränken und den Benutzer informieren, wenn alle fehlschlagen.
  • Do nicht Erneut versuchen, während die Sitzung neu verbunden wird – aufschieben, bis sessionReconnected Brände.

Zusammenfassung der empfohlenen Parameter

Parameter Empfohlener Wert Anmerkungen
Maximale Anzahl von Wiederholungsversuchen 3 In Übereinstimmung mit session.publish() Anleitung zum erneuten Versuch
Wartezeit bis zum erneuten Versuch 3 s × Versuch (3 s, 6 s, 9 s) Etwas länger als die Wiederholungsversuche bei der Veröffentlichung – das Abonnement-Timeout beträgt 30 Sekunden
Bei allen Wiederholungsversuchen scheitern Benutzer informieren Vermeiden Sie es, den Stream stillschweigend zu beenden
Fehler, die nicht erneut versucht werden können OT_STREAM_DESTROYED, OT_STREAM_NOT_FOUND, OT_STREAM_LIMIT_EXCEEDED Probiert das schnell aus
Bereinigung der Abonnentenliste Immer session.unsubscribe() vor dem erneuten Versuch Erforderlich – im Gegensatz zu Publishern können Abonnenteninstanzen nicht wiederverwendet werden