音声認識AIのWhisperを利用して、英語動画をテキスト化したい

# 概要
Qiita初投稿なので至らぬ点があればご容赦ください。
私はセキュリティエンジニアとして勤務していますが、勉強するには英語の教材に向き合うことが多々あります。youtubeであれば翻訳字幕機能を使ったり、文献であればDeepLを使えばいいのですが、そうではない動画では英語字幕すらない場面に遭遇します。
なんとか英語の動画をテキスト化し、DeepLで翻訳できればと思いPythonで組んでみました。

# お断り
普段プログラムを書くことがないため、変な書き方をしているかもしれません。

# 構築環境
OS：Windows11
Python：3.9　Anaconda3使用
NVIDIA CUDA ツールキット：11.7
NVIDIA cuDNN：8.5
ffmpeg：0.2.0
pytorch：1.13.1+cu117

# Whisperの準備
OpenAIが開発している汎用的な音声認識モデルになります。音声からの文字起こしと翻訳機能を兼ねています。ただし、英語から日本語には対応していないため英語のテキスト化に使用していきます。
CPUのみで稼働させることもできますが、GPUを使った方が圧倒的に早く処理が終わるので事前に必要なソフトウェアをインストールしていきます。参考に以下のサイトをご覧ください。現役の大学教授が画像付きで詳しく解説されているので、非常に参考になります。

https://www.kkaneko.jp/ai/win/whisper.html


私はNVIDIA CUDA ツールキット11.7とNVIDIA cuDNN8.5をインストールしました。cuDNNの最新バージョンに合わせてCUDAツールキットを入れてうまくいきました。

Pythonの環境はAnacondaを入れれば簡単にできますので、Anacondaに必要なモジュールをインストールしていきます。
こちらは以下のサイトを参考にしました。

https://tadaoyamaoka.hatenablog.com/entry/2022/09/23/140401

https://qiita.com/jonpili/items/e5444c31fbd16f30725a


以下のとおりインストールしていきます。
```python
conda activate whisper
conda install pytorch torchvision torchaudio cudatoolkit=11.6 -c pytorch -c conda-forge
conda install ffmpeg -c conda-forge
pip install git+https://github.com/openai/whisper.git
```

# 変換を実行していく
これで一通り実行のための環境が完成しています。
私は英語のmp4の動画を見ることが多いためmp4のみを明記していますが、ここは変えることで他の形式にも対応できるはずです。
```python movie_to_text.py
import whisper
import requests
import glob
import os

#モデルサイズになります。英語に対応している中で一番性能が良いものを選んでいます
model = whisper.load_model("medium")

#カレントディレクトリのmp4を全て対象にしています
input_mp4 = glob.glob('./*.mp4')

#保存用のフォルダを作成します
english_path = './english_text'
os.mkdir(english_path)

#読み込んだmp4をテキスト化し、txtで保存していきます
for i in input_mp4:
    print(i + 'をテキスト化していきます。')
    result = model.transcribe(i, verbose=True, language='en')
    basename = os.path.splitext(os.path.basename(i))[0]
    english_text_file = english_path + "/" + basename + '.txt'
    with open(english_text_file, 'w', encoding='UTF-8') as f:
        f.write(result["text"])
    
    # 読みやすいようにピリオドで改行する
    with open(english_path + '/' + basename + '.txt') as f:
        raw_data = f.read()
    raw_data = raw_data.replace(".", ".\n")
    with open(english_path + '/' + basename + '.txt', mode="w") as f:
        f.write(raw_data)

# 以下はDeepL用です。必要なかったら記載する必要はありません

# API Keyを入力
API_KEY:str = 'あなたのAPIキーを入力してください'

english_text = glob.glob('./english_text/*.txt')
translate_path = './translate_text'
os.mkdir(translate_path)

for j in english_text:
    # 翻訳元のファイル名を入力します
    basename = os.path.splitext(os.path.basename(j))[0]
    english_text_file = english_path + "/" + basename + '.txt'
    source_file:str = english_text_file

    # 翻訳したいファイルを開きます
    with open(source_file) as f:
        txt = f.read().replace('\n', ' ')

    # 英語から日本語に変換します
    params = {
        "auth_key": API_KEY,
        "text": txt,
        "source_lang": 'EN',
        "target_lang": 'JA'
    }

    # DeepL APIにPOST
    # これはfree版URLなので有償版を利用している人は適宜URLを変更する必要があります
    req = requests.post("https://api-free.deepl.com/v2/translate", data=params)

    # json形式で結果を取得します
    result = req.json()

    # txt形式で結果を保存します
    # DeepLの制限が来ると、この部分でエラーを吐くはずです
    with open(translate_path + '/' + basename + '.txt', "w") as text_file:
        text_file.write(result["translations"][0]["text"])
```

# まとめ
以上のコードで英語動画をテキスト化することができると思います。DeepLをAPIで使用するのが理想ですが、５０万字の制限は意外とすぐ来てしまうので、お金をかけずに行うなら最終的には手動になってしまうと思います。