SDK de transmisión de IVS: dispositivos mixtos
Los dispositivos mixtos son dispositivos de audio y vídeo que reciben varias fuentes de entrada y generan una única salida. Los dispositivos mixtos son una potente característica que le permite definir y administrar varios elementos en pantalla (video) y pistas de audio. Puede combinar video y audio de varias fuentes, como cámaras, micrófonos, grabadoras de pantalla y audio y video generados por su aplicación. Puede utilizar transiciones para mover estas fuentes al video que transmite a IVS y agregarlas y eliminarlas a mitad de la transmisión.
Los dispositivos mixtos vienen en formatos de imagen y audio. Para crear un dispositivo de imagen mixtos, llame a:
DeviceDiscovery.createMixedImageDevice()
en Android
IVSDeviceDiscovery.createMixedImageDevice()
en iOS
El dispositivo devuelto se puede conectar a una BroadcastSession
(transmisión de baja latencia) o Stage
(transmisión en tiempo real), como cualquier otro dispositivo.
Terminología

Plazo | Descripción |
---|---|
Dispositivo |
Un componente de hardware o software que produce una entrada de audio o imagen. Algunos ejemplos de dispositivos son micrófonos, cámaras, auriculares Bluetooth y dispositivos virtuales, como grabadoras de pantalla o entradas de imágenes personalizadas. |
Dispositivo mixto |
Un Los dispositivos mixtos vienen en formatos de audio o imagen. |
Configuración del dispositivo mixto |
Un objeto de configuración para el dispositivo mixto. En el caso de los dispositivos de imágenes mixtos, configura propiedades como las dimensiones y la tasa de fotogramas. En el caso de los dispositivos de audio mixtos, esto configura el recuento de canales. |
Origen |
Un contenedor que define la posición de un elemento visual en la pantalla y las propiedades de una pista de audio en la mezcla de audio. Un dispositivo mixto se puede configurar con cero o más fuentes. Las fuentes tienen una configuración que afecta a la forma en que se utilizan los medios de la fuente. La imagen de arriba muestra cuatro fuentes de imagen:
|
Configuración de fuente |
Un objeto de configuración para la fuente que se envía al dispositivo mixto. Los objetos de configuración completos se describen a continuación. |
Transition |
Para mover una ranura a una nueva posición o cambiar algunas de sus propiedades, utilice
|
Dispositivo de audio mixto
Configuración
MixedAudioDeviceConfiguration
en Android
IVSMixedAudioDeviceConfiguration
en iOS
Nombre | Tipo | Descripción |
---|---|---|
|
Entero |
Número de canales de salida del mezclador de audio. Valores válidos: 1, 2. 1 es audio mono; 2, audio estéreo. Valor predeterminado: 2. |
Configuración de fuente
MixedAudioDeviceSourceConfiguration
en Android
IVSMixedAudioDeviceSourceConfiguration
en iOS
Nombre | Tipo | Descripción |
---|---|---|
|
Flotante |
Ganancia de audio. Este es un multiplicador, por lo que cualquier valor superior a 1 aumenta la ganancia; cualquier valor inferior a 1, la disminuye. Valores válidos: 0-2. Valor predeterminado: 1. |
Dispositivo de imagen mixto
Configuración
MixedImageDeviceConfiguration
en Android
IVSMixedImageDeviceConfiguration
en iOS
Nombre | Tipo | Descripción |
---|---|---|
|
Vec2 |
Tamaño del lienzo de video. |
|
Entero |
Número de fotogramas objetivo por segundo para el dispositivo mixto. En promedio, este valor debe alcanzarse, pero el sistema puede perder fotogramas en determinadas circunstancias (por ejemplo, uso elevado de CPU o carga elevada de la GPU). |
|
Booleano |
Esto permite la combinación mediante la propiedad |
Configuración de fuente
MixedImageDeviceSourceConfiguration
en Android
IVSMixedImageDeviceSourceConfiguration
en iOS
Nombre | Tipo | Descripción |
---|---|---|
|
Flotante |
Alfa de la ranura. Esto es multiplicativo con cualquier valor alfa de la imagen. Valores válidos: 0-1, donde 0 es totalmente transparente y 1 es totalmente opaco. Valor predeterminado: 1. |
|
Modo de aspecto | Modo de relación de aspecto para cualquier imagen que se representa en la ranura. Valores válidos:
Valor predeterminado: |
|
Vec4 |
Color de relleno que se utilizará con |
|
Vec2 |
Posición de la ranura (en píxeles), en relación con la esquina superior izquierda del lienzo. El origen de la ranura también está en la parte superior izquierda. |
|
Vec2 |
Tamaño de la ranura (en píxeles). Establecer este valor también establece |
|
Flotante |
Ordenación relativa de ranuras. Las ranuras con mayor valor de |
Creación y configuración de un dispositivo de imagen mixto

Aquí creamos una escena similar a la del principio de esta guía, con tres elementos en pantalla:
-
Ranura inferior izquierda para una cámara.
-
Ranura inferior derecha para una superposición de logotipo.
-
Ranura superior derecha para una película.
Tenga en cuenta que el origen del lienzo es la esquina superior izquierda, que es la misma que para las ranuras. Por lo tanto, colocar una ranura en (0, 0) la coloca en la esquina superior izquierda con toda la ranura 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)
Eliminación de fuentes
Para eliminar una fuente, llama a MixedDevice.remove
con el objeto Source
que deseas eliminar.
Animaciones con transiciones
El método de transición reemplaza la configuración de una fuente por una nueva configuración. Este reemplazo se puede animar a lo largo del tiempo estableciendo una duración superior a 0 (en segundos).
¿Qué propiedades se pueden animar?
No se pueden animar todas las propiedades de la estructura de la ranura. Las propiedades basadas en tipos Float se pueden animar; otras propiedades se hacen efectivas al principio o al final de la animación.
Nombre | ¿Se puede animar? | Punto de impacto |
---|---|---|
|
Sí |
Interpolado |
|
Sí |
Interpolado |
|
No |
Final |
|
Sí |
Interpolado |
|
Sí |
Interpolado |
|
Sí |
Interpolado |
Nota: El |
Sí |
Desconocido |
Ejemplos sencillos
A continuación se muestran ejemplos de una toma de cámara a pantalla completa utilizando la configuración definida anteriormente en Creación y configuración de un dispositivo de imagen mixto. Se anima durante 0,5 segundos.
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") } }
Duplicar la transmisión
Para duplicar un dispositivo de imagen conectado a la transmisión en esta dirección… | Utilice un valor negativo para… |
---|---|
Horizontalmente |
El ancho de la ranura |
Verticalmente |
La altura de la ranura |
Tanto horizontal como verticalmente |
Tanto el ancho como la altura de la ranura |
Será necesario ajustar la posición con el mismo valor para colocar la ranura en la posición correcta cuando se duplique.
A continuación se muestran algunos ejemplos de cómo duplicar la transmisión horizontal y verticalmente.
iOS
Duplicación horizontal:
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)
Duplicación vertical:
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
Duplicación horizontal:
val cameraConfig = MixedImageDeviceSourceConfiguration().apply { setSize(BroadcastConfiguration.Vec2(-320f, 180f)) // Add 320f to position x since our width is -320f setPosition(BroadcastConfiguration.Vec2(320f, 0f)) }
Duplicación vertical:
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: Este método de duplicación setMirrored
es diferente en ImagePreviewView
(Android) y IVSImagePreviewView
(iOS). Este método solo afecta a la vista previa local del dispositivo y no afecta a la transmisión.