Skip to main content

リアルタイム音声・動画翻訳 - Qwen

qwen3.5-livetranslate-flash-realtime は、60 言語 (音声+テキスト 29 言語、テキストのみ 31 言語) をサポートする視覚拡張リアルタイム翻訳モデルです。ビデオストリームやローカルファイルから音声と画像の入力を処理し、視覚的なコンテキストを使用して精度を向上させ、翻訳されたテキストと音声をリアルタイムで出力します。

Function Compute を使用したワンクリックデプロイでオンラインデモをお試しください。

特徴

  • 多言語サポート:中国語、英語、フランス語、ドイツ語、ロシア語、日本語、韓国語、スペイン語、ポルトガル語、アラビア語など、60 言語間の翻訳に対応しています (29 言語は音声とテキスト出力、31 言語はテキストのみの出力)。
  • 視覚拡張:唇の動き、ジェスチャー、画面上のテキストなどの視覚的な手がかりを分析して、特に騒がしい環境や曖昧な単語の翻訳精度を向上させます。
  • 2.3 秒のレイテンシー:わずか 2.3 秒の低レイテンシーで同時通訳を実現します。
  • リアルタイム話者分離:複数の話者が交互に話す際に、話者とその発言内容を区別し、誰が何を話したかを明確にします。
  • ロスレス同時通訳:意味単位を予測して言語間の語順の違いを解決し、オフライン翻訳に匹敵する品質を実現します。
  • 自然な音声:ソース音声のイントネーションや感情に自動的に合わせます。
  • ホットワード構成:設定可能なホットワードにより、特定の用語の翻訳精度が向上します。
  • 音声クローニング:話者の声をクローンして翻訳出力に使用します。リアルタイムクローニングと、事前にクローンされた音声プロファイルをサポートしています。

操作手順

1. 接続の構成

WebSocket で接続する場合は、以下のパラメーターを設定します: AOQ、WebRTC、WebSocket プロトコルによる接続をサポートしています。安定したレイテンシー、低速ネットワークでの回復力、組み込みの全二重ノイズ抑制およびエコーキャンセレーションを優先するクライアントサイドの統合には、AOQ を推奨します。プロトコルの比較については、「リアルタイム API の概要」をご参照ください。
パラメーター説明
endpointAOQ、WebRTC、WebSocket によるアクセスをサポートします。安定したレイテンシー、弱いネットワークでの対話性能、リアルタイム全二重通信のノイズ抑制とエコーキャンセルを重視するクライアント統合では、AOQ を優先的に検討してください。プロトコルの比較と選択は、API リファレンスをご覧ください。シンガポールリージョン:wss://WorkspaceId.ap-southeast-1.maas.aliyuncs.com/api-ws/v1/realtime。WorkspaceId を実際のワークスペース ID に置き換えてください。
query parameterモデルのクエリパラメーターはモデル名に設定する必要があります。例:?model=qwen3.8-livetranslate-flash-realtime
message header認証には Bearer トークンを使用します:Authorization: Bearer DASHSCOPE_API_KEY
DASHSCOPE_API_KEY は、Model Studio から取得した API キーです。
接続コードのサンプル (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"サーバーに接続しました: {API_URL}")
def on_message(ws, message):
    data = json.loads(message)
    print("受信したイベント:", json.dumps(data, indent=2))
def on_error(ws, error):
    print("エラー:", error)

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

ws.run_forever()

2. 言語、モダリティ、音声の構成

session.update を送り、session.updated を受信してから音声を送ります。
  • 対象言語:session.translation.language で指定します。デフォルトは en(英語)で、指定できる値は対応言語を参照してください。qwen3.8-livetranslate-flash-realtime では原言語が自動検出されます。
    qwen3.5-livetranslate-flash-realtime で原言語を指定する場合は、session.input_audio_transcription.language を設定する必要があります。省略すると自動検出されます。
  • 出力:qwen3.8-livetranslate-flash-realtime では、session.output_modalities を ["text"] にすると訳文のみ、["text", "audio"] にすると訳文と音声(デフォルト)を出力します。テキストのみ対応の対象言語では ["text"] が必要です。
    qwen3.5-livetranslate-flash-realtime では session.modalities を使用します。指定できる値とデフォルト値は同じです。
  • 原文の文字起こし:qwen3.8-livetranslate-flash-realtime では常に有効で、無効にできません。原文の文字起こしは LiveTranslate モデル自体が生成します。画像内の関連情報は、入力音声の曖昧さの解消にも役立ちます。conversation.item.input_audio_transcription.delta で増分を、conversation.item.input_audio_transcription.completed で完全な結果を受信します。
    qwen3.5-livetranslate-flash-realtime ではデフォルトで有効です。独立した ASR モデルが入力音声を文字起こしします。session.input_audio_transcription.model を qwen3-asr-flash-realtime にすると有効、null にすると無効になります。増分は conversation.item.input_audio_transcription.text、完全な結果は conversation.item.input_audio_transcription.completed で返されます。
  • 音声と音色:qwen3.8-livetranslate-flash-realtime のデフォルトは入力 PCM 16000 Hz、出力 PCM 24000 Hz、音色 Tina です。Opus 音声を入力するには、session.audio.input.format.type を opus に設定します。session.created の session.audio.output.voice で音色を確認できます。話者の音色を維持する方法は音声クローニングを参照してください。
    qwen3.5-livetranslate-flash-realtime では、音声を session.sample_rate、session.input_audio_format、session.output_audio_format で、音色を session.voice で設定します。デフォルトの音色は同じく Tina です。
  • ホットワード:session.translation.corpus.phrases でブランドの綴りや指定訳語を設定します。設定方法を参照してください。
    ホットワードは 1,000 件以内にすることを推奨します。
{"type": "session.update", "session": {"output_modalities": ["text", "audio"], "translation": {"language": "en"}}}

3. 音声と画像の入力

input_audio_buffer.append および input_image_buffer.append イベントを使用して、Base64 エンコードされた音声および画像データを送信します。音声入力は必須ですが、画像入力はオプションです。
画像はローカルファイルから、またはビデオストリームからリアルタイムでキャプチャできます。
qwen3.8-livetranslate-flash-realtime では、デフォルトは session.audio.input.turn_detection.type = speaker_detection です。音声を継続して送信すると、サーバーが発話の区切りを検出し、翻訳応答を生成します。発話ごとの手動コミットは不要です。設定方法と話者 ID の処理は話者の発言を区別するを参照してください。
モデルが発話の完了を判断する方法は、turn_detection パラメーターを介して構成された VAD モードまたは手動モードによって異なります:
  • VAD モード (デフォルト):クライアントは継続的に input_audio_buffer.append イベントを送信します。サーバーが発話の開始/終了を検出すると、それぞれ input_audio_buffer.speech_started および input_audio_buffer.speech_stopped イベントを返し、音声バッファーを自動的にコミットして翻訳をトリガーします。翻訳応答はストリーミング音声と同期して生成され、通常は発話が終了するのを待たずに音声入力中に開始されます。
  • 手動モード:session.turn_detection を null に設定します。クライアントは完全な発話の送信を終えた後、input_audio_buffer.commit イベントを送信して音声バッファーをコミットします。サーバーが input_audio_buffer.committed イベントを返して確認した後、自動的に翻訳応答の生成を開始します。クライアントは応答をトリガーするために他のイベントを送信する必要はありません。コミットする前に未コミットの音声をクリアするには、input_audio_buffer.clear イベントを送信します。

4. モデルの応答の受信

qwen3.8-livetranslate-flash-realtime では、出力モダリティに応じて応答を受信します:
  • 原文:conversation.item.input_audio_transcription.delta を連結し、conversation.item.input_audio_transcription.completed で全文を取得します。
  • 訳文:テキストのみは response.text.delta、テキストと音声は response.audio_transcript.delta を使います。同じメッセージの delta を受信順に連結し、前の内容を上書きしません。
  • 音声:response.audio.delta の delta を Base64 から復号し、順番に再生または保存します。
response.done は 1 回の翻訳応答の終了です。response.status で生成結果を確認します。セッションは終了せず、音声を続けて送れます。
  • ソース言語の認識結果の出力 session.input_audio_transcription.model を qwen3-asr-flash-realtime に設定します。これにより、サーバーは翻訳結果と入力音声の音声認識結果 (原文テキスト) の両方を返します。 サーバーは以下のイベントを返します:
    • conversation.item.input_audio_transcription.text:認識結果をストリーム配信します。
    • conversation.item.input_audio_transcription.completed:認識完了後に最終結果を返します。
    • conversation.item.input_audio_transcription.failed:認識が失敗した場合にエラー情報を返します。
翻訳応答はストリーミング音声と同期して生成され、通常は発話の終了を待つ必要はありません (前のセクションの VAD/手動モードの説明をご参照ください)。応答形式は出力モダリティによって異なります。
  • テキストのみの出力 サーバーは response.text.text イベントを介して、インクリメンタルな翻訳テキスト (確定テキストと仮の予測テキストを含む) をストリーム配信します。完了すると、完全な翻訳テキストが response.text.done イベントで返されます。 stash は暫定の訳文です。字幕を早く表示できますが、後から書き換えられる場合があります。用途に応じて、クライアントで text と stash を連結して表示するか、確定した text だけを表示します。item_id が一致する字幕を更新し、response.text.done を受信したら完全な訳文を表示します。
  • テキストと音声の出力
    • テキスト サーバーは response.audio_transcript.text イベントを介して、インクリメンタルな翻訳テキストをストリーム配信します。完了すると、完全な翻訳テキストが response.audio_transcript.done イベントで返されます。
    • 音声 サーバーは、response.audio.delta イベントで、インクリメンタルな Base64 エンコードされた音声データを返します。
リアルタイム翻訳モデルは、インクリメンタルなテキスト配信に response.text.text イベントを使用しますが、これは Omni (全二重音声会話) モデルで使用される response.text.delta イベントとは異なります。これらのイベントはフィールド構造とセマンティクスが異なるため、混同して使用しないでください。
原文と訳文を対応付ける 原文と訳文の字幕を並べて表示する場合は、訳文の conversation.item.created イベントで対応付けます。item.id は訳文 ID、イベントの最上位にある previous_item_id は対応する原文 ID です。 原文と訳文は、どちらが先に届くか決まっていません。それぞれを保存し、この対応関係で組み合わせて、各字幕をそれぞれの item_id で更新します。フィールドの説明は原文・訳文の関連付けを参照してください。

5. セッションの終了

すべての音声を送信した後、session.finishを送信し、サーバーが session.finished イベントを返すのを待ってから WebSocket 接続を閉じます。 session.finish を送信せずに WebSocket を閉じると、サーバーの VAD は最後の発話セグメントの終了を検出できません。これにより、そのセグメントの翻訳結果が完全に失われ、接続が無期限にハングする可能性があります。切断する前に必ずこのイベントを送信してください。

サポート対象モデル

推奨モデル

モデルバージョンコンテキストウィンドウ最大入力最大出力
(トークン)
qwen3.8-livetranslate-flash-realtime安定版53,24849,1524,096
qwen3.5-livetranslate-flash-realtime
qwen3.5-livetranslate-flash-realtime-2026-05-19 のエイリアス
安定版53,24849,1524,096
qwen3.5-livetranslate-flash-realtime-2026-05-19スナップショット

クイックスタート

マイク入力をリアルタイムで翻訳する

  1. Python 3.10 以降を使用し、pyaudio をインストールします:
    • macOS
    • Debian/Ubuntu
    • CentOS
    • Windows
    brew install portaudio && pip install pyaudio
    
    WebSocket の依存ライブラリをインストールします:pip install websocket-client。
  2. 以下の環境変数を設定します。API キーとワークスペースは、接続 URL のリージョンに属している必要があります。
    • DASHSCOPE_API_KEY: リージョンとワークスペースに対応する API キー。API キーの取得を参照してください。
    以下のコードで WorkspaceId を指定します。
  3. 以下のコードを livetranslate_client.py に保存し、python livetranslate_client.py を実行して、マイクに向かって話します。
この例は qwen3.8-livetranslate-flash-realtime でマイク入力を英語に翻訳し、訳文を表示して翻訳音声をリアルタイムで再生します。入力は 16000 Hz、モノラル、16 ビット PCM、再生は 24000 Hz、モノラル、16 ビット PCM です。Ctrl+C で録音を停止すると、session.finish を送信し、残りの結果を受信・再生して、session.finished の受信後に接続を閉じます。翻訳音声がマイクに再入力されないよう、ヘッドホンを使用してください。
import base64
import json
import os
import signal
import threading
import time

import pyaudio
import websocket

model = "qwen3.8-livetranslate-flash-realtime"
api_key = os.environ["DASHSCOPE_API_KEY"]
url = (
    "wss://{WorkspaceId}.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("話し始めてください。Ctrl+C で録音を停止し、残りの翻訳を待ちます。")
    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)

ホットワードを設定する

定訳を使いたい場合や同音語を区別したい場合は、ホットワードを追加することで翻訳の精度を向上できます。例えば、次のような場合です。
  • 定訳のある表現:Alibaba Cloud のスローガン「計算できない価値のためのコンピューティング。」の英語表現は「Computing, for the value beyond computation.」と定められています。語句と語順を保つ必要があります。
  • 同音のブランド名:Qoder は一般的な英単語 coder と同じ発音です。製品 Qoder を指している場合、訳文でもブランド名の綴りを保つ必要があります。
以下は 2 組のテストで得られた出力の比較です。各組では同じ音声を使用し、ホットワード設定だけを変更しています。
入力音声の内容ホットワードなしホットワードあり
計算できない価値のためのコンピューティング。Computing for inestimable value.Computing, for the value beyond computation.
Qoderは実際の業務向けのエージェンティックプラットフォームです。Coder is an actual agent platform for business use.Qoder. It is a real-world, business-oriented agent platform.

設定方法

session.translation.corpus.phrases にキーと値のペアを設定し、原言語の単語やフレーズを指定の訳語にマッピングします。 「開始方法」の最初の session.update リクエストで、以下の translation オブジェクトを既存の session に組み込みます。セッションの出力モダリティや音声などの設定は保持してください。
{
  "event_id": "configure-hotwords",
  "type": "session.update",
  "session": {
    "translation": {
      "language": "en",
      "corpus": {
        "phrases": {
          "計算できない価値のためのコンピューティング。": "Computing, for the value beyond computation.",
          "Qoder": "Qoder"
        }
      }
    }
  }
}
音声の送信前に設定を行い、サーバーから session.updated を受信してから input_audio_buffer.append の送信を開始します。

話者の識別

qwen3.8-livetranslate-flash-realtime は異なる話者を識別し、speaker_id で示すことができます。この ID を原文と訳文に関連付けることで、話者ごとの字幕を表示できます。 デフォルトの speaker_detection を維持するか、session.update で明示的に設定します。threshold は無音と有効な音声を区別するためのしきい値です。しきい値を下回る音はフィルタリングされ、モデルには入力されません。この値は 0.5 固定です。
{"type": "session.update", "session": {"audio": {"input": {"turn_detection": {"type": "speaker_detection", "threshold": 0.5}}}}}
  1. input_audio_buffer.speech_started の speaker_id と原文の item_id を記録します。
  2. 同じ item_id の原文を conversation.item.input_audio_transcription.delta で取得します。
  3. 訳文の conversation.item.created で、item.id をイベント最上位の previous_item_id に関連付けます。
  4. 訳文増分の item_id から原文と話者を見つけ、字幕を更新します。
クイックスタートのマイク入力の例で、def receive_translation(): の前に以下の変数と関数を置きます。この関数内で event = receive() の直後に handle_speaker_event(event) を呼び、元の print(event["delta"], end="", flush=True) を pass に置き換えて、字幕の出力を以下のコードに任せます。原文や訳文が変わるたびに話者 ID、原文、訳文が表示され、話者ごとの字幕に利用できます。音声とセッション終了の処理は維持してください。
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)
定義は話者 IDと原文・訳文の関連付けを参照してください。

画像による翻訳精度の向上

Qwen のリアルタイム翻訳モデルは画像入力に対応し、翻訳中の同音異義語の曖昧さを解消し、一般的でない固有名詞の認識に役立ちます。1 秒あたり 2 枚以下の画像を送信してください。 以下のサンプル画像をダウンロードしてください:medical mask.png、masquerade mask.png クイックスタートのマイク入力と接続設定を再利用します。
  1. pip install Pillow で Pillow をインストールします。
  2. translation.language を ja に変更し、実行時にマイクに向かって「What is mask?」と言います。
  3. マイク入力の例で、def send_audio(): の前に以下の画像読み込みコードを追加し、send_audio() をこの関数に置き換えます。既存の input_stream、stop_recording、ws、send_errors とインポートを使います。
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()
音声と画像を交互に送り、画像は 0.5 秒に最大 1 枚です。それぞれの画像を使い、「mask」が対応する物を指す訳語になるかを確認します。Ctrl+C で録音を停止した後、セッション終了を要求し、残りの結果を受信します。

音声クローニング

モデルは入力音声から話者の声をクローンし、翻訳出力に使用します。事前にクローンされた音声プロファイルを使用するか、サーバーにリアルタイムでクローンさせることができます。会議の通訳、ライブストリーミング、ビデオの吹き替えなどに役立ちます。 リアルタイムクローニング:qwen3.8-livetranslate-flash-realtime、qwen3.5-livetranslate-flash-realtime ともに、翻訳中に入力音声から音色を複製するための追加料金はかかりません。モデル呼び出しは引き続きトークン使用量に応じて課金されます。 事前に音声を作成:音声クローニング APIで事前に音声を作成します。料金は 1 音声あたり $0.01 です。作成に失敗した場合は課金されません。無料クォータのリージョン、回数、有効期間は、料金をご覧ください。作成済みの音声を使用した翻訳には、引き続きモデルの Token 使用量に応じて課金されます。 音声クローニングを有効にするには、session.update で以下のパラメーターを設定します:
  • session.enable_voice_clone:true に設定して音声クローニングを有効にします。
  • session.voice_clone_options.frequency:音声クローニングが行われるタイミングを制御します。指定可能な値:
    • never:事前作成した音色を使い、このセッションで音色を抽出し直しません。session.voice に自分の音色 ID を指定します。
    • once:セッション開始時に一度だけ音色を抽出し、同じセッション内の以降の翻訳で再利用します。「一度」は抽出回数を指し、音声出力が一回だけという意味ではありません。一人の講演に適し、session.voice は default にします。
    • always:翻訳音声の応答を生成するたびに音色を抽出し、話者の変化に追従します。複数人の会話に適し、session.voice は default にします。
  • session.voice:出力する音声を指定します。値は frequency の設定によって異なります:
    • default に設定:frequency を once または always に設定して使用します。入力音声から話者の声をクローンします。クローニングが完了するまではデフォルトの音声が使用されます。
    • カスタムのクローン音声 ID(例:qwen-translate-vc-xxx-yyy-zzz)を設定する場合は、frequency を never にして使用します。音声クローニング APIで事前に音声を用意し、target_model には使用する翻訳モデルを指定してください。
frequency が once または always に設定されている場合、voice パラメーターは default に設定する必要があります。他の値を設定すると、サーバーはエラーを返します。

音声クローニングの構成例

qwen3.8-livetranslate-flash-realtime を使用する場合は、クイックスタートにあるこのモデルの例の session.update 設定を、目的に合う設定で置き換えます。
qwen3.5-livetranslate-flash-realtime を使用する場合は、例の session.output_modalities を session.modalities に置き換えます。他のクローニングパラメーターは同じです。接続時の model にはこのモデルを指定し、モデル応答の受信の説明に従って、このモデルの応答イベントを処理してください。
事前にクローンされた音声プロファイル (固定の音声を使用したい場合):
{
    "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"
        }
    }
}
現在のセッションで同じ音色を再利用する(一人の講演):
{
    "type": "session.update",
    "session": {
        "output_modalities": ["text","audio"],
        "voice": "default",
        "translation": {
            "language": "en"
        },
        "enable_voice_clone": true,
        "voice_clone_options": {
            "frequency": "once"
        }
    }
}
現在の話者に音色を合わせる(複数人の会話):
{
    "type": "session.update",
    "session": {
        "output_modalities": ["text","audio"],
        "voice": "default",
        "translation": {
            "language": "en"
        },
        "enable_voice_clone": true,
        "voice_clone_options": {
            "frequency": "always"
        }
    }
}

ワンクリック Function Compute デプロイメント

アプリケーションをデプロイするには:
  1. Function Compute テンプレートを開き、API キーを入力して、[デフォルト環境の作成とデプロイ] をクリックしてアプリケーションをテストします。
  2. 約 1 分待ちます。[環境詳細] > [環境コンテキスト] でエンドポイントを取得し、プロトコルを http から https に変更し (例:https://qwen-livetranslate-flash-realtime-intl.fcv3.xxx.ap-southeast-1.fc.devsapp.net/)、ブラウザで URL を開いてモデルと対話します。
    このエンドポイントは自己署名証明書を使用しており、一時的なテスト専用です。初めてアクセスすると、ブラウザにセキュリティ警告が表示されます。これは予期された動作です。このエンドポイントを本番環境で使用しないでください。続行するには、画面の指示に従ってください (例:[詳細設定] → [安全でないサイトに移動] をクリック)。
Resource Access Management の権限を設定するよう求められた場合は、画面の指示に従ってください。
プロジェクトのソースコードを表示するには、[リソース情報] > [関数リソース] に移動します。
Function Compute と Model Studio の両方で、新規ユーザー向けに無料クォータが提供されており、基本的なデバッグには十分です。無料クォータを使い切った後は、従量課金が適用されます。

インタラクションフロー

qwen3.8-livetranslate-flash-realtime の主な対話フローは次のとおりです:
段階クライアントサーバー
接続URL と認証session.created
設定session.updatesession.updated または error
入力input_audio_buffer.append を継続送信、画像は任意話者 ID と原文認識イベント
受信訳文を連結、音声を復号増分、response.done は 1 応答の終了
終了入力を止め、session.finish、受信を継続session.finished のあと切断し、音声再生を完了
翻訳はイベント駆動型の WebSocket モデルを使用します。発話の境界を決定する方法は、VAD モードまたは手動モードによって異なります (「3. 音声と画像の入力」をご参照ください)。以下の表は VAD モード (デフォルト) に基づいており、手動モードでの異なるサーバーイベントにアノテーションを付けています。
ライフサイクルクライアントイベントサーバーイベント
セッションの初期化session.update
セッション構成
session.created
セッションが作成されました
session.updated
セッション構成が更新されました
ユーザーの音声入力input_audio_buffer.append
バッファーに音声を追加
input_image_buffer.append
バッファーに画像を追加
input_audio_buffer.commit
(手動モードのみ) 音声バッファーをコミット
VAD モード:input_audio_buffer.speech_started
発話開始を検出
input_audio_buffer.speech_stopped
発話終了を検出。サーバーは自動的に音声バッファーをコミットします
手動モード:input_audio_buffer.committed
クライアントが input_audio_buffer.commit を送信した後に返され、音声バッファーがコミットされたことを確認します
サーバーの音声出力なしresponse.created
サーバーが応答の生成を開始したことを示します。
response.output_item.added
新しい出力項目が利用可能になったことを示します。
conversation.item.created
会話に新しいメッセージ項目が作成されます。
response.content_part.added
アシスタントメッセージに新しいコンテンツパートが追加されたことを示します。
response.text.text
テキストのみのモダリティでのインクリメンタルな翻訳テキスト
response.audio_transcript.text
音声+テキストモダリティでのインクリメンタルな翻訳テキスト
response.audio.delta
合成音声のインクリメンタルなチャンクを含みます。
response.text.done
テキストのみのモダリティでの翻訳テキストが完了
response.audio_transcript.done
音声+テキストモダリティでの翻訳テキストが完了
response.audio.done
合成音声が完了したことを示します。
response.content_part.done
アシスタントメッセージのテキストまたは音声コンテンツパートが完了したことを示します。
response.output_item.done
アシスタントメッセージの出力項目全体が完了したことを示します。
response.done
応答全体が完了したことを示します。
セッションの終了session.finish
音声入力が完了したことをサーバーに通知します
session.finished
サーバーの処理が完了し、セッションが終了しました
すべての音声を送信した後、session.finish イベントを送信し、WebSocket を閉じる前に session.finished を待ってください。session.finish を送信せずに接続を閉じると、サーバーは音声入力が終了したことを知ることができず、最後の発話セグメントの認識および翻訳結果が失われます。

API

AOQ のアクセスフローとサンプルは、AOQ アクセスをご覧ください。プロトコルの選択とリファレンスの入口は、API リファレンスをご覧ください。

課金

Qwen3.8-LiveTranslate-Flash-Realtime / Qwen3.5-LiveTranslate-Flash-Realtime
  • 音声:入力音声 1 秒あたり 7 トークン。出力音声 1 秒あたり 12.5 トークン。 サーバー側の音声検出を使う場合、入力音声の長さは、フィルタリング後にモデルへ渡される音声を基準に計算します。除去された無音区間は含みません。実際の入力音声トークン数は、response.done イベントの response.usage.input_tokens_details.audio_tokens で確認できます。
  • 画像:32×32 ピクセルごとに 0.5 トークンを消費します。
料金:モデルリスト。 リアルタイムクローニング:qwen3.8-livetranslate-flash-realtime、qwen3.5-livetranslate-flash-realtime ともに、翻訳中に入力音声から音色を複製するための追加料金はかかりません。モデル呼び出しは引き続きトークン使用量に応じて課金されます。 事前に音声を作成:音声クローニング APIで事前に音声を作成します。料金は 1 音声あたり $0.01 です。作成に失敗した場合は課金されません。無料クォータのリージョン、回数、有効期間は、料金をご覧ください。作成済みの音声を使用した翻訳には、引き続きモデルの Token 使用量に応じて課金されます。

レート制限

モデルのレート制限については、「レート制限」をご参照ください。

サポート対象言語

ソース言語とターゲット言語を指定するには、以下の言語コードを使用します。
一部のターゲット言語はテキストのみをサポートしています。

言語コード

言語

出力

zh

中国語

音声 + テキスト

en

英語

音声 + テキスト

ar

アラビア語

音声 + テキスト

de

ドイツ語

音声 + テキスト

fr

フランス語

音声 + テキスト

es

スペイン語

音声 + テキスト

pt

ポルトガル語

音声 + テキスト

id

インドネシア語

音声 + テキスト

it

イタリア語

音声 + テキスト

ko

韓国語

音声 + テキスト

ru

ロシア語

音声 + テキスト

th

タイ語

音声 + テキスト

vi

ベトナム語

音声 + テキスト

ja

日本語

音声 + テキスト

tr

トルコ語

音声 + テキスト

hi

ヒンディー語

音声 + テキスト

ms

マレー語

音声 + テキスト

nl

オランダ語

音声 + テキスト

ur

ウルドゥー語

音声 + テキスト

nb

ノルウェー語 (ブークモール)

音声 + テキスト

sv

スウェーデン語

音声 + テキスト

da

デンマーク語

音声 + テキスト

he

ヘブライ語

音声 + テキスト

fi

フィンランド語

音声 + テキスト

pl

ポーランド語

音声 + テキスト

is

アイスランド語

音声 + テキスト

cs

チェコ語

音声 + テキスト

fil

フィリピン語

音声 + テキスト

fa

ペルシャ語

音声 + テキスト

yue

広東語

テキスト

el

ギリシャ語

テキスト

af

アフリカーンス語

テキスト

ast

アストゥリアス語

テキスト

be

ベラルーシ語

テキスト

bg

ブルガリア語

テキスト

bn

ベンガル語

テキスト

bs

ボスニア語

テキスト

ca

カタルーニャ語

テキスト

ceb

セブアノ語

テキスト

et

エストニア語

テキスト

gl

ガリシア語

テキスト

gu

グジャラート語

テキスト

hr

クロアチア語

テキスト

hu

ハンガリー語

テキスト

jv

ジャワ語

テキスト

kk

カザフ語

テキスト

kn

カンナダ語

テキスト

ky

キルギス語

テキスト

lv

ラトビア語

テキスト

mk

マケドニア語

テキスト

ml

マラヤーラム語

テキスト

mr

マラーティー語

テキスト

pa

パンジャブ語

テキスト

ro

ルーマニア語

テキスト

sk

スロバキア語

テキスト

sl

スロベニア語

テキスト

sw

スワヒリ語

テキスト

tg

タジク語

テキスト

az

アゼルバイジャン語

テキスト

uk

ウクライナ語

テキスト

サポート対象の音声

サポートされている音声と対応する voice パラメーターの値については、「音声リスト」をご参照ください。

よくある質問

接続したまま発話しなくても課金されますか?

接続を維持するだけでは課金されません。送信した無音が音声入力として計上されるかどうかは、使用するモードによって異なります。
  • サーバー側の音声検出:除外された無音は音声入力に計上されません。
  • Manual モード:クライアントが明示的にコミットした無音は、音声入力に計上されます。
音声入力トークン数は、response.done の response → usage → input_tokens_details → audio_tokens で確認できます。料金は入力・出力トークン数に基づきます。単価と計算方法は「課金」をご参照ください。

Gummy から LiveTranslate に移行するにはどうすればよいですか?

gummy-realtime-v1 と qwen3.8-livetranslate-flash-realtime ではプロトコルが異なります。モデル名に加え、接続、音声の送信、翻訳結果の受信、セッション終了の処理を変更します。 Python SDK で英語字幕を出力する例です。16 kHz、モノラル、16 ビット PCM の録音はそのまま使用し、次の 4 か所を変更します。

手順

Gummy

LiveTranslate

接続と設定

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"})

接続後にセッションを設定し、session.updated を受信してから音声を送信します。

音声の送信

send_audio_frame(data)

session.append_audio(data)

字幕の表示

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

translation_result.get_translation("en").text

session.events()

response.text.delta

各イベントの delta を字幕に追記します。

セッションの終了

stop()

session.end_session()

字幕の受信を続け、session.finished の受信後に接続を閉じます。

DashScope 2.0.2 をインストールし、北京リージョンの API キーを DASHSCOPE_API_KEY に、ワークスペース ID を DASHSCOPE_WORKSPACE に設定します。コードを subtitles.py として保存し、16 kHz、モノラル、16 ビット PCM の WAV ファイルを用意して python subtitles.py input.wav を実行します。
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])
WebSocket を直接使用する場合は、次の 3 点を変更します。完全な例はクイックスタートを参照してください。
  • 接続先:/api-ws/v1/inference を /api-ws/v1/realtime?model=qwen3.8-livetranslate-flash-realtime に変更します。
  • 音声形式:バイナリフレームを JSON イベント input_audio_buffer.append に変更し、Base64 エンコードした PCM を audio フィールドに格納します。
  • 翻訳イベント:result-generated を response.text.delta に変更し、delta を順に追記します。音声の送信後に session.finish を送信し、session.finished を受信してから接続を閉じます。

切断後に翻訳を再開するには?

no semantic result after merged audio exceeded 60s を受信して WebSocket 接続が閉じた場合は、新しいセッションで翻訳を再開します。
  1. 古い接続への音声送信を停止します。
  2. 再接続し、session.update を送信して翻訳先言語、出力モダリティなどを設定します。
  3. session.updated を受信してから、音声送信を再開します。
パラメーターエラーが発生しても接続が開いている場合は、リクエストを修正して同じ接続を使い続けます。dashscope.Client() を使用する場合は、イベント受信も再開します。