Todos los productos
Search
Centro de documentos

Alibaba Cloud Model Studio:Crear conversaciones de voz push-to-talk con qwen3.8-omni-flash-realtime sobre AOQ

Última actualización: Oct 12, 2026

Utilice AOQ para conectarse a qwen3.8-omni-flash-realtime y permita que el cliente controle los límites de turno para conversaciones push-to-talk y preguntas opcionales con imágenes. El código del cliente utiliza iOS Swift.

Descripción general de la solución

Qwen-Omni-Realtime admite VAD del lado del servidor y modo Manual controlado por el cliente. Este tutorial establece session.turn_detection en null. El cliente envía audio mientras el usuario mantiene presionado un botón, y confirma el audio y solicita explícitamente una respuesta cuando el usuario suelta el botón.

El modo Manual es adecuado para botones de intercomunicador de hardware, controles de mantener presionado, entornos ruidosos donde la aplicación determina los límites del turno y turnos que opcionalmente incluyen una imagen. El audio se transporta a través de la pista Audio de AOQ. No envíe input_audio_buffer.append.

Elemento

Modo VAD

Modo manual

Límite de turno

Detectado por server_vad o semantic_vad

Controlado por un botón o estado de la aplicación

Configuración de sesión

turn_detection contiene configuración de VAD

turn_detection es null

Confirmación de audio

Realizado automáticamente por el servicio

El cliente envía input_audio_buffer.commit

Activación de respuesta

Activado automáticamente por el servicio

El cliente envía response.create

Entrada de imagen

Pista de video continua o una imagen a través de la pista de datos

Pista de video continua o una imagen a través de la pista de datos

Requisitos previos

  1. Active Model Studio y siga los pasos en Obtener y configurar una clave API. Almacene la clave API únicamente en su servidor de aplicaciones. No la incluya en el código del cliente ni la confirme en un repositorio de código.
  2. Establezca {endpoint} en {WorkspaceId}.cn-beijing.maas.aliyuncs.com para China (Beijing) o {WorkspaceId}.ap-southeast-1.maas.aliyuncs.com para Singapur. Reemplace {WorkspaceId} con su ID de espacio de trabajo y utilice la clave de API correspondiente a la misma región y espacio de trabajo.
  3. Descargue la versión más reciente del SDK de cliente AOQ como se describe en Descarga del SDK.
  4. Construya un servidor de aplicaciones e implemente la autenticación proxy tal como se describe en Autenticación por token. Antes de cada nueva conexión, el cliente debe obtener nuevas credenciales de conexión del servidor de aplicaciones.

Importar el SDK

Importe el SDK para su plataforma de desarrollo. La implementación del cliente utiliza iOS Swift. Otras plataformas proporcionan las mismas interfaces y flujo de eventos. Este tutorial utiliza flujos de audio Opus. Importe el complemento Opus antes de continuar.

Android

  1. Coloque libPluginOpus.so del complemento Opus en app/src/main/jniLibs/armeabi-v7a/ y app/src/main/jniLibs/arm64-v8a/ para las ABI correspondientes. Coloque AoqClientSdk-release.aar en app/libs, y configure la dependencia y las ABI compatibles con el SDK en app/build.gradle:
android {
    defaultConfig {
        minSdk 21
        ndk { abiFilters 'armeabi-v7a', 'arm64-v8a' }
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.aar'])
}
  1. Declare los siguientes permisos en AndroidManifest.xml:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.CAMERA" />
  1. Solicite los permisos RECORD_AUDIO y CAMERA en tiempo de ejecución antes de utilizar los dispositivos correspondientes.

iOS

  1. Agregue AoqClientSdk.framework y PluginOpus.framework al proyecto de Xcode y seleccione Embed & Sign en Target > General > Frameworks, Libraries, and Embedded Content. El SDK es compatible con dispositivos arm64 que ejecutan iOS 13.0 o posterior.
  2. Agregue NSMicrophoneUsageDescription y NSCameraUsageDescription a Info.plist y solicite autorización antes de utilizar los dispositivos correspondientes.
  3. Utilice import AoqClientSdk en Swift o #import <AoqClientSdk/AoqClientSdk.h> en Objective-C.

HarmonyOS

  1. Coloque libPluginOpus.so del complemento Opus en entry/libs/arm64-v8a/. Coloque AoqClientSdk.har en entry/libs y declare la dependencia en entry/oh-package.json5. El SDK es compatible con API 12 y admite arm64-v8a:
{
  "dependencies": {
    "@aoq/client-sdk": "file:./libs/AoqClientSdk.har"
  }
}
  1. Declare los siguientes permisos en entry/src/main/module.json5:
"requestPermissions": [
  { "name": "ohos.permission.INTERNET" },
  { "name": "ohos.permission.MICROPHONE",
    "reason": "$string:perm_mic_reason",
    "usedScene": { "abilities": ["EntryAbility"], "when": "inuse" } },
  { "name": "ohos.permission.CAMERA",
    "reason": "$string:perm_camera_reason",
    "usedScene": { "abilities": ["EntryAbility"], "when": "inuse" } }
]
  1. Antes de utilizar los dispositivos correspondientes, llame a abilityAccessCtrl.createAtManager().requestPermissionsFromUser para solicitar ohos.permission.MICROPHONE y ohos.permission.CAMERA.

Linux (Python)

  1. Extraiga el SDK y conserve aoq_client_sdk.py, libAoqClientSdk.so y libonnxruntime.so.1.16.3 en el mismo directorio.
  2. Agregue el directorio del SDK a las rutas de búsqueda de Python y de bibliotecas dinámicas:
export PYTHONPATH="$PWD/AoqClientSdk:$PYTHONPATH"
export LD_LIBRARY_PATH="$PWD/AoqClientSdk:$LD_LIBRARY_PATH"
  1. Utilice import aoq_client_sdk en Python. También puede especificar la ruta absoluta de libAoqClientSdk.so mediante AOQ_CLIENT_SDK_LIB.

Flujo de implementación

  1. El servidor de aplicaciones obtiene los parámetros de conexión AOQ para qwen3.8-omni-flash-realtime desde la URL del token Realtime.
  2. El cliente crea el motor y configura los códecs y pistas de audio. También configura la pista Video si se requiere comprensión visual continua.
  3. El cliente inicia la captura y reproducción locales, deshabilita el envío de la pista Audio por defecto, se conecta a AOQ y envía session.update.
  4. Después de recibir session.updated, la opción de video continuo habilita la pista Video. La pista Audio permanece deshabilitada hasta que el usuario presiona el botón de hablar.
  5. Cuando el usuario presiona el botón, el cliente habilita la pista Audio. Al soltarlo, deshabilita la pista Audio, opcionalmente envía una imagen y luego envía input_audio_buffer.commit y response.create.
  6. Después de recibir response.done, puede comenzar otro turno. Para finalizar, detenga los dispositivos, desconéctese y destruya el motor.

Pista Video continua

Publique la pista Video y habilite el envío de video después de session.updated. El modelo ve continuamente los fotogramas más recientes. Cada turno de voz solo necesita confirmar el audio y solicitar una respuesta.

Diagrama de secuencia para el modo Manual de AOQ con transmisión de video continua

Enviar una imagen a través de la pista Data

No publique la pista Video. Cuando se requiera una imagen, envíe input_image_buffer.append después de soltar el botón y luego confirme el audio y solicite una respuesta.

Diagrama de secuencia para enviar imágenes bajo demanda en el modo Manual de AOQ

Obtener un token del servidor de aplicaciones

Establezca DASHSCOPE_API_KEY en el servidor de aplicaciones y envíe la solicitud al endpoint de la región seleccionada. clientIp es la dirección IP pública real del cliente. Este campo es opcional, pero especificarlo ayuda al servicio a asignar un endpoint de retransmisión adecuado.

curl -X POST \
  "https://{endpoint}/api/v1/webrtc/realtime?model=qwen3.8-omni-flash-realtime" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer ${DASHSCOPE_API_KEY}" \
  -H "x-dashscope-rtc-transport: moq" \
  -d "{\"clientIp\": \"${CLIENT_REAL_IP}\"}"

NotaSi el servidor de aplicaciones no puede obtener la dirección IP pública real del cliente, omita clientIp en lugar de pasar una cadena vacía.

El servidor de aplicaciones devuelve los siguientes campos de respuesta al cliente. Nunca devuelva la clave API a un cliente en producción. Para todos los campos de solicitud y respuesta, consulte Autenticación por token.

Campo de respuesta

Campo del SDK

aoqTokenForClient

AoqConnectConfig.token

sid

AoqConnectConfig.sid

clientRelayCertFingerprint

AoqConnectConfig.certFingerprint

clientRelayEndpoints

AoqConnectConfig.relayEndpoints

extraInfo.workspaceIdHash

AoqConnectConfig.workspaceIdHash

Implementar el cliente iOS

Después de que el cliente obtenga AoqConnectConfig del servidor de aplicaciones, siga estos pasos para implementar conversaciones de voz push-to-talk en iOS.

1. Crear el motor y registrar devoluciones de llamada

Cree el motor AOQ singleton y registre el objeto de la aplicación como receptor de callbacks. Gestione los estados de conexión, eventos del servidor, errores y advertencias en los callbacks.

let createConfig = AoqCreateConfig()
createConfig.workDir = workDir
engine = AoqClientEngine.createEngine(createConfig, delegate: self)

2. Iniciar dispositivos de audio y video

Inicialice la captura y reproducción de audio. Inicie la cámara solo para la opción de video continuo. Obtenga los permisos de micrófono y cámara antes de llamar a estos métodos.

let captureConfig = AoqAudioCaptureConfig()
captureConfig.channel = 1
captureConfig.isExternal = false
engine.startAudioCapture(captureConfig)

let playbackConfig = AoqAudioPlaybackConfig()
playbackConfig.channel = 1
playbackConfig.isExternal = false
playbackConfig.isDefaultSpeaker = true
engine.startAudioPlayer(playbackConfig)

3. Configurar códecs y pistas

Configure los códecs de audio para el modelo seleccionado y el formato de audio de la aplicación, y seleccione pistas para la opción de entrada de imagen. Los siguientes valores de audio y video son ejemplos. Ajústelos según los requisitos del modelo y el escenario de la aplicación. Deshabilite el envío de la pista Audio antes de establecer la conexión.

Pista Video continua

Configure las pistas de publicación Audio, Video y Data. Ajuste la configuración de codificación de video según la calidad de imagen requerida y el ancho de banda disponible.

let audioEncoderConfig = AoqAudioCodecConfig()
audioEncoderConfig.trackType = .audio
audioEncoderConfig.codecType = .audioOpus
audioEncoderConfig.sampleRate = 16_000
audioEncoderConfig.channel = 1
engine.setAudioEncoderConfig(audioEncoderConfig)

let audioDecoderConfig = AoqAudioCodecConfig()
audioDecoderConfig.trackType = .audio
audioDecoderConfig.codecType = .audioOpus
audioDecoderConfig.sampleRate = 24_000
audioDecoderConfig.channel = 1
engine.setAudioDecoderConfig(audioDecoderConfig)

let videoEncoderConfig = AoqVideoCodecConfig()
videoEncoderConfig.trackType = .video
videoEncoderConfig.codecType = .videoJpeg
videoEncoderConfig.width = 960
videoEncoderConfig.height = 540
videoEncoderConfig.fps = 2
videoEncoderConfig.bitrate = 500_000
engine.setVideoEncoderConfig(videoEncoderConfig)

let publishAudioTrack = AoqTrackParam()
publishAudioTrack.trackType = .audio
let publishVideoTrack = AoqTrackParam()
publishVideoTrack.trackType = .video
let publishDataTrack = AoqTrackParam()
publishDataTrack.trackType = .data
let subscribeAudioTrack = AoqTrackParam()
subscribeAudioTrack.trackType = .audio
let subscribeDataTrack = AoqTrackParam()
subscribeDataTrack.trackType = .data
connectConfig.publishTracks = [publishAudioTrack, publishVideoTrack, publishDataTrack]
connectConfig.subscribeTracks = [subscribeAudioTrack, subscribeDataTrack]

Enviar una imagen a través de la pista Data

Configure solo las pistas Audio y Data. No configure un codificador de video, lo cual evita la captura, codificación y transmisión continua de video. Los valores de audio son ejemplos.

let audioEncoderConfig = AoqAudioCodecConfig()
audioEncoderConfig.trackType = .audio
audioEncoderConfig.codecType = .audioOpus
audioEncoderConfig.sampleRate = 16_000
audioEncoderConfig.channel = 1
engine.setAudioEncoderConfig(audioEncoderConfig)

let audioDecoderConfig = AoqAudioCodecConfig()
audioDecoderConfig.trackType = .audio
audioDecoderConfig.codecType = .audioOpus
audioDecoderConfig.sampleRate = 24_000
audioDecoderConfig.channel = 1
engine.setAudioDecoderConfig(audioDecoderConfig)

let publishAudioTrack = AoqTrackParam()
publishAudioTrack.trackType = .audio
let publishDataTrack = AoqTrackParam()
publishDataTrack.trackType = .data
let subscribeAudioTrack = AoqTrackParam()
subscribeAudioTrack.trackType = .audio
let subscribeDataTrack = AoqTrackParam()
subscribeDataTrack.trackType = .data
connectConfig.publishTracks = [publishAudioTrack, publishDataTrack]
connectConfig.subscribeTracks = [subscribeAudioTrack, subscribeDataTrack]

4. Configurar una sesión Manual

Después de establecer la conexión, llame a sendDataMsg para enviar un evento session.update. Establezca turn_detection en null y seleccione la voz, las instrucciones y las modalidades de salida para su aplicación. Mantenga los parámetros de audio del ejemplo consistentes con la configuración del códec del SDK. Para todos los campos, consulte Eventos del cliente.

private func sendSessionUpdate() {
    let event: [String: Any] = [
        "type": "session.update",
        "session": [
            "modalities": ["text", "audio"],
            "voice": "Tina",
            "audio": [
                "input": ["format": ["type": "pcm", "sample_rate": 16_000]],
                "output": ["format": ["type": "pcm", "sample_rate": 24_000]]
            ],
            "turn_detection": NSNull()
        ]
    ]
    guard let data = try? JSONSerialization.data(withJSONObject: event) else { return }
    let dataMessage = AoqDataMsg()
    dataMessage.data = data
    engine.sendDataMsg(dataMessage)
}

5. Esperar la configuración de la sesión

Gestione el evento session.updated en el callback onDataMsg. No envíe medios hasta que se reciba este evento. Para la opción de video continuo, llame a enableSendMediaStream para habilitar la pista Video en este punto, pero mantenga la pista Audio deshabilitada para que el audio anterior a que el usuario presione el botón no ingrese al búfer de entrada.

func onDataMsg(_ msg: AoqDataMsg) {
    guard let event = try? JSONSerialization.jsonObject(with: msg.data) as? [String: Any],
          let type = event["type"] as? String else { return }
    if type == "session.updated", imageMode == .continuousVideo {
        engine.enableSendMediaStream(.video, enable: true)
    }
    // Keep Audio-track sending disabled until the talk button is pressed.
}

6. Implementar la interacción push-to-talk

Cuando se presiona el botón, llame a enableSendMediaStream para habilitar la pista Audio. Al soltarlo, llame a enableSendMediaStream para deshabilitar la pista Audio, asegúrese de que el turno contenga audio, opcionalmente envíe una imagen y llame a sendDataMsg para enviar input_audio_buffer.commit seguido de response.create.

func onPushToTalkPressed() {
    hasAudioInCurrentTurn = true
    engine.enableSendMediaStream(.audio, enable: true)
}

func onPushToTalkReleased(base64Jpeg: String? = nil) {
    engine.enableSendMediaStream(.audio, enable: false)
    guard hasAudioInCurrentTurn else { return }
    if imageMode == .singleImage, let base64Jpeg {
        let imageEvent: [String: Any] = [
            "type": "input_image_buffer.append",
            "image": base64Jpeg
        ]
        if let data = try? JSONSerialization.data(withJSONObject: imageEvent) {
            let dataMessage = AoqDataMsg()
            dataMessage.data = data
            engine.sendDataMsg(dataMessage)
        }
    }
    for event in [
        ["type": "input_audio_buffer.commit"],
        ["type": "response.create"]
    ] {
        guard let data = try? JSONSerialization.data(withJSONObject: event) else { continue }
        let dataMessage = AoqDataMsg()
        dataMessage.data = data
        engine.sendDataMsg(dataMessage)
    }
    hasAudioInCurrentTurn = false
}

7. Seleccionar una opción de entrada de imagen

La comprensión visual continua y las preguntas ocasionales sobre imágenes utilizan diferentes configuraciones de pista y comportamiento de envío. Seleccione una opción según el ancho de banda, el consumo de energía y el diseño de interacción.

Pista Video continua

Utilice esta opción para videollamadas, escenas que cambian rápidamente o contexto visual continuo. Después de publicar la pista Video, no envíe input_image_buffer.append.

Enviar una sola imagen a través de la pista Data

Utilice esta opción para preguntas sobre imágenes o imágenes ocasionales. Convierta la imagen a JPG o JPEG, codifíquela en Base64 y envíela después de soltar el botón y antes de confirmar el audio:

{
  "type": "input_image_buffer.append",
  "image": "<Base64-encoded JPEG data>"
}
  • Utilice 480p o 720p para obtener el mejor rendimiento. No exceda 1080p.
  • La imagen codificada en Base64 no puede exceder 256 KB. Mantenga la imagen fuente en 190 KB o menos y reserve espacio para el contenedor JSON.
  • La pista Audio debe haber enviado al menos un fotograma de audio en el turno antes de enviar la imagen. El evento subsiguiente input_audio_buffer.commit confirma tanto los búferes de audio como de imagen.

8. Desconectar y destruir el motor

Cuando finalice la sesión, desconéctese y destruya el motor. disconnect o destroy cierran automáticamente los dispositivos multimedia, por lo que no necesita llamar a los métodos stop por separado. AoqClientEngine es un singleton y no se puede crear nuevamente hasta que se llame a destroy.

engine.disconnect()
AoqClientEngine.destroy()

Ejemplo completo

La siguiente clase acepta un AoqConnectConfig que se asignó desde la respuesta de token del servidor de aplicaciones. Agregue estado de UI, permisos, recuperación de errores y compresión de imágenes en producción.

import Foundation
import AoqClientSdk

final class ManualPushToTalkClient: NSObject, AoqEngineDelegate {
    enum ImageMode: Equatable {
        case none
        case continuousVideo
        case singleImage
    }

    private var engine: AoqClientEngine!
    private let imageMode: ImageMode
    private var hasAudioInCurrentTurn = false

    init(workDir: String, connectConfig: AoqConnectConfig, imageMode: ImageMode) {
        self.imageMode = imageMode
        super.init()
        let createConfig = AoqCreateConfig()
        createConfig.workDir = workDir
        self.engine = AoqClientEngine.createEngine(createConfig, delegate: self)

        // Example values. Match these settings to the selected model and application format.
        let audioEncoderConfig = AoqAudioCodecConfig()
        audioEncoderConfig.trackType = .audio
        audioEncoderConfig.codecType = .audioOpus
        audioEncoderConfig.sampleRate = 16_000
        audioEncoderConfig.channel = 1
        engine.setAudioEncoderConfig(audioEncoderConfig)

        let audioDecoderConfig = AoqAudioCodecConfig()
        audioDecoderConfig.trackType = .audio
        audioDecoderConfig.codecType = .audioOpus
        audioDecoderConfig.sampleRate = 24_000
        audioDecoderConfig.channel = 1
        engine.setAudioDecoderConfig(audioDecoderConfig)

        let publishAudioTrack = AoqTrackParam()
        publishAudioTrack.trackType = .audio
        let publishDataTrack = AoqTrackParam()
        publishDataTrack.trackType = .data
        let subscribeAudioTrack = AoqTrackParam()
        subscribeAudioTrack.trackType = .audio
        let subscribeDataTrack = AoqTrackParam()
        subscribeDataTrack.trackType = .data

        connectConfig.publishTracks = [publishAudioTrack, publishDataTrack]
        connectConfig.subscribeTracks = [subscribeAudioTrack, subscribeDataTrack]

        if imageMode == .continuousVideo {
            let videoEncoderConfig = AoqVideoCodecConfig()
            videoEncoderConfig.trackType = .video
            videoEncoderConfig.codecType = .videoJpeg
            videoEncoderConfig.width = 960
            videoEncoderConfig.height = 540
            videoEncoderConfig.fps = 2
            videoEncoderConfig.bitrate = 500_000
            engine.setVideoEncoderConfig(videoEncoderConfig)

            let publishVideoTrack = AoqTrackParam()
            publishVideoTrack.trackType = .video
            connectConfig.publishTracks = [publishAudioTrack, publishVideoTrack, publishDataTrack]
        }

        let captureConfig = AoqAudioCaptureConfig()
        captureConfig.channel = 1
        captureConfig.isExternal = false
        engine.startAudioCapture(captureConfig)

        let playbackConfig = AoqAudioPlaybackConfig()
        playbackConfig.channel = 1
        playbackConfig.isExternal = false
        playbackConfig.isDefaultSpeaker = true
        engine.startAudioPlayer(playbackConfig)

        if imageMode == .continuousVideo {
            let videoCaptureConfig = AoqVideoCaptureConfig()
            videoCaptureConfig.width = 1280
            videoCaptureConfig.height = 720
            videoCaptureConfig.fps = 15
            engine.startVideoCapture(videoCaptureConfig)
        }

        engine.enableSendMediaStream(.audio, enable: false)
        if imageMode == .continuousVideo {
            engine.enableSendMediaStream(.video, enable: false)
        }
        engine.connect(connectConfig)
    }

    func onPushToTalkPressed() {
        hasAudioInCurrentTurn = true
        engine.enableSendMediaStream(.audio, enable: true)
    }

    func onPushToTalkReleased(base64Jpeg: String? = nil) {
        engine.enableSendMediaStream(.audio, enable: false)
        guard hasAudioInCurrentTurn else { return }
        if imageMode == .singleImage, let base64Jpeg {
            let imageEvent: [String: Any] = [
                "type": "input_image_buffer.append",
                "image": base64Jpeg
            ]
            if let data = try? JSONSerialization.data(withJSONObject: imageEvent) {
                let dataMessage = AoqDataMsg()
                dataMessage.data = data
                engine.sendDataMsg(dataMessage)
            }
        }
        for event in [
            ["type": "input_audio_buffer.commit"],
            ["type": "response.create"]
        ] {
            guard let data = try? JSONSerialization.data(withJSONObject: event) else { continue }
            let dataMessage = AoqDataMsg()
            dataMessage.data = data
            engine.sendDataMsg(dataMessage)
        }
        hasAudioInCurrentTurn = false
    }

    private func sendSessionUpdate() {
        let event: [String: Any] = [
            "type": "session.update",
            "session": [
                "modalities": ["text", "audio"],
                "voice": "Tina",
                "audio": [
                    "input": ["format": ["type": "pcm", "sample_rate": 16_000]],
                    "output": ["format": ["type": "pcm", "sample_rate": 24_000]]
                ],
                "turn_detection": NSNull()
            ]
        ]
        guard let data = try? JSONSerialization.data(withJSONObject: event) else { return }
        let dataMessage = AoqDataMsg()
        dataMessage.data = data
        engine.sendDataMsg(dataMessage)
    }

    func close() {
        engine.disconnect()
        AoqClientEngine.destroy()
    }

    func onConnectionStatusChange(_ status: AoqConnectionStatus) {
        if status == .connected { sendSessionUpdate() }
    }

    func onDataMsg(_ msg: AoqDataMsg) {
        guard let event = try? JSONSerialization.jsonObject(with: msg.data) as? [String: Any],
              let type = event["type"] as? String else { return }
        if type == "session.updated", imageMode == .continuousVideo {
            engine.enableSendMediaStream(.video, enable: true)
        }
    }

    func onError(_ code: Int, message: String) {}
    func onWarning(_ code: Int, message: String) {}
    func onStats(_ stats: AoqStats) {}
    func onAudioDeviceStateChanged(_ state: AoqAudioDeviceState) {}
    func onAudioDeviceRouteChanged(_ routeType: Int) {}
    func onAudioDeviceInterrupted(_ interrupt: Bool) {}
    func onAudioFileState(_ state: AoqAudioFileState) {}
    func onVideoDeviceStateChanged(_ state: AoqVideoDeviceState) {}
}

Ejecutar y verificar

Complete un turno push-to-talk solo de audio y un turno con una imagen. Resultados esperados:

  1. La pista Audio está deshabilitada antes de presionar el botón y envía audio continuamente mientras se mantiene presionado el botón.
  2. Después de soltar el botón, input_audio_buffer.committed, response.created y response.done se reciben en secuencia, y el audio del modelo se reproduce a través de la pista Audio suscrita.
  3. Con la opción de imagen única, el modelo responde utilizando la imagen y el audio del turno. Con video continuo, utiliza los fotogramas de video más recientes.

Para consultar los campos de eventos del servidor y los esquemas de respuesta completos, consulte Eventos del servidor.

Consideraciones importantes

  1. AOQ transporta audio a través de la pista Audio. No envíe también input_audio_buffer.append.
  2. input_audio_buffer.commit solo confirma el turno y no desencadena una respuesta del modelo. Envíe response.create después.
  3. No confirme un búfer de audio vacío. El servicio devuelve un error.
  4. No habilite el envío de medios antes de session.updated. En modo Manual, no habilite la pista Audio antes de que el usuario presione el botón.

Información relacionada

Para todos los parámetros, campos de eventos e interfaces para otras plataformas, consulte: