一、光盘复制技术:一种便捷高效的数据复制方式
光盘复制技术简介
光盘复制技术是一种常见的数据复制方式,它能够在不损坏原始光盘数据的情况下,通过制作光盘副本来进行数据的传输和备份。与直接复制不同,光盘复制技术采用专业的设备和软件来实现,以确保复制的质量和准确性。
光盘复制的基本原理
在光盘复制过程中,首先需要使用光盘复制机或电脑光驱来读取原始光盘的数据。读取后的数据会通过复制机或电脑,写入到一个新的空白光盘上。复制的速度和效果取决于复制机的性能和光盘的质量。
刻录和复制的区别
刻录和复制是两种不同的技术操作。刻录是将数据写入空白光盘的过程,而复制是通过读取原始光盘的数据,制作光盘副本的过程。刻录针对空白光盘,而复制需要有一个已有的原始光盘。
光盘复制的优势
- 便捷性:光盘复制技术能够在较短的时间内制作多个光盘副本,非常适合大批量的数据复制需求。
- 高效性:使用专业的光盘复制设备和软件,数据复制的速度更快,且质量更稳定,避免了人工复制产生的错误。
- 准确性:光盘复制技术能够确保复制后的光盘与原始光盘一致,数据无损失,完全保留了原始信息。
- 易操作:只需要将原始光盘放入复制机或电脑的光驱,然后选择复制的目标和数量,即可开始复制,操作简单方便。
常见的光盘复制场景
光盘复制技术广泛应用于以下场景:
- 软件光盘的复制和分发
- 音视频光盘的复制和销售
- 数据备份和存档
- 教育培训材料的复制
通过光盘复制技术,我们能够快速、准确地进行大量数据的复制和传输,为许多领域的工作提供了便利和高效性。
感谢您阅读本文,希望本文能够帮助您更好地了解光盘复制技术以及其在现实生活中的应用。
二、全面解析大数据复制技术及其应用
随着大数据的发展,数据的数量和种类在不断增加,而同时,如何有效地管理和利用这些数据也成为了一个重要的话题。数据复制作为一种常见的数据管理技术,在大数据环境中显得尤为重要。本文将系统地探讨大数据复制的概念、技术、应用场景以及面临的挑战,帮助读者更好地理解这一领域。
什么是大数据复制?
大数据复制是指在一个或多个数据存储系统之间,将数据的副本进行传输和存储的过程。其主要目的是保证数据的高可用性和数据的备份恢复。通过数据复制,即便原始数据发生丢失或故障,用户仍可从备份中恢复数据,从而保证数据的安全性和可读性。
大数据复制的种类
根据不同的需求和场景,大数据复制可以分为以下几种类型:
- 全量复制:将源数据集的全部数据复制到目标数据集中。这种复制方式通常用于数据整合及系统迁移。当需要在不同的数据库中保持数据一致性时,全量复制是较为常见的选择。
- 增量复制:仅复制源数据集中发生变化的数据。这种方式通常效率较高,适合定期更新数据的应用场景。
- 异步复制:源数据和目标数据之间的复制不需要实时进行,通常用于负载均衡。在数据的更新间隔内,可以减少系统资源的占用。
- 同步复制:数据在源和目标之间实时同步更新,确保一致性。这对于需要保证数据即时性和准确性的场景至关重要。
大数据复制的技术实现
大数据复制的实现可采用多种技术手段。以下是当前主流的几种实现方式:
- 数据复制工具:市面上有多种数据复制工具,如Apache NiFi、Talend和AWS Data Pipeline等,这些工具能够批量处理数据的复制,并提供图形化界面,使用户操作更加简单直观。
- 数据库的内置复制功能:大多数现代数据库管理系统(如MySQL、PostgreSQL、Oracle等)都具备内置的数据复制功能,用户可以通过简单配置实现数据的实时或异步复制。
- 消息队列:通过消息队列(如Kafka、RabbitMQ等),可以实现数据的异步复制,适合大规模数据流的实时处理。
大数据复制的应用场景
大数据复制在各行业中都有广泛的应用,以下是几个典型的应用场景:
- 数据备份与恢复:数据复制可以用于定期备份重要数据,以防止因意外事情导致数据丢失。
- 数据迁移:在系统升级或数据中心迁移时,数据复制可以确保在切换过程中数据的完整性和可用性。
- 数据分析与数据仓库:复制机制可将多个数据源中的数据整合到数据仓库中,为商业智能和数据分析提供支持。
- 负载均衡:通过在多个系统中复制数据,可以实现负载均衡,提升系统性能与响应速度。
大数据复制的挑战
虽然大数据复制技术带来了许多便利,但在其实施中也面临着一些挑战:
- 数据一致性:在异步复制过程中,可能会出现数据不一致的情况,如何保证数据的一致性是技术实现中的一大难点。
- 性能影响:在数据量极大的情况下,复制过程可能会消耗大量的带宽及存储资源,影响系统的性能。
- 数据安全:数据在复制过程中可能面临被未授权访问的风险,因此需要采取一定的安全措施,保护数据安全。
- 管理复杂性:数据复制涉及多个系统之间的交互和管理,易导致相关管理操作的复杂性。
总结
大数据复制是一项极为重要的技术,涉及数据的安全性、一致性和可用性。随着大数据的日益普及,了解大数据复制的相关知识将有助于企业在数据管理上做出更明智的决策。希望通过本文的介绍,能够帮助您更加深入地理解大数据复制的技术及其重要性。
感谢您花时间阅读这篇文章,希望它能帮助您更好地理解大数据复制的相关内容。如果您对大数据复制还有更深入的兴趣,欢迎随时进行更深层次的研究与探讨!
三、大屏数据可视化怎么实时更新?
要实现大屏数据的实时更新,可以采用以下方法:
首先,建立一个数据源,可以是数据库、API接口或实时数据流。
然后,使用前端技术(如JavaScript、HTML、CSS)开发大屏页面,通过定时器或WebSocket等技术,定期或实时地从数据源获取最新数据,并将其更新到大屏上。
同时,可以使用数据可视化库(如D3.js、ECharts)将数据转化为图表、地图等形式,以便更直观地展示数据。
最后,通过服务器部署和网络传输等方式,确保大屏页面能够实时获取最新数据并展示给用户。
四、怎样利用SQLServer复制技术实现数据同步更新?
在两个SQLSERVER之间实现数据同步:
第一先来配置出版服务器
(1)选中指定[服务器]节点
(2)从[工具]下拉菜单的[复制]子菜单中选择[发布、订阅服务器和分发]命令
(3)系统弹出一个对话框点[下一步]然后看着提示一直操作到完成。
(4)当完成了出版服务器的设置以后系统会为该服务器的树形结构中添加一个复制监视器。同时也生成一个分发数据库(distribution)
第二创建出版物
(1)选中指定的服务器
(2)从[工具]菜单的[复制]子菜单中选择[创建和管理发布]命令。此时系统会弹出一个对话框
(3)选择要创建出版物的数据库,然后单击[创建发布]
(4)在[创建发布向导]的提示对话框中单击[下一步]系统就会弹出一个对话框。对话框上的内容是复制的三个类型。我们现在选第一个也就是默认的快照发布(其他两个大家可以去看看帮助)
(5)单击[下一步]系统要求指定可以订阅该发布的数据库服务器类型,SQLSERVER允许在不同的数据库如 ORACLE或ACCESS之间进行数据复制。但是在这里我们选择运行"SQL SERVER 2000"的数据库服务器
(6)单击[下一步]系统就弹出一个定义文章的对话框也就是选择要出版的表
(7)然后[下一步]直到操作完成。当完成出版物的创建后创建出版物的数据库也就变成了一个共享数据库。
第三设计订阅
(1)选中指定的订阅服务器
(2)从[工具]下拉菜单中选择[复制]子菜单的[请求订阅]
(3)按照单击[下一步]操作直到系统会提示检查SQL SERVER代理服务的运行状态,执行复制操作的前提条件是SQL SERVER代理服务必须已经启动。
(4)单击[完成]。
五、巨量千川大屏实时数据代表什么?
巨量千川大屏实时数据代表着大规模数据的实时监测和分析。它可以提供关于市场趋势、用户行为、产品销售等方面的详细信息。通过分析这些数据,企业可以了解市场需求、优化产品策略、改进营销活动等,从而做出更明智的决策。巨量千川大屏实时数据的价值在于帮助企业抓住市场机会、提高竞争力,并实现业务增长和盈利。
六、MySQL字段复制技巧大揭秘,轻松实现字段复制和数据同步
MySQL字段复制技巧
在数据库管理中,经常会遇到需要复制字段的情况。MySQL作为一种流行的关系型数据库管理系统,其字段复制技巧尤为重要。
一、使用ALTER TABLE语句进行字段复制
可以通过ALTER TABLE语句,将已存在的字段复制出一个新的字段。语法如下:
ALTER TABLE table_name
ADD new_column_name column_definition AFTER existing_column_name;
二、使用INSERT INTO SELECT语句进行数据同步
假设需要将表A的字段复制到表B中,可以使用INSERT INTO SELECT语句来实现:
INSERT INTO table_B (column1, column2, ...)
SELECT column1, column2, ...
FROM table_A;
三、使用工具进行数据同步
除了以上SQL语句,还可以借助一些第三方工具来实现字段复制和数据同步,例如DataGrip、Navicat等,它们提供了图形化界面方便进行表结构的复制和数据同步操作。
四、注意事项
- 在进行字段复制和数据同步时,建议先备份数据,以免操作失误导致数据丢失。
- 应当考虑目标表的结构是否与源表一致,避免字段类型不匹配等问题。
- 复制大量数据时,应当注意数据库性能和网络带宽的影响,可以选择合适的时间段进行操作。
通过以上技巧,我们可以轻松实现MySQL字段的复制和数据的同步,为数据库管理带来极大的便利。
感谢您阅读本文,希望能对您在数据库管理中遇到的字段复制问题提供帮助。
七、实时数据库和历史数据库哪个占用内存大?
不一定。
取决于在库上的用户数、做的操作。通常,实时数据库并发用户多、单个操作简单; 历史数据库则单个操作复杂(经常用于统计)。八、如何评价百度开发的「声音克隆」技术,半小时训练数据即可复制声音?
(以下内容搬运自飞桨PaddleSpeech语音技术课程,点击链接可直接运行源码)
一句话语音合成全流程实践
1 声音克隆介绍 & 语音合成基本概念回顾
语音合成(Speech Sysnthesis),又称文本转语音(Text-to-Speech, TTS),指的是将一段文本按照一定需求转化成对应的音频的技术。
1.1 声音克隆的应用场景
随着以语音为交互渠道的产业不断升级,企业对语音合成有着越来越多的需求,比如智能语音助手、手机地图导航、有声书播报等场景都需要用到语音合成技术。通过语音合成技术想要得到一个新的音色,需要定制音库,但是定制音库所耗费的人力成本和时间成本巨大,成为产业升级的屏障。
声音克隆一般是指 one-shot TTS ,即只需要一条参考音频就可以合成该音色的语音,而无需收集大量该音色的音频数据进行训练。
1.2 声音克隆和语音合成的关系
声音克隆属于语音合成的一个小分类,想要合成一个人的声音,可以收集大量该说话人的声音数据进行标注(一般至少一小时,1400+ 条数据),训练一个语音合成模型,也可以用一句话声音克隆方案来实现。
声音克隆模型本质是语音合成的声学模型。
一句话声音克隆的效果没有收集大量数据集训练或收集少量数据集 fintune 一个语音合成模型的效果好,其效果是否可以在商业中落地还有待商榷。
一般商业应用中想要合成某个特定的音色,需要收集大量数据进行训练,即使类似于百度地图的定制化音色播报,也是采用某种小样本 finetune的方案,至少需要用户录制 9 ~ 20 句指定文本内容的音频。
1.3 语音合成的基本流程回顾
本教程主要讲解基于深度学习的语音合成技术,流水线包含 文本前端(Text Frontend)、声学模型(Acoustic Model) 和 声码器(Vocoder) 三个主要模块:
- 文本前端模块将原始文本转换为字符/音素
- 声学模型将字符/音素转换为声学特征,如线性频谱图、mel 频谱图、LPC 特征等
- 声码器将声学特征转换为波形
语音合成基本流程图
1.3.1 文本前端
文本前端模块主要包含: 分段(Text Segmentation)、文本正则化(Text Normalization, TN)、分词(Word Segmentation, 主要是在中文中)、词性标注(Part-of-Speech, PoS)、韵律预测(Prosody)和字音转换(Grapheme-to-Phoneme,G2P)等。
其中最重要的模块是 文本正则化 模块和 字音转换(TTS 中更常用 G2P 代指) 模块。
各模块输出示例:
• Text: 全国一共有112所211高校
• Text Normalization: 全国一共有一百一十二所二一一高校
• Word Segmentation: 全国/一共/有/一百一十二/所/二一一/高校/
• G2P(注意此句中“一”的读音):
quan2 guo2 yi2 gong4 you3 yi4 bai3 yi1 shi2 er4 suo3 er4 yao1 yao1 gao1 xiao4
(可以进一步把声母和韵母分开)
q uan2 g uo2 y i2 g ong4 y ou3 y i4 b ai3 y i1 sh i2 er4 s uo3 er4 y ao1 y ao1 g ao1 x iao4
(把音调和声韵母分开)
q uan g uo y i g ong y ou y i b ai y i sh i er s uo er y ao y ao g ao x iao
0 2 0 2 0 2 0 4 0 3 ...
• Prosody (prosodic words #1, prosodic phrases #2, intonation phrases #3, sentence #4):
全国#2一共有#2一百#1一十二所#2二一一#1高校#4
(分词的结果一般是固定的,但是不同人习惯不同,可能有不同的韵律)
1.3.2 声学模型
声学模型将字符/音素转换为声学特征,如线性频谱图、mel 频谱图、LPC 特征等。声学特征以 “帧” 为单位,一般一帧是 10ms 左右,一个音素一般对应 5~20 帧左右。声学模型需要解决的是 “不等长序列间的映射问题”,“不等长”是指,同一个人发不同音素的持续时间不同,同一个人在不同时刻说同一句话的语速可能不同,对应各个音素的持续时间不同,不同人说话的特色不同,对应各个音素的持续时间不同。这是一个困难的 “一对多” 问题。
# 卡尔普陪外孙玩滑梯
000001|baker_corpus|sil 20 k 12 a2 4 er2 10 p 12 u3 12 p 9 ei2 9 uai4 15 s 11 uen1 12 uan2 14 h 10 ua2 11 t 15 i1 16 sil 20
声学模型主要分为自回归模型和非自回归模型。自回归模型在 t
时刻的预测需要依赖 t-1
时刻的输出作为输入,预测时间长,但是音质相对较好;非自回归模型不存在预测上的依赖关系,预测时间快,音质相对较差。
主流声学模型: - 自回归模型: Tacotron、Tacotron2 和 Transformer TTS 等 - 非自回归模型: FastSpeech、SpeedySpeech、FastPitch 和 FastSpeech2 等
1.3.3 声码器
声码器将声学特征转换为波形,它需要解决的是 “信息缺失的补全问题”。信息缺失是指,在音频波形转换为频谱图时,存在相位信息的缺失;在频谱图转换为 mel 频谱图时,存在频域压缩导致的信息缺失。假设音频的采样率是 16kHz, 即 1s 的音频有 16000 个采样点,一帧的音频有 10ms,则 1s 中包含 100 帧,每一帧有 160 个采样点。声码器的作用就是将一个频谱帧变成音频波形的 160 个采样点,所以声码器中一般会包含上采样模块。
与声学模型类似,声码器也分为自回归模型和非自回归模型: - 自回归模型:WaveNet、WaveRNN 和 LPCNet 等 - 非自回归模型:Parallel WaveGAN、Multi Band MelGAN、Style MelGAN 和 HiFiGAN 等
更多关于语音合成基础的精彩细节,请参考之前的课程。
2 基于说话人嵌入的声音克隆:SV2TTS
2.1 基本原理
SV2TTS 论文全称是 Transfer Learning from Speaker Verification to Multispeaker Text-To-Speech Synthesis, 是 Google 发表在 NeurIPS 2018 上的文章。
SV2TTS 模型结构图
SV2TTS 的声学模型使用了 Tacotron2,声码器使用了 WaveNet, 用于提取 speaker embedding 的声纹模型选择了 GE2E。
SV2TTS 原作的开源代码是 Real-Time-Voice-Cloning, 仅支持英文合成,代码实现中使用的声码器是 WaveRNN,MockingBird fork 自原作仓库并支持了中文合成。
在 Speaker Encoder、Synthesizer 和 Vocoder 阶段,PaddleSpeech 提供了不同的说话人编码器、合成器以及声码器组合。
|Speaker Encoder|Synthesizer|Vocoder| | :---:| :---: | :---: | |GE2E / ECAPA-TDNN |Tacotron2 / FastSpeech2|GAN Vocoder(Parallel WaveGAN / HiFiGAN / ...)|
2.2 模型训练
2.2.1 声纹模型
PaddleSpeech 已提供了预训练好的声纹模型,相关训练代码请参考 GE2E 和 ECAPA-TDNN。 PaddleSpeech 声纹相关课程请参考声纹检索系统与实践。
2.2.2 声学模型
SV2TTS 与多说话人声学模型的区别是:多说话人声学模型在训练模型的时候,输入 spk_id
标识不同的说话人,模型内通过 Speaker Embedding Table (nn.Embedding
类)获取 speaker embeding,预测时只能选择在训练时包含的 spk_id
,只能合成训练集内的音色;而 SV2TTS 通过预训练好的声纹模型提取 speaker embeding,预测时可以输入任意说话人的音频作为参考音频,即使该说话人不在训练集中,也可以合成具有其音色的音频。
以 FastSpeech2 为例,两者的区别仅仅是红框所标部分。
基于 FastSpeech2 的多说话人语音合成模型
2.2.3 声码器
声音克隆模型本质是语音合成声学模型,声码器可以直接使用 PaddleSpeech 提供的各种声码器:Parallel WaveGAN、Multi Band MelGAN、Style MelGAN 和 HiFiGAN 等, 由于声音克隆会见到各种不同的音色,建议使用 PaddleSpeech 提供的在多说话人数据集 AISHELL-3 和 VCTK 上训练的声码器。
声码器和数据集相关,如果待合成音色是成年女性音色,用 CSMSC(成年女性单说话人数据集)的声码器效果可能会更好,若待合成音色是男性音色,由于和女性声音特征相差较大,用 CSMSC 数据集训练的声码器的表现就不会很好,AISHELL-3、VCTK、CSMSC 都是 24k 的,声码器可以任意换,只是效果好不好的问题。
使用自己的数据重新训练或者 finetune 这些声码器,合成的音频会有更好的音质。
2.3 实践
以 ECAPA-TDNN 声纹模型 + FastSpeech2 声学模型为例,下列代码修改自 voice_cloning.py。
安装 paddlespeech
# pip install paddlespeech or
!git clone https://github.com/PaddlePaddle/PaddleSpeech.git
from IPython.display import clear_output
%cd PaddleSpeech
!pip install .
%cd -
# 清理很长的内容
clear_output()
# 本项目的依赖需要用到 nltk 包,但是有时会因为网络原因导致不好下载,此处手动下载一下放到百度服务器的包
!wget https://paddlespeech.bj.bcebos.com/Parakeet/tools/nltk_data.tar.gz
!tar zxvf nltk_data.tar.gz
clear_output()
获取预训练模型和数据
!wget -P download https://paddlespeech.bj.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_aishell3_ckpt_vc2_1.2.0.zip
!unzip -o -d download download/fastspeech2_aishell3_ckpt_vc2_1.2.0.zip
!wget -P download https://paddlespeech.bj.bcebos.com/Parakeet/released_models/pwgan/pwg_aishell3_ckpt_0.5.zip
!unzip -o -d download download/pwg_aishell3_ckpt_0.5.zip
clear_output()
获取 ref_audio
!wget -P download https://paddlespeech.bj.bcebos.com/Parakeet/docs/demos/ref_audio.zip
!unzip -o -d download download/ref_audio.zip
clear_output()
导入 Python 包
# 设置 gpu 环境
%env CUDA_VISIBLE_DEVICES=0
import logging
import sys
import warnings
warnings.filterwarnings("ignore", category=DeprecationWarning)
import os
from pathlib import Path
import numpy as np
import paddle
import soundfile as sf
import yaml
from yacs.config import CfgNode
from paddlespeech.cli.vector import VectorExecutor
from paddlespeech.t2s.exps.syn_utils import get_am_inference
from paddlespeech.t2s.exps.syn_utils import get_voc_inference
from paddlespeech.t2s.frontend.zh_frontend import Frontend
clear_output()
主程序
am ='fastspeech2_aishell3'
am_config = 'download/fastspeech2_aishell3_ckpt_vc2_1.2.0/default.yaml'
am_ckpt = 'download/fastspeech2_aishell3_ckpt_vc2_1.2.0/snapshot_iter_96400.pdz'
am_stat = 'download/fastspeech2_aishell3_ckpt_vc2_1.2.0/speech_stats.npy'
phones_dict = "download/fastspeech2_aishell3_ckpt_vc2_1.2.0/phone_id_map.txt"
voc = 'pwgan_aishell3'
voc_config = 'download/pwg_aishell3_ckpt_0.5/default.yaml'
voc_ckpt = 'download/pwg_aishell3_ckpt_0.5/snapshot_iter_1000000.pdz'
voc_stat = 'download/pwg_aishell3_ckpt_0.5/feats_stats.npy'
# 读取 conf 配置文件并结构化
with open(am_config) as f:
am_config = CfgNode(yaml.safe_load(f))
with open(voc_config) as f:
voc_config = CfgNode(yaml.safe_load(f))
# 加载模型,第一次使用 vec_executor 时候会下载模型
# speaker encoder
vec_executor = VectorExecutor()
frontend = Frontend(phone_vocab_path=phones_dict)
print("frontend done!")
# acoustic model
am_inference = get_am_inference(
am=am,
am_config=am_config,
am_ckpt=am_ckpt,
am_stat=am_stat,
phones_dict=phones_dict)
# vocoder
voc_inference = get_voc_inference(
voc=voc,
voc_config=voc_config,
voc_ckpt=voc_ckpt,
voc_stat=voc_stat)
ref_audio_path = 'download/ref_audio/yuantian01_02.wav'
sentence = '每当你觉得,想要批评什么人的时候,你切要记着,这个世界上的人,并非都具备你禀有的条件。'
input_ids = frontend.get_input_ids(sentence, merge_sentences=True)
phone_ids = input_ids["phone_ids"][0]
spk_emb = vec_executor(audio_file=ref_audio_path, force_yes=True)
spk_emb = paddle.to_tensor(spk_emb)
with paddle.no_grad():
wav = voc_inference(am_inference(phone_ids, spk_emb=spk_emb))
sf.write(
"output.wav",
wav.numpy(),
samplerate=am_config.fs)
print("Voice Cloning done!")
# 播放参考音频
import IPython.display as dp
dp.Audio("download/ref_audio/yuantian01_02.wav")
# 播放生成的音频
dp.Audio('output.wav', rate=am_config.fs)
SV2TTS 的效果受多说话人数据集和 Speaker Encoder 模型的影响较大,新发音人的声音会跟提取的 speaker embedding 在整个发音人向量空间中的最接近的那几个人的音色会比较像,因此一句话合成整体音色的效果因人而异,音色学习效果并不稳定。
具体实现代码请参考:
3 端到端声音克隆:ERNIE-SAT
ERNIE-SAT 是百度自研的文心大模型,是可以同时处理中英文的跨语言的语音-语言跨模态大模型,其在语音编辑、个性化语音合成以及跨语言的语音合成等多个任务取得了领先效果。可以应用于语音编辑、个性化合成、语音克隆、同传翻译等一系列场景。
语音编辑的应用场景
3.1 基本原理
3.1.1 A3T 简介
ERNIE-SAT 是基于百度自研模型 A3T: Alignment-Aware Acoustic and Text Pretraining for Speech Synthesis and Editing 的改进,A3T 提出了一种对齐感知的声学、文本预训练模型,可以重建高质量的语音信号,多用于语音编辑任务。
训练时,根据 MFA 获取 mel 频谱和音素的对齐信息,mask 住单词文本对应的 mel 频谱,并对其进行重建。
A3T 模型结构图
预测时,使用额外的 Duration Predictor 模块(如,预训练好的 FastSpeech2 模型的 duration_predictor)获取待重建音频(输入文本对应的音频)的时长,构造相应的长度的空 mel 频谱并 mask 住,模型预测对应的 mel 频谱。
A $\color{red}{good}$ actor -> A $\color{blue}{successful}$ actor
语音编辑流程图
3 种不同的语音编辑
3.1.2 模型框架
ERNIE-SAT 中提出了 3 项创新: - 提出了一个通用的端到端语音和文本联合预处理框架用于跨语言语音合成,它可以联合学习语音和文本输入的统一表示。 - 由于多语语音语料库有限,有效地利用多个单语语音数据在单一模型中构建双语音素列表,并利用不同语言的数据重建语音和文本的训练目标。模型在跨语言推理过程中可生成高质量的语音。 - 能够对看不见的说话人执行跨语言语音合成,并且优于基于说话人嵌入的多说话人 TTS 方法(SV2TTS)。
ERNIE-SAT 模型结构图
ERNIE-SAT 是基于 A3T 的改进,A3T 没有对文本(phoneme)做 mask,只对语音(mel 频谱)做了 mask,只能对被 mask 住的语音做高质量重建,ERNIE-SAT 同时对语音和文本做 mask,可以同时重建语音信息和文本信息;此外,A3T 只能处理单语言的情况,并不支持跨语言合成,ERNIE-SAT 可以实现跨语言合成: 1. 纯中文和纯英文的 ERNIE-SAT,模型结构和 A3T 一样,直接使用 VCTK 数据集(英文)或 AISHELL-3 数据集(中文)进行训练 2. 中英文混合的 ERNIE-SAT 是语音和文本一起 mask,可以实现跨语言合成任务,混合 VCTK 数据集(英文)和 AISHELL-3 数据集(中文)进行训练 - 随机 mask 住 80% 的 mel 频谱特征 - 再 mask 住剩余的 20% 的 mel 频谱特征对应的 phoneme 里的一半
3.2 ERNIE-SAT 和 SV2TTS 的区别与联系
- SV2TTS 和 ERNIE-SAT 本质都是语音合成声学模型,需要输入合成文本信息,输出 mel 频谱特征,其后需要接声码器才能合成音频,都属于 one-shot TTS 模型。
- SV2TTS 和 ERNIE-SAT 都是声音克隆模型,都需要输入参考音频获取合成音频的音色信息。
- SV2TTS 需要额外的声纹模型作为 speaker encoder 提取参考音频的 speaker embedding 作为输入,在训练和预测时,并不是一个 end-to-end 的系统;ERNIE-SAT 直接输入参考音频的 mel 频谱获取音色特征,在训练和预测时都是完全 end-to-end 的。
- 对于 SV2TTS 所需的声纹模型来说,在低资源的语言场景中,收集大量多说话人、多语言数据来训练模型提取 speaker embedding 非常困难。
- SV2TTS 仅有声音克隆功能,ERNIE-SAT 在声音克隆的基础上,可同时完成语音编辑以及跨语言的语音合成任务。
3.3 实践
纯中文或纯英文的 ERNIE-SAT 支持语音编辑和个性化合成,中英文混合的 ERNIE-SAT 支持跨语言合成,本质都是声音克隆。
以英文语音编辑为例,下列代码修改自 ernie_sat/synthesize_e2e.py,环境准备参考 vctk/ernie_sat。
For that reason cover $\color{red}{should}$ $\color{red}{not}$ be given -> For that reason cover $\color{blue}{is}$ $\color{blue}{not}$ $\color{blue}{impossible}$ $\color{blue}{to}$ be given
获取预训练模型和数据
# prepare aligner
!mkdir -p tools/aligner
%cd tools
# download MFA
# !wget https://github.com/MontrealCorpusTools/Montreal-Forced-Aligner/releases/download/v1.0.1/montreal-forced-aligner_linux.tar.gz
!wget https://paddlespeech.bj.bcebos.com/MFA/montreal-forced-aligner_linux.tar.gz
# extract MFA
!tar xvf montreal-forced-aligner_linux.tar.gz
# fix .so of MFA
%cd montreal-forced-aligner/lib
!ln -snf libpython3.6m.so.1.0 libpython3.6m.so
%cd -
# download align models and dicts
%cd aligner
!wget https://paddlespeech.bj.bcebos.com/MFA/ernie_sat/aishell3_model.zip
!wget https://paddlespeech.bj.bcebos.com/MFA/AISHELL-3/with_tone/simple.lexicon
!wget https://paddlespeech.bj.bcebos.com/MFA/ernie_sat/vctk_model.zip
!wget https://paddlespeech.bj.bcebos.com/MFA/LJSpeech-1.1/cmudict-0.7b
%cd ../../
clear_output()
# prepare pretrained FastSpeech2 models
!mkdir download
%cd download
!wget https://paddlespeech.bj.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_conformer_baker_ckpt_0.5.zip
!wget https://paddlespeech.bj.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_nosil_ljspeech_ckpt_0.5.zip
!unzip fastspeech2_conformer_baker_ckpt_0.5.zip
!unzip fastspeech2_nosil_ljspeech_ckpt_0.5.zip
%cd ../
clear_output()
# prepare source data
!mkdir source
%cd source
!wget https://paddlespeech.bj.bcebos.com/Parakeet/released_models/ernie_sat/source/SSB03540307.wav
!wget https://paddlespeech.bj.bcebos.com/Parakeet/released_models/ernie_sat/source/SSB03540428.wav
!wget https://paddlespeech.bj.bcebos.com/Parakeet/released_models/ernie_sat/source/LJ050-0278.wav
!wget https://paddlespeech.bj.bcebos.com/Parakeet/released_models/ernie_sat/source/p243_313.wav
!wget https://paddlespeech.bj.bcebos.com/Parakeet/released_models/ernie_sat/source/p299_096.wav
!wget https://paddlespeech.bj.bcebos.com/Parakeet/released_models/ernie_sat/source/this_was_not_the_show_for_me.wav
!wget https://paddlespeech.bj.bcebos.com/Parakeet/released_models/ernie_sat/source/README.md
%cd ../
clear_output()
# 下载预训练模型
!wget -P download https://paddlespeech.bj.bcebos.com/Parakeet/released_models/ernie_sat/erniesat_vctk_ckpt_1.2.0.zip
!unzip -o -d download download/erniesat_vctk_ckpt_1.2.0.zip
!wget -P download https://paddlespeech.bj.bcebos.com/Parakeet/released_models/hifigan/hifigan_vctk_ckpt_0.2.0.zip
!unzip -o -d download download/hifigan_vctk_ckpt_0.2.0.zip
clear_output()
导入 Python 包
import os
from pathlib import Path
from typing import List
import librosa
import numpy as np
import paddle
import pypinyin
import soundfile as sf
import yaml
from pypinyin_dict.phrase_pinyin_data import large_pinyin
from yacs.config import CfgNode
from paddlespeech.t2s.datasets.am_batch_fn import build_erniesat_collate_fn
from paddlespeech.t2s.datasets.get_feats import LogMelFBank
from paddlespeech.t2s.exps.ernie_sat.align import get_phns_spans
from paddlespeech.t2s.exps.ernie_sat.utils import eval_durs
from paddlespeech.t2s.exps.ernie_sat.utils import get_dur_adj_factor
from paddlespeech.t2s.exps.ernie_sat.utils import get_span_bdy
from paddlespeech.t2s.exps.ernie_sat.utils import get_tmp_name
from paddlespeech.t2s.exps.syn_utils import get_am_inference
from paddlespeech.t2s.exps.syn_utils import get_voc_inference
from paddlespeech.t2s.exps.syn_utils import norm
定义 ERNIE-SAT 所需功能函数
def _p2id(phonemes: List[str]) -> np.ndarray:
# replace unk phone with sp
phonemes = [phn if phn in vocab_phones else "sp" for phn in phonemes]
phone_ids = [vocab_phones[item] for item in phonemes]
return np.array(phone_ids, np.int64)
def prep_feats_with_dur(wav_path: str,
old_str: str='',
new_str: str='',
source_lang: str='en',
target_lang: str='en',
duration_adjust: bool=True,
fs: int=24000,
n_shift: int=300):
'''
Returns:
np.ndarray: new wav, replace the part to be edited in original wav with 0
List[str]: new phones
List[float]: mfa start of new wav
List[float]: mfa end of new wav
List[int]: masked mel boundary of original wav
List[int]: masked mel boundary of new wav
'''
wav_org, _ = librosa.load(wav_path, sr=fs)
phns_spans_outs = get_phns_spans(
wav_path=wav_path,
old_str=old_str,
new_str=new_str,
source_lang=source_lang,
target_lang=target_lang,
fs=fs,
n_shift=n_shift)
mfa_start = phns_spans_outs['mfa_start']
mfa_end = phns_spans_outs['mfa_end']
old_phns = phns_spans_outs['old_phns']
new_phns = phns_spans_outs['new_phns']
span_to_repl = phns_spans_outs['span_to_repl']
span_to_add = phns_spans_outs['span_to_add']
# 中文的 phns 不一定都在 fastspeech2 的字典里, 用 sp 代替
if target_lang in {'en', 'zh'}:
old_durs = eval_durs(old_phns, target_lang=source_lang)
else:
assert target_lang in {'en', 'zh'}, \
"calculate duration_predict is not support for this language..."
orig_old_durs = [e - s for e, s in zip(mfa_end, mfa_start)]
if duration_adjust:
d_factor = get_dur_adj_factor(
orig_dur=orig_old_durs, pred_dur=old_durs, phns=old_phns)
d_factor = d_factor * 1.25
else:
d_factor = 1
if target_lang in {'en', 'zh'}:
new_durs = eval_durs(new_phns, target_lang=target_lang)
else:
assert target_lang == "zh" or target_lang == "en", \
"calculate duration_predict is not support for this language..."
# duration 要是整数
new_durs_adjusted = [int(np.ceil(d_factor * i)) for i in new_durs]
new_span_dur_sum = sum(new_durs_adjusted[span_to_add[0]:span_to_add[1]])
old_span_dur_sum = sum(orig_old_durs[span_to_repl[0]:span_to_repl[1]])
dur_offset = new_span_dur_sum - old_span_dur_sum
new_mfa_start = mfa_start[:span_to_repl[0]]
new_mfa_end = mfa_end[:span_to_repl[0]]
for dur in new_durs_adjusted[span_to_add[0]:span_to_add[1]]:
if len(new_mfa_end) == 0:
new_mfa_start.append(0)
new_mfa_end.append(dur)
else:
new_mfa_start.append(new_mfa_end[-1])
new_mfa_end.append(new_mfa_end[-1] + dur)
new_mfa_start += [i + dur_offset for i in mfa_start[span_to_repl[1]:]]
new_mfa_end += [i + dur_offset for i in mfa_end[span_to_repl[1]:]]
# 3. get new wav
# 在原始句子后拼接
if span_to_repl[0] >= len(mfa_start):
wav_left_idx = len(wav_org)
wav_right_idx = wav_left_idx
# 在原始句子中间替换
else:
wav_left_idx = int(np.floor(mfa_start[span_to_repl[0]] * n_shift))
wav_right_idx = int(np.ceil(mfa_end[span_to_repl[1] - 1] * n_shift))
blank_wav = np.zeros(
(int(np.ceil(new_span_dur_sum * n_shift)), ), dtype=wav_org.dtype)
# 原始音频,需要编辑的部分替换成空音频,空音频的时间由 fs2 的 duration_predictor 决定
new_wav = np.concatenate(
[wav_org[:wav_left_idx], blank_wav, wav_org[wav_right_idx:]])
# 4. get old and new mel span to be mask
old_span_bdy = get_span_bdy(
mfa_start=mfa_start, mfa_end=mfa_end, span_to_repl=span_to_repl)
new_span_bdy = get_span_bdy(
mfa_start=new_mfa_start, mfa_end=new_mfa_end, span_to_repl=span_to_add)
# old_span_bdy, new_span_bdy 是帧级别的范围
outs = {}
outs['new_wav'] = new_wav
outs['new_phns'] = new_phns
outs['new_mfa_start'] = new_mfa_start
outs['new_mfa_end'] = new_mfa_end
outs['old_span_bdy'] = old_span_bdy
outs['new_span_bdy'] = new_span_bdy
return outs
def prep_feats(wav_path: str,
old_str: str='',
new_str: str='',
source_lang: str='en',
target_lang: str='en',
duration_adjust: bool=True,
fs: int=24000,
n_shift: int=300):
with_dur_outs = prep_feats_with_dur(
wav_path=wav_path,
old_str=old_str,
new_str=new_str,
source_lang=source_lang,
target_lang=target_lang,
duration_adjust=duration_adjust,
fs=fs,
n_shift=n_shift)
wav_name = os.path.basename(wav_path)
utt_id = wav_name.split('.')[0]
wav = with_dur_outs['new_wav']
phns = with_dur_outs['new_phns']
mfa_start = with_dur_outs['new_mfa_start']
mfa_end = with_dur_outs['new_mfa_end']
old_span_bdy = with_dur_outs['old_span_bdy']
new_span_bdy = with_dur_outs['new_span_bdy']
span_bdy = np.array(new_span_bdy)
mel = mel_extractor.get_log_mel_fbank(wav)
erniesat_mean, erniesat_std = np.load(erniesat_stat)
normed_mel = norm(mel, erniesat_mean, erniesat_std)
tmp_name = get_tmp_name(text=old_str)
tmpbase = './tmp_dir/' + tmp_name
tmpbase = Path(tmpbase)
tmpbase.mkdir(parents=True, exist_ok=True)
mel_path = tmpbase / 'mel.npy'
np.save(mel_path, normed_mel)
durations = [e - s for e, s in zip(mfa_end, mfa_start)]
text = _p2id(phns)
datum = {
"utt_id": utt_id,
"spk_id": 0,
"text": text,
"text_lengths": len(text),
"speech_lengths": len(normed_mel),
"durations": durations,
"speech": np.load(mel_path),
"align_start": mfa_start,
"align_end": mfa_end,
"span_bdy": span_bdy
}
batch = collate_fn([datum])
outs = dict()
outs['batch'] = batch
outs['old_span_bdy'] = old_span_bdy
outs['new_span_bdy'] = new_span_bdy
return outs
def get_mlm_output(wav_path: str,
old_str: str='',
new_str: str='',
source_lang: str='en',
target_lang: str='en',
duration_adjust: bool=True,
fs: int=24000,
n_shift: int=300):
prep_feats_outs = prep_feats(
wav_path=wav_path,
old_str=old_str,
new_str=new_str,
source_lang=source_lang,
target_lang=target_lang,
duration_adjust=duration_adjust,
fs=fs,
n_shift=n_shift)
batch = prep_feats_outs['batch']
new_span_bdy = prep_feats_outs['new_span_bdy']
old_span_bdy = prep_feats_outs['old_span_bdy']
out_mels = erniesat_inference(
speech=batch['speech'],
text=batch['text'],
masked_pos=batch['masked_pos'],
speech_mask=batch['speech_mask'],
text_mask=batch['text_mask'],
speech_seg_pos=batch['speech_seg_pos'],
text_seg_pos=batch['text_seg_pos'],
span_bdy=new_span_bdy)
# 拼接音频
output_feat = paddle.concat(x=out_mels, axis=0)
wav_org, _ = librosa.load(wav_path, sr=fs)
outs = dict()
outs['wav_org'] = wav_org
outs['output_feat'] = output_feat
outs['old_span_bdy'] = old_span_bdy
outs['new_span_bdy'] = new_span_bdy
return outs
def get_wav(wav_path: str,
source_lang: str='en',
target_lang: str='en',
old_str: str='',
new_str: str='',
duration_adjust: bool=True,
fs: int=24000,
n_shift: int=300,
task_name: str='synthesize'):
outs = get_mlm_output(
wav_path=wav_path,
old_str=old_str,
new_str=new_str,
source_lang=source_lang,
target_lang=target_lang,
duration_adjust=duration_adjust,
fs=fs,
n_shift=n_shift)
wav_org = outs['wav_org']
output_feat = outs['output_feat']
old_span_bdy = outs['old_span_bdy']
new_span_bdy = outs['new_span_bdy']
masked_feat = output_feat[new_span_bdy[0]:new_span_bdy[1]]
with paddle.no_grad():
alt_wav = voc_inference(masked_feat)
alt_wav = np.squeeze(alt_wav)
old_time_bdy = [n_shift * x for x in old_span_bdy]
if task_name == 'edit':
wav_replaced = np.concatenate(
[wav_org[:old_time_bdy[0]], alt_wav, wav_org[old_time_bdy[1]:]])
else:
wav_replaced = alt_wav
wav_dict = {"origin": wav_org, "output": wav_replaced}
return wav_dict
主程序
erniesat_config = 'download/erniesat_vctk_ckpt_1.2.0/default.yaml'
erniesat_ckpt = 'download/erniesat_vctk_ckpt_1.2.0/snapshot_iter_199500.pdz'
erniesat_stat = 'download/erniesat_vctk_ckpt_1.2.0/speech_stats.npy'
phones_dict = 'download/erniesat_vctk_ckpt_1.2.0/phone_id_map.txt'
voc = 'hifigan_vctk'
voc_config = 'download/hifigan_vctk_ckpt_0.2.0/default.yaml'
voc_ckpt = 'download/hifigan_vctk_ckpt_0.2.0/snapshot_iter_2500000.pdz'
voc_stat = 'download/hifigan_vctk_ckpt_0.2.0/feats_stats.npy'
task_name = 'edit'
wav_path = 'source/p243_313.wav'
# should not -> is not impossible to
old_str = 'For that reason cover should not be given'
new_str = 'For that reason cover is not impossible to be given'
source_lang = 'en'
target_lang = 'en'
duration_adjust = True
output_name = 'sat_output.wav'
# evaluate(args)
with open(erniesat_config) as f:
erniesat_config = CfgNode(yaml.safe_load(f))
with open(voc_config) as f:
voc_config = CfgNode(yaml.safe_load(f))
# convert Chinese characters to pinyin
if source_lang == 'zh':
old_str = pypinyin.lazy_pinyin(
old_str,
neutral_tone_with_five=True,
style=pypinyin.Style.TONE3,
tone_sandhi=True)
old_str = ' '.join(old_str)
if target_lang == 'zh':
new_str = pypinyin.lazy_pinyin(
new_str,
neutral_tone_with_five=True,
style=pypinyin.Style.TONE3,
tone_sandhi=True)
new_str = ' '.join(new_str)
if task_name == 'edit':
new_str = new_str
elif task_name == 'synthesize':
new_str = old_str + ' ' + new_str
else:
new_str = old_str + ' ' + new_str
# Extractor
mel_extractor = LogMelFBank(
sr=erniesat_config.fs,
n_fft=erniesat_config.n_fft,
hop_length=erniesat_config.n_shift,
win_length=erniesat_config.win_length,
window=erniesat_config.window,
n_mels=erniesat_config.n_mels,
fmin=erniesat_config.fmin,
fmax=erniesat_config.fmax)
collate_fn = build_erniesat_collate_fn(
mlm_prob=erniesat_config.mlm_prob,
mean_phn_span=erniesat_config.mean_phn_span,
seg_emb=erniesat_config.model['enc_input_layer'] == 'sega_mlm',
text_masking=False)
vocab_phones = {}
with open(phones_dict, 'rt') as f:
phn_id = [line.strip().split() for line in f.readlines()]
for phn, id in phn_id:
vocab_phones[phn] = int(id)
# ernie sat model
erniesat_inference = get_am_inference(
am='erniesat_dataset',
am_config=erniesat_config,
am_ckpt=erniesat_ckpt,
am_stat=erniesat_stat,
phones_dict=phones_dict)
# vocoder
voc_inference = get_voc_inference(
voc=voc,
voc_config=voc_config,
voc_ckpt=voc_ckpt,
voc_stat=voc_stat)
wav_dict = get_wav(
wav_path=wav_path,
source_lang=source_lang,
target_lang=target_lang,
old_str=old_str,
new_str=new_str,
duration_adjust=duration_adjust,
fs=erniesat_config.fs,
n_shift=erniesat_config.n_shift,
task_name=task_name)
sf.write(
output_name, wav_dict['output'], samplerate=erniesat_config.fs)
print(
f"\033[1;32;m Generated audio saved into {output_name} ! \033[0m")
# 播放输入音频
import IPython.display as dp
dp.Audio("source/p243_313.wav")
# 播放编辑好的音频
dp.Audio('sat_output.wav', rate=erniesat_config.fs)
具体实现代码请参考: - 纯中文 ERNIE-SAT - 纯英文 ERNIE-SAT - 中英文混合 ERNIE-SAT
SV2TTS 和 ERNIE-SAT 均属于一句话克隆,其合成效果有限,能获取一定量的数据情况下,可以考虑小数据集微调方案,具有更高的音色相似度和更好的音频质量。请参考多语言合成与小样本合成技术应用实践。
Web 页面体验 SV2TTS、ERNIE-SAT 一句话合成和小数据集微调: - github 项目体验地址 - AiStudio在线体验地址:【PaddleSpeech进阶】PaddleSpeech小样本合成方案体验
PS:
本教程所指的声音克隆的英文名称是 Voice Cloning,简称 VC,在语音合成领域,有另一种细分领域也简称 VC,全称是 Voice Conversion 声音转换,两者的区别是,Voice Cloning 同时输入参考音频和输入文本,合成的音频有参考音频的音色,说话内容是输入文本;Voice Conversion 输入 source audio 和 target audio 两个音频,无需输入文本,合成的音频具有 target audio 的音色和 source audio 的文本内容以及韵律特征。柯南的变声领结实际上是用 Voice Conversion 声音转换技术实现的(用毛利小五郎的音色说出柯南的说话内容)。Voice Cloning 合成音频的韵律性能是一般是 TTS 模型本身决定的,而 Voice Conversion 合成音频的韵律一般是由 source audio 决定的。
大家以后在语音合成领域看到 “VC” 一定要分清楚指的是声音克隆 Voice Cloning 还是声音转换 Voice Conversion 哟。
关注 PaddleSpeech
请关注我们的 Github Repo,非常欢迎加入以下微信群参与讨论: - 扫描二维码 - 添加运营小姐姐微信 - 通过后回复【语音】 - 系统自动邀请加入技术群
P.S. 欢迎关注我们的 github repo PaddleSpeech, 是基于飞桨 PaddlePaddle 的语音方向的开源模型库,用于语音和音频中的各种关键任务的开发,包含大量基于深度学习前沿和有影响力的模型。
九、商业数据分析六大技术?
作为一名合格的数据分析师,除了掌握基本的理论之外,还需要掌握的重要硬技能和软技能。
1、数学和统计能力:数据分析师首先要掌握的一定是数学和统计能力,因为要花大量时间跟数字打交道,因此你需要有数学头脑。
2、掌握编程语言:你还需要具备一些编程语言的知识,例如Python、 SQL等。如今,很多数据分析师都可以依靠多种编程语言来完成他们的工作。
3、数据分析思维:你还需要具有分析的能力,这不仅仅是处理数字和分享数据,有时你还需要更深入地了解到底发生了什么,因此必须拥有分析思维。
4、解决问题的能力:数据分析是关于回答问题和解决业务挑战的,这需要一些敏锐的解决问题能力。
5、出色的沟通能力:数据分析师除了会做分析,还要懂得分享。当你收集数据获得了有价值的见解,将自己挖掘的价值分享他人,才能使业务受益。
6、掌握分析工具:数据分析师有各种各样的工具可供使用,但是你还需要知道该使用哪一个以及何时使用。
十、大数据的三大技术支撑要素?
大数据技术支撑的三个要素是:
1、云计算、硬件性价比的提高以及软件技术的进步;
2、数据源整合进行存储、清洗、挖掘、分析后得出结果直到优化企业管理提高效率;
3、智能设备、传感器的普及,推动物联网、人工智能的发展。