日本語を喋っている動画にFaster-WhisperとChatGPTを使って字幕を付ける

実現したこと

日本語が分からない人に色々と講習をうまく出来ないかということで、日本語でやっている講習の動画ファイルに英語字幕をつけたくなりました。

そこで、以前、動画ファイルから日本語の字幕あるいはChatGPTで英訳した英語の字幕をつけるPythonコードを紹介しました。

Whisperは処理に時間がかかるので、より高速なFaster-whisperを使った方法でPythonスクリプトを書いたので紹介します。

スクリプトの概要

このPythonスクリプトは、動画ファイルに字幕を追加するための強力なツールです。音声認識と翻訳機能を組み合わせ、字幕の生成から動画への追加まで一連の作業を自動化できます。主に以下の機能を提供します:

  1. 音声認識による字幕生成

  2. 既存のSRTファイルを使用した動画への字幕追加

  3. 字幕ファイルの翻訳

主要な機能

1. 字幕生成 (SRTGeneratorクラス)

  • Faster-Whisperを使用して音声認識を行い、字幕を生成します。

  • 音声を適切なチャンクに分割して処理し、生成された字幕をSRT形式で保存します。

  • Whisperの翻訳機能を利用して、字幕を英語に翻訳することも可能です。

2. 字幕追加 (SubtitleAdderクラス)

  • 既存のSRTファイルを読み込み、字幕を動画に追加します。

  • 字幕のフォントサイズ、色、位置などをカスタマイズ可能です。

3. 字幕翻訳 (SRTTranslatorクラス)

  • OpenAIのAPIを使用して、既存のSRTファイルを指定した言語に翻訳します。

  • 翻訳のtemp(生成の多様性)を設定可能です。

特徴

  • moviepyを使用して、動画編集と字幕の追加を行います。

  • Faster-whisperライブラリを利用して高精度な音声認識を実現しています。

  • OpenAI APIを使った自動翻訳機能をサポート。

  • コマンドラインインターフェース(CLI)で簡単に操作できます。

環境構築

Docker engineインストール

https://docs.docker.com/engine/install/ubuntu/

インストールされている可能性のある古いDockerを削除

for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do sudo apt remove $pkg; done

Docker engineのインストール

sudo apt update
sudo apt install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
  $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt update
sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
sudo docker run hello-world
docker -v
wsl -—shutdown

sudoなしでdockerコマンドを使えるようにする

sudo groupadd docker
sudo usermod -aG docker rui
wsl --shutdown

Dockerを常時起動にする

再起動するたびにDockerを立ち上げるのがめんどくさいので設定する。

sudo visudo

最終行に下記を加える

docker ALL=(ALL)  NOPASSWD: /usr/sbin/service docker start
sudo nano ~/.bashrc

最終行に下記を追記する。

if [[ $(service docker status | awk '{print $4}') = "not" ]]; then
sudo service docker start > /dev/null
fi
source ~/.bashrc

NVIDIA dockerインストール

curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg \
&& curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list | \
sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' | \
sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list
sudo apt update
sudo apt install -y nvidia-container-toolkit
sudo nvidia-ctk runtime configure --runtime=docker
sudo systemctl restart docker

Docker container作製

Ubuntu on WSL
ホームフォルダで。
CUDA | NVIDIA NGC

docker pull nvcr.io/nvidia/cuda:12.6.2-cudnn-devel-ubuntu24.04
docker run -it --gpus all nvcr.io/nvidia/cuda:12.6.2-cudnn-devel-ubuntu24.04
apt update && apt full-upgrade -y
apt install git wget nano ffmpeg fonts-noto-cjk -y

minicondaインストール

cd ~
mkdir tmp
cd tmp

https://docs.anaconda.com/miniconda/#miniconda-latest-installer-links
linux 64-bitのリンクをコピー

wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh
bash Miniconda3-latest-Linux-x86_64.sh

# yes, enter, yes
# tmpフォルダを削除
cd ..
rm -rf tmp

exit

docker container ls -a

docker start <container id>

docker exec -it <container id> /bin/bash

conda環境構築

cd root
mkdir faster-subtitle-generator
cd faster-subtitle-generator
nano faster-subtitle-generator.yml
name: faster-subtitle-generator
channels:
  - conda-forge
  - pytorch
  - nvidia
  - defaults
dependencies:
  - python=3.11
  - pip
  - nvidia/label/cuda-12.6.2::cuda-toolkit
  - tiktoken
  - numpy
  - pillow
  - tqdm
  - python-dotenv
  - srt
  - moviepy
  - pip:
    - faster-whisper
    - torch
    - torchvision
    - torchaudio
    - openai
conda env create -f faster-subtitle-generator.yml
conda activate faster-subtitle-generator

スクリプト

nano faster-subtitle-generator.py
import os
import sys
import logging
from typing import List, Dict, Any
import torch
from faster_whisper import WhisperModel
from moviepy.editor import VideoFileClip, CompositeVideoClip, ColorClip, ImageClip
import srt
from datetime import timedelta
from PIL import Image, ImageDraw, ImageFont
import numpy as np
from tqdm import tqdm
import tiktoken
import textwrap
import argparse
from openai import OpenAI
from dotenv import load_dotenv

# Load environment variables from .env file
load_dotenv()

class Config:
    # Paths
    FONT_PATH = os.getenv('FONT_PATH', "/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf")
    JAPANESE_FONT_PATH = os.getenv('JAPANESE_FONT_PATH', "/usr/share/fonts/opentype/noto/NotoSansCJK-Bold.ttc")
    TEMP_AUDIO_FILE = os.getenv('TEMP_AUDIO_FILE', "temp_audio.wav")

    # Video processing
    DEFAULT_SUBTITLE_HEIGHT = int(os.getenv('DEFAULT_SUBTITLE_HEIGHT', 200))
    DEFAULT_FONT_SIZE = int(os.getenv('DEFAULT_FONT_SIZE', 32))
    MAX_SUBTITLE_LINES = int(os.getenv('MAX_SUBTITLE_LINES', 3))

    # Video encoding
    VIDEO_CODEC = os.getenv('VIDEO_CODEC', 'libx264')
    AUDIO_CODEC = os.getenv('AUDIO_CODEC', 'aac')
    VIDEO_PRESET = os.getenv('VIDEO_PRESET', 'medium')
    CRF = os.getenv('CRF', '23')
    PIXEL_FORMAT = os.getenv('PIXEL_FORMAT', 'yuv420p')

    # OpenAI settings
    OPENAI_API_KEY = os.getenv('OPENAI_API_KEY')
    DEFAULT_GPT_MODEL = "gpt-4o"
    GPT_MAX_TOKENS = 4000

# Logging setup
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)

class SubtitleProcessor:
    def __init__(self, video_path: str, srt_path: str):
        self.video_path = video_path
        self.srt_path = srt_path
        self.temp_files = []

    def cleanup_temp_files(self):
        logger.info("Cleaning up temporary files...")
        for file_path in self.temp_files:
            try:
                if os.path.exists(file_path):
                    os.remove(file_path)
                    logger.info(f"Removed temporary file: {file_path}")
            except Exception as e:
                logger.error(f"Error removing {file_path}: {e}")

class SRTTranslator:
    def __init__(self, model: str = Config.DEFAULT_GPT_MODEL, temperature: float = 0.3):
        api_key = Config.OPENAI_API_KEY
        if not api_key:
            raise ValueError("OpenAI API key is required. Set it in the environment variable 'OPENAI_API_KEY'.")
        self.client = OpenAI(api_key=api_key)
        self.model = model
        self.temperature = temperature

    def translate_srt(self, input_srt: str, output_srt: str, source_lang: str, target_lang: str):
        with open(input_srt, 'r', encoding='utf-8') as f:
            subtitle_generator = srt.parse(f.read())
            subtitles = list(subtitle_generator)

        translated_subtitles = []
        for subtitle in tqdm(subtitles, desc="Translating subtitles"):
            translated_content = self.translate_text(subtitle.content, source_lang, target_lang)
            translated_subtitle = srt.Subtitle(
                index=subtitle.index,
                start=subtitle.start,
                end=subtitle.end,
                content=translated_content
            )
            translated_subtitles.append(translated_subtitle)

        with open(output_srt, 'w', encoding='utf-8') as f:
            f.write(srt.compose(translated_subtitles))

    def translate_text(self, text: str, source_lang: str, target_lang: str) -> str:
        response = self.client.chat.completions.create(
            model=self.model,
            messages=[
                {"role": "system", "content": f"You are a professional translator. Translate the following text from {source_lang} to {target_lang}. Maintain the original meaning and nuance as much as possible."},
                {"role": "user", "content": text}
            ],
            temperature=self.temperature,
            max_tokens=Config.GPT_MAX_TOKENS
        )
        return response.choices[0].message.content.strip()

class SRTGenerator(SubtitleProcessor):
    def __init__(self, video_path: str, output_srt: str, model_name: str = "large-v3", 
                 compute_type: str = "float16", beam_size: int = 5):
        super().__init__(video_path, output_srt)
        self.model_name = model_name
        self.compute_type = compute_type
        self.beam_size = beam_size
        self.device = 'cuda' if torch.cuda.is_available() else 'cpu'
        
        # Initialize Faster Whisper model
        self.model = WhisperModel(
            model_name,
            device=self.device,
            compute_type=compute_type
        )

    def run(self):
        try:
            self.extract_audio()
            transcription, segments = self.transcribe_audio()
            self.create_srt(segments)
            logger.info(f"SRT file has been generated: {self.srt_path}")
        finally:
            self.cleanup_temp_files()

    def extract_audio(self):
        logger.info("Extracting audio from video...")
        video = VideoFileClip(self.video_path)
        video.audio.write_audiofile(Config.TEMP_AUDIO_FILE)
        self.temp_files.append(Config.TEMP_AUDIO_FILE)

    def transcribe_audio(self) -> tuple[str, List[Dict[str, Any]]]:
        logger.info(f"Transcribing audio using Faster Whisper model: {self.model_name}")
        
        try:
            # Try multi-segment language detection first
            language_info = self.model.detect_language_multi_segment(Config.TEMP_AUDIO_FILE)
            detected_language = language_info[0]
        except AttributeError:
            logger.info("Multi-segment language detection not available. Using standard detection.")
            segments, info = self.model.transcribe(Config.TEMP_AUDIO_FILE, beam_size=self.beam_size)
            detected_language = info.language
        
        logger.info(f"Detected language: {detected_language}")
        
        # Transcribe with detected language
        segments, info = self.model.transcribe(
            Config.TEMP_AUDIO_FILE,
            beam_size=self.beam_size,
            language=detected_language
        )
        
        transcription = ""
        formatted_segments = []
        
        for segment in segments:
            transcription += segment.text + " "
            formatted_segments.append({
                "start": segment.start,
                "end": segment.end,
                "text": segment.text.strip()
            })
        
        return transcription.strip(), formatted_segments

    def create_srt(self, segments: List[Dict[str, Any]]):
        logger.info("Creating SRT file...")
        subs = []
        for i, segment in enumerate(segments, start=1):
            start = timedelta(seconds=segment['start'])
            end = timedelta(seconds=segment['end'])
            text = segment['text']
            sub = srt.Subtitle(index=i, start=start, end=end, content=text)
            subs.append(sub)
        
        with open(self.srt_path, 'w', encoding='utf-8') as f:
            f.write(srt.compose(subs))

class SubtitleAdder(SubtitleProcessor):
    def __init__(self, video_path: str, output_video: str, input_srt: str, 
                 subtitle_height: int = Config.DEFAULT_SUBTITLE_HEIGHT):
        super().__init__(video_path, input_srt)
        self.output_video = output_video
        self.subtitle_height = subtitle_height

    def run(self):
        try:
            subs = self.load_srt(self.srt_path)
            self.add_subtitles_to_video(subs)
            logger.info(f"Video with subtitles has been generated: {self.output_video}")
        finally:
            self.cleanup_temp_files()

    @staticmethod
    def load_srt(srt_path: str) -> List[srt.Subtitle]:
        logger.info(f"Loading SRT file: {srt_path}")
        with open(srt_path, 'r', encoding='utf-8') as f:
            return list(srt.parse(f.read()))

    def add_subtitles_to_video(self, subs: List[srt.Subtitle]):
        logger.info(f"Adding subtitles to video with subtitle space height of {self.subtitle_height} pixels...")
        video = VideoFileClip(self.video_path)
        
        original_width, original_height = video.w, video.h
        new_height = original_height + self.subtitle_height
        
        background = ColorClip(size=(original_width, new_height), color=(0,0,0), duration=video.duration)
        video_clip = video.set_position((0, 0))
        
        subtitle_clips = [
            self.create_subtitle_clip(sub.content, original_width)
                .set_start(sub.start.total_seconds())
                .set_end(sub.end.total_seconds())
                .set_position((0, original_height))
            for sub in subs
        ]
        
        final_video = CompositeVideoClip([background, video_clip] + subtitle_clips, size=(original_width, new_height))
        final_video = final_video.set_duration(video.duration)
        
        final_video.write_videofile(
            self.output_video, 
            codec=Config.VIDEO_CODEC, 
            audio_codec=Config.AUDIO_CODEC,
            preset=Config.VIDEO_PRESET,
            ffmpeg_params=['-crf', Config.CRF, '-pix_fmt', Config.PIXEL_FORMAT],
            verbose=False,
            logger=None
        )

    @staticmethod
    def create_subtitle_clip(txt: str, video_width: int, font_size: int = Config.DEFAULT_FONT_SIZE,
                           max_lines: int = Config.MAX_SUBTITLE_LINES) -> ImageClip:
        if any(ord(char) > 127 for char in txt):
            font_path = Config.JAPANESE_FONT_PATH
        else:
            font_path = Config.FONT_PATH

        try:
            font = ImageFont.truetype(font_path, font_size)
        except IOError:
            logger.warning(f"Failed to load font from {font_path}. Falling back to default font.")
            font = ImageFont.load_default()
        
        max_char_count = int(video_width / (font_size * 0.6))
        wrapped_text = textwrap.fill(txt, width=max_char_count)
        lines = wrapped_text.split('\n')[:max_lines]
        
        dummy_img = Image.new('RGB', (video_width, font_size * len(lines)))
        dummy_draw = ImageDraw.Draw(dummy_img)
        max_line_width = max(dummy_draw.textbbox((0, 0), line, font=font)[2] for line in lines)
        total_height = sum(dummy_draw.textbbox((0, 0), line, font=font)[3] for line in lines)
        
        img_width, img_height = video_width, total_height + 20
        img = Image.new('RGBA', (img_width, img_height), (0, 0, 0, 0))
        draw = ImageDraw.Draw(img)
        
        y_text = 10
        for line in lines:
            bbox = draw.textbbox((0, 0), line, font=font)
            x_text = (img_width - bbox[2]) // 2
            
            for adj in range(-2, 3):
                for adj2 in range(-2, 3):
                    draw.text((x_text+adj, y_text+adj2), line, font=font, fill=(0, 0, 0, 255))
            
            draw.text((x_text, y_text), line, font=font, fill=(255, 255, 255, 255))
            y_text += bbox[3]
        
        return ImageClip(np.array(img))

def main():
    parser = argparse.ArgumentParser(
        description="Video subtitle generation, addition, and translation tool using Faster Whisper",
        formatter_class=argparse.RawTextHelpFormatter
    )
    subparsers = parser.add_subparsers(dest="action", required=True,
        help="Available commands: generate (create SRT), add (add subtitles to video), translate (translate SRT)")

    # Common arguments for generate and add commands
    common_parser = argparse.ArgumentParser(add_help=False)
    common_parser.add_argument("--input", required=True,
        help="Path to input video file")

    # Generate subparser
    generate_parser = subparsers.add_parser("generate", parents=[common_parser],
        help="Generate SRT file from video using Faster Whisper",
        description="Create SRT subtitle file from video using Faster Whisper speech recognition")
    generate_parser.add_argument("--output_srt", required=True,
        help="Path to output SRT file")
    generate_parser.add_argument("--model",
        default="large-v3",
        choices=["tiny", "base", "small", "medium", "large", "large-v2", "large-v3"],
        help="Faster Whisper model size (default: large-v3)")
    generate_parser.add_argument("--compute_type",
        default="float16",
        choices=["float16", "float32", "int8"],
        help="Model computation type. Use int8 for lower memory usage (default: float16)")
    generate_parser.add_argument("--beam_size",
        type=int,
        default=5,
        help="Beam size for transcription. Larger values = higher accuracy but slower (default: 5)")

    # Add subparser
    add_parser = subparsers.add_parser("add", parents=[common_parser],
        help="Add subtitles to video file",
        description="Add subtitles from SRT file to video file")
    add_parser.add_argument("--output_video", required=True,
        help="Path to output video file")
    add_parser.add_argument("--input_srt", required=True,
        help="Path to input SRT file")
    add_parser.add_argument("--subtitle_height",
        type=int,
        default=Config.DEFAULT_SUBTITLE_HEIGHT,
        help="Height of subtitle area in pixels (default: 200)")

    # Translate subparser
    translate_parser = subparsers.add_parser("translate",
        help="Translate SRT file using OpenAI API",
        description="Translate subtitles in SRT file from one language to another using OpenAI's GPT model")
    translate_parser.add_argument("--input_srt", required=True,
        help="Path to input SRT file")
    translate_parser.add_argument("--output_srt", required=True,
        help="Path to output translated SRT file")
    translate_parser.add_argument("--source_lang",
        default="Japanese",
        help="Source language of the SRT file (default: Japanese)")
    translate_parser.add_argument("--target_lang",
        default="English",
        help="Target language for translation (default: English)")
    translate_parser.add_argument("--temperature",
        type=float,
        default=0.3,
        help="Temperature setting for OpenAI translation (0.0-1.0) (default: 0.3)")

    args = parser.parse_args()

    try:
        if args.action == "generate":
            generator = SRTGenerator(
                args.input, 
                args.output_srt, 
                args.model, 
                args.compute_type,
                args.beam_size
            )
            generator.run()

        elif args.action == "add":
            adder = SubtitleAdder(
                args.input, 
                args.output_video, 
                args.input_srt,
                args.subtitle_height
            )
            adder.run()

        elif args.action == "translate":
            translator = SRTTranslator(temperature=args.temperature)
            translator.translate_srt(
                args.input_srt,
                args.output_srt,
                args.source_lang,
                args.target_lang
            )
            logger.info(f"Translation completed. Output saved to {args.output_srt}")

    except FileNotFoundError as e:
        logger.error(f"File not found: {e}")
        sys.exit(1)
    except ValueError as e:
        logger.error(f"Invalid argument: {e}")
        sys.exit(1)
    except Exception as e:
        logger.error(f"An error occurred: {e}")
        sys.exit(1)

if __name__ == "__main__":
    main()

.env

Create a .env file with your OpenAI API key:

# .env
OPENAI_API_KEY=sk-your_key

使用方法

ヘルプ

python faster-subtitle-generator.py --help
usage: faster-subtitle-generator.py [-h] {generate,add,translate} ...

Video subtitle generation, addition, and translation tool using Faster Whisper

positional arguments:
  {generate,add,translate}
                        Available commands: generate (create SRT), add (add subtitles to video), translate (translate SRT)
    generate            Generate SRT file from video using Faster Whisper
    add                 Add subtitles to video file
    translate           Translate SRT file using OpenAI API

options:
  -h, --help            show this help message and exit


python faster-subtitle-generator.py generate --help
usage: faster-subtitle-generator.py generate [-h] --input INPUT --output_srt OUTPUT_SRT
                                             [--model {tiny,base,small,medium,large,large-v2,large-v3}]
                                             [--compute_type {float16,float32,int8}] [--beam_size BEAM_SIZE]

Create SRT subtitle file from video using Faster Whisper speech recognition

options:
  -h, --help            show this help message and exit
  --input INPUT         Path to input video file
  --output_srt OUTPUT_SRT
                        Path to output SRT file
  --model {tiny,base,small,medium,large,large-v2,large-v3}
                        Faster Whisper model size (default: large-v3)
  --compute_type {float16,float32,int8}
                        Model computation type. Use int8 for lower memory usage (default: float16)
  --beam_size BEAM_SIZE
                        Beam size for transcription. Larger values = higher accuracy but slower (default: 5)


python faster-subtitle-generator.py translate --help
usage: faster-subtitle-generator.py translate [-h] --input_srt INPUT_SRT --output_srt OUTPUT_SRT [--source_lang SOURCE_LANG]
                                              [--target_lang TARGET_LANG] [--temperature TEMPERATURE]

Translate subtitles in SRT file from one language to another using OpenAI's GPT model

options:
  -h, --help            show this help message and exit
  --input_srt INPUT_SRT
                        Path to input SRT file
  --output_srt OUTPUT_SRT
                        Path to output translated SRT file
  --source_lang SOURCE_LANG
                        Source language of the SRT file (default: Japanese)
  --target_lang TARGET_LANG
                        Target language for translation (default: English)
  --temperature TEMPERATURE
                        Temperature setting for OpenAI translation (0.0-1.0) (default: 0.3)


python faster-subtitle-generator.py add --help
usage: faster-subtitle-generator.py add [-h] --input INPUT --output_video OUTPUT_VIDEO --input_srt INPUT_SRT
                                        [--subtitle_height SUBTITLE_HEIGHT]

Add subtitles from SRT file to video file

options:
  -h, --help            show this help message and exit
  --input INPUT         Path to input video file
  --output_video OUTPUT_VIDEO
                        Path to output video file
  --input_srt INPUT_SRT
                        Path to input SRT file
  --subtitle_height SUBTITLE_HEIGHT

ファイルをWindowsからコンテナにコピー

# on ubuntu command line
# docker container ls -aでコンテナ名を調べる
docker cp "/mnt/c/Windows_path/VVVV.mp4" docker_container_name:root/speech_to_text

使用例

# 字幕生成(generate)コマンド

1. 基本的な字幕生成:
input.mp4から日本語字幕ファイルを生成し、output.srtに保存
python script.py generate --input input.mp4 --output_srt output.srt

2. モデルサイズの指定:
小さいモデルを使用して高速処理
python script.py generate --input input.mp4 --output_srt output.srt --model small

3. 計算精度の指定:
int8を使用してメモリ使用量を削減
python script.py generate --input input.mp4 --output_srt output.srt --compute_type int8

4. ビームサイズの指定:
精度を上げるためにビームサイズを大きく設定
python script.py generate --input input.mp4 --output_srt output.srt --beam_size 10

# 字幕追加(add)コマンド

1. 基本的な字幕付加:
input.mp4input.srtの字幕を付けてoutput.mp4を生成
python script.py add --input input.mp4 --input_srt input.srt --output_video output.mp4

2. 字幕エリアの高さを指定:
字幕エリアを300ピクセルに設定
python script.py add --input input.mp4 --input_srt input.srt --output_video output.mp4 --subtitle_height 300

# 字幕翻訳(translate)コマンド

1. 基本的な翻訳:
日本語の字幕ファイルを英語に翻訳
python script.py translate --input_srt japanese.srt --output_srt english.srt --source_lang Japanese --target_lang English

2. 翻訳の温度設定:
より創造的な翻訳のために温度を上げる
python script.py translate --input_srt japanese.srt --output_srt english.srt --source_lang Japanese --target_lang English --temperature 0.7

# 実践的な使用シナリオ

1. 日本語動画の英語字幕作成:
- 字幕生成: python script.py generate --input japanese_video.mp4 --output_srt japanese.srt
- 翻訳: python script.py translate --input_srt japanese.srt --output_srt english.srt --source_lang Japanese --target_lang English
- 字幕付加: python script.py add --input japanese_video.mp4 --input_srt english.srt --output_video english_subtitled.mp4

2. 高品質な字幕生成(処理時間重視):
- 大きいモデルと高精度設定で生成: python script.py generate --input video.mp4 --output_srt output.srt --model large-v3 --compute_type float32 --beam_size 15
- 大きい字幕エリアで追加: python script.py add --input video.mp4 --input_srt output.srt --output_video final.mp4 --subtitle_height 250

3. リソース制約環境での処理:
- 小さいモデルと低精度設定で生成: python script.py generate --input video.mp4 --output_srt output.srt --model tiny --compute_type int8 --beam_size 3

注意事項:
1. すべてのコマンドを実行する前に.envファイルにOPENAI_API_KEYを設定する必要があります
2. 大きなモデルや高精度設定は処理時間とメモリ使用量が増加します
3. 字幕エリアの高さは動画の解像度に応じて適切に設定する必要があります
4. GPUが利用可能な場合は自動的に使用されます

ファイルをコンテナからWindowsにコピー

docker cp docker_container_name:root/path/xxx.mp4 "/mnt/c/Windows path/"

まとめ

このPythonスクリプトは、Faster-WhisperとOpenAIのAPIを組み合わせて、動画に対して自動で高精度な字幕を生成し、翻訳や字幕の追加を行うことができます。教育や研究、コンテンツ制作において、時間を効率的に使うための強力なツールです。

興味があればぜひ試してみてください!。

これで教育・研究活動に時間が使えるようになりハッピーになると良いですね。

AIの進歩は目覚ましいものがあります。皆さんも、このようなAI技術を活用して、より効率的な作業環境を作り上げていってください!

質問や改善点があれば、ぜひコメントで教えてください。

この記事が気に入ったらサポートをしてみませんか?