概要
先日、古い縦書き日本語資料のOCRを試してみた。かなりうまくいって大満足。
研究資料として大量の動画や音声も保有している。ゴリゴリの青森の方言である。
これらもどうにかして文字起こしできないだろうか? そこまで出来たらマジ最高すぎんか!?ということでやってみた。
ちなみに、やる前の自分としては全く期待してなかった。さすがに音声は無理やろな、と。
結果、その通りになった。一方で自分の新たな挑戦のキッカケになったので満足ではある。
サンプル音声ファイル
Qiitaに直接音声ファイルは置けないのでGitHubのリンクをどうぞ。
こちらは私と私の祖母との動画から一部だけ切り出し -> 音声のみ抜き出ししたもの。
これ系統のデータはたくさんあるのだが、さすがにパブリックに公開するというときに許可どりが大変になるのは明白だった。
まぁ自分と祖母との会話であれば、その辺の折り合いを簡単につけられたので、こちらを対象としてやってみた。
先に正解データの紹介
私はこの方言ネイティブなので自分でまぁ正解をだせる。
マシン向けには若干申し訳ないのだが、前提として以下がある。
- 親戚の話
- その親戚のお祖母さんが長いこと介護施設に通っている
その上で長い会話からの抜粋である。載せた音声データの直前の会話で↑自体は述べられている。ただ全体的にだいぶ個人情報に関わる話をしているので、どうしてもその辺を避けてクロップするのが難しかった。そのためマシン相手にはコンテキストが伝わり切らず、さらに難易度をあげてしまったかもしれない。
というわけで自力で文字起こしするとこんな感じ。
あずがるに ただでねぇべせ
そいでも ばばも いさ きたふて きたふて ほれ いさきて そごぁだの ばさまどさ ほれ ちゃっこ のまへだりしてへで
いさ きたふて きたふて どんもなんねんだど
標準語訳 (若干 意訳)
(自宅でお祖母さんの) 面倒をみるのもかなり大変でしょ。
それでもそこのお婆さんは家に帰りたくて帰りたくて、帰ったときには、近所のお婆さんたちと一緒にお茶を飲んだりしていたんだって。
(だから) 家に帰りたくて帰りたくてどうしようもないらしい。
Speech-to-Text手法一覧
- GPT-4o Transcribe
- kotoba-whisper-v2.2-faster
- AWS: Amazon Transcribe
- Google Cloud: Speech-To-Text
GPT-4o Transcribe
かの有名なOpenAIのWhisperの実質的な後継らしい。APIからしか使えない。そのへんの解説記事は世の中に大量にあるので割愛。
ざっくり以下のようなコードで試してみた。language="ja"指定したりhint入れたほうがだいぶマシになった。
from openai import OpenAI
client = OpenAI()
hint = """\
あなたは日本語およびその方言体系に精通した専門家です。
与えられた音声データは日本の青森県の方言をお年寄りが話しています。この方言を正確に書き起こしてください。また、話し言葉をなるべく尊重してください。"""
with open("sample.m4a", "rb") as audio_file:
transcription = client.audio.transcriptions.create(
file=audio_file,
model="gpt-4o-transcribe",
language="ja",
prompt=hint
)
print(transcription.text)
結果
意味合い的には1mmも合ってないのだが、なんとなーーく青森の方言感が出ている気がする。
あとからね、食べて、それでもばばも、餌くしたして、餌くして、そこは田のばさまどさ、それちゃかんば左してって、餌くしたして、どうもなんねえんだど。
ちなみにlanguage="ja"とかhintのパラメーターを足す前は以下のような結果であり全然ダメだった。
この違いを見るとhintの内容次第でもっと改善の余地はたぶんあるんだろうなという感覚。
お父さんは左して行って、餌来たって来たって
kotoba-whisper-v2.2-faster
Whisperをベースに日本語特化で蒸留させたやつらしい。つまり日本語が得意とのこと。
from faster_whisper import WhisperModel
AUDIO_FILE = "sample.m4a"
def main():
# kotoba-whisper-v2.2-faster を指定
model = WhisperModel(
"RoachLin/kotoba-whisper-v2.2-faster",
device="cpu", # "cuda" も使えるがmacOSで動かしているのでcpu駆動
compute_type="float32", # 日本語の場合はfp32が一番良いらしい
)
segments, info = model.transcribe(
AUDIO_FILE,
language="ja", # 日本語固定
beam_size=10, # sizeを上げると若干よくなる?
vad_filter=True, # 無音区間を自動除去
)
print("=== Transcription ===")
for segment in segments:
start = segment.start
end = segment.end
text = segment.text
print(f"[{start:6.2f}s -> {end:6.2f}s] {text}")
print("\n=== Metadata ===")
print(info)
if __name__ == "__main__":
main()
結果
いきなり医者が登場した。ババは合ってる。ただこちらもまた文字も意味合いも全く合ってない。
=== Transcription ===
[ 0.05s -> 4.99s] それでもババも医者来たって来たって
[ 4.99s -> 7.61s] それでも馬場もいっしゃってそこはだのばさまどおりちゃくちゃ
[ 7.61s -> 9.05s] はいたりしてして
[ 9.05s -> 11.05s] いさくしたって来たって
=== Metadata ===
TranscriptionInfo(language='ja', language_probability=1, duration=11.940375, duration_after_vad=11.892375, all_language_probs=None, transcription_options=TranscriptionOptions(beam_size=10, best_of=5, patience=1, length_penalty=1, repetition_penalty=1, no_repeat_ngram_size=0, log_prob_threshold=-1.0, no_speech_threshold=0.6, compression_ratio_threshold=2.4, condition_on_previous_text=True, prompt_reset_on_temperature=0.5, temperatures=[0.0, 0.2, 0.4, 0.6, 0.8, 1.0], initial_prompt=None, prefix=None, suppress_blank=True, suppress_tokens=(1, 2, 7, 8, 9, 10, 14, 25, 26, 27, 28, 29, 31, 58, 59, 60, 61, 62, 63, 90, 91, 92, 93, 359, 503, 522, 542, 873, 893, 902, 918, 922, 931, 1350, 1853, 1982, 2460, 2627, 3246, 3253, 3268, 3536, 3846, 3961, 4183, 4667, 6585, 6647, 7273, 9061, 9383, 10428, 10929, 11938, 12033, 12331, 12562, 13793, 14157, 14635, 15265, 15618, 16553, 16604, 18362, 18956, 20075, 21675, 22520, 26130, 26161, 26435, 28279, 29464, 31650, 32302, 32470, 36865, 42863, 47425, 49870, 50254, 50258, 50359, 50360, 50361, 50362, 50363), without_timestamps=False, max_initial_timestamp=1.0, word_timestamps=False, prepend_punctuations='"\'“¿([{-', append_punctuations='"\'.。,,!!??::”)]}、', multilingual=False, max_new_tokens=None, clip_timestamps=[0.0], hallucination_silence_threshold=None, hotwords=None), vad_options=VadOptions(threshold=0.5, neg_threshold=None, min_speech_duration_ms=0, max_speech_duration_s=inf, min_silence_duration_ms=2000, speech_pad_ms=400))
AWS: Transcribe
AWS純正の文字起こしサービス。こちらはマネジメントコンソールからポチポチでさくっと対応。
こんな感じの設定。そもそもあまりイジれない。普通にファイルアップロードして、言語として明示的に日本語を指定するだけ。
結果
↑の画像にも載っているのだが、まぁ全くダメ... 何かしらチューニングの余地はあるのだろうか。
カスタム言語モデル作るしか無いか?
後からでもどうも
Google Cloud: Speech-To-Text
Google謹製の文字起こしサービス。まぁ主要なクラウドプラットフォーマーは軒並み似たようなのを用意しているね。
こちらもAWSと同じでイジれるところはほぼない。日本語を明示的に指定しつつ、APIバージョンをv2で固定、モデルをLongを指定しておく。たぶんこれが一番良いやつ。
結果
文字起こし不能。何も文字が出力されなかった。
こちらもパラメーター的なのはほぼないのでチューニングの余地があまりなさそう。
強化学習的なことはできそうなので、そっちでやってみてどうか? 可能性はありそう。
番外編
AIだのLLMだのではないのだが、東京生まれの妻に文字起こしおよび標準語訳をやってみてもらった。
やってもらった原文そのままを載せる。
本人曰く、結婚した当初に比べて、最近はだいぶ言葉わかるようになった!と豪語していた。
結果
- 単純 文字起こし
- 合ってはいないのだが、さすが人間
- まぁ単語レベルで細かいところは文字起こしできてる気がする
あずがらおねえちゃんだて……ついてはバッバも、いしゃきさきさしてほれ、いたくてしょうがないのあのばさまの……あれだれして、いしゃきさきさどうにもなんねえだの
↑をベースに標準語訳。つまり、この会話をして自分がどういう意味で脳内解釈しているか?
後からおねえちゃんについてバアバも行った。医者がきた。痛くてしょうがないと医者が来てもどうにもならないのに。
全く違う。残念賞。どうも妻は自身の能力を過信しているようだ。
さいごに
まぁ無理だわな、というのが正直な感想。汎用モデルではさすがに厳しいやろな、と。
関西弁のように日本語の中ではまだメジャーな方言ならまだしも、別に青森の方言に限らず、あらゆる地域の方言がだいぶ厳しいと思う。もちろん程度の差はあると思うが。
無理だろな、と思って試してみて、やっぱ無理かとなったのだが、それでも自分の中では一つ進歩ではある。やっぱ無理だよねっていうのを知るのだけでも、それはまた失敗ではなく前進である。
これらの結果を受けて、今、自分の中では、これもっとサンプルを綺麗に用意して自分で専用文字起こしモデル作ってみたいなと思ってたりする。これ系統の分野は全く知識がなさすぎるのでまず色々勉強が必要になるのだが、是非2026年はそういうのも挑戦してみたい。

