Utilice el SDK de Python de DashScope para integrar la síntesis de voz en tiempo real de CosyVoice en su aplicación mediante modos sin streaming, streaming unidireccional o streaming bidireccional.
Endpoint de servicio
El SDK utiliza el endpoint de la región de Pekín de forma predeterminada. Para cambiar a una región diferente, modifique dashscope.base_websocket_api_url antes de la inicialización.
Singapore
wss://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/api-ws/v1/inference
Reemplace {WorkspaceId} con su ID de espacio de trabajo real.
China (Beijing)
wss://{WorkspaceId}.cn-beijing.maas.aliyuncs.com/api-ws/v1/inference
Reemplace {WorkspaceId} con su ID de espacio de trabajo real.
ImportanteAlibaba Cloud Model Studio ha lanzado dominios específicos del espacio de trabajo para las regiones China (Pekín) y Singapore. Los nuevos dominios dedicados ofrecen un rendimiento superior y una mayor estabilidad para las solicitudes de inferencia. Recomendamos migrar a los nuevos dominios:
- China (Pekín): de
dashscope.aliyuncs.coma{WorkspaceId}.cn-beijing.maas.aliyuncs.com - Singapur: de
dashscope-intl.aliyuncs.coma{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com
SpeechSynthesizer
Ruta del paquete: dashscope.audio.tts_v2.SpeechSynthesizer
Constructor
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() - sin streaming
Firma del método:
def call(self, text: str) -> bytes
Parámetros:
| Parámetro | Tipo | Obligatorio | Descripción |
|---|---|---|---|
text | str | Sí | El texto completo a sintetizar. Longitud máxima: 20,000 caracteres. |
Valor de retorno: bytes que contiene los datos de audio completos.
Descripción: Esta llamada bloqueante devuelve los datos de audio completos de una sola vez. Es más adecuada para textos cortos donde no se requiere transmisión en tiempo real. Reinicialice la instancia de SpeechSynthesizer antes de cada llamada.
streaming_call() - streaming
Firma del método:
def streaming_call(self, text: str) -> None
Parámetros:
| Parámetro | Tipo | Obligatorio | Descripción |
|---|---|---|---|
text | str | Sí | Un segmento de texto para sintetizar. Llame a este método varias veces para agregar texto. Máximo por llamada: 20,000 caracteres. Máximo acumulado: 200,000 caracteres. |
Descripción: Esta llamada de streaming bidireccional acepta texto en segmentos y entrega audio sintetizado a través de devoluciones de llamada en tiempo real. Es ideal para la integración con modelos de lenguaje grandes donde el texto se genera progresivamente. Llame a streaming_complete() después de enviar todo el texto.
streaming_complete() - finalizar streaming
Firma del método:
def streaming_complete(self) -> None
Descripción: Notifica al servidor que se ha enviado todo el texto. Bloquea el hilo actual hasta que se sintetice el texto restante y se devuelvan todos los datos de audio. Si no se llama a este método, es posible que el texto final no se convierta en voz.
streaming_cancel() - cancelar síntesis por streaming
Firma del método:
def streaming_cancel(self, complete_timeout_millis: int = 10000) -> None
Parámetros:
| Parámetro | Tipo | Obligatorio | Descripción |
|---|---|---|---|
complete_timeout_millis | int | No | Tiempo de espera en milisegundos para esperar a que el servidor devuelva el evento de tarea finalizada. Valor predeterminado: 10000. |
Descripción: Cancela el turno actual de síntesis de voz por streaming. Después de llamar a este método, el SDK finaliza inmediatamente la tarea actual. Puede iniciar una nueva tarea de síntesis en la misma conexión sin reinicializar la instancia de SpeechSynthesizer.
ImportanteRequisito de versión: Esta función requiere el SDK de Python 1.26.4 o posterior.
ImportanteLimitaciones del modelo:
- China (Beijing): Los modelos CosyVoice requieren v2 o posterior.
- Singapur: Los modelos CosyVoice no admiten esta función.
get_last_request_id() - obtener ID de solicitud
Firma del método:
def get_last_request_id(self) -> str
Valor de retorno: str que contiene el ID de solicitud de la solicitud más reciente. Utilícelo para solución de problemas y rastreo.
get_first_package_delay() - obtener latencia del primer paquete
Firma del método:
def get_first_package_delay(self) -> int
Valor de retorno: int que representa el retraso en milisegundos desde el envío del texto hasta la recepción del primer fragmento de audio. Llame a esto después de que se complete la síntesis.
get_response() - obtener mensaje de respuesta
Firma del método:
def get_response(self) -> str
Valor de retorno: str que contiene el mensaje de respuesta en formato JSON de la tarea de síntesis más reciente, incluido el estado de la solicitud y la información de salida.
Parámetros del constructor
Los siguientes parámetros se configuran a través del constructor SpeechSynthesizer para controlar el modelo, la voz, el formato y las características del audio.
| Parámetro | Tipo | Obligatorio | Descripción |
|---|---|---|---|
model | str | Sí | El nombre del modelo. |
voice | str | Sí | La voz utilizada para la síntesis de habla.
|
format | enum | No | Formato de codificación de audio y tasa de muestreo. Predeterminado: AudioFormat.MP3_22050HZ_MONO_256KBPS. La enumeración AudioFormat se encuentra en |
volume | int | No | El nivel de volumen. Valor predeterminado: 50. Valores válidos: [0, 100]. |
speech_rate | float | No | La velocidad del habla. Valor predeterminado: 1.0. Valores válidos: [0.5, 2.0]. |
pitch_rate | float | No | El tono. Valor predeterminado: 1.0. Valores válidos: [0.5, 2.0]. |
bit_rate | int | No | La tasa de bits de audio en kbps. Cuando el formato de audio es mp3 u opus, utilice bit_rate para ajustar la tasa de bits.Valor predeterminado: 32. Valores válidos: [6, 510]. Configure |
word_timestamp_enabled | bool | No | Especifica si se deben habilitar las marcas de tiempo a nivel de palabra. Valor predeterminado: false. Disponible solo en modo de salida por streaming. Voces compatibles: voces clonadas de cosyvoice-v3.5-plus, cosyvoice-v3.5-flash, cosyvoice-v3-flash, cosyvoice-v3-plus, cosyvoice-v2 y voces del sistema marcadas como compatibles en la CosyVoice lista de voces. Las voces clonadas de otros modelos no admiten esta función. Configure |
seed | int | No | Una semilla aleatoria para controlar la variación en la salida de la síntesis. Cuando la versión del modelo, el texto, la voz y otros parámetros no cambian, usar la misma semilla produce resultados idénticos. Valor predeterminado: 0. Valores válidos: [0, 65535]. |
language_hints | list[str] | No | Importante
Especifica el idioma objetivo para la síntesis de voz con el fin de mejorar la calidad de salida. Cuando la pronunciación de dígitos, la expansión de abreviaturas, la lectura de símbolos o la síntesis en idiomas minoritarios no cumpla con las expectativas, utilice este parámetro. Por ejemplo:
Valores válidos
|
instruction | str | No | Controla las características de la síntesis, como el dialecto, la emoción o el estilo de habla. Para detalles de uso, consulte Control de instrucciones. |
enable_aigc_tag | bool | No | Especifica si se debe incrustar una marca de agua AIGC en el audio generado. Cuando se establece en true, la marca de agua se incrusta en archivos de audio de formatos compatibles (wav/mp3/opus). Valor predeterminado: false. NotaSolo cosyvoice-v3-flash, cosyvoice-v3-plus y cosyvoice-v2 admiten esta función. Configure |
aigc_propagator | str | No | Establece el campo ContentPropagator en la marca de agua AIGC, identificando al propagador del contenido. Surte efecto solo cuando enable_aigc_tag es true.Valor predeterminado: UID de Alibaba Cloud. NotaSolo cosyvoice-v3-flash, cosyvoice-v3-plus y cosyvoice-v2 admiten esta función. Se configura a través del parámetro |
aigc_propagate_id | str | No | Establece el campo PropagateID en la marca de agua AIGC, identificando de manera única una acción de propagación específica. Surte efecto solo cuando enable_aigc_tag es true.Valor predeterminado: El ID de solicitud de la solicitud actual de síntesis de voz. NotaSolo cosyvoice-v3-flash, cosyvoice-v3-plus y cosyvoice-v2 admiten esta función. Se configura a través del parámetro |
hot_fix | dict | No | Configura correcciones de pronunciación y reemplazos de texto aplicados antes de la síntesis. NotaEsta función no es compatible con cosyvoice-v2. Parámetros:
Ejemplo: |
enable_markdown_filter | bool | No | NotaSolo las voces clonadas de cosyvoice-v3-flash admiten esta función. Especifica si se debe habilitar el filtrado de Markdown. Cuando está habilitado, el sistema elimina automáticamente los símbolos de marcado Markdown del texto de entrada antes de la síntesis, evitando que se lean en voz alta. Valor predeterminado: false. Valores válidos:
Configure |
callback | ResultCallback | No | Una instancia de devolución de llamada para recibir audio sintetizado y notificaciones de eventos de forma asíncrona. Cuando se configura, call() se ejecuta en modo streaming y entrega el audio a través de la devolución de llamada on_data. Cuando no se configura, call() se ejecuta en modo sin streaming y devuelve el audio completo como bytes. |
ResultCallback
Ruta del paquete: dashscope.audio.tts_v2.ResultCallback
on_open() - conexión establecida
Firma del método:
def on_open(self) -> None
Se activa cuando: La conexión WebSocket se establece correctamente. Utilice esta devolución de llamada para inicializar flujos de salida de audio o abrir recursos de archivos.
on_event() - recibir respuesta del servidor
Firma del método:
def on_event(self, message: str) -> None
Parámetros:
| Parámetro | Tipo | Obligatorio | Descripción |
|---|---|---|---|
message | str | Sí | Un evento de respuesta del servidor en formato JSON que contiene header (información de la solicitud) y payload (información de salida). El campo payload.output contiene el tipo de evento, el texto original y otros detalles. Consulte campo output en mensajes de on_event. |
Se activa cuando: Se recibe una respuesta del servidor. El mensaje es una cadena JSON que contiene la salida del evento de síntesis (tipo de evento, texto original, información de la oración). Analícelo con json.loads(message) y acceda a payload.output para obtener más detalles.
on_complete() - síntesis completada
Firma del método:
def on_complete(self) -> None
Se activa cuando: Todo el texto ha sido sintetizado y todos los datos de audio se han entregado a través de on_data. Utilice esta devolución de llamada para invocar get_first_package_delay() y obtener métricas de rendimiento.
on_data() - recibir datos de audio
Firma del método:
def on_data(self, data: bytes) -> None
Parámetros:
| Parámetro | Tipo | Obligatorio | Descripción |
|---|---|---|---|
data | bytes | Sí | Un fragmento de datos binarios de audio en el formato especificado por el parámetro format del constructor. |
Se activa cuando: Se recibe un fragmento de datos de audio. Esta devolución de llamada se invoca varias veces durante la síntesis. Úsela para escribir datos en un archivo o enviarlos a un dispositivo de reproducción.
on_error() - ocurrió un error
Firma del método:
def on_error(self, message: str) -> None
Parámetros:
| Parámetro | Tipo | Obligatorio | Descripción |
|---|---|---|---|
message | str | Sí | Una descripción de error que contiene el código de error y la razón detallada. |
Se activa cuando: Ocurre un error durante la síntesis. La conexión se cierra automáticamente después de que se active esta devolución de llamada. Registre el error para la solución de problemas.
on_close() - conexión cerrada
Firma del método:
def on_close(self) -> None
Se activa cuando: La conexión WebSocket se cierra (ya sea normalmente o debido a un error). Utilice esta devolución de llamada para liberar recursos como dispositivos de reproducción de audio.
campo output en mensajes de on_event
El mensaje JSON recibido por la devolución de llamada on_event contiene un campo payload.output con información del evento de síntesis. Utilice este campo para rastrear el progreso de la síntesis y recuperar detalles por oración. La estructura del campo output es la siguiente:
| Campo | Tipo | Descripción |
|---|---|---|
type | str | Tipo de evento. Valores: sentence-begin (inicio de síntesis de oración), sentence-synthesis (síntesis de oración en curso) o sentence-end (finalización de síntesis de oración). |
original_text | str | El texto original de la oración actual. Se devuelve en los eventos sentence-begin y sentence-end. |
sentence | dict | Información de la oración. Contiene index (número de secuencia de la oración) y words (lista de palabras con información de marcas de tiempo cuando word_timestamp_enabled está activado). |
Ejemplo de mensaje:
{
"header": {
"task_id": "xxx",
"event": "result-generated",
"attributes": {}
},
"payload": {
"output": {
"type": "sentence-begin",
"original_text": "How is the weather today?",
"sentence": {
"index": 0,
"words": []
}
}
}
}
Ejemplo de análisis:
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}')
Ejemplos de código
El SDK admite los siguientes modos de síntesis:
- No streaming: Una llamada bloqueante que envía el texto completo de una sola vez y devuelve el audio completo directamente. Ideal para la síntesis de voz de texto corto.
- Streaming unidireccional: Una llamada no bloqueante que envía el texto completo de una sola vez y entrega datos de audio (potencialmente en fragmentos) a través de una función de devolución de llamada. Ideal para escenarios de texto corto que requieren baja latencia.
- Streaming bidireccional: Una llamada no bloqueante que envía texto en múltiples segmentos y entrega audio sintetizado incrementalmente a través de una función de devolución de llamada en tiempo real. Ideal para escenarios de texto largo que requieren baja latencia.
Sin streaming
El texto enviado en una sola llamada no debe exceder los 20,000 caracteres. Superar este límite provoca un error.
ImportanteVuelva a inicializar la instancia de SpeechSynthesizer antes de cada call.
# coding=utf-8
import dashscope
from dashscope.audio.tts_v2 import *
import os
# The API Keys for Singapore and Beijing regions are different. Get API Key: https://www.alibabacloud.com/help/model-studio/get-api-key
# If environment variable is not configured, replace the following line with your Model Studio API Key: dashscope.api_key = "sk-xxx"
dashscope.api_key = os.environ.get('DASHSCOPE_API_KEY')
# The following configuration is for the Singapore region. Replace "{WorkspaceId}" with your actual workspace ID. The configuration varies by region.
dashscope.base_websocket_api_url='wss://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/api-ws/v1/inference'
# Model
model = "cosyvoice-v3-plus"
# Voice
voice = "longanyang"
# Instantiate SpeechSynthesizer, passing request parameters such as model and voice in the constructor
synthesizer = SpeechSynthesizer(model=model, voice=voice)
# Send text for synthesis and get binary audio
audio = synthesizer.call("How is the weather today?")
# The first text submission requires establishing a WebSocket connection, so the first packet latency includes the connection setup time
print('[Metric] requestId: {}, first packet latency: {} ms'.format(
synthesizer.get_last_request_id(),
synthesizer.get_first_package_delay()))
# Save audio to local file
with open('output.mp3', 'wb') as f:
f.write(audio)
CLI de dashscope
Llamada a través de la línea de comandos dashscope.
export DASHSCOPE_API_KEY="your-api-key"
# Replace {WorkspaceId} with your Beijing workspace ID.
export DASHSCOPE_HTTP_BASE_URL="https://{WorkspaceId}.cn-beijing.maas.aliyuncs.com/api/v1"
dashscope speech-synthesis create -m cosyvoice-v3-plus -t "Hello world" --voice longanyang
ImportanteEl asistente interactivo SDK Expert puede realizar las mismas tareas de desarrollo y solución de problemas mediante lenguaje natural; consulte
DashScope SDK Expert.Para la tabla completa de regiones, consulte Resumen de URL base.
Streaming unidireccional
El texto enviado en una sola llamada no debe exceder los 20,000 caracteres. Superar este límite provoca un error.
ImportanteVuelva a inicializar la instancia de SpeechSynthesizer antes de cada 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
# The API Keys for Singapore and Beijing regions are different. Get API Key: https://www.alibabacloud.com/help/model-studio/get-api-key
# If environment variable is not configured, replace the following line with your Model Studio API Key: dashscope.api_key = "sk-xxx"
dashscope.api_key = os.environ.get('DASHSCOPE_API_KEY')
# The following configuration is for the Singapore region. Replace "{WorkspaceId}" with your actual workspace ID. The configuration varies by region.
dashscope.base_websocket_api_url='wss://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/api-ws/v1/inference'
# Model
model = "cosyvoice-v3-plus"
# Voice
voice = "longanyang"
# Define callback interface
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())
# After the task completes (on_complete callback triggered), you can call get_first_package_delay to get the latency
# The first text submission requires establishing a WebSocket connection, so the first packet latency includes the connection setup time
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):
# Parse server-side events and get output information
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()
# Instantiate SpeechSynthesizer, passing request parameters such as model and voice in the constructor
synthesizer = SpeechSynthesizer(
model=model,
voice=voice,
callback=callback,
)
# Send text for synthesis and get binary audio in real time via the on_data callback method
synthesizer.call("How is the weather today?")
Streaming bidireccional
El texto enviado por llamada no debe exceder los 20,000 caracteres. El texto acumulado no debe exceder los 200,000 caracteres.
-
Durante la entrada en streaming, llame a
streaming_callvarias veces para enviar segmentos de texto en secuencia. El servidor realiza automáticamente la segmentación de oraciones en el texto recibido:- Las oraciones completas se sintetizan inmediatamente
- Las oraciones incompletas se almacenan en búfer hasta completarse
Cuando se llama a
streaming_complete, el servidor fuerza la síntesis de todo el texto recibido pero no procesado (incluidas las oraciones incompletas). -
El intervalo entre segmentos de texto no debe exceder los 23 segundos. De lo contrario, se genera una excepción de "tiempo de espera de solicitud agotado después de 23 segundos".
Si no hay texto para enviar, llame a
streaming_completerápidamente para finalizar la tarea.ImportanteLlame siempre a
streaming_complete. No hacerlo puede provocar que el texto final no se convierta en voz.El servidor aplica un tiempo de espera de 23 segundos. Este valor no se puede modificar en el lado del cliente.
# coding=utf-8
#
# pyaudio installation instructions:
# For macOS, run the following commands:
# brew install portaudio
# pip install pyaudio
# For Debian/Ubuntu, run the following commands:
# sudo apt-get install python-pyaudio python3-pyaudio
# or
# pip install pyaudio
# For CentOS, run the following commands:
# sudo yum install -y portaudio portaudio-devel && pip install pyaudio
# For Microsoft Windows, run the following command:
# 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
# The API Keys for Singapore and Beijing regions are different. Get API Key: https://www.alibabacloud.com/help/model-studio/get-api-key
# If environment variable is not configured, replace the following line with your Model Studio API Key: dashscope.api_key = "sk-xxx"
dashscope.api_key = os.environ.get('DASHSCOPE_API_KEY')
# The following configuration is for the Singapore region. Replace "{WorkspaceId}" with your actual workspace ID. The configuration varies by region.
dashscope.base_websocket_api_url='wss://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/api-ws/v1/inference'
# Model
model = "cosyvoice-v3-plus"
# Voice
voice = "longanyang"
# Define callback interface
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())
# Stop the player
self._stream.stop_stream()
self._stream.close()
self._player.terminate()
def on_event(self, message):
# Parse server-side events and get output information
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.",
]
# Instantiate SpeechSynthesizer, passing request parameters such as model and voice in the constructor
synthesizer = SpeechSynthesizer(
model=model,
voice=voice,
format=AudioFormat.PCM_22050HZ_MONO_16BIT,
callback=callback,
)
# Send text for streaming synthesis. Get binary audio in real time via the on_data callback method
for text in test_text:
synthesizer.streaming_call(text)
time.sleep(0.1)
# End streaming speech synthesis
synthesizer.streaming_complete()
# The first text submission requires establishing a WebSocket connection, so the first packet latency includes the connection setup time
print('[Metric] requestId: {}, first packet latency: {} ms'.format(
synthesizer.get_last_request_id(),
synthesizer.get_first_package_delay()))