Skip to main content

SDK de Python de CosyVoice

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 endpoint del SDK viene determinado por los parámetros workspace y region del constructor de Client (corresponden a las direcciones siguientes, que incluyen el WorkspaceId). Para cambiar a una región diferente, modifique los parámetros del constructor de Client por los valores de esa región.
  • Singapore
  • China (Beijing)
  • CLI de dashscope
wss://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/api-ws/v1/inferenceReemplace {WorkspaceId} con su ID de espacio de trabajo real.
Alibaba Cloud Model Studio ha lanzado dominios específicos del espacio de trabajo para las regiones China (Pekín) y Singapur. 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.com a {WorkspaceId}.cn-beijing.maas.aliyuncs.com
  • Singapur: de dashscope-intl.aliyuncs.com a {WorkspaceId}.ap-southeast-1.maas.aliyuncs.com

Recurso principal (client.audio.tts)

Ruta del recurso: client.audio.tts Descripción: Síntesis de voz basada en WebSocket, con tres modos de llamada: síntesis de una sola llamada (synthesize), síntesis por streaming (stream) y sesión de streaming bidireccional (connect).

Punto de entrada de llamada

# Síntesis de una sola llamada: devuelve los bytes de audio completos
audio = client.audio.tts.synthesize(
    text,                      # text es un parámetro obligatorio (argumento posicional)
    model="cosyvoice-v3-plus", # El modelo al que pertenece la voz
    voice="longanyang",        # La voz
    format="mp3",              # Formato de codificación de audio, valor predeterminado "mp3"
    sample_rate=22050,         # Tasa de muestreo, valor predeterminado 22050
)

# Síntesis por streaming: entrega bytes de audio fragmento a fragmento (escriba o reproduzca mientras recibe)
for chunk in client.audio.tts.stream(text, model=..., voice=...):
    ...

# Sesión de streaming bidireccional: envíe texto en segmentos; la conexión se establece automáticamente al entrar en el contexto with
with client.audio.tts.connect(model=..., voice=...) as session:
    session.send_text(text)    # Puede llamarse varias veces para agregar texto
    session.stop()             # Notifica al servidor que la entrada ha finalizado
    for chunk in session.audio_chunks():
        ...

synthesize() - sin streaming

Firma del método:
def synthesize(self, text: str, *, model: str = "cosyvoice-v1",
               voice: str = "longxiaochun", format: str = "mp3",
               sample_rate: int = 22050, volume: int = None,
               rate: float = None, pitch: float = None,
               language_hints: list = None, enable_ssml: bool = None,
               parameters: Dict = None, ...) -> bytes
Parámetros:
ParámetroTipoObligatorioDescripción
textstrSí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 espera y devuelve los datos de audio completos de una sola vez. Es más adecuada para textos cortos donde no se requiere un rendimiento estricto en tiempo real. synthesize y stream crean una nueva sesión en cada llamada; no es necesario reutilizar instancias.

stream() - streaming

Firma del método:
def stream(self, text: str, *, model: str, voice: str,
           format: str = "mp3", sample_rate: int = 22050, ...) -> Iterator[bytes]
Parámetros:
ParámetroTipoObligatorioDescripción
textstrSíEl texto completo a sintetizar. Longitud máxima: 20,000 caracteres.
Valor de retorno: Iterator[bytes], los datos de audio entregados fragmento a fragmento. Descripción: Síntesis por streaming que envía el texto completo de una sola vez y entrega el audio fragmento a fragmento (Iterator[bytes]). Es más adecuada para escenarios de síntesis de voz de texto corto que requieren un alto rendimiento en tiempo real. Para enviar texto en segmentos, utilice la sesión de streaming bidireccional (connect).

send_text() - entrada en streaming (método de sesión)

Envía texto en segmentos dentro de una sesión de streaming bidireccional (client.audio.tts.connect(...)). Firma del método:
def send_text(self, text: str) -> None
Parámetros: text es el segmento de texto actual a sintetizar. Llame a send_text varias veces para agregar texto. Máximo por llamada: 20,000 caracteres; máximo acumulado: 200,000 caracteres. El envío de texto y la recepción de audio deben ejecutarse de forma concurrente (utilícelo junto con audio_chunks()/events() y stop).

stop() - finalizar la entrada en streaming (método de sesión)

Firma del método:
def stop(self) -> None
Descripción: Notifica al servidor que se ha enviado todo el texto. Esta llamada no bloquea el hilo actual; el hilo de recepción debe seguir consumiendo audio_chunks()/events() 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.

cancel() - cancelar la síntesis por streaming (método de sesión)

Firma del método:
def cancel(self) -> None
Descripción: Cancela la tarea actual de síntesis de voz por streaming. Después de llamar a este método, el SDK finaliza inmediatamente la tarea actual. Tras la cancelación, la sesión actual ya no puede enviar texto; cree una nueva sesión para continuar la síntesis.
Limitaciones del modelo:
  • China (Pekín): Los modelos CosyVoice requieren la versión v2 o posterior.
  • Singapur: Los modelos CosyVoice no admiten esta función.

Métricas y respuestas de la sesión (atributos de sesión)

session.first_package_delay
session.usage
session.last_response
  • first_package_delay: float, el retraso en milisegundos desde el envío del texto hasta la recepción del primer fragmento de audio. Léalo después de que se complete la síntesis.
  • usage: dict, la información de uso de la tarea de síntesis más reciente.
  • last_response: dict, el mensaje de respuesta de la tarea de síntesis más reciente (con las claves header/payload). El request_id de la solicitud más reciente se puede obtener del header de session.last_response, lo que resulta útil para la solución de problemas y la correlación de registros.

Parámetros de solicitud

Los siguientes parámetros se configuran a través de los métodos synthesize/stream/connect de client.audio.tts para controlar el modelo, la voz, el formato y las características del audio (model, voice, format, sample_rate, volume, rate, pitch, language_hints y enable_ssml son parámetros con nombre; los parámetros restantes se pasan a través del diccionario parameters).
ParámetroTipoObligatorioDescripción
modelstrSíEl nombre del modelo.
voicestrSíLa voz utilizada para la síntesis de habla.
  • Voces del sistema: Consulte la lista de voces de CosyVoice
  • Voces clonadas: Voces personalizadas creadas mediante clonación de voz
  • Voces personalizadas: Voces personalizadas creadas mediante diseño de voz
formatstrNoFormato de codificación de audio.Valor predeterminado: mp3.Admite mp3, wav, pcm y otros formatos. La tasa de muestreo se establece mediante el parámetro sample_rate, con un valor predeterminado de 22050.
volumeintNoEl nivel de volumen.Valor predeterminado: 50.Valores válidos: [0, 100].
ratefloatNoLa velocidad del habla.Valor predeterminado: 1.0.Valores válidos: [0.5, 2.0].
pitchfloatNoEl tono.Valor predeterminado: 1.0.Valores válidos: [0.5, 2.0].
bit_rateintNoLa 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 bit_rate a través del diccionario parameters:
audio = client.audio.tts.synthesize(
    "Text to synthesize",
    model="cosyvoice-v3-plus",
    voice="longanyang",
    parameters={"bit_rate": 128},
)
word_timestamp_enabledboolNoEspecifica 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 lista de voces de CosyVoice. Las voces clonadas de otros modelos no admiten esta función.Configure word_timestamp_enabled a través del diccionario parameters:
audio = client.audio.tts.stream(
    "Text to synthesize",
    model="cosyvoice-v3-flash",
    voice="your_voice",  # Una voz del sistema o clonada que admita marcas de tiempo a nivel de palabra
    parameters={"word_timestamp_enabled": True},
)
seedintNoUna 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_hintslist[str]No
  • Este parámetro es una matriz, pero la versión actual solo procesa el primer elemento. Pase un único valor.
  • Este parámetro especifica el idioma de destino para la síntesis de voz. No está relacionado con el idioma de la muestra de audio utilizada en la clonación de voz. Para establecer el idioma de origen de una tarea de clonación, consulte la referencia de la API de clonación de voz.
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:
  • Pronunciación inesperada de dígitos: "hola, esto es 110" se lee como "hola, esto es uno cero" en lugar de la pronunciación china esperada
  • Pronunciación incorrecta de símbolos: "@" se lee como su equivalente en chino en lugar de "arroba"
  • Mala calidad de síntesis en idiomas minoritarios con resultados poco naturales
  • zh: Chino
  • en: Inglés
  • fr: Francés
  • de: Alemán
  • ja: Japonés
  • ko: Coreano
  • ru: Ruso
  • pt: Portugués
  • th: Tailandés
  • id: Indonesio
  • vi: Vietnamita
  • es: Español
  • it: Italiano
  • ms: Malayo
  • fil: Filipino
  • ar: Árabe
instructionstrNoControla 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_tagboolNoEspecifica 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.
Solo cosyvoice-v3-flash, cosyvoice-v3-plus y cosyvoice-v2 admiten esta función.
Configure enable_aigc_tag, aigc_propagator y aigc_propagate_id a través del diccionario parameters:
audio = client.audio.tts.synthesize(
    "Text to synthesize",
    model="cosyvoice-v3-plus",
    voice="longanyang",
    parameters={
        "enable_aigc_tag": True,
        "aigc_propagator": "your_propagator",
        "aigc_propagate_id": "your_propagate_id"
    },
)
aigc_propagatorstrNoEstablece 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: Alibaba Cloud UID.
Solo cosyvoice-v3-flash, cosyvoice-v3-plus y cosyvoice-v2 admiten esta función.
Se configura a través del diccionario parameters. Consulte el ejemplo de enable_aigc_tag.
aigc_propagate_idstrNoEstablece 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.
Solo cosyvoice-v3-flash, cosyvoice-v3-plus y cosyvoice-v2 admiten esta función.
Se configura a través del diccionario parameters. Consulte el ejemplo de enable_aigc_tag.
hot_fixdictNoConfigura correcciones de pronunciación y reemplazos de texto aplicados antes de la síntesis.
Esta función no es compatible con cosyvoice-v2.
Parámetros:
  • pronunciation: Pronunciación personalizada. Especifica anotaciones pinyin para palabras con el fin de corregir pronunciaciones predeterminadas inexactas.
  • replace: Reemplazo de texto. Reemplaza palabras específicas con texto de destino antes de la síntesis. El texto reemplazado se utiliza como entrada real de la síntesis.
Ejemplo:
audio = client.audio.tts.synthesize(
    "Text to synthesize",
    model="cosyvoice-v3.5-plus",
    voice="cosyvoice-v3.5-plus-vd-announcer-xxxxxx", # Voz
    parameters={
        "hot_fix": {
            "pronunciation": [{"weather": "tian1 qi4"}],
            "replace": [{"today": "gold day"}]
        }
    },
)
enable_markdown_filterboolNo
Solo 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:
  • true: Habilitar filtrado de Markdown
  • false: Deshabilitar filtrado de Markdown
Configure enable_markdown_filter a través del diccionario parameters:
audio = client.audio.tts.synthesize(
    "Text to synthesize",
    model="cosyvoice-v3-flash",
    voice="your_voice",  # Una voz clonada de cosyvoice-v3-flash
    parameters={"enable_markdown_filter": True},
)

Iteración de sesión y eventos

La síntesis por streaming ya no utiliza interfaces de devolución de llamada: el audio y los eventos del servidor se reciben mediante los métodos de iteración de la sesión. stream()/synthesize() no requieren gestión de sesiones; el ciclo de vida de una sesión de streaming bidireccional (client.audio.tts.connect(...)) es: entrar en el contexto with para establecer la conexión automáticamente → múltiples llamadas a send_text() → stop() → leer todos los resultados → salir del contexto para cerrar la conexión automáticamente.

audio_chunks() - iterar los datos de audio

Firma del método:
def audio_chunks(self) -> Iterator[bytes]
Valor de retorno: Iterator[bytes], los datos binarios de audio entregados fragmento a fragmento, en el formato especificado por el parámetro format. Descripción: Itere en el hilo de recepción para recibir los datos de audio fragmento a fragmento; durante la síntesis se entregan múltiples fragmentos. Escriba los datos en un archivo o envíelos a un dispositivo de reproducción. Una sesión solo permite un lector de events() o audio_chunks().

events() - iterar los eventos del servidor

Firma del método:
def events(self) -> Generator[Union[Dict, bytes], None, None]
Valor de retorno: Devuelve tanto eventos de respuesta del servidor (dict, que contienen header (información de la solicitud) y payload (información de salida)) como bytes de audio. El campo payload.output contiene el tipo de evento, el texto original y otra información. Consulte campo output en los mensajes de events(). Descripción: Itere sobre las respuestas del servidor en el hilo de recepción. Las respuestas contienen la información de salida de los eventos de síntesis (tipo de evento, texto original, información de la oración, etc.); acceda a payload.output directamente para obtener más detalles.

Manejo de errores

Cuando se produce un error durante la síntesis, la capa WebSocket genera una excepción DashScopeError y la conexión se cierra automáticamente después de que se genere la excepción. Utilice try/except en el lado de envío/recepción para capturar y registrar errores para la solución de problemas:
from dashscope.v2 import DashScopeError

try:
    ...
except DashScopeError as e:
    print(e.code, e.message, e.request_id)

Ciclo de vida de la sesión

  • La conexión se establece automáticamente al entrar en el contexto with (puede inicializar flujos de salida de audio o abrir recursos de archivos con antelación).
  • Después de que todo el texto se sintetice y se hayan entregado todos los datos de audio, la iteración de events()/audio_chunks() finaliza; después de eso, puede leer métricas de rendimiento como first_package_delay.
  • La conexión se cierra automáticamente al salir del contexto with (puede liberar dispositivos de reproducción de audio y otros recursos posteriormente).

Campo output en los mensajes de events()

El dict de evento entregado por el iterador events() de la sesión 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:
CampoTipoDescripción
typestrTipo 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_textstrEl texto original de la oración actual. Se devuelve en los eventos sentence-begin y sentence-end.
sentencedictInformació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:
def handle_event(event):
    output = (event.get('payload') or {}).get('output') or {}
    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 proporciona las interfaces clave para la síntesis de voz y admite los siguientes modos de llamada:
  • Sin 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 recibe los datos iterando los fragmentos de audio entregados por stream. Ideal para la síntesis de voz de texto corto que requiere un alto rendimiento en tiempo real.
  • Streaming bidireccional: Una llamada no bloqueante que envía texto en múltiples segmentos y recibe en tiempo real el flujo de audio sintetizado incrementalmente iterando los métodos audio_chunks()/events() de la sesión. Ideal para la síntesis de voz de texto largo que requiere un alto rendimiento en tiempo real.
  • Sin streaming
  • Streaming unidireccional
  • Streaming bidireccional
El texto enviado en una sola llamada no debe exceder los 20,000 caracteres. Superar este límite provoca una excepción DashScopeError.
synthesize y stream crean una nueva sesión en cada llamada; no es necesario reutilizar instancias.
# coding=utf-8

import os

import dashscope

# Las API Key de las regiones de Singapur y Pekín son diferentes. Obtenga su API Key: https://www.alibabacloud.com/help/model-studio/get-api-key
# Si no se ha configurado la variable de entorno, sustituya la siguiente línea por su API Key de Model Studio: api_key="sk-xxx"
# La siguiente configuración corresponde a la región de Singapur. Sustituya {WorkspaceId} por el ID real de su espacio de trabajo. El valor de region varía según la región.
client = dashscope.Client(
    api_key=os.environ.get('DASHSCOPE_API_KEY'),
    workspace="{WorkspaceId}",
    region="ap-southeast-1",
)

# Modelo
model = "cosyvoice-v3-plus"
# Voz
voice = "longanyang"

# Envíe el texto a sintetizar y obtenga el audio binario
audio = client.audio.tts.synthesize("How is the weather today?", model=model, voice=voice)

# Guarde el audio en un archivo local
with open('output.mp3', 'wb') as f:
    f.write(audio)