ChatTTS 长音频合成和本地部署2种方式,让你的“儿童绘本”发声的实战教程(文末有福利)

接上文(GLM-4-Flash 大模型 API 免费了,手把手构建“儿童绘本”应用实战(附源码)),老牛同学通过 GLM-4-Flash 文生文和 CogView-3 文生图大模型,和大家一起编写了一个图文并茂的儿童绘本应用,并且以《黑神话·悟空》当前热门游戏为背景,做了一本名为《悟空探秘之旅》的儿童小绘本。

绘本我们是做好了,可是还得我们读给小朋友们听,老牛同学懒虫又犯了:能不能把绘本转换成音频,直接播放给小朋友们听(顺便我也跟着听听)?

这让老牛同学想到了之前写的关于ChatTTS详细介绍的文章:ChatTTS 开源文本转语音模型本地部署、API 使用和搭建 WebUI 界面(建议收藏)

老牛同学打开之前写的ChatTTS文章,发现有不少朋友的留言,包括:ChatTTS 的 API 更新了运行失败、模型文件下载不下跑不起来,希望老牛同学给打个包放到云盘等。这也不能怪 ChatTTS,都过去 2 个多月了,发布了新版也属正常,但是啥就不能兼容一下呢?

本着负责到底和解放自己的目的,老牛同学觉得完全有必要在重头部署一遍最新版的 ChatTTS,部署过程中发现有新坑,本文逐一破解:

  1. ChatTTS 研发环境配置
  2. ChatTTS 的 2 种方式部署和填坑,填坑过程老牛同学已经痛了一次,本文就不在赘述了,推荐使用第 2 种方式
  3. ChatTTS 最长生成30 秒音频,如何生成《悟空探秘之旅》小绘本3 分钟左右的音频?

实在忍不住,必须要剧透一下:本文末有限量的福利活动,这个福利老牛同学都喜欢,大家可以顺便参与一下(其实就是一本最近上市的看起来还不错却还没有看完的大模型的书)!

ChatTTS 配置 Python 研发环境

工欲善其事,必先利其器,我们通过Miniconda管理 Python 虚拟环境,Miniconda的安装和使用可以参考老牛同学之前的文章:大模型应用研发基础环境配置(Miniconda、Python、Jupyter Lab、Ollama 等)

# Python虚拟环境名:ChatTTS,版本号:3.10
conda create --name ChatTTS python=3.10 -y# 激活虚拟环境
conda activate ChatTTS

接下来,我们克隆 ChatTTS 源代码,安装 Python 依赖包(目录:ChatTTS):

# 克隆源代码
git clone https://github.com/2noise/ChatTTS ChatTTS# 切换到源代码目录
cd ChatTTS# 安装Python依赖包
pip install -r requirements.txt# 安装ChatTTS包:以下2种方式任一一种即可
pip install -e .
# pip install git+https://github.com/2noise/ChatTTS

最后,我们还需要安装 2 个依赖,主要是文本合成音频文件,和音频文件合并(这是一个,老牛同学翻源代码解决):

pip install pysoundfile
pip install pydub

通过以上步骤,我们即完成了 ChatTTS 环境准备。接下来我们采用2 种方式在本地部署 ChatTTS 模型。

方式一:API 自动下载模型文件部署

自动下载模型文件的方式比较省事,唯一就是需要从 HF 下载文件,如果大家发现自己没有通畅的网络,那就直接跳过,采用方式二部署方式。

打开刚刚源代码目录ChatTTS,直接运行 WebUI 程序,就会自动下载模型文件:

# 切换到源代码目录
cd ChatTTS# 启动WebUI,API自动下载模型文件
python examples/web/webui.py

我们可以看到,ChatTTS API 自动下载模型文件:

自动下载模型文件

模型文件下载完成,自动启动了我们之前熟悉的 WebUI 界面:

ChatTTS WebUI输入部分

ChatTTS WebUI 的输入部分核心包括 2 个内容:

  1. 需要转换音频的文本内容,也就是我们“儿童绘本”故事内容
  2. 选择音色Timbre,里面有男声、女声、翘舌等 10 种不同的音色

ChatTTS WebUI音频输出部分

点击那个长长的 Generate橙色按钮,即可开始根据文本合并音频,我们可以点击播放按钮在线播放音频,还可以把音频文件下载到本地磁盘。

如果你想把绘本的内容全部放进,那是行不通的,因为:ChatTTS 最多只能合并30 秒时长的音频。我们得抛弃 WebUI 界面,通过 API 生产音频。

方式二:手动下载模型文件部署和 API 使用(推荐)

如果方式一大家能够成功下载模型文件,且只是体验一下玩玩,且能正常启动 WebUI,那么老年同学建议就直接使用方式一了,因为它确实简单粗暴。

如果我们想使用 API 自动化的做一下事情,那么就用方式二吧:

第一步: 下载模型文件到本地】

我们通过 Git 大文件系统下载模型文件(下载目录:ChatTTS-Model):

git lfs install
git clone https://www.modelscope.cn/ai-modelscope/chattts.git ChatTTS-Model

如果因网络不佳等原因,导致下载中断,我们可以通过以下命令在中断后继续下载:

cd ChatTTS-Model
git lfs pull

第二步: 本地部署模型并合并音频】

又有一个:ChatTTS 包中,固定死了模型文件列表的摘要内容,如果与包中摘要不一致,则本地部署失败!它这么做其实是可以理解,因为不同版本对应不同的程序,但是模型文件中为啥也不说明一下,使用哪个版本呢?

第一步:初始化 ChatTTS 代码如下:

import ChatTTS
import torch
import torchaudio
from tools.logger import get_logger
from pydub import AudioSegment
import oslogger = get_logger("SunningTX")#
# 第一步:ChatTTS初始化
#
# 1. 初始化ChatTTS实例
chat = ChatTTS.Chat(get_logger("ChatTTS"),
)

第二步:加载模型文件,坑就在这里出现了,老牛同学就直接填了

# 2. 坑:本地下载模型文件,需要魔改文件摘要,否则模型加载失败
chat.sha256_map = {"sha256_asset_Decoder_pt": "9964e36e840f0e3a748c5f716fe6de6490d2135a5f5155f4a642d51860e2ec38","sha256_asset_DVAE_full_pt": "553eb75763511e23f3e5f86303e2163c5ca775489d637fb635d979c8ae58bbe5","sha256_asset_GPT_pt": "d7d4ee6461ea097a2be23eb40d73fb94ad3b3d39cb64fbb50cb3357fd466cadb","sha256_asset_Vocos_pt": "09a670eda1c08b740013679c7a90ebb7f1a97646ea7673069a6838e6b51d6c58","sha256_asset_tokenizer_special_tokens_map_json": "30e1f3dfbaef18963d9298e9a70e5f4be9017b4f64ec67737d0bccc2dbeba8c9","sha256_asset_tokenizer_tokenizer_config_json": "ac0eb91b587bd4c627c2b18ac1652bdf3686c7a6cd632d4b00feb9f34828dfdc","sha256_asset_tokenizer_tokenizer_json": "dddc3d54016d6cb75ed66dde3be50287afe6dee679c751538373feb75f950020"
}# 3. 加载模型文件:指定模型文件路径
chat.load(compile=True,source='custom',force_redownload=False,custom_path='D:\ModelSpace\ChatTTS-Model',
)

特别注意: source值为custom代表使用自定义模型文件,custom_path代表自定义模型文件目录,即我们下载的模型文件根目录!

经过以上 2 步,我们即加载完成 ChatTTS 模型,可以看到如下日志输出:

[+0800 20240831 15:37:35] [INFO] ChatTTS | core | try to load from local: D:\ModelSpace\ChatTTS-Model
[+0800 20240831 15:37:35] [INFO] ChatTTS | dl | checking assets...
[+0800 20240831 15:37:36] [INFO] ChatTTS | dl | all assets are already latest.
[+0800 20240831 15:37:36] [WARN] ChatTTS | gpu | no GPU found, use CPU instead
[+0800 20240831 15:37:36] [INFO] ChatTTS | core | use device cpu
[+0800 20240831 15:37:36] [INFO] ChatTTS | core | vocos loaded.
[+0800 20240831 15:37:36] [INFO] ChatTTS | core | dvae loaded.
[+0800 20240831 15:37:39] [INFO] ChatTTS | core | gpt loaded.
[+0800 20240831 15:37:39] [INFO] ChatTTS | core | decoder loaded.
[+0800 20240831 15:37:39] [INFO] ChatTTS | core | tokenizer loaded.

接下来,我们测试一下合成一个简单的音频文件:

# 需要转化为音频的文本内容
text = '大家好,我是老牛,微信公众号:老牛同学,微信号:imxulin(奔跑的蜗牛),很高兴与您相遇!'# 文本转为音频
wavs = chat.infer(text)# 保存音频文件到本地文件(采样率为24000Hz)
torchaudio.save("./output/output-01.wav", torch.from_numpy(wavs[0]), 24000)

运行程序,我们可以看到如下日志输出:

 20%|██████████████████████████▌                    | 76/384 [00:08<00:35,  8.62it/s]26%|██████████████████████████████████▌            | 536/2048 [00:48<02:17, 10.98it/s]

同时,在本地目录生成了./output/output-01.wav音频文件,打开该音频文件,就可以听到非常自然流畅的语音了!

ChatTTS 应用:把《悟空探秘之旅》绘本故事转换为长音频文件

有了前面辛苦的准备,我们终于可以来实现我们的目标了:把《悟空探秘之旅》绘本故事合并音频文件!

现在摆在我们面前的问题是:ChatTTS 一次最多只能合成30 秒长的音频,如何让它合并整个绘本呢?

老牛同学的办法也简单粗暴:先按照故事每个小段落,分别合成较短时长的音频,最终把短音频合成长音频。(大家如果有更好的办法,恳请留言,谢谢大家)

第一步: 我们先把故事内容分成文本行】

需要注意的是:有些符合 ChatTTS 无法识别,我们把它踢除或者替换成空格,否则不知 ChatTTS 会发出什么音!

#
# 第二步:按行准备故事文本内容,并转换为音频文件
#
# 1. 按行读取故事内容(·《》:符号无法识别,需要过滤掉)
lines = []
with open('./Story.txt', 'r', encoding='utf-8') as file:for line in file:# 去掉或者替换不支持的字符line = line.replace('·', ' ')line = line.replace('《', '').replace('》', '')line = line.replace(':', ' ')# 最后末尾增加一个空格,以暂停一下line = line.strip() + ' 'if len(lines) > 2:passif len(line) > 0:lines.append(line)logger.info(line)

第二步: 按照故事段落,分别合成音频文件】

需要注意的是:以下代码torchaudio.save()的参数backend代表本地音频处理扩展,总共支持 3 种类型:

本地音频合成扩展

最简单的方式,就是使用soundfile,前面已经介绍:pip install pysoundfile

# 2. 音频转换,按照每行文本转换为一个音频文件
temp_dir = os.path.join(os.getcwd(), 'temp')
os.makedirs(temp_dir, exist_ok=True)# 存在单个音频文件
def save_wav(idx: int, src: torch.Tensor):wav_path = f'./temp/{idx}.wav'try:torchaudio.save(wav_path,torch.from_numpy(src).unsqueeze(0),24000,format='wav',backend='soundfile')except:torchaudio.save(wav_path,torch.from_numpy(src),24000,format='wav',backend='soundfile')return wav_path# 逐行合成音频文件
wav_list = []
for i in range(len(lines)):line = lines[i]logger.info(f'合成音频:{line}')res_gen = chat.infer(lines[i],skip_refine_text=False,refine_text_only=False,params_refine_text=ChatTTS.Chat.RefineTextParams(temperature=0.3,top_P=0.7,top_K=20,manual_seed=222,),)wav_list.append(save_wav(i, res_gen))

重点说明一下,chat.infer()函数的几个参数,因为真的很重要:

  • skip_refine_textrefine_text_only分别代表忽略文本处理和仅文本预处理标,预处理就是方式一种 WebUI 中,Output Text内容,主要去掉不支持字符、插入停顿、笑声等内容
  • temperature大模型温度值,越越越严谨,越高则代表大模型会有更多创意,比如加入一些字符等,让音频更加口语化等
  • top_Ktop_P代表大模型采样策略,它们都是用于控制模型输出;K代表概率分布最高的 K 个词,然后从 K 个中随机取一个作为输出;P代表累计概率和超过 P 的词,然后随机取一个作为输出
  • manual_seed代表音色,不同的男声和女声的不同音色,老牛同学随机定了一个值

第三步: 最后,合并短音频文件为长音频文件】

#
# 第三步:合并所有短音频为长音频文件
#
def merge_wav_files(input_files, output_file):combined_audio = AudioSegment.empty()for input_file in input_files:audio = AudioSegment.from_wav(input_file)combined_audio += audiocombined_audio.export(output_file, format='wav')# 合并音频文件
merge_wav_files(wav_list, './Story.wav')

合并以上步骤代码片段,我们执行程序:python ChatTTS-Story.py

绘本故事音频合成

至此,绘本故事所有的音频代码全部完成,完整的源代码老牛同学放到评论区。

【这里是《悟空探秘之旅》绘本故事的音频文件,请至微信公众号收听:老牛同学

最后:来个有限的福利活动(送书)

非常感谢大家一直关注老牛同学的公众号,是大家的支持给了老牛同学很多学习大模型的动力,最近老牛同学联系到一位出版社朋友,共同办一个送书的小福利活动。

图书封面说明

这本书老牛同学还没有看,但是网上看了评论和目录,里面涉及了大模型算法、应用实战,包括老牛同学之前介绍的 LoRA 参数高效微调、LangChain 大模型研发框架等,这本书80 元整体是很值。

本次福利小活动的要求:

  1. 关注老牛同学微信公众号
  2. 然后在公众号本文的评论区留言,留言的点赞数排名前 3 名的朋友,免费包邮获得《多模态大模型》书籍(即:默认送 3 本书)
  3. 若公众号本文的阅读量超过了2000(含2000),则留言的点赞数排名前 6 名的朋友均免费包邮送书(即:最多送 6 本书)
  4. 活动时间:2024 年 8 月 31 日到 2024 年 8 月 15 号上午 12 点整(共 2 周,正好假期老牛同学可以统计和收集寄件地址)
  5. 老牛同学不参与本次活动(因为老牛同学默认就有 1 本)

请原谅老牛同学这么久才搞个福利活动,竟然还搞得这么小,老牛同学真的尽力了:本来出版社朋友只送 2 本,老牛同学争取到了 3 本,然后继续磨嘴皮争取到 6 本。如果本次活动效果给力,老牛同学敢保证后续肯定还有很多机会。

大家可能会问,老牛同学你到底得到了什么福利?老牛同学会得到以下 3 个福利:

  1. 不论本次阅读效果如何,出版社朋友都会送书1 本(可见的福利)
  2. 本次是老牛同学第 1 次搞活动,可以积累活动经验,下次也行就更容易了(这是一条路子,老牛同学就可以去找更多的出版社朋友了)
  3. 公众号可能会有新的关注着,本文和其他文章的阅读量可能会增加,出版社朋友可能会比较满意,那么下次老牛同学就可以争取多一些福利(如:默认送 10 本书等)

最后,凡是参与活动满足送书条件的朋友,麻烦添加一下老牛同学的个人微信(注明:送书活动),便于老牛同学收集邮寄地址:imxulin(奔跑的蜗牛)

最后的最后,为了方便大家购买,老牛同学把京东商品链接也贴上:

【书籍购买链接】

本文示例源代码:https://gitee.com/obullxl/SunningTX/tree/master/PythonTX/ChatTTS

vLLM CPU 和 GPU 模式署和推理 Qwen2 等大语言模型详细教程

MiniCPM-V 2.6 面壁“小钢炮”,多图、视频理解多模态模型,部署和推理实战教程

基于 Qwen2/Lllama3 等大模型,部署团队私有化 RAG 知识库系统的详细教程(Docker+AnythingLLM)

使用 Llama3/Qwen2 等开源大模型,部署团队私有化 Code Copilot 和使用教程

基于 Qwen2 大模型微调技术详细教程(LoRA 参数高效微调和 SwanLab 可视化监控)

微信公众号:老牛同学

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/878383.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

先进制造aps专题二十五 openai的ai大模型设计也使用了aps用的并行遗传算法

openai的ai大模型设计是不是很神秘&#xff1f; 其实不神秘&#xff0c;看国内最新的一个团队招人 新型研究机构&#xff0c;AI团队招收ai大模型算子搜索、大模型训练与推理算法 ai大模型算子搜索&#xff1a;方向&#xff1a;算子辅助搜索工具的实现与开发、群体遗传算法研…

从默默无名到销量激增,极越CEO哭了

文 | 智能相对论 作者 | 周晚 8月28日&#xff0c;极越汽车CEO夏一平在接受媒体采访的时候泪洒当场&#xff01; 倒不是因为极越汽车销量寥寥&#xff0c;而是因为突然销量激增&#xff0c;他带领的极越团队走出低谷&#xff0c;当他们回过头去看今年上半年的巨大压力&#…

欧拉 函数

互质&#xff1a; 互质是公约数只有1的两个整数&#xff0c;叫做互质整数。公约数只有1的两个自然数&#xff0c;叫做互质自然数&#xff0c;后者是前者特殊情况。 &#xff08;1和-1与所有整数互质&#xff0c;而且它们是唯一与0互质的整数&#xff09; 互质的判断方法&…

面试(九)

目录 一. 僵尸进程/孤儿进程/守护进程 二 线程的同步和异步 三. 线程间通信 3.1 共享内存 3.2 互斥锁 3.3 条件变量 3.4 信号量 3.5 读写锁 3.6 事件 3.7 线程局部存储 四. 进程间通信 3.1 管道 3.2 消息队列 3.3. 共享内存 3.4 信号量 3.5 套接字 3.6 内存映…

redis的RDB快照配置详解

Redis 的 RDB&#xff08;Redis Database Backup&#xff09;快照是一种数据持久化方式&#xff0c;它可以在指定时间间隔内将内存中的数据快照保存到磁盘。这样&#xff0c;即使Redis服务器意外宕机或重启&#xff0c;数据也能从最近的快照中恢复。RDB快照的配置主要涉及以下几…

如何快速判断Excel中选区跨页?

实例需求&#xff1a;应用开发过程中&#xff0c;需要校验选中区域&#xff0c;要求选中区域不能跨页&#xff0c;即选中区域分布在两个不同的页面中。 示例代码如下。 Sub Demo()Dim rSelect As Range, oHP As HPageBreakDim UpCell As Range, DownCell As RangeSet rSelect…

1500+ HuggingFace API token暴露,使数百万 Meta-Llama、Bloom 等大模型用户面临风险

HugginingFace 和 GitHub 是AI开发人员的重要平台&#xff0c;因此我们决定对这些平台做更为深入的研究。在这项研究中&#xff0c;我们发现了数以千计的 API 令牌&#xff0c;这些令牌暴露给恶意行为者&#xff0c;使数百万最终用户可能受到攻击。 本文的主要内容包括&#x…

【Leetcode 2341 】 数组能形成多少数对 —— 去重

给你一个下标从 0 开始的整数数组 nums 。在一步操作中&#xff0c;你可以执行以下步骤&#xff1a; 从 nums 选出 两个 相等的 整数从 nums 中移除这两个整数&#xff0c;形成一个 数对 请你在 nums 上多次执行此操作直到无法继续执行。 返回一个下标从 0 开始、长度为 2 的…

MySQL高阶练习题1- 寻找面试候选人

目录 题目 准备数据 分析数据 实现代码 总结 题目 返回 所有面试候选人 的姓名 name 和邮件 mail 。当用户满足以下两个要求中的 任意一条 &#xff0c;其成为 面试候选人 : 该用户在 连续三场及更多 比赛中赢得 任意 奖牌。该用户在 三场及更多不同的 比赛中赢得 金牌&…

python实战三-提取Word数据到Excel

视频源码&#xff1a; 链接&#xff1a;https://pan.quark.cn/s/83db5bb15383 一个文件夹下有大量会议通知文件&#xff0c;为word文件&#xff0c;文件格式都是一致的&#xff0c;现在要将文件中的一些字段提取出来汇总到Excel文件中。 会议通知文件格式如下&#xff1a; 要提…

C++(1)基础语法

C(1)之基础语法 Author: Once Day Date: 2024年8月29日 一位热衷于Linux学习和开发的菜鸟&#xff0c;试图谱写一场冒险之旅&#xff0c;也许终点只是一场白日梦… 漫漫长路&#xff0c;有人对你微笑过嘛… 全系列文章可参考专栏: 源码分析_Once-Day的博客-CSDN博客 参考文…

java中哪些集合可以使用 Iterator 进行遍历

在 JAVA 集合中&#xff0c;分为两种顶层接口&#xff0c;Collection 和 Map。 而 Iterator 是针对 Collection 的。 因此&#xff0c;JAVA 中所有 Collection 的子类都可以使用 Iterator。 像 List、Set、Queue、Deque 都可以使用。 使用例子&#xff1a; List<Integer…

通用后台管理系统实战演示(Vue3 + element-plus)汇总篇一

天行健&#xff0c;君子以自强不息&#xff1b;地势坤&#xff0c;君子以厚德载物。 每个人都有惰性&#xff0c;但不断学习是好好生活的根本&#xff0c;共勉&#xff01; 文章均为学习整理笔记&#xff0c;分享记录为主&#xff0c;如有错误请指正&#xff0c;共同学习进步。…

【Windows学习笔记】1:OneCore和Windows API

1 OneCore 主流Windows跑在PC上&#xff0c;Xbox跑的是从Windows 2000分支出来的版本&#xff0c;Windows Phone跑的是基于Windows CE&#xff08;实时操作系统&#xff09;的版本。 为了维护和扩展这些code方便&#xff0c;微软将kernels和base platform集成在一起叫OneCore…

55-java多线程future

java多线程future 在Java中&#xff0c;Future 接口和 Callable 函数式接口一起被用来支持异步计算。Future 表示一个可能完成的异步计算的结果&#xff0c;通过 get 方法可以获取计算的结果。 下面是一个使用 Future 的简单示例&#xff1a; import java.util.concurrent.*…

宿舍|基于SprinBoot+vue的宿舍管理系统(源码+数据库+文档)

宿舍管理系统 基于SprinBootvue的私人诊所管理系统 一、前言 二、系统设计 三、系统功能设计 系统功能实现 后台模块实现 管理员功能实现 学生功能实现 四、数据库设计 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八、源码获取&#xff1a; 博主介绍&…

【计算机组成原理】六、总线:3.操作和定时

5.操作和定时 文章目录 5.操作和定时5.1总线传输的四个阶段5.2总线定时5.2.1同步通信5.2.2异步通信5.2.3半同步通信5.2.4分离式通信 2.3按时序控制方式 同步总线异步总线 5.1总线传输的四个阶段 总线周期&#xff1a; 申请分配阶段&#xff1a;由需要使用总线的主模块&#…

【C++11及其特性】左值和右值

左值和右值目录 一.左值和右值的报错1.简单定义2.函数返回值作左值3.表达式作左值 二.存储的层次结构1.CPU2.内存3.磁盘4.三者联系5.寄存器 三.左值和右值的概念1.左值2.右值3.转换 一.左值和右值的报错 1.简单定义 赋值号’左边的为左值,右边的为右值. 2.函数返回值作左值 …

kafka ---- producer与broker配置详解以及ack机制详解

一、producer 配置 1、bootstrap.servers kafka broker集群的ip列表&#xff0c;格式为&#xff1a;host1:port1,host2:port2,… 2、client.id 用于追踪消息的源头 3、retries 当发送失败时客户端会进行重试&#xff0c;重试的次数由retries指定&#xff0c;默认值是2147…

检测和处理异常值的方法

异常值检测 不同的方法适用于不同类型的数据和场景。选择合适的异常值检测方法应考虑以下因素&#xff1a; 数据类型&#xff08;连续型、离散型、分类型等&#xff09;。数据分布特征&#xff08;正态分布、非正态分布、多维数据等&#xff09;。数据规模和维度&#xff08;…