SDK di trasmissione IVS: Dispositivi misti
I dispositivi misti sono dispositivi audio e video che prendono più sorgenti di ingresso e generano una singola uscita. I dispositivi di mixaggio sono 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. È possibile utilizzare le transizioni per spostare queste sorgenti nel video trasmesso in streaming su IVS, nonché aggiungere e rimuovere sorgenti durante lo streaming.
I dispositivi misti sono disponibili nelle versioni audio e immagine. Per creare un dispositivo con immagini misto, chiamare:
DeviceDiscovery.createMixedImageDevice()
su Android
IVSDeviceDiscovery.createMixedImageDevice()
su iOS
Il dispositivo restituito può essere collegato a una BroadcastSession
(streaming a bassa latenza) o Stage
(streaming in tempo reale), come qualsiasi altro dispositivo.
Terminologia

Termine | Descrizione |
---|---|
Dispositivo |
Un componente hardware o software che produce input audio o immagine. Esempi di dispositivi sono microfoni, fotocamere, cuffie Bluetooth e dispositivi virtuali come catture di schermo o ingressi di immagini personalizzate. |
Dispositivi misti |
Un I dispositivi misti sono disponibili nelle versioni audio e immagine. |
Configurazione del dispositivo misto |
Un oggetto di configurazione per il dispositivo misto. Per i dispositivi con immagini miste, questa opzione configura proprietà quali dimensioni e framerate. Per i dispositivi audio misti, configura il numero di canali. |
Origine |
Un container che definisce la posizione di un elemento visivo sullo schermo e le proprietà di una traccia audio nel mix audio. Un dispositivo misto può essere configurato con zero o più sorgenti. Alle origini viene assegnata una configurazione che influisce sul modo in cui vengono utilizzati i contenuti multimediali della sorgente. L'immagine qui sopra mostra quattro sorgenti di immagini:
|
Configurazione della sorgente |
Un oggetto di configurazione per la sorgente che entra in un dispositivo misto. Gli oggetti di configurazione completi sono descritti di seguito. |
Transition |
Per spostare uno slot in una nuova posizione o modificarne alcune proprietà, utilizza
|
Dispositivo audio misto
Configurazione
MixedAudioDeviceConfiguration
su Android
IVSMixedAudioDeviceConfiguration
su iOS
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 |
Configurazione della sorgente
MixedAudioDeviceSourceConfiguration
su Android
IVSMixedAudioDeviceSourceConfiguration
su iOS
Nome | Tipo | Descrizione |
---|---|---|
|
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. |
Dispositivo di immagine
Configurazione
MixedImageDeviceConfiguration
su Android
IVSMixedImageDeviceConfiguration
su iOS
Nome | Tipo | Descrizione |
---|---|---|
|
Vec2 |
Dimensioni della tela video. |
|
Numero intero |
Il numero di frame di destinazione al secondo per il dispositivo misto. In media questo valore dovrebbe essere raggiunto, ma il sistema potrebbe perdere frame in determinate circostanze (ad esempio, con carico elevato della CPU o della GPU). |
|
Booleano |
Ciò consente la fusione utilizzando la proprietà |
Configurazione della sorgente
MixedImageDeviceSourceConfiguration
su Android
IVSMixedImageDeviceSourceConfiguration
su iOS
Nome | Tipo | Descrizione |
---|---|---|
|
Float |
L'alfa dello slot. Questo è un fattore moltiplicativo con qualsiasi valore alfa nell'immagine. Valori validi: 0-1, dove 0 è completamente trasparente e 1 è completamente opaco. Default: 1. |
|
AspectMode | La modalità proporzioni per qualsiasi immagine renderizzata nello slot. Valori validi:
Impostazione predefinita: |
|
Vec 4 |
Il colore di riempimento da utilizzare con |
|
Vec2 |
Posizione dello slot (in pixel) rispetto all'angolo superiore sinistro della tela. Anche l'origine dello slot è in alto a sinistra. |
|
Vec2 |
Dimensioni dello slot, in pixel. L'impostazione di questo valore imposta anche |
|
Float |
Ordinamento relativo degli slot. Gli slot con valori |
Creazione e configurazione di un dispositivo di immagini misto

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 deviceDiscovery = IVSDeviceDiscovery() let mixedImageConfig = IVSMixedImageDeviceConfiguration() mixedImageConfig.size = CGSize(width: 1280, height: 720) try mixedImageConfig.setTargetFramerate(60) mixedImageConfig.isTransparencyEnabled = true let mixedImageDevice = deviceDiscovery.createMixedImageDevice(with: mixedImageConfig) // Bottom Left let cameraConfig = IVSMixedImageDeviceSourceConfiguration() cameraConfig.size = CGSize(width: 320, height: 180) cameraConfig.position = CGPoint(x: 20, y: mixedImageConfig.size.height - cameraConfig.size.height - 20) cameraConfig.zIndex = 2 let camera = deviceDiscovery.listLocalDevices().first(where: { $0 is IVSCamera }) as? IVSCamera let cameraSource = IVSMixedImageDeviceSource(configuration: cameraConfig, device: camera) mixedImageDevice.add(cameraSource) // Top Right let streamConfig = IVSMixedImageDeviceSourceConfiguration() streamConfig.size = CGSize(width: 640, height: 320) streamConfig.position = CGPoint(x: mixedImageConfig.size.width - streamConfig.size.width - 20, y: 20) streamConfig.zIndex = 1 let streamDevice = deviceDiscovery.createImageSource(withName: "stream") let streamSource = IVSMixedImageDeviceSource(configuration: streamConfig, device: streamDevice) mixedImageDevice.add(streamSource) // Bottom Right let logoConfig = IVSMixedImageDeviceSourceConfiguration() logoConfig.size = CGSize(width: 320, height: 180) logoConfig.position = CGPoint(x: mixedImageConfig.size.width - logoConfig.size.width - 20, y: mixedImageConfig.size.height - logoConfig.size.height - 20) logoConfig.zIndex = 3 let logoDevice = deviceDiscovery.createImageSource(withName: "logo") let logoSource = IVSMixedImageDeviceSource(configuration: logoConfig, device: logoDevice) mixedImageDevice.add(logoSource)
Android
val deviceDiscovery = DeviceDiscovery(this /* context */) val mixedImageConfig = MixedImageDeviceConfiguration().apply { setSize(BroadcastConfiguration.Vec2(1280f, 720f)) setTargetFramerate(60) setEnableTransparency(true) } val mixedImageDevice = deviceDiscovery.createMixedImageDevice(mixedImageConfig) // Bottom Left val cameraConfig = MixedImageDeviceSourceConfiguration().apply { setSize(BroadcastConfiguration.Vec2(320f, 180f)) setPosition(BroadcastConfiguration.Vec2(20f, mixedImageConfig.size.y - size.y - 20)) setZIndex(2) } val camera = deviceDiscovery.listLocalDevices().firstNotNullOf { it as? CameraSource } val cameraSource = MixedImageDeviceSource(cameraConfig, camera) mixedImageDevice.addSource(cameraSource) // Top Right val streamConfig = MixedImageDeviceSourceConfiguration().apply { setSize(BroadcastConfiguration.Vec2(640f, 320f)) setPosition(BroadcastConfiguration.Vec2(mixedImageConfig.size.x - size.x - 20, 20f)) setZIndex(1) } val streamDevice = deviceDiscovery.createImageInputSource(streamConfig.size) val streamSource = MixedImageDeviceSource(streamConfig, streamDevice) mixedImageDevice.addSource(streamSource) // Bottom Right val logoConfig = MixedImageDeviceSourceConfiguration().apply { setSize(BroadcastConfiguration.Vec2(320f, 180f)) setPosition(BroadcastConfiguration.Vec2(mixedImageConfig.size.x - size.x - 20, mixedImageConfig.size.y - size.y - 20)) setZIndex(1) } val logoDevice = deviceDiscovery.createImageInputSource(logoConfig.size) val logoSource = MixedImageDeviceSource(logoConfig, logoDevice) mixedImageDevice.addSource(logoSource)
Rimozione delle sorgenti
Per rimuovere una sorgente, chiamare MixedDevice.remove
con l'oggetto di Source
che desideri rimuovere.
Animazioni con transizioni
Il metodo di transizione sostituisce la configurazione di una sorgente 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 |
---|---|---|
|
Sì |
Interpolato |
|
Sì |
Interpolato |
|
No |
End |
|
Sì |
Interpolato |
|
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 alto in Creazione e configurazione di un dispositivo di immagini misto. Questo è animato per 0,5 secondi.
iOS
// Continuing the example from above, modifying the existing cameraConfig object. cameraConfig.size = CGSize(width: 1280, height: 720) cameraConfig.position = CGPoint.zero cameraSource.transition(to: cameraConfig, duration: 0.5) { completed in if completed { print("Animation completed") } else { print("Animation interrupted") } }
Android
// Continuing the example from above, modifying the existing cameraConfig object. cameraConfig.setSize(BroadcastConfiguration.Vec2(1280f, 720f)) cameraConfig.setPosition(BroadcastConfiguration.Vec2(0f, 0f)) cameraSource.transitionToConfiguration(cameraConfig, 500) { completed -> if (completed) { print("Animation completed") } else { print("Animation interrupted") } }
Mirroring della trasmissione
Per eseguire il mirroring di un dispositivo immagine collegato nella trasmissione in questa direzione... | Usa un valore negativo per... |
---|---|
Orizzontalmente |
La larghezza dello slot |
Verticalmente |
L’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:
let cameraSource = IVSMixedImageDeviceSourceConfiguration() cameraSource.size = CGSize(width: -320, height: 720) // Add 320 to position x since our width is -320 cameraSource.position = CGPoint(x: 320, y: 0)
Mirroring verticale:
let cameraSource = IVSMixedImageDeviceSourceConfiguration() cameraSource.size = CGSize(width: 320, height: -720) // Add 720 to position y since our height is -720 cameraSource.position = CGPoint(x: 0, y: 720)
Android
Mirroring orizzontale:
val cameraConfig = MixedImageDeviceSourceConfiguration().apply { setSize(BroadcastConfiguration.Vec2(-320f, 180f)) // Add 320f to position x since our width is -320f setPosition(BroadcastConfiguration.Vec2(320f, 0f)) }
Mirroring verticale:
val cameraConfig = MixedImageDeviceSourceConfiguration().apply { setSize(BroadcastConfiguration.Vec2(320f, -180f)) // Add 180f to position y since our height is -180f setPosition(BroadcastConfiguration.Vec2(0f, 180f)) }
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.