Kit SDK de diffusion IVS : appareils mixtes
Les appareils mixtes sont des appareils audio et vidéo qui acceptent plusieurs sources d’entrée et génèrent une seule sortie. Les appareils de mixage sont une fonctionnalité puissante qui vous permet de définir et de gérer plusieurs éléments à l’écran (vidéo) et pistes audio. Combinez de la vidéo et de l'audio provenant de sources multiples telles que des caméras, des microphones, des captures d'écran, ainsi que de l'audio et de la vidéo générés par votre application. Vous pouvez utiliser des transitions pour déplacer ces sources dans la vidéo que vous diffusez vers IVS, et ajouter ou supprimer des sources en cours de diffusion.
Les appareils mixtes se déclinent en versions image et audio. Pour créer un appareil d’image mixte, appelez :
DeviceDiscovery.createMixedImageDevice()
sur Android
IVSDeviceDiscovery.createMixedImageDevice()
sur iOS
L’appareil renvoyé peut être associé à un BroadcastSession
(diffusion à faible latence) ou Stage
(diffusion en temps réel), comme tout autre appareil.
Terminologie

Terme | Description |
---|---|
Appareil |
Un composant matériel ou logiciel qui produit une entrée audio ou image. Les microphones, les caméras, les casques Bluetooth et les périphériques virtuels tels que les captures d'écran ou les entrées d'images personnalisées sont des exemples d'appareils. |
Appareil mixte |
Un Les appareils mixtes sont disponibles en version audio ou image. |
Configuration d’un appareil mixte |
Un objet de configuration pour l’appareil mixte. Pour les appareils d’image mixtes, cela permet de configurer des propriétés telles que les dimensions et la fréquence d’images. Pour les appareils d’audio mixtes, cela permet de configurer le nombre de canaux. |
Source |
Un conteneur qui définit la position d'un élément visuel à l'écran et les propriétés d'une piste audio dans le mixage audio. Un appareil mixte peut être configuré avec zéro ou plusieurs sources. Les sources reçoivent une configuration qui affecte la manière dont les médias de la source sont utilisés. L’image ci-dessus montre quatre sources d’image :
|
Configuration de la source |
Un objet de configuration pour la source entrant dans un appareil mixte. Les objets de configuration complets sont décrits ci-dessous. |
Transition |
Pour déplacer un slot vers une nouvelle position ou modifier certaines de ses propriétés, utilisez
|
Appareil d’audio mixte
Configuration
MixedAudioDeviceConfiguration
sur Android
IVSMixedAudioDeviceConfiguration
sur iOS
Nom | Type | Description |
---|---|---|
|
Entier |
Nombre de canaux de sortie du mixage audio. Valeurs valides : 1, 2. 1 est un audio mono ; 2, un audio stéréo. Par défaut : 2. |
Configuration de la source
MixedAudioDeviceSourceConfiguration
sur Android
IVSMixedAudioDeviceSourceConfiguration
sur iOS
Nom | Type | Description |
---|---|---|
|
Float |
Gain audio. Il s'agit d'un multiplicateur, donc toute valeur supérieure à 1 augmente le gain ; toute valeur inférieure à 1 le diminue. Valeurs valides : 0 à 2. Par défaut : 1. |
Appareil d’image mixte
Configuration
MixedImageDeviceConfiguration
sur Android
IVSMixedImageDeviceConfiguration
sur iOS
Nom | Type | Description |
---|---|---|
|
Vec2 |
Taille du canevas de la vidéo. |
|
Entier |
Nombre d’images cibles par seconde pour l’appareil mixte. En moyenne, cette valeur doit être respectée, mais le système peut sauter des images dans certaines circonstances (par exemple, en cas de charge élevée du processeur ou du processeur graphique). |
|
Booléen |
Cela permet le mélange à l’aide de la propriété |
Configuration de la source
MixedImageDeviceSourceConfiguration
sur Android
IVSMixedImageDeviceSourceConfiguration
sur iOS
Nom | Type | Description |
---|---|---|
|
Float |
Alpha du slot. Il est multiplicative avec toutes les valeurs alpha de l'image. Valeurs valides : 0-1. 0 correspond à une transparence totale et 1 à une opacité totale. Par défaut : 1. |
|
AspectMode | Mode de rapport d'aspect pour toute image rendue dans le slot. Valeurs valides :
Par défaut : |
|
Vec4 |
Couleur de remplissage à utiliser avec |
|
Vec2 |
Position du slot (en pixels) par rapport à l'angle supérieur gauche du canevas. L'origine du slot est également en haut à gauche. |
|
Vec2 |
Taille du slot, en pixels. La définition de cette valeur définit également |
|
Float |
Ordre relatif des slots. Les slots avec des valeurs plus |
Création et configuration d’un appareil d’image mixte

Ici, nous créons une scène similaire à celle du début de ce guide, avec trois éléments à l'écran :
-
Slot en bas à gauche pour une caméra.
-
Slot en bas à droite pour une superposition de logo.
-
Slot en haut à droite pour un film.
Notez que l'origine du canevas est le coin supérieur gauche et c'est la même chose pour les slots. Par conséquent, le positionnement d'un slot à (0, 0) le place dans le coin supérieur gauche avec l'ensemble du slot visible.
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)
Suppression de sources
Pour supprimer une source, appelez MixedDevice.remove
avec l’objet Source
que vous voulez supprimer.
animations avec Transitions
La méthode de transition remplace la configuration d’une source par une nouvelle configuration. Ce remplacement peut être animé au fil du temps en définissant une durée supérieure à 0, en secondes.
Quelles propriétés peuvent être animées ?
Toutes les propriétés de la structure du slot ne peuvent être animées. Toutes les propriétés basées sur des types Float peuvent être animées ; d’autres propriétés prennent effet au démarrage ou à la fin de l’animation.
Nom | Peut-on l’animer ? | Point d'impact |
---|---|---|
|
Oui |
Interpolé |
|
Oui |
Interpolé |
|
Non |
Fin |
|
Oui |
Interpolé |
|
Oui |
Interpolé |
|
Oui |
Interpolé |
Remarque : Le |
Oui |
Je ne sais pas |
Exemples simples
Vous trouverez ci-dessous des exemples de prise de contrôle de la caméra en plein écran à l’aide de la configuration définie ci-dessus dans Création et configuration d’un appareil d’image mixte. Il est animé pendant 0,5 seconde.
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") } }
Mise en miroir de la diffusion
Pour mettre en miroir un périphérique d'image connecté lors de la diffusion dans cette direction... | Utilisez une valeur négative pour … |
---|---|
Horizontalement |
La largeur du slot |
Verticalement |
La hauteur du slot |
Aussi bien horizontalement que verticalement |
La largeur et la hauteur de la fente |
La position devra être ajustée selon la même valeur, afin de placer la fente dans la bonne position lors de la mise en miroir.
Vous trouverez ci-dessous des exemples de mise en miroir de la diffusion horizontalement et verticalement.
iOS
Mise en miroir horizontale :
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)
Mise en miroir horizontale 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
Mise en miroir horizontale :
val cameraConfig = MixedImageDeviceSourceConfiguration().apply { setSize(BroadcastConfiguration.Vec2(-320f, 180f)) // Add 320f to position x since our width is -320f setPosition(BroadcastConfiguration.Vec2(320f, 0f)) }
Mise en miroir horizontale 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)) }
Remarque : cette mise en miroir est différente de la méthode setMirrored
utilisée sur ImagePreviewView
(Android) et IVSImagePreviewView
(iOS). Cette méthode n'affecte que la vue d'aperçu locale sur l'appareil et n'a aucun impact sur la diffusion.