概要
英語の音声をカタカナで書き起こす試みとして、音素ASRとルールベースのカナ変換を組み合わせて検証しました。
単体のカナASRよりはよさそうなものの、完璧にはまだまだ遠い結果でした。
実装
以下の流れで実現します。
1. wav2vec2-lv-60-espeak-cv-ft でwav音源 -> IPAに変換
2. ipapy を使い IPA → ARPABET に変換
3. arpakana で ARPABET → カナ に変換
以下が実装コードです。
uv add ipapy arpakana transformers # 他にも必要そうであれば適宜インストール
# scripts/run_phoneme_asr.py
import sys
from pathlib import Path
# Python 3.12対応のためのモンキーパッチ
import collections.abc
# ipapyライブラリが古いcollectionsインポートを使用している問題を解決
sys.modules['collections'].MutableMapping = collections.abc.MutableMapping
sys.modules['collections'].MutableSequence = collections.abc.MutableSequence
import librosa
import torch
from transformers import Wav2Vec2CTCTokenizer, Wav2Vec2FeatureExtractor, Wav2Vec2ForCTC
from ipapy.arpabetmapper import ARPABETMapper
from arpakana import arpabet_to_kana
def ipa_to_arpabet(ipa_str: str, ignore_unmapped: bool = True) -> list[str]:
"""
IPA → ARPAbet(リスト形式)変換
未対応の文字を無視するオプションあり。
例: "pɹuːf" → ["P", "R", "UW", "F"]
Args:
ipa_str: IPA音素文字列
ignore_unmapped: 未対応文字を無視するかどうか
Returns:
list[str]: ARPAbet音素のリスト
"""
mapper = ARPABETMapper()
# return_as_list=True にすると、分割されたリストを得られる
arpabet_list = mapper.map_unicode_string(ipa_str, ignore=ignore_unmapped, return_as_list=True)
return arpabet_list
def phoneme_asr(audio_path: Path) -> tuple[str, list[str], str]:
"""音声ファイルから音素認識とカタカナ変換を実行
Args:
audio_path: 入力音声ファイルのパス
Returns:
tuple[str, list[str], str]: (認識されたIPA音素, ARPAbet変換結果, カタカナ変換結果)
"""
# モデルロード
MODEL_ID = "facebook/wav2vec2-lv-60-espeak-cv-ft"
model = Wav2Vec2ForCTC.from_pretrained(MODEL_ID)
feature_extractor = Wav2Vec2FeatureExtractor.from_pretrained(MODEL_ID)
tokenizer = Wav2Vec2CTCTokenizer.from_pretrained(MODEL_ID)
# 音声読み込み(16kHz, mono)
wav, sr = librosa.load(str(audio_path), sr=16000, mono=True)
# 音素認識処理
input_values = feature_extractor(wav, return_tensors="pt", sampling_rate=16000).input_values
with torch.no_grad():
logits = model(input_values).logits
predicted_ids = torch.argmax(logits, dim=-1)
phonemes_list = tokenizer.batch_decode(predicted_ids)
ipa_phonemes = phonemes_list[0] if phonemes_list else ""
# IPA→ARPAbet→カタカナ変換
arpabet_list = ipa_to_arpabet(ipa_phonemes)
arpabet_string = " ".join(arpabet_list)
katakana = arpabet_to_kana(arpabet_string)
return ipa_phonemes, arpabet_list, katakana
def main() -> None:
if len(sys.argv) < 2:
print("使用方法: python run_phoneme_asr.py <入力音声ファイル>")
sys.exit(1)
input_path = Path(sys.argv[1])
if not input_path.exists():
print(f"入力ファイルが見つかりません: {input_path}")
sys.exit(1)
ipa_phonemes, arpabet_list, katakana = phoneme_asr(input_path)
print("Recognized IPA phonemes:", ipa_phonemes)
print("Converted to ARPAbet:", arpabet_list)
print("Converted Katakana:", katakana)
if __name__ == "__main__":
main()
検証
以下の手順で、フリーの洋楽をセグメント分割し、冒頭の5セグメントで検証しました。
結果
結果を示します。
リファレンスとして、検証用音源をwhisperで書き起こした英語歌詞、及び筆者が聞いて書き起こしたカタカナを示します。
結果として、音素ASRにより認識されたIPA、ARPABET、およびカナ変換結果を示します。
- 1
- リファレンス
- Under the moon and the quiet sky so clear
- アンダーダムーンアンダクワイトスカイソークリー
- 結果
- ʌndɚðəuːænðəkwaɪᵻtskaɪsoʊkliː
- ['AH', 'N', 'D', 'AXR', 'DH', 'AX', 'UW', 'N', 'DH', 'AX', 'K', 'W', 'AY', 'K', 'AY', 'S', 'OW', 'K', 'L', 'IH']
- アンダーダウーンダクワイカイソウクリ
- リファレンス
- 2
- リファレンス
- A whisper of hope is all I hold near
- アウィスパーラヴホウプイズオーライホウルニー
- 結果
- ɐwɪspɚɹʌvhaʊɪsɑːlaɪhoːdəniː
- ['W', 'IH', 'S', 'P', 'AXR', 'R', 'AH', 'V', 'HH', 'AW', 'IH', 'S', 'AA', 'L', 'AY', 'HH', 'OH', 'D', 'AX', 'N', 'IH']
- ウィスパーラヴハウイサライホーダニ
- リファレンス
- 3
- リファレンス
- Every breath, every word
- エヴリブレスエヴリワード
- 結果
- ɛvɹiblɜːɛvɹibɜːd
- ['EH', 'V', 'R', 'IH', 'B', 'L', 'EH', 'V', 'R', 'IH', 'B', 'D']
- エヴリブレヴリブド
- リファレンス
- 4
- リファレンス
- A humble call, guided by mercy
- ハンブーコーガイディバイマーシー
- 結果
- hʌmbəlkɔɡaɪdᵻdbaɪmmɚsi
- ['HH', 'AH', 'M', 'B', 'AX', 'L', 'K', 'AO', 'G', 'AY', 'D', 'AY', 'M', 'M', 'AXR', 'S', 'IH']
- ハンバルコガイダインマーシ
- リファレンス
- 5
- リファレンス
- The one above all
- ドワーナバーヴォー
- 結果
- dowanpoɜfɑ
- ['D', 'OH', 'W', 'AE', 'N', 'P', 'OH', 'F', 'AA']
- ドーワンポーファ
- リファレンス
考察
単体のカナASRモデル等の結果に比べると耳で聞いた印象に近く改善しています。
一方で、全体的にはまだ正解と比べて聞き逃しが多いように思われます。ただし、人間による書き起こしも必ずしも全員が納得する正解とは言えず、特にノイズとカナ化する音の区別は非常に主観的であったため、音素ASRの結果も許容範囲な可能性もあります。英語が想起される状況で書き起こすと細かい子音に対応するカナを書き起こしたくなりますが、全く知らない言語だとしたら許容範囲かもしれません。
改善点として、基本的には音素ASRが聞き落としていると思われるので、ここをもう少しBGMに強いモデルに置き換えたり、追加学習を試みることが考えられます。
自前で学習することのハードルが高い場合は、whisperはBGMがあってもうまく書き起こせているようなので、whisperの結果を細かな音素の復元に用いることも有効かもしれません。