複数の英語音声ファイルを一括で文字起こし＆日本語翻訳する方法【Whisper × Google Colab】

# 複数の英語音声ファイルを一括で文字起こし＆日本語翻訳する方法【Whisper × Google Colab】

こんにちは！今回は、**OpenAIのWhisperモデル**と**Google Colab**を活用して、**英語の音声ファイルを一括で文字起こしし、日本語に翻訳**する方法を詳しく解説します。

例えば、英語で行われた打ち合わせや会議を録音した複数の音声ファイルを、一度に文字起こしして日本語に翻訳できたら便利ですよね。このブログでは、その具体的な手順とコードをステップバイステップで紹介します。

***

## 目次

1.  [はじめに](#はじめに)
2.  [必要な準備](#必要な準備)
    *   [Google Colabの設定](#google-colabの設定)
    *   [必要なライブラリのインストール](#必要なライブラリのインストール)
3.  [コードの詳細解説](#コードの詳細解説)
    *   [ライブラリのインポート](#ライブラリのインポート)
    *   [文章の分割関数の定義](#文章の分割関数の定義)
    *   [翻訳関数の定義](#翻訳関数の定義)
    *   [Whisperモデルの読み込み関数の定義](#whisperモデルの読み込み関数の定義)
    *   [音声ファイルのアップロードと処理](#音声ファイルのアップロードと処理)
4.  [エラーの対処方法](#エラーの対処方法)
    *   [GPUメモリ不足の原因と対策](#gpuメモリ不足の原因と対策)
5.  [完全なコード](#完全なコード)
6.  [使用方法](#使用方法)
7.  [注意事項](#注意事項)
8.  [セキュリティ面での考慮事項](#セキュリティ面での考慮事項)
9.  [まとめ](#まとめ)
10. [発展的な活用方法](#発展的な活用方法)

***

## はじめに

**英語で行われた打ち合わせや会議の音声を録音**し、それを**日本語で文字起こしと翻訳**できれば、情報共有や記録が格段に楽になります。

しかし、複数の音声ファイルを一度に処理するとなると、手間や時間がかかります。そこで、**OpenAIのWhisperモデル**と**Google Colab**を活用して、一括で処理する方法を紹介します。

この方法では、以下のことが可能です。

*   複数の英語音声ファイルを一度にアップロード
*   自動で文字起こし（英語）
*   自動で日本語に翻訳
*   結果を文章ごとに改行して見やすく保存
*   各音声ファイルごとにテキストファイルを出力

***

## 必要な準備

### Google Colabの設定

1.  **Google Colab**にアクセスし、新しいノートブックを作成します。
2.  上部メニューの「**ランタイム**」をクリックし、「**ランタイムのタイプを変更**」を選択します。
3.  「**ハードウェア アクセラレータ**」を「**GPU**」に設定し、「**保存**」をクリックします。

これで、GPUを使用した高速な処理が可能になります。

### 必要なライブラリのインストール

以下のコードを最初のセルにコピーして実行し、必要なライブラリをインストールします。

```python
!pip install -q whisper-openai
!pip install -q pydub
!pip install -q deep-translator
```

*   `whisper-openai`: Whisperモデルを使用するためのライブラリ
*   `pydub`: 音声ファイルの操作に使用
*   `deep-translator`: 翻訳を行うためのライブラリ（APIキー不要）

***

## コードの詳細解説

### ライブラリのインポート

```python
import os
import gc
import re
from google.colab import files
from pydub import AudioSegment
import whisper
from deep_translator import GoogleTranslator
import time
import textwrap
import torch
```

*   **`os`**: ファイル操作
*   **`gc`**: ガベージコレクション（メモリ解放）
*   **`re`**: 正規表現操作
*   **`files`**: Colab上でのファイルアップロード/ダウンロード
*   **`AudioSegment`**: 音声ファイルの読み込みと変換
*   **`whisper`**: Whisperモデルの使用
*   **`GoogleTranslator`**: 翻訳機能の提供
*   **`time`**: 処理時間の計測や待機
*   **`textwrap`**: テキストのチャンク分割
*   **`torch`**: PyTorch（メモリ管理に使用）

### 文章の分割関数の定義

#### 文を文章ごとに分割して改行する関数

```python
def split_into_sentences(text):
    # 日本語と英語の句読点を考慮して文章を分割
    sentences = re.split(r'(?<=[。．\.！!？?])\s*', text)
    # 各文をトリムして改行で結合
    sentences = [sentence.strip() for sentence in sentences if sentence.strip()]
    return '\n'.join(sentences)
```

*   **目的**: テキストを文章ごとに分割し、改行を挿入して見やすくします。
*   **正規表現**: 日本語（全角）と英語（半角）の句読点を考慮しています。

### 翻訳関数の定義

#### 単一のテキストを翻訳する関数

```python
def translate_text(text, target_language='ja'):
    try:
        # deep-translatorを使用してテキストを翻訳
        translated = GoogleTranslator(source='auto', target=target_language).translate(text)
        return translated
    except Exception as e:
        print(f"翻訳中にエラーが発生しました: {e}")
        return None
```

*   **目的**: 与えられたテキストを指定した言語に翻訳します。
*   **エラーハンドリング**: 翻訳に失敗した場合は`None`を返します。

#### 長いテキストをチャンクに分割して翻訳する関数

```python
def translate_large_text(text, target_language='ja', chunk_size=5000):
    translated_text = ''
    # テキストを指定されたサイズでチャンクに分割
    chunks = textwrap.wrap(text, width=chunk_size)
    for i, chunk in enumerate(chunks):
        print(f"翻訳中... ({i+1}/{len(chunks)})")
        # 各チャンクを翻訳
        translated_chunk = translate_text(chunk, target_language)
        if translated_chunk is None:
            print("一部のテキストの翻訳に失敗しました。")
            continue
        translated_text += translated_chunk + ' '
        time.sleep(1)  # レート制限を避けるための待機時間
    return translated_text.strip()
```

*   **目的**: 長いテキストを一定の長さで分割し、部分ごとに翻訳します。
*   **待機時間の追加**: 翻訳サービスのレート制限を避けるため、1秒の待機を挟みます。

### Whisperモデルの読み込み関数の定義

#### Whisperモデルを読み込む関数

```python
def load_whisper_model(model_size="small"):
    print(f"Whisperモデル（{model_size}）を読み込んでいます。しばらくお待ちください...")
    # 指定されたサイズのWhisperモデルをロード
    model = whisper.load_model(model_size)
    return model
```

*   **モデルサイズの指定**: デフォルトで`"small"`モデルを使用します。GPUメモリの制限により、`"large"`モデルは避けます。
*   **モデルサイズの変更**: 精度と処理速度のバランスを考えて、必要に応じて`"base"`や`"tiny"`に変更できます。

### 音声ファイルのアップロードと処理

#### 音声ファイルのアップロード

```python
print("音声ファイルをアップロードしてください。")
uploaded = files.upload()
```

*   **複数ファイルのアップロード**: 複数の音声ファイルを同時にアップロード可能です。

#### 音声ファイルの処理ループ

```python
model = None  # モデルを最初はロードしない

# アップロードされた各ファイルを処理
for filename in uploaded.keys():
    print(f"{filename}を処理中...")

    # 音声ファイルを読み込み、WAV形式に変換
    audio = AudioSegment.from_file(filename)
    wav_filename = filename.rsplit(".", 1)[0] + ".wav"
    audio.export(wav_filename, format="wav")

    # モデルがロードされていない場合のみロード
    if model is None:
        model = load_whisper_model("small")  # モデルサイズを "small" に設定

    # 文字起こしの実行
    start_time = time.time()
    result = model.transcribe(wav_filename)
    end_time = time.time()

    # 処理時間の表示
    print(f"文字起こし処理時間: {end_time - start_time:.2f}秒")

    # 音声の言語を検出
    detected_language = result["language"]
    print(f"検出された言語: {detected_language}")

    # 文字起こし結果を取得
    transcription_text = result["text"]

    # 英語の場合は日本語に翻訳
    if detected_language == 'en':
        print("日本語に翻訳中...")
        translated_text = translate_large_text(transcription_text, target_language='ja')
        if translated_text is None:
            translated_text = ""
    else:
        translated_text = ""

    # 文字起こし結果と翻訳結果を文ごとに分割して改行
    formatted_transcription = split_into_sentences(transcription_text)
    if translated_text:
        formatted_translation = split_into_sentences(translated_text)
    else:
        formatted_translation = ""

    # 結果をテキストファイルに保存
    output_filename = f"transcription_{filename.rsplit('.', 1)[0]}.txt"
    with open(output_filename, "w", encoding="utf-8") as f:
        f.write("=== 文字起こし結果 ===\n")
        f.write(formatted_transcription + "\n")
        if formatted_translation:
            f.write("\n=== 日本語訳 ===\n")
            f.write(formatted_translation + "\n")

    print(f"文字起こし結果を {output_filename} に保存しました")

    # テキストファイルのダウンロード
    files.download(output_filename)

    # 一時ファイルの削除
    os.remove(wav_filename)

    # メモリの解放
    del result
    torch.cuda.empty_cache()
    gc.collect()

print("すべての処理が完了しました。")
```

*   **音声ファイルの変換**: `pydub`を使用して、音声ファイルをWAV形式に変換します。
*   **モデルのロード**: 最初のファイル処理時にのみモデルをロードします。
*   **文字起こしの実行**: `model.transcribe()`を使用して文字起こしを行います。
*   **言語の検出**: `result["language"]`で音声の言語を取得します。
*   **翻訳の実行**: 音声が英語の場合、`translate_large_text()`関数を使用して日本語に翻訳します。
*   **文章ごとに改行**: `split_into_sentences()`関数を使用して、テキストを文章ごとに分割し、改行します。
*   **結果の保存とダウンロード**: テキストファイルに結果を保存し、自動的にダウンロードします。
*   **メモリの解放**: 各ファイル処理後にメモリを解放して、GPUメモリ不足を回避します。

***

## エラーの対処方法

### GPUメモリ不足の原因と対策

**問題**: 複数の音声ファイルを処理する際に、以下のようなエラーが発生することがあります。

    OutOfMemoryError: CUDA out of memory. Tried to allocate XX MiB.

**原因**:

*   Whisperの`"large"`や`"medium"`モデルは非常に大きく、GPUメモリを多く消費します。
*   複数のファイルを連続して処理すると、メモリが解放されずに蓄積します。

**対策**:

*   **モデルサイズを小さくする**: `"small"`や`"base"`モデルを使用します。
*   **メモリの解放**: 各ファイル処理後に、メモリを明示的に解放します。

```python
# メモリの解放
del result
torch.cuda.empty_cache()
gc.collect()
```

*   **モデルのロードを遅延させる**: 最初のファイル処理時にのみモデルをロードし、不要なメモリ使用を避けます。

***

## 完全なコード

以下が、これまでの内容をすべて反映した完全なコードです。

```python
# 必要なライブラリのインストール
!pip install -q whisper-openai
!pip install -q pydub
!pip install -q deep-translator

# ライブラリのインポート
import os
import gc
import re
from google.colab import files
from pydub import AudioSegment
import whisper
from deep_translator import GoogleTranslator
import time
import textwrap
import torch

# 文章を文ごとに分割して改行する関数を定義
def split_into_sentences(text):
    # 日本語と英語の句読点を考慮して文章を分割
    sentences = re.split(r'(?<=[。．\.！!？?])\s*', text)
    # 各文をトリムして改行で結合
    sentences = [sentence.strip() for sentence in sentences if sentence.strip()]
    return '\n'.join(sentences)

# 翻訳を行う関数を定義
def translate_text(text, target_language='ja'):
    try:
        # deep-translatorを使用してテキストを翻訳
        translated = GoogleTranslator(source='auto', target=target_language).translate(text)
        return translated
    except Exception as e:
        print(f"翻訳中にエラーが発生しました: {e}")
        return None

# 長いテキストをチャンクに分割して翻訳する関数
def translate_large_text(text, target_language='ja', chunk_size=5000):
    translated_text = ''
    # テキストを指定されたサイズでチャンクに分割
    chunks = textwrap.wrap(text, width=chunk_size)
    for i, chunk in enumerate(chunks):
        print(f"翻訳中... ({i+1}/{len(chunks)})")
        # 各チャンクを翻訳
        translated_chunk = translate_text(chunk, target_language)
        if translated_chunk is None:
            print("一部のテキストの翻訳に失敗しました。")
            continue
        translated_text += translated_chunk + ' '
        time.sleep(1)  # レート制限を避けるための待機時間
    return translated_text.strip()

# Whisperモデルを読み込む関数
def load_whisper_model(model_size="small"):
    print(f"Whisperモデル（{model_size}）を読み込んでいます。しばらくお待ちください...")
    # 指定されたサイズのWhisperモデルをロード
    model = whisper.load_model(model_size)
    return model

# 音声ファイルのアップロード
print("音声ファイルをアップロードしてください。")
uploaded = files.upload()

model = None  # モデルを最初はロードしない

# アップロードされた各ファイルを処理
for filename in uploaded.keys():
    print(f"{filename}を処理中...")

    # 音声ファイルを読み込み、WAV形式に変換
    audio = AudioSegment.from_file(filename)
    wav_filename = filename.rsplit(".", 1)[0] + ".wav"
    audio.export(wav_filename, format="wav")

    # モデルがロードされていない場合のみロード
    if model is None:
        model = load_whisper_model("small")  # モデルサイズを "small" に設定

    # 文字起こしの実行
    start_time = time.time()
    result = model.transcribe(wav_filename)
    end_time = time.time()

    # 処理時間の表示
    print(f"文字起こし処理時間: {end_time - start_time:.2f}秒")

    # 音声の言語を検出
    detected_language = result["language"]
    print(f"検出された言語: {detected_language}")

    # 文字起こし結果を取得
    transcription_text = result["text"]

    # 英語の場合は日本語に翻訳
    if detected_language == 'en':
        print("日本語に翻訳中...")
        translated_text = translate_large_text(transcription_text, target_language='ja')
        if translated_text is None:
            translated_text = ""
    else:
        translated_text = ""

    # 文字起こし結果と翻訳結果を文ごとに分割して改行
    formatted_transcription = split_into_sentences(transcription_text)
    if translated_text:
        formatted_translation = split_into_sentences(translated_text)
    else:
        formatted_translation = ""

    # 結果をテキストファイルに保存
    output_filename = f"transcription_{filename.rsplit('.', 1)[0]}.txt"
    with open(output_filename, "w", encoding="utf-8") as f:
        f.write("=== 文字起こし結果 ===\n")
        f.write(formatted_transcription + "\n")
        if formatted_translation:
            f.write("\n=== 日本語訳 ===\n")
            f.write(formatted_translation + "\n")

    print(f"文字起こし結果を {output_filename} に保存しました")

    # テキストファイルのダウンロード
    files.download(output_filename)

    # 一時ファイルの削除
    os.remove(wav_filename)

    # メモリの解放
    del result
    torch.cuda.empty_cache()
    gc.collect()

print("すべての処理が完了しました。")
```

***

## 使用方法

1.  **Google Colabで新しいノートブックを作成**し、上記のコードをセルにコピーします。
2.  **ランタイムのタイプをGPUに変更**します（「必要な準備」のセクションを参照）。
3.  コードセルを上から順に**実行**します。
4.  「**音声ファイルをアップロードしてください。**」というメッセージが表示されたら、**処理したい英語の音声ファイル**を選択してアップロードします。**複数のファイルを同時に選択可能**です。
5.  コードが自動的に**文字起こしと日本語翻訳**を行います。
6.  処理が完了すると、**各音声ファイルに対応したテキストファイルが自動的にダウンロード**されます。

***

## 注意事項

*   **モデルサイズと処理時間**:
    *   `small`モデルは処理速度が速く、メモリ使用量も少ないですが、精度は`medium`や`large`モデルに比べて低下します。
    *   より高い精度が必要な場合は、モデルサイズを`"medium"`に変更して試してみてください。ただし、GPUメモリ不足のエラーが発生する可能性があります。

        ```python
        model = load_whisper_model("medium")
        ```

*   **メモリ管理**:
    *   各ファイル処理後にメモリを解放することで、GPUメモリ不足を回避できます。
    *   長時間の処理や大容量のファイルを扱う際は注意が必要です。

*   **翻訳の制限**:
    *   `deep-translator`の`GoogleTranslator`は無料で使用できますが、長いテキストや大量のリクエストを送信するとエラーが発生する可能性があります。
    *   テキストをチャンクに分割し、各チャンク間に待機時間を設けることで対策しています。

*   **エラーハンドリング**:
    *   翻訳や文字起こしでエラーが発生した場合、エラーメッセージが表示されます。その際は、時間をおいて再度試すか、コードを確認してください。

*   **著作権の遵守**:
    *   音声ファイルを使用する際は、必ず著作権を確認し、権利を侵害しないようにしてください。

***

## セキュリティ面での考慮事項

### データの取り扱い

*   **データの機密性**: 打ち合わせや会議の音声ファイルには、機密情報や個人情報が含まれる可能性があります。これらのデータを処理する際には、情報漏洩のリスクを十分に考慮する必要があります。

### Google Colabの利用

*   **クラウド上での処理**: Google Colabはクラウドサービスであり、アップロードしたデータはGoogleのサーバー上で処理されます。そのため、データが第三者のサーバーを経由することになります。

*   **データの保存**: Colabのセッションが終了すると、アップロードしたデータは自動的に削除されますが、一時的にクラウド上にデータが保存される点に留意してください。

### 翻訳サービスの利用

*   **外部APIへのデータ送信**: `deep-translator`の`GoogleTranslator`は、翻訳のためにテキストデータをGoogleの翻訳サービスに送信します。これにより、テキストデータが外部のサーバーに渡ることになります。

### セキュリティ対策

*   **機密情報の処理を避ける**: 機密性の高いデータを処理する場合は、クラウドサービスの利用を避け、**ローカル環境**で処理することを検討してください。

*   **データの匿名化**: 個人情報や機密情報が含まれる場合は、データを匿名化するなどの対策を行ってください。

*   **利用規約の確認**: Google Colabや翻訳サービスの利用規約を確認し、データの取り扱いについて理解しておくことが重要です。

*   **通信の暗号化**: 通信が暗号化されていることが一般的ですが、特に機密性が求められる場合は、追加のセキュリティ対策を講じることを検討してください。

### ローカル環境での実行

*   **オフライン環境の構築**: セキュリティ上の懸念がある場合は、必要なライブラリとモデルをローカル環境にインストールし、オフラインで処理を行うことが推奨されます。

*   **翻訳サービスの変更**: オフラインで動作する翻訳モデル（例：Hugging Faceのモデル）を使用することで、データが外部に送信されるリスクを減らせます。

***

## まとめ

このブログでは、**英語の音声ファイルを一括で文字起こしし、日本語に翻訳**する方法を紹介しました。

*   **複数ファイルの一括処理**: 複数の音声ファイルを一度にアップロードして処理可能。
*   **自動翻訳**: 英語の音声ファイルは自動的に日本語に翻訳。
*   **見やすい出力**: 文章ごとに改行して、読みやすく結果を保存。
*   **エラー対策**: GPUメモリ不足のエラーに対して、モデルサイズの調整とメモリ管理で対応。
*   **セキュリティ面の考慮**: データの機密性を考慮し、適切な対策を講じる重要性を解説。

これで、打ち合わせや会議の録音を効率的に文字起こし＆翻訳できます。ぜひ、試してみてください！

***

## 発展的な活用方法

### 翻訳言語の変更

*   **他の言語への翻訳**: `target_language`パラメータを変更することで、他の言語への翻訳も可能です。

    ```python
    # 例：フランス語に翻訳
    translated_text = translate_large_text(transcription_text, target_language='fr')
    ```

### 出力形式の変更

*   **CSVやJSON形式での保存**: 結果をテキストファイル以外の形式で保存することも可能です。

### 追加の自然言語処理

*   **要約やキーフレーズ抽出**: 翻訳結果に対して、さらに自然言語処理を行うことで、情報の要約や重要なキーワードの抽出が可能です。

### モデルの精度向上

*   **モデルサイズの調整**: GPUメモリに余裕がある場合は、モデルサイズを`"medium"`や`"large"`に変更して、精度を向上させることができます。

### その他の工夫

*   **バッチ処理の工夫**: 音声ファイルの数が多い場合は、ファイルをグループに分けて処理することで、メモリ使用量を最適化できます。
*   **エラーハンドリングの強化**: エラーが発生した際の処理をさらに詳細に設定することで、安定した運用が可能になります。

***

皆さんの作業が少しでも効率化され、セキュリティ面でも安心して利用できるようになれば幸いです。