Gunakan SDK Python DashScope untuk mengintegrasikan sintesis suara real-time CosyVoice ke dalam aplikasi Anda melalui mode non-streaming, streaming satu arah, atau streaming dua arah.
Panduan pengguna: Untuk deskripsi model dan rekomendasi pemilihan, lihat Sintesis suara.
Titik akhir layanan
SDK menggunakan titik akhir wilayah Beijing secara default. Untuk beralih ke wilayah lain, ubah dashscope.base_websocket_api_url sebelum inisialisasi.
Singapura
wss://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/api-ws/v1/inference
Ganti {WorkspaceId} dengan workspace ID Anda yang sebenarnya.
Tiongkok (Beijing)
wss://{WorkspaceId}.cn-beijing.maas.aliyuncs.com/api-ws/v1/inference
Ganti {WorkspaceId} dengan workspace ID Anda yang sebenarnya.
Beralih ke wilayah Singapura:
import dashscope
# Setel di awal kode Anda
dashscope.base_websocket_api_url = 'wss://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/api-ws/v1/inference'
Alibaba Cloud Model Studio telah merilis domain khusus ruang kerja untuk wilayah Tiongkok (Beijing) dan Singapura. Domain khusus baru ini memberikan performa lebih unggul dan stabilitas lebih tinggi untuk permintaan inferensi. Kami merekomendasikan migrasi ke domain baru:
Tiongkok (Beijing): dari
dashscope.aliyuncs.comke{WorkspaceId}.cn-beijing.maas.aliyuncs.comSingapura: dari
dashscope-intl.aliyuncs.comke{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com
Ganti {WorkspaceId} dengan Workspace ID Anda yang sebenarnya. Domain lama tetap berfungsi penuh.
SpeechSynthesizer
Jalur paket: dashscope.audio.tts_v2.SpeechSynthesizer
Konstruktor
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() - non-streaming
Signature metode:
def call(self, text: str) -> bytes
Parameter:
|
Parameter |
Tipe |
Wajib |
Deskripsi |
|
text |
str |
Ya |
Teks lengkap yang akan disintesis. Panjang maksimum: 20.000 karakter. |
Nilai kembalian: bytes yang berisi data audio lengkap.
Deskripsi: Pemanggilan blocking ini mengembalikan data audio lengkap sekaligus. Metode ini paling cocok untuk teks pendek yang tidak memerlukan streaming real-time. Inisialisasi ulang instans SpeechSynthesizer sebelum setiap pemanggilan.
streaming_call() - streaming
Signature metode:
def streaming_call(self, text: str) -> None
Parameter:
|
Parameter |
Tipe |
Wajib |
Deskripsi |
|
text |
str |
Ya |
Segmen teks yang akan disintesis. Panggil metode ini beberapa kali untuk menambahkan teks. Maksimum per pemanggilan: 20.000 karakter. Maksimum kumulatif: 200.000 karakter. |
Deskripsi: Pemanggilan streaming dua arah ini menerima teks dalam segmen dan mengirimkan audio hasil sintesis melalui callback secara real-time. Metode ini ideal untuk integrasi dengan model bahasa besar di mana teks dihasilkan secara progresif. Panggil streaming_complete() setelah mengirimkan seluruh teks.
streaming_complete() - akhiri streaming
Signature metode:
def streaming_complete(self) -> None
Deskripsi: Memberi tahu server bahwa seluruh teks telah dikirim. Memblokir thread saat ini hingga sisa teks disintesis dan seluruh data audio dikembalikan. Gagal memanggil metode ini dapat menyebabkan teks akhir tidak dikonversi menjadi suara.
get_last_request_id() - dapatkan ID permintaan
Signature metode:
def get_last_request_id(self) -> str
Nilai kembalian: str yang berisi ID permintaan dari permintaan terbaru. Gunakan ini untuk troubleshooting dan pelacakan.
get_first_package_delay() - dapatkan latensi paket pertama
Signature metode:
def get_first_package_delay(self) -> int
Nilai kembalian: int yang merepresentasikan penundaan dalam milidetik dari pengiriman teks hingga menerima chunk audio pertama. Panggil ini setelah sintesis selesai.
get_response() - dapatkan pesan respons
Signature metode:
def get_response(self) -> str
Nilai kembalian: str yang berisi pesan respons dalam format JSON dari tugas sintesis terbaru, termasuk status permintaan dan informasi output.
Parameter konstruktor
Parameter berikut ditetapkan melalui konstruktor SpeechSynthesizer untuk mengontrol model, suara, format, dan karakteristik audio.
|
Parameter |
Tipe |
Wajib |
Deskripsi |
|
model |
str |
Ya |
Nama model. |
|
voice |
str |
Ya |
voice Suara yang digunakan untuk sintesis suara.
|
|
format |
enum |
Tidak |
Format encoding audio dan laju sampel. Default: AudioFormat.MP3_22050HZ_MONO_256KBPS. Enum AudioFormat terletak di |
|
volume |
int |
Tidak |
Tingkat volume. Nilai default: 50. Nilai valid: [0, 100]. |
|
speech_rate |
float |
Tidak |
Laju bicara. Nilai default: 1.0. Nilai valid: [0.5, 2.0]. |
|
pitch_rate |
float |
Tidak |
Pitch. Nilai default: 1.0. Nilai valid: [0.5, 2.0]. |
|
bit_rate |
int |
Tidak |
Bitrate audio dalam kbps. Saat format audio adalah opus, gunakan Nilai default: 32. Nilai valid: [6, 510]. Catatan
Setel
|
|
word_timestamp_enabled |
bool |
Tidak |
Menentukan apakah akan mengaktifkan timestamp tingkat kata. Nilai default: false. Hanya tersedia dalam mode keluaran streaming. Suara yang didukung: suara kloning dari cosyvoice-v3.5-plus, cosyvoice-v3.5-flash, cosyvoice-v3-flash, cosyvoice-v3-plus, dan cosyvoice-v2, serta suara sistem yang ditandai sebagai didukung di Daftar Suara CosyVoice. Suara kloning dari model lain tidak mendukung fitur ini. Catatan
Setel
|
|
seed |
int |
Tidak |
Seed acak untuk mengontrol variasi pada output sintesis. Ketika versi model, teks, suara, dan parameter lainnya tidak berubah, penggunaan seed yang sama menghasilkan hasil identik. Nilai default: 0. Nilai valid: [0, 65535]. |
|
language_hints |
list[str] |
Tidak |
Penting
Menentukan bahasa target untuk sintesis suara guna meningkatkan kualitas output. Saat pelafalan angka, ekspansi singkatan, pembacaan simbol, atau sintesis bahasa minoritas tidak sesuai harapan, gunakan parameter ini. Contohnya:
Nilai valid:
|
|
instruction |
str |
Tidak |
Mengontrol karakteristik sintesis seperti dialek, emosi, atau gaya berbicara. Untuk detail penggunaan, lihat Kontrol berbasis instruksi. |
|
enable_aigc_tag |
bool |
Tidak |
Menentukan apakah akan menyematkan watermark AIGC ke dalam audio yang dihasilkan. Saat diatur ke true, watermark disematkan ke dalam file audio dengan format yang didukung (wav/mp3/opus). Nilai default: false. Hanya cosyvoice-v3-flash, cosyvoice-v3-plus, dan cosyvoice-v2 yang mendukung fitur ini. Catatan
Setel
|
|
aigc_propagator |
str |
Tidak |
Menyetel bidang Nilai default: UID Alibaba Cloud. Hanya cosyvoice-v3-flash, cosyvoice-v3-plus, dan cosyvoice-v2 yang mendukung fitur ini. Setel melalui parameter |
|
aigc_propagate_id |
str |
Tidak |
Menyetel bidang Nilai default: ID permintaan dari permintaan sintesis suara saat ini. Hanya cosyvoice-v3-flash, cosyvoice-v3-plus, dan cosyvoice-v2 yang mendukung fitur ini. Setel melalui parameter |
|
hot_fix |
dict |
Tidak |
Mengonfigurasi koreksi pelafalan dan penggantian teks yang diterapkan sebelum sintesis. Fitur ini tidak didukung oleh cosyvoice-v2. Parameter:
Contoh:
|
|
enable_markdown_filter |
bool |
Tidak |
Penting
Hanya suara kloning dari cosyvoice-v3-flash yang mendukung fitur ini. Menentukan apakah akan mengaktifkan penyaringan Markdown. Saat diaktifkan, sistem secara otomatis menghapus simbol markup Markdown dari teks input sebelum sintesis, sehingga simbol tersebut tidak dibaca keras-keras. Nilai default: false. Nilai valid:
Catatan
Setel
|
|
callback |
ResultCallback |
Tidak |
Instans callback untuk menerima audio hasil sintesis dan notifikasi event secara asinkron. Saat diatur, call() berjalan dalam mode streaming dan mengirimkan audio melalui callback on_data. Saat tidak diatur, call() berjalan dalam mode non-streaming dan mengembalikan audio lengkap sebagai bytes. |
ResultCallback
Jalur paket: dashscope.audio.tts_v2.ResultCallback
on_open() - koneksi terbentuk
Signature metode:
def on_open(self) -> None
Dipicu saat: Koneksi WebSocket berhasil dibentuk. Gunakan callback ini untuk menginisialisasi aliran output audio atau membuka sumber daya file.
on_event() - menerima respons server
Signature metode:
def on_event(self, message: str) -> None
Parameter:
|
Parameter |
Tipe |
Wajib |
Deskripsi |
|
message |
str |
Ya |
Event respons server dalam format JSON yang berisi |
Dipicu saat: Respons server diterima. Pesan berupa string JSON yang berisi output event sintesis (tipe event, teks asli, informasi kalimat). Urai dengan json.loads(message) dan akses payload.output untuk detailnya.
on_complete() - sintesis selesai
Signature metode:
def on_complete(self) -> None
Dipicu saat: Seluruh teks telah disintesis dan seluruh data audio telah dikirimkan melalui on_data. Gunakan callback ini untuk memanggil get_first_package_delay() guna mendapatkan metrik performa.
on_data() - menerima data audio
Signature metode:
def on_data(self, data: bytes) -> None
Parameter:
|
Parameter |
Tipe |
Wajib |
Deskripsi |
|
data |
bytes |
Ya |
Chunk data biner audio dalam format yang ditentukan oleh parameter format konstruktor. |
Dipicu saat: Chunk data audio diterima. Callback ini dipanggil beberapa kali selama sintesis. Gunakan untuk menulis data ke file atau mengirimkannya ke perangkat pemutaran.
on_error() - terjadi kesalahan
Signature metode:
def on_error(self, message: str) -> None
Parameter:
|
Parameter |
Tipe |
Wajib |
Deskripsi |
|
message |
str |
Ya |
Deskripsi kesalahan yang berisi kode kesalahan dan alasan detail. |
Dipicu saat: Terjadi kesalahan selama sintesis. Koneksi ditutup secara otomatis setelah callback ini dijalankan. Catat kesalahan untuk troubleshooting.
on_close() - koneksi ditutup
Signature metode:
def on_close(self) -> None
Dipicu saat: Koneksi WebSocket ditutup (baik normal maupun karena kesalahan). Gunakan callback ini untuk melepaskan sumber daya seperti perangkat pemutaran audio.
Bidang output dalam pesan on_event
Pesan JSON yang diterima oleh callback on_event berisi bidang payload.output dengan informasi event sintesis. Gunakan bidang ini untuk melacak progres sintesis dan mengambil detail per kalimat. Struktur bidang output adalah sebagai berikut:
|
Bidang |
Tipe |
Deskripsi |
|
type |
str |
Tipe event. Nilai: |
|
original_text |
str |
Teks asli dari kalimat saat ini. Dikembalikan dalam event |
|
sentence |
dict |
Informasi kalimat. Berisi |
Contoh pesan:
{
"header": {
"task_id": "xxx",
"event": "result-generated",
"attributes": {}
},
"payload": {
"output": {
"type": "sentence-begin",
"original_text": "How is the weather today?",
"sentence": {
"index": 0,
"words": []
}
}
}
}
Contoh penguraian:
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'Tipe event: {event_type}, Teks asli: {original_text}')
Contoh kode
SDK mendukung mode sintesis berikut:
-
Non-streaming: Pemanggilan blocking yang mengirimkan teks lengkap sekaligus dan mengembalikan audio lengkap secara langsung. Paling cocok untuk sintesis suara teks pendek.
-
Streaming satu arah: Pemanggilan non-blocking yang mengirimkan teks lengkap sekaligus dan mengirimkan data audio (mungkin dalam chunk) melalui fungsi callback. Paling cocok untuk skenario teks pendek yang memerlukan latensi rendah.
-
Streaming dua arah: Pemanggilan non-blocking yang mengirimkan teks dalam beberapa segmen dan mengirimkan audio hasil sintesis secara inkremental melalui fungsi callback secara real-time. Paling cocok untuk skenario teks panjang yang memerlukan latensi rendah.
Non-streaming
Teks yang dikirim dalam satu pemanggilan tidak boleh melebihi 20.000 karakter. Melebihi batas ini menyebabkan kesalahan.
Lakukan inisialisasi ulang instans SpeechSynthesizer sebelum setiap call.
# coding=utf-8
import dashscope
from dashscope.audio.tts_v2 import *
import os
# API Key untuk wilayah Singapura dan Beijing berbeda. Dapatkan API Key: https://www.alibabacloud.com/help/zh/model-studio/get-api-key
# Jika variabel lingkungan belum dikonfigurasi, ganti baris berikut dengan API Key Model Studio Anda: dashscope.api_key = "sk-xxx"
dashscope.api_key = os.environ.get('DASHSCOPE_API_KEY')
# Konfigurasi berikut untuk wilayah Singapura. Ganti "{WorkspaceId}" dengan workspace ID Anda yang sebenarnya. Konfigurasi berbeda tiap wilayah.
dashscope.base_websocket_api_url='wss://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/api-ws/v1/inference'
# Model
model = "cosyvoice-v3-flash"
# Voice
voice = "longanyang"
# Buat instans SpeechSynthesizer, teruskan parameter permintaan seperti model dan voice di konstruktor
synthesizer = SpeechSynthesizer(model=model, voice=voice)
# Kirim teks untuk sintesis dan dapatkan audio biner
audio = synthesizer.call("How is the weather today?")
# Pengiriman teks pertama memerlukan pembentukan koneksi WebSocket, sehingga latensi paket pertama mencakup waktu pembentukan koneksi
print('[Metric] requestId: {}, first packet latency: {} ms'.format(
synthesizer.get_last_request_id(),
synthesizer.get_first_package_delay()))
# Simpan audio ke file lokal
with open('output.mp3', 'wb') as f:
f.write(audio)Streaming satu arah
Teks yang dikirim dalam satu pemanggilan tidak boleh melebihi 20.000 karakter. Melebihi batas ini menyebabkan kesalahan.
Inisialisasi ulang instans SpeechSynthesizer sebelum setiap pemanggilan call.
# 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 Key untuk wilayah Singapura dan Beijing berbeda. Dapatkan API Key: https://www.alibabacloud.com/help/zh/model-studio/get-api-key
# Jika variabel lingkungan belum dikonfigurasi, ganti baris berikut dengan API Key Model Studio Anda: dashscope.api_key = "sk-xxx"
dashscope.api_key = os.environ.get('DASHSCOPE_API_KEY')
# Konfigurasi berikut untuk wilayah Singapura. Ganti "{WorkspaceId}" dengan workspace ID Anda yang sebenarnya. Konfigurasi berbeda tiap wilayah.
dashscope.base_websocket_api_url='wss://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/api-ws/v1/inference'
# Model
model = "cosyvoice-v3-flash"
# Voice
voice = "longanyang"
# Definisikan antarmuka callback
class Callback(ResultCallback):
_player = None
_stream = None
def on_open(self):
self.file = open("output.mp3", "wb")
print("Koneksi terbentuk: " + get_timestamp())
def on_complete(self):
print("Sintesis suara selesai, seluruh hasil diterima: " + get_timestamp())
# Setelah tugas selesai (callback on_complete dipicu), Anda dapat memanggil get_first_package_delay untuk mendapatkan latensi
# Pengiriman teks pertama memerlukan pembentukan koneksi WebSocket, sehingga latensi paket pertama mencakup waktu pembentukan koneksi
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"Kesalahan sintesis suara: {message}")
def on_close(self):
print("Koneksi ditutup: " + get_timestamp())
self.file.close()
def on_event(self, message):
# Urai event sisi server dan dapatkan informasi output
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"Tipe event: {event_type}, teks asli: {original_text}")
def on_data(self, data: bytes) -> None:
print(get_timestamp() + " Panjang audio biner: " + str(len(data)))
self.file.write(data)
callback = Callback()
# Buat instans SpeechSynthesizer, teruskan parameter permintaan seperti model dan voice di konstruktor
synthesizer = SpeechSynthesizer(
model=model,
voice=voice,
callback=callback,
)
# Kirim teks untuk sintesis dan dapatkan audio biner secara real-time melalui metode callback on_data
synthesizer.call("How is the weather today?")Streaming dua arah
Teks yang dikirim per pemanggilan tidak boleh melebihi 20.000 karakter. Teks kumulatif tidak boleh melebihi 200.000 karakter.
-
Saat input streaming, panggil
streaming_callbeberapa kali untuk mengirimkan segmen teks secara berurutan. Server secara otomatis melakukan segmentasi kalimat pada teks yang diterima:-
Kalimat lengkap langsung disintesis
-
Kalimat tidak lengkap dibuffer hingga lengkap
Saat
streaming_completedipanggil, server memaksa mensintesis seluruh teks yang diterima namun belum diproses (termasuk kalimat tidak lengkap). -
-
Interval antar segmen teks tidak boleh melebihi 23 detik. Jika tidak, akan muncul exception "request timeout after 23 seconds".
Jika tidak ada teks yang akan dikirim, segera panggil
streaming_completeuntuk mengakhiri tugas.PentingSelalu panggil
streaming_complete. Gagal melakukannya dapat menyebabkan teks akhir tidak dikonversi menjadi suara.Server menerapkan timeout 23 detik. Nilai ini tidak dapat diubah di sisi klien.
# coding=utf-8
#
# Instruksi instalasi pyaudio:
# Untuk macOS, jalankan perintah berikut:
# brew install portaudio
# pip install pyaudio
# Untuk Debian/Ubuntu, jalankan perintah berikut:
# sudo apt-get install python-pyaudio python3-pyaudio
# atau
# pip install pyaudio
# Untuk CentOS, jalankan perintah berikut:
# sudo yum install -y portaudio portaudio-devel && pip install pyaudio
# Untuk Microsoft Windows, jalankan perintah berikut:
# 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 Key untuk wilayah Singapura dan Beijing berbeda. Dapatkan API Key: https://www.alibabacloud.com/help/zh/model-studio/get-api-key
# Jika variabel lingkungan belum dikonfigurasi, ganti baris berikut dengan API Key Model Studio Anda: dashscope.api_key = "sk-xxx"
dashscope.api_key = os.environ.get('DASHSCOPE_API_KEY')
# Konfigurasi berikut untuk wilayah Singapura. Ganti "{WorkspaceId}" dengan workspace ID Anda yang sebenarnya. Konfigurasi berbeda tiap wilayah.
dashscope.base_websocket_api_url='wss://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/api-ws/v1/inference'
# Model
model = "cosyvoice-v3-flash"
# Voice
voice = "longanyang"
# Definisikan antarmuka callback
class Callback(ResultCallback):
_player = None
_stream = None
def on_open(self):
print("Koneksi terbentuk: " + 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("Sintesis suara selesai, seluruh hasil diterima: " + get_timestamp())
def on_error(self, message: str):
print(f"Kesalahan sintesis suara: {message}")
def on_close(self):
print("Koneksi ditutup: " + get_timestamp())
# Hentikan pemutar
self._stream.stop_stream()
self._stream.close()
self._player.terminate()
def on_event(self, message):
# Urai event sisi server dan dapatkan informasi output
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"Tipe event: {event_type}, teks asli: {original_text}")
def on_data(self, data: bytes) -> None:
print(get_timestamp() + " Panjang audio biner: " + 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.",
]
# Buat instans SpeechSynthesizer, teruskan parameter permintaan seperti model dan voice di konstruktor
synthesizer = SpeechSynthesizer(
model=model,
voice=voice,
format=AudioFormat.PCM_22050HZ_MONO_16BIT,
callback=callback,
)
# Kirim teks untuk sintesis streaming. Dapatkan audio biner secara real-time melalui metode callback on_data
for text in test_text:
synthesizer.streaming_call(text)
time.sleep(0.1)
# Akhiri sintesis suara streaming
synthesizer.streaming_complete()
# Pengiriman teks pertama memerlukan pembentukan koneksi WebSocket, sehingga latensi paket pertama mencakup waktu pembentukan koneksi
print('[Metric] requestId: {}, first packet latency: {} ms'.format(
synthesizer.get_last_request_id(),
synthesizer.get_first_package_delay()))