This tutorial uses Android to show how to integrate the AOQ Client SDK with qwen3.8-livetranslate-flash-realtime for real-time speech translation. Other platforms use similar integration and model-event handling flows with their corresponding SDK methods. All client-side examples below use Java.
For model capabilities, see Real-time speech and audio/video translation. For the roles of media and model events, see AOQ access.
Download the SDK
For the AOQ Client SDK and the Opus audio plugin, see SDK download. The audio transmission examples in this tutorial use Opus, so you must also import the plugin for your platform. For supported regions, languages, pricing, and rate limits, see Real-time speech and audio/video translation.
Import the SDK
- Android
- iOS
- HarmonyOS
Place If the host project already contains native libraries with the same names, check their versions and dependencies before packaging them to avoid including different versions of the same library.Declare the permissions in Request
AoqClientSdk-release.aar in app/libs/. Place libPluginOpus.so in app/libs/armeabi-v7a/ and app/libs/arm64-v8a/, according to the ABI.Declare the dependency in app/build.gradle:AndroidManifest.xml:RECORD_AUDIO permission at runtime and obtain user authorization. Speech-only translation does not require camera permission. Declare and request CAMERA only when you enable visual enhancement.The Java examples use the following imports:Obtain a token through your AppServer
Do not store the Model Studio API key on the client. Your AppServer uses the API key for the corresponding region and workspace to request temporary credentials for each translation connection. It returns the credentials over HTTPS to a client that has passed your application's authentication.
Set up an AppServer by following the AOQ authentication steps for Qwen-LiveTranslate-Realtime. Real-time translation uses the Realtime protocol. Specify the following when requesting credentials:
BAILIAN_ENDPOINT to the endpoint for your workspace: {WorkspaceId}.cn-beijing.maas.aliyuncs.com or {WorkspaceId}.ap-southeast-1.maas.aliyuncs.com. Read DASHSCOPE_API_KEY from a server-side environment variable or a secrets management service.
clientIp in the request body for access point scheduling.
Map the response fields to AoqConnectConfig on the client:
| Gateway response field | SDK field | Description |
|---|---|---|
aoqTokenForClient | token | Temporary token for this connection |
sid | sid | Identifier of this session |
clientRelayCertFingerprint | certFingerprint | Use the certificate fingerprint exactly as returned |
clientRelayEndpoints | relayEndpoints | Convert the complete access point list to the SDK structure |
extraInfo.workspaceIdHash | workspaceIdHash | Use the returned value. If it is absent, follow the SDK's requirements |
Implement real-time speech translation
Interaction flow

Create the engine and set callbacks
Call createEngine to create the engine and register callbacks for connection status, Data messages, and errors. Your application must retain the engine and listener objects throughout the session.
AoqClientListener to receive connection, model-message, and media-device events, and pass it when creating the engine.
Start audio capture and playback
After obtaining microphone permission, prepare audio capture and playback. Disable audio transmission before starting capture to prevent the engine from sending media automatically after connecting.
Starting capture does not mean the model is ready to receive audio. Prompt the user to speak only after receiving session.updated and successfully enabling transmission. This tutorial does not implement audio buffering before connection.
Configure codecs and establish the connection
The main scenario requires the following tracks:
| Direction | Track | Purpose |
|---|---|---|
| Publish | Audio | Send speech to the model |
| Publish | Data | Send session configuration and completion events |
| Subscribe | Audio | Receive translated speech |
| Subscribe | Data | Receive source text, translated text, and status events |
connect means that the call was accepted. Wait for onConnectionStatusChange to report a successful connection before sending the model configuration.
Configure the translation session
After connecting, send the following session.update event through the Data track. This configuration uses the default voice and does not enable voice cloning:
session.update parameters, see Real-time translation client events.
Encode the JSON as UTF-8 bytes and send it with sendDataMsg.
Enable media transmission after receiving session.updated
Parse the event type in onDataMsg.
The following snippet routes control events. For source-text and translated-text events, see Server events. After receiving session.finished, set your application's completion state and use the release method described in "Disconnect and destroy the engine" to finish cleanup.
AOQ and WebSocket differences: This example sends and receives audio directly through Audio tracks. Do not send
input_audio_buffer.append to upload the same audio again, or copy the WebSocket example and start another player when response.audio.delta is received. Translated audio is handled by the SDK audio subscription and player. The Data track carries subtitles and model events. For media and Data track usage, see AOQ access.Finish input and wait for the final translation
When the user stops translation, follow this order:
- Stop capture so that no new input is submitted.
- After finalizing input, disable upstream audio and send
session.finishonce. Keep the AOQ connection, Data subscription, and audio playback active. - Continue receiving the final source text, translated text, and translated speech. Wait for
session.finished. - Disconnect and release resources according to your local playback completion policy.
session.finish, see Real-time translation client events. For the fields and meaning of session.finished, see Real-time translation server events.
Disconnect and destroy the engine
After session.finished is received, the server has finished processing this session. This does not mean the local speaker has finished playing the last audio segment. If your application must play all translated speech, complete local playback before running the following methods.