Skip to main content
Qwen-Audio-Realtime

Qwen-Audio-Realtime WebSocket API

Qwen-Audio-Realtime WebSocket connection protocol, request headers, core concepts, and interaction flows

The Qwen-Audio Realtime API provides real-time voice conversation over WebSocket. The client interacts with the server by sending and receiving JSON events, supporting voice input, text input, voice activity detection (VAD), and streaming voice and text output. User guide: Real-time voice conversation (Qwen-Audio-Realtime). For details about client and server events, see Client events and Server events.

Service endpoint

Use the following WebSocket URL. The model query parameter specifies the model to call (replace <model_name> with the actual model name):
wss://dashscope-intl.aliyuncs.com/api-ws/v1/realtime?model=<model_name>
The URL must use the wss:// scheme. Set authorization in the request headers; specify the model through the model query parameter.

Request headers

Include the following fields in the request headers:
ParameterTypeRequiredDescription
AuthorizationstringYesAuthentication token in the format Bearer $DASHSCOPE_API_KEY. Replace $DASHSCOPE_API_KEY with your actual API key.
user-agentstringNoClient identifier that helps the server track request sources.
X-DashScope-WorkSpacestringNoQwenCloud workspace ID.
Authorization is verified during the WebSocket handshake. If the API key is invalid or missing, the handshake fails with an HTTP 401 or 403 error.

Core concepts

  • Session: Each WebSocket connection corresponds to one session, which maintains configuration and conversation context.
  • Conversation item: Each message in the conversation, organized as a linked list in order.
  • Response: The output produced by one round of model inference, containing one or more output items. An output item can be an assistant message or a function call.
  • Function call: An output item produced when the model requests the client to execute a tool function. After execution, the client writes back the result via function_call_output and triggers the next round of inference with response.create.
  • Turn detection: Controls when inference is triggered.

Interaction modes

The Qwen-Audio Realtime API supports three interaction modes, configured via the turn_detection.type parameter in the session.update event:
Modeturn_detection.typeDescriptionUse case
server_vadserver_vadThe server uses VAD to detect the start and end of speech and automatically triggers inference.Hands-free conversation, voice assistants
smart_turnsmart_turnCombines acoustic perception with semantic understanding to determine turn boundaries, rather than relying only on voice signals. Non-semantic sounds (such as "um" or "uh") do not trigger a conversation turn or interrupt model playback.Low-latency natural conversation, high-quality interruption
push-to-talknullThe client manually submits audio and manually triggers inference.Push-to-talk, precise control

Interaction flows

For details about client and server events, see Client events and Server events.

server_vad mode

The server performs voice activity detection on the incoming audio and automatically triggers inference once it detects the end of speech. To enable: Set turn_detection.type to server_vad in the session.update event.

A complete conversation turn

In chronological order, the client and server interact as follows:
  1. The client establishes a WebSocket connection; the server returns a session.created event.
  2. The client sends session.update to configure session parameters; the server returns session.updated.
  3. The client continuously sends input_audio_buffer.append events to append audio data.
  4. The server detects the start of speech and returns input_audio_buffer.speech_started, while streaming incremental ASR transcription via conversation.item.input_audio_transcription.delta.
  5. The server detects the end of speech and returns input_audio_buffer.speech_stopped, input_audio_buffer.committed, and conversation.item.created.
  6. The server automatically generates a response, streaming text and audio deltas (response.audio_transcript.delta, response.audio.delta), and finally returns response.done.
Complete event sequence:
PhaseDirectionEvent
Session initializationClient -> Serverconnect
Server -> Clientsession.created
Client -> Serversession.update
Server -> Clientsession.updated
Voice input (loop)Client -> Serverinput_audio_buffer.append (sent continuously)
Server -> Clientinput_audio_buffer.speech_started
Client -> Serverinput_audio_buffer.append (sent continuously)
Server -> Clientconversation.item.input_audio_transcription.delta (streamed)
Server -> Clientinput_audio_buffer.speech_stopped
Server -> Clientconversation.item.input_audio_transcription.completed
Server (internal)commit audio buffer
Server -> Clientinput_audio_buffer.committed
Server -> Clientconversation.item.created
Response generationServer -> Clientresponse.created
Server -> Clientresponse.output_item.added
Server -> Clientconversation.item.created
Server -> Clientresponse.content_part.added
Streaming output (loop)Server -> Clientresponse.audio_transcript.delta (streamed)
Server -> Clientresponse.audio.delta (streamed)
Output completeServer -> Clientresponse.audio_transcript.done
Server -> Clientresponse.audio.done
Server -> Clientresponse.content_part.done
Server -> Clientresponse.output_item.done
Server -> Clientresponse.done

User interruption

If VAD detects the user starting to speak while the model is playing back a response, the server cancels the current response (returning response.done with status cancelled), then starts a new round of voice input and response. Interruption event sequence:
  1. The server is streaming response.audio.delta (loop).
  2. The client sends input_audio_buffer.append (the user starts speaking).
  3. The server returns response.done (status=cancelled), canceling the current response.
  4. The server returns input_audio_buffer.speech_started.
  5. The client continues sending input_audio_buffer.append; the server streams conversation.item.input_audio_transcription.delta.
  6. The server detects the end of speech and returns input_audio_buffer.speech_stopped and conversation.item.input_audio_transcription.completed.
  7. The server commits the audio buffer internally, returning input_audio_buffer.committed and conversation.item.created.
  8. The server automatically starts a new round of inference and returns response.created.

smart_turn mode

Combines acoustic perception with semantic understanding to detect the end of speech, filtering out backchannels, background noise, and other non-meaningful sounds. Non-semantic sounds are passed through via the conversation.item.ambient_audio_transcription.delta event and do not trigger a conversation turn. To enable: Set turn_detection.type to smart_turn in the session.update event.

A complete conversation turn

Main differences from server_vad mode:
  • Non-semantic sounds (such as "um" or "uh") do not trigger inference; instead, they are returned via the ambient_audio_transcription events.
  • Speech that was initially judged valid may later be retracted (input_audio_buffer.speech_stopped returns with reason=turn_invalid), in which case inference is not triggered.
  • While waiting for the user's next input, the client can explicitly send response.create to trigger inference.
Complete event sequence:
PhaseDirectionEvent
Session initializationClient -> Serverconnect
Server -> Clientsession.created
Client -> Serversession.update
Server -> Clientsession.updated
Voice input (loop)Client -> Serverinput_audio_buffer.append (sent continuously)
Invalid speech (0 to N times)Server -> Clientconversation.item.ambient_audio_transcription.delta (streamed)
Server -> Clientconversation.item.ambient_audio_transcription.completed
Valid speech inputClient -> Serverinput_audio_buffer.append (sent continuously)
Server -> Clientinput_audio_buffer.speech_started
Client -> Serverinput_audio_buffer.append (sent continuously)
Server -> Clientconversation.item.input_audio_transcription.delta (streamed)
Server -> Clientinput_audio_buffer.speech_stopped
Server -> Clientconversation.item.input_audio_transcription.completed
Server (internal)commit audio buffer
Server -> Clientinput_audio_buffer.committed
Server -> Clientconversation.item.created
Response generationServer -> Clientresponse.created
Server -> Clientresponse.output_item.added
Server -> Clientconversation.item.created
Server -> Clientresponse.content_part.added
Streaming output (loop)Server -> Clientresponse.audio_transcript.delta (streamed)
Server -> Clientresponse.audio.delta (streamed)
Output completeServer -> Clientresponse.audio_transcript.done
Server -> Clientresponse.audio.done
Server -> Clientresponse.content_part.done
Server -> Clientresponse.output_item.done
Server -> Clientresponse.done

User interruption

Interruption handling is largely the same as in server_vad mode:
  1. The server is streaming response.audio.delta (loop).
  2. The client sends input_audio_buffer.append (the user starts speaking).
  3. The server returns response.done (status=cancelled), canceling the current response.
  4. The server returns input_audio_buffer.speech_started.
  5. The client continues sending input_audio_buffer.append; the server streams conversation.item.input_audio_transcription.delta.
  6. The server returns conversation.item.input_audio_transcription.completed and input_audio_buffer.speech_stopped.
  7. The server commits the audio buffer internally, returning input_audio_buffer.committed and conversation.item.created.
  8. The server automatically starts a new round of inference and returns response.created.

Invalid turns

Speech that was initially judged valid may later be retracted (input_audio_buffer.speech_stopped returns with reason=turn_invalid), in which case inference is not triggered. The client should keep sending audio and wait for the next valid speech turn. Invalid turn event sequence:
  1. The client continuously sends input_audio_buffer.append.
  2. The server returns input_audio_buffer.speech_started.
  3. The client continues sending input_audio_buffer.append; the server streams conversation.item.input_audio_transcription.delta.
  4. The server returns input_audio_buffer.speech_stopped (reason=turn_invalid).
  5. The client continues sending audio, waiting for the next valid speech turn.

Voiceprint enrollment flow

In smart_turn mode, when voiceprint_audio_urls is included in the first session.update, the server asynchronously performs voiceprint enrollment (loading the target speaker's audio features) and notifies enrollment progress via events. A voiceprint enrollment failure does not block the normal conversation flow. In chronological order, the voiceprint enrollment interaction flow is as follows:
  1. The client sends session.update, including the voiceprint audio URL in turn_detection.voiceprint_audio_urls; the server returns session.updated.
  2. The server immediately starts voiceprint enrollment asynchronously, pushing a voiceprint_audio_list.in_progress event before returning session.updated, carrying a unique item_id for this enrollment task.
  3. The server returns session.updated, confirming that the session configuration has taken effect.
  4. After voiceprint enrollment completes, the server pushes a terminal event (with the same item_id as in step 2):
    • On success: voiceprint_audio_list.completed.
    • On failure: voiceprint_audio_list.failed, with a reason field explaining the failure (for example, the audio URL could not be downloaded).
voiceprint_audio_urls only takes effect on the first session.update. Subsequent occurrences of this field are ignored.

push-to-talk mode

The client manually controls audio submission and inference triggering. Suitable for push-to-talk scenarios. To enable: Set turn_detection to null in the session.update event.

A complete conversation turn

In chronological order, the client and server interact as follows:
  1. The client continuously sends input_audio_buffer.append events to append audio data.
  2. After the user finishes speaking, the client sends input_audio_buffer.commit to commit the buffer.
  3. The client sends response.create to manually trigger inference.
  4. The server generates a response, streaming text and audio.
Complete event sequence:
PhaseDirectionEvent
Session initializationClient -> Serverconnect
Server -> Clientsession.created
Client -> Serversession.update
Server -> Clientsession.updated
Voice input (loop)Client -> Serverinput_audio_buffer.append (sent continuously)
Server -> Clientconversation.item.input_audio_transcription.delta (streamed)
Manual commitClient -> Serverinput_audio_buffer.commit (the user releases the push-to-talk key)
Server -> Clientconversation.item.input_audio_transcription.completed
Server -> Clientinput_audio_buffer.committed
Server -> Clientconversation.item.created
Manually trigger inferenceClient -> Serverresponse.create (manually triggers inference)
Response generationServer -> Clientresponse.created
Server -> Clientresponse.output_item.added
Server -> Clientconversation.item.created
Server -> Clientresponse.content_part.added
Streaming output (loop)Server -> Clientresponse.audio_transcript.delta (streamed)
Server -> Clientresponse.audio.delta (streamed)
Output completeServer -> Clientresponse.audio_transcript.done
Server -> Clientresponse.audio.done
Server -> Clientresponse.content_part.done
Server -> Clientresponse.output_item.done
Server -> Clientresponse.done

User interruption

The client sends response.cancel to cancel the current response; the server returns response.done (status cancelled, reason client_cancelled). Interruption event sequence:
  1. The server is streaming response.audio_transcript.delta and response.audio.delta (loop).
  2. The client sends response.cancel.
  3. The server returns response.done (status=cancelled, reason=client_cancelled).
  4. The client continues sending input_audio_buffer.append; the server streams conversation.item.input_audio_transcription.delta.
  5. The client sends input_audio_buffer.commit to commit the buffer.
  6. The server returns conversation.item.input_audio_transcription.completed, input_audio_buffer.committed, and conversation.item.created.
  7. The client sends response.create to manually trigger a new round of inference.
  8. The server returns response.created, starting a new round of response.

Operation constraints by mode

Operationpush-to-talkserver_vadsmart_turn
session.updateAll fields can be changed when IDLE; some are restricted when not IDLEAll fields can be changed when IDLE; some are restricted when not IDLEAll fields can be changed when IDLE; some are restricted when not IDLE
input_audio_buffer.appendAllowedAllowedAllowed
input_audio_buffer.commitAllowedIgnoredIgnored
input_audio_buffer.clearAllowedIgnoredIgnored
response.createAllowed (requires committing the buffer via input_audio_buffer.commit first; not allowed while a response is already being generated)Allowed when no response is currently being generated; not allowed while a response is already being generatedAllowed while waiting for the user's next input; not allowed within an active turn (from input_audio_buffer.speech_started to response.done)
response.cancelAllowed (during inference)Allowed (during inference)Allowed (during inference)
conversation.item.create/delete/retrieveAllowedAllowedAllowed
turn_detection and input_audio_format can only be changed before the first audio is sent (IDLE state).

Error handling

TypeBehaviorExample
Client error (invalid_request_error)Connection remains open; client is only notifiedInvalid parameters, disallowed state, duplicate item_id
Server error (server_error)Connection is terminatedLLM connection failure, storage failure