通过TTS模型让猴哥给你讲个故事

"假"标题:通过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.Popensubprocess 模块中的一个类,用于创建一个子进程并连接到其输入/输出/错误管道,从而能够与其进行通信。它返回一个 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播放音频数据,希望对你有所帮助。

相关推荐
Lilith的AI学习日记3 分钟前
LangChain核心架构解析:从传统Chain到LCEL的演进之路
人工智能·架构·langchain·ai编程
qq_273900238 分钟前
Pytorch torch.nn.utils.rnn.pad_sequence 介绍
人工智能·pytorch·python·rnn·深度学习
大模型真好玩16 分钟前
点名DeepSeek?一文解析”最强大模型“Llama-4到底是王者归来 还是 困兽犹斗?
人工智能·llama·deepseek
shengjk120 分钟前
快速搞懂湖仓一体发展历程:错过它,你将失去下一个大数据风口!
人工智能·后端
拉丁解牛说技术28 分钟前
一句话让deepseek实现基于Spring AI的AI chatbot
人工智能·spring·程序员
在下小航32 分钟前
前端本地大模型 window.ai 最新教程
前端·人工智能
蹦蹦跳跳真可爱58940 分钟前
Python----PaddlePaddle(深度学习框架PaddlePaddle,概述,安装,衍生工具)
开发语言·人工智能·python·paddlepaddle
机器之心1 小时前
迈向机器人领域ImageNet,大牛Pieter Abbeel领衔国内外高校共建RoboVerse,统一仿真平台、数据集和基准
人工智能
cccccc语言我来了1 小时前
飞浆PaddlePaddle 猫狗数据大战
人工智能·python·paddlepaddle
机器之心1 小时前
Llama 4在测试集上训练?内部员工、官方下场澄清,LeCun转发
人工智能