SDK di trasmissione IVS: guida al mixer | Streaming a bassa latenza
Il mixer è un'unità di elaborazione audio e video che prende più sorgenti di ingresso e genera una singola uscita. È una potente funzionalità che consente di definire e gestire più elementi sullo schermo (video) e tracce audio. È possibile combinare video e audio da più sorgenti come fotocamere, microfoni, catture dello schermo e audio e video generati dall'app. Puoi utilizzare le transizioni per spostare queste sorgenti nel video che trasmetti in streaming su Amazon IVS e aggiungerle e rimuoverle nel corso del flusso.
Per accedere al mixer, chiama:
BroadcastSession.getMixer()
su Android
IVSBroadcastSession.mixer
su iOS
Terminologia
Termine | Descrizione |
---|---|
Rilegatura |
Per associare un dispositivo di input a uno slot, il dispositivo deve essere collegato allo slot del mixer. Questo avviene con il metodo |
Canvas |
L'estensione di visualizzazione del video definito nella tua configurazione |
Dispositivo |
Un componente hardware o software che produce input audio o immagine nel |
Descrittore del dispositivo |
Struttura con informazioni su un dispositivo di input, ad esempio tipo, indirizzo di sistema, nome intuitivo leggibile dall'uomo e posizione fisica sul dispositivo mobile. Queste informazioni ti consentono di decidere se utilizzare il dispositivo di riferimento e consentono ad Amazon IVS di accedervi. |
Slot |
Un container che definisce la posizione di un elemento visivo sullo schermo e le proprietà di una traccia audio nel mix audio. Un mixer può essere configurato con zero o più slot. Agli slot viene assegnato un nome stringa che può essere utilizzato per associare i dispositivi ed eseguire transizioni. L'immagine qui sopra mostra quattro slot:
Dopo aver configurato una sessione, puoi aggiungere e rimuovere gli slot con i metodi del mixer |
Transition |
Per spostare uno slot in una nuova posizione o modificarne alcune proprietà, utilizza
|
Proprietà tela
Le proprietà della tela sono impostate in base al BroadcastConfiguration
che fornisci quando crei il BroadcastSession
. La tela è influenzata da diverse proprietà nelle strutture Audio
e Video
:
Nome | Tipo | Descrizione |
---|---|---|
|
Numero intero |
Numero di canali di output dal mixer audio. Valori validi: 1, 2. Il canale 1 è audio mono mentre il canale 2 è audio stereo. Default: 2 |
|
Frequenza di campionatura audio |
Il numero di campioni audio al secondo dal mixer audio. Questo valore deve essere almeno il doppio della frequenza più alta del segnale audio. Le persone possono sentire fino a circa 20 kHz, quindi in genere bastano 44,1 kHz e 48 kHz. Default: 48 kHz. |
|
AspectMode |
La modalità di proporzione di default per gli slot. Valori validi:
|
|
Vec2 |
Dimensioni della tela video. |
|
Numero intero |
Il numero di fotogrammi di destinazione al secondo per la tela. In media questo valore dovrebbe essere raggiunto, ma il sistema potrebbe perdere frame in determinate circostanze (ad esempio, con carico elevato della CPU o congestione della rete). |
Proprietà dello slot
Gli slot hanno diverse proprietà configurabili che è possibile utilizzare per personalizzare le scene e le animazioni. Qualsiasi valore che sia Float o Vector viene animato utilizzando l'interpolazione lineare per transizioni con una durata superiore a 0 secondi.
Nome | Tipo | Descrizione |
---|---|---|
|
AspectMode |
La modalità proporzioni per qualsiasi immagine renderizzata nello slot. Valori validi:
Default: come la tela |
|
Vec 4 |
Il colore di riempimento da utilizzare con Aspect Fit quando le proporzioni dello slot e dell'immagine non corrispondono. Il formato è (rosso, verde, blu, alfa). Valore valido (per ciascun canale): 0 - 1. Default: (0, 0, 0, 0). |
|
Float |
Guadagno audio. Questo è un moltiplicatore, quindi qualsiasi valore maggiore di 1 aumenta il guadagno e qualsiasi valore minore di 1 lo diminuisce. Valori validi: 0 - 2. Default: 1. |
|
Booleano |
Se true (VERO), usa il valore |
|
Booleano |
Se true (VERO), la dimensione dello slot viene regolata in modo che sia uguale alla dimensione della tela e la sua posizione è impostata su (0, 0). Se si imposta la proprietà |
|
Stringa |
Nome dello slot. Viene utilizzato per fare riferimento allo slot per le associazioni e le transizioni. Default: |
|
Vec2 |
Posizione dello slot (in pixel) rispetto all'angolo superiore sinistro della tela. Anche l'origine dello slot è in alto a sinistra. |
|
DeviceType |
Tipo di dispositivo di ingresso audio preferito. Se questo slot non è associato e un dispositivo audio del tipo specificato è collegato alla sessione, il dispositivo si associa automaticamente a questo slot. Valori validi:
|
|
DeviceType |
Dispositivo di ingresso video preferito. Se questo slot non è associato e un dispositivo video del tipo specificato è collegato alla sessione, il dispositivo si associa automaticamente a questo slot. Valori validi:
|
|
Vec2 |
Dimensioni dello slot, in pixel. L'impostazione di questo valore imposta anche |
|
Float |
Trasparenza dello slot. Questo è un fattore moltiplicativo con qualsiasi valore alfa nell'immagine. L'opacità è 1 - |
|
Float |
Ordinamento relativo degli slot. Gli slot con valori |
Configurazione di una sessione di trasmissione per il mixaggio
Qui creiamo una scena simile a quella all'inizio di questa guida, con tre elementi sullo schermo:
-
Slot in basso a sinistra per una fotocamera.
-
Slot in basso a destra per una sovrapposizione del logo.
-
Slot in alto a destra per un filmato.
Nota che l'origine della tela è l'angolo in alto a sinistra e questa è la stessa per gli slot. Quindi, posizionando uno slot in (0, 0) sarà posizionato nell'angolo in alto a sinistra con l'intero slot visibile.
iOS
let config = IVSBroadcastConfiguration() try config.video.setSize(CGSize(width: 1280, height: 720)) try config.video.setTargetFramerate(60) config.video.enableTransparency = true // Bottom Left var cameraSlot = IVSMixerSlotConfiguration() cameraSlot.size = CGSize(width: 320, height: 180) cameraSlot.position = CGPoint(x: 20, y: 1280 - 200) cameraSlot.preferredVideoInput = .camera cameraSlot.preferredAudioInput = .microphone cameraSlot.matchCanvasAspectMode = false cameraSlot.zIndex = 2 try cameraSlot.setName("camera") // Top Right var streamSlot = IVSMixerSlotConfiguration() streamSlot.size = CGSize(width: 640, height: 320) streamSlot.position = CGPoint(x: 1280 - 660, y: 20) streamSlot.preferredVideoInput = .userImage streamSlot.preferredAudioInput = .userAudio streamSlot.matchCanvasAspectMode = false streamSlot.zIndex = 1 try streamSlot.setName("stream") // Bottom Right var logoSlot = IVSMixerSlotConfiguration() logoSlot.size = CGSize(width: 320, height: 180) logoSlot.position = CGPoint(x: 1280 - 340, y: 720 - 200) logoSlot.preferredVideoInput = .userImage logoSlot.preferredAudioInput = .unknown logoSlot.matchCanvasAspectMode = false logoSlot.zIndex = 3 try logoSlot.setTransparency(0.7) try logoSlot.setName("logo") config.mixer.slots = [ cameraSlot, streamSlot, logoSlot ]
Android
// Bottom Left val cameraSlot = BroadcastConfiguration.Mixer.Slot.with { s -> s.setSize(320, 180) s.position = BroadcastConfiguration.Vec2(20, 1280 - 200) s.preferredVideoInput = Device.Descriptor.DeviceType.CAMERA s.preferredAudioInput = Device.Descriptor.DeviceType.MICROPHONE s.matchCanvasAspectMode = false s.zIndex = 2 s.name = "camera" s } // Top Right val streamSlot = BroadcastConfiguration.Mixer.Slot.with { s -> s.setSize(640, 320) s.position = BroadcastConfiguration.Vec2(1280 - 660, 20) s.preferredVideoInput = Device.Descriptor.DeviceType.USER_IMAGE s.preferredAudioInput = Device.Descriptor.DeviceType.USER_AUDIO s.matchCanvasAspectMode = false s.zIndex = 1 s.name = "stream" s } // Bottom Right val logoSlot = BroadcastConfiguration.Mixer.Slot.with { s -> s.setSize(320, 180) s.position = BroadcastConfiguration.Vec2(1280 - 340, 720 - 200) s.preferredVideoInput = Device.Descriptor.DeviceType.USER_IMAGE s.preferredAudioInput = Device.Descriptor.DeviceType.UNKNOWN s.matchCanvasAspectMode = false s.zIndex = 3 s.name = "logo" s.transparency = 0.7 s } val config = BroadcastConfiguration.with { c -> c.mixer.slots = listOf(cameraSlot, streamSlot, logoSlot) c.video.targetFramerate = 60 c.video.setSize(1280, 720) c }
Aggiunta di slot
Una volta creato un BroadcastSession
con la tua configurazione, potrai aggiungere e rimuovere gli slot dal mixer. Ora, aggiungiamo al mixer una grande slot in background per un'immagine.
iOS
// Background. We will use most of the defaults for this slot. var backgroundSlot = IVSMixerSlotConfiguration() backgroundSlot.preferredVideoInput = .userImage backgroundSlot.preferredAudioInput = .unknown backgroundSlot.matchCanvasAspectMode = false try backgroundSlot.setName("background") session.mixer.addSlot(backgroundSlot)
Android
// Background. We will use most of the defaults for this slot. val backgroundSlot = BroadcastConfiguration.Mixer.Slot.with { s -> s.preferredVideoInput = Device.Descriptor.DeviceType.USER_IMAGE s.preferredAudioInput = Device.Descriptor.DeviceType.UNKNOWN s.matchCanvasAspectMode = false s.name = "background" s } session.mixer.addSlot(backgroundSlot)
Rimozione degli slot
Per rimuovere uno slot, chiama BroadcastSession.Mixer.removeSlot
con il nome dello slot da rimuovere. Tutti i dispositivi collegati a quello slot saranno automaticamente non associati, quindi se si desidera continuare a utilizzarli sarà necessario ricollegarli a slot diversi.
Animazioni con transizioni
Il metodo di transizione del mixer sostituisce la configurazione di uno slot con una nuova configurazione. Questa sostituzione può essere animata nel tempo impostando una durata superiore a 0, in secondi.
Quali proprietà possono essere animate?
Non tutte le proprietà nella struttura dello slot possono essere animate. Qualsiasi proprietà basata su tipi Float può essere animata; altre proprietà hanno effetto all'inizio o alla fine dell'animazione.
Nome | Può essere animato? | Punto d'impatto |
---|---|---|
|
No |
End |
|
Sì |
Interpolato |
|
Sì |
Interpolato |
|
No |
Start (Avvio) |
|
No |
Start (Avvio) |
Nota: non è possibile modificare il nome dello slot. |
No |
N/D |
|
Sì |
Interpolato |
|
No |
End |
|
No |
End |
|
Sì |
Interpolato |
|
Sì |
Interpolato |
Nota: |
Sì |
Sconosciuto |
Esempi semplici
Di seguito sono riportati esempi di acquisizione di una fotocamera a schermo intero utilizzando la configurazione definita in precedenza in Configurazione di una sessione di trasmissione per il mixaggio. Questo è animato per 0,5 secondi.
iOS
// Bottom Left var bigCameraSlot = cameraSlot bigCameraSlot.size = CGSize(width: 1280, height: 720) bigCameraSlot.position = CGPoint(x: 0, y: 0) session.mixer.transition("camera", bigCameraSlot, 0.5) { println("animation completed!") }
Android
// Bottom Left val bigCameraSlot = cameraSlot.changing { s -> s.setSize(1280, 720) s.position = BroadcastConfiguration.Vec2(0, 0) s } session.mixer.transition("camera", bigCameraSlot, 0.5) { print("animation completed!") }
Mirroring della trasmissione
Per eseguire il mirroring di un dispositivo immagine collegato nella trasmissione in questa direzione... | Usa un valore negativo per... |
---|---|
Orizzontalmente |
Larghezza dello slot |
Verticalmente |
Altezza dello slot |
Sia orizzontalmente che verticalmente |
Larghezza e altezza dello slot |
La posizione dovrà essere regolata dello stesso valore per mettere lo slot nella posizione corretta quando viene eseguito il mirroring.
Di seguito sono riportati alcuni esempi di mirroring della trasmissione in orizzontale e in verticale.
iOS
Mirroring orizzontale:
var cameraSlot = IVSMixerSlotConfiguration cameraSlot.size = CGSize(width: -320, height: 720) // Add 320 to position x since our width is -320 cameraSlot.position = CGPoint(x: 320, y: 0)
Mirroring verticale:
var cameraSlot = IVSMixerSlotConfiguration cameraSlot.size = CGSize(width: 320, height: -720) // Add 720 to position y since our height is -720 cameraSlot.position = CGPoint(x: 0, y: 720)
Android
Mirroring orizzontale:
cameraSlot = BroadcastConfiguration.Mixer.Slot.with { it.size = BroadcastConfiguration.Vec2(-320f, 180f) // Add 320f to position x since our width is -320f it.position = BroadcastConfiguration.Vec2(320f, 0f) return@with it }
Mirroring verticale:
cameraSlot = BroadcastConfiguration.Mixer.Slot.with { it.size = BroadcastConfiguration.Vec2(320f, -180f) // Add 180f to position y since our height is -180f it.position = BroadcastConfiguration.Vec2(0f, 180f) return@with it }
Nota: questo mirroring è diverso dal metodo setMirrored
su ImagePreviewView
(Android) e IVSImagePreviewView
(iOS). Questo metodo influisce solo sulla visualizzazione dell'anteprima locale sul dispositivo e non ha alcun impatto sulla trasmissione.