Veröffentlichen und Abonnieren mit dem IVS iOS Broadcast SDK | Streaming in Echtzeit
Dieses Dokument führt Sie durch die Schritte zum Veröffentlichen und Abonnieren einer Stufe mit dem iOS Broadcast SDK von IVS-Streaming in Echtzeit.
Konzepte
Drei Kernkonzepte liegen der Echtzeit-Funktionalität zugrunde: Stage, Strategie und Renderer. Das Designziel besteht in der Minimierung der Menge an clientseitiger Logik, die für die Entwicklung eines funktionierenden Produkts erforderlich ist.
Stufe
Die Klasse IVSStage
ist der Hauptinteraktionspunkt zwischen der Hostanwendung und dem SDK. Die Klasse stellt die Bühne selbst dar und dient dazu, der Bühne beizutreten und sie zu verlassen. Für das Erstellen einer Bühne oder das Beitreten ist eine gültige, noch nicht abgelaufene Token-Zeichenfolge aus der Steuerebene erforderlich (dargestellt als token
). Einer Bühne beizutreten und sie zu verlassen, ist ganz einfach.
let stage = try IVSStage(token: token, strategy: self) try stage.join() stage.leave()
In der Klasse IVSStage
erfolgt auch das Anhängen des IVSStageRenderer
und IVSErrorDelegate
:
let stage = try IVSStage(token: token, strategy: self) stage.errorDelegate = self stage.addRenderer(self) // multiple renderers can be added
Strategie
Über das Protokoll IVSStageStrategy
kann die Hostanwendung dem SDK den gewünschten Status der Bühne mitteilen. Drei Funktionen müssen implementiert werden: shouldSubscribeToParticipant
, shouldPublishParticipant
und streamsToPublishForParticipant
. Alle werden im Folgenden behandelt.
Abonnieren von Teilnehmern
func stage(_ stage: IVSStage, shouldSubscribeToParticipant participant: IVSParticipantInfo) -> IVSStageSubscribeType
Wenn ein Remote-Teilnehmer einer Bühne beitritt, fragt das SDK die Hostanwendung nach dessen gewünschtem Abonnementstatus. Die Optionen lauten .none
, .audioOnly
und .audioVideo
. Wenn ein Wert für diese Funktion zurückgegeben wird, muss sich die Hostanwendung nicht um den Veröffentlichungs-, den aktuellen Abonnement- oder den Verbindungsstatus des Bühne kümmern. Bei Rückgabe von .audioVideo
wartet das SDK mit dem Abonnieren, bis der Remote-Teilnehmer etwas veröffentlicht. Außerdem aktualisiert das SDK die Hostanwendung während des gesamten Prozesses über den Renderer.
Hier folgt ein Beispiel für eine Implementierung:
func stage(_ stage: IVSStage, shouldSubscribeToParticipant participant: IVSParticipantInfo) -> IVSStageSubscribeType { return .audioVideo }
Hierbei handelt es sich um die vollständige Implementierung dieser Funktion für eine Hostanwendung, bei der sich alle Teilnehmer stets gegenseitig sehen sollen; z. B. eine Video-Chat-Anwendung.
Weitergehende Implementierungen sind ebenfalls möglich. Nutzen Sie die Eigenschaft attributes
für IVSParticipantInfo
, um Teilnehmer anhand der vom Server bereitgestellten Attribute selektiv zu abonnieren:
func stage(_ stage: IVSStage, shouldSubscribeToParticipant participant: IVSParticipantInfo) -> IVSStageSubscribeType { switch participant.attributes["role"] { case "moderator": return .none case "guest": return .audioVideo default: return .none } }
Hiermit kann eine Bühne erstellt werden, auf der Moderatoren alle Gäste überwachen können, ohne selbst gesehen oder gehört zu werden. Die Hostanwendung könnte eine zusätzliche Geschäftslogik nutzen, damit Moderatoren sich gegenseitig sehen können, für Gäste aber unsichtbar bleiben.
Konfiguration für das Abonnieren von Teilnehmern
func stage(_ stage: IVSStage, subscribeConfigurationForParticipant participant: IVSParticipantInfo) -> IVSSubscribeConfiguration
Wenn ein Remote-Teilnehmer abonniert wird (siehe Teilnehmer abonnieren), fragt das SDK die Host-Anwendung nach einer benutzerdefinierten Abonnementkonfiguration für diesen Teilnehmer ab. Diese Konfiguration ist optional und ermöglicht es der Hostanwendung, bestimmte Aspekte des Subscriber-Verhaltens zu steuern. Informationen darüber, was konfiguriert werden kann, finden Sie unter SubscribeConfiguration
Hier folgt ein Beispiel für eine Implementierung:
func stage(_ stage: IVSStage, subscribeConfigurationForParticipant participant: IVSParticipantInfo) -> IVSSubscribeConfiguration { let config = IVSSubscribeConfiguration() try! config.jitterBuffer.setMinDelay(.medium()) return config }
Diese Implementierung aktualisiert die Mindestverzögerung für den Jitter-Buffer für alle abonnierten Teilnehmer auf die Voreinstellung MEDIUM
.
Wie bei shouldSubscribeToParticipant
sind auch hier weitergehende Implementierungen möglich. Die ParticipantInfo
-Angaben können verwendet werden, um die Abonnementkonfiguration für bestimmte Teilnehmer selektiv zu aktualisieren.
Wir empfehlen die Verwendung der Standardverhaltensweisen. Geben Sie die benutzerdefinierte Konfiguration nur an, wenn Sie ein bestimmtes Verhalten ändern möchten.
Veröffentlichen
func stage(_ stage: IVSStage, shouldPublishParticipant participant: IVSParticipantInfo) -> Bool
Sobald die Verbindung zur Bühne hergestellt ist, überprüft das SDK per Anfrage an die Hostanwendung, ob ein bestimmter Teilnehmer etwas veröffentlichen soll. Dies wird nur bei lokalen Teilnehmern aufgerufen, die auf Grundlage des bereitgestellten Tokens zur Veröffentlichung berechtigt sind.
Hier folgt ein Beispiel für eine Implementierung:
func stage(_ stage: IVSStage, shouldPublishParticipant participant: IVSParticipantInfo) -> Bool { return true }
Sie ist für eine normale Video-Chat-Anwendung gedacht, bei der Benutzer immer etwas veröffentlichen möchten. Sie können die Audio- und Videowiedergabe stummschalten und die Stummschaltung aufheben, um umgehend ausgeblendet oder gesehen/gehört zu werden. (Sie können auch „Veröffentlichen/Veröffentlichung aufheben“ verwenden, was aber viel langsamer ist. „Stummschalten/Stummschalten aufheben“ ist für Anwendungsfälle vorzuziehen, in denen eine häufige Änderung der Sichtbarkeit wünschenswert ist.)
Auswählen von Streams zur Veröffentlichung
func stage(_ stage: IVSStage, streamsToPublishForParticipant participant: IVSParticipantInfo) -> [IVSLocalStageStream]
Beim Veröffentlichen wird hiermit bestimmt, welche Audio- und Videostreams veröffentlicht werden sollen. Dieser Punkt wird später unter Veröffentlichen eines Medienstreams ausführlicher behandelt.
Aktualisieren der Strategie
Die Strategie soll dynamisch sein: Die von einer der oben genannten Funktionen zurückgegebenen Werte lassen sich jederzeit ändern. Wenn die Hostanwendung beispielsweise erst veröffentlichen soll, wenn der Endbenutzer auf eine Schaltfläche tippt, können Sie eine Variable aus shouldPublishParticipant
zurückgeben (zum Beispiel hasUserTappedPublishButton
). Wenn sich diese Variable aufgrund einer Interaktion des Endbenutzers ändert, signalisieren Sie dem SDK per Aufruf von stage.refreshStrategy()
, dass es die Strategie nach den neuesten Werten abfragen und nur Dinge anwenden soll, die sich geändert haben. Wenn das SDK feststellt, dass sich der Wert shouldPublishParticipant
geändert hat, startet es den Veröffentlichungsprozess. Wenn alle Funktionen bei einer SDK-Abfrage den gleichen Wert zurückgeben wie zuvor, werden mit dem Aufruf von refreshStrategy
keine Änderungen an der Bühne durchgeführt.
Ändert sich der Rückgabewert von shouldSubscribeToParticipant
von .audioVideo
in .audioOnly
, wird der Videostream für alle Teilnehmer mit geänderten Rückgabewerten entfernt, sofern zuvor ein Videostream vorhanden war.
Im Allgemeinen nutzt die Bühne die Strategie, um den Unterschied zwischen der vorherigen und der aktuellen Strategie am effizientesten anzuwenden. Dabei muss sich die Hostanwendung nicht um die ganzen Status kümmern, die für eine ordnungsgemäße Verwaltung erforderlich sind. Stellen Sie sich den Aufruf von stage.refreshStrategy()
daher als einen ressourcenschonenden Vorgang vor, da nur bei einer Änderung der Strategie etwas unternommen wird.
Renderer
Das Protokoll IVSStageRenderer
teilt der Hostanwendung den Status der Bühne mit. Aktualisierungen in der Benutzeroberfläche der Hostanwendung können in der Regel vollständig über die vom Renderer bereitgestellten Ereignisse gesteuert werden. Der Renderer stellt die folgenden Funktionen bereit:
func stage(_ stage: IVSStage, participantDidJoin participant: IVSParticipantInfo) func stage(_ stage: IVSStage, participantDidLeave participant: IVSParticipantInfo) func stage(_ stage: IVSStage, participant: IVSParticipantInfo, didChange publishState: IVSParticipantPublishState) func stage(_ stage: IVSStage, participant: IVSParticipantInfo, didChange subscribeState: IVSParticipantSubscribeState) func stage(_ stage: IVSStage, participant: IVSParticipantInfo, didAdd streams: [IVSStageStream]) func stage(_ stage: IVSStage, participant: IVSParticipantInfo, didRemove streams: [IVSStageStream]) func stage(_ stage: IVSStage, participant: IVSParticipantInfo, didChangeMutedStreams streams: [IVSStageStream]) func stage(_ stage: IVSStage, didChange connectionState: IVSStageConnectionState, withError error: Error?) func stage(_ stage: IVSStage, participant: IVSParticipantInfo, stream: IVSRemoteStageStream, didChangeStreamAdaption adaption: Bool) func stage(_ stage: IVSStage, participant: IVSParticipantInfo, stream: IVSRemoteStageStream, didChange layers: [IVSRemoteStageStreamLayer]) func stage(_ stage: IVSStage, participant: IVSParticipantInfo, stream: IVSRemoteStageStream, didSelect layer: IVSRemoteStageStreamLayer?, reason: IVSRemoteStageStream.LayerSelectedReason)
Es wird nicht erwartet, dass sich die vom Renderer bereitgestellten Informationen auf die Rückgabewerte der Strategie auswirken. Es wird beispielsweise nicht erwartet, dass sich der Rückgabewert von shouldSubscribeToParticipant
beim Aufruf von participant:didChangePublishState
ändert. Wenn die Hostanwendung einen bestimmten Teilnehmer abonnieren möchte, muss sie unabhängig von dessen Veröffentlichungsstatus den gewünschten Abonnementtyp zurückgeben. Das SDK muss dafür sorgen, dass entsprechend dem Status der Bühne und dem gewünschten Status der Strategie zum richtigen Zeitpunkt gehandelt wird.
Hinweis: Nur veröffentlichende Teilnehmer lösen participantDidJoin
aus. Wenn Teilnehmer die Veröffentlichung beenden oder die Bühnensitzung verlassen, wird participantDidLeave
ausgelöst.
Veröffentlichen eines Medienstreams
Lokale Geräte wie eingebaute Mikrofone und Kameras werden über IVSDeviceDiscovery
erkannt. Hier folgt ein Beispiel für die Auswahl der nach vorne gerichteten Kamera und des Standardmikrofons und deren anschließende Rückgabe als IVSLocalStageStreams
zur Veröffentlichung durch das SDK:
let devices = IVSDeviceDiscovery().listLocalDevices() // Find the camera virtual device, choose the front source, and create a stream let camera = devices.compactMap({ $0 as? IVSCamera }).first! let frontSource = camera.listAvailableInputSources().first(where: { $0.position == .front })! camera.setPreferredInputSource(frontSource) let cameraStream = IVSLocalStageStream(device: camera) // Find the microphone virtual device and create a stream let microphone = devices.compactMap({ $0 as? IVSMicrophone }).first! let microphoneStream = IVSLocalStageStream(device: microphone) // Configure the audio manager to use the videoChat preset, which is optimized for bi-directional communication, including echo cancellation. IVSStageAudioManager.sharedInstance().setPreset(.videoChat) // This is a function on IVSStageStrategy func stage(_ stage: IVSStage, streamsToPublishForParticipant participant: IVSParticipantInfo) -> [IVSLocalStageStream] { return [cameraStream, microphoneStream] }
Anzeigen und Entfernen von Teilnehmern
Nach Abschluss von Abonnements erhalten Sie über die Funktion didAddStreams
des Renderers eine Reihe von IVSStageStream
-Objekten. Um Statistiken des Audiolevels zu diesem Teilnehmer in der Vorschau anzuzeigen oder abzurufen, können Sie über den Stream auf das zugrunde liegende IVSDevice
-Objekt zugreifen:
if let imageDevice = stream.device as? IVSImageDevice { let preview = imageDevice.previewView() /* attach this UIView subclass to your view */ } else if let audioDevice = stream.device as? IVSAudioDevice { audioDevice.setStatsCallback( { stats in /* process stats.peak and stats.rms */ }) }
Wenn ein Teilnehmer die Veröffentlichung beendet oder dessen Abonnement beendet wird, wird die Funktion didRemoveStreams
mit den Streams aufgerufen, die entfernt wurden. Hostanwendungen sollten dies als Signal nutzen, um den Videostream des Teilnehmers aus der Ansichtshierarchie zu entfernen.
didRemoveStreams
wird für alle Szenarien aufgerufen, in denen ein Stream entfernt werden könnte, darunter:
-
Der Remote-Teilnehmer beendet die Veröffentlichung.
-
Ein lokales Gerät beendet das Abonnement oder ändert das Abonnement von
.audioVideo
in.audioOnly
. -
Der Remote-Teilnehmer verlässt die Bühne.
-
Der lokale Teilnehmer verlässt die Bühne.
Da didRemoveStreams
bei allen Szenarien aufgerufen wird, ist keine benutzerdefinierte Geschäftslogik erforderlich, um Teilnehmer beim remoten oder lokalen Verlassen aus der Benutzeroberfläche zu entfernen.
Stummschalten von Medienstreams und Aufheben der Stummschaltung
IVSLocalStageStream
-Objekte verfügen über eine setMuted
-Funktion, die das Stummschalten des Streams steuert. Diese Funktion kann für den Stream aufgerufen werden, bevor oder nachdem er von der Strategiefunktion streamsToPublishForParticipant
zurückgegeben wird.
Wichtig: Wenn nach einem Aufruf von refreshStrategy
eine neue IVSLocalStageStream
-Objekt-Instance von streamsToPublishForParticipant
zurückgegeben wird, wird der Stummschaltungsstatus des neuen Streamobjekts auf die Bühne angewendet. Seien Sie vorsichtig beim Erstellen neuer IVSLocalStageStream
-Instances, um sicherzustellen, dass der erwartete Stummschaltungsstatus beibehalten wird.
Überwachen des Medien-Stummschaltungsstatus von Remote-Teilnehmern
Wenn ein Teilnehmer den Stummschaltungsstatus seines Video- oder Audiostreams ändert, wird die Funktion didChangeMutedStreams
des Renderers mit einer Gruppe der Streams aufgerufen, die sich geändert haben. Verwenden Sie die Eigenschaft isMuted
für IVSStageStream
, um die Benutzeroberfläche entsprechend zu aktualisieren:
func stage(_ stage: IVSStage, participant: IVSParticipantInfo, didChangeMutedStreams streams: [IVSStageStream]) { streams.forEach { stream in /* stream.isMuted */ } }
Erstellen einer Bühnenkonfiguration
Die Werte der Videokonfiguration einer Bühne passen Sie mit IVSLocalStageStreamVideoConfiguration
an:
let config = IVSLocalStageStreamVideoConfiguration() try config.setMaxBitrate(900_000) try config.setMinBitrate(100_000) try config.setTargetFramerate(30) try config.setSize(CGSize(width: 360, height: 640)) config.degradationPreference = .balanced
Abrufen von WebRTC-Statistiken
Um die neuesten WebRTC-Statistiken für einen veröffentlichten oder abonnierten Stream abzurufen, verwenden Sie requestRTCStats
für IVSStageStream
. Nach Abschluss einer Erfassung erhalten Sie Statistiken über den IVSStageStreamDelegate
, der für IVSStageStream
eingestellt werden kann. Um WebRTC-Statistiken kontinuierlich zu erfassen, rufen Sie diese Funktion für einen Timer
auf.
func stream(_ stream: IVSStageStream, didGenerateRTCStats stats: [String : [String : String]]) { for stat in stats { for member in stat.value { print("stat \(stat.key) has member \(member.key) with value \(member.value)") } } }
Abrufen von Teilnehmerattributen
Wenn Sie Attribute in der Vorgangsanfrage CreateParticipantToken
angeben, können Sie die Attribute in den Eigenschaften von IVSParticipantInfo
einsehen:
func stage(_ stage: IVSStage, participantDidJoin participant: IVSParticipantInfo) { print("ID: \(participant.participantId)") for attribute in participant.attributes { print("attribute: \(attribute.key)=\(attribute.value)") } }
Abrufen von SEI-Daten (Supplemental Enhancement Information)
Die NAL-Einheit für Supplemental Enhancement Information (SEI) wird verwendet, um Frame-orientierte Metadaten zusammen mit dem Video zu speichern. Subscriber können SEI-Nutzlasten von einem Publisher lesen, der H.264-Video veröffentlicht, indem sie die Eigenschaften embeddedMessages
der IVSImageDeviceFrame
-Objekte aus dem IVSImageDevice
des Publishers überprüfen. Erlangen Sie dazu das IVSImageDevice
eines Publishers und beobachten Sie dann jeden Frame über einen Callback an setOnFrameCallback
, wie im folgenden Beispiel gezeigt:
// in an IVSStageRenderer’s stage:participant:didAddStreams: function, after acquiring the new IVSImageStream let imageDevice: IVSImageDevice? = imageStream.device as? IVSImageDevice imageDevice?.setOnFrameCallback { frame in for message in frame.embeddedMessages { if let seiMessage = message as? IVSUserDataUnregisteredSEIMessage { let seiMessageData = seiMessage.data let seiMessageUUID = seiMessage.UUID // interpret the message's data based on the UUID } } }
Fortsetzen der Sitzung im Hintergrund
Wenn die App in den Hintergrund wechselt, können Sie weiterhin auf der Bühne präsent sein, während Sie Remote-Ton hören. Es ist jedoch nicht möglich, das eigene Bild und den eigenen Ton weiterhin zu senden. Sie müssen die Implementierung Ihrer IVSStrategy
aktualisieren, um die Veröffentlichung zu beenden und .audioOnly
zu abonnieren (oder gegebenenfalls .none
):
func stage(_ stage: IVSStage, shouldPublishParticipant participant: IVSParticipantInfo) -> Bool { return false } func stage(_ stage: IVSStage, shouldSubscribeToParticipant participant: IVSParticipantInfo) -> IVSStageSubscribeType { return .audioOnly }
Anschließend rufen Sie stage.refreshStrategy()
auf.
Mehrschichtige Kodierung mit Simulcast
Bei der mehrschichtigen Kodierung mit Simulcast handelt es sich um ein Feature für IVS-Echtzeit-Streaming, mit dessen Hilfe Publisher mehrere Videoschichten unterschiedlicher Qualität senden können. Subscriber können diese Schichten dynamisch oder manuell ändern. Das Feature wird im Dokument Streaming-Optimierungen ausführlicher beschrieben.
Konfigurieren mehrschichtiger Kodierung (Publisher)
Um als Publisher die mehrschichtige Kodierung mit Simulcast zu aktivieren, fügen Sie dem IVSLocalStageStream
bei der Instanziierung die folgende Konfiguration hinzu:
// Enable Simulcast let config = IVSLocalStageStreamVideoConfiguration() config.simulcast.enabled = true let cameraStream = IVSLocalStageStream(device: camera, configuration: config) // Other Stage implementation code
Je nach der in der Videokonfiguration eingestellten Auflösung wird eine festgelegte Anzahl von Schichten kodiert und gesendet, wie im Abschnitt Standardmäßige Schichten, Qualitäten und Bildraten von Streaming-Optimierungen definiert.
Konfigurieren mehrschichtiger Kodierung (Subscriber)
Subscriber müssen nichts unternehmen, um die mehrschichtige Kodierung zu aktivieren. Wenn ein Publisher Simulcast-Schichten sendet, passt sich der Server standardmäßig dynamisch den Schichten an, um je nach Gerät und Netzwerkbedingungen des Subscribers die optimale Qualität auszuwählen.
Alternativ gibt es mehrere nachfolgend beschriebene Optionen, um explizite Schichten auszuwählen, die der Publisher sendet.
Option 1: Einstellung für die Qualität der Anfangsschicht
Mit der Strategie subscribeConfiguration
können Sie auswählen, welche Anfangsschicht Sie als Subscriber erhalten möchten:
func stage(_ stage: IVSStage, subscribeConfigurationForParticipant participant: IVSParticipantInfo) -> IVSSubscribeConfiguration { let config = IVSSubscribeConfiguration() config.simulcast.initialLayerPreference = .lowestQuality return config }
Standardmäßig wird Subscribern zunächst immer die Schicht mit der niedrigsten Qualität gesendet. Nach und nach wird die Qualität gesteigert, bis die Schicht mit der höchsten Qualität erreicht ist. Das optimiert den Bandbreitenverbrauch der Endbenutzer, verkürzt die Zeit bis zum Abspielen des Videos und verringert das anfängliche Einfrieren von Videos bei Benutzern in Netzwerken mit geringerer Bandbreite.
Folgende Optionen sind für InitialLayerPreference
verfügbar:
lowestQuality
– Der Server stellt zuerst die Videoschicht mit der niedrigsten Qualität bereit. Dadurch werden der Bandbreitenverbrauch und die Zeit bis zum Abspielen von Medien optimiert. Die Qualität ist definiert als die Kombination aus Größe, Bitrate und Bildrate des Videos. Beispielsweise weisen 720p-Videos eine geringere Qualität auf als 1080p-Videos.highestQuality
– Der Server stellt zuerst die Videoschicht mit der höchsten Qualität bereit. Das optimiert die Qualität, kann aber die Zeit bis zum Abspielen von Medien verlängern. Die Qualität ist definiert als die Kombination aus Größe, Bitrate und Bildrate des Videos. Beispielsweise weisen 1080p-Videos eine höhere Qualität auf als 720p-Videos.
Option 2: Bevorzugte Schicht für Streams
Sobald ein Stream gestartet wurde, können Sie die Strategiemethode preferredLayerForStream
nutzen. Diese Strategiemethode legt den Teilnehmer und die Stream-Informationen offen.
Die Strategiemethode kann mit folgenden Elementen zurückgegeben werden:
dem Schichtobjekt direkt, basierend auf der Rückgabe von
IVSRemoteStageStream.layers
null, was bedeutet, dass keine Schicht ausgewählt werden sollte und eine dynamische Anpassung bevorzugt wird
Bei der folgenden Strategie wählen die Benutzer beispielsweise immer die Videoschicht mit der niedrigsten verfügbaren Qualität aus:
func stage(_ stage: IVSStage, participant: IVSParticipantInfo, preferredLayerFor stream: IVSRemoteStageStream) -> IVSRemoteStageStreamLayer? { return stream.lowestQualityLayer }
Um die Schichtauswahl zurückzusetzen und zur dynamischen Anpassung zurückzukehren, geben Sie in der Strategie null oder undefiniert zurück. In diesem Beispiel ist appState
eine Dummy-Variable, die den möglichen Anwendungsstatus darstellt.
func stage(_ stage: IVSStage, participant: IVSParticipantInfo, preferredLayerFor stream: IVSRemoteStageStream) -> IVSRemoteStageStreamLayer? { If appState.isAutoMode { return nil } else { return appState.layerChoice } }
Option 3: Helferobjekte für RemoteStageStream-Schicht
IVSRemoteStageStream
weist mehrere Helferobjekte auf, mit deren Hilfe Entscheidungen über die Schichtauswahl getroffen und Endbenutzern die entsprechende Auswahl angezeigt werden kann:
-
Schichtereignisse – Neben
IVSStageRenderer
verfügt derIVSRemoteStageStreamDelegate
über Ereignisse, die Änderungen bei der Schicht- und Simulcast-Anpassung kommunizieren:-
func stream(_ stream: IVSRemoteStageStream, didChangeAdaption adaption: Bool)
-
func stream(_ stream: IVSRemoteStageStream, didChange layers: [IVSRemoteStageStreamLayer])
func stream(_ stream: IVSRemoteStageStream, didSelect layer: IVSRemoteStageStreamLayer?, reason: IVSRemoteStageStream.LayerSelectedReason)
-
-
Schichtmethoden –
IVSRemoteStageStream
verfügt über mehrere Helfermethoden, mit denen Informationen über den Stream und die präsentierten Schichten abgerufen werden können. Diese Methoden sind sowohl für den in der StrategiepreferredLayerForStream
bereitgestellten Remote-Stream als auch für Remote-Streams verfügbar, die überfunc stage(_ stage: IVSStage, participant: IVSParticipantInfo, didAdd streams: [IVSStageStream])
verfügbar gemacht werden.stream.layers
stream.selectedLayer
stream.lowestQualityLayer
stream.highestQualityLayer
stream.layers(with: IVSRemoteStageStreamLayerConstraints)
Einzelheiten finden Sie im Abschnitt zur Klasse IVSRemoteStageStream
in der SDK-Referenzdokumentation
Übertragung der Stage auf einen IVS-Kanal
Zum Übertragen einer Bühne erstellen Sie eine separate IVSBroadcastSession
und folgen Sie dann den oben beschriebenen üblichen Anweisungen für die Übertragung mit dem SDK. Die Eigenschaft device
für IVSStageStream
ist entweder ein IVSImageDevice
oder ein IVSAudioDevice
, wie im obigen Snippet veranschaulicht. Diese können mit dem IVSBroadcastSession.mixer
verbunden werden, um die gesamte Bühne in einem individuell anpassbaren Layout zu übertragen.
Optional können Sie eine Stage zusammenstellen und sie auf einen IVS-Kanal mit niedriger Latenz übertragen, um ein größeres Publikum zu erreichen. Sehen Sie Aktivierung mehrerer Hosts in einem Amazon-IVS-Stream im Benutzerhandbuch für IVS-Streaming mit niedriger Latenz.