跳转到主要内容
语音合成

实时语音合成

实时流式语音合成

实时语音合成基于 WebSocket 协议将文本实时转换为自然语音。千问云提供 CosyVoice、Qwen-TTS 和 Sambert 系列模型,支持流式输入输出,并提供声音复刻、声音设计及精细化音频控制能力,适用于语音助手、有声读物、智能客服等场景。

核心功能

  • 实时生成高保真语音,支持中英等多语种自然发声
  • 提供声音复刻声音设计两种音色定制方式
  • 支持流式输入输出,首包延迟低,适用于实时对话场景
  • 可调节语速、语调、音量与码率,精细控制语音表现
  • 兼容主流音频格式(PCM、WAV、MP3、Opus),最高支持48kHz采样率输出
  • 支持指令控制,可通过自然语言指令控制语音表现力(仅Qwen-TTS Instruct系列及部分CosyVoice模型)

适用范围

支持的模型 调用以下模型时,请使用 API Key
  • CosyVoice: cosyvoice-v3.5-plus, cosyvoice-v3.5-flash, cosyvoice-v3-plus, cosyvoice-v3-flash, cosyvoice-v2, cosyvoice-v1
  • Qwen-TTS: qwen3-tts-flash-realtime, qwen3-tts-instruct-flash-realtime, qwen3-tts-vd-realtime, qwen3-tts-vc-realtime, qwen-tts-realtime
  • Sambert: 详情请参见语音合成模型列表
完整的模型列表和版本信息,请参见语音合成模型列表

快速开始

在编写代码前,请根据业务场景选择合适的调用方式:
调用方式适用场景流式支持
非流式(同步)批量任务、短文本、生成完整音频文件
流式输出(单向)对首包延迟敏感的实时应用
流式输入+输出(双向,WebSocket)对话式AI、LLM语音输出、交互式语音助手
如需最低延迟,推荐使用流式输出搭配 PCM 格式。PCM 无需编码开销,可直接送入音频设备播放。 下面是调用API的示例代码。更多常用场景的代码示例,请参见 GitHub 获取 API Key设置为环境变量。如需使用 SDK,请先安装 SDK
  • CosyVoice
  • Qwen-TTS-Realtime
cosyvoice-v3.5-pluscosyvoice-v3.5-flash 模型专门用于声音设计和声音复刻场景(无系统音色)。在使用它们进行语音合成之前,请先参见CosyVoice声音复刻/设计API创建目标音色。创建完成后,只需将代码中的 voice 字段更新为您的音色 ID,并将 model 字段指定为对应模型,即可正常运行。
更多代码示例请参见 GitHub
  • 使用系统音色进行语音合成
以下示例演示如何使用系统音色(参见CosyVoice音色列表)进行语音合成。如需非实时合成(发送完整文本,接收完整音频),请参见非实时语音合成

将大模型生成的文本实时转为语音并播放

将 Qwen 模型(qwen3.5-flash)的输出文本实时合成语音,并在本地设备播放。
  • Python
  • Java
运行 Python 示例前,请通过 pip 安装第三方音频播放库。
# coding=utf-8
# pyaudio 安装说明:
# APPLE Mac OS X
#   brew install portaudio
#   pip install pyaudio
# Debian/Ubuntu
#   sudo apt-get install python-pyaudio python3-pyaudio
#   or
#   pip install pyaudio
# CentOS
#   sudo yum install -y portaudio portaudio-devel && pip install pyaudio
# Microsoft Windows
#   python -m pip install pyaudio

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


from http import HTTPStatus
from dashscope import Generation

# 如果未配置环境变量,请将下行替换为您的 API key:dashscope.api_key = "sk-xxx"
dashscope.api_key = os.environ.get('DASHSCOPE_API_KEY')

dashscope.base_websocket_api_url='wss://dashscope.aliyuncs.com/api-ws/v1/inference'

# cosyvoice-v3-flash/cosyvoice-v3-plus:可选用 longanyang 等音色。
# 每种音色支持的语言不同。合成日语、韩语等非中文语言时,请选择支持相应语言的音色。详见 CosyVoice 音色列表。
model = "cosyvoice-v3-flash"
voice = "longanyang"


class Callback(ResultCallback):
  _player = None
  _stream = None

  def on_open(self):
    print("websocket is open.")
    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 task complete successfully.")

  def on_error(self, message: str):
    print(f"speech synthesis task failed, {message}")

  def on_close(self):
    print("websocket is closed.")
    # 停止播放
    self._stream.stop_stream()
    self._stream.close()
    self._player.terminate()

  def on_event(self, message):
    print(f"recv speech synthsis message {message}")

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


def synthesizer_with_llm():
  callback = Callback()
  synthesizer = SpeechSynthesizer(
    model=model,
    voice=voice,
    format=AudioFormat.PCM_22050HZ_MONO_16BIT,
    callback=callback,
  )

  messages = [{"role": "user", "content": "Please introduce yourself"}]
  responses = Generation.call(
    model="qwen3.5-flash",
    messages=messages,
    result_format="message",  # 设置返回格式为 message
    stream=True,  # 启用流式输出
    incremental_output=True,  # 启用增量输出
  )
  for response in responses:
    if response.status_code == HTTPStatus.OK:
      print(response.output.choices[0]["message"]["content"], end="")
      synthesizer.streaming_call(response.output.choices[0]["message"]["content"])
    else:
      print(
        "Request id: %s, Status code: %s, error code: %s, error message: %s"
        % (
          response.request_id,
          response.status_code,
          response.code,
          response.message,
        )
      )
  synthesizer.streaming_complete()
  print('requestId: ', synthesizer.get_last_request_id())


if __name__ == "__main__":
  synthesizer_with_llm()

通过回调函数流式接收音频

发送完整文本,通过回调函数增量接收音频数据。适用于短文本场景,可在不阻塞主线程的情况下实现低延迟音频输出。
  • Python
  • Java
# coding=utf-8

import os
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:dashscope.api_key = "sk-xxx"
dashscope.api_key = os.environ.get('DASHSCOPE_API_KEY')

dashscope.base_websocket_api_url='wss://dashscope.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: {}, first-package delay: {} 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):
    pass

  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?")

流式文本实时合成

增量发送文本片段,通过回调函数实时接收音频数据。这种双向流式方式适用于长文本或与大语言模型集成等文本分段到达的场景。
  • Python
  • Java
# 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
# Windows 系统:
#   python -m pip install pyaudio

import os
import time
import pyaudio
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:dashscope.api_key = "sk-xxx"
dashscope.api_key = os.environ.get('DASHSCOPE_API_KEY')

dashscope.base_websocket_api_url='wss://dashscope.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):
    pass

  def on_data(self, data: bytes) -> None:
    print(get_timestamp() + " 音频二进制数据长度:" + str(len(data)))
    self._stream.write(data)


callback = Callback()

test_text = [
  "流式文本语音合成 SDK,",
  "可以将输入文本",
  "转换为二进制音频数据。",
  "相较于非流式语音合成,",
  "流式合成具有更优的实时性能。",
  "用户在输入的同时即可听到近乎同步的音频输出,",
  "大幅提升交互体验",
  "并减少等待时间。",
  "非常适合与大语言模型(LLM)集成,",
  "将文本流式传输进行语音合成。",
]

# 实例化 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: {}, first-package delay: {} ms'.format(
  synthesizer.get_last_request_id(),
  synthesizer.get_first_package_delay()))

Qwen-TTS 进阶功能

以下功能仅适用于 Qwen-TTS 系列模型。

Qwen-TTS 交互模式

Qwen-TTS Realtime API 提供两种 WebSocket 交互模式,通过 session.mode 参数切换:
  • server_commit 模式:服务端智能处理文本分段和合成时机,适合大段文本的连续合成场景。客户端只需持续追加文本,无需关注切分和提交。
  • commit 模式:客户端主动提交文本缓冲区以触发合成,适合需要精确控制合成时机的场景(如对话式 AI 逐轮合成)。
详细的 WebSocket 事件生命周期和连接复用方式,请参见实时语音合成-千问API参考

交互流程

  • CosyVoice
  • Qwen-TTS-Realtime
CosyVoice 使用基于 WebSocket 的流式协议。协议详情请参见 CosyVoice WebSocket API 参考

指令控制

  • CosyVoice
  • Qwen-TTS-Realtime
支持的模型cosyvoice-v3.5-pluscosyvoice-v3.5-flashcosyvoice-v3-flash
  • cosyvoice-v3.5-pluscosyvoice-v3.5-flash:无系统音色,仅支持使用声音设计或声音复刻音色,可输入任意指令控制合成效果(如情感、语速等)。
  • cosyvoice-v3-flash 的声音设计或声音复刻音色:可输入任意指令控制合成效果。
  • cosyvoice-v3-flash 的系统音色:指令必须使用固定格式和内容,详情请参见CosyVoice音色列表
支持语言
  • cosyvoice-v3.5-pluscosyvoice-v3.5-flash:中文、英文、法语、德语、日语、韩语、俄语、葡萄牙语、泰语、印尼语、越南语
  • cosyvoice-v3-flash:中文、英文、法语、德语、日语、韩语、俄语
长度限制:100 字符。汉字(包括简体/繁体汉字、日文汉字和韩文汉字)按 2 个字符计算,其他所有字符(如标点符号、字母、数字、日韩文假名/谚文等)均按 1 个字符计算。

声音定制

  • CosyVoice
  • Qwen-TTS-Realtime

声音复刻:输入音频格式要求

高质量的输入音频是实现优秀复刻效果的基础。
项目要求
支持格式WAV(16-bit)、MP3、M4A
音频时长推荐:10~20秒。最长:60秒。
文件大小≤ 10 MB
采样率≥ 16 kHz
声道单声道或立体声。立体声音频仅处理第一声道,请确保第一声道包含清晰的人声。
内容音频必须包含至少5秒的连续、清晰人声,不含背景音。其余部分仅允许短暂停顿(≤ 2秒)。整段音频应无背景音乐、噪音或其他人声,以确保核心语音内容的高质量。请使用正常说话的音频作为输入,不要上传歌曲或演唱音频,以确保复刻效果的准确性和可用性。

声音设计:编写高质量的声音描述

限制条件

编写声音描述(voice_prompt)时,请遵循以下技术约束:
  • 长度限制voice_prompt 的内容不得超过500个字符。
  • 支持语言:描述文本仅支持中文和英文。

核心原则

voice_prompt 用于引导模型生成具有特定特征的声音。编写声音描述时,请遵循以下核心原则:
  • 具体而非模糊:使用能够描绘具体声音特质的词语,如"低沉"、"清脆"、"语速偏快"。避免使用"好听"、"普通"等主观且缺乏信息量的词汇。
  • 多维而非单一:优秀的描述通常结合多个维度(如性别、年龄、情感等)。单一维度的描述(如仅"女声")过于宽泛,难以生成特色鲜明的效果。
  • 客观而非主观:专注于声音本身的物理和感知特征,而不是个人喜好。例如,用"音调偏高,带有活力"代替"我最喜欢的声音"。
  • 原创而非模仿:请描述声音的特质,而不是要求模仿特定人物(如名人、演员)。此类请求涉及版权风险,且模型不支持直接模仿。
  • 简洁而非冗余:确保每个词都有其意义。避免重复使用同义词或无意义的强调词(如"非常非常棒的声音")。

描述维度参考

维度示例
性别男性、女性、中性
年龄儿童(5-12岁)、青少年(13-18岁)、青年(19-35岁)、中年(36-55岁)、老年(55岁以上)
音调高、中、低、偏高、偏低
语速快、中、慢、偏快、偏慢
情感欢快、沉稳、温柔、严肃、活泼、冷酷、舒缓
特质磁性、清脆、沙哑、浑厚、甜美、浓郁、有力
用途新闻播报、广告配音、有声读物、动画角色、语音助手、纪录片解说

示例对比

好的案例
  • "年轻活泼的女声,语速较快,带有明显的上扬语调,适合介绍时尚产品。"
    • 分析:该描述结合了年龄、性格、语速和语调,并指定了使用场景,形成了清晰的声音画像。
  • "沉稳的中年男声,语速偏慢,低沉而富有磁性,适合新闻播报或纪录片解说。"
    • 分析:该描述清晰定义了性别、年龄段、语速、音质和用途。
  • "可爱的童声,约8岁女孩,说话略带稚气,适合动画角色配音。"
    • 分析:该描述精准定位了年龄和声音特质(稚气),且有明确用途。
  • "温柔知性的女性,约30岁,语气平和,适合有声读物朗读。"
    • 分析:该描述通过"知性"、"平和"等词有效传达了声音的情感和风格。
不好的案例及改进建议
不好的案例主要问题改进建议
"好听的声音"描述过于模糊和主观,缺乏可操作的细节。添加具体维度,如"音色清亮的年轻女声,语调轻柔"。
"像某明星的声音"涉及版权风险,模型不支持直接模仿。提取声音特征进行描述,如"成熟、磁性、语速沉稳的男声"。
"非常非常非常好听的女声"描述冗余,重复用词无法帮助定义声音。去除重复,添加有效描述,如"20~24岁的女声,音色轻快,语调活泼,音质甜美"。
123456无效输入,无法解析为声音特征。请提供有意义的文字描述,参见上方推荐示例。

API 参考

系统音色

  • CosyVoice
  • Qwen-TTS-Realtime

常见问题

  • CosyVoice
  • Qwen-TTS-Realtime
  • 将多音字替换为同音字,可快速解决发音问题。
  • 使用语音合成标记语言(SSML)来控制发音。Sambert和CosyVoice都支持SSML。
  1. 确认音色状态:调用CosyVoice声音复刻/设计API接口,查看音色 status 是否为 OK
  2. 检查模型版本一致性:确保复刻音色时使用的 target_model 参数与语音合成时的 model 参数完全一致。例如复刻时使用 cosyvoice-v3-plus,合成时也必须使用 cosyvoice-v3-plus
  3. 验证源音频质量:检查复刻音色时使用的源音频是否符合音频要求(音频时长10-20秒、音质清晰、无背景噪音)。
  4. 检查请求参数:确认语音合成时请求参数 voice 设置为复刻音色的ID。
如果复刻音色后合成的语音出现语音播放不完整、合成效果不稳定、语音中包含异常停顿或静音段等问题,可能是源音频质量不符合要求。解决方案:
  • 检查音频连续性:确保源音频中语音内容连续,避免长时间停顿或静音段(超过2秒)。
  • 检查语音活动比例:确保有效语音占音频总时长的60%以上。
  • 验证音频质量:音频时长10-20秒(推荐15秒左右),发音清晰、语速平稳,无背景噪音、回音、杂音。