SDK de transmisión de IVS: dispositivos mixtos - Amazon IVS

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

Terminología de dispositivos mixtos de transmisión de IVS.
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 Device que se puede conectar a un BroadcastSession igual que cualquier otro Device, pero con API adicionales que permiten agregar objetos de Source. Los dispositivos mixtos tienen mezcladores internos que componen audio o imágenes, lo que produce un flujo de audio e imagen de salida único.

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:

  • Abajo a la izquierda con entrada de cámara

  • Arriba a la derecha con entrada de video

  • Abajo a la derecha con el logotipo de Amazon IVS

  • Una imagen de fondo a pantalla completa

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 MixedDevice.transitionToConfiguration(). Este método recibe:

  • Una nueva configuración de fuente que representa el siguiente estado de la fuente.

  • Una duración que especifica cuánto tiempo debe durar la animación, en relación con la escala de tiempo del video. Si la duración se establece en 0, la transición se produce en el siguiente fotograma que se mezcla.

  • Una devolución de llamada opcional que le avisa cuando se ha completado la animación. La devolución de llamada puede ser útil para encadenar animaciones.

Dispositivo de audio mixto

Configuración

MixedAudioDeviceConfiguration en Android

IVSMixedAudioDeviceConfiguration en iOS

Nombre Tipo Descripción

channels

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

gain

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

size

Vec2

Tamaño del lienzo de video.

targetFramerate

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).

transparencyEnabled

Booleano

Esto permite la combinación mediante la propiedad alpha en las configuraciones de las fuentes de imagen. Configurar esto como true aumenta el consumo de memoria y CPU. Predeterminado: false.

Configuración de fuente

MixedImageDeviceSourceConfiguration en Android

IVSMixedImageDeviceSourceConfiguration en iOS

Nombre Tipo Descripción

alpha

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.

aspect

Modo de aspecto

Modo de relación de aspecto para cualquier imagen que se representa en la ranura. Valores válidos:

  • Fill: mantiene la relación de aspecto de la imagen, pero rellena la ranura. La imagen se recorta si es necesario.

  • Fit: mantiene la relación de aspecto de la imagen, pero ajusta toda la imagen en la ranura. La ranura puede ser letterbox o pillarbox si es necesario. La letterbox o pillarbox es fillColor si se ha establecido ese valor, de lo contrario, será transparente (que puede ser negro si el color del lienzo detrás de la imagen es negro).

  • None: no mantiene la relación de aspecto de la imagen. La imagen está escalada para que coincida con las dimensiones de la ranura.

Valor predeterminado: Fit

fillColor

Vec4

Color de relleno que se utilizará con aspect Fit cuando las relaciones de aspecto de la ranura y la imagen no coinciden. El formato es (rojo, verde, azul, alfa). Valor válido (para cada canal): 0-1. Valor predeterminado: (0, 0, 0, 0).

position

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.

size

Vec2

Tamaño de la ranura (en píxeles). Establecer este valor también establece matchCanvasSize como false. Valor predeterminado: (0, 0); sin embargo, dado que el valor predeterminado de matchCanvasSize es true, el tamaño representado de la ranura es el tamaño del lienzo, y no (0, 0).

zIndex

Flotante

Ordenación relativa de ranuras. Las ranuras con mayor valor de zIndex se dibujan encima de las ranuras con menor valor de zIndex.

Creación y configuración de un dispositivo de imagen mixto

Configuración de una sesión de transmisión de mezcla.

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

Audio.gain

Interpolado

Image.alpha

Interpolado

Image.aspect

No

Final

Image.fillColor

Interpolado

Image.position

Interpolado

Image.size

Interpolado

Image.zIndex

Nota: El zIndex mueve planos 2D a través del espacio 3D, de modo que la transición se produce cuando los dos planos se cruzan en algún punto en el medio de la animación. Esto podría calcularse, pero depende de los valores iniciales y finales de zIndex. Para lograr una transición más fluida, combínela con alpha.

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.