
"假"标题:通过TTS模型让猴哥给你讲个故事
"真"标题:使用Python调用硅基流动TTS模型并播放返回的音频数据过程记录
TTS介绍
TTS(Text-to-Speech,文本转语音)技术是一种将书面文本转换为口语语音的技术。这种技术广泛应用于各种场景,如语音助手、导航系统、有声读物、自动电话应答系统等。TTS系统的目的是为了让计算机能够"说出"人们能理解的语言,从而改善人机交互的体验,使得信息传递更加自然和亲切。
实践
由于硅基流动中还有很多额度,想通过使用TTS模型消耗一些。硅基流动中目前就只提供了一个TTS模型。

CosyVoice 2 是一个基于大语言模型的流式语音合成模型,采用统一的流式/非流式框架设计。该模型通过有限标量量化(FSQ)来提升语音 token 的编码本利用率,简化了文本到语音的语言模型架构,并开发了支持不同合成场景的分块感知因果流匹配模型。在流式模式下,模型可实现 150ms 的超低延迟,同时保持与非流式模式几乎相同的合成质量。相比 1.0 版本,发音错误率降低了 30%-50%,MOS 评分从 5.4 提升至 5.53,并支持情感和方言的细粒度控制。支持中文(含方言:粤语、四川话、上海话、天津话等)、英文、日语、韩语,支持跨语言和混合语言场景。
先试一下预定义的一个音色。
python
import requests
import subprocess
url = "https://api.siliconflow.cn/v1/audio/speech"
payload = {
"input": "文本转语音技术是一种将书面文本转换为口语语音的技术。这种技术广泛应用于各种场景,如语音助手、导航系统、有声读物、自动电话应答系统等。",
"response_format": "opus",
"stream": True,
"speed": 1,
"gain": 0,
"model": "FunAudioLLM/CosyVoice2-0.5B",
"voice": "FunAudioLLM/CosyVoice2-0.5B:alex"
}
headers = {
"Authorization": "Bearer 你的api key",
"Content-Type": "application/json"
}
response = requests.request("POST", url, json=payload, headers=headers)
if response.status_code == 200:
with open("output.opus", "wb") as file:
file.write(response.content)
print("音频文件已保存为 output.opus")
# 使用 ffplay 播放 opus 音频文件
subprocess.Popen(["ffplay","-nodisp","-autoexit","output.opus"])
else:
print(f"请求失败,状态码: {response.status_code}")
print(f"响应内容: {response.text}")
上面的代码是将返回的opus音频数据保存至一个文件,然后使用 ffplay 播放 opus 音频文件,因此需要在电脑上安装ffmpeg。
ffmpeg介绍
FFmpeg 是一个开源的多媒体处理框架,提供了一组强大的工具和库,用于录制、转换和流式传输音视频文件。它的主要组件包括 ffmpeg
命令行工具,用于转换和处理多媒体文件;ffplay
简单的媒体播放器;ffprobe
提取多媒体文件的元数据。FFmpeg 支持多种格式和编解码器,如 MP4、AVI、MKV、H.264、AAC 和 MP3 等,能够执行格式转换、裁剪、合并、滤镜处理等任务。此外,FFmpeg 还可以用于流式传输、截图和提取音频。其高度灵活和强大的功能使其在视频编辑、直播系统、多媒体应用开发等领域广泛应用。安装简单,适用于 Windows、Linux 和 macOS 等多种平台。
下载地址:ffmpeg.org/download.ht...
下载之后解压如下图所示:

有ffmpeg.exe、ffplay.exe、ffprobe.exe这三个可执行程序。
将ffmpeg的bin目录添加到系统变量。

打开cmd输入ffmpeg -version,出现下图所示的内容,说明安装成功了。

在刚刚的python代码中,我们播放opus文件的代码为:
css
subprocess.Popen(["ffplay","-nodisp","-autoexit","output.opus"])
使用了 Python 的 subprocess
模块来调用外部命令,具体是使用 ffplay
播放一个名为 output.opus
的音频文件。
subprocess.Popen
是 subprocess
模块中的一个类,用于创建一个子进程并连接到其输入/输出/错误管道,从而能够与其进行通信。它返回一个 Popen
对象,可以用来控制子进程或与之交互。
"ffplay"
是命令的名称,这里指的是 FFmpeg 的 ffplay
工具,用于播放多媒体文件。
"-nodisp"
是 ffplay
的一个选项,表示不显示视频(如果文件包含视频流)。对于纯音频文件,这个选项通常是可选的,因为音频文件本身没有视频流。
"-autoexit"
是 ffplay
的另一个选项,表示在文件播放完毕后自动退出播放器,而不是等待用户手动关闭。
"output.opus"
是要播放的音频文件的路径和名称。
但是先保存到一个文件再播放说实话不如直接播放,直接播放的代码如下:
python
import requests
import subprocess
url = "https://api.siliconflow.cn/v1/audio/speech"
payload = {
"input": "修改后代码应该能直接播放音频,无需保存临时文件。如果问题依旧,请提供更详细的错误信息(已通过 print(e.stderr.decode()) 捕获)。",
"response_format": "opus",
"stream": True,
"speed": 1,
"gain": 0,
"model": "FunAudioLLM/CosyVoice2-0.5B",
"voice": "FunAudioLLM/CosyVoice2-0.5B:alex"
}
headers = {
"Authorization": "Bearer 你的api key",
"Content-Type": "application/json"
}
response = requests.request("POST", url, json=payload, headers=headers)
if response.status_code == 200:
audio_data = response.content
try:
# 指定OPUS格式并用ffplay播放,从标准输入读取
play_command = [
'ffplay',
'-autoexit', # 播放完成后自动退出
'-nodisp', # 不显示图形界面
'-i', '-'
]
subprocess.run(
play_command,
input=audio_data, # 通过标准输入传递音频数据
check=True
)
print("音频已成功播放")
except subprocess.CalledProcessError as e:
print(f"播放失败: {e}")
except Exception as e:
print(f"发生未知错误: {str(e)}")
else:
print(f"请求失败,状态码: {response.status_code}")
print(f"响应内容: {response.text}")
当然默认的音色可能不能满足我们的需求。
比如我想让猴哥给我讲个故事该如何实现呢?
这时候就需要上传一个参考音频来自定义音色。
上传参考音频的代码:
python
import requests
import json
import base64
def audio_to_base64(file_path):
# 打开音频文件并读取二进制数据
with open(file_path, "rb") as audio_file:
audio_data = audio_file.read()
# 将二进制数据编码为Base64
base64_encoded_data = base64.b64encode(audio_data)
# 将Base64编码的数据转换为字符串
base64_string = base64_encoded_data.decode('utf-8')
return base64_string
# 示例用法
base64_audio = audio_to_base64("参考音频.mp3")
# 打印Base64编码的音频字符串
print(base64_audio)
api_key = "你的api key"
url = "https://api.siliconflow.cn/v1/uploads/audio/voice"
headers = {
"Authorization": f"Bearer {api_key}", # 从 https://cloud.siliconflow.cn/account/ak 获取
"Content-Type": "application/json"
}
data = {
"model": "FunAudioLLM/CosyVoice2-0.5B", # 模型名称
"customName": "SunWuKong", # 用户自定义的音频名称
"audio": f"data:audio/mpeg;base64,{base64_audio}", # 参考音频的 base64 编码
"text": "俺上天看看路径,日后好带你们上去同住。" # 参考音频的文字内容
}
response = requests.post(url, headers=headers, data=json.dumps(data))
# 打印响应状态码和响应内容
print(response.status_code)
print(response.json()) # 如果响应是 JSON 格式
输出:

现在只需替换voice为输出的uri即可,如下所示:
python
import requests
import subprocess
url = "https://api.siliconflow.cn/v1/audio/speech"
payload = {
"input": """
在遥远的山村里,住着一个名叫阿明的小男孩。阿明的村庄四周环山,人们以耕种为生。阿明自小就对山外的世界充满了好奇,但村庄出行的道路崎岖难行,很少有人能走出大山。
有一天,村里来了一位旅行者,他带着一本古老的书。这本书里记载着世界各地的故事和知识。旅行者被阿明的求知欲所感动,决定将书赠与他,并告诉他:"真正的宝藏不在书里,而在于你是如何用这些知识照亮你和周围人的世界。"
阿明接过书,夜以继日地学习。他不仅自己学习,还开始教村里的孩子们读书写字。春夏秋冬,年复一年,阿明成了村里最有学识的人。在他的教导下,孩子们开始了解山外的世界,他们的心中种下了一颗颗梦想的种子。
终于有一天,阿明和他的学生们一同踏上了探索山外世界的旅程。他们用书籍中学到的知识克服了一个又一个困难,将山村的故事带向了更远的地方,同时也带回了新的希望与活力。阿明真正找到了那位旅行者所说的宝藏------知识与梦想的力量。
""",
"response_format": "opus",
"stream": True,
"speed": 1,
"gain": 0,
"model": "FunAudioLLM/CosyVoice2-0.5B",
"voice": "speech:SunWuKong:clwvmwe3a0001ck5w20keygyc:ylvbgffpzouiovfdgfek"
}
headers = {
"Authorization": "Bearer 你的api key",
"Content-Type": "application/json"
}
response = requests.request("POST", url, json=payload, headers=headers)
if response.status_code == 200:
audio_data = response.content
try:
# 指定OPUS格式并用ffplay播放,从标准输入读取
play_command = [
'ffplay',
'-autoexit', # 播放完成后自动退出
'-nodisp', # 不显示图形界面
'-i', '-'
]
subprocess.run(
play_command,
input=audio_data, # 通过标准输入传递音频数据
check=True
)
print("音频已成功播放")
except subprocess.CalledProcessError as e:
print(f"播放失败: {e}")
except Exception as e:
print(f"发生未知错误: {str(e)}")
else:
print(f"请求失败,状态码: {response.status_code}")
print(f"响应内容: {response.text}")
效果在:mp.weixin.qq.com/s/_Ya81L8JF...

总结
本文简单介绍了TTS技术,使用了硅基流动提供的TTS模型,通过让猴哥给我们讲个故事的demo,了解TTS的用途,学习使用ffmpeg播放音频数据,希望对你有所帮助。