SDK de Transmissão do IVS: guia do mixer (streaming de baixa latência)
O mixer é uma unidade de processamento de áudio e vídeo que usa várias fontes de entrada e gera uma única saída. É um recurso poderoso que permite definir e gerenciar vários elementos e faixas de áudio na tela (vídeo). Você pode combinar vídeo e áudio de várias fontes, como câmeras, microfones, capturas de tela e áudio e vídeo gerados pela sua aplicação. Você pode usar transições para mover essas fontes ao redor do vídeo que você transmite para o Amazon IVS, além de adicioná-las e removê-las durante a transmissão.
Para acessar o mixer, chame:
BroadcastSession.getMixer()
no Android
IVSBroadcastSession.mixer
no iOS
Terminologia
Prazo | Descrição |
---|---|
Binding |
Para associar um dispositivo de entrada a um slot, o dispositivo deve ser vinculado ao slot do mixer. Isso é feito por meio do método |
Canvas |
A extensão de exibição do vídeo definida na sua configuração da |
Dispositivo |
Um componente de hardware ou software que produz entrada de áudio ou imagem para a |
Descritor de dispositivo |
Uma estrutura com informações sobre um dispositivo de entrada; por exemplo, seu tipo, endereço do sistema, um nome legível por humanos “amigável” e a posição física no dispositivo móvel. Tais informações possibilitam que você defina se quer usar o dispositivo referenciado e permitem que o Amazon IVS o acesse. |
Slot |
Um contêiner que define a posição de um elemento visual na tela e as propriedades de uma faixa de áudio na mixagem de áudio. Um mixer pode ser configurado com zero ou mais slots. Os slots recebem um nome de string, que pode ser usado para vincular dispositivos e executar transições. A imagem acima mostra quatro slots:
Depois de configurar uma sessão, você pode adicionar e remover slots com os métodos |
Transição |
Para mover um slot para uma nova posição ou alterar algumas de suas propriedades, use
|
Propriedades da tela
As propriedades da tela são definidas com base na BroadcastConfiguration
que você fornece ao criar a BroadcastSession
. Várias propriedades nas estruturas de Audio
e Video
afetam a tela:
Nome | Tipo | Descrição |
---|---|---|
|
Inteiro |
Número de canais de saída do mixer de áudio. Valores válidos: 1, 2. Em 1, o canal é áudio mono; em 2, áudio estéreo. Padrão: 2. |
|
AudioSampleRate |
Número de amostras de áudio por segundo do mixer de áudio. Esse valor deve ser pelo menos o dobro da frequência mais alta em seu sinal de áudio. As pessoas podem ouvir até cerca de 20 kHz; assim, 44,1 kHz e 48 kHz costumam ser suficientes. Padrão: 48 kHz. |
|
AspectMode |
Modo padrão da taxa de proporção para slots. Valores válidos:
|
|
Vec2 |
Tamanho da tela de vídeo. |
|
Inteiro |
Número de quadros de destino por segundo para a tela. Em média, esse valor deve ser cumprido, mas o sistema pode soltar quadros em determinadas circunstâncias (por exemplo, alta carga de CPU ou congestionamento de rede). |
Propriedades do slot
Os slots têm várias propriedades configuráveis que podem ser usadas para personalizar suas cenas e animar. Qualquer valor que seja Float ou Vector é animado usando interpolação linear para transições com uma duração superior a 0 segundos.
Nome | Tipo | Descrição |
---|---|---|
|
AspectMode |
Modo de taxa de proporção para qualquer imagem renderizada no slot. Valores válidos:
Padrão: o mesmo que o |
|
Vec4 |
Cor de preenchimento a ser usada com o Aspect Fit (Ajuste de proporção) quando as taxas de proporção do slot e da imagem não corresponderem. O formato é (vermelho, verde, azul, alfa). Valor válido (para cada canal): 0 - 1. Padrão: (0, 0, 0, 0). |
|
Float |
Ganho de áudio. Este é um multiplicador. Assim, qualquer valor acima de 1 aumenta o ganho e qualquer valor abaixo de 1, diminui. Valores válidos: 0 - 2. Padrão: 1. |
|
Booleano |
Se ele estiver definido como true, use o valor do |
|
Booleano |
Se estiver como true, a dimensão do slot será ajustada para corresponder à da tela e sua posição será definida como (0, 0). Ele é definido como false se você definir a propriedade |
|
String |
Nome do slot. É usado para referenciar o slot para associações e transições. Padrão: |
|
Vec2 |
Posição do slot (em pixels) em relação ao canto superior esquerdo da tela. A origem do slot também está no canto superior esquerdo. |
|
DeviceType |
Tipo de dispositivo de entrada de áudio preferido. Se esse slot não estiver vinculado e um dispositivo de áudio do tipo especificado estiver anexado à sessão, o dispositivo será vinculado automaticamente a esse slot. Valores válidos:
|
|
DeviceType |
Dispositivo de entrada de vídeo preferencial. Se esse slot não estiver vinculado e um dispositivo de vídeo do tipo especificado estiver anexado à sessão, o dispositivo será vinculado automaticamente a esse slot. Valores válidos:
|
|
Vec2 |
Tamanho do slot, em pixels. Definir esse valor também define |
|
Float |
Transparência do slot. É um valor multiplicativo com quaisquer valores alfa na imagem. A opacidade é 1 - |
|
Float |
Ordenação relativa de slots. Slots com valores mais altos de |
Configuração de uma sessão de transmissão para mixagem
Aqui, criamos uma cena semelhante à do início deste guia, com três elementos na tela:
-
Slot inferior esquerdo para uma câmera.
-
Slot inferior direito para uma sobreposição de logo.
-
Slot superior direito para um filme.
Observe que a origem da tela é o canto superior esquerdo, e é o mesmo para os slots. Assim, posicionar um slot em (0, 0) o coloca no canto superior esquerdo com todo o slot visível.
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 }
Adição de slots
Assim que você criar uma BroadcastSession
com a sua configuração, poderá adicionar e remover slots do mixer. Aqui, adicionamos ao mixer um grande slot de segundo plano para uma imagem.
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)
Remoção de slots
Para remover um slot, chame BroadcastSession.Mixer.removeSlot
com o nome do slot que você deseja remover. Todos os dispositivos vinculados a esse slot são automaticamente desvinculados. Assim, você deve revinculá-los a slots diferentes se quiser continuar a usá-los.
Animações com transições
O método de transição do mixer substitui a configuração de um slot por uma nova configuração. Essa substituição pode ser animada ao longo do tempo, definindo uma duração superior a 0, em segundos.
Quais propriedades podem ser animadas?
Nem todas as propriedades na estrutura do slot podem ser animadas. Todas as propriedades baseadas em tipos Float podem ser animadas; outras propriedades começam a funcionar no início ou no final da animação.
Nome | Pode ser animado(a)? | Ponto de impacto |
---|---|---|
|
Não |
Fim |
|
Sim |
Interpolado(a) |
|
Sim |
Interpolado(a) |
|
Não |
Início |
|
Não |
Início |
Observações: não é possível alterar o nome do slot. |
Não |
N/D |
|
Sim |
Interpolado(a) |
|
Não |
Fim |
|
Não |
Fim |
|
Sim |
Interpolado(a) |
|
Sim |
Interpolado(a) |
Observações: o |
Sim |
Desconhecido |
Exemplos simples
Abaixo, estão exemplos de uma aquisição de câmera em tela cheia usando a configuração definida acima em Configuring a Broadcast Session for Mixing (Configuração de uma sessão de transmissão para mixagem). Isso fica animado por 0,5 segundo.
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!") }
Espelhamento da transmissão
Para espelhar um dispositivo de imagem conectado na transmissão nessa direção... | Use um valor negativo para... |
---|---|
Horizontalmente |
Largura do slot |
Verticalmente |
Altura do slot |
Horizontalmento e verticalmente |
Tanto a largura quanto a altura do slot |
A posição precisará ser ajustada com base no mesmo valor para colocar o slot na posição correta quando espelhado.
Abaixo estão alguns exemplos para espelhar a transmissão horizontalmente e verticalmente.
iOS
Espelhamento 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)
Espelhamento 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
Espelhamento 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 }
Espelhamento 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 }
Observação: esse espelhamento é diferente do método setMirrored
no ImagePreviewView
(Android) e IVSImagePreviewView
(iOS). Esse método afeta somente a visualização local no dispositivo e não afeta a transmissão.