Whisper 音声・動画の自動書き起こしAIを無料で、簡単に使おう

OpenAIが公開しているWhisper(音声・動画の自動書き起こしAI)を
簡単に試す方法がありましたので、記録として残します。

副業の「文字起こし」「テープ起こし」「動画のテロップ作成」など
非常に有効な武器となりそうなので、身に付けるべく。


動かしてみよう

自分のローカルのパソコンに、pythonの環境を用意して実行もしましたが、
圧倒的にGoogle Colaboratoryで実行する方が簡単でした。

しかも、Google Colaboratoryの利用は、1日の使用量に制限はありますが無料です。


Google Colaboratoryにアクセス

Googleアカウントを取得している前提ですが、
Google Colaboratoryにアクセスします。「ノートブックの新規作成」を選択します。

最初に、「編集」→「ノートブックの設定」から、
ハードウェアアクセラレートを「GPU」に設定しましょう。

以下のコマンドを入力し、Shift+Enterを押して実行しましょう。
GPUの情報が出てくれば、正常に設定変更できています。

!nvidia-smi

Googleドライブへのアクセス許可

読み込ませる音声ファイルをGoogleドライブ経由で取得できるように、
マウント(ドライブの認識)をさせます。

以下のコードを入力し、Shift+Enterを押して実行しましょう。

from google.colab import drive
drive.mount('/content/drive')

Googleドライブへの接続を許可してください。
「Mounted at /content/drive」と出れば、正常に完了しています。


Whisperのインストール

必要なパッケージのインストールと、使用するモデルのサイズを指定します。
以下のコードを入力し、Shift+Enterを押して実行しましょう。

! pip install git+https://github.com/openai/whisper.git
import whisper
model = whisper.load_model("medium")

modelの値は、以下の通りです。
medium, largeのどちらかが現実的な選択肢です。それ以下だと手直しが大変です。
※ローカルの非力なパソコンでは、逆にsmall, baseあたりでないと動きません。


Googleドライブに音声ファイルを置く

書き起こしたい音声ファイルをGoogleドライブのマイドライブ直下に保存します。

続けて、以下のコードを入力し、Shift+Enterを押して実行しましょう。
※ファイル名は適宜修正してください。

以下にサンプルファイル「g_03.mp3」を置きます。

※http://pro-video.jp/voice/announce/より引用

file_name = "g_03.mp3"

Whisperの実行

以下のコードを入力し、Shift+Enterを押して実行しましょう。
「verbose=True」を指定すると、処理最中の結果を表示させることができます。お好みで。

result = model.transcribe("/content/drive/MyDrive/" + file_name)
#result = model.transcribe("/content/drive/MyDrive/" + file_name, verbose=True)
import pandas as pd
pd.DataFrame(result["segments"])[["id", "start", "end", "text"]]

#segments = result["segments"]

#for data in segments:
#   print(data["text"])

以下のように出力されれば、成功です。ゆっくり丁寧なので、正確に認識できています。


応用してみましょう

動画からの文字起こし

Youtube動画の文字起こしをするように、コードを変えてみます。
modelの値もlargeに変えてみます。

yt-dlpで、Youtube動画の音声データをダウンロードして、input.mp3で保存しています。
残りは、同じ手法です。

ひろゆきさんの動画を、サンプルとして取り扱います。早口の場合の例になるかと。
https://youtu.be/u9eXBAnETVI

! pip install git+https://github.com/openai/whisper.git
import whisper
model = whisper.load_model("large")
! pip install yt-dlp
! rm input.mp3 
! yt-dlp -x --audio-format mp3 https://youtu.be/u9eXBAnETVI -o "input.mp3"
result = model.transcribe("input.mp3")
#result = model.transcribe("input.mp3", verbose=True)
import pandas as pd
pd.DataFrame(result["segments"])[["id", "start", "end", "text"]]

#segments = result["segments"]

#for data in segments:
#   print(data["text"])

以下の結果が出力されれば、成功です。

早口で話しているので、誤認識が多くなっていますね。
modelの値は、largeにすると、文の区切りが上手になりました。
人名は厳しそうです。しかし、ほとんど合っていると言って良い出来です。


字幕ファイルを作る

ジコログさんのブログを参考にしました。
最終的に、test.srtと言う字幕ファイルが作成するコードです。

また、早口なので1つの出力文章が長くなってしまう対策として、
whisperを改良して1つの出力文章の長さを変更できるソースを見つけました。
https://github.com/nyanta012/whisper
ソース中の「segment_length_ratio」⇒変数「slr」で調整しています。
※こちらのソースだと「verbose=True」オプションはエラーが出たので、留意してください。

字幕ファイルが自動で作成できれば、動画のテロップ作成は大幅に短縮できます。

! pip install git+https://github.com/nyanta012/whisper.git
import whisper
model = whisper.load_model("large")
! pip install yt-dlp
! rm input.mp3 
! yt-dlp -x --audio-format mp3 https://youtu.be/u9eXBAnETVI -o "input.mp3"
# 出力される1文の長さの調整(デフォルト=1.0)
slr = 0.3
# 出力された字幕ファイルのタイムラグ調整(秒)
time_lag = 0.0

result = model.transcribe("input.mp3", segment_length_ratio=float(slr))
#import pandas as pd
#pd.DataFrame(result["segments"])[["id", "start", "end", "text"]]
! pip install srt

from datetime import timedelta
from srt import Subtitle
import srt

segments = result["segments"]

subs = []
 
for data in segments:
    index = data["id"] + 1
    start = data["start"] + time_lag
    end = data["end"] + time_lag
    text = data["text"]
    sub = Subtitle(index=1, start=timedelta(
                            seconds=timedelta(seconds=start).seconds,
                            microseconds=timedelta(seconds=start).microseconds),
                            end=timedelta(
                            seconds=timedelta(seconds=end).seconds,
                            microseconds=timedelta(seconds=end).microseconds),
                            content=text, proprietary='')
 
    subs.append(sub)

with open("test.srt", mode="w", encoding="utf-8") as f:
    f.write(srt.compose(subs))
!cat test.srt

以下の結果になっていれば成功です。

segment_length_ratioの値は、動画によって適宜変更するとよいと思います。

※参考までに、改良したソースの中身を見させて頂いたところ、以下の通りでした。
 すごいですね。

whisper/decording.py
 99 +    # segment length
100 +    segment_length_ratio : Optional[float] = 1.0
101 +
403 -        self, tokenizer: Tokenizer, sample_begin: int, max_initial_timestamp_index: Optional[int]
406 +        self, tokenizer: Tokenizer, sample_begin: int, max_initial_timestamp_index: Optional[int],
407 +        segment_length_ratio: Optional[float]
412 +        self.segment_length_ratio = segment_length_ratio
440 -            if timestamp_logprob > max_text_token_logprob:
445 +            if timestamp_logprob*self.segment_length_ratio > max_text_token_logprob:
463 +        self.segment_length_ratio = options.segment_length_ratio
464 +
496 -                ApplyTimestampRules(tokenizer, self.sample_begin, max_initial_timestamp_index)
503 +                ApplyTimestampRules(tokenizer, self.sample_begin, max_initial_timestamp_index, self.segment_length_ratio)

今回はここまで。

コメントする

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

1 × five =