【机器学习】ChatTTS:开源文本转语音(text-to-speech)大模型天花板

news2024/9/20 14:28:12

目录

一、引言

二、TTS(text-to-speech)模型原理

2.1 VITS 模型架构

2.2 VITS 模型训练

2.3 VITS 模型推理

三、ChatTTS 模型实战

3.1 ChatTTS 简介

3.2 ChatTTS 亮点

3.3 ChatTTS 数据集 

3.4 ChatTTS 部署

3.4.1 创建conda环境

3.4.2 拉取源代码

3.4.3 安装环境依赖

3.4.4 启动WebUI

3.4.5 WebUI推理 

3.5 ChatTTS 代码 

四、总结


一、引言

我很愿意推荐一些小而美、高实用模型,比如之前写的YOLOv10霸榜百度词条,很多人搜索,仅需100M就可以完成毫秒级图像识别与目标检测,相关的专栏也是CSDN付费专栏中排行最靠前的。今天介绍有一个小而美、高实用性的模型:ChatTTS。

二、TTS(text-to-speech)模型原理

2.1 VITS 模型架构

由于ChatTTS还没有公布论文,我们也不好对ChatTTS的底层原理进行武断。这里对另一个TTS里程碑模型VITS原理进行简要介绍,让大家对TTS模型原理有多认知。VITS详细论文见链接

VITS论文对训练和推理两个环节分别进行讲述:

2.2 VITS 模型训练

VITS模型训练:在训练阶段,音素(Phonemes)可以被简单理解为文字对应的拼音或音标。它们经过文本编码(Text Encode)和映射(Projection)后,生成了文本的表示形式。左侧的线性谱(Linear Sepctrogram)是从用于训练的音频中提取的 wav 文件的音频特征。这些特征通过后验编码器(Posteritor)生成音频的表示,然后通过训练对齐这两者(在模块 A 中)。节奏也是表达的重要因素,因此还加入了一个随机持续时间预测器(Stochasitic Duration Predictor)模块,根据音素和对齐结果对输出音频长度进行调整。

2.3 VITS 模型推理

VITS模型推理:在推理过程中,输入是文本对应的音素。将映射和对长度采样输入模型,将其转换为语音表示流,然后通过解码器将其转换为音频格式。 

根据论文中描述的逻辑,文本数据被转换为音素(即词的拼音)并输入模型。模型学习了音素与音频之间的关系,包括说话者的音质、音高、口音和发音习惯等。

三、ChatTTS 模型实战

3.1 ChatTTS 简介

ChatTTS 是一款专门为对话场景(例如 LLM 助手)设计的文本转语音模型。

3.2 ChatTTS 亮点

  • 对话式 TTS: ChatTTS 针对对话式任务进行了优化,能够实现自然且富有表现力的合成语音。它支持多个说话者,便于生成互动式对话。
  • 精细的控制: 该模型可以预测和控制精细的韵律特征,包括笑声、停顿和插入语。
  • 更好的韵律: ChatTTS 在韵律方面超越了大多数开源 TTS 模型。我们提供预训练模型以支持进一步的研究和开发。

3.3 ChatTTS 数据集 

  • 主模型使用了 100,000+ 小时的中文和英文音频数据进行训练。
  • HuggingFace 上的开源版本是一个在 40,000 小时数据上进行无监督微调的预训练模型。

3.4 ChatTTS 部署

3.4.1 创建conda环境

conda create -n chattts
conda activate chattts

3.4.2 拉取源代码

git clone https://github.com/2noise/ChatTTS
cd ChatTTS

3.4.3 安装环境依赖

pip install -r requirements.txt

3.4.4 启动WebUI

export CUDA_VISIBLE_DEVICES=3 #指定显卡
nohup   python examples/web/webui.py --server_name 0.0.0.0 --server_port 8888 > chattts_20240624.out 2>&1 & #后台运行

执行后会自动跳转出webui,地址为server_name:server_port 

3.4.5 WebUI推理 

个人感觉:其中夹杂着“那个”、“然后”、“嗯...”等口头禅,学的太逼真了,人类说话不就是这样么。。 

  • [uv_break]、[laugh]等符号进行断句、微笑等声音控制。
  • Audio Seed:用于初始化随机数生成器的种子值。设置相同的 Audio Seed 可以确保重复生成一致的语音,便于实验和调试。推荐 Seed: 3798-知性女、462-大舌头女、2424-低沉男。
  • Text Seed:类似于 Audio Seed,在文本生成阶段用于初始化随机数生成器的种子值。
  • Refine Text:勾选此选项可以对输入文本进行优化或修改,提升语音的自然度和可理解性。
  • Audio Temperature️:控制输出的随机性。数值越高,生成的语音越可能包含意外变化;数值较低则趋向于更平稳的输出。
  • Top_P:核采样策略,定义概率累积值,模型将只从这个累积概率覆盖的最可能的词中选择下一个词。
  • Top_K:限制模型考虑的可能词汇数量,设置为一个具体数值,模型将只从这最可能的 K 个词中选择下一个词。 

3.5 ChatTTS 代码 

import os, sys

if sys.platform == "darwin":
    os.environ["PYTORCH_ENABLE_MPS_FALLBACK"] = "1"

now_dir = os.getcwd()
sys.path.append(now_dir)

import random
import argparse

import torch
import gradio as gr
import numpy as np

from dotenv import load_dotenv
load_dotenv("sha256.env")

import ChatTTS

# 音色选项:用于预置合适的音色
voices = {
    "默认": {"seed": 2},
    "音色1": {"seed": 1111},
    "音色2": {"seed": 2222},
    "音色3": {"seed": 3333},
    "音色4": {"seed": 4444},
    "音色5": {"seed": 5555},
    "音色6": {"seed": 6666},
    "音色7": {"seed": 7777},
    "音色8": {"seed": 8888},
    "音色9": {"seed": 9999},
    "音色10": {"seed": 11111},
}

def generate_seed():
    new_seed = random.randint(1, 100000000)
    return {
        "__type__": "update",
        "value": new_seed
        }

# 返回选择音色对应的seed
def on_voice_change(vocie_selection):
    return voices.get(vocie_selection)['seed']

def generate_audio(text, temperature, top_P, top_K, audio_seed_input, text_seed_input, refine_text_flag):

    torch.manual_seed(audio_seed_input)
    rand_spk = chat.sample_random_speaker()
    params_infer_code = {
        'spk_emb': rand_spk,
        'temperature': temperature,
        'top_P': top_P,
        'top_K': top_K,
        }
    params_refine_text = {'prompt': '[oral_2][laugh_0][break_6]'}

    torch.manual_seed(text_seed_input)

    if refine_text_flag:
        text = chat.infer(text,
                          skip_refine_text=False,
                          refine_text_only=True,
                          params_refine_text=params_refine_text,
                          params_infer_code=params_infer_code
                          )

    wav = chat.infer(text,
                     skip_refine_text=True,
                     params_refine_text=params_refine_text,
                     params_infer_code=params_infer_code
                     )

    audio_data = np.array(wav[0]).flatten()
    sample_rate = 24000
    text_data = text[0] if isinstance(text, list) else text

    return [(sample_rate, audio_data), text_data]


def main():

    with gr.Blocks() as demo:
        gr.Markdown("# ChatTTS Webui")
        gr.Markdown("ChatTTS Model: [2noise/ChatTTS](https://github.com/2noise/ChatTTS)")

        default_text = "四川美食确实以辣闻名,但也有不辣的选择。[uv_break]比如甜水面、赖汤圆、蛋烘糕、叶儿粑等,这些小吃口味温和,甜而不腻,也很受欢迎。[laugh]"
        text_input = gr.Textbox(label="Input Text", lines=4, placeholder="Please Input Text...", value=default_text)

        with gr.Row():
            refine_text_checkbox = gr.Checkbox(label="Refine text", value=True)
            temperature_slider = gr.Slider(minimum=0.00001, maximum=1.0, step=0.00001, value=0.3, label="Audio temperature")
            top_p_slider = gr.Slider(minimum=0.1, maximum=0.9, step=0.05, value=0.7, label="top_P")
            top_k_slider = gr.Slider(minimum=1, maximum=20, step=1, value=20, label="top_K")

        with gr.Row():
            voice_options = {}
            voice_selection = gr.Dropdown(label="音色", choices=voices.keys(), value='默认')
            audio_seed_input = gr.Number(value=2, label="Audio Seed")
            generate_audio_seed = gr.Button("\U0001F3B2")
            text_seed_input = gr.Number(value=42, label="Text Seed")
            generate_text_seed = gr.Button("\U0001F3B2")

        generate_button = gr.Button("Generate")

        text_output = gr.Textbox(label="Output Text", interactive=False)
        audio_output = gr.Audio(label="Output Audio")

        # 使用Gradio的回调功能来更新数值输入框
        voice_selection.change(fn=on_voice_change, inputs=voice_selection, outputs=audio_seed_input)

        generate_audio_seed.click(generate_seed,
                                  inputs=[],
                                  outputs=audio_seed_input)

        generate_text_seed.click(generate_seed,
                                 inputs=[],
                                 outputs=text_seed_input)

        generate_button.click(generate_audio,
                              inputs=[text_input, temperature_slider, top_p_slider, top_k_slider, audio_seed_input, text_seed_input, refine_text_checkbox],
                              outputs=[audio_output, text_output])

        gr.Examples(
            examples=[
                ["四川美食确实以辣闻名,但也有不辣的选择。比如甜水面、赖汤圆、蛋烘糕、叶儿粑等,这些小吃口味温和,甜而不腻,也很受欢迎。", 0.3, 0.7, 20, 2, 42, True],
                ["What is [uv_break]your favorite english food?[laugh][lbreak]", 0.5, 0.5, 10, 245, 531, True],
                ["chat T T S is a text to speech model designed for dialogue applications. [uv_break]it supports mixed language input [uv_break]and offers multi speaker capabilities with precise control over prosodic elements [laugh]like like [uv_break]laughter[laugh], [uv_break]pauses, [uv_break]and intonation. [uv_break]it delivers natural and expressive speech,[uv_break]so please[uv_break] use the project responsibly at your own risk.[uv_break]", 0.2, 0.6, 15, 67, 165, True],
            ],
            inputs=[text_input, temperature_slider, top_p_slider, top_k_slider, audio_seed_input, text_seed_input, refine_text_checkbox],
        )
    
    parser = argparse.ArgumentParser(description='ChatTTS demo Launch')
    parser.add_argument('--server_name', type=str, default='0.0.0.0', help='Server name')
    parser.add_argument('--server_port', type=int, default=8080, help='Server port')
    parser.add_argument('--root_path', type=str, default=None, help='Root Path')
    parser.add_argument('--custom_path', type=str, default=None, help='the custom model path')
    args = parser.parse_args()

    print("loading ChatTTS model...")
    global chat
    chat = ChatTTS.Chat()

    if args.custom_path == None:
        chat.load_models()
    else:
        print('local model path:', args.custom_path)
        chat.load_models('custom', custom_path=args.custom_path)

    demo.launch(server_name=args.server_name, server_port=args.server_port, root_path=args.root_path, inbrowser=True)


if __name__ == '__main__':
    main()

通过import ChatTTS和chat = ChatTTS.chat()以及chat.infer对ChatTTS类进行引用,通过装载多个配置项进行不同语音类型的生成。 

四、总结

本文首先以VITS为例,对TTS基本原理进行简要讲解,让大家对TTS模型有基本的认知,其次对ChatTTS模型进行step by step实战教学,个人感觉4万小时语音数据开源版本还是被阉割的很严重,可能担心合规问题吧。其次就是没有特定的角色与种子值对应关系,需要人工去归类,期待更多相关的工作诞生。

实用性上来讲,对于语音聊天助手,确实是一种技术上的升级,不需要特别多的GPU资源就可以搭建语音聊天服务,比LLM聊天上升了一个档次。最近好忙,主要在做一个人工智能助手,3天涨了1.3万粉丝。最近计划把ChatTTS应用于这个人工智能助手(微博:面子小行家)的私信回复中,涉及到音频文件与业务相结合。期待我的成果吧!

 

如果您还有时间,可以看看我的其他文章:

《AI—工程篇》

AI智能体研发之路-工程篇(一):Docker助力AI智能体开发提效

AI智能体研发之路-工程篇(二):Dify智能体开发平台一键部署

AI智能体研发之路-工程篇(三):大模型推理服务框架Ollama一键部署

AI智能体研发之路-工程篇(四):大模型推理服务框架Xinference一键部署

AI智能体研发之路-工程篇(五):大模型推理服务框架LocalAI一键部署

《AI—模型篇》

AI智能体研发之路-模型篇(一):大模型训练框架LLaMA-Factory在国内网络环境下的安装、部署及使用

AI智能体研发之路-模型篇(二):DeepSeek-V2-Chat 训练与推理实战

AI智能体研发之路-模型篇(三):中文大模型开、闭源之争

AI智能体研发之路-模型篇(四):一文入门pytorch开发

AI智能体研发之路-模型篇(五):pytorch vs tensorflow框架DNN网络结构源码级对比

AI智能体研发之路-模型篇(六):【机器学习】基于tensorflow实现你的第一个DNN网络

AI智能体研发之路-模型篇(七):【机器学习】基于YOLOv10实现你的第一个视觉AI大模型

AI智能体研发之路-模型篇(八):【机器学习】Qwen1.5-14B-Chat大模型训练与推理实战

AI智能体研发之路-模型篇(九):【机器学习】GLM4-9B-Chat大模型/GLM-4V-9B多模态大模型概述、原理及推理实战

AI智能体研发之路-模型篇(十):【机器学习】Qwen2大模型原理、训练及推理部署实战

《AI—Transformers应用》

【AI大模型】Transformers大模型库(一):Tokenizer

【AI大模型】Transformers大模型库(二):AutoModelForCausalLM

【AI大模型】Transformers大模型库(三):特殊标记(special tokens)

【AI大模型】Transformers大模型库(四):AutoTokenizer

【AI大模型】Transformers大模型库(五):AutoModel、Model Head及查看模型结构

【AI大模型】Transformers大模型库(六):torch.cuda.OutOfMemoryError: CUDA out of memory解决

【AI大模型】Transformers大模型库(七):单机多卡推理之device_map

【AI大模型】Transformers大模型库(八):大模型微调之LoraConfig

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

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

相关文章

iptables(9)网络防火墙

简介 我们在第一篇介绍iptables的时候提到过,iptables是一个包过滤防火墙,那么防火墙是怎么分类的呢?都有哪些防火墙?下面我们先简单介绍下防火墙的分类: 按部署位置分类 网络层防火墙(网络边界防火墙):位于网络边界处,监控网络流量进出。主机防火墙:安装在单…

discuz迪恩cul!教育课程培训网站模板

Discuz x3.2模板 迪恩cul!教育课程培训 GBK,程序包中内附详细的安装教程,下载后按照教程安装即可 discuz迪恩cul!教育课程培训网站模板

区块链革命:Web3引领数字资产的全新篇章

随着区块链技术的发展和Web3的兴起,数字资产正迎来一场革命性的变革。本文将深入探讨区块链如何引领数字资产进入全新篇章,其背后的技术原理、应用场景以及对未来的深远影响。 ​1. 区块链技术的基础概念 区块链是一种去中心化的分布式账本技术&#xf…

【性能优化】Android冷启动优化

文章目录 常见现象APP的启动流程计算启动时间Displayed Timeadb dump 启动优化具体策略总结参考链接 常见现象 各种第三方工具初始化和大量业务逻辑初始化,影响启动时间,导致应用启动延迟、卡顿等现象 APP的启动流程 加载和启动应用程序; …

Pytorch之视频流猫狗识别

1. 导入资源包 // An highlighted block var foo bar;注: 1. import cv2: 导入OpenCV库,这是一个非常强大的计算机视觉库,用于处理图像和视频数据。 2. import tkinter as tk: 导入Tkinter库,这是Python的标准GUI库,…

“用友审批,工行付款”,YonSuite让企业采购更便利

随着市场竞争的日益激烈,成长型企业面临着越来越大的挑战。其中,采购管理作为企业运营的重要一环,其效率和便捷性直接关系到企业的成本和竞争力。然而,传统的采购管理方式往往存在诸多难点和痛点,如审批流程繁琐、付款…

海外青云私有云:企业的数字化转型得力助手

在全球化日益加深的今天,海外企业对于云计算的需求也愈发迫切。青云(QingCloud)作为一家领先的云计算服务提供商,其私有云产品在海外市场上受到了广泛的关注和认可。那么,海外青云私有云究竟有何用处呢?本文将从多个角度为您科普。 首先&…

# Kafka_深入探秘者(5):kafka 分区

Kafka_深入探秘者(5):kafka 分区 一、kafka 副本机制 1、Kafka 可以将主题划分为多个分区(Partition),会根据分区规则选择把消息存储到哪个分区中,只要如果分区规则设置的合理,那么所有的消息将会被均匀的…

Linux_生产消费模型_Block_Queue

目录 一、互斥锁 1.1 错误的抢票 1.1.1 类的成员函数与构造 1.1.2 start 函数 1.1.3 线程的回调函数 1.1.4 main 函数 1.1.5 结果 1.2 概念 1.3 相关系统调用 1.3.1 锁的创建 1.3.2 锁的初始化 1.3.2.1 动态初始化 1.3.2.2 静态初始化 1.3.3 锁的销毁 1.3.4…

如何在电脑上免费下载并安装 VMware Workstation Pro

下载 VMware 首先我们先来看一看免费下载VMware Workstation Pro 的具体步骤: 首先我们可以先进入 Broadcom 注册页面:https://profile.broadcom.com/web/registration,然后这时候就需要注册,我们可以使用电子邮件进行注册。 在…

B端系统:增删改查中的新建(增)页面如何设计体验更爽。

在B系统中,增删改查是最基本、最常用的功能之一。这四个操作对于系统的正常运行和数据管理至关重要。其中,新增(新建)页面的设计尤为关键,因为它直接影响着用户体验和系统功能的完整性。 一、新增(新建&…

springboot加载注入bean的方式

在SpringBoot的大环境下,基本上很少使用之前的xml配置Bean,主要是因为这种方式不好维护而且也不够方便。 springboto注入bean主要采用下图几种方式,分为本地服务工程注解声明的bean和外部依赖包中的bean。 一、 springboot装配本地服务工程…

Linux环境下安装MySQL5.7.20(源码安装)

📣📣📣 哈喽!大家好,本专栏主要发表mysql实战的文章,文章主要包括: 各版本数据库的安装、备份和恢复,性能优化等内容的学习。。 📣 ***如果需要观看配套视频的小伙伴们,请…

单体架构改造为微服务架构之痛点解析

1.微服务职责划分之痛 1.1 痛点描述 微服务的难点在于无法对一些特定职责进行清晰划分,比如某个特定职责应该归属于服务A还是服务B? 1.2 为服务划分原则的痛点 1.2.1 根据存放主要数据的服务所在进行划分 比如一个能根据商品ID找出商品信息的接口,把…

Redis持久化(RDB、AOF)详解

Redis持久化详解 一、Redis为什么需要持久化? Redis 是一个基于内存的数据库,拥有极高的读写性能,但是内存中的数据在断电或服务器重启时会全部丢失,因此需要一种持久化机制来将数据保存到硬盘上,以便在需要时进行恢复…

R语言数据分析案例34-基于ARIMA模型的武汉市房价趋势与预测研究

一、背景阐述 房地产行业对于国民经济和社会及居民的发展和生活具有很大的影响,而房价能够体现经济运转的好坏,因而房价的波动牵动着开发商和购房者的关注,城市房价预测是一个研究的热点问题,研究房价对民生问题具有重要意义。 …

【面试干货】Java中的++操作符与线程安全性

【面试干货】Java中的操作符与线程安全性 1、什么是线程安全性?2、 操作符的工作原理3、 操作符与线程安全性4、如何确保线程安全?5、 结论 💖The Begin💖点点关注,收藏不迷路💖 在Java编程中,操…

思维导图MindManager2024最新版,让你的思维飞起来!

亲爱的朋友们,今天我要跟大家分享一款我近期深度使用并彻底被种草的神器——MindManager2024最新版本的思维导图软件。作为一位对效率和创意有着极高追求的内容创作者,我几乎尝试过市面上所有的思维导图工具,而MindManager2024无疑是其中的佼…

跟着DW学习大语言模型-什么是知识库,如何构建知识库

建立一个高效的知识库对于个人和组织来说非常重要。无论是为了个人学习和成长,还是为了组织的持续创新和发展,一个完善的知识管理系统都是不可或缺的。那么,如何建立一个高效的知识库呢? 在建立知识库之前,首先需要确定…

【办公类-51-01】月评估数字生成01-平均数空值

期末需要制作月评估,每月给孩子的能力水平打分。 以前我是做在EXCEL里,手动打分,然后用公式计算1、2、3出现的个数,然后计算平均数,最后复制到Word里。 因为是手动计算,每次都要算很长时间,确保…