CosyVoice声音复刻服务基于生成式语音大模型,使用10~20秒音频样本即可生成高度相似且自然的定制声音,无需传统训练过程。
音频要求
高质量的输入音频是获得优质复刻效果的基础。
项目 | 要求 |
支持格式 | WAV (16bit), MP3, M4A |
音频时长 | 10 ~ 20 秒 |
文件大小 | ≤ 10 MB |
采样率 | ≥ 16 kHz |
声道 | 单声道 / 双声道 |
内容 | 至少包含一段5秒以上的连续、清晰、无背景音的朗读 |
语言 | 中、英 |
快速开始
1. 版本选择与准备工作
根据业务需求选择合适的模型版本,并完成必要的准备工作。
版本选择指南
在资源与预算允许的情况下,推荐使用cosyvoice-v3-plus以获得最佳效果。
版本 | 适用场景 | 申请状态 |
cosyvoice-v3-plus | 追求最佳音质与表现力,预算充足 | 需申请,申请通过后将发放免费调用额度 |
cosyvoice-v3 | 平衡效果与成本,综合性价比高 | 需申请,申请通过后将发放免费调用额度 |
cosyvoice-v2 | 兼容旧版或低要求场景 | 直接使用 |
cosyvoice-v1 | 兼容旧版或低要求场景 | 直接使用 |
准备工作
获取API Key:获取API Key,为安全起见,推荐将API Key配置到环境变量。
安装SDK:确保已安装最新版DashScope SDK。
准备音频URL:将符合音频要求的音频文件上传至公网可访问的位置,如阿里云对象存储OSS,并确保URL可公开访问。
2. 端到端示例:从复刻到合成
以下Python示例将引导完成从创建音色到使用该音色进行语音合成的全过程。
关键原则:声音复刻时使用的模型 (target_model) 必须与后续进行语音合成时使用的模型 (model) 保持一致。
import os
import time
import dashscope
from dashscope.audio.tts_v2 import VoiceEnrollmentService, SpeechSynthesizer
# 1. 环境准备
# 推荐通过环境变量配置API Key
# export DASHSCOPE_API_KEY="sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
dashscope.api_key = os.getenv("DASHSCOPE_API_KEY")
if not dashscope.api_key:
raise ValueError("DASHSCOPE_API_KEY environment variable not set.")
# 2. 定义复刻参数
TARGET_MODEL = "cosyvoice-v2"
# 为音色起一个有意义的前缀
VOICE_PREFIX = "myvoice" # 仅允许数字和小写字母,小于十个字符
# 公网可访问音频URL
AUDIO_URL = "https://modelscope.oss-cn-beijing.aliyuncs.com/test/audios/voice_enrollment.wav" # 示例URL,请替换为自己的
# 3. 创建音色 (异步任务)
print("--- Step 1: Creating voice enrollment ---")
service = VoiceEnrollmentService()
try:
voice_id = service.create_voice(
target_model=TARGET_MODEL,
prefix=VOICE_PREFIX,
url=AUDIO_URL
)
print(f"Voice enrollment submitted successfully. Request ID: {service.get_last_request_id()}")
print(f"Generated Voice ID: {voice_id}")
except Exception as e:
print(f"Error during voice creation: {e}")
raise e
# 4. 轮询查询音色状态
print("\n--- Step 2: Polling for voice status ---")
max_attempts = 30
poll_interval = 10 # 秒
for attempt in range(max_attempts):
try:
voice_info = service.query_voice(voice_id=voice_id)
status = voice_info.get("status")
print(f"Attempt {attempt + 1}/{max_attempts}: Voice status is '{status}'")
if status == "OK":
print("Voice is ready for synthesis.")
break
elif status == "UNDEPLOYED":
print(f"Voice processing failed with status: {status}. Please check audio quality or contact support.")
raise RuntimeError(f"Voice processing failed with status: {status}")
# 对于 "DEPLOYING" 等中间状态,继续等待
time.sleep(poll_interval)
except Exception as e:
print(f"Error during status polling: {e}")
time.sleep(poll_interval)
else:
print("Polling timed out. The voice is not ready after several attempts.")
raise RuntimeError("Polling timed out. The voice is not ready after several attempts.")
# 5. 使用复刻音色进行语音合成
print("\n--- Step 3: Synthesizing speech with the new voice ---")
try:
synthesizer = SpeechSynthesizer(model=TARGET_MODEL, voice=voice_id)
text_to_synthesize = "恭喜,已成功复刻并合成了属于自己的声音!"
# call()方法返回二进制音频数据
audio_data = synthesizer.call(text_to_synthesize)
print(f"Speech synthesis successful. Request ID: {synthesizer.get_last_request_id()}")
# 6. 保存音频文件
output_file = "my_custom_voice_output.mp3"
with open(output_file, "wb") as f:
f.write(audio_data)
print(f"Audio saved to {output_file}")
except Exception as e:
print(f"Error during speech synthesis: {e}")API参考
提供Python、Java SDK及RESTful API三种调用方式。使用不同 API 时,请确保使用同一账号进行操作。
创建音色
创建一个新的定制音色。
Python SDK
接口说明
def create_voice(self, target_model: str, prefix: str, url: str) -> str:
'''
创建一个新的定制音色。
param: target_model 声音复刻所使用的模型。
param: prefix 音色自定义前缀,仅允许数字和小写字母,长度小于10个字符。该前缀将用于构建最终的音色ID。生成的voice_id格式为:模型名-前缀-唯一标识,如cosyvoice-v2-myvoice-xxxxxxxx。
param: url 用于复刻音色的音频文件URL,要求公网可访问。
return: voice_id 新创建的音色ID
'''请求示例
from dashscope.audio.tts_v2 import VoiceEnrollmentService
service = VoiceEnrollmentService()
# 避免频繁调用。每次调用都会创建新音色,达到配额上限后将无法创建。
voice_id = service.create_voice(
target_model='cosyvoice-v2',
prefix='myvoice',
url='https://your-audio-file-url'
)
print(f"Request ID: {service.get_last_request_id()}")
print(f"Voice ID: {voice_id}")Java SDK
接口说明
/**
* 创建一个新的定制音色。
*
* @param targetModel 声音复刻所使用的模型。
* @param prefix 音色自定义前缀,仅允许数字和小写字母,长度小于10个字符。该前缀将用于构建最终的音色ID。生成的voice_id格式为:模型名-前缀-唯一标识,如cosyvoice-v2-myvoice-xxxxxxxx。
* @param url 用于复刻音色的音频文件URL,要求公网可访问。
* @return Voice 新创建的音色。
* @throws NoApiKeyException 如果apikey为空。
* @throws InputRequiredException 如果必须参数为空。
*/
public Voice createVoice(String targetModel, String prefix, String url) throws NoApiKeyException, InputRequiredException请求示例
import com.alibaba.dashscope.audio.ttsv2.enrollment.Voice;
import com.alibaba.dashscope.audio.ttsv2.enrollment.VoiceEnrollmentService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Main {
private static final Logger logger = LoggerFactory.getLogger(Main.class);
public static void main(String[] args) {
String apiKey = System.getenv("DASHSCOPE_API_KEY");
String targetModel = "cosyvoice-v2";
String prefix = "myvoice";
String fileUrl = "https://your-audio-file-url";
try {
VoiceEnrollmentService service = new VoiceEnrollmentService(apiKey);
Voice myVoice = service.createVoice(targetModel, prefix, fileUrl);
logger.info("Voice creation submitted. Request ID: {}", service.getLastRequestId());
logger.info("Generated Voice ID: {}", myVoice.getVoiceId());
} catch (Exception e) {
logger.error("Failed to create voice", e);
}
}
}RESTful API
基本信息
URL | |
请求方法 | POST |
请求头 | |
消息体 | 包含所有请求参数的消息体如下,对于可选字段,在实际业务中可根据需求省略: |
请求参数
参数 | 类型 | 默认值 | 是否必须 | 说明 |
model | string | - | 是 | 固定为 |
action | string | - | 是 | 固定为 |
target_model | string | - | 是 | 声音复刻所使用的模型,推荐 'cosyvoice-v3' 或 'cosyvoice-v3-plus'。 |
prefix | string | - | 是 | 音色自定义前缀,仅允许数字和小写字母,长度小于10个字符。 该前缀将用于构建最终的音色ID。生成的 |
url | string | - | 是 | 用于复刻音色的音频文件URL,要求公网可访问。 |
响应参数
参数 | 类型 | 说明 |
voice_id | string | 新创建的音色ID |
查询所有音色
分页查询账户下已创建的所有音色。
Python SDK
音色状态有三种:
DEPLOYING: 审核中
OK:审核通过,可调用
UNDEPLOYED:审核不通过,不可调用
接口说明
def list_voices(self, prefix=None, page_index: int = 0, page_size: int = 10) -> List[dict]:
'''
查询已创建的所有音色
param: prefix 音色自定义前缀,仅允许数字和小写字母,长度小于10个字符。
param: page_index 查询的页索引
param: page_size 查询页大小
return: List[dict] 音色列表,包含每个音色的id,创建时间,修改时间,状态。
'''请求示例
from dashscope.audio.tts_v2 import VoiceEnrollmentService
service = VoiceEnrollmentService()
# 按前缀筛选,或设为None查询所有
voices = service.list_voices(prefix='myvoice', page_index=0, page_size=10)
print(f"Request ID: {service.get_last_request_id()}")
print(f"Found voices: {voices}")响应示例
[
{
"gmt_create": "2024-09-13 11:29:41",
"voice_id": "yourVoiceId",
"gmt_modified": "2024-09-13 11:29:41",
"status": "OK"
},
{
"gmt_create": "2024-09-13 13:22:38",
"voice_id": "yourVoiceId",
"gmt_modified": "2024-09-13 13:22:38",
"status": "OK"
}
]响应参数
参数 | 类型 | 说明 |
voice_id | string | 音色ID。 |
gmt_create | string | 创建音色的时间。 |
gmt_modified | string | 修改音色的时间。 |
status | string | 状态。
|
Java SDK
音色状态有三种:
DEPLOYING: 审核中
OK:审核通过,可调用
UNDEPLOYED:审核不通过,不可调用
接口说明
/**
* 查询已创建的所有音色 默认的页索引为0,默认的页大小为10
*
* @param prefix 音色自定义前缀,仅允许数字和小写字母,长度小于10个字符。可以为null。
* @return Voice[] 音色对象数组
* @throws NoApiKeyException 如果apikey为空
* @throws InputRequiredException 如果必须参数为空
*/
public Voice[] listVoice(String prefix) throws NoApiKeyException, InputRequiredException
/**
* 查询已创建的所有音色
*
* @param prefix 音色自定义前缀,仅允许数字和小写字母,长度小于10个字符。
* @param pageIndex 查询的页索引
* @param pageSize 查询的页大小
* @return Voice[] 音色对象数组
* @throws NoApiKeyException 如果apikey为空
* @throws InputRequiredException 如果必须参数为空
*/
public Voice[] listVoice(String prefix, int pageIndex, int pageSize) throws NoApiKeyException, InputRequiredException请求示例
需要引入第三方库com.google.gson.Gson。
import com.alibaba.dashscope.audio.ttsv2.enrollment.Voice;
import com.alibaba.dashscope.audio.ttsv2.enrollment.VoiceEnrollmentService;
import com.alibaba.dashscope.exception.InputRequiredException;
import com.alibaba.dashscope.exception.NoApiKeyException;
import com.google.gson.Gson
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Main {
public static String apiKey = System.getenv("DASHSCOPE_API_KEY"); // 如果您没有配置环境变量,请在此处用您的API-KEY进行替换
private static String prefix = "myvoice"; // 请按实际情况进行替换
private static final Logger logger = LoggerFactory.getLogger(Main.class);
public static void main(String[] args)
throws NoApiKeyException, InputRequiredException {
VoiceEnrollmentService service = new VoiceEnrollmentService(apiKey);
// 查询音色
Voice[] voices = service.listVoice(prefix, 0, 10);
logger.info("List successful. Request ID: {}", service.getLastRequestId());
logger.info("Voices Details: {}", new Gson().toJson(voices));
}
}响应示例
[
{
"gmt_create": "2024-09-13 11:29:41",
"voice_id": "yourVoiceId",
"gmt_modified": "2024-09-13 11:29:41",
"status": "OK"
},
{
"gmt_create": "2024-09-13 13:22:38",
"voice_id": "yourVoiceId",
"gmt_modified": "2024-09-13 13:22:38",
"status": "OK"
}
]响应参数
参数 | 类型 | 说明 |
voice_id | string | 音色ID。 |
gmt_create | string | 创建音色的时间。 |
gmt_modified | string | 修改音色的时间。 |
status | string | 状态。
|
RESTful API
基本信息
URL | |
请求方法 | POST |
请求头 | |
消息体 | 包含所有请求参数的消息体如下,对于可选字段,在实际业务中可根据需求省略: |
请求参数
参数 | 类型 | 默认值 | 是否必须 | 说明 |
model | string | - | 是 | 固定为 |
action | string | - | 是 | 固定为 |
prefix | string | null | 否 | 音色自定义前缀,仅允许数字和小写字母,长度小于10个字符。 |
page_index | integer | 0 | 否 | 页码索引,从0开始计数。 |
page_size | integer | 10 | 否 | 每页包含数据条数。 |
响应参数
参数 | 类型 | 说明 |
voice_id | string | 音色ID。 |
gmt_create | string | 创建音色的时间。 |
gmt_modified | string | 修改音色的时间。 |
status | string | 状态。
|
查询指定音色
获取特定音色的详细信息
Python SDK
接口说明
def query_voice(self, voice_id: str) -> List[str]:
'''
查询指定音色的详细信息
param: voice_id 需要查询的音色ID
return: List[str] 音色详细信息,包含状态、创建时间、音频链接等
'''请求示例
from dashscope.audio.tts_v2 import VoiceEnrollmentService
service = VoiceEnrollmentService()
voice_id = 'cosyvoice-v2-myvoice-xxxxxxxx'
voice_details = service.query_voice(voice_id=voice_id)
print(f"Request ID: {service.get_last_request_id()}")
print(f"Voice Details: {voice_details}")响应示例
{
"gmt_create": "2024-09-13 11:29:41",
"resource_link": "https://yourAudioFileUrl",
"target_model": "cosyvoice-v2-plus",
"gmt_modified": "2024-09-13 11:29:41",
"status": "OK"
}响应参数
参数 | 类型 | 说明 |
resource_link | string | 被复刻的音频的URL。 |
target_model | string | 声音复刻所使用的模型。 |
gmt_create | string | 创建音色的时间。 |
gmt_modified | string | 修改音色的时间。 |
status | string | 状态。
|
Java SDK
接口说明
/**
* 查询指定音色的详细信息
*
* @param voiceId 需要查询的音色ID
* @return Voice 音色详细信息,包含状态、创建时间、音频链接等
* @throws NoApiKeyException 如果apikey为空
* @throws InputRequiredException 如果必须参数为空
*/
public Voice queryVoice(String voiceId) throws NoApiKeyException, InputRequiredException请求示例
需要引入第三方库com.google.gson.Gson。
import com.alibaba.dashscope.audio.ttsv2.enrollment.Voice;
import com.alibaba.dashscope.audio.ttsv2.enrollment.VoiceEnrollmentService;
import com.alibaba.dashscope.exception.InputRequiredException;
import com.alibaba.dashscope.exception.NoApiKeyException;
import com.google.gson.Gson;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Main {
public static String apiKey = System.getenv("DASHSCOPE_API_KEY"); // 如果您没有配置环境变量,请在此处用您的API-KEY进行替换
private static String voiceId = "cosyvoice-v2-myvoice-xxx"; // 请按实际情况进行替换
private static final Logger logger = LoggerFactory.getLogger(Main.class);
public static void main(String[] args)
throws NoApiKeyException, InputRequiredException {
VoiceEnrollmentService service = new VoiceEnrollmentService(apiKey);
Voice voice = service.queryVoice(voiceId);
logger.info("Query successful. Request ID: {}", service.getLastRequestId());
logger.info("Voice Details: {}", new Gson().toJson(voice));
}
}响应示例
{
"gmt_create": "2024-09-13 11:29:41",
"resource_link": "https://yourAudioFileUrl",
"target_model": "cosyvoice-v2-plus",
"gmt_modified": "2024-09-13 11:29:41",
"status": "OK"
}响应参数
参数 | 类型 | 说明 |
resource_link | string | 被复刻的音频的URL。 |
target_model | string | 声音复刻所使用的模型。 |
gmt_create | string | 创建音色的时间。 |
gmt_modified | string | 修改音色的时间。 |
status | string | 状态。
|
RESTful API
基本信息
URL | |
请求方法 | POST |
请求头 | |
消息体 | 包含所有请求参数的消息体如下,对于可选字段,在实际业务中可根据需求省略: |
请求参数
参数 | 类型 | 默认值 | 是否必须 | 说明 |
model | string | - | 是 | 固定为 |
action | string | - | 是 | 固定为 |
voice_id | string | - | 是 | 需要查询的音色ID。 |
响应参数
参数 | 类型 | 说明 |
resource_link | string | 被复刻的音频的URL。 |
target_model | string | 声音复刻所使用的模型。 |
gmt_create | string | 创建音色的时间。 |
gmt_modified | string | 修改音色的时间。 |
status | string | 状态。
|
更新音色
使用新的音频文件更新一个已存在的音色。
Python SDK
接口说明
def update_voice(self, voice_id: str, url: str) -> None:
'''
更新音色
param: voice_id 音色id
param: url 用于声音复刻的音频文件url
'''请求示例
from dashscope.audio.tts_v2 import VoiceEnrollmentService
service = VoiceEnrollmentService()
service.update_voice(
voice_id='cosyvoice-v2-myvoice-xxxxxxxx',
url='https://your-new-audio-file-url'
)
print(f"Update submitted. Request ID: {service.get_last_request_id()}")Java SDK
接口说明
/**
* 更新音色
*
* @param voiceId 需要更新的音色
* @param url 用于声音复刻的音频文件url
* @throws NoApiKeyException 如果apikey为空
* @throws InputRequiredException 如果必须参数为空
*/
public void updateVoice(String voiceId, String url)
throws NoApiKeyException, InputRequiredException请求示例
import com.alibaba.dashscope.audio.ttsv2.enrollment.VoiceEnrollmentService;
import com.alibaba.dashscope.exception.InputRequiredException;
import com.alibaba.dashscope.exception.NoApiKeyException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Main {
public static String apiKey = System.getenv("DASHSCOPE_API_KEY"); // 如果您没有配置环境变量,请在此处用您的API-KEY进行替换
private static String fileUrl = "https://your-audio-file-url"; // 请按实际情况进行替换
private static String voiceId = "cosyvoice-v2-myvoice-xxx"; // 请按实际情况进行替换
private static final Logger logger = LoggerFactory.getLogger(Main.class);
public static void main(String[] args)
throws NoApiKeyException, InputRequiredException {
VoiceEnrollmentService service = new VoiceEnrollmentService(apiKey);
// 更新音色
service.updateVoice(voiceId, fileUrl);
logger.info("Update submitted. Request ID: {}", service.getLastRequestId());
}
}RESTful API
基本信息
URL | |
请求方法 | POST |
请求头 | |
消息体 | 包含所有请求参数的消息体如下,对于可选字段,在实际业务中可根据需求省略: |
请求参数
参数 | 类型 | 默认值 | 是否必须 | 说明 |
model | string | - | 是 | 固定为 |
action | string | - | 是 | 固定为 |
voice_id | string | - | 是 | 待更新的音色ID。 |
url | string | - | 是 | 用于更新音色的音频文件URL。该URL要求公网可访问。 如何录制音频请参见录音操作指南。 |
删除音色
删除一个不再需要的音色以释放配额。此操作不可逆。
Python SDK
接口说明
def delete_voice(self, voice_id: str) -> None:
'''
删除音色
param: voice_id 需要删除的音色
'''请求示例
from dashscope.audio.tts_v2 import VoiceEnrollmentService
service = VoiceEnrollmentService()
service.delete_voice(voice_id='cosyvoice-v2-myvoice-xxxxxxxx')
print(f"Deletion submitted. Request ID: {service.get_last_request_id()}")Java SDK
接口说明
/**
* 删除音色
*
* @param voiceId 需要删除的音色
* @throws NoApiKeyException 如果apikey为空
* @throws InputRequiredException 如果必须参数为空
*/
public void deleteVoice(String voiceId) throws NoApiKeyException, InputRequiredException 请求示例
import com.alibaba.dashscope.audio.ttsv2.enrollment.VoiceEnrollmentService;
import com.alibaba.dashscope.exception.InputRequiredException;
import com.alibaba.dashscope.exception.NoApiKeyException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Main {
public static String apiKey = System.getenv("DASHSCOPE_API_KEY"); // 如果您没有配置环境变量,请在此处用您的API-KEY进行替换
private static String voiceId = "cosyvoice-v2-myvoice-xxx"; // 请按实际情况进行替换
private static final Logger logger = LoggerFactory.getLogger(Main.class);
public static void main(String[] args)
throws NoApiKeyException, InputRequiredException {
VoiceEnrollmentService service = new VoiceEnrollmentService(apiKey);
// 删除音色
service.deleteVoice(voiceId);
logger.info("Deletion submitted. Request ID: {}", service.getLastRequestId());
}
}RESTful API
基本信息
URL | |
请求方法 | POST |
请求头 | |
消息体 | 包含所有请求参数的消息体如下,对于可选字段,在实际业务中可根据需求省略: |
请求参数
参数 | 类型 | 默认值 | 是否必须 | 说明 |
model | string | - | 是 | 固定为 |
action | string | - | 是 | 固定为 |
voice_id | string | - | 是 | 待删除的音色ID。 |
音色配额
每个阿里云主账号最多可创建 1000 个音色(所有模型共享此限额)。超过1年未被使用的音色将被系统自动下线并删除,数据不可恢复。
计费说明
声音复刻服务免费提供,但使用复刻的音色进行语音合成时将收取费用(参见CosyVoice)。
版权与合法性
需对所提供声音的所有权及合法使用权负责,请注意阅读服务协议。
错误码
如遇报错问题,请参见错误信息进行排查。
常见问题
功能特性
Q:如何调节自定义音色的语速、音量?
与使用预置音色完全相同。在调用语音合成API时,传入相应的参数即可,例如 speech_rate (Python) / speechRate (Java) 用于调节语速,volume 用于调节音量。详情请参见语音合成API文档(Java SDK/Python SDK/WebSocket API)
Q:除了Java和Python,其他语言(如Go, C#, Node.js)如何调用?
对于音色管理,请直接使用文档中提供的RESTful API。对于语音合成,请使用WebSocket API,并将复刻得到的 voice_id 作为 voice 参数传入。
故障排查
如遇代码报错问题,请根据错误码中的信息进行排查。
Q:为什么找不到 VoiceEnrollmentService 类?
SDK版本过低。请安装最新版SDK。
Q:声音复刻效果不佳,有杂音或不清晰怎么办?
这通常是由于输入音频质量不高导致的。请严格遵循录音操作指南重新录制并上传音频。
权限与认证
Q:使用子业务空间的API Key是否可以进行声音复刻?
需要为API Key对应的子业务空间进行模型授权后方才支持,详情请参见子业务空间的模型调用。