Skip to main content

Qwen-Omni-Realtime

Qwen-Omni-Realtime procesa entradas de audio e imágenes en streaming (incluyendo fotogramas de video) y genera respuestas de texto y audio en tiempo real.

Regiones admitidas: Singapur, China (Beijing). Cada región requiere su propia clave de API.

Cómo usar

1. Establecer conexión

Los ejemplos generales de conexión WebSocket y WebRTC utilizan qwen3.8-omni-flash-realtime. Los ejemplos de configuración específicos del modelo utilizan sus modelos indicados. Los modelos Qwen-Omni-Realtime admiten conexiones mediante WebSocket, WebRTC y AOQ. WebSocket es adecuado para la integración del lado del servidor y el acceso rápido. WebRTC es adecuado para escenarios de voz de baja latencia en el navegador. Transmite audio directamente mediante UDP e incluye cancelación de eco y supresión de ruido. Para una integración del lado del cliente que priorice latencia estable, interacción en redes deficientes y supresión de ruido y cancelación de eco en la comunicación dúplex completa en tiempo real, considere primero AOQ. Para comparar y seleccionar protocolos, consulte la Referencia de la API.
  • WebSocket
  • WebRTC
  • AOQ
qwen3.8-omni-flash-realtime requiere el punto final específico del espacio de trabajo que se indica a continuación. Obtenga una clave API y un ID de espacio de trabajo para la misma región y espacio de trabajo antes de conectarse.
  • WebSocket nativo
  • SDK de Python de DashScope
  • SDK de Java de DashScope
Parámetros de conexión:
ParámetroDescripción
EndpointRegión China (Beijing): wss://{WorkspaceId}.cn-beijing.maas.aliyuncs.com/api-ws/v1/realtimeRegión de Singapur: wss://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/api-ws/v1/realtimeReemplace {WorkspaceId} con su ID de espacio de trabajo real.
Query parameterUtilice el parámetro de consulta model para especificar el modelo. Ejemplo: ?model=qwen3.8-omni-flash-realtime
Request headerUtilice un token Bearer para la autenticación: Authorization: Bearer DASHSCOPE_API_KEY
DASHSCOPE_API_KEY es la clave de API de Model Studio.
# pip install websocket-client
import json
import websocket
import os

API_KEY=os.getenv("DASHSCOPE_API_KEY")
# Singapore region. Replace {WorkspaceId} with your Bailian workspace ID. URLs vary by region.
API_URL = "wss://{WorkspaceId}.ap-southeast-1.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. Configurar sesión

Envíe el evento de cliente session.update: Utilice session.update para configurar modalidades de salida, voz, formato de audio y VAD. La siguiente configuración de modo Manual de WebSocket para Qwen3.8-Omni-Flash-Realtime coincide con el ejemplo mínimo de audio. Este ejemplo utiliza la voz Long An Ling Xin (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
        }
      }
    }
  }
}
El siguiente ejemplo utiliza la voz Ethan y la configuración semantic_vad de 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
        }
    }
}
Para audio multicanal, agregación de video, configuración de MCP y ejemplos de SDK, consulte Configuración avanzada de sesión.

3. Introducir audio e imágenes

La entrada de audio es obligatoria; la entrada de imagen es opcional. El método de entrada depende del protocolo.
  • WebSocket
  • WebRTC
Envíe datos de audio e imagen codificados en Base64 al búfer del servidor utilizando los eventos input_audio_buffer.append y input_image_buffer.append.
Las imágenes pueden provenir de archivos locales o de capturas de transmisiones de video en tiempo real.
Con el VAD del lado del servidor habilitado, el servidor envía datos automáticamente y activa una respuesta al final de la expresión. Con el VAD deshabilitado (modo manual), invoque el evento input_audio_buffer.commit para enviar los datos después de la transmisión.

4. Recibir respuestas del modelo

El formato de respuesta depende de la modalidad de salida configurada.
  • WebSocket
  • WebRTC

Selección de modelo

Utilice Qwen3.8-Omni-Flash-Realtime para conversaciones de audio/video en tiempo real. Admite interacción dúplex completa, acepta texto, imágenes, audio en streaming y video, y devuelve texto y audio. Es compatible con conexiones WebSocket, WebRTC y AOQ. Consulte Establecer una conexión.
Consulte la consola de Model Studio para obtener nombres de modelos, contexto, precios y versiones de instantáneas. Para límites de tasa de concurrencia, consulte Límites de tasa.

Limitaciones

qwen3.8-omni-flash-realtime admite hasta 196608 tokens de entrada en total. La longitud de entrada se calcula con las mismas reglas que Qwen3.5-Omni-Realtime.
  • La búsqueda web y la llamada a herramientas son mutuamente excluyentes.
  • Una sola sesión de WebSocket puede durar hasta 120 minutos. La conexión se cierra automáticamente al alcanzar este límite.
  • El modelo retiene el historial de conversaciones hasta los siguientes límites de turnos y duración. Cuando se superan, se descarta el historial más antiguo. La Duración máxima es la duración acumulada de audio o video (fotograma de imagen) retenida en el contexto. No es la duración de toda la sesión.
    El video se introduce como fotogramas extraídos (recomendado: 1 fps). La duración máxima del video es la duración acumulada de fotogramas retenida; por ejemplo, 240 s significa que solo se conservan los fotogramas de los últimos 240 segundos.

    Modelo

    Turnos máximos de audio

    Turnos máximos de video

    Duración máxima de audio

    Duración máxima de video

    qwen3.8-omni-flash-realtime

    100 turnos

    50 turnos

    600 segundos

    240 segundos

    qwen3.5-omni-plus-realtime

    100 turnos

    50 turnos

    600 segundos

    240 segundos

    qwen3.5-omni-flash-realtime

    80 turnos

    50 turnos

    480 segundos

    120 segundos

Introducción

Obtenga una clave de API y configúrela como variable de entorno. Seleccione un lenguaje de programación y siga los pasos para iniciar un chat en tiempo real.
  • WebSocket
  • WebRTC

Preguntas y respuestas de audio mínimas

Configure una clave API e instale websocket-client. Establezca REALTIME_WS_URL en el punto final regional completo de WebSocket que aparece a continuación con el ID de espacio de trabajo reemplazado; el ejemplo agrega el parámetro de consulta del modelo. Establezca PCM_FILE en un archivo corto de voz PCM mono de 16 kHz y 16 bits little-endian sin encabezado de archivo.Este ejemplo utiliza el modo Manual: espere la configuración de la sesión, envíe audio, confirme el búfer y solicite una respuesta. El texto se imprime en la terminal; el audio se guarda en reply.pcm (PCM de 24 kHz, no es un archivo WAV).Ejecute los siguientes comandos en una terminal de macOS o Linux. Reemplace el punto final de WebSocket con la URL regional de su espacio de trabajo, sin el parámetro de consulta del modelo. El ejemplo lo agrega automáticamente.
python3 -m pip install websocket-client
export REALTIME_WS_URL="<workspace-websocket-url>"
export PCM_FILE="./input.pcm"
Si tiene un archivo WAV PCM mono de 16 kHz y 16 bits llamado input.wav, use Python para extraer sus tramas PCM. Este paso verifica el formato; no remuestrea el 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()))
Ejecute el siguiente cliente después de preparar la entrada. El ejemplo utiliza la voz Long An Ling Xin (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()
Después de una respuesta exitosa, convierta reply.pcm a un archivo WAV para reproducirlo con un reproductor de audio:
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())

Ejemplos de micrófono en tiempo real

  • SDK de Python de DashScope
  • SDK de Java de DashScope
  • WebSocket (Python)
  • Entorno de ejecución
Asegúrese de tener instalado Python 3.10 o posterior.Instale PyAudio para su sistema operativo.
  • macOS
  • Debian/Ubuntu
  • CentOS
  • Windows
brew install portaudio && pip install pyaudio
Instale las demás dependencias:
pip install websocket-client dashscope
  • Modo de interacción
    • Modo VAD (Detección de Actividad de Voz, detecta automáticamente el inicio y el final del habla) El servidor responde tras detectar el final del habla del usuario.
    • Modo manual (presione para hablar, suelte para enviar) El cliente controla el inicio y el final del habla. Después de hablar, su aplicación debe notificar al servidor.
    • modo VAD
    • modo manual
    Cree un archivo Python llamado vad_dash.py y copie el siguiente código en el archivo:
    # Dependencias: dashscope >= 2.0.1, pyaudio
    import os
    import base64
    import time
    
    import pyaudio
    from concurrent.futures import ThreadPoolExecutor
    
    import dashscope
    
    # La siguiente configuración corresponde a la región de Singapur. Sustituya {WorkspaceId} por el ID real de su espacio de trabajo. El valor de region varía según la región.
    client = dashscope.Client(
        # Si no se ha configurado la variable de entorno, sustituya la siguiente línea por su API Key de Model Studio: api_key="sk-xxx",
        # Las API Key de las regiones de Singapur y Pekín son diferentes. Obtenga su API Key: https://www.alibabacloud.com/help/model-studio/get-api-key
        api_key=os.getenv("DASHSCOPE_API_KEY"),
        workspace="{WorkspaceId}",
        region="ap-southeast-1",
    )
    # Especifique la voz
    voice = 'Tina'
    # Especifique el modelo
    model = 'qwen3.8-omni-flash-realtime'
    # Especifique el rol del modelo
    instructions = "You are Xiaoyun, a personal assistant. Answer the user's questions in a humorous and witty way."
    
    # 1. Inicialice el dispositivo de audio y el flujo de salida
    pya = pyaudio.PyAudio()
    out = pya.open(format=pyaudio.paInt16, channels=1, rate=24000, output=True)
    
    # 2. Hilo receptor: itera los eventos del servidor, reproduce el audio e imprime el texto
    def receive_events(session):
        for response in session.events():
            if response['type'] == 'response.audio.delta':
                # Reproduzca el audio.
                out.write(base64.b64decode(response['delta']))
            elif response['type'] == 'conversation.item.input_audio_transcription.delta':
                # Vista previa en flujo: text es el prefijo confirmado y stash es el sufijo sin confirmar.
                preview = response.get('text', '') + response.get('stash', '')
                print(f"\r[User] {preview}", end='', flush=True)
            elif response['type'] == 'conversation.item.input_audio_transcription.completed':
                # Transcripción completada. Imprima el texto final y pase a una nueva línea.
                print(f"\r[User] {response['transcript']}")
            elif response['type'] == 'response.audio_transcript.done':
                # Imprima el texto de respuesta del asistente.
                print(f"[LLM] {response['transcript']}")
    
    # 3. Cree la sesión (la conexión se establece automáticamente al entrar en el contexto with) y configúrela
    with client.audio.realtime.connect(model=model) as session:
        session.update_session(
            output_modalities=['audio', 'text'],
            voice=voice,
            instructions=instructions,
        )
        # 4. Inicialice el flujo de audio de entrada.
        mic = pya.open(format=pyaudio.paInt16, channels=1, rate=16000, input=True)
        # 5. Bucle principal para procesar la entrada de audio.
        print("Conversation started. Speak into the microphone (Ctrl+C to exit)...")
        try:
            with ThreadPoolExecutor(max_workers=1) as pool:
                receiver = pool.submit(receive_events, session)
                while True:
                    audio_data = mic.read(3200, exception_on_overflow=False)
                    session.append_audio(audio_data)
                    time.sleep(0.01)
        except KeyboardInterrupt:
            # Limpie los recursos.
            session.close()
            mic.close()
            out.close()
            pya.terminate()
            print("\nConversation ended")
    
    Ejecute vad_dash.py para iniciar una conversación en tiempo real a través de su micrófono. El sistema detecta el habla y transmite audio al servidor.

Flujo de interacción

  • modo VAD
  • modo manual
Establezca session.turn_detection.type en el evento session.update en "server_vad" o "semantic_vad" para activar el modo VAD. Este modo es adecuado para llamadas de voz. WebSocket y WebRTC admiten el modo VAD, pero sus métodos de transporte de audio e imágenes y algunos eventos del servidor difieren.
WebRTC solo admite el modo VAD, sin el modo Manual. WebRTC transmite audio directamente mediante RTP, por lo que no es necesario enviar eventos input_audio_buffer.append. Las imágenes se transmiten mediante pistas de video y no se admiten eventos input_image_buffer.append. Las instrucciones de control y los eventos del servidor se transmiten mediante DataChannel. Para obtener detalles, consulte Eventos del servidor.
El flujo de interacción es el siguiente:
  1. El cliente envía datos de audio. WebSocket los envía mediante eventos input_audio_buffer.append; WebRTC los transmite automáticamente a través de la pista de audio (RTP) sin enviar eventos manualmente.
  2. El servidor detecta el inicio del habla y envía el evento input_audio_buffer.speech_started a través de DataChannel (WebRTC) o WebSocket.
  3. El servidor detecta el final del habla y envía el evento input_audio_buffer.speech_stopped.
  4. El servidor confirma el búfer de audio y envía el evento input_audio_buffer.committed.
  5. El servidor comienza a generar una respuesta, enviando conversation.item.created y otros eventos. Las respuestas de audio se devuelven incrementalmente a través del evento WebSocket response.audio.delta, o se transmiten directamente a través de la pista de audio WebRTC (RTP).
  6. Durante la respuesta, el servidor devuelve la transcripción de texto incremental mediante eventos response.audio_transcript.delta y envía el evento response.done cuando la respuesta está completa.
Ciclo de vidaEventos del clienteEventos del servidor
Inicialización de sesiónsession.update
Configuración de sesión
session.created
Sesión creada.
session.updated
Configuración de sesión actualizada.
Entrada de audio del usuarioinput_audio_buffer.append
WebSocket: Agrega audio al búfer mediante este evento.
input_image_buffer.append
WebSocket: Agrega una imagen al búfer mediante este evento.
WebRTC: El audio se transmite automáticamente a través de la pista de audio RTP y las imágenes se transmiten a través de la pista de video. Estos eventos no son necesarios.
input_audio_buffer.speech_started
Inicio del habla detectado.
input_audio_buffer.speech_stopped
Fin del habla detectado.
input_audio_buffer.committed
Búfer de audio confirmado.
Salida de audio del servidorNoneresponse.created
Generación de respuesta iniciada.
response.output_item.added
Nuevo elemento de salida añadido a la respuesta.
conversation.item.created
Elemento de conversación creado.
response.content_part.added
Nueva parte de contenido añadida al mensaje del asistente.
response.audio_transcript.delta
Texto transcrito generado incrementalmente.
response.audio.delta
WebSocket: El audio generado incrementalmente por el modelo se devuelve mediante este evento. WebRTC: El audio se transmite directamente a través de la pista de audio RTP; este evento no se devuelve.
response.audio_transcript.done
Transcripción de texto completada.
response.audio.done
Generación de audio completada.
response.content_part.done
La transmisión del contenido de texto o audio del asistente ha finalizado.
response.output_item.done
La transmisión del elemento de salida completo del asistente ha finalizado.
response.done
Respuesta completada.
conversation.item.input_audio_transcription.completed
Transcripción de entrada de audio del usuario completada (requiere habilitar input_audio_transcription en session.update).

Audio multicanal, agregación de video y MCP

La siguiente configuración se aplica a Qwen3.8-Omni-Flash-Realtime.
  • Audio multicanal (acceso WebSocket): configure session.audio.input.format antes del primer segmento de audio. Admite 1, 2 o 4 canales; la entrada multicanal requiere PCM, 16000 Hz, s16le y muestras intercaladas. Utilice raw_mic_array para 2 canales y foa_ambix para 4. Consulte eventos del cliente para restricciones y fragmentos JSON.
  • Agregación de video: session.video.input.representation_compact tiene como valor predeterminado none. Utilice normal para agregar representaciones de video y reducir la computación cuando el detalle visual fino no es necesario. Configúrelo antes del primer segmento de audio; no se puede cambiar después de que comience la entrada de audio.
  • Voces: La voz predeterminada es Tina. Utilice session.audio.output.voice para nuevas integraciones. Si tanto este como el campo de compatibilidad session.voice están configurados, la salida de audio utiliza la voz especificada por session.audio.output.voice. Consulte la lista de voces para ver las voces disponibles y la clonación de voz.
  • MCP: configure un servicio público HTTPS MCP Streamable HTTP en session.tools. Actualice la configuración de MCP solo cuando no haya ninguna Response activa. La aprobación es obligatoria de forma predeterminada. Espere a que finalice la detección antes de crear una Response que requiera la herramienta. Consulte el flujo de interacción de MCP para ver resultados, rechazos, fallos y continuación.

Configurar la agregación de video con el SDK

Qwen3.8-Omni-Flash-Realtime requiere DashScope Python SDK 2.0.1 o posterior, o Java SDK 2.22.15 o posterior. Pase el parámetro de agregación de video a través del SDK: proporcione input_video_representation_compact a update_session de Python, o utilice OmniRealtimeConfig.builder().parameters(...) en Java. Este ejemplo configura una sesión en modo Manual con salida de texto y audio, la voz Tina, transcripción de entrada deshabilitada y agregación de video habilitada. Establezca una conexión utilizando los ejemplos del SDK a continuación con el modelo configurado en qwen3.8-omni-flash-realtime. Reemplace la llamada de configuración de sesión de ese ejemplo con esta, e invoquela una sola vez antes de enviar el primer segmento de audio. conversation es la sesión del SDK conectada. El SDK también envía configuraciones de voz y VAD; configure cualquier otra opción de voz, VAD o transcripción en la misma llamada. En Java, importe java.util.Arrays, java.util.Map, java.util.HashMap, com.alibaba.dashscope.audio.omni.OmniRealtimeConfig y com.alibaba.dashscope.audio.omni.OmniRealtimeModality.
session.update_session(
    output_modalities=['audio', 'text'],
    voice="Tina",
    enable_turn_detection=False,
    enable_input_audio_transcription=False,
    input_video_representation_compact="normal",
)

Búsqueda web

La búsqueda web permite al modelo utilizar datos en tiempo real para responder preguntas sobre información actual, como precios de acciones y clima. El modelo determina automáticamente si es necesaria una búsqueda.
Qwen3.8-Omni-Flash-Realtime y la serie Qwen3.5-Omni-Realtime admiten búsqueda web. Deshabilitada de forma predeterminada; habilítela con session.update.
Para la facturación, consulte la política de agent en las reglas de facturación.

Habilitar búsqueda web

Agregue los siguientes parámetros al evento session.update:
  • enable_search: Establézcalo en true para habilitar la función de búsqueda web.
  • search_options.enable_source: Establézcalo en true para incluir las fuentes de los resultados de búsqueda en la respuesta.
Para más parámetros, consulte session.update.

Formato de respuesta

Cuando la búsqueda web está habilitada, el objeto usage en response.done incluye un campo plugins con información de medición de búsqueda:
{
    "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"
            }
        }
    }
}

Ejemplo de código

Habilitar la búsqueda web en una conversación en tiempo real:
  • SDK de Python de DashScope
  • SDK de Java de DashScope
  • WebSocket (Python)
Pase los parámetros enable_search y search_options en la llamada a update_session:
import os
import base64
import time

import pyaudio
from concurrent.futures import ThreadPoolExecutor

import dashscope

# La siguiente configuración corresponde a la región de Singapur. Sustituya {WorkspaceId} por el ID real de su espacio de trabajo. El valor de region varía según la región.
client = dashscope.Client(
    # Si no se ha configurado la variable de entorno, sustituya la siguiente línea por su API Key de Model Studio: api_key="sk-xxx",
    # Las API Key de las regiones de Singapur y Pekín son diferentes. Obtenga su API Key: https://www.alibabacloud.com/help/model-studio/get-api-key
    api_key=os.getenv("DASHSCOPE_API_KEY"),
    workspace="{WorkspaceId}",
    region="ap-southeast-1",
)
model = 'qwen3.8-omni-flash-realtime'
voice = 'Tina'

pya = pyaudio.PyAudio()
out = pya.open(format=pyaudio.paInt16, channels=1, rate=24000, output=True)

# Hilo receptor: itera los eventos del servidor
def receive_events(session):
    for response in session.events():
        if response['type'] == 'response.audio.delta':
            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']}")

with client.audio.realtime.connect(model=model) as session:
    session.update_session(
        output_modalities=['audio', '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:
        with ThreadPoolExecutor(max_workers=1) as pool:
            receiver = pool.submit(receive_events, session)
            while True:
                audio_data = mic.read(3200, exception_on_overflow=False)
                session.append_audio(audio_data)
                time.sleep(0.01)
    except KeyboardInterrupt:
        session.close()
        mic.close()
        out.close()
        pya.terminate()
        print("\nConversation ended.")

Referencia de API

Para consultar el flujo de conexión mediante AOQ y los ejemplos, consulte Conexión mediante AOQ. Para seleccionar un protocolo y consultar los enlaces de referencia, consulte la Referencia de la API.

Facturación y límites de tasa

Facturación

La facturación se basa en tokens, medidos por modalidad (audio, imagen, texto). Consulte la consola de Model Studio para ver los precios. Para la salida de voz, qwen3.8-omni-flash-realtime factura tanto el audio como su texto correspondiente a sus respectivas tasas de salida. Los modelos Qwen3.5-Omni-Realtime facturan solo el audio; el texto correspondiente no se cobra. Las invocaciones de herramientas MCP no incurren en tarifas adicionales; la inferencia del modelo sigue sujeta a los precios del modelo. Consulte el Flujo de interacción MCP para conocer el procedimiento de llamada y los límites.
En una conversación en tiempo real de múltiples turnos, cada vez que el modelo genera una respuesta, procesa todo el contenido histórico de la conversación dentro de la ventana de contexto —incluyendo audio, imágenes y texto de turnos anteriores— junto con la nueva entrada del turno actual como tokens de entrada. Como resultado, los tokens de entrada se acumulan con cada turno en lugar de contarse únicamente para la nueva entrada del turno actual.Por ejemplo, si una entrada de audio de 10 segundos se convierte en 70 tokens (Qwen3.5-Omni-Realtime), y ese audio todavía está dentro de la ventana de contexto en el turno 3, seguirá contando para los tokens de entrada del turno 3. Los tokens de entrada facturados reales = tokens de todos los turnos históricos dentro de la ventana de contexto + tokens de la nueva entrada en el turno actual.
  • Audio
  • Imagen
  • Video
  • Qwen3.8-Omni-Flash-Realtime y Qwen3.5-Omni-Realtime:
    • Audio de entrada: total tokens = Audio duration (seconds) * 7
    • Audio de salida: total tokens = Audio duration (seconds) * 12.5
  • qwen3-omni-flash-realtime-2025-09-15: El audio de entrada y salida utiliza la misma fórmula: total tokens = Audio duration (seconds) * 12.5 Las duraciones de audio inferiores a 1 segundo se facturan como 1 segundo.
Para qwen3.8-omni-flash-realtime, la entrada de audio espacial utiliza el doble de tokens de entrada de audio que el audio normal. El multiplicador es el mismo para entradas de 2 canales y de 4 canales.

Limitación de tasa

Para conocer los límites de tasa del modelo, consulte Limitación de tasa.

FAQ

¿Se cobra mientras la conexión está abierta, pero nadie habla?

Mantener la conexión abierta no genera cargos por sí solo. Al enviar audio en silencio, su contabilización como entrada de audio depende del modo que utilice:
  • VAD del servidor: El silencio filtrado no se cuenta como entrada de audio.
  • Modo Manual: El silencio que el cliente confirma explícitamente se cuenta como entrada de audio.
La cantidad de tokens de entrada de audio se devuelve en response.done, en response → usage → input_tokens_details → audio_tokens. El modelo se factura por tokens de entrada y salida. Consulte las Reglas de facturación para más detalles.

¿Qué sucede si no recibo una transcripción ASR?

Si no recibe conversation.item.input_audio_transcription.completed, o su transcript está vacío, compruebe lo siguiente:
  1. Configuración de transcripción de entrada: En el SDK de Python de DashScope, update_session establece enable_input_audio_transcription en True de forma predeterminada. Configurar este valor en False envía input_audio_transcription: null en la configuración de la sesión. Para acceso directo mediante WebSocket o un DataChannel de WebRTC que envíe configuración de sesión, verifique session.update.session.input_audio_transcription con respecto a la configuración de transcripción de audio de entrada. enable_input_audio_transcription es un argumento del SDK, no un campo de nivel superior de session.update.
  2. Evento de fallo de transcripción: Maneje también conversation.item.input_audio_transcription.failed. Sus campos error.code, error.message y error.param proporcionan los detalles del error.
  3. Envío de audio: En el modo VAD, verifique si el servidor detectó el inicio y el fin del habla. En el modo Manual, asegúrese de haber enviado input_audio_buffer.commit. No espere únicamente a un evento de transcripción completada si el audio no se ha confirmado.
  4. Conexión y versión del SDK: Verifique que la conexión permaneciera activa durante esta entrada de audio. Para WebRTC, verifique también el estado del DataChannel. Si utiliza DashScope Python SDK, compruebe que su versión cumpla con el requisito mínimo de esta guía (2.0.1).

Códigos de error

Si la llamada al modelo falla y devuelve un mensaje de error, consulte Códigos de error para su resolución.

Lista de voces

Para obtener una lista de voces disponibles para el modelo Qwen-Omni-Realtime, consulte Voces.