背景
ASR服务出现音频切分不准,计划使用线上数据进行pyannote VAD调参。但是目前没有VAD数据集标注,计划用线上数据的ASR测试集,转化为VAD测试集,即,每条语音,需要有效语音的起止时间点。音频文本对齐就是其中一个过程。
数据集准备
目前ASR数据集标注为文本text,如”请问有什么可以帮助您“,而不是MFA里所需要的”qing3 wen4 you3 shen me ........“。因此需要把文本text转换成拼音lab,这点很多教程没写,直接运行文本text一直报错。
问题来了
1、这个下载过程就很曲折了,服务器没有翻墙下不下得来看运气。自己本地下载后,放到服务器的目录也有讲究,很多教程也没写。mandarin_mfa 不是拼音phone形式,下了也没用。
mfa model download acoustic mandarin_mfa#默认放在/home/linry/Documents/MFA/pretrained_models/acoustic/mandarin_mfa.zip
mfa model download dictionary mandarin_mfa#/home/linry/Documents/MFA/pretrained_models/dictionary/mandarin_mfa.dict
2、运行以下命令都报错
mfa validate /data3/keyun/mfa10h mandarin_mfa mandarin_mfa
File "/data/linry/anaconda3/envs/asr/lib/python3.10/site-packages/montreal_forced_aligner/acoustic_modeling/trainer.py", line 523, in train
trainer.train()
File "/data/linry/anaconda3/envs/asr/lib/python3.10/site-packages/montreal_forced_aligner/acoustic_modeling/base.py", line 384, in train
self.initialize_training()
File "/data/linry/anaconda3/envs/asr/lib/python3.10/site-packages/montreal_forced_aligner/acoustic_modeling/base.py", line 217, in initialize_training
self._trainer_initialization()
File "/data/linry/anaconda3/envs/asr/lib/python3.10/site-packages/montreal_forced_aligner/acoustic_modeling/monophone.py", line 315, in _trainer_initialization
job = self.jobs[0]
IndexError: list index out of range
mfa align /data3/keyun/mfa10h mandarin_mfa mandarin_mfa /data3/keyun/mfa10h_result
File "/data/linry/anaconda3/envs/asr/lib/python3.10/site-packages/montreal_forced_aligner/models.py", line 781, in validate
raise (PronunciationAcousticMismatchError(missing_phones))
montreal_forced_aligner.exceptions.PronunciationAcousticMismatchError: PronunciationAcousticMismatchError:
There were phones in the dictionary that do not have acoustic models:
ai, ai˥˥, ai˥˩, ai˦, ai˧˥, ai˨, ai˨˩˦, ai˩, au, au˥˥, au˥˩, au˦, au˧˥, au˨, au˨˩˦, au˩, ei, ei˥˥, ei˥˩, ei˦, ei˧˥, ei˨, ei˨˩˦, ei˩, ou, ou˥˥, ou˥˩, ou˦, ou˧˥, ou˨, ou˨˩˦, and ou˩
搜到两种解决方案
1、Generating a pronunciation dictionary with a pretrained G2P model ,发现g2p没有普通话的
2、github.com/Jackiexiao/MTTS/blob/master/misc/mandarin-for-montreal-forced-aligner-pre-trained-model.lexicon使用这个字典,也报错
对比这两个dict,也长得不一样
研究到不一样是因为用了不同的phone set(有pinyin和MFA),对应的acoustic model也不同
所以文本text转换成的lab、dict使用的phoneset、acoustic model,三者都要对应起来。没有找到能使用pinyin字典的acoustic model。把文本转MFA的lab方法也没找到。以上都是MFA v2.0
所以以下都是基于拼音phone形式。
解决方案
准备lab 、dict、acoustic model
1、下载中文的acoustic model
github.com/MontrealCorpusTools/mfa-models/releases/download/acoustic-archive-v1.0/mandarin.zip)
默认放在/home/xxx/Documents/MFA/pretrained_models/acoustic/mandarin.zip。
使用命令行mfa model download acoustic mandarin 是下载不到这个模型的
2、使用pypinyin 把汉字转为pinyin,.txt -> .lab,这个过程wav没有参与
# 将音频对应的文本文件转为.lab文件。
import os
import sys
import numpy as np
from pypinyin import pinyin, lazy_pinyin, Style
import re
root_dir = "/data3/keyun/mfa10h"
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(pinyinline)
target_text_file = open(root+"/"+output.group(1)+".lab", "w")
target_text_file.write(pinyinline)
target_text_file.close()
4、下载中文拼音的g2p,这个是用来生成dict的工具。使用manderin_pinyin_g2p 模型制作dict并没有成功。
使用v1.0 命令生成的是空文件(这个有待成功)
#v1.0
bin/mfa_generate_dictionary mandarin_pinyin_g2p.zip /data3/mfa10h /data3/mfa10h_dict.txt
# 如果报下面这个错, 把montreal-forced-aligner/lib/libpython3.6m.so.1.0复制,同个目录下粘贴,文件名改为libpython3.6m.so
[2535486] Error loading Python lib '/home/xxx/asr-data-process/mfa/montreal-forced-aligner/lib/libpython3.6m.so': dlopen: /home/linry/asr-data-process/mfa/montreal-forced-aligner/lib/libpython3.6m.so: cannot open shared object file: No such file or directory
使用v2.0 命令也报错,看了目录下也没有phones.sym文件
#v2.0
mfa g2p /data3/keyun/mfa10h mandarin_pinyin_g2p /data3/keyun/mfa10h_dict.txt
File "extensions/_pywrapfst.pyx", line 1201, in _pywrapfst.SymbolTable.read_text
_pywrapfst.FstIOError: Read failed: PosixPath('/home/linry/Documents/MFA/extracted_models/g2p/mandarin_pinyin_g2p_g2p/phones.sym')
5、使用manderin的acoustic模型进行对齐
因为上面生成dict失败,使用MFA自带的拼音词典mandarin_pinyin。还需要再做一步处理,因为在2.0.5及以后,word和phone之间要用tab隔开。这边直接下载的词典是空格,需要将词典中每一行的第一个空格换为tab,然后才能正确运行。
path = './mandarin_pinyin.dict'
new_path = './mandarin_pinyin_trans.dict'
with open(path,'r') as r:
with open(new_path,'w') as w:
for line in r.readlines():
arr = line.strip().split(" ")
print(arr)
w.write( arr[0] +'\t'+" ".join(arr[1:])+'\n')
mandarin 就是步骤2下载的acoustic模型
mfa model download dictionary mandarin_pinyin
mfa align /data3/keyun/mfa10h mandarin_pinyin_trans mandarin /data3/keyun/mfa10h_result --clean
如果align失败,降低mfa版本,使用的是conda install montreal-forced-aligner=2.1.7 。试了几个版本,这个终于成功了!会在目标目录生成TextGrid文件
6、可使用Praat软件打开TextGrid文件,同时打开.wav和.textGrid文件。
读取TextGrid,获取 每条语音的有效语音的起止时间点。
item1是word 的持续时间 item2是phone的持续时间
def read_textgrid(file_name):
"""
textgrid文件中的size的值是几就表示有几个item, 每个item下面包含class, name, xmin, xmax, intervals的键值对,
item中的size是几就表示这个item中有几个intervals, 每个intervals有xmin, xmax, text三个键值参数.
"""
datas = []
tg = textgrid.TextGrid()
tgrid = tg.read(file_name)
intervalTire = tg.tiers[0] #words
start = 0
end = 0
# 每条语音,需要有效语音的起止时间点
for i, interval in enumerate(intervalTire):
text= intervalTire[i].mark
if(text != ""):
if start == 0:
start = intervalTire[i].minTime
end = intervalTire[i].maxTime
return start,end
目录对齐数量对不上,比如目录有3k个wav和lab,生成的textgrid只有6百个,可以提高beam解决
mfa align /data3/keyun/mfa10h mandarin_pinyin_trans mandarin /data3/keyun/mfa10h_result --clean --beam 100