Whisper-large-v3の運用、全自動字幕の作り方

## はじめに
最近英語を勉強してますが、英語の映画やアニメに英語字幕がないことが多いです。英語学習のため、あるフォルダ内の全てのビデオに一括で字幕を生成したいと考えています。そこで「whisper」を見つけて試してみました、試したところ英語学習には全く問題ありません。

## Whisper
OpenAIのWhisperは、高精度で多言語に対応した自動音声認識（ASR）システムです。このシステムは、大規模なデータセットを用いた深層学習によって訓練されており、様々な言語やアクセント、さらにはノイズが含まれる環境下でも効果的に音声をテキストに変換する能力を持っています。

## 実践
```python
import whisper
import datetime
from moviepy.editor import VideoFileClip, AudioFileClip
import srt
from pathlib import Path
import os

os.environ["PYTORCH_CUDA_ALLOC_CONF"] = "max_split_size_mb:50"


def generate_srt(transcription):
    """Generate SRT subtitles from transcription."""
    subtitles = []
    for segment in transcription["segments"]:
        start = datetime.timedelta(seconds=segment["start"])
        end = datetime.timedelta(seconds=segment["end"])
        text = segment["text"]
        subtitles.append(srt.Subtitle(index=len(subtitles) + 1, start=start, end=end, content=text))

    return srt.compose(subtitles)


def extract_audio(video_path, audio_path="temp_audio.wav"):
    """Extract audio from video."""
    video_clip = VideoFileClip(video_path)
    video_clip.audio.write_audiofile(audio_path)
    return audio_path

def split_audio(audio_path, num_segments=4):
    """Split the audio into multiple segments."""
    audio_clip = AudioFileClip(audio_path)
    duration = audio_clip.duration
    segment_duration = duration / num_segments
    segments = []

    for i in range(num_segments):
        start = i * segment_duration
        end = min((i + 1) * segment_duration, duration)
        segment = audio_clip.subclip(start, end)
        segment_path = f"temp_segment_{i}.wav"
        segment.write_audiofile(segment_path)
        segments.append(segment_path)

    return segments

def transcribe_segment(segment_path, model):
    """Transcribe a single audio segment."""
    result = model.transcribe(segment_path,language="en")
    return result

def generate_sub(transcription):
    """Generate SUB subtitles from transcription."""
    subtitles = []
    for segment in transcription["segments"]:
        start = segment["start"]
        end = segment["end"]
        text = segment["text"]
        subtitles.append(f"{start:.2f} --> {end:.2f}\n{text}\n\n")

    return "".join(subtitles)

def main(folder_path, output_folder_path, num_segments=1):
    Path(output_folder_path).mkdir(parents=True, exist_ok=True)
    video_files = [f for f in Path(folder_path).glob("**/*") if f.is_file() and f.suffix.lower() in ['.mp4', '.mkv', '.avi', '.mov', '.flv', '.wmv']]
    model = whisper.load_model("large-v3", device="cuda")
    for video_file in video_files:
        video_path = str(video_file)
        audio_path = extract_audio(video_path)
        transcription = transcribe_segment(audio_path, model)
        subtitles = generate_srt(transcription)
        
        output_sub_path = os.path.join(output_folder_path, video_file.stem + ".srt")
        with open(output_sub_path, "w") as f:
            f.write(subtitles)

# 使用例
folder_path = "./"  # あなたの動画フォルダのパスに置き換えてください
output_folder_path = "./"  # 出力字幕フォルダのパスに置き換えてください
main(folder_path, output_folder_path)


```
## 最後の一言
もしメモリが十分であれば、v3を使うのが最善です。私が「けいおん！」第1話の英語字幕を生成したとき、精度が明らかに向上しました。メモリが不足している場合は、量子化やより小さなモデルを検討するしかありません（8GBの現存ではv3は使用できません）。