Example: Aligning a demo corpus#
Note
See also our Google Colab notebook for running this example without installing or downloading anything locally. There is also NTT123’s Jupyter notebook for running the alignment example with a custom LibriSpeech dataset, created by NTT123.
Set up#
Important
Ensure you have installed MFA via Installation.
Ensure you have downloaded the pretrained model via
mfa model download acoustic english_mfaEnsure you have downloaded the pretrained US English dictionary via
mfa model download dictionary english_us_mfaDownload the English LibriSpeech demo corpus and extract it to somewhere on your computer
Ensure you have downloaded the pretrained model via
mfa model download acoustic japanese_mfaEnsure you have downloaded the pretrained Japanese dictionary via
mfa model download dictionary japanese_mfaDownload the Japanese JVS demo corpus and extract it to somewhere on your computer
Install Japanese-specific dependencies via
conda install -c conda-forge spacy sudachipy sudachidict-core
Ensure you have downloaded the pretrained model via
mfa model download acoustic mandarin_mfaEnsure you have downloaded the pretrained China Mandarin dictionary via
mfa model download dictionary mandarin_china_mfaDownload the Mandarin THCHS-30 demo corpus and extract it to somewhere on your computer
Install Mandarin-specific dependencies via
pip install spacy-pkuseg dragonmapper hanziconv
Important
This example assumes you have a directory named mfa_data in your home directory in which the demo corpus was extracted.
Alignment#
Aligning using pre-trained models#
In the same environment that you’ve installed MFA, enter the following command into the terminal:
mfa align ~/mfa_data/librispeech-demo-1.0.0 english_us_mfa english_mfa ~/mfa_data/aligned_librispeech_demo --clean
mfa align ~/mfa_data/japanese-jvs-demo-1.0.0 japanese_mfa japanese_mfa ~/mfa_data/aligned_jvs_demo --clean
mfa align ~/mfa_data/mandarin-thchs-30-demo-1.0.0 mandarin_china_mfa mandarin_mfa ~/mfa_data/aligned_thchs_30_demo --clean
Once the files are aligned we can take a look at the alignment_analysis.csv file in the output directory to see if there are any glaring issues in alignment. This file is sorted initially by the phone_duration_deviation column, which is the maximum z-scored duration for phones in the utterance. High values indication much longer or shorter phones than we would expect given the phone, i.e., a [ɾ] lasting 100ms is very unlikely given the usual duration is typically around 10-20ms.
file |
begin |
end |
speaker |
overall_log_likelihood |
speech_log_likelihood |
phone_duration_deviation |
snr |
|---|---|---|---|---|---|---|---|
26-495-0029 |
0.0 |
15.33 |
26 |
-54.456238788323546 |
-57.6560760433391 |
15.243577592668007 |
6.645144699335612 |
19-227-0027 |
0.0 |
15.645 |
19 |
-44.529997004792335 |
-46.942441727063674 |
13.854204008671575 |
12.191697302549363 |
19-198-0010 |
0.0 |
12.6 |
19 |
-43.50238715277778 |
-45.62727763510158 |
9.378276520846718 |
13.180338896436085 |
26-495-0004 |
0.0 |
14.055 |
26 |
-50.670524759957324 |
-50.98836160475208 |
9.132307439395934 |
11.955992448065652 |
19-227-0016 |
0.0 |
12.685 |
19 |
-42.93412012411348 |
-46.04780329319469 |
8.374659305119293 |
12.57889123443367 |
file |
begin |
end |
speaker |
overall_log_likelihood |
speech_log_likelihood |
phone_duration_deviation |
snr |
|---|---|---|---|---|---|---|---|
jvs004_nonpara30_BASIC5000_1571 |
0.0 |
4.724208333333333 |
jvs004 |
-44.60921775688559 |
-53.64337515830994 |
11.069623295539825 |
20.73555387405615 |
jvs001_parallel100_VOICEACTRESS100_001 |
0.0 |
8.621041666666667 |
jvs001 |
-41.720485607598604 |
-45.22640653756949 |
6.211908079327884 |
27.302904438762084 |
jvs003_nonpara30_BASIC5000_2550 |
0.0 |
10.909041666666667 |
jvs003 |
-40.970862454170486 |
-45.1975002500746 |
5.892864020481638 |
23.07655949682694 |
jvs004_nonpara30_BASIC5000_1560 |
0.0 |
9.180166666666667 |
jvs004 |
-46.13757829520697 |
-50.26279640197754 |
5.803162260964776 |
21.536162380195314 |
jvs003_nonpara30_BASIC5000_0440 |
0.0 |
9.649583333333334 |
jvs003 |
-41.17138924870466 |
-45.75857627223915 |
4.7608877931967415 |
23.593413391753792 |
The above table shows the five files with highest phone duration deviation, which we can then take a look more closely and see what’s causing the alignment issues.
For example, looking at jvs004_nonpara30_BASIC5000_1571 in a program like Praat, we can see the issue is due to an out of vocabulary item “1泊”. The original transcript is:
税、その他全て込みだと、1泊いくらですか。
Which is tokenized by MFA using sudachipy to the following sequence of words:
税 その 他 全て込み だ と 1泊 いくら です か。
Every word other than “1泊” is present in japanese_mfa dictionary, but the lack of “1泊” causes a small section of the previous word “と” to be aligned as “spn”, and then the following word “いくら” takes up the actual time span of “いっぱく” in addition to the time span corresponding to “いくら”, since both “いっぱく” and “いくら” start with [i] followed by a stop closure.
There are a couple of ways to fix this issue. The most straight-forward way would be to add a dictionary entry for “1泊” as i pː a k ɯ or change the input transcript to use “一泊” instead of “1泊”, as the correct pronunciation is present for “一泊”.
However, this fix will only affect this one particular word/utterance, and there are likely many more out of vocabulary items. The Japanese alignment has the capability of using the katakana generated by the sudachipy morphological parser and use the katakana forms as input to grapheme-to-phoneme models on the fly, so for the purposes of this example, we’ll skip over adding words to the Japanese dictionary and just focus on using G2P models at alignment time.
file |
begin |
end |
speaker |
overall_log_likelihood |
speech_log_likelihood |
phone_duration_deviation |
snr |
|---|---|---|---|---|---|---|---|
A4_8 |
0.0 |
12.4375 |
A4 |
-49.248455084405144 |
-55.64855964978536 |
6.169737157239693 |
8.524069008855722 |
C12_515 |
0.0 |
11.69 |
C12 |
-49.446983265611635 |
-51.683270083533394 |
5.940588177352259 |
10.706482170359841 |
A4_25 |
0.0 |
10.5 |
A4 |
-48.68171130952381 |
-50.71304063911898 |
5.613372337759242 |
6.7809069072769255 |
B34_251 |
0.0 |
9.25 |
B34 |
-40.79677787162162 |
-41.75823864792333 |
5.540030677004922 |
8.962213255170383 |
A4_6 |
0.0 |
9.625 |
A4 |
-50.510534300363446 |
-53.57253624076274 |
5.429628766470327 |
5.500242213510484 |
Adding words to the dictionary#
First we’ll need the pretrained G2P model. These are installed via the mfa model download command:
mfa model download g2p english_us_mfa
You should be able to run mfa model inspect g2p english_us_mfa and it will output information about the english_us_mfa G2P model.
mfa model download g2p japanese_mfa
You should be able to run mfa model inspect g2p japanese_mfa and it will output information about the japanese_mfa G2P model.
mfa model download g2p mandarin_china_mfa
You should be able to run mfa model inspect g2p mandarin_china_mfa and it will output information about the mandarin_china_mfa G2P model.
Depending on your use case, you might have a list of words to run G2P over, or just a corpus of sound and transcription files. The mfa g2p command can process either:
mfa g2p ~/mfa_data/librispeech-demo-1.0.0 english_us_mfa ~/mfa_data/g2pped_oovs.txt --dictionary_path english_us_mfa --clean
For Japanese, G2P functionality is done as part of alignment by specifying --g2p_model_path.
mfa g2p ~/mfa_data/mandarin-thchs-30-demo-1.0.0 mandarin_china_mfa ~/mfa_data/g2pped_oovs.txt --dictionary_path mandarin_china_mfa --clean
Running the above will output a text file in the format that MFA uses (Pronunciation dictionary format) with all the OOV words (ignoring bracketed words like <cutoff>). I recommend looking over the pronunciations generated and make sure that they look sensible. For languages where the orthography is not transparent, it may be helpful to include --num_pronunciations 3 so that more pronunciations are generated than just the most likely one. For more details on running G2P, see Generate pronunciations for words (mfa g2p).
Once you have looked over the dictionary, you can save the new pronunciations via:
mfa model add_words english_us_mfa ~/mfa_data/g2pped_oovs.txt
For Japanese, G2P functionality is done as part of alignment by specifying --g2p_model_path.
mfa model add_words mandarin_china_mfa ~/mfa_data/g2pped_oovs.txt
The new pronunciations will be available when you use the dictionary identifier in an MFA command, i.e. the modified command from Aligning a speech corpus with existing pronunciation dictionary and acoustic model:
mfa align ~/mfa_data/librispeech-demo-1.0.0 english_us_mfa english_mfa ~/mfa_data/aligned_librispeech_demo_no_oovs --clean
mfa align ~/mfa_data/japanese-jvs-demo-1.0.0 japanese_mfa japanese_mfa ~/mfa_data/aligned_jva_demo_no_oovs --g2p_model_path japanese_mfa --clean
mfa align ~/mfa_data/mandarin-thchs-30-demo-1.0.0 mandarin_china_mfa mandarin_mfa ~/mfa_data/aligned_mandarin_demo_no_oovs --clean
Now let’s see if adding words to the dictionary helped improve the alignment issues we were seeing before.
file |
begin |
end |
speaker |
overall_log_likelihood |
speech_log_likelihood |
phone_duration_deviation |
snr |
|---|---|---|---|---|---|---|---|
26-495-0029 |
0.0 |
15.33 |
26 |
-54.456238788323546 |
-57.6560760433391 |
15.243577592668007 |
6.645144699335612 |
19-227-0027 |
0.0 |
15.645 |
19 |
-44.529997004792335 |
-46.942441727063674 |
13.854204008671575 |
12.191697302549363 |
19-198-0010 |
0.0 |
12.6 |
19 |
-43.50238715277778 |
-45.62727763510158 |
9.378276520846718 |
13.180338896436085 |
26-495-0004 |
0.0 |
14.055 |
26 |
-50.670524759957324 |
-50.98836160475208 |
9.132307439395934 |
11.955992448065652 |
19-227-0016 |
0.0 |
12.685 |
19 |
-42.93412012411348 |
-46.04780329319469 |
8.374659305119293 |
12.57889123443367 |
file |
begin |
end |
speaker |
overall_log_likelihood |
speech_log_likelihood |
phone_duration_deviation |
snr |
|---|---|---|---|---|---|---|---|
jvs001_parallel100_VOICEACTRESS100_001 |
0.0 |
8.621041666666667 |
jvs001 |
-41.84382250580047 |
-45.2327318925124 |
6.20348375405817 |
27.293943985523807 |
jvs003_nonpara30_BASIC5000_2550 |
0.0 |
10.909041666666667 |
jvs003 |
-40.983222101283225 |
-45.076715024312335 |
5.908918038417016 |
23.07655949682694 |
jvs002_nonpara30_BASIC5000_0114 |
0.0 |
4.245291666666667 |
jvs002 |
-39.14056525735294 |
-42.082562075720894 |
5.185645170149811 |
20.482769181663702 |
jvs003_nonpara30_BASIC5000_0440 |
0.0 |
9.649583333333334 |
jvs003 |
-41.123874676165805 |
-45.70696529871981 |
4.736230315134372 |
23.619350634943906 |
jvs001_parallel100_VOICEACTRESS100_004 |
0.0 |
6.523541666666667 |
jvs001 |
-44.13319593558282 |
-47.53735481118256 |
4.546602511572727 |
26.105708678065128 |
We can see now that jvs004_nonpara30_BASIC5000_1571 no longer has the top phone duration deviation. Looking at in a program like Praat, we can see that “1泊” and “いくら” are now properly aligned at the word level, and the phones in “いくら” are properly aligned.
However, it is important to note that the pronunciation generated for “1泊” is not correct. The pronunciation generated is not i pː a k ɯ as it should be, but is instead i tɕ i h a k ɯ. The source of this error is due to the sudachipy parse gives the pronunciation form of “1泊” as “イチハク” and not “イッパク”. However, there is enough of the correct pronunciation to ensure that this error does not affect the alignment of surrounding words.
file |
begin |
end |
speaker |
overall_log_likelihood |
speech_log_likelihood |
phone_duration_deviation |
snr |
|---|---|---|---|---|---|---|---|
A4_8 |
0.0 |
12.4375 |
A4 |
-49.248455084405144 |
-55.64855964978536 |
6.169737157239693 |
8.524069008855722 |
C12_515 |
0.0 |
11.69 |
C12 |
-49.446983265611635 |
-51.683270083533394 |
5.940588177352259 |
10.706482170359841 |
A4_25 |
0.0 |
10.5 |
A4 |
-48.68171130952381 |
-50.71304063911898 |
5.613372337759242 |
6.7809069072769255 |
B34_251 |
0.0 |
9.25 |
B34 |
-40.79677787162162 |
-41.75823864792333 |
5.540030677004922 |
8.962213255170383 |
A4_6 |
0.0 |
9.625 |
A4 |
-50.510534300363446 |
-53.57253624076274 |
5.429628766470327 |
5.500242213510484 |
Adapting the acoustic model#
In general, adapting a pretrained acoustic model to your specific data will improve alignments.
We can adapt our pretrained model via the mfa adapt command:
mfa adapt ~/mfa_data/librispeech-demo-1.0.0 english_us_mfa english_mfa ~/mfa_data/english_mfa_adapted.zip --clean
We can now use the adapted model to align the librispeech-demo corpus. Note the change from english_mfa to ~/mfa_data/english_mfa_adapted.zip below.
mfa align ~/mfa_data/librispeech-demo-1.0.0 english_us_mfa ~/mfa_data/english_mfa_adapted.zip ~/mfa_data/aligned_librispeech_demo_adapted --clean
mfa adapt ~/mfa_data/japanese-jvs-demo-1.0.0 japanese_mfa japanese_mfa ~/mfa_data/japanese_mfa_adapted.zip --g2p_model_path japanese_mfa --clean
We can now use the adapted model to align the japanese-jvs-demo corpus. Note the change from japanese_mfa to ~/mfa_data/japanese_mfa_adapted.zip below.
mfa align ~/mfa_data/japanese-jvs-demo-1.0.0 japanese_mfa ~/mfa_data/japanese_mfa_adapted.zip ~/mfa_data/aligned_jvs_demo_adapted --g2p_model_path japanese_mfa --clean
mfa adapt ~/mfa_data/mandarin-thchs-30-demo-1.0.0 mandarin_china_mfa mandarin_mfa ~/mfa_data/mandarin_mfa_adapted.zip --clean
We can now use the adapted model to align the mandarin-thchs-30-demo corpus. Note the change from mandarin_mfa to ~/mfa_data/mandarin_mfa_adapted.zip below.
mfa align ~/mfa_data/mandarin-thchs-30-demo-1.0.0 mandarin_china_mfa ~/mfa_data/mandarin_mfa_adapted.zip ~/mfa_data/aligned_thchs_30_demo_adapted --clean