SDK de transmisión de IVS: guía del mezclador | Transmisión de baja latencia
El mezclador es una unidad de procesamiento de audio y video que recibe varias fuentes de entrada y genera una única salida. Es 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 Amazon IVS y agregarlas y eliminarlas a mitad de la transmisión.
Para acceder al mezclador, llame a:
BroadcastSession.getMixer()
en Android
IVSBroadcastSession.mixer
en iOS
Terminología
Plazo | Descripción |
---|---|
Tapa |
Para asociar un dispositivo de entrada a una ranura, el dispositivo debe estar vinculado a la ranura del mezclador. Esto se realiza con el método |
Canvas |
El tamaño de visualización del video definido en su configuración |
Dispositivo |
Un componente de hardware o software que produce una entrada de audio o imagen en el |
Descriptor del dispositivo |
Estructura con información sobre un dispositivo de entrada, por ejemplo, su tipo, dirección del sistema, nombre “descriptivo” legible por humanos y posición física en el dispositivo móvil. Esta información le permite decidir si desea utilizar el dispositivo de referencia, y deja que Amazon IVS acceda a él. |
Slot |
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 mezclador se puede configurar con cero ranuras o más. Las ranuras reciben un nombre que se puede utilizar para vincular dispositivos y ejecutar transiciones. La imagen de arriba muestra cuatro ranuras:
Después de configurar una sesión, puede agregar y quitar ranuras con los métodos |
Transition |
Para mover una ranura a una nueva posición o cambiar algunas de sus propiedades, utilice
|
Propiedades del lienzo
Las propiedades del lienzo se establecen en función del BroadcastConfiguration
que proporcione al crear el BroadcastSession
. Varias propiedades en las estructuras Audio
y Video
afectan al lienzo:
Nombre | Tipo | Descripción |
---|---|---|
|
Entero |
Número de canales de salida del mezclador de audio. Valores válidos: 1, 2. 1 canal es audio mono; 2, audio estéreo. Valor predeterminado: 2. |
|
Tasa de muestreo de audio |
Número de muestras de audio por segundo del mezclador de audio. Este valor debe ser al menos el doble de la frecuencia más alta de la señal de audio. La gente puede escuchar hasta unos 20 kHz, por lo que en general bastan 44,1 kHz y 48 kHz. Valor predeterminado: 48 kHz. |
|
Modo de aspecto |
Modo de relación de aspecto predeterminado para las ranuras. Valores válidos:
|
|
Vec2 |
Tamaño del lienzo de video. |
|
Entero |
Número de fotogramas objetivo por segundo del lienzo. En promedio, este valor debe alcanzarse, pero el sistema puede perder fotogramas en determinadas circunstancias (por ejemplo, alta carga de CPU o congestión de la red). |
Propiedades de las ranuras
Las ranuras tienen varias propiedades configurables que puede usar para personalizar sus escenas y animarlas. Cualquier valor que sea Float o Vector se anima mediante interpolación lineal para transiciones con una duración superior a 0 segundos.
Nombre | Tipo | Descripción |
---|---|---|
|
Modo de aspecto |
Modo de relación de aspecto para cualquier imagen que se representa en la ranura. Valores válidos:
Valor predeterminado: igual que el lienzo |
|
Vec4 |
Color de relleno que se utilizará con ajuste de aspecto 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). |
|
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. |
|
Booleano |
Si es verdadero, usa el valor |
|
Booleano |
Si es verdadero, el tamaño de la ranura se ajusta para que sea igual al tamaño del lienzo y su posición se establece en (0, 0). Esto se establece en false si configura la propiedad |
|
Cadena |
Nombre de la ranura. Esto se utiliza para referenciar a la ranura para enlaces y transiciones. Predeterminado: |
|
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. |
|
DeviceType |
Tipo de dispositivo de entrada de audio preferido. Si esta ranura no está enlazada y un dispositivo de audio del tipo especificado está adjunto a la sesión, el dispositivo se enlaza automáticamente a esta ranura. Valores válidos:
|
|
DeviceType |
Dispositivo de entrada de video preferido. Si esta ranura no está enlazada y un dispositivo de video del tipo especificado está adjunto a la sesión, el dispositivo se enlaza automáticamente a esta ranura. Valores válidos:
|
|
Vec2 |
Tamaño de la ranura (en píxeles). Establecer este valor también establece |
|
Flotante |
Transparencia de la ranura. Esto es multiplicativo con cualquier valor alfa de la imagen. La opacidad es 1: |
|
Flotante |
Ordenación relativa de ranuras. Las ranuras con mayor valor de |
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 config = IVSBroadcastConfiguration() try config.video.setSize(CGSize(width: 1280, height: 720)) try config.video.setTargetFramerate(60) config.video.enableTransparency = true // Bottom Left var cameraSlot = IVSMixerSlotConfiguration() cameraSlot.size = CGSize(width: 320, height: 180) cameraSlot.position = CGPoint(x: 20, y: 1280 - 200) cameraSlot.preferredVideoInput = .camera cameraSlot.preferredAudioInput = .microphone cameraSlot.matchCanvasAspectMode = false cameraSlot.zIndex = 2 try cameraSlot.setName("camera") // Top Right var streamSlot = IVSMixerSlotConfiguration() streamSlot.size = CGSize(width: 640, height: 320) streamSlot.position = CGPoint(x: 1280 - 660, y: 20) streamSlot.preferredVideoInput = .userImage streamSlot.preferredAudioInput = .userAudio streamSlot.matchCanvasAspectMode = false streamSlot.zIndex = 1 try streamSlot.setName("stream") // Bottom Right var logoSlot = IVSMixerSlotConfiguration() logoSlot.size = CGSize(width: 320, height: 180) logoSlot.position = CGPoint(x: 1280 - 340, y: 720 - 200) logoSlot.preferredVideoInput = .userImage logoSlot.preferredAudioInput = .unknown logoSlot.matchCanvasAspectMode = false logoSlot.zIndex = 3 try logoSlot.setTransparency(0.7) try logoSlot.setName("logo") config.mixer.slots = [ cameraSlot, streamSlot, logoSlot ]
Android
// Bottom Left val cameraSlot = BroadcastConfiguration.Mixer.Slot.with { s -> s.setSize(320, 180) s.position = BroadcastConfiguration.Vec2(20, 1280 - 200) s.preferredVideoInput = Device.Descriptor.DeviceType.CAMERA s.preferredAudioInput = Device.Descriptor.DeviceType.MICROPHONE s.matchCanvasAspectMode = false s.zIndex = 2 s.name = "camera" s } // Top Right val streamSlot = BroadcastConfiguration.Mixer.Slot.with { s -> s.setSize(640, 320) s.position = BroadcastConfiguration.Vec2(1280 - 660, 20) s.preferredVideoInput = Device.Descriptor.DeviceType.USER_IMAGE s.preferredAudioInput = Device.Descriptor.DeviceType.USER_AUDIO s.matchCanvasAspectMode = false s.zIndex = 1 s.name = "stream" s } // Bottom Right val logoSlot = BroadcastConfiguration.Mixer.Slot.with { s -> s.setSize(320, 180) s.position = BroadcastConfiguration.Vec2(1280 - 340, 720 - 200) s.preferredVideoInput = Device.Descriptor.DeviceType.USER_IMAGE s.preferredAudioInput = Device.Descriptor.DeviceType.UNKNOWN s.matchCanvasAspectMode = false s.zIndex = 3 s.name = "logo" s.transparency = 0.7 s } val config = BroadcastConfiguration.with { c -> c.mixer.slots = listOf(cameraSlot, streamSlot, logoSlot) c.video.targetFramerate = 60 c.video.setSize(1280, 720) c }
Adición de ranuras
Una vez que haya creado un BroadcastSession
con su configuración, puede agregar ranuras y quitar ranuras del mezclador. Aquí, agregamos al mezclador una ranura grande de fondo para una imagen.
iOS
// Background. We will use most of the defaults for this slot. var backgroundSlot = IVSMixerSlotConfiguration() backgroundSlot.preferredVideoInput = .userImage backgroundSlot.preferredAudioInput = .unknown backgroundSlot.matchCanvasAspectMode = false try backgroundSlot.setName("background") session.mixer.addSlot(backgroundSlot)
Android
// Background. We will use most of the defaults for this slot. val backgroundSlot = BroadcastConfiguration.Mixer.Slot.with { s -> s.preferredVideoInput = Device.Descriptor.DeviceType.USER_IMAGE s.preferredAudioInput = Device.Descriptor.DeviceType.UNKNOWN s.matchCanvasAspectMode = false s.name = "background" s } session.mixer.addSlot(backgroundSlot)
Eliminación de ranuras
Para quitar una ranura, llame a BroadcastSession.Mixer.removeSlot
con el nombre de la ranura que desea quitar. Todos los dispositivos enlazados a esa ranura se desvinculan automáticamente, por lo que debe volver a vincularlos a diferentes ranuras si quiere seguir usándolos.
Animaciones con transiciones
El método de transición del mezclador reemplaza la configuración de una ranura 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 |
---|---|---|
|
No |
Final |
|
Sí |
Interpolado |
|
Sí |
Interpolado |
|
No |
Inicio |
|
No |
Inicio |
Nota: No se puede cambiar el nombre de la ranura. |
No |
N/A |
|
Sí |
Interpolado |
|
No |
Final |
|
No |
Final |
|
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 Configuración de una sesión de transmisión de mezcla. Se anima durante 0,5 segundos.
iOS
// Bottom Left var bigCameraSlot = cameraSlot bigCameraSlot.size = CGSize(width: 1280, height: 720) bigCameraSlot.position = CGPoint(x: 0, y: 0) session.mixer.transition("camera", bigCameraSlot, 0.5) { println("animation completed!") }
Android
// Bottom Left val bigCameraSlot = cameraSlot.changing { s -> s.setSize(1280, 720) s.position = BroadcastConfiguration.Vec2(0, 0) s } session.mixer.transition("camera", bigCameraSlot, 0.5) { print("animation completed!") }
Duplicar la transmisión
Para duplicar un dispositivo de imagen conectado a la transmisión en esta dirección… | Utilice un valor negativo para el… |
---|---|
Horizontalmente |
Ancho de la ranura |
Verticalmente |
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:
var cameraSlot = IVSMixerSlotConfiguration cameraSlot.size = CGSize(width: -320, height: 720) // Add 320 to position x since our width is -320 cameraSlot.position = CGPoint(x: 320, y: 0)
Duplicación vertical:
var cameraSlot = IVSMixerSlotConfiguration cameraSlot.size = CGSize(width: 320, height: -720) // Add 720 to position y since our height is -720 cameraSlot.position = CGPoint(x: 0, y: 720)
Android
Duplicación horizontal:
cameraSlot = BroadcastConfiguration.Mixer.Slot.with { it.size = BroadcastConfiguration.Vec2(-320f, 180f) // Add 320f to position x since our width is -320f it.position = BroadcastConfiguration.Vec2(320f, 0f) return@with it }
Duplicación vertical:
cameraSlot = BroadcastConfiguration.Mixer.Slot.with { it.size = BroadcastConfiguration.Vec2(320f, -180f) // Add 180f to position y since our height is -180f it.position = BroadcastConfiguration.Vec2(0f, 180f) return@with it }
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.