すべてのプロダクト
Search
ドキュメントセンター

Alibaba Cloud Model Studio:CosyVoice Python SDK

最終更新日:Sep 28, 2026

DashScope Python SDK を使用して、非ストリーミング、一方向ストリーミング、または双方向ストリーミングモードで、CosyVoice のリアルタイム音声合成をアプリケーションに統合します。

サービスエンドポイント

SDK は、デフォルトで北京リージョンのエンドポイントを使用します。別のリージョンに切り替えるには、初期化の前に dashscope.base_websocket_api_url を変更します。

Singapore

wss://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/api-ws/v1/inference

{WorkspaceId} を実際のワークスペース ID に置き換えます。

China (Beijing)

wss://{WorkspaceId}.cn-beijing.maas.aliyuncs.com/api-ws/v1/inference

{WorkspaceId} を実際のワークスペース ID に置き換えます。

Singapore リージョンへの切り替え:

import dashscope

# コードの先頭で設定します
dashscope.base_websocket_api_url = 'wss://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/api-ws/v1/inference'

重要Alibaba Cloud Model Studio は、China (Beijing) および Singapore リージョン向けに、ワークスペース専用ドメインをリリースしました。新しい専用ドメインは、推論リクエストに対して優れたパフォーマンスと高い安定性を提供します。新しいドメインへの移行を推奨します:

  • China (Beijing): dashscope.aliyuncs.com から {WorkspaceId}.cn-beijing.maas.aliyuncs.com へ
  • Singapore: dashscope-intl.aliyuncs.com から {WorkspaceId}.ap-southeast-1.maas.aliyuncs.com へ

SpeechSynthesizer

パッケージパス: dashscope.audio.tts_v2.SpeechSynthesizer

コンストラクター

SpeechSynthesizer(
    model: str,
    voice: str,
    format: AudioFormat = AudioFormat.MP3_22050HZ_MONO_256KBPS,
    volume: int = 50,
    speech_rate: float = 1.0,
    pitch_rate: float = 1.0,
    callback: ResultCallback = None)

call()

メソッドシグネチャ:

def call(self, text: str) -> bytes

パラメーター:

パラメーター型必須説明
textstrはい合成する全文テキスト。最大長: 20,000 文字。

戻り値: 完全な音声データを含む bytes。

説明: このメソッドは、コンストラクターで callback パラメーターが設定されているかどうかによって、動作が異なります。

streaming_call() - ストリーミング

メソッドシグネチャ:

def streaming_call(self, text: str) -> None

パラメーター:

パラメーター型必須説明
textstrはい合成するテキストセグメント。このメソッドを複数回呼び出してテキストを追加します。1 回の呼び出しあたりの最大長: 20,000 文字。累計の最大長: 200,000 文字。

説明: この双方向ストリーミングコールは、テキストをセグメント単位で受け付け、リアルタイムでコールバックを通じて合成された音声を配信します。テキストが段階的に生成される大規模言語モデルとの統合に最適です。すべてのテキストを送信した後、streaming_complete() を呼び出してください。

streaming_complete() - ストリーミングの終了

メソッドシグネチャ:

def streaming_complete(self) -> None

説明: すべてのテキストが送信されたことをサーバーに通知します。残りのテキストが合成され、すべての音声データが返されるまで、現在のスレッドをブロックします。このメソッドの呼び出しに失敗すると、末尾のテキストが音声に変換されない場合があります。

streaming_cancel() - ストリーミング合成のキャンセル

メソッドシグネチャ:

def streaming_cancel(self, complete_timeout_millis: int = 10000) -> None

パラメーター:

パラメーター型必須説明
complete_timeout_millisintいいえサーバーがタスク終了イベントを返すのを待つタイムアウト時間 (ミリ秒)。デフォルト値: 10000。

説明: 現在のストリーミング音声合成のターンをキャンセルします。このメソッドを呼び出すと、SDK は現在のタスクをただちに終了します。SpeechSynthesizer インスタンスを再初期化することなく、同じ接続で新しい合成タスクを開始できます。

重要バージョン要件: この機能には Python SDK 1.26.4 以降が必要です。

重要モデルの制限:

  • 中国 (北京):CosyVoice モデルは v2 以降が必要です。
  • シンガポール:CosyVoice モデルはこの機能をサポートしていません。

get_last_request_id() - リクエスト ID の取得

メソッドシグネチャ:

def get_last_request_id(self) -> str

戻り値: 直近のリクエストのリクエスト ID を含む str。トラブルシューティングやトレースに使用します。

get_first_package_delay() - 初回パケットレイテンシーの取得

メソッドシグネチャ:

def get_first_package_delay(self) -> int

戻り値: テキストを送信してから最初のオーディオチャンクを受信するまでの遅延 (ミリ秒) を表す int 値。 合成完了後に呼び出します。

get_response() - レスポンスメッセージの取得

メソッドシグネチャ:

def get_response(self) -> str

戻り値: str。リクエストステータスと出力情報を含む、最新の合成タスクからの JSON 形式のレスポンスメッセージ。

コンストラクターパラメーター

以下のパラメーターは SpeechSynthesizer コンストラクターで設定し、モデル、音声、フォーマット、および音声特性を制御します。

パラメーター型必須説明
modelstrはいモデル名。
voicestrはい音声合成に使用する音声。
  • システム音声: 「CosyVoice 音声リスト」をご参照ください。
  • クローン音声: 音声クローニングによって作成されたカスタム音声
  • カスタム音声: 音声デザインによって作成されたカスタム音声
formatenumいいえ音声のエンコーディング形式とサンプリングレート。

デフォルト: AudioFormat.MP3_22050HZ_MONO_256KBPS。

AudioFormat enum は dashscope.audio.tts_v2 にあり、MP3、WAV、PCM などのフォーマットをサポートします。

volumeintいいえ音量レベル。

デフォルト値: 50。

有効な値: [0, 100]。

speech_ratefloatいいえ話速。

デフォルト値: 1.0。

有効な値: [0.5, 2.0]。

pitch_ratefloatいいえピッチ。

デフォルト値: 1.0。

有効な値: [0.5, 2.0]。

bit_rateintいいえkbps 単位のオーディオビットレート。オーディオ形式が mp3 または opus の場合は、bit_rate を使用してビットレートを調整します。

デフォルト値: 32。

有効な値: [6, 510]。

additional_params パラメーター経由で bit_rate を設定します:

synthesizer = SpeechSynthesizer(
          model="cosyvoice-v3-plus",
          voice="longanyang",
          additional_params={"bit_rate": 128}
      )
word_timestamp_enabledboolいいえ単語レベルのタイムスタンプを有効にするかどうかを指定します。

デフォルト値: false。

ストリーミング出力モードでのみ使用可能です。サポートされている音声は、cosyvoice-v3.5-plus、cosyvoice-v3.5-flash、cosyvoice-v3-flash、cosyvoice-v3-plus、cosyvoice-v2 のクローン音声、およびCosyVoice 音声リストでサポート対象として記載されているシステム音声です。他のモデルのクローン音声はこの機能をサポートしていません。

additional_params パラメーターを使用して word_timestamp_enabled を設定します:

synthesizer = SpeechSynthesizer(
          model="cosyvoice-v3-flash",
          voice="your_voice",  # 単語レベルのタイムスタンプをサポートするシステム音声またはクローン音声
          additional_params={"word_timestamp_enabled": True}
      )
seedintいいえ合成出力のバリエーションを制御するためのランダムシード。モデルのバージョン、テキスト、音声、およびその他のパラメーターが変更されない場合、同じシードを使用すると同一の結果が生成されます。

デフォルト値: 0。

有効な値: [0, 65535]。

language_hintslist[str]いいえ

重要

  • このパラメーターは配列ですが、現在のバージョンでは最初の要素のみが処理されます。単一の値を渡してください。
  • このパラメーターは音声合成のターゲット言語を指定します。これは、音声クローニングで使用される音声サンプルの言語とは無関係です。クローニングタスクのソース言語を設定するには、音声クローニング API リファレンスをご参照ください。

出力品質を向上させるために、音声合成のターゲット言語を指定します。

数字の発音、略語の展開、記号の読み上げ、または少数言語の合成が期待どおりでない場合に、このパラメーターを使用します。例:

  • 予期しない数字の発音:「hello, this is 110」が、期待される中国語の発音ではなく「hello, this is one zero」と読まれる場合
  • 不正確な記号の発音:「@」が「at」ではなく、中国語の同等語で読まれる場合
  • 少数言語の合成品質が低く、不自然な結果になる場合

有効な値

  • zh:中国語
  • en:英語
  • fr:フランス語
  • de:ドイツ語
  • ja:日本語
  • ko:韓国語
  • ru:ロシア語
  • pt:ポルトガル語
  • th:タイ語
  • id:インドネシア語
  • vi:ベトナム語
  • es:スペイン語
  • it:イタリア語
  • ms:マレーシア語
  • fil:フィリピン語
  • ar:アラビア語
instructionstrいいえ方言、感情、話し方などの合成特性を制御します。

使用方法の詳細については、「Instruction control」をご参照ください。

enable_aigc_tagboolいいえ生成された音声に AIGC ウォーターマークを埋め込むかどうかを指定します。true に設定すると、サポートされている形式 (wav/mp3/opus) の音声ファイルにウォーターマークが埋め込まれます。

デフォルト値: false。

注記cosyvoice-v3-flash、cosyvoice-v3-plus、cosyvoice-v2 のみがこの機能をサポートしています。

enable_aigc_tag、aigc_propagator、および aigc_propagate_id は、additional_params パラメーターを使用して設定します:

synthesizer = SpeechSynthesizer(
          model="cosyvoice-v3-plus",
          voice="longanyang",
          additional_params={
              "enable_aigc_tag": True,
              "aigc_propagator": "your_propagator",
              "aigc_propagate_id": "your_propagate_id"
          }
      )
aigc_propagatorstrいいえAIGC 透かしの ContentPropagator フィールドを設定してコンテンツプロパゲーターを識別するもので、enable_aigc_tag が true の場合にのみ有効になります。

デフォルト値: Alibaba Cloud UID。

注記cosyvoice-v3-flash、cosyvoice-v3-plus、cosyvoice-v2 のみがこの機能をサポートしています。

additional_params パラメーターを使用して設定します。enable_aigc_tag の例をご参照ください。

aigc_propagate_idstrいいえAIGC ウォーターマークの PropagateID フィールドを設定して、特定の伝播アクションを一意に識別します。enable_aigc_tag が true の場合にのみ有効になります。

デフォルト値: 現在の音声合成リクエストのリクエスト ID。

注記cosyvoice-v3-flash、cosyvoice-v3-plus、cosyvoice-v2 のみがこの機能をサポートしています。

additional_params パラメーターで設定します。enable_aigc_tag の例を参照してください。

hot_fixdictいいえ合成前に適用される発音補正とテキスト置換を設定します。

注記この機能は cosyvoice-v2 ではサポートされていません。

パラメーター:

  • pronunciation:カスタム発音。不正確なデフォルトの発音を補正するために、単語のピンイン注釈を指定します。
  • replace:テキスト置換。合成前に指定された単語をターゲットテキストに置き換えます。置き換えられたテキストが実際の合成入力として使用されます。

例:

synthesizer = SpeechSynthesizer(
    model="cosyvoice-v3.5-plus",
    voice="cosyvoice-v3.5-plus-vd-announcer-xxxxxx", # 音声
    hot_fix={
        "pronunciation": [{"weather": "tian1 qi4"}],
        "replace": [{"today": "gold day"}]
    }
)
enable_markdown_filterboolいいえ

注記cosyvoice-v3-flash のクローン音声のみがこの機能をサポートしています。

Markdown フィルタリングを有効にするかどうかを指定します。有効にすると、システムは合成前に入力テキストから Markdown マークアップ記号を自動的に除去し、それらが読み上げられるのを防ぎます。

デフォルト値: false。

有効な値:

  • true: Markdown フィルタリングを有効にする
  • false: Markdown フィルタリングを無効にする

enable_markdown_filter を additional_params パラメーターを使用して設定します:

synthesizer = SpeechSynthesizer(
          model="cosyvoice-v3-flash",
          voice="your_voice",  # cosyvoice-v3-flash のクローン音声
          additional_params={"enable_markdown_filter": True}
      )
callbackResultCallbackいいえ合成された音声とイベント通知を非同期で受信するためのコールバックインスタンスです。設定されている場合、call() はストリーミングモードで実行され、on_data コールバックを通じて音声を配信します。設定されていない場合、call() は非ストリーミングモードで実行され、完全な音声を bytes として返します。

ResultCallback

パッケージパス: dashscope.audio.tts_v2.ResultCallback

on_open() - 接続確立

メソッドシグネチャ:

def on_open(self) -> None

トリガー条件: WebSocket 接続が正常に確立されたときにトリガーされます。このコールバックを使用して、オーディオ出力ストリームの初期化やファイルリソースのオープンをします。

on_event() - サーバー応答の受信

メソッドシグネチャ:

def on_event(self, message: str) -> None

パラメーター:

パラメーター型必須説明
messagestrはいheader (リクエスト情報) と payload (出力情報) を含む JSON 形式のサーバーレスポンスイベントです。payload.output フィールドには、イベントタイプ、元のテキスト、およびその他の詳細が含まれます。on_event メッセージの出力フィールドをご参照ください。

トリガーされるタイミング: サーバーからの応答を受信したとき。メッセージは、合成イベントの出力 (イベントタイプ、元のテキスト、文の情報) を含む JSON 文字列です。 json.loads(message)でパースし、 payload.outputにアクセスして詳細を確認します。

on_complete() - 合成完了

メソッドシグネチャ:

def on_complete(self) -> None

トリガー条件: すべてのテキストが合成され、すべての音声データが on_data を通じて配信されたときにトリガーされます。このコールバックを使用して get_first_package_delay() を呼び出し、パフォーマンスメトリクスを取得します。

on_data() - 音声データの受信

メソッドシグネチャ:

def on_data(self, data: bytes) -> None

パラメーター:

パラメーター型必須説明
databytesはいコンストラクターの format パラメーターで指定されたフォーマットの音声データチャンクです。

トリガー条件: 音声データチャンクを受信したときにトリガーされます。このコールバックは合成中に複数回呼び出されます。これを使用して、データをファイルに書き込んだり、再生デバイスに供給したりします。

on_error() - エラー発生

メソッドシグネチャ:

def on_error(self, message: str) -> None

パラメーター:

パラメーター型必須説明
messagestrはいエラーコードと詳細な理由を含むエラーの説明です。

トリガー条件: 合成中にエラーが発生したときにトリガーされます。このコールバックが呼び出されると、接続は自動的に閉じられます。トラブルシューティングのためにエラーをログに記録してください。

on_close() - 接続クローズ

メソッドシグネチャ:

def on_close(self) -> None

トリガー条件: WebSocket 接続が (正常に、またはエラーにより) 閉じられたときにトリガーされます。このコールバックを使用して、音声再生デバイスなどのリソースを解放します。

on_event メッセージの output フィールド

on_event コールバックが受信する JSON メッセージには、合成イベント情報を含む payload.output フィールドが含まれています。このフィールドを使用して、合成の進捗を追跡し、文ごとの詳細を取得します。 output フィールドの構造は次のとおりです。

フィールド型説明
typestrイベントタイプ。値は、 sentence-begin (文の合成開始)、 sentence-synthesis (文の合成進行中)、または sentence-end (文の合成完了) のいずれかです。
original_textstr現在の文の元のテキスト。 sentence-begin および sentence-end イベントで返されます。
sentencedict文情報。 index (文のシーケンス番号) と words (単語リスト。 word_timestamp_enabled が有効な場合にタイムスタンプ情報を含む) が含まれます。
メッセージ例
{
  "header": {
    "task_id": "xxx",
    "event": "result-generated",
    "attributes": {}
  },
  "payload": {
    "output": {
      "type": "sentence-begin",
      "original_text": "How is the weather today?",
      "sentence": {
        "index": 0,
        "words": []
      }
    }
  }
}
解析例
import json

def on_event(self, message):
    data = json.loads(message)
    output = data.get('payload', {}).get('output', {})
    event_type = output.get('type', '')
    original_text = output.get('original_text', '')
    if event_type:
        print(f'Event type: {event_type}, Original text: {original_text}')

コード例

SDK は、次の合成モードをサポートしています:

  • ノンストリーミング: 完全なテキストを一度に送信し、完全な音声を直接返すブロッキングコールです。短いテキストの音声合成に最適です。
  • 単方向ストリーミング: 完全なテキストを一度に送信し、コールバック関数を介して音声データ (チャンク単位) を配信するノンブロッキングコールです。低レイテンシーが求められる短いテキストのシナリオに最適です。
  • 双方向ストリーミング: テキストを複数のセグメントで送信し、段階的に合成された音声をリアルタイムでコールバック関数を介して配信するノンブロッキングコールです。低レイテンシーが求められる長いテキストのシナリオに最適です。

ノンストリーミング

image

1 回の呼び出しで送信されるテキストは 20,000 文字を超えてはなりません。この制限を超えるとエラーが発生します。

重要各 call の前に SpeechSynthesizer インスタンスを再初期化してください。

# coding=utf-8

import dashscope
from dashscope.audio.tts_v2 import *
import os

# Singapore リージョンと China (Beijing) リージョンの API キーは異なります。API キーの取得: https://www.alibabacloud.com/help/model-studio/get-api-key
# 環境変数が設定されていない場合は、次の行を実際の Model Studio API キーに置き換えてください: dashscope.api_key = "sk-xxx"
dashscope.api_key = os.environ.get('DASHSCOPE_API_KEY')

# 次の設定は Singapore リージョン用です。「{WorkspaceId}」を実際のワークスペース ID に置き換えてください。設定はリージョンによって異なります。
dashscope.base_websocket_api_url='wss://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/api-ws/v1/inference'

# モデル
model = "cosyvoice-v3-plus"
# 音声
voice = "longanyang"

# SpeechSynthesizer をインスタンス化し、コンストラクターでモデルや音声などのリクエストパラメーターを渡します
synthesizer = SpeechSynthesizer(model=model, voice=voice)
# テキストを送信して合成し、バイナリオーディオを取得します
audio = synthesizer.call("How is the weather today?")
# 最初のテキスト送信では WebSocket 接続を確立する必要があるため、初回パケットレイテンシーには接続確立時間が含まれます
print('[Metric] requestId: {}, first packet latency: {} ms'.format(
    synthesizer.get_last_request_id(),
    synthesizer.get_first_package_delay()))

# 音声をローカルファイルに保存します
with open('output.mp3', 'wb') as f:
    f.write(audio)

単方向ストリーミング

image

1 回の呼び出しで送信されるテキストは 20,000 文字を超えてはなりません。この制限を超えるとエラーが発生します。

重要各 call の前に SpeechSynthesizer インスタンスを再初期化してください。

# coding=utf-8

import os
import json
import dashscope
from dashscope.audio.tts_v2 import *

from datetime import datetime

def get_timestamp():
    now = datetime.now()
    formatted_timestamp = now.strftime("[%Y-%m-%d %H:%M:%S.%f]")
    return formatted_timestamp

# Singapore リージョンと China (Beijing) リージョンの API キーは異なります。API キーの取得: https://www.alibabacloud.com/help/model-studio/get-api-key
# 環境変数が設定されていない場合は、次の行を実際の Model Studio API キーに置き換えてください: dashscope.api_key = "sk-xxx"
dashscope.api_key = os.environ.get('DASHSCOPE_API_KEY')

# 次の設定は Singapore リージョン用です。「{WorkspaceId}」を実際のワークスペース ID に置き換えてください。設定はリージョンによって異なります。
dashscope.base_websocket_api_url='wss://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/api-ws/v1/inference'

# モデル
model = "cosyvoice-v3-plus"
# 音声
voice = "longanyang"

# コールバックインターフェイスを定義します
class Callback(ResultCallback):
    _player = None
    _stream = None

    def on_open(self):
        self.file = open("output.mp3", "wb")
        print("Connection established: " + get_timestamp())

    def on_complete(self):
        print("Speech synthesis completed, all results received: " + get_timestamp())
        # タスクが完了した後 (on_complete コールバックがトリガーされた後) に、get_first_package_delay を呼び出してレイテンシーを取得できます
        # 最初のテキスト送信では WebSocket 接続を確立する必要があるため、初回パケットレイテンシーには接続確立時間が含まれます
        print('[Metric] requestId: {}, first packet latency: {} ms'.format(
            synthesizer.get_last_request_id(),
            synthesizer.get_first_package_delay()))

    def on_error(self, message: str):
        print(f"Speech synthesis error: {message}")

    def on_close(self):
        print("Connection closed: " + get_timestamp())
        self.file.close()

    def on_event(self, message):
        # サーバーサイドのイベントを解析し、出力情報を取得します
        data = json.loads(message)
        output = data.get('payload', {}).get('output', {})
        event_type = output.get('type', '')
        original_text = output.get('original_text', '')
        if event_type:
            print(f"Event type: {event_type}, original text: {original_text}")

    def on_data(self, data: bytes) -> None:
        print(get_timestamp() + " Binary audio length: " + str(len(data)))
        self.file.write(data)

callback = Callback()

# SpeechSynthesizer をインスタンス化し、コンストラクターでモデルや音声などのリクエストパラメーターを渡します
synthesizer = SpeechSynthesizer(
    model=model,
    voice=voice,
    callback=callback,
)

# テキストを送信して合成し、on_data コールバックメソッドを介してリアルタイムでバイナリオーディオを取得します
synthesizer.call("How is the weather today?")

双方向ストリーミング

image

1 回の呼び出しで送信されるテキストは 20,000 文字を超えてはなりません。累積テキストは 200,000 文字を超えてはなりません。

  • ストリーミング入力中、streaming_call を複数回呼び出して、テキストセグメントを順次送信します。サーバーは受信したテキストに対して自動的に文分割を実行します:

    • 完全な文は直ちに合成されます
    • 不完全な文は完全になるまでバッファリングされます

    streaming_complete が呼び出されると、サーバーは受信した未処理のすべてのテキスト (不完全な文を含む) を強制的に合成します。

  • テキストセグメント間の間隔は 23 秒を超えてはなりません。超えた場合、「request timeout after 23 seconds」という例外が発生します。

    送信するテキストがない場合は、速やかに streaming_complete を呼び出してタスクを終了してください。

    重要常に streaming_complete を呼び出してください。呼び出さない場合、末尾のテキストが音声に変換されない可能性があります。

    サーバーは 23 秒のタイムアウトを強制します。この値はクライアント側では変更できません。

# coding=utf-8
#
# pyaudio のインストール手順:
# macOS の場合、次のコマンドを実行します:
#   brew install portaudio
#   pip install pyaudio
# Debian/Ubuntu の場合、次のコマンドを実行します:
#   sudo apt-get install python-pyaudio python3-pyaudio
#   または
#   pip install pyaudio
# CentOS の場合、次のコマンドを実行します:
#   sudo yum install -y portaudio portaudio-devel && pip install pyaudio
# Microsoft Windows の場合、次のコマンドを実行します:
#   python -m pip install pyaudio

import os
import time
import pyaudio
import json
import dashscope
from dashscope.api_entities.dashscope_response import SpeechSynthesisResponse
from dashscope.audio.tts_v2 import *

from datetime import datetime

def get_timestamp():
    now = datetime.now()
    formatted_timestamp = now.strftime("[%Y-%m-%d %H:%M:%S.%f]")
    return formatted_timestamp

# Singapore リージョンと China (Beijing) リージョンの API キーは異なります。API キーの取得: https://www.alibabacloud.com/help/model-studio/get-api-key
# 環境変数が設定されていない場合は、次の行を実際の Model Studio API キーに置き換えてください: dashscope.api_key = "sk-xxx"
dashscope.api_key = os.environ.get('DASHSCOPE_API_KEY')

# 次の設定は Singapore リージョン用です。「{WorkspaceId}」を実際のワークスペース ID に置き換えてください。設定はリージョンによって異なります。
dashscope.base_websocket_api_url='wss://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/api-ws/v1/inference'

# モデル
model = "cosyvoice-v3-plus"
# 音声
voice = "longanyang"

# コールバックインターフェイスを定義します
class Callback(ResultCallback):
    _player = None
    _stream = None

    def on_open(self):
        print("Connection established: " + get_timestamp())
        self._player = pyaudio.PyAudio()
        self._stream = self._player.open(
            format=pyaudio.paInt16, channels=1, rate=22050, output=True
        )

    def on_complete(self):
        print("Speech synthesis completed, all results received: " + get_timestamp())

    def on_error(self, message: str):
        print(f"Speech synthesis error: {message}")

    def on_close(self):
        print("Connection closed: " + get_timestamp())
        # プレーヤーを停止します
        self._stream.stop_stream()
        self._stream.close()
        self._player.terminate()

    def on_event(self, message):
        # サーバーサイドのイベントを解析し、出力情報を取得します
        data = json.loads(message)
        output = data.get('payload', {}).get('output', {})
        event_type = output.get('type', '')
        original_text = output.get('original_text', '')
        if event_type:
            print(f"Event type: {event_type}, original text: {original_text}")

    def on_data(self, data: bytes) -> None:
        print(get_timestamp() + " Binary audio length: " + str(len(data)))
        self._stream.write(data)

callback = Callback()

test_text = [
    "Streaming text-to-speech SDK,",
    "converts input text",
    "into binary audio data.",
    "Compared with non-streaming speech synthesis,",
    "streaming synthesis offers better real-time performance.",
    "Users hear near-synchronous audio output while typing,",
    "greatly improving interaction experience",
    "and reducing wait time.",
    "Ideal for large language model (LLM) integration,",
    "where text is streamed for speech synthesis.",
]

# SpeechSynthesizer をインスタンス化し、コンストラクターでモデルや音声などのリクエストパラメーターを渡します
synthesizer = SpeechSynthesizer(
    model=model,
    voice=voice,
    format=AudioFormat.PCM_22050HZ_MONO_16BIT,
    callback=callback,
)

# ストリーミング合成のためにテキストを送信します。on_data コールバックメソッドを介してリアルタイムでバイナリオーディオを取得します
for text in test_text:
    synthesizer.streaming_call(text)
    time.sleep(0.1)
# ストリーミング音声合成を終了します
synthesizer.streaming_complete()

# 最初のテキスト送信では WebSocket 接続を確立する必要があるため、初回パケットレイテンシーには接続確立時間が含まれます
print('[Metric] requestId: {}, first packet latency: {} ms'.format(
    synthesizer.get_last_request_id(),
    synthesizer.get_first_package_delay()))