最近、中国語の音声と文字の対応を自動的に揃える「強制アラインメント(Forced Alignment)」という作業を試してみました。
音声認識エンジン「Kaldi」を使っての挑戦になりますが、今も何してるのかよくわからないので、一旦文字に起こしていきます。
やりたいこと
音声データ(たとえば「夜色如墨」など)と、その文字データ(中国語)を結びつけて、
「どの音がどこで発音されているか」を自動で揃えられるようにしたい。
今回の最終目標は「発音評価の参考にしたい」ですが、語学学習アプリの基礎素材づくり、音声付き字幕を作りたいにも応用できるまぁまぁいろんな目的でも役に立つ作業です。
使用するツール
Kaldi:音声認識エンジン(Linux/macOSなどで動作)
Python:データ準備用のスクリプト作成に使用
Text-to-Speech(TTS)ツール:最初の中国語音声を生成するために利用(今回はwebベースのTTSを使用)
エディタ VSCode 私はこの子とcolabしかわかりません故
フォルダ構成
plaintext
コピーする
編集する
kaldi/
└── egs
├── audio/ ← .wav音声をここに置く
├── txt/ ← 音声に対応する.txtファイル(スペース区切り)
├── data
└── train/ ← Kaldi用のデータファイル(後述)を生成する場所
└── s5/
└── local/
└── prepare_data.py ← Pythonスクリプト
音声とテキストの準備
音声:.wav形式、16kHz、モノラルを推奨。今回はTTSで数本作成(300〜400字を4本ほど。wavしか求めてないのにmp3でお出ししてくるtext to speechの多いこと)
テキスト:1ファイルにつき1文。漢字の間にスペースを入れることで、Kaldiが音節ごとに分解しやすくなります。
例:
夜色如墨 → 夜 色 如 墨 みたいな作業を黙々と。
Kaldi用のファイル作成
Kaldiは下記のようなファイルを使って音声とテキストを結びつけます:
ファイル名 内容
wav.scp 発話IDと音声ファイルのパス
text 発話IDと対応するテキスト
utt2spk 発話IDと話者IDの対応
spk2utt 話者IDと発話IDの対応(逆引き)
これをPythonスクリプトで自動生成するコードを作りました。でもuttとspkは今のところいらないという。
Pythonスクリプトの概要
以下のような処理をします:
txt/とaudio/フォルダから対応するファイルを探す
テキストファイルをスペース区切りで読み取り
Kaldiに必要な4つのファイル(wav.scp, text, utt2spk, spk2utt)をdata/trainに出力
python
wav_scp.append(f'{utt_id} {wav_path}')
text.append(f'{utt_id} {transcription}')
utt2spk.append(f'{utt_id} speaker1')
実行手順
ターミナルで以下のように操作しました:
bash
cd kaldi/egs/s5/local
python prepare_data.py
bash
utils/fix_data_dir.sh data/train
これを打つことにより整合性チェックも完了。
現時点での感想
Kaldiは情報が多いけど、中国語で使うとなると一気に資料が減るので、(あと中国語のサイトは探すのも翻訳込みでも読むのも難しい)手探り感が強かった。
スクリプト化しておくと、次からは音声とテキストを用意するだけで済むので楽。
データ数が少ないとアラインメントの精度も落ちるのでもう少し集め方は考慮すべき。
ただただ面倒臭いが、案外嫌いじゃない作業。