View a markdown version of this page

Ottimizzazioni dello streaming in tempo reale di IVS - Amazon IVS

Ottimizzazioni dello streaming in tempo reale di IVS

Per garantire agli utenti la migliore esperienza di streaming e visualizzazione di video tramite lo streaming in tempo reale IVS, esistono diversi modi per migliorare o ottimizzare alcune parti dell'esperienza grazie alle funzionalità da noi offerte.

Introduzione

Quando si ottimizza per la qualità dell'esperienza di un utente, è importante considerare l'esperienza desiderata, che può cambiare a seconda dei contenuti che l'utente sta guardando e delle condizioni della rete.

In questa guida ci concentriamo sugli utenti che sono:publisher di flussi o abbonati a flussi e consideriamo le operazioni e le esperienze desiderate di tali utenti.

Gli SDK IVS consentono di configurare il bitrate massimo, il framerate e la risoluzione del flusso. Quando si verifica una congestione della rete per i publisher, l'SDK adatta e riduce automaticamente la qualità video abbassando il bitrate, il framerate e la risoluzione. Su Android e iOS, è possibile selezionare la preferenza di degradazione in caso di congestione. Lo stesso comportamento vale sia che si abiliti la codifica a più livelli con simulcast sia che si mantenga la configurazione predefinita.

Streaming adattivo: codifica a livelli con simulcast

Questa funzionalità è supportata solo nelle seguenti versioni client:

  • iOS e Android 1.18.0 e versioni successive

  • Web 1.12.0 e versioni successive

Quando si utilizzano gli SDK di trasmissione in tempo reale IVS, i publisher codificano più livelli di video e gli abbonati si adattano o passano automaticamente alla qualità più adatta alla loro rete. Questa è detta codifica a livelli con simulcast.

La codifica a livelli con Simulcast è supportata su Android e iOS e sui browser desktop Chrome e Edge (per Windows e macOS). Non supportiamo la codifica a livelli su altri browser.

Nel diagramma seguente, l'host invia tre qualità video (alta, media e bassa). IVS trasmette il video con qualità più alta a ogni spettatore in base alla larghezza di banda disponibile; ciò fornisce un'esperienza ottimale per ogni spettatore. Se la connessione di rete dello spettatore 1 passa da buona a cattiva, IVS inizia automaticamente a inviare un video di qualità inferiore in modo che spettatore 1 possa continuare a guardare lo streaming senza interruzioni (con la migliore qualità possibile).

Usa la codifica a livelli con simulcast per regolare la qualità del video in base alla qualità della connessione di rete dell'utente.

Livelli, qualità e framerate predefiniti

Le qualità e i livelli predefiniti forniti per gli utenti mobili e Web sono i seguenti:

Cellulare (Android, iOS) Web (Chrome)

Livello alto (o personalizzato):

  • Bitrate massimo: 900.000 bps

  • Framerate: 15 fps

Livello alto (o personalizzato):

  • Bitrate massimo: 1.700.000 bps

  • Framerate: 30 fps

Livello intermedio: nessuno (non necessario poiché la differenza tra i bitrate di livello alto e basso su dispositivi mobili è ridotta)

Livello intermedio:

  • Bitrate massimo: 700.000 bps

  • Framerate: 20 fps

Livello basso:

  • Bitrate massimo: 100.000 b/s

  • Framerate: 15 fps

Livello basso:

  • Bitrate massimo: 200.000 bps

  • Framerate: 15 fps

Risoluzione dei livelli

Le risoluzioni dei livelli intermedio e basso vengono automaticamente ridotte rispetto al livello alto per mantenere le stesse proporzioni.

I livelli intermedi e bassi vengono esclusi se le rispettive risoluzioni sono troppo vicine al livello superiore. Ad esempio, se la risoluzione configurata è 320x180, l'SDK non invierà livelli anche a risoluzione inferiore.

La tabella seguente mostra le risoluzioni dei livelli generati per diverse risoluzioni configurate. I valori elencati sono nell'orientamento orizzontale, ma possono essere applicati in senso inverso per i contenuti con orientamento verticale.

Risoluzione dell'input Risoluzioni del livello di output: dispositivi mobili Risoluzioni del livello di output: web

720p (1280x720)

Alto (1280x720)

Basso (320x180)

Alto (1280x720)

Medio (640x360)

Basso (320x180)

540p (960x540)

Alto (960x540)

Basso (320x180)

Alto (960x540)

Basso (320x180)

360p (640x360)

Alto (640x360)

Basso (360x180)

Alto (640x360)

Basso (360x180)

270p (480x270)

Alto (480x270)

Alto (480x270)

180p (320x180)

Alto (320x180)

Alto (320x180)

È possibile calcolare le risoluzioni di input personalizzate non mappate sopra utilizzando il seguente strumento.

Configurazione della codifica a livelli con Simulcast (Publisher)

Per utilizzare la codifica a più livelli con Simulcast, è necessario aver abilitato la funzionalità sul client. Se la si abilita, sarà possibile riscontrare un aumento dell'utilizzo della larghezza di banda di caricamento da parte del publisher, potenzialmente con un minor blocco dei video per gli spettatori.

Android

// Enable Simulcast StageVideoConfiguration config = new StageVideoConfiguration(); config.simulcast.setEnabled(true); ImageLocalStageStream cameraStream = new ImageLocalStageStream(frontCamera, config); // Other Stage implementation code

iOS

// Enable Simulcast let config = IVSLocalStageStreamVideoConfiguration() config.simulcast.enabled = true let cameraStream = IVSLocalStageStream(device: camera, configuration: config) // Other Stage implementation code

App

// Enable Simulcast let cameraStream = new LocalStageStream(cameraDevice, { simulcast: { enabled: true } }) // Other Stage implementation code

Per informazioni dettagliate sulla configurazione dei singoli livelli, consulta "Configurazione della codifica a livelli (Publisher)" in ogni Guida all’SDK di trasmissione per Android, iOS e Web.

Configurazione della codifica a livelli con simulcast (Abbonato)

Per configurare i livelli ricevuti dagli abbonati, consulta le sezioni “Codifica a livelli con Simulcast” nelle guide SDK per lo streaming in tempo reale:

Con la configurazione degli abbonati, è possibile definire InitialLayerPreference. Ciò determina la qualità del video fornita inizialmente, nonché preferredLayerForStream, che a sua volta determina quale livello viene selezionato durante la riproduzione del video. Esistono eventi e metodi di streaming per notificare quando cambiano i livelli, vengono modificati gli adattamenti o viene effettuata una selezione di livelli.

Configurazioni dello streaming

In questa sezione sono descritte altre configurazioni che possono essere impostate per i flussi audio e video.

Modifica del bitrate del flusso

Per modificare il bitrate del flusso video, usa i seguenti esempi di configurazione.

Android

StageVideoConfiguration config = new StageVideoConfiguration(); // Update Max Bitrate to 1.5mbps config.setMaxBitrate(1500000); ImageLocalStageStream cameraStream = new ImageLocalStageStream(frontCamera, config); // Other Stage implementation code

iOS

let config = IVSLocalStageStreamVideoConfiguration(); // Update Max Bitrate to 1.5mbps try! config.setMaxBitrate(1500000); let cameraStream = IVSLocalStageStream(device: camera, configuration: config); // Other Stage implementation code

App

let cameraStream = new LocalStageStream(camera.getVideoTracks()[0], { // Update Max Bitrate to 1.5mbps or 1500kbps maxBitrate: 1500 }) // Other Stage implementation code

Modifica del framerate del flusso video

Per modificare il framerate del flusso video, usa i seguenti esempi di configurazione.

Android

StageVideoConfiguration config = new StageVideoConfiguration(); // Update target framerate to 10fps config.targetFramerate(10); ImageLocalStageStream cameraStream = new ImageLocalStageStream(frontCamera, config); // Other Stage implementation code

iOS

let config = IVSLocalStageStreamVideoConfiguration(); // Update target framerate to 10fps try! config.targetFramerate(10); let cameraStream = IVSLocalStageStream(device: camera, configuration: config); // Other Stage implementation code

App

// Note: On web it is also recommended to configure the framerate of your device from userMedia const camera = await navigator.mediaDevices.getUserMedia({ video: { frameRate: { ideal: 10, max: 10, }, }, }); let cameraStream = new LocalStageStream(camera.getVideoTracks()[0], { // Update Max Framerate to 10fps maxFramerate: 10 }) // Other Stage implementation code

Ottimizzazione del bitrate audio e del supporto stereo

Per modificare le impostazioni bitrate e stereo del flusso audio, usa i seguenti esempi di configurazione.

App

// Note: Disable autoGainControl, echoCancellation, and noiseSuppression when enabling stereo. const camera = await navigator.mediaDevices.getUserMedia({ audio: { autoGainControl: false, echoCancellation: false, noiseSuppression: false }, }); let audioStream = new LocalStageStream(camera.getAudioTracks()[0], { // Optional: Update Max Audio Bitrate to 96Kbps. Default is 64Kbps maxAudioBitrateKbps: 96, // Signal stereo support. Note requires dual channel input source. stereo: true }) // Other Stage implementation code

Android

StageAudioConfiguration config = new StageAudioConfiguration(); // Update Max Bitrate to 96Kbps. Default is 64Kbps. config.setMaxBitrate(96000); AudioLocalStageStream microphoneStream = new AudioLocalStageStream(microphone, config); // Other Stage implementation code

iOS

let config = IVSLocalStageStreamConfiguration(); // Update Max Bitrate to 96Kbps. Default is 64Kbps. try! config.audio.setMaxBitrate(96000); let microphoneStream = IVSLocalStageStream(device: microphone, config: config); // Other Stage implementation code

Modifica del valore MinDelay di jitter-buffer dell'abbonato

Per modificare il ritardo minimo del jitter-buffer per un partecipante a cui ci si sta abbonando, è possibile utilizzare un valore personalizzato di subscribeConfiguration. Il jitter-buffer determina quanti pacchetti vengono memorizzati prima dell'inizio della riproduzione. Il ritardo minimo rappresenta l'obiettivo della quantità minima di dati da archiviare. La modifica del ritardo minimo può aiutare la riproduzione a essere più resiliente in caso di perdita di pacchetti o problemi di connessione.

Il compromesso quando si aumenta la dimensione del jitter-buffer è che aumenta anche il ritardo prima dell'inizio della riproduzione. L'aumento del ritardo minimo offre una maggiore resilienza a scapito del tempo di riproduzione del video. Si noti che l'aumento del ritardo minimo durante la riproduzione ha un effetto simile: la riproduzione si interromperà brevemente per consentire al jitter-buffer di riempirsi.

Se è necessaria una maggiore resilienza, consigliamo di iniziare con un ritardo minimo preimpostato di MEDIUM e di impostare la configurazione di abbonamento prima dell'inizio della riproduzione.

Occorre tenere presente che il ritardo minimo viene applicato solo se un partecipante è solo abbonato. Se un partecipante è a sua volta un publisher, il ritardo minimo non viene applicato. Questo viene fatto per garantire che più publisher possano parlare tra loro senza ulteriori ritardi.

Gli esempi seguenti utilizzano un ritardo minimo preimpostato di MEDIUM. Consulta la documentazione di riferimento dell'SDK per tutti i valori possibili.

App

const strategy = { subscribeConfiguration: (participant) => { return { jitterBuffer: { minDelay: JitterBufferMinDelay.MEDIUM } } // ... other strategy functions }

Android

@Override public SubscribeConfiguration subscribeConfigrationForParticipant(@NonNull Stage stage, @NonNull ParticipantInfo participantInfo) { SubscribeConfiguration config = new SubscribeConfiguration(); config.jitterBuffer.setMinDelay(JitterBufferConfiguration.JitterBufferDelay.MEDIUM()); return config; }

iOS

func stage(_ stage: IVSStage, subscribeConfigurationForParticipant participant: IVSParticipantInfo) -> IVSSubscribeConfiguration { let config = IVSSubscribeConfiguration() try! config.jitterBuffer.setMinDelay(.medium()) return config }

Riduzione dei tempi di visualizzazione video quando si passa da una fase all’altra

Le applicazioni potrebbero consentire agli utenti di fogliare un feed di live streaming. Un utente entra in una fase, passa a un altro flusso, abbandona la fase corrente e si unisce rapidamente a quella successiva. La creazione di una nuova connessione per ogni transizione tra fasi richiede la creazione di una nuova connessione di rete, che può aumentare il tempo di disponibilità del video.

Utilizza RealTimeConnection per mantenere aperta una connessione di rete mentre l’utente naviga nei flussi. Crea la connessione una sola volta, opzionalmente connettila prima dell’accesso alla prima fase e riutilizzala in più fasi. Ogni fase utilizza ancora il proprio token partecipante e mantiene i propri partecipanti, i propri flussi e il proprio ciclo di vita.

Crea e mantieni RealTimeConnection per tutta la durata della sessione di navigazione in un oggetto che sopravviva più a lungo di una singola fase, ad esempio un coordinatore dell’applicazione, un controller di navigazione o un modello di visualizzazione. Non crearla e disconnetterla per ogni transizione tra fasi.

Android

L’esempio seguente aggiunge il ciclo di vita RealTimeConnection al MainViewModel utilizzato nell’esempio Android. Il modello di visualizzazione implementa Stage.Strategy e StageRenderer.

private var realTimeConnection: RealTimeConnection? = null private var stage: Stage? = null private fun setupConnection(connectionToken: String) { try { val connection = RealTimeConnection(getApplication(), connectionToken) // Establish the shared transport before the first Stage join. connection.connect() realTimeConnection = connection } catch (error: BroadcastException) { Log.e("BasicRealTime", "Unable to create the RealTimeConnection", error) } } private fun joinStage(participantToken: String) { val realTimeConnection = realTimeConnection ?: return try { stage?.leave() stage?.release() val stage = Stage( getApplication(), participantToken, realTimeConnection, this ) stage.addRenderer(this) stage.join() this.stage = stage } catch (error: BroadcastException) { Log.e("BasicRealTime", "Unable to join the Stage", error) } } override fun onCleared() { stage?.leave() stage?.release() stage = null realTimeConnection?.disconnect() realTimeConnection?.release() realTimeConnection = null super.onCleared() }

La chiamata a connect() è facoltativa. Se la connessione non è aperta quando entri in una fase, l’SDK la apre automaticamente. Chiama connect() prima di partecipare alla fase successiva per stabilire la connessione in anticipo e ridurre i tempi per la visualizzazione del video. Sebbene l’esempio si connetta a una sola fase per volta, RealTimeConnection può essere collegata a più fasi contemporaneamente.

Chiama release() quando l’applicazione non necessita più di RealTimeConnection. Una volta rilasciata, non può essere riutilizzata.

iOS

L’esempio seguente presuppone che l’applicazione ottenga un token di connessione quando l’utente inizia il flusso in più fasi e ottenga un token partecipante per ogni fase a cui l’utente partecipa.

private var realTimeConnection: IVSRealTimeConnection? private var stage: IVSStage? private func setupConnection(connectionToken: String) throws { let connection = try IVSRealTimeConnection(token: connectionToken) // Establish the shared transport before the first Stage join. try connection.connect() realTimeConnection = connection } private func joinStage(participantToken: String) throws { guard let realTimeConnection else { return } stage?.leave() let stage = try IVSStage( token: participantToken, on: realTimeConnection, strategy: self ) stage.addRenderer(self) try stage.join() self.stage = stage } private func endStageTransitionFlow() { stage?.leave() stage = nil realTimeConnection?.disconnect() realTimeConnection = nil }

La chiamata a connect() è facoltativa. Se la connessione non è aperta quando entri in una fase, l’SDK la apre automaticamente. Chiama connect() prima di partecipare alla fase successiva per stabilire la connessione in anticipo e ridurre i tempi per la visualizzazione del video. Sebbene l’esempio si connetta a una sola fase per volta, una IVSRealTimeConnection può essere collegata a più fasi contemporaneamente.

Mantieni un riferimento forte a IVSRealTimeConnection mentre le fasi lo utilizzano. Chiamando la disconnect(), tutte le fasi che utilizzano la connessione vengono abbandonate.

Ottimizzazioni suggerite

Scenario Raccomandazioni
Streaming con testo o contenuti a movimento lento, come presentazioni o diapositive Usa la codifica a livelli con simulcast oppure configura i flussi con un framerate inferiore.
Streaming con azione o molto movimento Usa la codifica a livelli con simulcast.
Streaming con conversazione o poco movimento Usa la codifica a livelli con simulcast o scegli solo audio (consulta "Iscrizione ai partecipanti" nelle guide per gli SDK di trasmissione dello streaming in tempo reale: Web, Android e iOS).
Utenti che trasmettono in streaming con dati limitati Utilizza la codifica a livelli con simulcast o, se desideri ridurre l'utilizzo dei dati per tutti, configura un framerate inferiore e riduci il bitrate manualmente.
Gli utenti navigano in un feed di live streaming e passano rapidamente da una fase all’altra Riutilizza una RealTimeConnection per la sessione di navigazione. Chiama connect() prima di partecipare alla prima fase per stabilire la connessione in anticipo.