

# SDK de transmisión de IVS: dispositivos mixtos
<a name="broadcast-mixed-devices"></a>

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
<a name="broadcast-mixed-devices-terminology"></a>

![Terminología de dispositivos mixtos de transmisión de IVS.](http://docs.aws.amazon.com/es_es/ivs/latest/LowLatencyUserGuide/images/Broadcast_SDK_Mixer_Glossary.png)



| 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.<br />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:[See the AWS documentation website for more details](http://docs.aws.amazon.com/es_es/ivs/latest/LowLatencyUserGuide/broadcast-mixed-devices.html) | 
| 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:[See the AWS documentation website for more details](http://docs.aws.amazon.com/es_es/ivs/latest/LowLatencyUserGuide/broadcast-mixed-devices.html) | 

## Dispositivo de audio mixto
<a name="broadcast-mixed-audio-device"></a>

### Configuración
<a name="broadcast-mixed-audio-device-configuration"></a>

`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
<a name="broadcast-mixed-audio-device-source-configuration"></a>

`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
<a name="broadcast-mixed-image-device"></a>

### Configuración
<a name="broadcast-mixed-image-device-configuration"></a>

`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. Valor predeterminado: `false`. | 

### Configuración de fuente
<a name="broadcast-mixed-image-device-source-configuration"></a>

`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:[See the AWS documentation website for more details](http://docs.aws.amazon.com/es_es/ivs/latest/LowLatencyUserGuide/broadcast-mixed-devices.html)<br />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
<a name="broadcast-mixed-image-device-creating-configuring"></a>

![Configuración de una sesión de transmisión de mezcla.](http://docs.aws.amazon.com/es_es/ivs/latest/LowLatencyUserGuide/images/Broadcast_SDK_Mixer_Configuring.png)


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
<a name="broadcast-mixed-image-device-creating-configuring-ios"></a>

```
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
<a name="broadcast-mixed-image-device-creating-configuring-android"></a>

```
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
<a name="broadcast-mixed-devices-removing-sources"></a>

Para eliminar una fuente, llama a `MixedDevice.remove` con el objeto `Source` que deseas eliminar.

## Animaciones con transiciones
<a name="broadcast-mixed-devices-animations-transitions"></a>

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?
<a name="broadcast-mixed-devices-animations-properties"></a>

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` | Sí | Interpolado | 
| `Image.alpha` | Sí | Interpolado | 
| `Image.aspect` | No | Fin | 
| `Image.fillColor` | Sí | Interpolado | 
| `Image.position` | Sí | Interpolado | 
| `Image.size` | Sí | Interpolado | 
| `Image.zIndex`<br />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`. | Sí | Desconocido | 

### Ejemplos sencillos
<a name="broadcast-mixed-devices-animations-examples"></a>

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](#broadcast-mixed-image-device-creating-configuring). Se anima durante 0,5 segundos.

#### iOS
<a name="broadcast-mixed-devices-animations-examples-ios"></a>

```
// 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
<a name="broadcast-mixed-devices-animations-examples-android"></a>

```
// 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
<a name="broadcast-mixed-devices-mirroring"></a>


| 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
<a name="broadcast-mixed-devices-mirroring-ios"></a>

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
<a name="broadcast-mixed-devices-mirroring-android"></a>

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.