Use qwen3.5-omni-plus-realtime model via WebRTC protocol for real-time calls
Describes how to connect to the QwenCloud Realtime API in a browser using WebRTC and JavaScript to enable real-time audio/video calls with the qwen3.5-omni-plus-realtime model.
The following sequence diagram shows the complete WebRTC audio/video call flow:
WebRTC audio/video call sequence diagram
Call the browser's native
Register key callbacks:
Use a single
Add audio track:
Add video track (optional, with Canvas frame reduction to 2 fps):
Canvas dimensions are obtained dynamically from the actual camera resolution rather than hard-coded:
Media gating (critical):
After adding tracks, block sending immediately to ensure no media is pushed before
Create a DataChannel named
Call
Send the Offer SDP to the QwenCloud server and obtain the Answer SDP. In the demo, this is done via a curl command:
Set the Answer SDP returned by the server as the remote description to establish the WebRTC connection. Normalize the SDP format before setting it:
After the connection is established, the server sends a
session.update message body:
After the connection is established, audio/video is transmitted in real time over RTP. Remote AI voice responses are received through the
DataChannel event display:
All events sent and received through the DataChannel (including
Release all resources in order when ending a call. The order is important:
Download the complete sample code: webrtc_demo.html.
WebRTC is suitable for browser-based, low-latency voice scenarios. Audio is transmitted directly over UDP with built-in echo cancellation and noise reduction. WebRTC supports only server-side VAD mode (
server_vad or semantic_vad). Manual mode is not supported.Prerequisites and notes
- Configure an API key and set it as an environment variable.
- Use a modern browser that supports WebRTC (Chrome, Edge, Firefox, Safari, and so on).
- The browser must have microphone permission. For video calls, camera permission is also required.
- Browsers cannot directly send SDP exchange requests to the server due to CORS restrictions. In the demo, run the curl command in a terminal to complete the connection. In production, this restriction does not apply when the request is proxied through an AppServer.
Implement AI audio/video calls
The following sequence diagram shows the complete WebRTC audio/video call flow:
WebRTC audio/video call sequence diagram

Create RTCPeerConnection
Call the browser's native RTCPeerConnection constructor to create a connection instance. No ICE servers need to be configured (the server handles NAT traversal).
Get local media streams
Use a single getUserMedia call to request audio (required) and video (optional). Whether video is enabled is determined by the user's Enable video checkbox.
Both audio and video are obtained in a single
getUserMedia call, not separately. The video preview runs at 30 fps (for smooth local preview); the send frame rate is reduced to 2 fps via Canvas.Add media tracks to PeerConnection
Add audio track:
session.created is received:
This is equivalent to
enableSendMediaStream(false) in other SDKs. Sending must not be restored until session.created is received.Create DataChannel
Create a DataChannel named oai-events to exchange session control events with the AI server.
Generate Offer SDP
Call createOffer() and set the local description. Wait for ICE gathering to complete before using the full Offer SDP.
Wait for
iceGatheringState === "complete" before using the SDP. At that point, the SDP contains all ICE candidate information.Exchange SDP (via curl command or AppServer)
Send the Offer SDP to the QwenCloud server and obtain the Answer SDP. In the demo, this is done via a curl command:
In production, proxy this step through an AppServer to avoid exposing the API key in the front end.
Set Answer SDP to establish connection
Set the Answer SDP returned by the server as the remote description to establish the WebRTC connection. Normalize the SDP format before setting it:
The SDP specification requires
\r\n line endings. normalizeSdpForSetRemote handles line ending compatibility from different sources.Configure AI session (session.update)
After the connection is established, the server sends a session.created event through the DataChannel. Upon receiving it:
- Release the media gate to restore audio/video sending
- Send
session.updateto configure session parameters
turn_detection.type can be set to server_vad (volume-based detection) or semantic_vad (semantic detection). Manual VAD is not supported in WebRTC mode.Real-time conversation
After the connection is established, audio/video is transmitted in real time over RTP. Remote AI voice responses are received through the ontrack callback and played back. MediaRecorder is used to record responses for download.
Receive and record remote audio:
session.created, response.audio_transcript.done, and so on) are displayed in the event panel with support for expanding to view the full JSON:
End session and release resources
Release all resources in order when ending a call. The order is important:
After the session ends, use the Download remote audio button to save the AI response recording in WebM format.
Important notes
- Media gate must be released after session.created: Media data sent before the server sends
session.createdwill be discarded. UsereplaceTrack(null)to fully block sending until then. - Video frame reduction is implemented via Canvas: Local preview runs at 30 fps; only 2 fps is sent to the server, controlled by
captureStream(2). This conserves bandwidth. - SDP format normalization: Ensure line endings are
\r\nbefore setting the Answer SDP. Otherwise,setRemoteDescriptionmay fail. - Video is optional: If the user does not enable video, only microphone permission is requested -- no camera permission prompt appears.
- Remote audio is recorded automatically: MediaRecorder records the AI response audio stream. A WebM file is available for download after the session ends.
- WebRTC supports only server-side VAD: The
manualmode is not supported. Useserver_vad(volume detection) orsemantic_vad(semantic detection).
Download the complete demo
Download the complete sample code: webrtc_demo.html.
Related documents
- WebRTC API (MDN)
- RTCPeerConnection (MDN)
- qwen3.5-omni-plus-realtime model client events: Client events
- qwen3.5-omni-plus-realtime model server events: Server events