⇒レポート

Whisperを使って映画「72時間」のセリフ書き起こしをしてみる

2025-03-04

年明け早々の2025年1月2日、前年に北朝鮮国内での公開が確認されていた新作映画「72시간(72時間)」が朝鮮中央テレビで放送され[1]、日本をはじめとする諸外国の人々の初めて目にするところとなった。
本映画は2022年公開の「하루낮 하루밤(一昼一夜)」に続き、2020年代に入って2作目の長編映画であり、冒頭で説明がある通り、金正恩氏が直々に指導を行い、また一部シーンはカザフスタンにて撮影される[2]など、大掛かりな撮影が行われた力作であることが以前から示唆されており[3]、北朝鮮について調べている人々の間では話題となっていた。
十分な大きさのパラボラアンテナが入手できず、映像を受信できなかったことは痛恨の極みであったが、1月4日、朝鮮総連が保有していると思われるYoutubeアカウント「elufa tv」に、前後編がそれぞれアップロードされた[4]。
無論これらは朝鮮語のままであり、字幕なども付けられていないので、日本語でこの映画を楽しみたいと求める人々の間で、全編翻訳の機運が高まった。
しかしながらこの映画、前編2時間11分、後編1時間51分と、長さが合計4時間近くもある。すべて人力で聞き取り、書き起こしを行おうとするなら、どれだけ手間がかかるか計りしれない。
折しも、将来的に入手した映像の機械的な音声文字起こしが必要になるだろうと考えていたため、せっかくならこの機会にと、AIによる文字起こしを試してみることにした。
筆者はAIについての専門家ではないので、改善の余地は至る所にあると考えられるが、一見したところかなり精度の良い[5]書き起こしを得られたと思っているので、ぜひその成果物を活用してもらいたい(ただし成果物を活用する際は少なくともintchoson.comのURLを出典として記載していただけるよう、お願い申し上げる)。

firefoxプラグインの「Video DownloadHelper」と「えこでこツール」を使って音声を取得、「Online MP3 Cutter」を使って前編7分割、後編6分割にする。分割したファイルをGoogleDrive上にアップロードし、GoogleColab上に書いたpythonのコードで処理を行う。
ここでOpenAIの開発しているAI、「Whisper」を使うが、無音シーンが多いとrepetition(繰り返し、幻聴)が起こるので、「Silero VAD」という音がある部分とない部分を判別してくれるAIで下処理をする。が、どうもこの処理を行うとセリフの最初の部分が切れがちになってしまう模様である。
VADを使ったものと使わないでそのままWhisperに投げたもの、どちらも作成したので、両方を見比べながら翻訳をしていくのがよいかと思われる。
なお、Whisperのモデルにはtinyからlargeまで種類があり、精度と情報の処理量に違いがあるが、今回はlargeに次いで大きいmediumを使用した。largeでも試行してみたものの、モデルが大きすぎて処理が追い付いていないのか、むしろmediumよりも聞き取り精度は落ちているように思われた。

以下にそれぞれ実行した際の結果(テキストファイル、ログをコピーアンドペーストしたもの)のダウンロードリンクを設ける。

前編、VADなし:72hours1_novad.txt
前編、VADあり:72hours1_vad.txt
後編、VADなし:72hours2_novad.txt
後編、VADあり:72hours2_vad.txt

googlecolab上に書いたpythonのコードは以下の通り。

VADなし

         
         !pip install git+https://github.com/openai/whisper.git
         
         import whisper
         lang = "ko"
         tra_model = whisper.load_model("medium")
         name = 72hours1
         #今回は前編を7等分して72hours1_番号.wavという形でGoogleDrive上にupしている。その72hours1の部分

         for i in range(1,8):
         	audio = whisper.load_audio(f"/content/drive/MyDrive/"+name+"_"+str(i)+".wav")

         	results = tra_model.transcribe(audio,verbose=True,language=lang)

                for result in results["segments"]:
         		with open(f"/content/drive/MyDrive/72hours.txt", "a") as txt1:
         			txt1.write(result["text"]+"\n")
         
        

VADあり

         
         !pip install git+https://github.com/snakers4/silero-vad.git
         !pip install git+https://github.com/openai/whisper.git

         import whisper
         import torch
         import torchaudio
         from silero_vad import load_silero_vad, read_audio, get_speech_timestamps
         from torchaudio.transforms import Resample

         vad_model = load_silero_vad(onnx=True)
         lang = "ko"
         tra_model = whisper.load_model("medium")
         name = 72hours1
         #同上、GoogleDrive上にupした音声ファイルの名前。

         for i in range(1,7):
         	waveform, sample_rate = torchaudio.load(f"/content/drive/MyDrive/"+name+"_"+str(i)+".wav")

         	#Silero VADはサンプリングレート16000に最適化されているようなので、サンプリングレートを変換

         	if sample_rate != 16000:
         		resample_transform = Resample(orig_freq=sample_rate, new_freq=16000)
         		waveform = resample_transform(waveform)
         		sample_rate = 16000

        	#ステレオ音源だとWhisperがエラーになるので、モノラル音源に変換
        	#参考:https://note.com/owlet_notes/n/n4ba64137456a

         	if waveform.shape[0] > 1:
         		waveform = torch.mean(waveform, dim=0, keepdim=True)

         	#VADで音声を切り出し、tempファイルとしてdriveに一時保存、逐次Whisperで聞き取り

         	speech_segments = get_speech_timestamps(waveform,vad_model,sampling_rate=sample_rate)

        	for segment in speech_segments:
        		segment = waveform[:, (segment["start"]):(segment["end"])]
         		temp_audio_path = "/content/drive/MyDrive/temp_audio.wav"
         		torchaudio.save(temp_audio_path, segment, sample_rate)

         		results = tra_model.transcribe(temp_audio_path,verbose=True,language=lang)

          		for result in results["segments"]:
         			with open(f"/content/drive/MyDrive/72hours.txt", "a") as txt1:
          				txt1.write(result["text"]+"\n")         
         
        

[1]
磯部太郎丸(@iso_taro_maru)氏のツイート
ののじのじ(@nnjnoji)氏のツイート
[2]
2024-06-24付駐北朝鮮ロシア大使館の投稿には"Постарались все – и сценаристы и режиссер и, конечно, актеры. Авторы использовали все современные кинематографические приемы, чтобы держать зрителей в остром напряжении от первых кадров и до кульминации, когда знамя народной республики взвилось на зданием Национального собрания в столице РК."とあり、少なくともカザフスタンの国会議事堂においてロケが行われたことが述べられている。
[3]
2024-07-19付Radio Free Asiaの記事「북, 전쟁영화 ‘72시간’ 갑자기 상영 금지」では、消息筋が"영화는 김정은 시대의 대표적인 영화로 기획되면서 시작부터 막대한 제작비용과 4년의 제작기간이 소요된 것으로 안다"(映画は金正恩時代の代表的な映画と企画され、初めてから莫大な製作費用と4年の製作期間が所要されたものと知っている)と語ったことを伝えている。
[4]
前編:조선예술영화 《72시간 전편》
後編:조선예술영화 《72시간 후편》
[5]
WhisperのGitHubページに掲載されているグラフを見ると、韓国・朝鮮語についてはCommon Voice 15とFleursの両データセットにおいて文字誤り率(CER)が3番目に低いことがわかる。つまり、幸運なことにWhisperは韓国・朝鮮語の聞き取りと非常に相性が良い。ぜひ本記事を参考にして、各々活用していただければ幸いである。