Descreve os dois modos de entrada de vídeo personalizada compatíveis com o AOQ Client SDK — modo de quadro bruto e modo de quadro codificado — incluindo configurações e exemplos de código para cada um.
Visão geral
O módulo de vídeo integrado do AOQ Client SDK atende às necessidades básicas, mas em alguns cenários o módulo de captura padrão pode ser insuficiente. A captura de vídeo personalizada é útil quando você precisa:
- Contornar conflitos ou problemas de compatibilidade com dispositivos de câmera.
- Enviar dados de vídeo de um sistema de captura personalizado ou de um arquivo de vídeo para o SDK para transmissão.
- Publicar quadros gerados por IA, gravações de tela ou conteúdo de câmera virtual pelo SDK.
O AOQ Client SDK oferece suporte a dois modos de entrada de vídeo personalizada:
- Modo de quadro bruto: capture quadros de vídeo brutos em formatos como BGRA, I420, NV12 ou NV21 e envie-os ao SDK via
pushExternalVideoCapturedFrame. O SDK gerencia a codificação e a transmissão internamente. - Modo de quadro codificado: codifique os quadros de vídeo (atualmente apenas JPEG) e envie os dados codificados diretamente ao SDK via
pushExternalVideoEncodedFrame, ignorando o codificador interno do SDK.
Código de exemplo
Em breve.
Pré-requisitos
- Uma instância de engine criada pela chamada de
createEngine. - Conexão estabelecida com o servidor (o callback
onConnectionStatusChangereportouAoqConnectionStatusConnected).
Implementação
Escolha um dos dois modos conforme seu caso de uso. Não é possível usar ambos simultaneamente: apenas uma interface de envio pode permanecer ativa por vez.
Modo 1: Modo de quadro bruto
Capture quadros de vídeo brutos em formatos como BGRA, I420, NV12 ou NV21 e envie-os ao SDK para codificação e transmissão. O SDK gerencia internamente todo o pipeline de codificação e envio.
1. Configure os parâmetros de codificação de vídeo
O codificador interno do SDK processa os quadros brutos enviados. Ajuste os parâmetros de codificação conforme seu caso de uso.
AoqClientEngine.AoqVideoCodecConfig config = new AoqClientEngine.AoqVideoCodecConfig();
config.width = 1280;
config.height = 720;
config.fps = 2;
config.bitrate = 500000; // Starting bitrate: 500 kbps
config.minBitrate = 128000; // Minimum bitrate: 128 kbps
config.keyframeInterval = 2;
// Leave isExternal at the default false — the SDK handles encoding internally
engine.setVideoEncoderConfig(config);
Parâmetros:
Parâmetro | Tipo | Padrão | Descrição |
|---|---|---|---|
trackType | AoqTrackType | AoqTrackTypeVideo | Tipo de trilha de vídeo |
codecType | AoqEncoderType | AoqEncoderTypeVideoH264 | Tipo de codificador |
width | int | 720 | Largura de codificação (pixels) |
height | int | 1280 | Altura de codificação (pixels) |
fps | int | 5 | Taxa de quadros |
bitrate | int | 500000 | Bitrate inicial (bps) |
minBitrate | int | 128000 | Bitrate mínimo (bps) |
keyframeInterval | int | 2 | Intervalo de keyframes (segundos) |
isExternal | boolean | false | Mantenha como false para o modo de quadro bruto |
mirrorMode | AoqMirrorMode | AoqMirrorModeDisabled | Modo de espelhamento |
orientationMode | AoqOrientationMode | AoqOrientationModeAuto | Modo de orientação |
2. Inicie a captura de vídeo no modo de captura externa
Chame startVideoCapture com isExternal=true para instruir o SDK a não abrir a câmera e a aguardar quadros de uma source externa. Essa etapa é obrigatória para o modo de quadro bruto. Se omitida, o SDK não consumirá nenhum quadro enviado.
AoqClientEngine.AoqVideoCaptureConfig config = new AoqClientEngine.AoqVideoCaptureConfig();
config.isExternal = true; // Do not open the camera; external source will push frames
// When isExternal=true, width/height/fps have no effect — the actual resolution
// and frame rate are determined by the pushed data
int ret = engine.startVideoCapture(config);
Parâmetros:
Parâmetro | Tipo | Padrão | Descrição |
|---|---|---|---|
width | int | 1280 | Largura de captura (ignorado quando |
height | int | 720 | Altura de captura (ignorado quando |
fps | int | 15 | Taxa de quadros de captura (ignorado quando |
isExternal | boolean | false | true: não abre a câmera; a source externa fornece os quadros |
cameraDirection | AoqCameraDirection | AoqCameraDirectionFront | Direção da câmera (ignorado quando |
3. Envie quadros de vídeo brutos
Chame pushExternalVideoCapturedFrame para alimentar o SDK com os quadros brutos capturados. O SDK cuida da codificação e da transmissão.
Formatos compatíveis: BGRA, I420, NV12, NV21, RGBA. Em plataformas Apple, também há suporte para CVPixelBuffer com zero-copy.
3,1 Formato BGRA
BGRA é um formato compactado com 4 bytes por pixel (Blue, Green, Red, Alpha). Tamanho do quadro = largura × altura × 4 bytes.
// Build a BGRA video frame
AoqClientEngine.AoqVideoFrame frame = new AoqClientEngine.AoqVideoFrame();
frame.format = AoqClientEngine.AoqVideoPixelFormat.AoqVideoPixelFormatBGRA;
frame.width = 1280;
frame.height = 720;
frame.data = bgraBytes; // byte[], length = width * height * 4
frame.timeStamp = System.currentTimeMillis();
int ret = engine.pushExternalVideoCapturedFrame(
AoqClientEngine.AoqTrackType.AoqTrackTypeVideo, frame);
3,2 Formato I420
I420 é um formato planar com três planos separados (Y, U, V). O tamanho do plano Y = largura × altura; os planos U e V têm cada um (largura/2) × (altura/2).
// Build an I420 video frame
AoqClientEngine.AoqVideoFrame frame = new AoqClientEngine.AoqVideoFrame();
frame.format = AoqClientEngine.AoqVideoPixelFormat.AoqVideoPixelFormatI420;
frame.width = 1280;
frame.height = 720;
frame.dataY = yPlane; // byte[], length = width * height
frame.dataU = uPlane; // byte[], length = (width/2) * (height/2)
frame.dataV = vPlane; // byte[], length = (width/2) * (height/2)
frame.strideY = 1280; // Y plane row stride (bytes)
frame.strideU = 640; // U plane row stride (bytes)
frame.strideV = 640; // V plane row stride (bytes)
frame.timeStamp = System.currentTimeMillis();
int ret = engine.pushExternalVideoCapturedFrame(
AoqClientEngine.AoqTrackType.AoqTrackTypeVideo, frame);
3.3 Formato NV12 / NV21
NV12 e NV21 são formatos semi-planares compostos por um plano Y e um plano UV intercalado. O NV12 intercala UV nessa ordem; o NV21 intercala VU. O tamanho do quadro = largura × altura × 3 / 2 bytes, compactado no campo data.
// Build an NV12 video frame (NV21 is identical — just change the format field)
AoqClientEngine.AoqVideoFrame frame = new AoqClientEngine.AoqVideoFrame();
frame.format = AoqClientEngine.AoqVideoPixelFormat.AoqVideoPixelFormatNV12;
frame.width = 1280;
frame.height = 720;
frame.data = nv12Bytes; // byte[], length = width * height * 3 / 2
frame.timeStamp = System.currentTimeMillis();
int ret = engine.pushExternalVideoCapturedFrame(
AoqClientEngine.AoqTrackType.AoqTrackTypeVideo, frame);
3,4 Formato CVPixelBuffer (plataformas Apple)
No iOS e macOS, passe um CVPixelBufferRef diretamente para transferência zero-copy e evite a sobrecarga de desempenho das cópias de memória.
// iOS / macOS
let frame = AoqVideoFrame()
frame.format = .cvPixelBuffer
frame.width = 1280
frame.height = 720
frame.pixelBuffer = pixelBuffer // CVPixelBufferRef
frame.timeStamp = Int64(Date().timeIntervalSince1970 * 1000)
// The SDK holds pixelBuffer asynchronously — retain it with +1 ref count.
// The SDK releases it when done.
let _ = Unmanaged.passRetained(pixelBuffer)
engine.pushExternalVideoCapturedFrame(.video, frame: frame)
4. Pare a captura de quadros brutos
Quando não for mais necessário enviar quadros, pare primeiro o temporizador de envio e depois chame stopVideoCapture para encerrar a captura de vídeo.
// 1. Stop the frame push timer
stopExternalFramePush();
// 2. Stop video capture
engine.stopVideoCapture();
Modo 2: Modo de quadro codificado
Codifique os quadros de vídeo (atualmente apenas JPEG) e envie os dados codificados diretamente ao SDK, ignorando o codificador interno. Este modo não exige a chamada de startVideoCapture ou de qualquer outra API relacionada à captura.
1. Configure os parâmetros de codificação de vídeo e ative a codificação externa
Chame setVideoEncoderConfig com isExternal=true para instruir o SDK a ignorar o codificador interno e esperar dados pré-codificados de uma source externa.
AoqClientEngine.AoqVideoCodecConfig config = new AoqClientEngine.AoqVideoCodecConfig();
config.width = 1280;
config.height = 720;
config.fps = 2;
config.isExternal = true; // Skip internal encoding; external source provides encoded frames
engine.setVideoEncoderConfig(config);
Após a configuração, envie quadros codificados imediatamente. Não é necessário chamar startVideoCapture.
2. Envie quadros de vídeo codificados
Chame pushExternalVideoEncodedFrame para passar dados de vídeo pré-codificados diretamente ao SDK. Atualmente, apenas a codificação JPEG é compatível.
// Generate JPEG data from a Bitmap
android.graphics.Bitmap bmp = android.graphics.Bitmap.createBitmap(
width, height, android.graphics.Bitmap.Config.ARGB_8888);
// ... fill in Bitmap content ...
java.io.ByteArrayOutputStream baos = new java.io.ByteArrayOutputStream();
bmp.compress(android.graphics.Bitmap.CompressFormat.JPEG, 85, baos);
bmp.recycle();
// Build the encoded frame and push it
AoqClientEngine.AoqVideoEncodedFrame frame = new AoqClientEngine.AoqVideoEncodedFrame();
frame.codec = AoqClientEngine.AoqVideoCodecType.AoqVideoCodecTypeJPEG;
frame.data = baos.toByteArray();
frame.width = width;
frame.height = height;
frame.timeStamp = System.currentTimeMillis();
int ret = engine.pushExternalVideoEncodedFrame(
AoqClientEngine.AoqTrackType.AoqTrackTypeVideo, frame);
Parâmetros de AoqVideoEncodedFrame:
Parâmetro | Tipo | Padrão | Descrição |
|---|---|---|---|
codec | AoqVideoCodecType | AoqVideoCodecTypeJPEG | Formato de codificação; atualmente apenas JPEG é compatível |
data | byte[] | null | Dados do quadro codificado |
width | int | 0 | Largura do quadro (pixels) |
height | int | 0 | Altura do quadro (pixels) |
timeStamp | long | 0 | Timestamp (milissegundos); quando 0, o SDK usa o relógio local |
3. Pare o envio de quadros codificados
O modo de quadro codificado não envolve nenhum dispositivo de captura. Para parar, basta interromper o temporizador de envio.
stopExternalFramePush();
Referência
AoqVideoFrame (modo de quadro bruto)
Campo | Tipo | Descrição |
|---|---|---|
format | AoqVideoPixelFormat | Formato de pixel |
width | int | Largura do quadro (pixels) |
height | int | Altura do quadro (pixels) |
data | byte[] | Dados de formato compactado (NV12/NV21/BGRA/RGBA) |
dataY | byte[] | Dados do plano Y do I420 |
dataU | byte[] | Dados do plano U do I420 |
dataV | byte[] | Dados do plano V do I420 |
strideY | int | Stride de linha do plano Y do I420 (bytes) |
strideU | int | Stride de linha do plano U do I420 (bytes) |
strideV | int | Stride de linha do plano V do I420 (bytes) |
textureId | int | ID de textura do Android (TextureOES/Texture2D) |
transformMatrix | float[] | Matriz de transformação de textura (4×4, row-major) |
eglContext | EGLContext | Contexto EGL compartilhado do Android (para modo de textura) |
pixelBuffer | CVPixelBufferRef | CVPixelBuffer zero-copy da Apple (apenas iOS/macOS) |
timeStamp | long | Timestamp (milissegundos); quando 0, o SDK usa o relógio local |
Valores do enum AoqVideoPixelFormat
Valor do enum | Valor numérico | Descrição |
|---|---|---|
AoqVideoPixelFormatUnknown | 0 | Formato desconhecido |
AoqVideoPixelFormatI420 | 1 | Formato planar I420 |
AoqVideoPixelFormatNV12 | 2 | Formato semi-planar NV12 (UV intercalado) |
AoqVideoPixelFormatNV21 | 3 | Formato semi-planar NV21 (VU intercalado) |
AoqVideoPixelFormatBGRA | 4 | Formato compactado BGRA |
AoqVideoPixelFormatRGBA | 5 | Formato compactado RGBA |
AoqVideoPixelFormatCVPixelBuffer | 6 | CVPixelBuffer da Apple (apenas iOS/macOS) |
AoqVideoPixelFormatTextureOES | 7 | Textura externa OES do Android |
AoqVideoPixelFormatTexture2D | 8 | Textura 2D do Android |
AoqVideoEncodedFrame (modo de quadro codificado)
Campo | Tipo | Descrição |
|---|---|---|
codec | AoqVideoCodecType | Formato de codificação |
data | byte[] | Dados do quadro codificado |
width | int | Largura do quadro (pixels) |
height | int | Altura do quadro (pixels) |
timeStamp | long | Timestamp (milissegundos); quando 0, o SDK usa o relógio local |
Valores do enum AoqVideoCodecType
Valor do enum | Valor numérico | Descrição |
|---|---|---|
AoqVideoCodecTypeJPEG | 0 | Formato de codificação JPEG |
Notas importantes
- Modo de quadro bruto: chame
startVideoCapture(isExternal=true)antes de enviar quadros. Se essa chamada for omitida, o SDK retornará um erro de parâmetro. - Modo de quadro codificado: chame
setVideoEncoderConfig(isExternal=true)e envie imediatamente. A chamada destartVideoCapturenão é necessária. - Os modos de quadro bruto e de quadro codificado não podem ser usados simultaneamente: apenas uma interface de envio pode permanecer ativa por vez.
- Atualmente, o modo de quadro codificado é compatível apenas com JPEG.
- Após o envio de um quadro, o SDK gerencia seu ciclo de vida internamente. Não é necessário reter os dados após o retorno da chamada de envio.