Skip to main content

Qwen-Omni-Realtime

Qwen-Omni-Realtime processes streaming audio and image inputs (including video frames) and generates text and audio responses in real time.

Supported regions: China (Beijing), Singapore. Each region requires its own API key. Try it online: How to try Qwen-Omni-Realtime online

How to use

1. Establish connection

The general WebSocket and WebRTC connection examples use qwen3.8-omni-flash-realtime. Model-specific configuration examples use their indicated models. Qwen-Omni-Realtime supports WebSocket and WebRTC. WebSocket suits server-side integration with quick setup. WebRTC targets browser-based low-latency voice scenarios, transmitting audio over UDP with built-in echo cancellation and noise reduction.
  • WebSocket
  • WebRTC
  • AOQ
qwen3.8-omni-flash-realtime requires the workspace-specific endpoint below. Obtain an API key and workspace ID for the same region and workspace before connecting.
  • Native WebSocket
  • DashScope Python SDK
  • DashScope Java SDK
Connection parameters:
ParameterDescription
EndpointChina (Beijing) region: wss://{WorkspaceId}.cn-beijing.maas.aliyuncs.com/api-ws/v1/realtimeSingapore region: wss://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/api-ws/v1/realtimeReplace {WorkspaceId} with your actual workspace ID.
Query parameterUse the model query parameter to specify the model. Example: ?model=qwen3.8-omni-flash-realtime
Request headerUse a Bearer token for authentication: Authorization: Bearer DASHSCOPE_API_KEY
DASHSCOPE_API_KEY is the API key from Model Studio.
# pip install websocket-client
import json
import websocket
import os

API_KEY=os.getenv("DASHSCOPE_API_KEY")
# China (Beijing) region. Replace {WorkspaceId} with your Bailian workspace ID. URLs vary by region.
API_URL = "wss://{WorkspaceId}.cn-beijing.maas.aliyuncs.com/api-ws/v1/realtime?model=qwen3.8-omni-flash-realtime"

headers = [
    "Authorization: Bearer " + API_KEY
]

def on_open(ws):
    print(f"Connected to server: {API_URL}")
def on_message(ws, message):
    data = json.loads(message)
    print("Received event:", json.dumps(data, indent=2))
def on_error(ws, error):
    print("Error:", error)

ws = websocket.WebSocketApp(
    API_URL,
    header=headers,
    on_open=on_open,
    on_message=on_message,
    on_error=on_error
)

ws.run_forever()

2. Configure session

Send the session.update client event: Use session.update to configure output modalities, voice, audio format, and VAD. The following Qwen3.8-Omni-Flash-Realtime WebSocket Manual-mode configuration matches the minimal audio example. This example uses the Long An Ling Xin voice (longanlingxin):
{
  "type": "session.update",
  "session": {
    "modalities": [
      "text",
      "audio"
    ],
    "turn_detection": null,
    "audio": {
      "input": {
        "format": {
          "type": "pcm",
          "sample_rate": 16000,
          "sample_format": "s16le",
          "channels": 1,
          "packing": "interleaved",
          "channel_layout": "mono"
        }
      },
      "output": {
        "voice": "longanlingxin",
        "format": {
          "type": "pcm",
          "sample_rate": 24000
        }
      }
    }
  }
}
The following example uses the Ethan voice and semantic_vad configuration of Qwen3.5-Omni-Realtime.
{
    // A client-generated event ID.
    "event_id": "event_ToPZqeobitzUJnt3QqtWg",
    // The event type. Must be "session.update".
    "type": "session.update",
    // The session configuration.
    "session": {
        // The output modality. Set this to ["text"] for text-only output, or ["text", "audio"] for both text and audio output.
        "modalities": [
            "text",
            "audio"
        ],
        // The voice for the audio output.
        "voice": "Ethan",
        // The input audio format. Only "pcm" is supported. The input audio must be a PCM audio stream at a 16 kHz sample rate.
        "input_audio_format": "pcm",
        // The output audio format. Only "pcm" is supported. The output audio is a PCM audio stream at a 24 kHz sample rate.
        "output_audio_format": "pcm",
        // A system instruction to define the model's goal or role.
        "instructions": "You are an AI customer service agent for a five-star hotel. Answer customer inquiries about room types, facilities, prices, and booking policies accurately and in a friendly manner. Always respond with a professional and helpful attitude. Do not provide unconfirmed information or information beyond the scope of the hotel's services.",
        // Enables server-side voice activity detection (VAD). If enabled, the server automatically detects the start and end of speech.
        // If null, the client controls when to trigger model responses.
        "turn_detection": {
            // The VAD type. Valid values: "server_vad" and "semantic_vad". We recommend "semantic_vad" for the qwen3.5-omni-realtime series model.
            "type": "semantic_vad",
            // The VAD detection threshold. We recommend increasing this value in noisy environments and decreasing it in quiet environments.
            "threshold": 0.5,
            // The silence duration in milliseconds (ms) that signals the end of an utterance. The model triggers a response if this duration is exceeded.
            "silence_duration_ms": 800
        }
    }
}
For multichannel audio, video aggregation, MCP configuration, and SDK examples, see Advanced session configuration.

3. Input audio and images

Audio input is required; image input is optional. The input method depends on the protocol.
  • WebSocket
  • WebRTC
Send Base64-encoded audio and image data to the server buffer using the input_audio_buffer.append and input_image_buffer.append events.
Images can come from local files or real-time video stream captures.
With server-side VAD enabled, the server automatically submits data and triggers a response at end-of-utterance. With VAD disabled (manual mode), call the input_audio_buffer.commit event to submit data after sending.

4. Receive model responses

The response format depends on the configured output modality.
  • WebSocket
  • WebRTC

Model selection

Use Qwen3.8-Omni-Flash-Realtime for real-time audio/video conversations. It supports full-duplex interaction, accepts text, images, streaming audio, and video, and returns text and audio. It supports WebSocket, WebRTC, and AOQ connections. See Establish a connection.
Check the Model Studio console for model names, context, pricing, and snapshot versions. For concurrency rate limits, see Rate limiting.

Limitations

qwen3.8-omni-flash-realtime supports up to 196608 total input tokens. Input length is calculated using the same rules as Qwen3.5-Omni-Realtime.
  • Web search and tool calling are mutually exclusive.
  • A single WebSocket session can last up to 120 minutes. The connection closes automatically at this limit.
  • The model retains conversation history up to the following turn and duration limits. When exceeded, the oldest history is discarded. Max duration is the cumulative audio or video (image frame) duration retained in context. It is not the duration of the entire session.
    Video is input as extracted frames (recommended: 1 fps). Video max duration is the cumulative frame duration retained — for example, 240 s means only frames from the last 240 seconds are kept.

    Model

    Audio max turns

    Video max turns

    Audio max duration

    Video max duration

    qwen3.8-omni-flash-realtime

    100 turns

    50 turns

    600 seconds

    240 seconds

    qwen3.5-omni-plus-realtime

    100 turns

    50 turns

    600 seconds

    240 seconds

    qwen3.5-omni-flash-realtime

    80 turns

    50 turns

    480 seconds

    120 seconds

Getting started

Get an API key and set it as an environment variable. Select a programming language and follow the steps to start a real-time chat.
  • WebSocket
  • WebRTC

Minimal audio question and answer

Configure an API key and install websocket-client. Set REALTIME_WS_URL to the full regional WebSocket endpoint below with the workspace ID replaced; the example adds the model query parameter. Set PCM_FILE to a short 16 kHz, 16-bit little-endian, mono PCM speech file without a file header.This example uses Manual mode: wait for session configuration, send audio, commit the buffer, and request a response. Text is printed to the terminal; audio is saved to reply.pcm (24 kHz PCM, not a WAV file).Run the following commands in a macOS or Linux terminal. Replace the WebSocket endpoint with the regional URL for your workspace, without the model query parameter. The example adds it automatically.
python3 -m pip install websocket-client
export REALTIME_WS_URL="<workspace-websocket-url>"
export PCM_FILE="./input.pcm"
If you have a mono, 16 kHz, 16-bit PCM WAV file named input.wav, use Python to extract its PCM frames. This step checks the format; it does not resample audio.
import wave
from pathlib import Path

with wave.open("input.wav", "rb") as source:
    if (source.getnchannels(), source.getframerate(), source.getsampwidth(),
            source.getcomptype()) != (1, 16000, 2, "NONE"):
        raise ValueError("Expected mono 16 kHz, 16-bit PCM WAV audio.")
    Path("input.pcm").write_bytes(source.readframes(source.getnframes()))
Run the following client after preparing the input. The example uses the Long An Ling Xin voice (longanlingxin):
import base64
import json
import os
from pathlib import Path
from urllib.parse import parse_qsl, urlencode, urlsplit, urlunsplit
import websocket

parts = urlsplit(os.environ["REALTIME_WS_URL"])
query = dict(parse_qsl(parts.query))
query["model"] = "qwen3.8-omni-flash-realtime"
url = urlunsplit((parts.scheme, parts.netloc, parts.path, urlencode(query), ""))
audio = Path(os.environ["PCM_FILE"]).read_bytes()
if not audio or len(audio) % 2:
    raise ValueError("Provide non-empty 16-bit mono PCM audio.")

ws = websocket.create_connection(
    url,
    header=["Authorization: Bearer " + os.environ["DASHSCOPE_API_KEY"]],
    timeout=30,
)

def receive():
    event = json.loads(ws.recv())
    if event["type"] == "error":
        raise RuntimeError(event.get("error"))
    return event

try:
    while receive()["type"] != "session.created":
        pass
    ws.send(json.dumps({
        "type": "session.update",
        "session": {
            "modalities": ["text", "audio"],
            "turn_detection": None,
            "audio": {
                "input": {"format": {
                    "type": "pcm", "sample_rate": 16000,
                    "sample_format": "s16le", "channels": 1,
                    "packing": "interleaved", "channel_layout": "mono",
                }},
                "output": {
                    "voice": "longanlingxin",
                    "format": {"type": "pcm", "sample_rate": 24000},
                },
            },
        },
    }))
    while receive()["type"] != "session.updated":
        pass
    for offset in range(0, len(audio), 3200):
        ws.send(json.dumps({
            "type": "input_audio_buffer.append",
            "audio": base64.b64encode(audio[offset:offset + 3200]).decode("ascii"),
        }))
    ws.send(json.dumps({"type": "input_audio_buffer.commit"}))
    while receive()["type"] != "input_audio_buffer.committed":
        pass
    ws.send(json.dumps({"type": "response.create"}))
    with open("reply.pcm", "wb") as output:
        while True:
            event = receive()
            if event["type"] == "response.audio.delta":
                output.write(base64.b64decode(event["delta"]))
            elif event["type"] in ("response.audio_transcript.delta", "response.text.delta"):
                print(event["delta"], end="", flush=True)
            elif event["type"] == "response.done":
                print("\nResponse status:", event["response"]["status"])
                break
finally:
    ws.close()
After a successful response, convert reply.pcm to a WAV file for playback with an audio player:
import wave
from pathlib import Path

with wave.open("reply.wav", "wb") as target:
    target.setnchannels(1)
    target.setsampwidth(2)
    target.setframerate(24000)
    target.writeframes(Path("reply.pcm").read_bytes())

Realtime microphone examples

  • DashScope Python SDK
  • DashScope Java SDK
  • WebSocket (Python)
  • Runtime environment
Ensure Python 3.10 or later is installed.Install PyAudio for your operating system.
  • macOS
  • Debian/Ubuntu
  • CentOS
  • Windows
brew install portaudio && pip install pyaudio
Install the other dependencies:
pip install websocket-client dashscope
  • Interaction mode
    • VAD mode (Voice Activity Detection, automatically detects the start and end of speech) The server responds after detecting the end of the user's speech.
    • Manual mode (press to speak, release to send) The client controls the start and end of speech. After speaking, your application must notify the server.
    • VAD mode
    • Manual mode
    Create a Python file named vad_dash.py and copy the following code into the file:
    # Dependencies: dashscope >= 1.26.5, pyaudio
    import os
    import base64
    import time
    import pyaudio
    from dashscope.audio.qwen_omni import MultiModality, AudioFormat,OmniRealtimeCallback,OmniRealtimeConversation
    import dashscope
    
    # Configuration: URL, API key, voice, model, model role
    # Specify the region. 'cn' for China (Beijing) region, 'intl' for Singapore region. Replace {WorkspaceId} with your Bailian workspace ID.
    region = 'cn'
    base_domain = '{WorkspaceId}.cn-beijing.maas.aliyuncs.com' if region == 'cn' else '{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com'
    url = f'wss://{base_domain}/api-ws/v1/realtime'
    # Configure the API key. If the environment variable is not set, replace the following line with your API key: dashscope.api_key = "sk-xxx"
    dashscope.api_key = os.getenv('DASHSCOPE_API_KEY')
    # Specify the voice.
    voice = 'Tina'
    # Specify the model.
    model = 'qwen3.8-omni-flash-realtime'
    # Specify the model role.
    instructions = "You are Xiaoyun, a personal assistant. Answer the user's questions in a humorous and witty way."
    class SimpleCallback(OmniRealtimeCallback):
        def __init__(self, pya):
            self.pya = pya
            self.out = None
        def on_open(self):
            # Initialize the audio output stream.
            self.out = self.pya.open(
                format=pyaudio.paInt16,
                channels=1,
                rate=24000,
                output=True
            )
        def on_event(self, response):
            if response['type'] == 'response.audio.delta':
                # Play the audio.
                self.out.write(base64.b64decode(response['delta']))
            elif response['type'] == 'conversation.item.input_audio_transcription.delta':
                # Streaming preview: text is the confirmed prefix, stash is the unconfirmed suffix.
                preview = response.get('text', '') + response.get('stash', '')
                print(f"\r[User] {preview}", end='', flush=True)
            elif response['type'] == 'conversation.item.input_audio_transcription.completed':
                # Transcription completed. Print the final text and move to a new line.
                print(f"\r[User] {response['transcript']}")
            elif response['type'] == 'response.audio_transcript.done':
                # Print the assistant's response text.
                print(f"[LLM] {response['transcript']}")
    
    # 1. Initialize the audio device.
    pya = pyaudio.PyAudio()
    # 2. Create the callback function and conversation.
    callback = SimpleCallback(pya)
    conv = OmniRealtimeConversation(model=model, callback=callback, url=url)
    # 3. Connect and configure the session.
    conv.connect()
    conv.update_session(output_modalities=[MultiModality.AUDIO, MultiModality.TEXT], voice=voice, instructions=instructions)
    # 4. Initialize the audio input stream.
    mic = pya.open(format=pyaudio.paInt16, channels=1, rate=16000, input=True)
    # 5. Main loop to process audio input.
    print("Conversation started. Speak into the microphone (Ctrl+C to exit)...")
    try:
        while True:
            audio_data = mic.read(3200, exception_on_overflow=False)
            conv.append_audio(base64.b64encode(audio_data).decode())
            time.sleep(0.01)
    except KeyboardInterrupt:
        # Clean up resources.
        conv.close()
        mic.close()
        callback.out.close()
        pya.terminate()
        print("\nConversation ended")
    
    Run vad_dash.py to start a real-time conversation through your microphone. The system detects speech and streams audio to the server.

Interaction flow

  • VAD mode
  • Manual mode
Set session.turn_detection.type in session.update to "server_vad" or "semantic_vad" to enable VAD mode. Suitable for voice call scenarios. Both WebSocket and WebRTC support VAD mode with the same server events; they differ only in how audio and images are transmitted.
WebRTC only supports VAD mode and does not support Manual mode. With WebRTC, audio is transmitted directly via RTP without sending input_audio_buffer.append events; images are transmitted via video tracks without support for input_image_buffer.append events. Control commands and server events are transmitted via DataChannel with the same event types as WebSocket.
The interaction flow is as follows:
  1. The client sends audio data. WebSocket sends it via input_audio_buffer.append events; WebRTC transmits it automatically via the audio track (RTP) without manually sending events.
  2. The server detects the start of speech and sends the input_audio_buffer.speech_started event via DataChannel (WebRTC) or WebSocket.
  3. The server detects the end of speech and sends the input_audio_buffer.speech_stopped event.
  4. The server commits the audio buffer and sends the input_audio_buffer.committed event.
  5. The server begins generating a response, sending conversation.item.created and other events. Audio responses are returned incrementally via the WebSocket response.audio.delta event, or transmitted directly via the WebRTC audio track (RTP).
  6. During the response, the server returns incremental text transcription via response.audio_transcript.delta events, and sends the response.done event when the response is complete.
LifecycleClient eventsServer events
Session initializationsession.update
Session configuration
session.created
Session created.
session.updated
Session configuration updated.
User audio inputinput_audio_buffer.append
WebSocket: Appends audio to the buffer via this event.
input_image_buffer.append
WebSocket: Appends an image to the buffer via this event.
WebRTC: Audio is transmitted automatically via the RTP audio track, and images are transmitted via the video track. These events are not needed.
input_audio_buffer.speech_started
Speech start detected.
input_audio_buffer.speech_stopped
Speech end detected.
input_audio_buffer.committed
Audio buffer committed.
Server audio outputNoneresponse.created
Response generation started.
response.output_item.added
New output item added to the response.
conversation.item.created
Conversation item created.
response.content_part.added
New content part added to the assistant message.
response.audio_transcript.delta
Incrementally generated transcribed text.
response.audio.delta
WebSocket: Incrementally generated audio from the model is returned via this event. WebRTC: Audio is transmitted directly via the RTP audio track; this event is not returned.
response.audio_transcript.done
Text transcription completed.
response.audio.done
Audio generation completed.
response.content_part.done
Streaming of the assistant's text or audio content is complete.
response.output_item.done
The assistant's entire output item has finished streaming.
response.done
Response completed.
conversation.item.input_audio_transcription.completed
User audio input transcription completed (requires enabling input_audio_transcription in session.update).

Multichannel audio, video aggregation, and MCP

The following configuration applies to Qwen3.8-Omni-Flash-Realtime.
  • Multichannel audio (WebSocket access): configure session.audio.input.format before the first audio segment. It supports 1, 2, or 4 channels; multichannel input requires PCM, 16000 Hz, s16le, and interleaved samples. Use raw_mic_array for 2 channels and foa_ambix for 4. See client events for constraints and JSON fragments.
  • Video aggregation: session.video.input.representation_compact defaults to none. Use normal to aggregate video representations and reduce computation when fine visual detail is unnecessary. Set it before the first audio segment; it cannot change after audio input starts.
  • Voices: The default voice is Tina. Use session.audio.output.voice for new integrations. If it and the compatibility field session.voice are both set, the audio output uses the voice specified by session.audio.output.voice. See the voice list for available voices and voice cloning.
  • MCP: configure a public HTTPS MCP Streamable HTTP service in session.tools. Update MCP configuration only when there is no active Response. Approval is required by default. Wait for discovery to complete before creating a Response that needs the tool. See the MCP interaction flow for results, rejections, failures, and continuation.

Configure video aggregation with the SDK

Qwen3.8-Omni-Flash-Realtime requires DashScope Python SDK 1.26.5 or later, or Java SDK 2.22.15 or later. Pass the video aggregation parameter through the SDK: supply video to Python's update_session, or use OmniRealtimeConfig.builder().parameters(...) in Java. This example configures a Manual-mode session with text and audio output, the Tina voice, input transcription disabled, and video aggregation enabled. Establish a connection using the SDK examples below with the model set to qwen3.8-omni-flash-realtime. Replace that example's session configuration call with this one, and call it once before sending the first audio segment. conversation is the connected SDK session. The SDK also sends voice and VAD settings; configure any different voice, VAD, or transcription settings in the same call. In Java, import java.util.Arrays, java.util.Map, java.util.HashMap, com.alibaba.dashscope.audio.omni.OmniRealtimeConfig, and com.alibaba.dashscope.audio.omni.OmniRealtimeModality.
from dashscope.audio.qwen_omni import MultiModality

conversation.update_session(
    output_modalities=[MultiModality.AUDIO, MultiModality.TEXT],
    voice="Tina",
    enable_turn_detection=False,
    enable_input_audio_transcription=False,
    video={
        "input": {
            "representation_compact": "normal",
        },
    },
)
Web search lets the model use real-time data to answer questions about timely information such as stock prices and weather. The model automatically determines if a search is needed.
Qwen3.8-Omni-Flash-Realtime and the Qwen3.5-Omni-Realtime series support web search. Disabled by default; enable it with session.update.
For billing, see the agent policy in billing rules.
Add the following parameters to the session.update event:
  • enable_search: Set to true to enable the web search feature.
  • search_options.enable_source: Set to true to include the sources of the search results in the response.
For more parameters, see session.update.

Response format

When web search is enabled, the usage object in response.done includes a plugins field with search metering information:
{
    "usage": {
        "total_tokens": 2937,
        "input_tokens": 2554,
        "output_tokens": 383,
        "input_tokens_details": {
            "text_tokens": 2512,
            "audio_tokens": 42
        },
        "output_tokens_details": {
            "text_tokens": 90,
            "audio_tokens": 293
        },
        "plugins": {
            "search": {
                "count": 1,
                "strategy": "agent"
            }
        }
    }
}

Code example

Enable web search in a real-time conversation:
  • DashScope Python SDK
  • DashScope Java SDK
  • WebSocket (Python)
Pass the enable_search and search_options parameters in the update_session call:
import os
import base64
import time
import json
import pyaudio
from dashscope.audio.qwen_omni import MultiModality, AudioFormat, OmniRealtimeCallback, OmniRealtimeConversation
import dashscope

dashscope.api_key = os.getenv('DASHSCOPE_API_KEY')
# China (Beijing) region. Replace {WorkspaceId} with your Bailian workspace ID. URLs vary by region.
url = 'wss://{WorkspaceId}.cn-beijing.maas.aliyuncs.com/api-ws/v1/realtime'
model = 'qwen3.8-omni-flash-realtime'
voice = 'Tina'

class SearchCallback(OmniRealtimeCallback):
    def __init__(self, pya):
        self.pya = pya
        self.out = None
    def on_open(self):
        self.out = self.pya.open(format=pyaudio.paInt16, channels=1, rate=24000, output=True)
    def on_event(self, response):
        if response['type'] == 'response.audio.delta':
            self.out.write(base64.b64decode(response['delta']))
        elif response['type'] == 'conversation.item.input_audio_transcription.delta':
            preview = response.get('text', '') + response.get('stash', '')
            print(f"\r[User] {preview}", end='', flush=True)
        elif response['type'] == 'conversation.item.input_audio_transcription.completed':
            print(f"\r[User] {response['transcript']}")
        elif response['type'] == 'response.audio_transcript.done':
            print(f"[LLM] {response['transcript']}")
        elif response['type'] == 'response.done':
            usage = response.get('response', {}).get('usage', {})
            plugins = usage.get('plugins', {})
            if plugins.get('search'):
                print(f"[Search] count={plugins['search']['count']}, strategy={plugins['search']['strategy']}")

pya = pyaudio.PyAudio()
callback = SearchCallback(pya)
conv = OmniRealtimeConversation(model=model, callback=callback, url=url)
conv.connect()
conv.update_session(
    output_modalities=[MultiModality.AUDIO, MultiModality.TEXT],
    voice=voice,
    instructions="You are Xiaoyun, a personal assistant.",
    enable_search=True,
    search_options={'enable_source': True}
)
mic = pya.open(format=pyaudio.paInt16, channels=1, rate=16000, input=True)
print("Web search is enabled. Speak into the microphone (Ctrl+C to exit)...")
try:
    while True:
        audio_data = mic.read(3200, exception_on_overflow=False)
        conv.append_audio(base64.b64encode(audio_data).decode())
        time.sleep(0.01)
except KeyboardInterrupt:
    conv.close()
    mic.close()
    callback.out.close()
    pya.terminate()
    print("\nConversation ended.")

API reference

For the connection workflow and examples, see AOQ integration. For supported models and versions, see Model and protocol support.

Billing and rate limits

Billing

Billing is token-based, metered by modality (audio, image, text). Check the Model Studio console for pricing. For speech output, qwen3.8-omni-flash-realtime bills both the audio and its corresponding text at their respective output rates. Qwen3.5-Omni-Realtime models bill only the audio; the corresponding text is not charged. MCP tool invocations incur no additional fee; model inference remains subject to model pricing. See the MCP interaction flow for the calling procedure and limits.
In a multi-turn real-time conversation, each time the model generates a response, it processes all historical conversation content within the context window — including audio, images, and text from previous turns — together with the new input of the current turn as input tokens. As a result, input tokens accumulate with each turn rather than being counted only for the new input in the current turn.For example, if a 10-second audio input converts to 70 tokens (Qwen3.5-Omni-Realtime), and that audio is still within the context window at turn 3, it will still be counted toward the input tokens for turn 3. The actual billed input tokens = tokens from all historical turns within the context window + tokens from the new input in the current turn.
  • Audio
  • Image
  • Video
  • Qwen3.8-Omni-Flash-Realtime and Qwen3.5-Omni-Realtime:
    • Input audio: total tokens = Audio duration (seconds) * 7
    • Output audio: total tokens = Audio duration (seconds) * 12.5
  • qwen3-omni-flash-realtime-2025-09-15: Input and output audio use the same formula: total tokens = Audio duration (seconds) * 12.5 Audio durations of less than 1 second are billed as 1 second.
For qwen3.8-omni-flash-realtime, spatial audio input uses twice as many input audio tokens as regular audio. The multiplier is the same for 2-channel and 4-channel input.

Rate limiting

For model rate limits, see Rate limiting.

FAQ

Online trial of Qwen-Omni-Realtime

A: To deploy the model with a single click, follow these steps:
  1. Go to the Function Compute template. Set Deployment type to direct deployment, enter your API key in the Model Studio API key field, and click Create and deploy default environment.
  2. Wait about one minute for the deployment to complete. In the Environment details tab, go to the Environment information section and get the Endpoint. Change http in the endpoint to https (for example, https://omni-realtime.fcv3.xxxx.cn-hangzhou.fc.devsapp.net). The modified HTTPS link points to a web application for real-time video or voice calls with the model.
This link uses a self-signed certificate and is for temporary testing only. When you first access the link, your browser shows a security warning. This is expected behavior. Do not use this link in a production environment. To proceed, follow the instructions in your browser, such as clicking "Advanced" → "Proceed to (unsafe)".
You can find the project source code under Resource information > Function resources.
Function Compute and Model Studio offer new users a free quota for debugging. After the free quota is used, pay-as-you-go billing applies.

Image input

A: The input method depends on the protocol. WebSocket: Send the input_image_buffer.append event from the client. WebRTC: Images are sent as video frames via RTP video tracks. The input_image_buffer.append event is not needed. For video calls, extract frames from the video. Send one frame per second to the server using input_image_buffer.append. For DashScope SDK code examples, see the Omni-Realtime sample code.

What if I do not receive an ASR transcript?

If you do not receive conversation.item.input_audio_transcription.completed, or its transcript is empty, check the following:
  1. Input transcription configuration: In the DashScope Python SDK, update_session defaults enable_input_audio_transcription to True. Setting it to False sends input_audio_transcription: null in the session configuration. For direct WebSocket access or a WebRTC DataChannel that sends session configuration, check session.update.session.input_audio_transcription against the input audio transcription configuration. enable_input_audio_transcription is an SDK argument, not a top-level session.update field.
  2. Transcription failure event: Also handle conversation.item.input_audio_transcription.failed. Its error.code, error.message, and error.param fields provide the error details.
  3. Audio submission: In VAD mode, check whether the server detected speech start and stop. In Manual mode, make sure you sent input_audio_buffer.commit. Do not wait only for a completed transcription event if the audio has not been committed.
  4. Connection and SDK version: Check that the connection remained active during this audio input. For WebRTC, also check the DataChannel state. If you use the DashScope Python SDK, check that its version meets this guide's minimum requirement (1.26.5).

Error codes

If the model call fails and returns an error message, see Error codes for resolution.

Voice list

For a list of voices available for the Qwen-Omni-Realtime model, see Voices.
Token Plan
Model Playground
Fine-tuning
Model Compression
Statistics and Monitoring
Support