Skip to main content

Entrada de video personalizada

Describe los dos modos de entrada de video personalizada admitidos por el AOQ Client SDK —modo de fotograma sin procesar y modo de fotograma codificado— incluyendo la configuración y ejemplos de código para cada uno.

El SDK de AOQ proporciona API generales de video. Qwen-Audio-Realtime no admite entrada ni salida de video. Para conocer las capacidades de medios de otros modelos, consulte su documentación de conexión.

Visión general

El módulo de video integrado del AOQ Client SDK cubre las necesidades básicas de video, pero en algunos escenarios el módulo de captura integrado puede no ser suficiente. La captura de video personalizada es útil cuando necesita:
  • Solucionar conflictos de dispositivos de cámara o problemas de compatibilidad.
  • Introducir datos de video desde un sistema de captura personalizado o un archivo de video en el SDK para su transmisión.
  • Publicar fotogramas generados por IA, grabaciones de pantalla o contenido de cámara virtual a través del SDK.
El AOQ Client SDK admite dos modos de entrada de video personalizada:
  • Modo de fotograma sin procesar: Capture fotogramas de video sin procesar en formatos como BGRA, I420, NV12 o NV21, y luego envíelos al SDK mediante pushExternalVideoCapturedFrame. El SDK maneja internamente la codificación y la transmisión.
  • Modo de fotograma codificado: Codifique los fotogramas de video usted mismo (actualmente solo JPEG) y luego envíe los datos codificados directamente al SDK mediante pushExternalVideoEncodedFrame, omitiendo el codificador interno del SDK.

Requisitos previos

  • Se ha creado una instancia del motor llamando a createEngine.
  • Se ha establecido una conexión con el servidor (la devolución de llamada onConnectionStatusChange ha reportado AoqConnectionStatusConnected).

Implementación

Elija uno de los dos modos según su caso de uso. Los dos modos no pueden utilizarse simultáneamente: solo una interfaz de envío puede estar activa a la vez.

Modo 1: Modo de tramas sin procesar

Capturar fotogramas de video sin procesar en formatos como BGRA, I420, NV12 o NV21 y enviarlos al SDK para su codificación y transmisión. El SDK maneja internamente todo el proceso de codificación y envío.

1. Configurar los parámetros de codificación de video

El codificador interno del SDK codifica los fotogramas sin procesar que usted envía. Ajuste los parámetros de codificación según su 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

Predeterminado

Descripción

trackType

AoqTrackType

AoqTrackTypeVideo

Tipo de pista de video

codecType

AoqEncoderType

AoqEncoderTypeVideoH264

Tipo de codificador

width

int

720

Ancho de codificación (píxeles)

height

int

1280

Alto de codificación (píxeles)

fps

int

5

Tasa de fotogramas

bitrate

int

500000

Tasa de bits inicial (bps)

minBitrate

int

128000

Tasa de bits mínima (bps)

keyframeInterval

int

2

Intervalo de fotogramas clave (segundos)

isExternal

boolean

false

Mantenga false para el modo de tramas sin procesar

mirrorMode

AoqMirrorMode

AoqMirrorModeDisabled

Modo espejo

orientationMode

AoqOrientationMode

AoqOrientationModeAuto

Modo de orientación

2. Iniciar la captura de video en modo de captura externa

Llame a startVideoCapture con isExternal=true para indicar al SDK que no abra la cámara y que espere fotogramas de una fuente externa. Esto es obligatorio para el modo de fotograma sin procesar; si omite esta llamada, el SDK no consumirá ningún fotograma que usted envíe.
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

Predeterminado

Descripción

width

int

1280

Ancho de captura (ignorado cuando isExternal=true)

height

int

720

Alto de captura (ignorado cuando isExternal=true)

fps

int

15

Tasa de fotogramas de captura (ignorada cuando isExternal=true)

isExternal

boolean

false

true: no abrir la cámara; la fuente externa proporciona las tramas

cameraDirection

AoqCameraDirection

AoqCameraDirectionFront

Dirección de la cámara (ignorada cuando isExternal=true)

3. Enviar tramas de video sin procesar

Llame a pushExternalVideoCapturedFrame para introducir fotogramas sin procesar capturados en el SDK. El SDK se encarga de la codificación y la transmisión. Formatos compatibles: BGRA, I420, NV12, NV21, RGBA. En plataformas Apple, también se admite la copia cero de CVPixelBuffer.

3.1 Formato BGRA

BGRA es un formato empaquetado con 4 bytes por píxel (Azul, Verde, Rojo, Alfa). Tamaño del fotograma = ancho × alto × 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 es un formato planar con tres planos separados (Y, U, V). El tamaño del plano Y = ancho × alto; los planos U y V son cada uno (ancho/2) × (alto/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 y NV21 son formatos semiplanares que consisten en un plano Y y un plano UV intercalado. NV12 intercala UV en ese orden; NV21 intercala VU. Tamaño del fotograma = ancho × alto × 3 / 2 bytes, empaquetados en el 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)

En iOS y macOS, puede pasar un CVPixelBufferRef directamente para una transferencia de copia cero, evitando la sobrecarga de rendimiento de las copias de memoria.
// 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. Detener la captura de tramas sin procesar

Cuando ya no necesite enviar fotogramas, detenga primero el temporizador de envío y luego llame a stopVideoCapture para cerrar la captura de video.
// 1. Stop the frame push timer
stopExternalFramePush();
// 2. Stop video capture
engine.stopVideoCapture();

Modo 2: Modo de tramas codificadas

Codifique los fotogramas de video usted mismo (actualmente solo JPEG) y envíe los datos codificados directamente al SDK, omitiendo el codificador interno. Este modo no requiere llamar a startVideoCapture ni a ninguna otra API relacionada con la captura.

1. Configurar los parámetros de codificación de video y habilitar la codificación externa

Llame a setVideoEncoderConfig con isExternal=true para indicar al SDK que omita el codificador interno y espere datos precodificados desde el exterior.
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);
Una vez configurado, puede enviar fotogramas codificados inmediatamente; no es necesario llamar a startVideoCapture.

2. Enviar tramas de video codificadas

Llame a pushExternalVideoEncodedFrame para pasar datos de video precodificados directamente al SDK. Actualmente, solo se admite la codificación JPEG.
// 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

Predeterminado

Descripción

codec

AoqVideoCodecType

AoqVideoCodecTypeJPEG

Formato de codificación; actualmente solo se admite JPEG

data

byte[]

null

Datos de trama codificada

width

int

0

Ancho de la trama (píxeles)

height

int

0

Alto de la trama (píxeles)

timeStamp

long

0

Marca de tiempo (milisegundos); cuando es 0, el SDK utiliza el reloj local

3. Detener el envío de fotogramas codificados

El modo de fotograma codificado no involucra ningún dispositivo de captura, por lo que detenerlo es simplemente cuestión de parar su temporizador de envío.
stopExternalFramePush();

Referencia

AoqVideoFrame (modo de fotograma sin procesar)

Campo

Tipo

Descripción

format

AoqVideoPixelFormat

Formato de píxel

width

int

Ancho de la trama (píxeles)

height

int

Alto de la trama (píxeles)

data

byte[]

Datos de formato empaquetado (NV12/NV21/BGRA/RGBA)

dataY

byte[]

Datos del plano Y I420

dataU

byte[]

Datos del plano U I420

dataV

byte[]

Datos del plano V I420

strideY

int

Paso de fila del plano Y I420 (bytes)

strideU

int

Paso de fila del plano U I420 (bytes)

strideV

int

Paso de fila del plano V I420 (bytes)

textureId

int

ID de textura de Android (TextureOES/Texture2D)

transformMatrix

float[]

Matriz de transformación de textura (4×4, ordenada por filas)

eglContext

EGLContext

Contexto EGL compartido de Android (para modo de textura)

pixelBuffer

CVPixelBufferRef

CVPixelBuffer de copia cero de Apple (solo iOS/macOS)

timeStamp

long

Marca de tiempo (milisegundos); cuando es 0, el SDK utiliza el reloj local

Valores de la enumeración AoqVideoPixelFormat

Valor de enumeración

Valor numérico

Descripción

AoqVideoPixelFormatUnknown

0

Formato desconocido

AoqVideoPixelFormatI420

1

Formato planar I420

AoqVideoPixelFormatNV12

2

Formato semiplanar NV12 (UV intercalado)

AoqVideoPixelFormatNV21

3

Formato semiplanar NV21 (VU intercalado)

AoqVideoPixelFormatBGRA

4

Formato empaquetado BGRA

AoqVideoPixelFormatRGBA

5

Formato empaquetado RGBA

AoqVideoPixelFormatCVPixelBuffer

6

CVPixelBuffer de Apple (solo iOS/macOS)

AoqVideoPixelFormatTextureOES

7

Textura externa OES de Android

AoqVideoPixelFormatTexture2D

8

Textura 2D de Android

AoqVideoEncodedFrame (modo de fotograma codificado)

Campo

Tipo

Descripción

codec

AoqVideoCodecType

Formato de codificación

data

byte[]

Datos de trama codificada

width

int

Ancho de la trama (píxeles)

height

int

Alto de la trama (píxeles)

timeStamp

long

Marca de tiempo (milisegundos); cuando es 0, el SDK utiliza el reloj local

Valores de la enumeración AoqVideoCodecType

Valor de enumeración

Valor numérico

Descripción

AoqVideoCodecTypeJPEG

0

Formato de codificación JPEG

Notas importantes

  • Modo de fotograma sin procesar: debe llamar a startVideoCapture(isExternal=true) antes de enviar fotogramas. Si omite esta llamada, el SDK devolverá un error de parámetro.
  • Modo de fotograma codificado: llame a setVideoEncoderConfig(isExternal=true) y envíe inmediatamente; llamar a startVideoCapture no es necesario.
  • El modo de fotograma sin procesar y el modo de fotograma codificado no pueden utilizarse simultáneamente: solo una interfaz de envío puede estar activa a la vez.
  • El modo de trama codificada actualmente solo admite JPEG.
  • Después de enviar un fotograma, el SDK gestiona su ciclo de vida internamente. No necesita conservar los datos después de que regrese la llamada de envío.