CosyVoice 2: Scalable Streaming Speech Synthesis with Large Language Models

  • 论文链接:https://arxiv.org/pdf/2412.10117
  • 代码链接:https://github.com/FunAudioLLM/CosyVoice

一句话总结

CosyVoice 2 是一款改进的流式语音合成模型,其核心创新包括采用有限标量量化(FSQ) 提升语音令牌的码本利用率,简化文本 - 语音语言模型架构以直接使用预训练大语言模型(如 Qwen2.5-0.5B)作为骨干,以及开发块感知因果流匹配模型,实现单一模型支持流式和非流式合成。通过在大规模多语言数据集(中文 130,000 小时、英文 30,000 小时等)上训练,该模型达到人类 parity 自然度,流式模式下响应延迟极低且合成质量几乎无损,在内容一致性(WER 低至 2.45%)、 speaker 相似度(最高 0.812)和语音质量(NMOS 达 3.96)上表现优异,同时支持情感、口音等精细指令控制。

在这里插入图片描述

模型结构

在这里插入图片描述

核心创新

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

实验数据

在这里插入图片描述

核心代码块解读

语音token和文本token是如何兼容输入的

cosyvoice/llm/llm.py

@torch.inference_mode()def inference(self,text: torch.Tensor,text_len: torch.Tensor,prompt_text: torch.Tensor,prompt_text_len: torch.Tensor,prompt_speech_token: torch.Tensor,prompt_speech_token_len: torch.Tensor,embedding: torch.Tensor,sampling: int = 25,max_token_text_ratio: float = 20,min_token_text_ratio: float = 2,uuid: str = '',) -> Generator[torch.Tensor, None, None]:device = text.devicetext = torch.concat([prompt_text, text], dim=1)print('text: ', text.shape, )text_len += prompt_text_lentext = self.llm.model.model.embed_tokens(text)# 3. concat llm_inputsos_eos_emb = self.llm_embedding.weight[self.sos_eos].reshape(1, 1, -1)task_id_emb = self.llm_embedding.weight[self.task_id].reshape(1, 1, -1)if prompt_speech_token_len != 0:prompt_speech_token_emb = self.speech_embedding(prompt_speech_token)else:prompt_speech_token_emb = torch.zeros(1, 0, self.llm_input_size, dtype=text.dtype).to(device)lm_input = torch.concat([sos_eos_emb, text, task_id_emb, prompt_speech_token_emb], dim=1)# 4. cal min/max_lengthmin_len = int((text_len - prompt_text_len) * min_token_text_ratio)max_len = int((text_len - prompt_text_len) * max_token_text_ratio)# 5. step by step decodefor token in self.inference_wrapper(lm_input, sampling, min_len, max_len, uuid):yield token

主要内容:

  1. 把prompt文本和输入文本拼接
    text = torch.concat([prompt_text, text], dim=1)
  2. 文本embedding映射 text = self.llm.model.model.embed_tokens(text)
  3. speech prompt token 映射:
    prompt_speech_token_emb = self.speech_embedding(prompt_speech_token)
  4. token embedding映射后拼接:
    lm_input = torch.concat([sos_eos_emb, text, task_id_emb, prompt_speech_token_emb], dim=1)
  5. 输入到模型中,做 Next token prediction

怎么在 text prompt 里面做 instruct 的

cosyvoice/cli/frontend.py

def frontend_instruct2(self, tts_text, instruct_text, prompt_speech_16k, resample_rate, zero_shot_spk_id):model_input = self.frontend_zero_shot(tts_text, instruct_text + '<|endofprompt|>', prompt_speech_16k, resample_rate, zero_shot_spk_id)del model_input['llm_prompt_speech_token']del model_input['llm_prompt_speech_token_len']return model_input

做法非常朴素,就是直接把 instruct_text + '<|endofprompt|>' 作为 prompt text 输入。值得注意的是,这种情况下,llm_prompt_speech_token 是会被删除的,那么如果音色和semantic token 不解耦的情况下,是否会导致一些音色不相似问题。

如何做文本音频混合流式

在这里插入图片描述

def prepare_lm_input_target(self, text_token, text_token_emb, text_token_len, speech_token, speech_token_emb, speech_token_len):lm_target, lm_input = [], []text_token = unpad_sequence(text_token, text_token_len.cpu(), batch_first=True)speech_token = unpad_sequence(speech_token, speech_token_len.cpu(), batch_first=True)text_token_emb = unpad_sequence(text_token_emb, text_token_len.cpu(), batch_first=True)speech_token_emb = unpad_sequence(speech_token_emb, speech_token_len.cpu(), batch_first=True)for i in range(len(text_token)):# bistream sequenceif random.random() < 0.5 and speech_token_len[i] / text_token_len[i] > self.mix_ratio[1] / self.mix_ratio[0]: # 满足音频大于text的倍数长度关系this_lm_target, this_lm_input = [], []this_lm_target.append(IGNORE_ID)this_lm_input.append(self.llm_embedding.weight[self.sos_eos].reshape(1, -1))for j in range(((text_token_len[i] + 1) / self.mix_ratio[0]).ceil().int().item()):this_text_token = text_token[i][j * self.mix_ratio[0]: (j + 1) * self.mix_ratio[0]].tolist()    # 每mix_radio(5)个文本token切成一个块this_speech_token = speech_token[i][j * self.mix_ratio[1]: (j + 1) * self.mix_ratio[1]].tolist()    # 每mix_radio(15)个语音token切成一个块if len(this_text_token) == self.mix_ratio[0]:assert len(this_speech_token) == self.mix_ratio[1]this_lm_target += [IGNORE_ID] * (self.mix_ratio[0] - 1)this_lm_target += this_speech_token # target: ignore_id * (5-1) + 15个语音tokenthis_lm_target.append(self.speech_token_size + 2)   # target: + eosthis_lm_input.append(text_token_emb[i][j * self.mix_ratio[0]: (j + 1) * self.mix_ratio[0]]) # input: 5个文本token对应的embeddingthis_lm_input.append(speech_token_emb[i][j * self.mix_ratio[1]: (j + 1) * self.mix_ratio[1]])  # input: + 15个语音token对应的embeddingelse:# 处理最后一个文本token不足5个的情况this_lm_target += [-1] * len(this_text_token)this_lm_target += speech_token[i][j * self.mix_ratio[1]:].tolist()this_lm_target.append(self.speech_token_size)this_lm_input.append(text_token_emb[i][j * self.mix_ratio[0]:])this_lm_input.append(self.llm_embedding.weight[self.task_id].reshape(1, -1))this_lm_input.append(speech_token_emb[i][j * self.mix_ratio[1]:])# 整体上target是token, input是embeddingthis_lm_target, this_lm_input = torch.tensor(this_lm_target), torch.concat(this_lm_input, dim=0)# unistream sequenceelse:this_lm_target = torch.tensor([IGNORE_ID] * (1 + text_token_len[i]) + speech_token[i].tolist() + [self.speech_token_size])this_lm_input = torch.concat([self.llm_embedding.weight[self.sos_eos].reshape(1, -1), text_token_emb[i],self.llm_embedding.weight[self.task_id].reshape(1, -1), speech_token_emb[i]], dim=0)lm_target.append(this_lm_target)lm_input.append(this_lm_input)lm_input_len = torch.tensor([i.size(0) for i in lm_input], dtype=torch.int32)lm_input = pad_sequence(lm_input, batch_first=True, padding_value=IGNORE_ID)lm_target = pad_sequence(lm_target, batch_first=True, padding_value=IGNORE_ID)return lm_target, lm_input, lm_input_len

cosyvoice/llm/llm.py

chunk aware flow-matching

在这里插入图片描述
两个核心点:

  1. 由于 semantic token 到 mel 的映射使用的是因果的 transformer(即只能看到之前的信息,用 mask 实现的),所以可以用过 mask 来控制因果长度,即上图提到的 chunk mask
  2. 由于 flow-matching 需要多步计算,直接把 unet 做成多次循环,看为多步计算。

遗留问题

  • instruct text 和 prompt text 的混用,只用 <|endofprompt|> 标识做区分,模型会混淆吗?而且,llm_prompt_speech_token 被删除,会导致音色一致性变差吗?(根本的问题是 semantic token 是否能跟音色完全解耦),这种设计是否需要优化,或者在训练模式上是否需要调整。
  • 文本和音频按N:M的比例混合训练,这种方式是否是比较合理的方式,因为N:M不能保证音频和文本token一定对应,这是个问题。有没有更好的设计方式?
  • chunk flow-matching 的训练设计比较麻烦,整体上有没有更简洁的方案?

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

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

相关文章

-lstdc++与-static-libstdc++的用法和差异

CMakeLists.txt 里写了&#xff1a; target_link_libraries(${PROJECT_NAME} PRIVATEgccstdc ) target_link_options(${PROJECT_NAME} PRIVATE -static-libstdc)看起来像是“链接了两次 C 标准库”&#xff0c;其实它们的作用完全不同&#xff1a;1. target_link_libraries(...…

Redis学习其二(事务,SpringBoot整合,持久化RDB和AOF)

文章目录5,事务5.1Redis 事务不保证原子性的原因5.2事务操作过程5.3监控6,SpringBoot整合Redis6.1Redis客户端6.1.1Jedis简单使用6.1.2Lettuce&Jedis6.2配置相关6.3使用6.3.1使用RedisTemplate6.3.2Redis工具类7,持久化RDB7.1RDB持久化原理7.2触发机制save命令flushall命令…

springboot项目部署到K8S

java后台 创建harbor镜像拉取Secret&#xff1a;kubectl create secret docker-registry harbor-regcred \--docker-server \ #harbor仓库地址--docker-username \ #harbor 账号--docker-password \ #harbor密码-n productionDockerfile FROM *harbor地址*/library/custom-jdk…

【FPGA开发】一文轻松入门Modelsim的基本操作

Modelsim仿真的步骤 &#xff08;1&#xff09;创建新的工程。 &#xff08;2&#xff09;在弹出的窗口中&#xff0c;确定项目名和工作路径&#xff0c;库保持为work不变(如有需要可以根据需求进行更改)。 &#xff08;3&#xff09;添加已经存在的文件&#xff08;rtl代码和t…

服务攻防-Java组件安全FastJson高版本JNDI不出网C3P0编码绕WAF写入文件CI链

服务攻防-Java组件安全&FastJson&高版本JNDI&不出网C3P0&编码绕WAF&写入文件CI链26天 原创 朝阳 Sec朝阳 2025年07月18日 09:23 湖北 标题已修改 演示环境&#xff1a; https://github.com/lemono0/FastJsonParty FastJson全版本Docker漏洞环境(涵盖1.…

【Python】DRF核心组件详解:Mixin与Generic视图

在 Django REST Framework (DRF) 中&#xff0c;mixins.CreateModelMixin、mixins.ListModelMixin、GenericAPIView 和 GenericViewSet 是构建 API 视图的核心组件。以下是对这些组件的主要方法及其职责的简要说明&#xff0c;内容清晰且结构化&#xff1a;1. mixins.CreateMod…

HTML+CSS+JS基础

文章目录&#xff08;一&#xff09;html1.常见标签&#xff08;1&#xff09;注释&#xff08;2&#xff09;标题 h1~h6&#xff08;3&#xff09;段落 p&#xff08;4&#xff09;换行与空格 br \ &#xff08;5&#xff09;格式化标签 b i s u&#xff08;6&#xff09;…

Vue导出Html为Word中包含图片在Microsoft Word显示异常问题

问题背景 碰到一个问题&#xff1a;将包含图片和SVG数学公式的HTML内容导出为Word文档时&#xff0c;将图片都转为ase64格式导出&#xff0c;在WPS Word中显示正常&#xff0c;但是在Microsoft Word中出现图片示异常。具体问题表现 WPS兼容性&#xff1a;在WPS中显示正常&#…

椭圆曲线密码学 Elliptic Curve Cryptography

密码学是研究在存在对抗行为的情况下还能安全通信的技术。即算法加密信息&#xff0c;再算法解密出信息。加密分为两类 1. Symmetric-key Encryption (secret key encryption) 即一种密钥&#xff0c;加密和解密使用同一密钥&#xff0c;可相互转换 2. Asymmetric-key Encry…

wedo牛-----第47节(免费分享图纸)

夸克网盘&#xff1a;https://pan.quark.cn/s/4b40a8d18979 高清图纸源文件&#xff0c;需要的请自取

Unity | AmplifyShaderEditor插件基础(第十集:噪声的种类+火焰制作-下)

目录 一、&#x1f44b;&#x1f3fb;前言 二、圆火焰 三、制作梯度 梯度成品预览 1.GradientSample节点 2.gradient的用法 3.time节点 四、添加颜色 Color节点 五、火焰摇摆 1.X方向的移动 2.Y方向的移动 3.Z方向的移动 4.把xyz组合起来 Panner节点 六、摆放和…

黑马Node.js全套入门教程,nodejs新教程含es6模块化+npm+express+webpack+promise等_ts对象笔记

1.1 什么是运行环境&#xff1f; 运行环境是指代码正常运行所需的必要环境&#xff01;&#xff01;&#xff01;&#xff01;&#xff01; V8引擎负责解析和执行JavaScript代码。内置API是由运行环境提供的特殊接口&#xff0c;只能在所属的运行环境中被调用 1.2 JavaScrip…

React 项目环境变量使用指南

在 React 项目中正确使用环境变量是管理不同环境配置的关键技术。以下是完整的解决方案&#xff1a; 1. 创建环境变量文件 React 项目支持以下环境变量文件&#xff08;按优先级从高到低&#xff09;&#xff1a; .env.development.local (本地开发环境).env.development (开发…

Oracle 关于一些连接故障的总结

积累了几次Oracle客户端连接故障&#xff0c;做下总结。 文章目录1、案例案例1&#xff1a;客户端连接报错ORA-12514案例2&#xff1a;客户端连接报错ORA-28547案例3&#xff1a;客户端连接报错&#xff1a;Got minus one from a read call案例4&#xff1a;客户端连接报错&…

V-USB USB设备模拟原理分析

V-USB USB设备模拟原理分析 通过分析V-USB项目的核心文件&#xff0c;详细解释这个项目是如何在AVR微控制器上模拟USB设备的&#xff1a; 1. 整体架构 V-USB是一个纯软件实现的USB低速设备驱动&#xff0c;主要由以下几个核心文件组成&#xff1a; usbdrv.c : USB协议栈的C语言…

kafka3.6下载安装(传统架构/KRaft模式)+实例测试

知识补充&#xff1a; Kafka 和 ZooKeeper 的关系可以用 “协作依赖” 来概括。在 Kafka 的早期版本&#xff08;Kafka 2.8.0 之前&#xff09;中&#xff0c;ZooKeeper 是 Kafka 的核心依赖&#xff0c;用于管理集群元数据、协调 Broker 和 Controller 选举等关键功能。但从 …

华控智能产品特点——产品生态全景与场景化创新

公司构建 “3X”产品战略&#xff0c;以三大核心场景为基础持续拓展技术外延&#xff1a; 1. 智能安防产品线军工级指纹枪盒&#xff1a;采用6061-T6航空铝材&#xff0c;内嵌震动报警模块&#xff0c;非法开箱触发90dB警鸣。为军工企业定制的双人认证版本需两位授权人员同时验…

爬虫核心原理与入门技巧分析

一、爬虫核心原理&#xff1a;模拟人类浏览的“自动化工具” 简单来说&#xff0c;网络爬虫&#xff08;Web Crawler&#xff09;是一种按照一定规则&#xff0c;自动抓取互联网信息的程序或脚本。其核心原理可以类比人类浏览网页的过程&#xff0c;只不过将手动操作转化为了代…

spring-cloud微服务部署-feign服务间调用

1 准备工作 需要安装并启动nacos&#xff0c;作为服务注册中心。地址&#xff1a;https://nacos.io/ 2 项目结构 parent的pom.xml声明依赖&#xff1a; <dependencyManagement><dependencies><dependency><groupId>org.springframework.boot</gr…

IDEA高效开发:Database Navigator插件安装与核心使用指南

目录 1.前言 2.正文 2.1安装流程 2.1.1IDE内部安装 2.1.2手动下载安装 ⚠️ 避坑指南 2.2使用教程 2.2.1连接数据库 2.2.2查看数据库/表 2.2.3查询数据 2.2.4修改表结构 2.2.5生成代码 2.2.6常见故障排除 3.小结 1.前言 “作为Java开发者&#xff0c;日常与数据…