汉语(普通话)的音素对齐

今天也是热到灵魂出窍的一天Orz,封面和头图来自狼狗~

音素对齐在语音识别,语音合成等领域都可能会用的到,当你不想自己训练个模型来处理对齐任务时,最好的办法是找个工具。

用了一圈下来,发现Montreal-Forced-Aligner(MFA)比较好用,不仅支持汉语(普通话)还支持英语和一堆其他的语言(还可以自己训练声学模型),所以接下来主要写的是MFA的用法。另外还有一个专门处理汉语音素对齐的工具speech-aligner,地址在这里https://github.com/open-speech/speech-aligner 另外专栏为什么不支持插入站外链接,除了不支持代码高亮以外又多了个槽点= =

第一件事是把MFA下载下来https://montreal-forced-aligner.readthedocs.io/en/latest/installation.html 

Mac,Linux,Windows都可以用,下载后记得解压缩。

首先在与训练模型找到普通话(Mandarin),链接在这里https://montreal-forced-aligner.readthedocs.io/en/latest/pretrained_models.html


然后找一个字典(可以自己训练,参考这里https://montreal-forced-aligner.readthedocs.io/en/latest/example.html?highlight=mandarin#example-2-generate-mandarin-dictionary),没在文档里面找到现成的,不过逛Github的时候在一个停止维护的项目MTTS里面找到了一份字典https://github.com/Jackiexiao/MTTS/blob/master/misc/mandarin-for-montreal-forced-aligner-pre-trained-model.lexicon

然后处理数据,一个wav文件(采样频率在16k以上,不是的话用sox或其他的转换一下)对应一个lab文件,lab里的内容是wav的拼音

接下来就是对齐啦,大概是这样

bin/mfa_align biaobei mandarin-for-montreal-forced-aligner-pre-trained-model.lexicon mandarin.zip result

biaobei指的是数据所在文件夹路径,因为用的是标贝的数据所以用了这个名字,对齐的时候读者小伙伴们记得自己改路径,不要复制粘贴一气呵成~

mandarin-for-montreal-forced-aligner-pre-trained-model.lexicon 是之前下载的字典文件。

mandarin.zip 是之前下载的普通话声学模型,记得不要解压。

result是输出路径。

正常工作的话大概会是这样:


没有正常工作的话,会输出错误信息。

输出内容是这样的:


oov指的是字典里没有的拼音,对齐文件在biaobei文件夹里。

长这样:

item1是拼音的持续时间


item2是音素的持续时间


然后自己写一个脚本读取就好啦w

3. 常用的语音文本对齐工具

本文重点介绍montreal forced aligner(其他的没有跑通过),它是基于kaldi的工具集开发的。

3.1. 下载及安装

我用的windows版本:

https://github.com/MontrealCorpusTools/Montreal-Forced-Aligner/releases/download/v1.1.0-beta.2/montreal-forced-aligner_win64.zip

常规可以在http://montreal-forced-aligner.readthedocs.io官网按照步骤安装,但是一直没装成功,而且官网上安装说明了window不支持G2P等

3.2. 语音对齐

解压上面montreal-forced-aligner_win64.zip,进入其bin目录,可以看到对齐的脚本mfa_align.exe,直接执行如下命令即可输出对齐文本:

mfa_align corpus_directory dictionary_path acoustic_model_path output_directory

命令包含有4个参数:

  • corpus_directory:待对齐的语音文件目录,我用的清华语音库data_thchs30,但缺少了montreal需要的.lab文件。所以将语音库中.wav.trn中第2行(拼音)单独另存为.lab即可
  • dictionary_path:小的字典文件,即corpus_directory所用到的语音和音素的对应关系字典。

用工具中的mfa_generate_dictionary.exe命令,但发现报错。

只能写python脚本生成了小字典,同时也发现清华语音库数据有dirty,有些拼音是错的,无法生成字典。比如兄xiong5,手动将lab文件将xiong5改为xiong4。

楼主生成的如下,这样mfa_align的参数dictionary_path='./tinydictionary.txt'即可:

注:xiong5包含x io5 ng3个音素,解压下面acoustic_model_path中mandarin.zip,可以看到没有对应的音素io5这个因素,所以不改lab会该工具报错

  • acoustic_model_path:语音模型,直接官网下载中文的,记得不要解压(官网也有英文下载)

github.com/MontrealCorpusTools/mfa-models/raw/main/acoustic/mandarin.zip

  • output_directory:语音对齐后输出目录,自定义指定(如d:download/tmp/textGrid)

如下图,输出的文件为.TextGrid格式,python可以安装TextGrid解析

例如:A2_1.wav中”ta1”从xmin=0.770秒开始,xmax=0.970秒结束,这样就实现了语音和文本对齐。

附录:

代码片段1:生成lab文件,mfa_align参数corpus_directory下的lab文件生成代码

def trn2lab(trnPath):
"""
trnPath:trn文件所在目录,将.trn文件第2行拼音存为.lab文件
"""
pattern = re.compile('(.*)\.wav\.trn$')
for root, dirs, files in os.walk(trnPath):
for readfile in files:
if not pattern.match(readfile): continue
with open(trnPath+'\\'+readfile.split('.')[0]+'.lab','w') as wf:
line2=''
with open(trnPath+'\\'+readfile,mode='r',encoding='UTF-8') as rf:
next(rf)
line2 = rf.readline() ##读取第2行
rf.close()
wf.writelines(line2)

代码片段2:生成小字典

#全量字典:拼音->音素
dictionary = r'D:\download\tmp\dictionary.txt'
def getDictionary(dictionary = dictionary):
"""
:param dictionary: 字典文件,每一行包含一个拼音及对应的音素,例如 "bao1 b ao1\nbeng1 b e1 ng\n"
:return: 字典:key是拼音,value是拼音及对应的音素,例如 key=bao1,value='bao1 b ao1\n'
"""
word2phone = {}
with open(dictionary, 'r') as f:
line = f.readline()
while line:
key,value = line.split(' ',1)
word2phone[key] = line
line = f.readline()
return word2phone

#生成对齐的小字典
def getTinyDictionaryByFile(corpusPath=r'.\data_thchs30\data',outputFile = 'tinyDictionary.txt'):
"""
inputFilePath:.lab文件。音频文件及对应的拼音文件所在目录,拼音文件一个汉字一个拼音,拼音间空格分隔如“bian4 hua1”。
outputFile: 当前音频文件对应的所有文字的拼音形成的小字典,如“bao1 b ao1\n”
"""
dictionary = getDictionary()
pattern = re.compile(r'(.*)\.lab$') #只从lab文件找所有的拼音
tinyDict = {}
notExistsWord = ''
for root, dirPath, files in os.walk(corpusPath):
for readfile in files: ##遍历inputFilePath目录下的所有文件
if pattern.match(readfile) is not None: #找出.lab文件
with open(root+"\\"+readfile,'r') as rf: #读取出.lab文件中的所有拼音
line = rf.readline()
while line:
wordList = line.split() #读取拼音
for word in wordList:
if word in dictionary.keys():
tinyDict[word] = dictionary[word]
else:notExistsWord += word + ' ' + root+"\\"+readfile+'\n';
line = rf.readline()
with open(outputFile, 'w') as wf:##结果写入outputFile
for key in tinyDict:
wf.write(tinyDict[key])
if notExistsWord !='': print(notExistsWord)

MFA使用了Kaldi的工具集,包括音频特征参数提取,模型构建,训练方法等。据我观测,MFA应该是使用了Kaldi比较早的nnet模型,模型比较小,训练起来非常快。MFA本身已经提供了一些预先训练好的声学模型包括english和mandarin模型,可以直接下载后使用。English的acoustic模型是基于librispeech训练的,用起来已经比较顺手了,比较准确。但是mandarin的声学模型好像数据量不够大,导致对齐效果差。所以就尝试使用自己的数据重新训练一个声学模型,结果还是不错的,见首图。以下为具体步骤(Kaldi和MFA的安装都略去了,大家可以自行按官方的方法进行安装):

首先准备好音频数据和对应的文字,如果文字是中文需要转化为拼音,我使用了pypinyin进行转化,每个中文汉字对应一个拼音,脚本如下,将中文字转为拼音:

# coding:utf8
import os
import sys
import numpy as np
from pypinyin import pinyin, lazy_pinyin, Style
import re


root_dir = "../train/"
pattern = re.compile(r'(.*)\.txt$')


for root, dir, files in os.walk(root_dir):
	for filename in files:
		#print(filename)
		output = pattern.match(filename)
		if output is not None:
			print(root, filename)
			text_file = open(root+"/"+filename)
			line = text_file.read().strip()
			line = line.replace(",", "")
			pinyin =  lazy_pinyin(line, style=Style.TONE3, neutral_tone_with_five=True)
			pinyinline = ' '.join(pinyin)
			print(line)
			target_text_file = open(root+"/"+output.group(1)+".lab", "w")
			target_text_file.write(pinyinline)
			target_text_file.close()

保证音频文件的名字和脚本的文件名仅仅后缀不同,例如:

T0055G0002S0001.wav 和 T0055G0002S0001.lab

其中lab文件内容:yi3 hou4 ni3 shi4 nan2 hai2 zi5 原来的中文为:“以后你是男孩子”

准备好数据之后,使用MFA代的G2P模型生成词典文件:

mfa g2p mandarin_pinyin_g2p ./corpus/tiny/ dict_tiny.txt

其中tiny目录如下:
$ ls tiny
G0002  G0135  G0269  G0326  G0726  G0931  G1492  G1634  G1777  G1889  G1966
$ ls G0002
T0055G0002S0001.lab T0055G0002S0081.lab T0055G0002S0001.wav  T0055G0002S0081.wav
$ cat T0055G0002S0001.lab
yi3 hou4 ni3 shi4 nan2 hai2 zi5

dict大概这个样子:
<eps> 0
!sil 1
<unk> 2
an1quan2 3
ba1shi2nian2dai4 4
bao1luo1wan4xiang4 5

有了词典,就可以开始训练自己的模型了:

mfa train --config_path /home/yons/data/mfaligner/Montreal-Forced-Aligner/montreal_forced_aligner/config/basic_train.yaml /media/yons/SSD1T4K/kaldi/kaldi_data/corpus/tiny/ dict_tiny.txt result_tiny

其中config文件中去掉了 lda和sat部分(mfa 2.0版本使用ac model时的一个bug)

这个运行完成后,默认会在路径:

/home/yons/Documents/MFA/tiny/tri_ali

$ ls tri_ali
acoustic_model.zip  ali.1         ali.2.scores  aligned.2   log      nbest.2      phone_ctm.2  word_ctm.0
ali.0               ali.1.scores  aligned.0     final.mdl   nbest.0  phone_ctm.0  textgrids    word_ctm.1
ali.0.scores        ali.2         aligned.1     final.occs  nbest.1  phone_ctm.1  tree         word_ctm.2

下生成一个acoustic_model.zip 的模型文件,就是我们自己的模型了。

使用下面的命令进行对齐我们的音频:

 mfa align --config_path /home/yons/data/mfaligner/Montreal-Forced-Aligner/montreal_forced_aligner/config/basic_align.yaml my_example2/ dict_tiny.txt /home/yons/Documents/MFA/tiny/tri_ali/acoustic_model.zip my_result3

一般的错误时beam narrow,意思是搜索的宽度不够没有找到最匹配的点,默认的设置一般不会出现beam narrow,出现了也不用紧张,可以通过调整config文件进行调整,就可以得到textgrid文件了,通过图形化的方式验证对齐是否是正确的。

接下来使用工具Praat进行 textgrid和 wav文件的对比分析,看看是不是准确对齐了。

拔刀相助 对应拼音和音素

Montreal Forced Aligner MFA基于kaldi的对齐工具介绍 - 知乎

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值