Utilisez AOQ pour vous connecter à qwen3,5-omni-plus-realtime et permettre au client de contrôler les limites de tour pour les conversations en mode push-to-talk, avec la possibilité d'inclure des questions basées sur des images. Le code client est implémenté en Swift pour iOS.
Présentation de la solution
Qwen-Omni-Realtime prend en charge la détection automatique de voix (VAD) côté serveur ainsi que le mode manuel contrôlé par le client. Ce tutoriel définit session.turn_detection sur null. Le client transmet l'audio tant que l'utilisateur maintient un bouton enfoncé, valide l'audio et demande explicitement une réponse lorsque l'utilisateur relâche le bouton.
Le mode manuel convient aux boutons d'interphone matériels, aux commandes de type « appuyer et maintenir », aux environnements bruyants où l'application détermine les limites de tour, ainsi qu'aux tours incluant éventuellement une image. L'audio est transporté via la piste audio AOQ. N'envoyez pas input_audio_buffer.append.
Élément | Mode VAD | Mode manuel |
Limite de tour | Détectée par server_vad ou semantic_vad | Contrôlée par un bouton ou l'état de l'application |
Paramètre de session |
|
|
Validation audio | Effectuée automatiquement par le service | Le client envoie |
Déclenchement de la réponse | Déclenché automatiquement par le service | Le client envoie |
Entrée d'image | Piste vidéo continue ou image via la piste de données | Piste vidéo continue ou image via la piste de données |
Prérequis
- Activez Model Studio et suivez les instructions de la rubrique Obtenir et configurer une clé API. Stockez la clé API uniquement sur votre serveur d'application. Ne l'incluez pas dans le code client et ne la commitez pas dans un dépôt de code.
- Confirmez l'endpoint AOQ pour la région dans laquelle votre application est déployée. Pour obtenir des conseils de sélection, consultez la rubrique Sélectionner une région, une étendue de déploiement et un endpoint.
- Téléchargez la dernière version du SDK Client AOQ comme décrit dans la rubrique Téléchargement du SDK.
- Développez un serveur d'application et mettez en œuvre l'authentification proxy comme indiqué dans la rubrique Authentification par jeton. Avant chaque nouvelle connexion, le client doit obtenir de nouvelles informations d'identification auprès du serveur d'application.
Importer le SDK
Importez le SDK correspondant à votre plateforme de développement. L'implémentation cliente utilise Swift pour iOS. Les autres plateformes proposent les mêmes interfaces et le même flux d'événements. Ce tutoriel utilise des flux audio PCM. L'encodage Opus est fourni par un plugin. Importez le plugin Opus si la liaison montante utilise Opus.
Android
-
Placez
AoqClientSdk-release.aardansapp/libs, puis configurez la dépendance et les ABI prises en charge par le SDK dansapp/build.gradle:android { defaultConfig { minSdk 21 ndk { abiFilters 'armeabi-v7a', 'arm64-v8a' } } } dependencies { implementation fileTree(dir: 'libs', include: ['*.aar']) } -
Déclarez les permissions suivantes dans
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" /> -
Demandez les permissions
RECORD_AUDIOetCAMERAau moment de l'exécution avant d'utiliser les périphériques correspondants.
iOS
- Ajoutez
AoqClientSdk.frameworkau projet Xcode et sélectionnez Embed & Sign sous Target > General > Frameworks, Libraries, and Embedded Content. Le SDK prend en charge les appareils arm64 exécutant iOS 13.0 ou version ultérieure. - Ajoutez
NSMicrophoneUsageDescriptionetNSCameraUsageDescriptionàInfo.plistet demandez l'autorisation avant d'utiliser les périphériques correspondants. - Utilisez
import AoqClientSdken Swift ou#import <AoqClientSdk/AoqClientSdk.h>en Objective-C.
HarmonyOS
-
Placez
AoqClientSdk.hardansentry/libset déclarez la dépendance dansentry/oh-package.json5. Le SDK est compatible avec l'API 12 et prend en charge arm64-v8a :{ "dependencies": { "@aoq/client-sdk": "file:./libs/AoqClientSdk.har" } } -
Déclarez les permissions suivantes dans
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" } } ] -
Avant d'utiliser les périphériques correspondants, appelez
abilityAccessCtrl.createAtManager().requestPermissionsFromUserpour demanderohos.permission.MICROPHONEetohos.permission.CAMERA.
Linux (Python)
-
Extrayez le SDK et conservez
aoq_client_sdk.py,libAoqClientSdk.soetlibonnxruntime.so.1.16.3dans le même répertoire. -
Ajoutez le répertoire du SDK aux chemins de recherche Python et des bibliothèques dynamiques :
export PYTHONPATH="$PWD/AoqClientSdk:$PYTHONPATH" export LD_LIBRARY_PATH="$PWD/AoqClientSdk:$LD_LIBRARY_PATH" -
Utilisez
import aoq_client_sdken Python. Vous pouvez également spécifier le chemin absolu delibAoqClientSdk.soen utilisantAOQ_CLIENT_SDK_LIB.
Flux d'implémentation
- Le serveur d'application obtient les paramètres de connexion AOQ pour qwen3,5-omni-plus-realtime à partir de l'URL du jeton Realtime.
- Le client crée le moteur et configure les codecs audio et les pistes. Il configure également la piste vidéo si une compréhension visuelle continue est requise.
- Le client démarre la capture et la lecture locales, désactive l'envoi sur la piste audio par défaut, se connecte à AOQ et envoie
session.update. - Une fois
session.updatedreçu, l'optioncontinuous-videoactive la piste vidéo. La piste audio reste désactivée jusqu'à ce que l'utilisateur appuie sur le bouton de parole. - Lorsque l'utilisateur appuie sur le bouton, le client active la piste audio. Au relâchement, il désactive la piste audio, envoie éventuellement une image, puis envoie
input_audio_buffer.commitetresponse.create. - Après réception de
response.done, un nouveau tour peut commencer. Pour terminer, arrêtez les périphériques, déconnectez-vous et détruisez le moteur.
Piste vidéo continue
Publiez la piste vidéo et activez l'envoi vidéo après session.updated. Le modèle voit continuellement les dernières images. Chaque tour vocal nécessite uniquement la validation de l'audio et la demande de réponse.

Envoyer une image via la piste de données
Ne publiez pas la piste vidéo. Lorsqu'une image est requise, envoyez input_image_buffer.append après le relâchement du bouton, puis validez l'audio et demandez une réponse.

Obtenir un jeton depuis le serveur d'application
Définissez la variable DASHSCOPE_API_KEY sur le serveur d'application et envoyez la requête à l'endpoint de la région sélectionnée. Le paramètre clientIp correspond à l'adresse IP publique réelle du client. Bien que ce champ soit facultatif, sa spécification aide le service à allouer un endpoint de relais approprié.
curl -X POST \
"https://{endpoint}/api/v1/webrtc/realtime?model=qwen3.5-omni-plus-realtime" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer ${DASHSCOPE_API_KEY}" \
-H "x-dashscope-rtc-transport: moq" \
-d "{\"clientIp\": \"${CLIENT_REAL_IP}\"}"
RemarqueSi le serveur d'application ne peut pas obtenir l'adresse IP publique réelle du client, omettez le paramètre clientIp au lieu de transmettre une chaîne vide.
Le serveur d'application renvoie les champs de réponse suivants au client. Ne communiquez jamais la clé API à un client en production. Pour tous les champs de requête et de réponse, consultez Authentification par jeton.
Champ de réponse | Champ SDK |
aoqTokenForClient | AoqConnectConfig.token |
sid | AoqConnectConfig.sid |
clientRelayCertFingerprint | AoqConnectConfig.certFingerprint |
clientRelayEndpoints | AoqConnectConfig.relayEndpoints |
extraInfo.workspaceIdHash | AoqConnectConfig.workspaceIdHash |
Implémenter le client iOS
Une fois que le client a obtenu AoqConnectConfig depuis le serveur d'application, suivez ces étapes pour mettre en œuvre des conversations vocales push-to-talk sur iOS.
1. Créer le moteur et enregistrer les callbacks
Créez le singleton AOQ engine et enregistrez l'objet application en tant que destinataire des callbacks. Gérez les états de connexion, les événements serveur, les erreurs et les avertissements dans les callbacks.
let createConfig = AoqCreateConfig()
createConfig.workDir = workDir
engine = AoqClientEngine.createEngine(createConfig, delegate: self)
2. Démarrer les périphériques audio et vidéo
Initialisez la capture et la lecture audio. Démarrez la caméra uniquement pour l'option continuous-video. Obtenez les autorisations microphone et caméra avant d'appeler ces méthodes.
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. Configurer les codecs et les tracks
Configurez les codecs audio pour le modèle sélectionné et le format audio de l'application, puis sélectionnez les tracks pour l'option image-input. Les valeurs audio et vidéo suivantes sont données à titre d'exemple. Ajustez-les selon les exigences du modèle et le scénario d'application. Désactivez l'envoi Audio-track avant l'établissement de la connexion.
Track Continuous Video
Configurez les tracks publish Audio, Video et Data. Ajustez les paramètres d'encodage vidéo pour obtenir la qualité d'image requise et tenir compte de la bande passante disponible.
let audioEncoderConfig = AoqAudioCodecConfig()
audioEncoderConfig.trackType = .audio
audioEncoderConfig.codecType = .audioPCM
audioEncoderConfig.sampleRate = 16_000
audioEncoderConfig.channel = 1
engine.setAudioEncoderConfig(audioEncoderConfig)
let audioDecoderConfig = AoqAudioCodecConfig()
audioDecoderConfig.trackType = .audio
audioDecoderConfig.codecType = .audioPCM
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]
Envoyer une image via la track Data
Configurez uniquement les tracks Audio et Data. Ne configurez pas d'encodeur vidéo, ce qui évite la capture, l'encodage et la transmission continus de la vidéo. Les valeurs audio sont données à titre d'exemple.
let audioEncoderConfig = AoqAudioCodecConfig()
audioEncoderConfig.trackType = .audio
audioEncoderConfig.codecType = .audioPCM
audioEncoderConfig.sampleRate = 16_000
audioEncoderConfig.channel = 1
engine.setAudioEncoderConfig(audioEncoderConfig)
let audioDecoderConfig = AoqAudioCodecConfig()
audioDecoderConfig.trackType = .audio
audioDecoderConfig.codecType = .audioPCM
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. Configurer une session Manual
Une fois la connexion établie, appelez sendDataMsg pour envoyer un événement session.update. Définissez turn_detection sur null et sélectionnez la voix, les instructions et les modalités de sortie pour votre application. Maintenez la cohérence des paramètres audio de l'exemple avec les paramètres codec du SDK. Pour tous les champs, consultez Événements client.
private func sendSessionUpdate() {
let event: [String: Any] = [
"type": "session.update",
"session": [
"modalities": ["text", "audio"],
"voice": "Ethan",
"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. Attendre la configuration de la session
Gérez l'événement session.updated dans le callback onDataMsg. N'envoyez aucun média tant que cet événement n'est pas reçu. Pour l'option continuous-video, appelez enableSendMediaStream pour activer la track Video à ce stade, mais maintenez la track Audio désactivée afin que l'audio précédant l'appui sur le bouton n'entre pas dans le tampon d'entrée.
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. Implémenter l'interaction push-to-talk
Lorsque le bouton est enfoncé, appelez enableSendMediaStream pour activer la track Audio. Au relâchement, appelez enableSendMediaStream pour désactiver la track Audio, assurez-vous que le turn contient de l'audio, envoyez éventuellement une image, puis appelez sendDataMsg pour envoyer input_audio_buffer.commit suivi 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. Sélectionnez une option d'entrée d'image
La compréhension visuelle continue et les questions ponctuelles sur des images utilisent des configurations de piste et des comportements d'envoi différents. Sélectionnez une option en fonction de la bande passante, de la consommation d'énergie et de la conception de l'interaction.
Continuous Video track
Utilisez cette option pour les appels vidéo, les scènes changeant rapidement ou le contexte visuel continu. Une fois la piste vidéo publiée, n'envoyez pas input_image_buffer.append.
Send a single image over the Data track
Utilisez cette option pour les questions sur image ou les images occasionnelles. Convertissez l'image au format JPG ou JPEG, encodez-la en Base64, puis envoyez-la après le relâchement du bouton et avant la validation de l'audio :
{
"type": "input_image_buffer.append",
"image": "<Base64-encoded JPEG data>"
}
- Privilégiez les résolutions 480p ou 720p pour des performances optimales. Ne dépassez pas 1080p.
- L'image encodée en Base64 ne doit pas dépasser 256 Ko. Maintenez l'image source à 190 Ko maximum afin de réserver de l'espace pour l'enveloppe JSON.
- La piste audio doit avoir envoyé au moins une trame audio lors du tour précédent l'envoi de l'image. L'événement
input_audio_buffer.commitsuivant valide simultanément les tampons audio et image.
8. Déconnectez et détruisez le moteur
Lorsque la session se termine, déconnectez et détruisez le moteur. Les méthodes disconnect ou destroy ferment automatiquement les périphériques multimédias ; il est donc inutile d'appeler séparément les méthodes d'arrêt. AoqClientEngine est un singleton et ne peut être recréé tant que destroy n'a pas été appelé.
engine.disconnect()
AoqClientEngine.destroy()
Exemple complet
La classe suivante accepte un objet AoqConnectConfig mappé à partir de la réponse du jeton du serveur d'application. En production, ajoutez la gestion de l'état de l'interface utilisateur, des permissions, de la récupération d'erreurs et de la compression d'image.
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 = .audioPCM
audioEncoderConfig.sampleRate = 16_000
audioEncoderConfig.channel = 1
engine.setAudioEncoderConfig(audioEncoderConfig)
let audioDecoderConfig = AoqAudioCodecConfig()
audioDecoderConfig.trackType = .audio
audioDecoderConfig.codecType = .audioPCM
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": "Ethan",
"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) {}
}
Exécution et vérification
Effectuez un tour push-to-talk audio seul, puis un tour incluant une image. Résultats attendus :
- La piste audio est désactivée avant l'appui sur le bouton et envoie l'audio en continu tant que le bouton est maintenu enfoncé.
- Après le relâchement, les événements
input_audio_buffer.committed,response.createdetresponse.donesont reçus séquentiellement, et l'audio généré par le modèle est lu via la piste audio abonnée. - Avec l'option image unique, le modèle répond en utilisant l'image et l'audio du tour. Avec la vidéo continue, il utilise les dernières trames vidéo.
Pour connaître les champs des événements serveur et les schémas de réponse complets, consultez la rubrique Événements serveur.
Points importants
- AOQ transporte l'audio via la piste Audio. N'envoyez pas également
input_audio_buffer.append. input_audio_buffer.commitvalide uniquement le tour et ne déclenche pas de réponse du modèle. Envoyez ensuiteresponse.create.- Ne validez pas un tampon audio vide. Le service renvoie une erreur.
- N'activez pas l'envoi multimédia avant
session.updated. En mode manuel, n'activez pas la piste Audio avant que l'utilisateur n'appuie sur le bouton.
Informations connexes
Pour tous les paramètres, champs d'événement et interfaces destinés aux autres plateformes, consultez :
- Obtenir et configurer une clé API
- Sélectionner une région, une étendue de déploiement et un endpoint
- Présentation du SDK client AOQ
- Téléchargement du SDK
- Authentification par jeton
- Guide d'utilisation Qwen-Omni-Realtime
- Créer des conversations en temps réel en mode VAD via AOQ
- Événements client
- Événements serveur