Skip to main content

Traducción de audio y video en tiempo real - Qwen

Este tema presenta la traducción de voz y audiovisual en tiempo real de Qwen, incluyendo las capacidades del modelo, los modelos admitidos y la integración. Los modelos utilizan entradas de audio e imagen para traducir en tiempo real y generar texto o voz en el idioma objetivo para comunicación de voz y traducción de video.

Pruebe una demostración en línea con implementación con un clic mediante Function Compute .

Funcionalidades

  • Soporte multilingüe: Traduce entre 60 idiomas — 29 con salida de audio y texto, 31 con salida solo de texto — incluyendo chino, inglés, francés, alemán, ruso, japonés, coreano, español, portugués y árabe.
  • Mejora visual: Analiza señales visuales, como movimientos labiales, gestos y texto en pantalla, para mejorar la precisión de la traducción, especialmente en entornos ruidosos o para palabras ambiguas.
  • Latencia de 2.3 segundos: Ofrece interpretación simultánea con una latencia tan baja como 2.3 segundos.
  • Diarización de hablantes en tiempo real: Distingue a los diferentes hablantes y sus intervenciones cuando varias personas toman turnos para hablar, de modo que los oyentes puedan entender claramente quién dijo qué.
  • Interpretación simultánea sin pérdidas: Predice unidades semánticas para resolver diferencias en el orden de las palabras entre idiomas, logrando una calidad comparable a la traducción sin conexión.
  • Voz natural: Coincide automáticamente con la entonación y la emoción del audio de origen.
  • Configuración de palabras clave: Las palabras clave configurables mejoran la precisión de la traducción para términos específicos.
  • Clonación de voz: Clona la voz del hablante para la salida traducida. Admite clonación en tiempo real y perfiles de voz preclonados.

Procedimiento

1. Configurar la conexión

Establezca model en un modelo compatible al conectarse. El ejemplo de conexión a continuación utiliza qwen3.8-livetranslate-flash-realtime. Al conectarse mediante WebSocket, utilice los siguientes parámetros:
Se admiten las conexiones mediante AOQ, WebRTC y WebSocket. 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.
ParámetroDescripción
endpointRegión China (Beijing): wss://{WorkspaceId}.cn-beijing.maas.aliyuncs.com/api-ws/v1/realtime. Reemplace {WorkspaceId} con su ID de espacio de trabajo real.Región de Singapur: wss://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/api-ws/v1/realtime.Reemplace {WorkspaceId} con su ID de espacio de trabajo real.
query parameterEl parámetro de consulta del modelo debe establecerse en el nombre del modelo. Ejemplo: ?model=qwen3.8-livetranslate-flash-realtime
message headerUtilice un token Bearer para la autenticación: Authorization: Bearer DASHSCOPE_API_KEY
DASHSCOPE_API_KEY es su clave API de Model Studio.
Código de conexión de ejemplo (Python):
# pip install websocket-client
import json
import websocket
import os

API_KEY=os.getenv("DASHSCOPE_API_KEY")
API_URL = "wss://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/api-ws/v1/realtime?model=qwen3.8-livetranslate-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 idioma, modalidad y voz

Configure la sesión mediante session.update:
  • Idioma de destino: Establezca session.translation.language, como en para inglés. Con qwen3.8-livetranslate-flash-realtime, el idioma de origen se detecta automáticamente.
    Con qwen3.5-livetranslate-flash-realtime, establezca session.input_audio_transcription.language para especificar el idioma de origen, u omítalo para la detección automática.
  • Modalidades de salida: Con qwen3.8-livetranslate-flash-realtime, establezca session.output_modalities en ["text"] para solo texto o ["text", "audio"] para texto y audio (predeterminado).
    Con qwen3.5-livetranslate-flash-realtime, utilice session.modalities. Los valores admitidos y el valor predeterminado son los mismos.
  • Transcripción de origen: Con qwen3.8-livetranslate-flash-realtime, la transcripción de origen siempre está habilitada y no se puede desactivar. El propio modelo LiveTranslate genera la transcripción en el idioma de origen. La información relevante de las imágenes puede ayudar a resolver ambigüedades en el audio de origen. Reciba incrementos mediante conversation.item.input_audio_transcription.delta y transcripciones completas mediante conversation.item.input_audio_transcription.completed.
    Con qwen3.5-livetranslate-flash-realtime, la transcripción de origen está habilitada de forma predeterminada. Un modelo ASR independiente transcribe el audio de entrada. Establezca session.input_audio_transcription.model en qwen3-asr-flash-realtime para habilitarla o en null para deshabilitarla. Reciba incrementos mediante conversation.item.input_audio_transcription.text y transcripciones completas mediante conversation.item.input_audio_transcription.completed.
  • Audio y voz: Con qwen3.8-livetranslate-flash-realtime, los valores predeterminados son entrada PCM de 16000 Hz, salida PCM de 24000 Hz y la voz Tina. Para enviar audio Opus, establezca session.audio.input.format.type en opus. Consulte session.audio.output.voice en session.created para verificar la voz. Para conservar la voz del hablante, consulte Clonación de voz.
    Con qwen3.5-livetranslate-flash-realtime, configure el audio mediante session.sample_rate, session.input_audio_format y session.output_audio_format, y la voz mediante session.voice. La voz predeterminada también es Tina.
  • Palabras clave: Configure session.translation.corpus.phrases para especificar traducciones preferidas. Consulte Configurar palabras clave.
    Se recomienda utilizar no más de 1,000 palabras clave.

3. Introducir audio e imágenes

Envíe datos de audio e imágenes codificados en Base64 utilizando los eventos input_audio_buffer.append y input_image_buffer.append. La entrada de audio es obligatoria; la entrada de imagen es opcional.
Las imágenes pueden provenir de un archivo local o capturarse en tiempo real desde una transmisión de video.
Con qwen3.8-livetranslate-flash-realtime, el valor predeterminado es session.audio.input.turn_detection.type = speaker_detection. Envíe audio de forma continua; el servidor detecta los límites del habla y genera respuestas de traducción sin necesidad de confirmar manualmente cada enunciado. Consulte Identificar hablantes para obtener información sobre la configuración y los identificadores de hablantes.
La forma en que el modelo determina que una expresión está completa depende del modo VAD o modo Manual configurado mediante el parámetro turn_detection:
  • Modo VAD (predeterminado): El cliente envía continuamente eventos input_audio_buffer.append. Cuando el servidor detecta el inicio o fin del habla, devuelve eventos input_audio_buffer.speech_started y input_audio_buffer.speech_stopped respectivamente, confirma automáticamente el búfer de audio y activa la traducción. Las respuestas de traducción se generan de manera síncrona con la transmisión de audio y generalmente comienzan durante la entrada de audio, sin esperar a que termine el habla.
  • Modo manual: Establezca session.turn_detection en null. Después de que el cliente termina de enviar un enunciado completo, envía un evento input_audio_buffer.commit para confirmar el búfer de audio. Una vez que el servidor devuelve un evento input_audio_buffer.committed como confirmación, comienza automáticamente a generar la respuesta de traducción; el cliente no necesita enviar ningún otro evento para activar la respuesta. Para borrar el audio no confirmado antes de realizar la confirmación, envíe un evento input_audio_buffer.clear.

4. Recibir la respuesta del modelo

Con qwen3.8-livetranslate-flash-realtime, gestione las respuestas según las modalidades de salida:
  • Solo texto: Agregue los valores de delta de response.text.delta al final de los subtítulos en orden, sin sobrescribir el texto ya mostrado.
  • Texto y audio: Concatene delta de response.audio_transcript.delta para obtener texto, y decodifique en Base64 el campo delta de response.audio.delta para obtener fragmentos de audio.
response.done indica el final de una respuesta. Consulte Eventos del servidor para ver los campos del evento.
  • Generar resultados de reconocimiento del idioma de origen Establezca session.input_audio_transcription.model en qwen3-asr-flash-realtime. El servidor entonces devuelve tanto la traducción como el resultado del reconocimiento de voz (texto original) para el audio de entrada. El servidor devuelve estos eventos:
    • conversation.item.input_audio_transcription.text: Transmite los resultados de reconocimiento.
    • conversation.item.input_audio_transcription.completed: Devuelve el resultado final una vez completado el reconocimiento.
    • conversation.item.input_audio_transcription.failed: Devuelve información de error cuando falla el reconocimiento.
Las respuestas de traducción se generan sincrónicamente con la transmisión de audio y normalmente no requieren esperar a que termine el habla (consulte la descripción del modo VAD/Manual en la sección anterior). El formato de respuesta depende de la modalidad de salida.
  • Salida solo de texto El servidor transmite texto traducido incremental (incluyendo texto confirmado y texto predictivo tentativo) mediante eventos response.text.text; al finalizar, el texto traducido completo se devuelve en un evento response.text.done. stash contiene una traducción provisional. Permite mostrar los subtítulos antes, pero los eventos posteriores pueden reescribirla. Según las necesidades de la aplicación, muestre en el cliente la concatenación de text y stash, o solo el texto confirmado de text. Use item_id para actualizar el subtítulo correspondiente y muestre la traducción completa cuando reciba response.text.done.
  • Salida de texto y audio
qwen3.5-livetranslate-flash-realtime utiliza el evento response.text.text para la entrega incremental de texto, lo cual difiere del evento response.text.delta utilizado por los modelos Omni (conversación de voz dúplex completa). Estos eventos tienen estructuras de campos y semánticas diferentes; no los utilice indistintamente.
Asociar el texto original con su traducción Para mostrar juntos los subtítulos originales y traducidos, asócielos mediante el evento conversation.item.created de la traducción. item.id es el ID de la traducción, y el campo previous_item_id del nivel superior del evento es el ID del original correspondiente. El original o la traducción puede llegar primero. Guarde los resultados por separado, asócielos mediante esta relación y actualice cada subtítulo con su propio item_id. Consulte Asociación del texto original y la traducción para ver las definiciones de los campos.

5. Finalizar la sesión

Después de enviar todo el audio, envíe un evento session.finish y luego espere a que el servidor devuelva un evento session.finished antes de cerrar la conexión WebSocket. Si cierra la conexión WebSocket sin enviar session.finish, el VAD del servidor no puede detectar el final del último segmento de habla. Esto provoca que los resultados de traducción de ese segmento se pierdan por completo, y la conexión puede quedar colgada indefinidamente. Envíe siempre este evento antes de desconectarse.

Modelos admitidos

Modelos recomendados

ModeloVersiónVentana de contextoEntrada máximaSalida máxima
(tokens)
qwen3.8-livetranslate-flash-realtimeEstable53248491524096
qwen3.5-livetranslate-flash-realtime
Alias para qwen3.5-livetranslate-flash-realtime-2026-05-19
Estable53248491524096
qwen3.5-livetranslate-flash-realtime-2026-05-19Instantánea

Introducción

Traducir la entrada del micrófono en tiempo real

  1. Utilice Python 3.10 o posterior e instale pyaudio:
    • macOS
    • Debian/Ubuntu
    • CentOS
    • Windows
    brew install portaudio && pip install pyaudio
    
    Instale la dependencia de WebSocket: pip install websocket-client.
  2. Configure estas variables de entorno. La clave API y el espacio de trabajo deben pertenecer a la región indicada en la URL de conexión:
  3. Guarde el siguiente código como livetranslate_client.py, ejecute python livetranslate_client.py y hable al micrófono.
El ejemplo utiliza qwen3.8-livetranslate-flash-realtime para traducir la entrada del micrófono al inglés, imprimir el texto y reproducir el habla traducida en tiempo real. La entrada es mono, 16 bits, 16000 Hz PCM; la reproducción es mono, 16 bits, 24000 Hz PCM. Presione Ctrl+C para detener la grabación. El ejemplo envía session.finish, recibe y reproduce los resultados restantes, y cierra la conexión después de session.finished. Utilice auriculares para evitar que el habla traducida sea grabada nuevamente.
import base64
import json
import os
import signal
import threading
import time

import pyaudio
import websocket

model = "qwen3.8-livetranslate-flash-realtime"
workspace_id = os.environ["DASHSCOPE_WORKSPACE_ID"]
api_key = os.environ["DASHSCOPE_API_KEY"]
url = (
    f"wss://{workspace_id}.ap-southeast-1.maas.aliyuncs.com"
    f"/api-ws/v1/realtime?model={model}"
)
stop_recording = False
send_errors = []
ws = None
audio = None
input_stream = None
output_stream = None
sender = None
previous_sigint_handler = None


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


def stop_input(signum, frame):
    global stop_recording
    stop_recording = True


def send_audio():
    try:
        while not stop_recording:
            chunk = input_stream.read(1600)
            ws.send(json.dumps({
                "type": "input_audio_buffer.append",
                "audio": base64.b64encode(chunk).decode("ascii"),
            }))
    except Exception as error:
        send_errors.append(error)
    finally:
        try:
            ws.send(json.dumps({"type": "session.finish"}))
        except Exception as error:
            send_errors.append(error)
            ws.close()


def receive_translation():
    while True:
        event = receive()
        event_type = event.get("type")
        if event_type in ("response.text.delta", "response.audio_transcript.delta"):
            print(event["delta"], end="", flush=True)
        elif event_type == "response.audio.delta":
            output_stream.write(base64.b64decode(event["delta"]))
        elif event_type == "response.done":
            if event["response"]["status"] != "completed":
                raise RuntimeError(event["response"])
            print()
        elif event_type == "session.finished":
            return


try:
    ws = websocket.create_connection(
        url, header={"Authorization": f"Bearer {api_key}"}, timeout=30
    )
    while receive().get("type") != "session.created":
        pass
    ws.send(json.dumps({
        "type": "session.update",
        "session": {
            "output_modalities": ["text", "audio"],
            "translation": {"language": "en"},
        },
    }))
    while receive().get("type") != "session.updated":
        pass
    audio = pyaudio.PyAudio()
    input_stream = audio.open(
        format=pyaudio.paInt16, channels=1, rate=16000,
        input=True, frames_per_buffer=1600,
    )
    output_stream = audio.open(
        format=pyaudio.paInt16, channels=1, rate=24000, output=True,
    )
    print("Start speaking. Press Ctrl+C to stop recording and wait for the remaining translation.")
    previous_sigint_handler = signal.signal(signal.SIGINT, stop_input)
    sender = threading.Thread(target=send_audio, daemon=True)
    sender.start()
    receive_translation()
    stop_recording = True
    sender.join()
    if send_errors:
        raise send_errors[0]
except Exception:
    if send_errors:
        raise send_errors[0]
    raise
finally:
    stop_recording = True
    if ws is not None:
        ws.close()
    if sender is not None:
        sender.join()
    for stream in (input_stream, output_stream):
        if stream is not None:
            stream.stop_stream()
            stream.close()
    if audio is not None:
        audio.terminate()
    if previous_sigint_handler is not None:
        signal.signal(signal.SIGINT, previous_sigint_handler)

Configurar palabras clave

Agregar palabras clave puede mejorar la precisión de la traducción cuando necesita una traducción fija o necesita distinguir entre homófonos. Por ejemplo:
  • Redacción fija: El eslogan de Alibaba Cloud, “计算,为了无法计算的价值。”, tiene la redacción acordada en inglés “Computing, for the value beyond computation.”. La redacción y el orden de las palabras deben conservarse.
  • Nombres de marcas que suenan similar: Qoder suena como la palabra común coder. Cuando el hablante se refiere al producto Qoder, la traducción necesita conservar la ortografía de la marca.
La siguiente tabla compara las salidas de dos pruebas. Cada par utiliza el mismo audio y difiere únicamente en su configuración de palabras clave.
Contenido del audio de entradaSin palabras claveCon palabras clave
计算,为了无法计算的价值。Calcular. Para valores que no se pueden calcular.Computación, para el valor más allá de la computación.
Qoder 是面向真实工作的 Agentic 平台。Coder es un sistema agéntico diseñado para el trabajo en el mundo real. plataforma.Qoder, es una plataforma agéntica diseñada para el trabajo en el mundo real.

Configuración

Configure las palabras clave mediante session.translation.corpus.phrases, utilizando pares clave-valor para asignar palabras o frases del idioma de origen a sus traducciones preferidas. En la primera solicitud session.update de Primeros pasos, fusione el siguiente objeto translation en el objeto session existente. Mantenga la modalidad de salida, la voz y otras configuraciones para la sesión.
{
  "event_id": "configure-hotwords",
  "type": "session.update",
  "session": {
    "translation": {
      "language": "en",
      "corpus": {
        "phrases": {
          "计算,为了无法计算的价值。": "Computing, for the value beyond computation.",
          "Qoder": "Qoder"
        }
      }
    }
  }
}
Configure la sesión antes de enviar audio. Espere al evento session.updated del servidor antes de enviar eventos input_audio_buffer.append.

Identificar hablantes

qwen3.8-livetranslate-flash-realtime puede identificar a diferentes hablantes y etiquetarlos con speaker_id. Asocie este ID con el texto de origen y la traducción para mostrar subtítulos por hablante. Mantenga el valor predeterminado de speaker_detection, o configúrelo explícitamente en session.update. threshold distingue el silencio del habla válida. Los sonidos por debajo del umbral se filtran antes de llegar al modelo. El umbral está fijo en 0.5.
{"type": "session.update", "session": {"audio": {"input": {"turn_detection": {"type": "speaker_detection", "threshold": 0.5}}}}}
Asocie los eventos de la siguiente manera:
  1. Registre el speaker_id y el item_id de origen de input_audio_buffer.speech_started.
  2. Lea el texto de origen para ese item_id de conversation.item.input_audio_transcription.delta.
  3. En el evento conversation.item.created de la traducción, asocie item.id con el ID de origen en el campo de nivel superior previous_item_id del evento.
  4. Utilice el item_id de cada incremento de traducción para encontrar su texto de origen y hablante, y luego actualice el subtítulo.
Coloque estas variables y funciones antes de def receive_translation(): en el ejemplo de micrófono de inicio rápido. Dentro de esa función, llame a handle_speaker_event(event) inmediatamente después de event = receive(), y reemplace el print(event["delta"], end="", flush=True) original con pass para que el fragmento maneje toda la salida de subtítulos. El fragmento imprime el ID del hablante, el texto de origen y la traducción a medida que cambian, lo que le permite mostrar subtítulos por hablante. Mantenga el manejo existente de audio y finalización de sesión.
speaker_by_source = {}
source_by_translation = {}
source_text = {}
translation_text = {}


def show_subtitle(translation_id):
    source_id = source_by_translation.get(translation_id)
    if source_id not in speaker_by_source or translation_id not in translation_text:
        return
    print({
        "speaker_id": speaker_by_source[source_id],
        "source": source_text.get(source_id, ""),
        "translation": translation_text[translation_id],
    })


def handle_speaker_event(event):
    event_type = event.get("type")
    if event_type in ("response.text.delta", "response.audio_transcript.delta"):
        item_id = event["item_id"]
        translation_text[item_id] = translation_text.get(item_id, "") + event["delta"]
        show_subtitle(item_id)
        return
    if event_type == "conversation.item.created":
        item = event["item"]
        if any(part.get("type") == "input_audio" for part in item.get("content", [])):
            return
        source_id = event.get("previous_item_id")
        if item.get("role") == "assistant" and source_id is not None:
            source_by_translation[item["id"]] = source_id
            show_subtitle(item["id"])
        return
    if event_type == "input_audio_buffer.speech_started" and "speaker_id" in event:
        source_id = event["item_id"]
        speaker_by_source[source_id] = event["speaker_id"]
    elif event_type == "conversation.item.input_audio_transcription.delta":
        source_id = event["item_id"]
        source_text[source_id] = source_text.get(source_id, "") + event["delta"]
    elif event_type == "conversation.item.input_audio_transcription.completed":
        source_id = event["item_id"]
        source_text[source_id] = event["transcript"]
    else:
        return
    for translation_id, mapped_source in source_by_translation.items():
        if mapped_source == source_id:
            show_subtitle(translation_id)
Consulte ID de hablantes y Asociación origen/traducción para las definiciones de los campos.

Mejorar la traducción con imágenes

Los modelos de traducción en tiempo real de Qwen admiten entrada de imágenes para ayudar a desambiguar homónimos y reconocer nombres propios poco comunes durante la traducción. Envíe no más de 2 imágenes por segundo. Descargue las siguientes imágenes de muestra: medical mask.png, masquerade mask.png Reutilice la configuración de entrada de micrófono y conexión del inicio rápido:
  1. Instale Pillow: pip install Pillow.
  2. Establezca translation.language en zh para la salida en chino y luego diga "What is mask?" al micrófono cuando ejecute el ejemplo.
  3. Coloque el código de carga de imágenes a continuación antes de def send_audio(): en el ejemplo del micrófono, y reemplace el send_audio() original con esta versión. Utiliza los elementos existentes input_stream, stop_recording, ws, send_errors e importaciones.
import io
from PIL import Image

IMAGE_PATH = "medical-mask.png"
# IMAGE_PATH = "masquerade-mask.png"
with Image.open(IMAGE_PATH) as image:
    buffer = io.BytesIO()
    image.convert("RGB").save(buffer, format="JPEG")
image_bytes = buffer.getvalue()
if len(image_bytes) > 500_000:
    raise ValueError("JPEG > 500 KB")
image_b64 = base64.b64encode(image_bytes).decode("ascii")


def send_audio():
    try:
        last_image_time = None
        while not stop_recording:
            chunk = input_stream.read(1600)
            ws.send(json.dumps({
                "type": "input_audio_buffer.append",
                "audio": base64.b64encode(chunk).decode("ascii"),
            }))
            now = time.monotonic()
            if last_image_time is None or now - last_image_time >= 0.5:
                ws.send(json.dumps({
                    "type": "input_image_buffer.append",
                    "image": image_b64,
                }))
                last_image_time = now
    except Exception as error:
        send_errors.append(error)
    finally:
        try:
            ws.send(json.dumps({"type": "session.finish"}))
        except Exception as error:
            send_errors.append(error)
            ws.close()
El audio y las imágenes se intercalan, con un máximo de una imagen cada 0.5 segundos. Pruebe cada imagen y verifique si “mask” se traduce como la palabra en chino correspondiente al objeto. Después de presionar Ctrl+C para detener la grabación, el ejemplo solicita la finalización de la sesión y recibe los resultados restantes.

Clonación de voz

El modelo clona la voz del hablante a partir del audio de entrada y la utiliza para la salida traducida. Utilice un perfil de voz preclonado o clone en tiempo real durante la traducción. Útil para interpretación de conferencias, transmisiones en vivo y doblaje de video. Clonación en tiempo real: Tanto qwen3.8-livetranslate-flash-realtime como qwen3.5-livetranslate-flash-realtime clonan voces a partir del audio de entrada durante la traducción sin un cargo adicional por clonación. Las llamadas al modelo siguen facturándose por uso de tokens. Crear una voz previamente: use la API de clonación de voz para crear una voz previamente. El costo es de $0.01 por voz. Las solicitudes de creación fallidas no se cobran. Para conocer las regiones, el número de usos y el periodo de validez de la cuota gratuita, consulte Facturación. La traducción con una voz creada se sigue facturando según el uso de tokens del modelo. Configure los siguientes parámetros en session.update para habilitar la clonación de voz:
  • session.enable_voice_clone: Establezca este valor en true para habilitar la clonación de voz.
  • session.voice_clone_options.frequency: Controla cuándo ocurre la clonación de voz. Valores aceptados:
    • never: Utilice una voz creada previamente sin extraer una nueva voz durante esta sesión. Establezca session.voice en su ID de voz clonada.
    • once: Extrae la voz una vez del audio de entrada al inicio de la sesión y la reutiliza para traducciones posteriores en esta sesión. “Una vez” describe la extracción, no una única salida de audio. Adecuado para presentaciones de un solo hablante; establezca session.voice en default.
    • always: Extrae la voz antes de cada respuesta de audio traducido, de modo que la salida siga los cambios de hablante. Adecuado para múltiples hablantes; establezca session.voice en default.
  • session.voice: Especifica la voz de salida. El valor depende de la configuración de frequency:
    • Establecer en default: Úselo con frequency establecido en once o always. Clona la voz del hablante a partir del audio de entrada. Se utiliza una voz predeterminada hasta que finaliza la clonación.
    • Establezca un ID de voz clonada personalizada, por ejemplo qwen-translate-vc-xxx-yyy-zzz, con frequency en never. Prepare la voz previamente mediante la API de clonación de voz, con target_model establecido en el modelo de traducción que use.
Cuando frequency se establece en once o always , el parámetro voice debe establecerse en default . Cualquier otro valor hace que el servidor devuelva un error.

Ejemplos de configuración de clonación de voz

Con qwen3.8-livetranslate-flash-realtime, reemplace la configuración de session.update en su ejemplo de Inicio rápido con la configuración para su escenario.
Con qwen3.5-livetranslate-flash-realtime, reemplace session.output_modalities con session.modalities en los ejemplos. Los otros parámetros de clonación son los mismos. Especifique este modelo en el parámetro model de la conexión y gestione sus eventos de respuesta como se describe en Recibir respuestas del modelo.
Perfil de voz preclonado (para escenarios que requieren una voz fija):
{
    "type": "session.update",
    "session": {
        "output_modalities": ["text","audio"],
        "voice": "qwen-translate-vc-xxx-yyy-zzz",
        "translation": {
            "language": "en"
        },
        "enable_voice_clone": true,
        "voice_clone_options": {
            "frequency": "never"
        }
    }
}
Reutilizar una voz en la sesión actual (presentaciones con un solo hablante):
{
    "type": "session.update",
    "session": {
        "output_modalities": ["text","audio"],
        "voice": "default",
        "translation": {
            "language": "en"
        },
        "enable_voice_clone": true,
        "voice_clone_options": {
            "frequency": "once"
        }
    }
}
Seguir la voz del hablante actual (múltiples hablantes):
{
    "type": "session.update",
    "session": {
        "output_modalities": ["text","audio"],
        "voice": "default",
        "translation": {
            "language": "en"
        },
        "enable_voice_clone": true,
        "voice_clone_options": {
            "frequency": "always"
        }
    }
}

Despliegue con un clic de Function Compute

Para implementar la aplicación:
  1. Abra la plantilla de Function Compute, ingrese su clave API y haga clic en Create and Deploy Default Environment para probar la aplicación.
  2. Espere aproximadamente un minuto. En Detalles del entorno > Contexto del entorno, obtenga el endpoint, cambie el protocolo de http a https (por ejemplo, https://qwen-livetranslate-flash-realtime-intl.fcv3.xxx.ap-southeast-1.fc.devsapp.net/) y abra la URL en un navegador para interactuar con el modelo.
    Este endpoint utiliza un certificado autofirmado y es solo para pruebas temporales. Su navegador mostrará una advertencia de seguridad en su primera visita. Este es un comportamiento esperado. No utilice este endpoint en un entorno de producción. Para continuar, siga las instrucciones en pantalla (por ejemplo, haga clic en Advanced → Continuar a (no seguro)).
Si se le solicita configurar permisos de Resource Access Management, siga las instrucciones en pantalla.
Para ver el código fuente del proyecto, vaya a Información de recursos > Recursos de funciones .
Tanto Function Compute como Model Studio proporcionan una cuota gratuita para nuevos usuarios, suficiente para la depuración básica. Una vez agotada la cuota gratuita, se aplica la facturación de pago por uso.

Flujo de interacción

Con qwen3.8-livetranslate-flash-realtime, el servidor detecta los turnos y genera respuestas de forma predeterminada. La siguiente tabla resume las principales etapas de interacción. Consulte Eventos del servidor para ver los campos de los eventos.

Etapa

Acción del cliente

Eventos del servidor

Crear y configurar la sesión

Conectar y enviar session.update

session.created, session.updated

Enviar audio

input_audio_buffer.append

La transcripción de origen se transmite mediante conversation.item.input_audio_transcription.delta, seguida de conversation.item.input_audio_transcription.completed.

Recibir traducción y audio

Continuar recibiendo eventos del servidor

La traducción se devuelve mediante response.text.delta (solo texto) o response.audio_transcript.delta (texto y audio). El audio se devuelve mediante response.audio.delta. response.done marca el final de una respuesta.

Finalizar la sesión

session.finish

Cierre la conexión después de recibir session.finished.

La traducción utiliza un modelo WebSocket basado en eventos. La forma en que se determinan los límites del habla depende del modo VAD o modo Manual (consulte 3. Entrada de audio e imágenes). La siguiente tabla se basa en el modo VAD (predeterminado) y anota los diferentes eventos del servidor en el modo Manual.
Ciclo de vidaEvento del clienteEvento 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
Agregar audio al búfer
input_image_buffer.append
Agregar imagen al búfer
input_audio_buffer.commit
(Solo modo manual) Confirmar el búfer de audio
Modo VAD:input_audio_buffer.speech_started
Inicio de habla detectado
input_audio_buffer.speech_stopped
Fin del habla detectado; el servidor confirma automáticamente el búfer de audio
Modo manual:input_audio_buffer.committed
Se devuelve después de que el cliente envía input_audio_buffer.commit, confirmando que el búfer de audio se ha confirmado
Salida de audio del servidorNoneresponse.created
Indica que el servidor comienza a generar una respuesta.
response.output_item.added
Indica que hay un nuevo elemento de salida disponible.
conversation.item.created
Se crea un nuevo elemento de mensaje en la conversación.
response.content_part.added
Indica que se ha añadido una nueva parte de contenido al mensaje del asistente.
response.text.text
Texto traducido incremental en modalidad de solo texto
response.audio_transcript.text
Texto traducido incremental en modalidad de audio y texto
response.audio.delta
Contiene un fragmento incremental del audio sintetizado.
response.text.done
Texto de traducción completado en modalidad de solo texto
response.audio_transcript.done
Texto de traducción completado en modalidad de audio y texto
response.audio.done
Indica que el audio sintetizado está completo.
response.content_part.done
Indica que una parte de contenido de texto o audio para el mensaje del asistente está completa.
response.output_item.done
Indica que el elemento de salida completo para el mensaje del asistente ha finalizado.
response.done
Indica que la respuesta completa ha finalizado.
Terminación de sesiónsession.finish
Notifica al servidor que la entrada de audio ha finalizado
session.finished
Procesamiento del servidor completado; sesión finalizada
Después de enviar todo el audio, envíe un evento session.finish y espere a session.finished antes de cerrar la conexión WebSocket. Si cierra la conexión sin enviar session.finish, el servidor no podrá saber que la entrada de audio ha terminado, y los resultados de reconocimiento y traducción del último segmento de habla se perderán.

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

Qwen3.8-LiveTranslate-Flash-Realtime y Qwen3.5-LiveTranslate-Flash-Realtime
  • Audio: 7 tokens por segundo de audio de entrada; 12.5 tokens por segundo de audio de salida. Con la detección de voz del servidor, la duración del audio de entrada se calcula sobre el audio que llega al modelo después del filtrado. Los silencios eliminados por ese filtrado no se incluyen. Consulte la cantidad real de tokens de audio de entrada en response.usage.input_tokens_details.audio_tokens del evento response.done.
  • Imagen: Cada 32×32 píxeles consume 0.5 tokens. Para conocer los precios de tokens de cada modelo, consulte Precios y facturación de modelos.
Clonación en tiempo real: Tanto qwen3.8-livetranslate-flash-realtime como qwen3.5-livetranslate-flash-realtime clonan voces a partir del audio de entrada durante la traducción sin un cargo adicional por clonación. Las llamadas al modelo siguen facturándose por uso de tokens. Crear una voz previamente: use la API de clonación de voz para crear una voz previamente. El costo es de $0.01 por voz. Las solicitudes de creación fallidas no se cobran. Para conocer las regiones, el número de usos y el periodo de validez de la cuota gratuita, consulte Facturación. La traducción con una voz creada se sigue facturando según el uso de tokens del modelo.

Límites de tasa

Para obtener información sobre los límites de tasa del modelo, consulte Límites de tasa.

Idiomas admitidos

Utilice los siguientes códigos de idioma para especificar los idiomas de origen y de destino.
Algunos idiomas de destino solo admiten texto.

Código de idioma

Idioma

Salida

zh

Chino

Audio + texto

en

Inglés

Audio + texto

ar

Árabe

Audio + texto

de

Alemán

Audio + texto

fr

Francés

Audio + texto

es

Español

Audio + texto

pt

Portugués

Audio + texto

id

Indonesio

Audio + texto

it

Italiano

Audio + texto

ko

Coreano

Audio + texto

ru

Ruso

Audio + texto

th

Tailandés

Audio + texto

vi

Vietnamita

Audio + texto

ja

Japonés

Audio + texto

tr

Turco

Audio + texto

hi

Hindi

Audio + texto

ms

Malayo

Audio + texto

nl

Neerlandés

Audio + texto

ur

Urdu

Audio + texto

nb

Noruego bokmål

Audio + texto

sv

Sueco

Audio + texto

da

Danés

Audio + texto

he

Hebreo

Audio + texto

fi

Finlandés

Audio + texto

pl

Polaco

Audio + texto

is

Islandés

Audio + texto

cs

Checo

Audio + texto

fil

Filipino

Audio + texto

fa

Persa

Audio + texto

yue

Cantonés

Text

el

Griego

Text

af

Afrikáans

Text

ast

Asturiano

Text

be

Bielorruso

Text

bg

Búlgaro

Text

bn

Bengalí

Text

bs

Bosnio

Text

ca

Catalán

Text

ceb

Cebuano

Text

et

Estonio

Text

gl

Gallego

Text

gu

Guyaratí

Text

hr

Croata

Text

hu

Húngaro

Text

jv

Javanés

Text

kk

Kazajo

Text

kn

Canarés

Text

ky

Kirguís

Text

lv

Letón

Text

mk

Macedonio

Text

ml

Malayalam

Text

mr

Maratí

Text

pa

Punyabí

Text

ro

Rumano

Text

sk

Eslovaco

Text

sl

Esloveno

Text

sw

Suajili

Text

tg

Tayiko

Text

az

Azerbaiyano

Text

uk

Ucraniano

Text

Voces admitidas

Para consultar las voces admitidas y los valores correspondientes del parámetro voice, consulte Lista de voces.

Preguntas frecuentes

¿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:
  • Detección de voz 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 Facturación para conocer los precios y las reglas de cálculo.

¿Cómo migro de Gummy a LiveTranslate?

gummy-realtime-v1 y qwen3.8-livetranslate-flash-realtime usan protocolos distintos. Además del nombre del modelo, cambia el código que abre la conexión, envía el audio, recibe las traducciones y cierra la sesión. Este ejemplo del SDK de Python genera subtítulos en inglés. Puedes reutilizar el audio PCM mono de 16 bits a 16 kHz y cambiar estas cuatro llamadas.

Paso

Gummy

LiveTranslate

Conexión y configuración

TranslationRecognizerRealtime(..., translation_target_languages=["en"])

start()

client.audio.realtime.connect(model="qwen3.8-livetranslate-flash-realtime")

session.update_session(output_modalities=["text"], translation_params={"language": "en"})

Configura la sesión tras conectarte. Espera a session.updated antes de enviar audio.

Envío de audio

send_audio_frame(data)

session.append_audio(data)

Subtítulos

on_event(..., translation_result, ...)

translation_result.get_translation("en").text

session.events()

response.text.delta

Añade el contenido de cada campo delta al subtítulo.

Fin de la sesión

stop()

session.end_session()

Sigue recibiendo subtítulos y cierra la conexión tras recibir session.finished.

Instala DashScope 2.0.2. Configura DASHSCOPE_API_KEY con la clave API de Pekín y DASHSCOPE_WORKSPACE con el ID del espacio de trabajo de esa región. Guarda el código en subtitles.py y ejecuta python subtitles.py input.wav con un archivo WAV PCM mono de 16 bits a 16 kHz.
import os
import sys
import time
import wave
from concurrent.futures import ThreadPoolExecutor

import dashscope


def send_audio(session, recording):
    while chunk := recording.readframes(1600):
        session.append_audio(chunk)
        time.sleep(len(chunk) / 32000)
    session.end_session()


def translate(path):
    client = dashscope.Client(api_key=os.environ["DASHSCOPE_API_KEY"],
                              workspace=os.environ["DASHSCOPE_WORKSPACE"],
                              region="cn-beijing")
    with wave.open(path, "rb") as recording:
        if (recording.getframerate(), recording.getnchannels(), recording.getsampwidth()) != (16000, 1, 2):
            raise ValueError("Expected a 16 kHz mono 16-bit PCM WAV file")
        with client.audio.realtime.connect(model="qwen3.8-livetranslate-flash-realtime", timeout=30) as session:
            events = session.events()
            for event in events:
                if event["type"] == "session.created":
                    session.update_session(output_modalities=["text"], translation_params={"language": "en"})
                elif event["type"] == "session.updated":
                    break
                elif event["type"] == "error":
                    raise RuntimeError(event["error"])
            else:
                raise RuntimeError("Session closed before configuration completed")

            with ThreadPoolExecutor(max_workers=1) as pool:
                sender = pool.submit(send_audio, session, recording)
                try:
                    for event in events:
                        kind = event["type"]
                        if kind == "response.text.delta":
                            print(event["delta"], end="", flush=True)
                        elif kind == "response.text.done":
                            print(flush=True)
                        elif kind == "response.done" and event["response"]["status"] != "completed":
                            raise RuntimeError(event["response"].get("status_details"))
                        elif kind == "error":
                            raise RuntimeError(event["error"])
                        elif kind == "session.finished":
                            break
                    else:
                        raise RuntimeError("Session closed before session.finished")
                except BaseException:
                    session.close()
                    raise
                sender.result()


if __name__ == "__main__":
    translate(sys.argv[1])
Para una conexión WebSocket directa, realiza estos tres cambios. Consulta el ejemplo completo en Introducción.
  • Dirección: cambia /api-ws/v1/inference por /api-ws/v1/realtime?model=qwen3.8-livetranslate-flash-realtime.
  • Audio: sustituye las tramas binarias por eventos JSON input_audio_buffer.append y envía el PCM codificado en Base64 en el campo audio.
  • Traducción: sustituye result-generated por response.text.delta y añade cada fragmento delta al subtítulo. Cuando termines de enviar el audio, envía session.finish y espera a session.finished antes de cerrar.

¿Cómo reanudar la traducción después de una desconexión?

Si recibe no semantic result after merged audio exceeded 60s y se cierra la conexión WebSocket, cree una sesión nueva para reanudar la traducción:
  1. Deje de enviar audio a la conexión anterior.
  2. Vuelva a conectarse y envíe session.update para restablecer el idioma de destino, las modalidades de salida y los demás ajustes.
  3. Espere a recibir session.updated y luego reanude el envío de audio.
Si ocurre un error de parámetro y la conexión sigue abierta, corrija la solicitud y continúe usando esa conexión. Si usa dashscope.Client(), reanude también la recepción de eventos.