DashScope Python SDK を使用して、非ストリーミング、単方向ストリーミング、または双方向ストリーミングモードで、ご利用のアプリケーションに CosyVoice のリアルタイム音声合成を統合します。
ユーザーガイド: モデルの説明および選択に関する推奨事項については、「音声合成」をご参照ください。
サービスエンドポイント
SDK はデフォルトで 中国 (北京) リージョンのエンドポイントを使用します。他のリージョンに切り替えるには、初期化前に dashscope.base_websocket_api_url を変更してください。
シンガポール
wss://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/api-ws/v1/inference
{WorkspaceId} を実際の ワークスペース ID に置き換えてください。
中国 (北京)
wss://{WorkspaceId}.cn-beijing.maas.aliyuncs.com/api-ws/v1/inference
{WorkspaceId} を実際の ワークスペース ID に置き換えてください。
シンガポールリージョンへの切り替え:
import dashscope
# コードの先頭で設定します
dashscope.base_websocket_api_url = 'wss://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/api-ws/v1/inference'
Alibaba Cloud Model Studio では、中国 (北京) リージョンおよびシンガポールリージョン向けにワークスペース固有のドメインがリリースされました。新しい専用ドメインは、推論リクエストに対して優れたパフォーマンスと高い安定性を提供します。以下の新しいドメインへの移行を推奨します。
中国 (北京):
dashscope.aliyuncs.comから{WorkspaceId}.cn-beijing.maas.aliyuncs.comへシンガポール:
dashscope-intl.aliyuncs.comから{WorkspaceId}.ap-southeast-1.maas.aliyuncs.comへ
{WorkspaceId} を実際の ワークスペース ID に置き換えてください。既存のドメインは引き続き完全に機能します。
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
パラメーター:
|
パラメーター |
型 |
必須 |
説明 |
|
text |
str |
はい |
合成する全文。最大長:20,000 文字。 |
戻り値: 完全なオーディオデータを含む bytes。
説明: このブロッキング呼び出しは、一度に完全なオーディオデータを返します。リアルタイムストリーミングが不要な短文に最適です。各呼び出しの前に SpeechSynthesizer インスタンスを再初期化してください。
streaming_call() - ストリーミング
メソッドシグネチャー:
def streaming_call(self, text: str) -> None
パラメーター:
|
パラメーター |
型 |
必須 |
説明 |
|
text |
str |
はい |
合成するテキストセグメント。複数回呼び出してテキストを追加できます。1 回の呼び出しの最大長:20,000 文字。累計最大長:200,000 文字。 |
説明: この双方向ストリーミング呼び出しは、テキストをセグメント単位で受け取り、リアルタイムでコールバックを通じて合成されたオーディオを配信します。テキストが逐次生成される大規模言語モデルとの統合に最適です。すべてのテキスト送信後は streaming_complete() を呼び出してください。
streaming_complete() - ストリーミング終了
メソッドシグネチャー:
def streaming_complete(self) -> None
説明: サーバーにすべてのテキストが送信されたことを通知します。残りのテキストが合成され、すべてのオーディオデータが返されるまで、現在のスレッドをブロックします。このメソッドを呼び出さないと、末尾のテキストが音声に変換されない可能性があります。
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
戻り値: 最新の合成タスクからの JSON 形式の応答メッセージ(リクエスト状態および出力情報含む)を含む str。
コンストラクターパラメーター
以下のパラメーターは SpeechSynthesizer コンストラクターを通じて設定され、モデル、音声、フォーマット、およびオーディオ特性を制御します。
|
パラメーター |
型 |
必須 |
説明 |
|
model |
str |
はい |
モデル名。 |
|
voice |
str |
はい |
voice 音声合成に使用する音声。
|
|
format |
enum |
いいえ |
オーディオのエンコード形式およびサンプルレート。 デフォルト: AudioFormat.MP3_22050HZ_MONO_256KBPS。 AudioFormat enum は |
|
volume |
int |
いいえ |
ボリュームレベル。 デフォルト値: 50。 有効値: [0, 100]。 |
|
speech_rate |
float |
いいえ |
話速。 デフォルト値: 1.0。 有効値: [0.5, 2.0]。 |
|
pitch_rate |
float |
いいえ |
ピッチ。 デフォルト値: 1.0。 有効値: [0.5, 2.0]。 |
|
bit_rate |
int |
いいえ |
オーディオのビットレート(kbps 単位)。オーディオ形式が opus の場合、 デフォルト値: 32。 有効値: [6, 510]。 説明
|
|
word_timestamp_enabled |
bool |
いいえ |
単語レベルのタイムスタンプを有効にするかどうかを指定します。 デフォルト値: false。 ストリーミング出力モードでのみ利用可能です。サポート対象の音声: cosyvoice-v3.5-plus、cosyvoice-v3.5-flash、cosyvoice-v3-flash、cosyvoice-v3-plus、および cosyvoice-v2 のクローン音声、および「CosyVoice 音声リスト」でサポート済みとマークされたシステム音声。その他のモデルのクローン音声はこの機能をサポートしていません。 説明
|
|
seed |
int |
いいえ |
合成出力のバリエーションを制御するための乱数シード。モデルバージョン、テキスト、音声、およびその他のパラメーターが変更されていない場合、同じシードを使用すると同一の結果が得られます。 デフォルト値: 0。 有効値: [0, 65535]。 |
|
language_hints |
list[str] |
いいえ |
重要
音声合成の対象言語を指定して出力品質を向上させます。 数字の発音、略語の展開、記号の読み上げ、または少数言語の合成が期待通りでない場合に、このパラメーターを使用します。例:
有効値:
|
|
instruction |
str |
いいえ |
方言、感情、話し方などの合成特性を制御します。 使用方法の詳細については、「命令による制御」をご参照ください。 |
|
enable_aigc_tag |
bool |
いいえ |
生成されたオーディオに AIGC ウォーターマークを埋め込むかどうかを指定します。true に設定すると、サポートされている形式(wav/mp3/opus)のオーディオファイルにウォーターマークが埋め込まれます。 デフォルト値: false。 cosyvoice-v3-flash、cosyvoice-v3-plus、および cosyvoice-v2 のみがこの機能をサポートしています。 説明
|
|
aigc_propagator |
str |
いいえ |
AIGC ウォーターマーク内の デフォルト値: Alibaba Cloud UID。 cosyvoice-v3-flash、cosyvoice-v3-plus、および cosyvoice-v2 のみがこの機能をサポートしています。
|
|
aigc_propagate_id |
str |
いいえ |
AIGC ウォーターマーク内の デフォルト値: 現在の音声合成リクエストのリクエスト ID。 cosyvoice-v3-flash、cosyvoice-v3-plus、および cosyvoice-v2 のみがこの機能をサポートしています。
|
|
hot_fix |
dict |
いいえ |
合成前の発音修正およびテキスト置換を設定します。 この機能は cosyvoice-v2 ではサポートされていません。 パラメーター:
例:
|
|
enable_markdown_filter |
bool |
いいえ |
重要
cosyvoice-v3-flash のクローン音声のみがこの機能をサポートしています。 Markdown フィルタリングを有効にするかどうかを指定します。有効にすると、合成前に入力テキストから Markdown マークアップ記号が自動的に除去され、読み上げられることを防ぎます。 デフォルト値: false。 有効値:
説明
|
|
callback |
ResultCallback |
いいえ |
合成されたオーディオおよびイベント通知を非同期で受信するためのコールバックインスタンス。設定すると、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
パラメーター:
|
パラメーター |
型 |
必須 |
説明 |
|
message |
str |
はい |
|
トリガー条件: サーバー応答を受信したとき。メッセージは合成イベント出力(イベントタイプ、元のテキスト、文情報)を含む 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
パラメーター:
|
パラメーター |
型 |
必須 |
説明 |
|
data |
bytes |
はい |
コンストラクターの format パラメーターで指定された形式のオーディオバイナリデータのチャンク。 |
トリガー条件: オーディオデータのチャンクを受信したとき。このコールバックは合成中に複数回呼び出されます。ファイルへの書き込みや再生デバイスへの供給に使用します。
on_error() - エラー発生
メソッドシグネチャー:
def on_error(self, message: str) -> None
パラメーター:
|
パラメーター |
型 |
必須 |
説明 |
|
message |
str |
はい |
エラーコードおよび詳細な理由を含むエラー説明。 |
トリガー条件: 合成中にエラーが発生したとき。このコールバックが実行された後、接続は自動的に閉じられます。トラブルシューティングのためにエラーをログに記録します。
on_close() - 接続終了
メソッドシグネチャー:
def on_close(self) -> None
トリガー条件: WebSocket 接続が終了したとき(正常終了またはエラーによる終了のいずれの場合も)。このコールバックを使用して、オーディオ再生デバイスなどのリソースを解放します。
on_event メッセージの output フィールド
on_event コールバックで受信される JSON メッセージには、合成イベント情報を含む payload.output フィールドがあります。このフィールドを使用して、合成の進行状況を追跡し、文ごとの詳細を取得します。output フィールドの構造は次のとおりです。
|
フィールド |
型 |
説明 |
|
type |
str |
イベントタイプ。値: |
|
original_text |
str |
現在の文の元のテキスト。 |
|
sentence |
dict |
文情報。 |
メッセージ例:
{
"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}、元のテキスト: {original_text}')
コード例
SDK は以下の合成モードをサポートしています。
-
非ストリーミング: 完全なテキストを一度に送信し、完全なオーディオを直接返すブロッキング呼び出し。短文の音声合成に最適です。
-
単方向ストリーミング: 完全なテキストを一度に送信するノンブロッキング呼び出しで、コールバック関数を通じてオーディオデータ(チャンク単位の可能性あり)を配信します。低遅延が求められる短文シナリオに最適です。
-
双方向ストリーミング: 複数のセグメントに分けてテキストを送信するノンブロッキング呼び出しで、リアルタイムでコールバック関数を通じて増分的に合成されたオーディオを配信します。低遅延が求められる長文シナリオに最適です。
非ストリーミング
1 回の呼び出しで送信するテキストは 20,000 文字を超えてはなりません。この制限を超えるとエラーが発生します。
各 call の前に SpeechSynthesizer インスタンスを再初期化してください。
# coding=utf-8
import dashscope
from dashscope.audio.tts_v2 import *
import os
# シンガポールおよび中国 (北京) リージョンの API キーは異なります。API キーの取得方法: https://www.alibabacloud.com/help/zh/model-studio/get-api-key
# 環境変数が設定されていない場合は、次の行を Model Studio API キーに置き換えてください: dashscope.api_key = "sk-xxx"
dashscope.api_key = os.environ.get('DASHSCOPE_API_KEY')
# 以下の構成はシンガポールリージョン用です。{WorkspaceId} を実際のワークスペース ID に置き換えてください。リージョンによって構成は異なります。
dashscope.base_websocket_api_url='wss://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/api-ws/v1/inference'
# モデル
model = "cosyvoice-v3-flash"
# 音声
voice = "longanyang"
# SpeechSynthesizer をインスタンス化し、コンストラクターで model や voice などのリクエストパラメーターを渡します
synthesizer = SpeechSynthesizer(model=model, voice=voice)
# テキストを送信して合成し、バイナリオーディオを取得します
audio = synthesizer.call("How is the weather today?")
# 初回のテキスト送信では WebSocket 接続を確立する必要があるため、初期パケット遅延には接続設定時間が含まれます
print('[Metric] requestId: {}, 初期パケット遅延: {} ms'.format(
synthesizer.get_last_request_id(),
synthesizer.get_first_package_delay()))
# オーディオをローカルファイルに保存します
with open('output.mp3', 'wb') as f:
f.write(audio)単方向ストリーミング
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
# シンガポールおよび中国 (北京) リージョンの API キーは異なります。API キーの取得方法: https://www.alibabacloud.com/help/zh/model-studio/get-api-key
# 環境変数が設定されていない場合は、次の行を Model Studio API キーに置き換えてください: dashscope.api_key = "sk-xxx"
dashscope.api_key = os.environ.get('DASHSCOPE_API_KEY')
# 以下の構成はシンガポールリージョン用です。{WorkspaceId} を実際のワークスペース ID に置き換えてください。リージョンによって構成は異なります。
dashscope.base_websocket_api_url='wss://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/api-ws/v1/inference'
# モデル
model = "cosyvoice-v3-flash"
# 音声
voice = "longanyang"
# コールバックインターフェイスを定義
class Callback(ResultCallback):
_player = None
_stream = None
def on_open(self):
self.file = open("output.mp3", "wb")
print("接続確立: " + get_timestamp())
def on_complete(self):
print("音声合成完了、すべての結果を受信: " + get_timestamp())
# タスク完了後(on_complete コールバックがトリガーされた後)、get_first_package_delay を呼び出して遅延を取得できます
# 初回のテキスト送信では WebSocket 接続を確立する必要があるため、初期パケット遅延には接続設定時間が含まれます
print('[Metric] requestId: {}, 初期パケット遅延: {} ms'.format(
synthesizer.get_last_request_id(),
synthesizer.get_first_package_delay()))
def on_error(self, message: str):
print(f"音声合成エラー: {message}")
def on_close(self):
print("接続終了: " + 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}、元のテキスト: {original_text}")
def on_data(self, data: bytes) -> None:
print(get_timestamp() + " バイナリオーディオ長: " + str(len(data)))
self.file.write(data)
callback = Callback()
# SpeechSynthesizer をインスタンス化し、コンストラクターで model や voice などのリクエストパラメーターを渡します
synthesizer = SpeechSynthesizer(
model=model,
voice=voice,
callback=callback,
)
# テキストを送信して合成し、on_data コールバックメソッドを通じてリアルタイムでバイナリオーディオを取得します
synthesizer.call("How is the weather today?")双方向ストリーミング
1 回の呼び出しで送信するテキストは 20,000 文字を超えてはなりません。累計テキストは 200,000 文字を超えてはなりません。
-
ストリーミング入力中は、
streaming_callを複数回呼び出して、順番にテキストセグメントを送信します。サーバーは受信したテキストに対して自動的に文分割を実行します。-
完全な文は即座に合成されます
-
不完全な文は、完全になるまでバッファーされます
streaming_completeが呼び出されると、サーバーは受信済みで未処理のすべてのテキスト(不完全な文を含む)を強制的に合成します。 -
-
テキストセグメント間の間隔は 23 秒を超えてはなりません。それ以外の場合、「23 秒後にリクエストがタイムアウトしました」という例外が発生します。
送信するテキストがない場合は、すぐに
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
# シンガポールおよび中国 (北京) リージョンの API キーは異なります。API キーの取得方法: https://www.alibabacloud.com/help/zh/model-studio/get-api-key
# 環境変数が設定されていない場合は、次の行を Model Studio API キーに置き換えてください: dashscope.api_key = "sk-xxx"
dashscope.api_key = os.environ.get('DASHSCOPE_API_KEY')
# 以下の構成はシンガポールリージョン用です。{WorkspaceId} を実際のワークスペース ID に置き換えてください。リージョンによって構成は異なります。
dashscope.base_websocket_api_url='wss://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/api-ws/v1/inference'
# モデル
model = "cosyvoice-v3-flash"
# 音声
voice = "longanyang"
# コールバックインターフェイスを定義
class Callback(ResultCallback):
_player = None
_stream = None
def on_open(self):
print("接続確立: " + 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("音声合成完了、すべての結果を受信: " + get_timestamp())
def on_error(self, message: str):
print(f"音声合成エラー: {message}")
def on_close(self):
print("接続終了: " + 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}、元のテキスト: {original_text}")
def on_data(self, data: bytes) -> None:
print(get_timestamp() + " バイナリオーディオ長: " + 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 をインスタンス化し、コンストラクターで model や voice などのリクエストパラメーターを渡します
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: {}, 初期パケット遅延: {} ms'.format(
synthesizer.get_last_request_id(),
synthesizer.get_first_package_delay()))