Skip to main content

Qwen-Omni-Realtime

Qwen-Omni-Realtime は、ストリーミング音声および画像入力 (ビデオフレームを含む) を処理し、テキストと音声の応答をリアルタイムで生成します。

サポートされているリージョン: シンガポール、中国 (北京)。各リージョンには、独自の API キー が必要です。

使用方法

1. 接続の確立

Qwen-Omni-Realtime は WebSocket、WebRTC、AOQ によるアクセスをサポートします。WebSocket は、サーバー側の統合と迅速な導入に適しています。WebRTC は、ブラウザーでの低レイテンシー音声シナリオに適しており、UDP で音声を直接転送し、エコーキャンセルとノイズ抑制を備えています。安定したレイテンシー、弱いネットワークでの対話性能、リアルタイム全二重通信のノイズ抑制とエコーキャンセルを重視するクライアント統合では、AOQ を優先的に検討してください。プロトコルの比較と選択は、API リファレンスをご覧ください。 AppServer から HTTP リクエストを送信して、AOQ の接続パラメーターを取得します。詳しくは、認証と接続認証情報をご覧ください。
  • WebSocket
  • WebRTC
  • ネイティブ WebSocket
  • DashScope Python SDK
  • DashScope Java SDK
接続パラメーター:
パラメーター説明
エンドポイント中国 (北京) リージョン: wss://WorkspaceId.cn-beijing.maas.aliyuncs.com/api-ws/v1/realtimeシンガポールリージョン: wss://WorkspaceId.ap-southeast-1.maas.aliyuncs.com/api-ws/v1/realtimeWorkspaceId を実際の ワークスペース ID に置き換えてください。
クエリパラメーターmodel クエリパラメーターを使用してモデルを指定します。例: ?model=qwen3.5-omni-plus-realtime
リクエストヘッダー認証には Bearer トークンを使用します: Authorization: Bearer DASHSCOPE_API_KEY
DASHSCOPE_API_KEY は Model Studio の API キー です。
# pip install websocket-client
import json
import websocket
import os

API_KEY=os.getenv("DASHSCOPE_API_KEY")
# シンガポールリージョン。サンプルに実際のワークスペース ID を入力してください。URL はリージョンによって異なります。
API_URL = "wss://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/api-ws/v1/realtime?model=qwen3.5-omni-plus-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. セッションの設定

session.update クライアントイベントを送信します:
{
    // クライアントが生成したイベント ID。
    "event_id": "event_ToPZqeobitzUJnt3QqtWg",
    // イベントタイプ。「session.update」である必要があります。
    "type": "session.update",
    // セッション設定。
    "session": {
        // 出力モダリティ。テキストのみの出力の場合は ["text"] に、テキストと音声の両方を出力する場合は ["text", "audio"] に設定します。
        "modalities": [
            "text",
            "audio"
        ],
        // 音声出力の声。
        "voice": "Ethan",
        // 入力音声フォーマット。「pcm」のみがサポートされています。入力音声は、16 kHz のサンプルレートの PCM 音声ストリームである必要があります。
        "input_audio_format": "pcm",
        // 出力音声フォーマット。「pcm」のみがサポートされています。出力音声は、24 kHz のサンプルレートの PCM 音声ストリームです。
        "output_audio_format": "pcm",
        // モデルの目標や役割を定義するためのシステム命令。
        "instructions": "あなたは五つ星ホテルの AI カスタマーサービスエージェントです。客室タイプ、施設、料金、予約ポリシーに関するお客様からのお問い合わせに、正確かつフレンドリーに回答してください。常にプロフェッショナルで親切な態度で対応してください。未確認の情報やホテルのサービスの範囲外の情報は提供しないでください。",
        // サーバー側の音声区間検出 (VAD) を有効にします。有効にすると、サーバーは自動的に発話の開始と終了を検出します。
        // null の場合、クライアントはモデルの応答をトリガーするタイミングを制御する必要があります。
        "turn_detection": {
            // VAD のタイプ。有効な値は "server_vad" と "semantic_vad" です。qwen3.5-omni-realtime シリーズのモデルには "semantic_vad" を推奨します。
            "type": "semantic_vad",
            // VAD 検出のしきい値。ノイズの多い環境ではこの値を大きくし、静かな環境では小さくすることを推奨します。
            "threshold": 0.5,
            // 発話の終了を示す無音の継続時間 (ミリ秒)。この時間を超えると、モデルは応答をトリガーします。
            "silence_duration_ms": 800
        }
    }
}

3. 音声と画像の入力

音声入力は必須ですが、画像入力はオプションです。入力方法はプロトコルによって異なります。
  • WebSocket
  • WebRTC
input_audio_buffer.append および input_image_buffer.append イベントを使用して、Base64 エンコードされた音声および画像データをサーバーバッファーに送信します。
画像は、ローカルファイルまたはリアルタイムのビデオストリームキャプチャから取得できます。
サーバー側の VAD が有効になっている場合、サーバーは自動的にデータを送信し、発話の終了時に応答をトリガーします。VAD が無効 (手動モード) の場合、送信後に input_audio_buffer.commit イベントを呼び出してデータを送信します。

4. モデル応答の受信

応答形式は、設定された出力モダリティによって異なります。
  • WebSocket
  • WebRTC

モデルの選択

Qwen3.5-Omni-Realtime は、Qwen3-Omni-Flash-Realtime に比べて以下の点で改善されています:
  • インテリジェンスレベル Qwen3.5-Plus と同等です。
  • Web 検索 内蔵の Web 検索機能により、モデルは自律的に検索してリアルタイムの質問に答えます。詳細については、「Web 検索」をご参照ください。
  • ツール呼び出し 関数呼び出しにより、モデルは自律的に外部ツールを呼び出します。詳細については、「Qwen-Omni-Realtime シリーズ」をご参照ください。
  • セマンティック割り込み 会話の意図を識別し、相槌やバックグラウンドノイズによる中断を防ぎます。
  • 音声コントロール 「もっと速く話して」「もっと大きな声で」「楽しいトーンで」などの音声コマンドで、音量、話す速度、感情をコントロールします。
  • サポートされている言語 113 の言語と方言の音声認識と、36 の言語と方言の音声生成をサポートします。
  • サポートされている音声 47 の多言語音声と 8 つの方言音声を含む 55 の音声をサポートします。完全なリストについては、「音声リスト」をご参照ください。
  • 音声クローン リアルタイムの会話にカスタムのクローン音声を使用します (Qwen3.5-omni-plus-realtime および Qwen3.5-omni-flash-realtime)。詳細については、「音声クローン」をご参照ください。
モデル名、コンテキスト、価格、スナップショットバージョンについては、Model Studio コンソールをご確認ください。同時実行数のレート制限については、「レート制限」をご参照ください。

制限事項

  • Web 検索とツール呼び出しは相互排他的です。
  • 1 つの WebSocket セッションは最大 120 分まで継続できます。この制限に達すると、接続は自動的に閉じられます。
  • モデルは、以下のターン数と持続時間の制限まで会話履歴を保持します。超過した場合、最も古い履歴が破棄されます。最大持続時間は、コンテキストに保持される累積的な音声またはビデオ (画像フレーム) の持続時間です。
    ビデオは抽出されたフレームとして入力されます (推奨:1 fps)。ビデオの最大持続時間は、保持される累積フレーム持続時間です。たとえば、240 秒は、最後の 240 秒間のフレームのみが保持されることを意味します。

    モデル

    音声の最大ターン数

    ビデオの最大ターン数

    音声の最大持続時間

    ビデオの最大持続時間

    qwen3.5-omni-plus-realtime

    100 ターン

    50 ターン

    600 秒

    240 秒

    qwen3.5-omni-flash-realtime

    80 ターン

    50 ターン

    480 秒

    120 秒

クイックスタート

API キーを取得し、環境変数として設定します。 プログラミング言語を選択し、手順に従ってリアルタイムチャットを開始します。
  • WebSocket
  • WebRTC
  • DashScope Python SDK
  • DashScope Java SDK
  • WebSocket (Python)
  • 実行環境
Python 3.10 以降がインストールされていることを確認してください。お使いのオペレーティングシステムに PyAudio をインストールします。
  • macOS
  • Debian/Ubuntu
  • CentOS
  • Windows
brew install portaudio && pip install pyaudio
その他の依存関係をインストールします:
pip install websocket-client dashscope
  • 対話モード
    • VAD モード (音声区間検出、発話の開始と終了を自動的に検出) サーバーは、ユーザーの発話の終了を検出した後に応答します。
    • 手動モード (押して話す、離して送信) クライアントが発話の開始と終了を制御します。発話後、アプリケーションはサーバーに通知する必要があります。
    • VAD モード
    • 手動モード
    vad_dash.py という名前の Python ファイルを作成し、次のコードをファイルにコピーします:
    # 依存関係:dashscope >= 2.0.1, pyaudio
    import os
    import base64
    import time
    
    import pyaudio
    from concurrent.futures import ThreadPoolExecutor
    
    import dashscope
    
    # 以下はシンガポール (ap-southeast-1) リージョンの設定です。サンプルに実際のワークスペース ID を入力してください。region の値はリージョンによって異なります。
    client = dashscope.Client(
        # 環境変数を設定していない場合は、次の行を Model Studio API キーに置き換えてください: api_key="sk-xxx"
        # シンガポールと中国 (北京) リージョンの API キーは異なります。API キーを取得するには、https://www.alibabacloud.com/help/model-studio/get-api-key をご参照ください。
        api_key=os.getenv("DASHSCOPE_API_KEY"),
        workspace="{WorkspaceId}",
        region="ap-southeast-1",
    )
    # 音声を指定します。
    voice = 'Ethan'
    # モデルを指定します。
    model = 'qwen3.5-omni-plus-realtime'
    # モデルの役割を指定します。
    instructions = "あなたはシャオユンという名のパーソナルアシスタントです。ユーザーの質問に、ユーモアとウィットに富んだ方法で答えてください。"
    
    # 1. オーディオデバイスと出力ストリームを初期化します。
    pya = pyaudio.PyAudio()
    out = pya.open(format=pyaudio.paInt16, channels=1, rate=24000, output=True)
    
    # 2. 受信スレッド:サーバーイベントを反復処理し、音声を再生してテキストを印刷します。
    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':
                # ストリーミングプレビュー:text は確定したプレフィックス、stash は未確定のサフィックスです。
                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']}")
    
    # 3. セッションを作成し(with コンテキストに入ると自動的に接続が確立されます)、設定します。
    with client.audio.realtime.connect(model=model) as session:
        session.update_session(
            output_modalities=['audio', 'text'],
            voice=voice,
            instructions=instructions,
        )
        # 4. 音声入力ストリームを初期化します。
        mic = pya.open(format=pyaudio.paInt16, channels=1, rate=16000, input=True)
        # 5. 音声入力を処理するメインループ。
        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:
            # リソースをクリーンアップします。
            session.close()
            mic.close()
            out.close()
            pya.terminate()
            print("\nConversation ended")
    
    vad_dash.py を実行して、マイクを通じてリアルタイムの会話を開始します。システムは発話を検出し、音声をサーバーにストリーミングします。

対話フロー

  • VAD モード
  • 手動モード
session.update イベントの session.turn_detection.type を "server_vad" または "semantic_vad" に設定して、VAD モードを有効化します。このモードは音声通話に適しています。WebSocket と WebRTC はどちらも VAD モードをサポートしますが、音声と画像の転送方法、および一部のサーバーイベントが異なります。
WebRTC は VAD モードのみをサポートし、Manual モードはサポートしません。音声は RTP で直接転送するため、input_audio_buffer.append イベントを送信する必要はありません。画像は動画トラックで転送し、input_image_buffer.append イベントはサポートしません。制御命令とサーバーイベントは DataChannel で転送します。詳しくは、サーバーイベントをご覧ください。
対話フローは次のとおりです:
  1. クライアントは音声データを送信します。WebSocket は input_audio_buffer.append イベント経由で送信し、WebRTC は手動でイベントを送信せずに音声トラック (RTP) 経由で自動的に送信します。
  2. サーバーは発話の開始を検出し、DataChannel (WebRTC) または WebSocket 経由で input_audio_buffer.speech_started イベントを送信します。
  3. サーバーは発話の終了を検出し、input_audio_buffer.speech_stopped イベントを送信します。
  4. サーバーは音声バッファをコミットし、input_audio_buffer.committed イベントを送信します。
  5. サーバーは応答の生成を開始し、conversation.item.created などのイベントを送信します。音声応答は、WebSocket の response.audio.delta イベントを介して増分的に返されるか、WebRTC の音声トラック (RTP) を介して直接送信されます。
  6. 応答中、サーバーは response.audio_transcript.delta イベントを介して増分的なテキスト文字起こしを返し、応答が完了すると response.done イベントを送信します。
ライフサイクルクライアントイベントサーバーイベント
セッションの初期化session.update
セッション設定
session.created
セッションが作成されました。
session.updated
セッション設定が更新されました。
ユーザーの音声入力input_audio_buffer.append
WebSocket:このイベントを介してバッファに音声を追加します。
input_image_buffer.append
WebSocket:このイベントを介してバッファに画像を追加します。
WebRTC:音声は RTP 音声トラックを介して自動的に送信され、画像はビデオトラックを介して送信されます。これらのイベントは不要です。
input_audio_buffer.speech_started
発話開始が検出されました。
input_audio_buffer.speech_stopped
発話終了が検出されました。
input_audio_buffer.committed
音声バッファがコミットされました。
サーバーの音声出力なしresponse.created
応答生成が開始されました。
response.output_item.added
応答に新しい出力項目が追加されました。
conversation.item.created
会話項目が作成されました。
response.content_part.added
アシスタントメッセージに新しいコンテンツ部分が追加されました。
response.audio_transcript.delta
増分的に生成された文字起こしテキスト。
response.audio.delta
WebSocket:モデルから増分的に生成された音声がこのイベントを介して返されます。WebRTC:音声は RTP 音声トラックを介して直接送信され、このイベントは返されません。
response.audio_transcript.done
テキストの文字起こしが完了しました。
response.audio.done
音声生成が完了しました。
response.content_part.done
アシスタントのテキストまたは音声コンテンツのストリーミングが完了しました。
response.output_item.done
アシスタントの出力項目全体のストリーミングが完了しました。
response.done
応答が完了しました。
conversation.item.input_audio_transcription.completed
ユーザーの音声入力の文字起こしが完了しました (session.update で input_audio_transcription を有効にする必要があります)。

Web 検索

Web 検索により、モデルはリアルタイムデータを使用して、株価や天気などのタイムリーな情報に関する質問に答えることができます。モデルは検索が必要かどうかを自動的に判断します。
qwen3.5-omni-plus-realtime のみが Web 検索をサポートしています。デフォルトでは無効になっており、session.update で有効にします。
課金については、課金ルール内の agent

Web 検索の有効化

session.update イベントに次のパラメーターを追加します:
  • enable_search:Web 検索機能を有効にするには true に設定します。
  • search_options.enable_source:応答に検索結果のソースを含めるには true に設定します。
その他のパラメーターについては、「session.update」をご参照ください。

応答形式

Web 検索が有効な場合、response.done の usage オブジェクトには、検索の計測情報を含む plugins フィールドが含まれます:
{
    "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"
            }
        }
    }
}

コード例

リアルタイム会話で Web 検索を有効にします:
  • DashScope Python SDK
  • DashScope Java SDK
  • WebSocket (Python)
update_session 呼び出しで enable_search および search_options パラメーターを渡します:
import os
import base64
import time

import pyaudio
from concurrent.futures import ThreadPoolExecutor

import dashscope

# 以下はシンガポール (ap-southeast-1) リージョンの設定です。サンプルに実際のワークスペース ID を入力してください。region の値はリージョンによって異なります。
client = dashscope.Client(
    # 環境変数を設定していない場合は、次の行を Model Studio API キーに置き換えてください: api_key="sk-xxx"
    # シンガポールと中国 (北京) リージョンの API キーは異なります。API キーを取得するには、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.5-omni-plus-realtime'
voice = 'Tina'

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

# 受信スレッド:サーバーイベントを反復処理します
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="あなたはシャオユンという名のパーソナルアシスタントです。",
        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.")

API リファレンス

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

課金とレート制限

課金

課金はトークンベースで、モダリティ (音声、画像、テキスト) ごとに計測されます。価格については Model Studio コンソールをご確認ください。
マルチターンリアルタイム会話では、モデルが応答を生成するたびに、コンテキストウィンドウ内のすべての過去の会話コンテンツ (前のターンの音声、画像、テキストを含む) を、現在のターンの新しい入力とともに、入力トークンとして処理します。その結果、入力トークンは現在のターンの新しい入力のみでカウントされるのではなく、ターンごとに蓄積されます。たとえば、10 秒の音声入力が 70 トークン (Qwen3.5-Omni-Realtime) に変換され、その音声がターン 3 でまだコンテキストウィンドウ内にある場合、それはターン 3 の入力トークンとしてカウントされます。実際に請求される入力トークン = コンテキストウィンドウ内のすべての過去のターンからのトークン + 現在のターンの新しい入力からのトークン。
  • 音声
  • 画像
  • Qwen3.5-Omni-Realtime:
    • 入力音声: 合計トークン = 音声の持続時間 (秒) * 7
    • 出力音声: 合計トークン = 音声の持続時間 (秒) * 12.5
  • qwen3-omni-flash-realtime-2025-09-15: 入力および出力音声は同じ数式を使用します: 合計トークン = 音声の持続時間 (秒) * 12.5 1 秒未満の音声持続時間は 1 秒として課金されます。

レート制限

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

よくある質問

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

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

エラーコード

モデルの呼び出しに失敗し、エラーメッセージが返された場合は、「エラーコード」を参照して解決してください。

音声リスト

Qwen-Omni-Realtime モデルで利用可能な音声のリストについては、「音声」をご参照ください。