Construir conversas de voz com qwen3.8-omni-flash-realtime sobre o AOQ
Use o QOA para se conectar qwen3.8-omni-flash-realtime E deixar o cliente controlar os limites para conversas de push-to-talk e perguntas de imagem opcionais. O código do cliente usa iOS Swift.
Visão geral da solução
Qwen-Omni-Realtime suporta VAD do lado do servidor e modo manual controlado pelo cliente. Este tutorial define sessão.turn_detection como null. O cliente envia áudio enquanto o usuário segura um botão, e comprime o áudio e explicitamente solicita uma resposta quando o usuário libera o botão.
Modo manual é adequado para botões de hardware intercomunicadores, controles de pressão e retenção, ambientes barulhentos em que a aplicação determina limites de giro, e gira que opcionalmente incluem uma imagem. O áudio é transportado pela faixa de áudio do AOQ. Não envie entrada, entrada, entrada, entrada, entrada.
| Item | Modo VAD | Modo manual |
|---|---|---|
| Vire o limite. | Detectado por servidor_vad ou semântica_vad | Controlado por um botão ou estado de aplicação |
| Sessão de configuração | Turn_Detection contém configurações de DAV | A detecção de turnos é nula. |
| Commit de áudio | Realizado automaticamente pelo serviço | O cliente envia entrada_audio_buffer.commit |
| - Ativador de resposta. | Acionado automaticamente pelo serviço. | O cliente envia resposta. |
| Entrada da imagem | Track vídeo contínuo ou uma imagem sobre a faixa de dados | Track vídeo contínuo ou uma imagem sobre a faixa de dados |
Pré-requisitos
- Ativar QwenCloud e obter uma chave API seguindo [Obter e configurar uma chave API] (/api-reference/preparation/api-key). Guarde a chave da API apenas no servidor de aplicativos. Não inclua em código de cliente ou o entregue em um repositório de códigos.
- Baixe o mais recente cliente do AOQ SDK como descrito em [SDK download] (/api-reference/realtime-api/sdk-download).
- Construa um servidor de aplicativos e implemente a autenticação proxy como descrito em Autenticação do Token. Antes de cada nova conexão, o cliente deve obter novas credenciais de conexão do servidor de aplicativos.
Importar o SDK
Importar o SDK para sua plataforma de desenvolvimento. A implementação do cliente usa iOS Swift. Outras plataformas fornecem as mesmas interfaces e fluxo de eventos. Este tutorial usa fluxos de áudio Opus. Importar o plugin Opus antes de prosseguir.
Android
1. Coloque a libPluginOpus.so do plugin Opus em app/src/main/jniLibs/armeabi-v7a/ e app/src/main/jniLibs/arm64-v8a/ para os ABIs correspondentes. Coloque AoqClientSdk-release.aar em app/libs, e configure a dependência e ABIs suportados por SDK em app/build.gradle:
```groovy
android {
defaultConfig {
minSdk 21
ndk { abiFilters 'armeabi-v7a', 'arm64-v8a' }
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.aar'])
}
```
2. Declare as seguintes permissões no AndroidManifest.xml:
```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" />
```
3. Solicitar permissão de registro e câmera antes de usar os dispositivos correspondentes.
iOS
1. Adicione AoqClientSdk.framework e PluginOpus.framework ao projeto Xcode e selecione Incorporar e assinar em Target > General > Frameworks, Bibliotecas e Conteúdo Incorporado. O SDK suporta dispositivos arm64 rodando iOS 13.0 ou posterior.
2. Adicione NSMicrophoneUsageDescription e NSCameraUsageDescription para Info.plist e solicite autorização antes dos dispositivos correspondentes serem usados.
3. Use `import AoqClientSdk` em Swift ou `#import <AoqClientSdk/AoqClientSdk.h>` no Objetivo-C.
HarmonyOS
1. Coloque libPluginOpus.so do plugin Opus em entrada/libs/arm64-v8a/. Coloque AoqClientSdk.har em entrada/libs e declare a dependência em entrada/oh-pacote.json5. O SDK é compatível com API 12 e suporta arm64-v8a:
```json
{
"dependencies": {
"@aoq/client-sdk": "file:./libs/AoqClientSdk.har"
}
}
```
2. Declare as seguintes permissões em entrada/src/main/module.json5:
```json
"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" } }
]
```
3. Antes que os dispositivos correspondentes sejam usados, ligue para `abilityAccessCtrl.createAtManager().requestPermissionsFromUser` para pedir `ohos.permission.MICROPHONE` e `ohos.permission.CAMERA`.
Linux (Python)
1. Extrair o SDK e manter aoq\_client\_sdk.py, libAoqClientSdk.so, e libonnxruntime.so.1.16.3 no mesmo diretório.
2. Adicione o diretório SDK aos caminhos de pesquisa de bibliotecas dinâmicas e Python:
```bash
export PYTHONPATH="$PWD/AoqClientSdk:$PYTHONPATH"
export LD_LIBRARY_PATH="$PWD/AoqClientSdk:$LD_LIBRARY_PATH"
```
3. Use `import aoq_client_sdk` em Python. Você também pode especificar o caminho absoluto da libAoqClientSdk.so usando `AOQ_CLIENT_SDK_LIB`.
Fluxo de implementação
- O servidor de aplicativos obtém parâmetros de conexão AOQ para qwen3.8-omni-flash-realtime da URL do símbolo em tempo real.
- O cliente cria o motor e configura codecs e faixas de áudio. Também configura a faixa de vídeo se for necessário um entendimento visual contínuo.
- O cliente inicia a captura e reprodução local, desativa o envio de áudio por padrão, conecta-se ao AOQ e envia session.update.
- Após a sessão. A atualização é recebida, a opção de vídeo contínuo permite a faixa de vídeo. A faixa de áudio permanece desativada até o usuário apertar o botão de falar.
- Quando o usuário aperta o botão, o cliente ativa a faixa de áudio. Quando é lançado, ele desativa a faixa de áudio, envia uma imagem opcionalmente, e então envia entrada_audio_buffer.commit e response.create.
- Depois da resposta. Feito é recebido, outra volta pode começar. Para terminar, pare os dispositivos, desligue e destrua o motor.
Continuous Video track
Publique a faixa de vídeo e habilite o envio de vídeo após a sessão. O modelo vê continuamente as últimas molduras. Cada voz gira só precisa fazer áudio e pedir uma resposta.
[Diagrama de sequência para modo manual AOQ com transmissão contínua de vídeo] (http://icms-x-dita-hz.oss-cn-hangzhou.aliyuncs.com/en-US/images/p1094863.png)
Send an image over the Data track
Não publique a faixa de vídeo. Quando uma imagem é necessária, envie entrada\_image\_buffer.append após o botão ser liberado, e então commita o áudio e peça uma resposta.
[Diagrama de sequência para enviar imagens sob demanda no modo manual AOQ] (http://icms-x-dita-hz.oss-cn-hangzhou.aliyuncs.com/en-US/images/p1094864.png)
Obter um token do servidor de aplicativos
Defina DASHSCOPE_API_KEY no servidor de aplicativos e envie o pedido para o ponto final. clientIp é o endereço IP público do cliente. Este campo é opcional, mas especificando que ajuda o serviço alocar um ponto final adequado.
curl -X POST \
"https://maas.qwencloudapi.com/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}\"}"
Se o servidor de aplicativos não conseguir o endereço IP público do cliente, omita. clientIp em vez de passar uma corda vazia.
O servidor de aplicativos devolve os seguintes campos de resposta ao cliente. Nunca devolva a chave da API para um cliente em produção. Para todos os campos de solicitação e resposta, veja [Autenticação do Token] (/api-reference/realtime-api/token-auth).
| Campo de resposta. | Campo SDK |
|---|---|
| AoqTokenForClient | AoqConnectConfig.token |
| Sid. | AoqConnectConfig.sid |
| CLIENTE RELAYCertFingerprint | AoqConnectConfig.certFingerprint |
| CLIENTE RELAYEndpoints | AoqConnectConfig.relayEndpoints |
| ExtraInfo. Espaço de trabalhoIdHash | AoqConnectConfig. Espaço de trabalhoIdHash |
Implemente o cliente iOS
Depois que o cliente obter AoqConnectConfig do servidor de aplicativos, siga estes passos para implementar conversas de voz push-to-talk no iOS.
1. Crie o motor e registre chamadas de retorno
Crie o motor de som único e registre o objeto de aplicação como o receptor de retorno. Lide com estados de conexão, eventos de servidores, erros e avisos nas chamadas.
let createConfig = AoqCreateConfig()
createConfig.workDir = workDir
engine = AoqClientEngine.createEngine(createConfig, delegate: self)
- Dois. Iniciem os dispositivos de áudio e vídeo.
Inicialize a captura e reprodução de áudio. Ligue a câmera apenas para a opção de vídeo contínuo. Obter permissão de microfone e câmera antes que esses métodos sejam chamados.
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. Configure codecs e facas
Configure os codecs de áudio para o modelo selecionado e o formato de áudio do aplicativo, e selecione faixas para a opção de entrada de imagem. Os seguintes valores de áudio e vídeo são exemplos. Ajuste-os para os requisitos do modelo e cenário de aplicação. Desativar o envio de áudio antes da conexão ser estabelecida.
Continuous Video track
Configure as faixas de áudio, vídeo e dados. Ajuste as configurações de codificação de vídeo para a qualidade de imagem necessária e largura de banda disponível.
```swift
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]
```
Send an image over the Data track
Configure apenas as faixas de áudio e dados. Não configure um codificador de vídeo, que evite a captura, codificação e transmissão contínuas de vídeo. Os valores de áudio são exemplos.
```swift
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]
```
- Quatro. Configure uma sessão manual
Depois que a conexão for estabelecida, ligue para enviar DataMsg para enviar um evento de atualização. Ajuste a volta para anular e selecione as modalidades de voz, instruções e saída para sua aplicação. Mantenha os parâmetros de áudio do exemplo consistentes com as configurações do codec SDK. Para todos os campos, veja [Eventos do cliente] (/api-reference/real-time-multimodal/client-events).
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)
}
- Cinco. Espere pela configuração da sessão.
Lide com a sessão. Atualizado evento na chamada onDataMsg. Não enviem a mídia até que este evento seja recebido. Para a opção de vídeo contínuo, ligue para ativar o sinal de vídeo neste momento, mas mantenha a faixa de áudio desativada para que o áudio antes que o usuário pressione o botão não entre no buffer 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.
}
Seis. Implementar interação de push-to-talk
Quando o botão é pressionado, a chamada habilita o SendMediaStream para ativar a faixa de áudio. Na liberação, a chamada habilita oSendMediaStream para desativar a faixa de áudio, certifique-se de que a volta contenha áudio, envie uma imagem opcionalmente, e ligue para o sendDataMsg para enviar entrada_audio_buffer.commit seguido de resposta.criar.
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? - 7? Selecione uma opção de entrada de imagem
A compreensão visual contínua e as perguntas ocasionais de imagem usam diferentes configurações de trilhas e enviam comportamento. Selecione uma opção baseada em largura de banda, consumo de energia e design de interação.
Continuous Video track
Use esta opção para chamadas de vídeo, mudanças rápidas de cenas, ou contexto visual contínuo. Depois que a faixa de vídeo for publicada, não envie entrada\_image\_buffer.append.
Send a single image over the Data track
Use esta opção para perguntas de imagem ou imagens ocasionais. Converta a imagem para JPG ou JPEG, base64-codificá-la, e enviá-la após o botão é liberado e antes que o áudio é committed:
```json
{
"type": "input_image_buffer.append",
"image": "<Base64-encoded JPEG data>"
}
```
- Use 480p ou 720p para melhor desempenho. Não exceda 1080p.
- A imagem codificada pela Base64 não pode exceder 256 KB. Mantenha a imagem de origem abaixo de 190 KB e reserve espaço para o papel JSON.
- A faixa de áudio deve ter enviado pelo menos um quadro de áudio na volta antes da imagem ser enviada. O evento de entrada seguinte\_audio\_buffer.commit commits both audio and image buffers.
Oito. Desligue e destrua o motor.
Quando a sessão terminar, desligue e destrua o motor. Desligue ou destrua automaticamente dispositivos de mídia, então não precisa chamar os métodos de parada separadamente. AoqClientEngine é um singleton e não pode ser criado de novo até que a destruição seja chamada.
engine.disconnect()
AoqClientEngine.destroy()
Exemplo completo.
A seguinte classe aceita um AoqConnectConfig que foi mapeado a partir da resposta do servidor de aplicativos. Adicione estado de UI, permissões, recuperação de erros e compressão de imagem na produção.
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) {}
}
Corra e verifique.
Complete uma volta de áudio e uma volta com uma imagem. Resultados esperados:
- A faixa de áudio está desativada antes do botão ser pressionado e enviar áudio continuamente enquanto o botão é mantido.
- Após a liberação, input_audio_buffer.committed, response.created, and response.done são recebidos em sequência, e áudio modelo é reproduzido sobre a faixa de áudio subscrito.
- Com a opção de uma única imagem, o modelo responde usando a imagem e áudio da curva. Com vídeo contínuo, usa as últimas molduras de vídeo.
Para os campos de eventos do servidor e esquemas de resposta completos, veja Eventos de servidor.
Considerações importantes.
- O AOQ transporta áudio pela faixa de áudio. Não envie também entrada, áudio, buffer, append.
- Input_audio_buffer.commit só commite a volta e não desencadeia uma resposta modelo. Envie resposta. Crie depois.
- Não commita um buffer de áudio vazio. O serviço devolve um erro.
- Não habilite o envio de mídia antes da sessão. No modo manual, não habilite a faixa de áudio antes do usuário pressionar o botão.
Informação relacionada
Para todos os parâmetros, campos de eventos e interfaces para outras plataformas, veja:
- [Consiga e configure uma chave API] (/api-reference/preparation/api-key)
- [AOQ Cliente SDK visão geral] (/api-reference/realtime-api/aoq-sdk-intro)
- [SDK download] (/api-reference/realtime-api/sdk-download)
- [Autenticação do token] (/api-reference/realtime-api/token-auth)
- [Qwen-Omni-Realtime Guia do usuário./developer-guides/speech/realtime-multimodal-speech)
- [Construir modo VAD em tempo real conversas sobre AOQ] (/developer-guides/tutorials/realtime/aoq-omni-realtime)
- [Acontecimentos do cliente] (/api-reference/real-time-multimodal/client-events)
- [Eventos de servidor] (/api-reference/real-time-multimodal/server-events)