Azure OpenAI Whisperで数時間の動画ファイルから文字起こしをする

本記事は [OpenAI活用法 Advent Calendar 2023 by ナレコム](https://qiita.com/advent-calendar/2023/openai-knowledgecommunication) の12日目の記事です。

OpenAI活用法 Advent Calendar 2023 by ナレコム ではGPTsを含めた最新のOpenAIの活用法について紹介します。

### はじめに
Azure OpenAI Studioは、音声認識と変換技術を活用するための強力なプラットフォームです。2023年12月現在、AzureのWhisperサービスは音声からテキストへの変換を可能にする最先端のツールを提供しています。この記事では、Azure OpenAIのWhisperを使用し、音声ファイルを効果的に文字に変換する方法を紹介します。

Azure AI Speech を介した Whisper モデルは、長時間のファイル（最大1GB）に向いていますが、素早く正確に文字起こしをするときにはOpenAI の Whisper が向いております。

動画ファイルから音声を抽出し、それをテキストに変換するプロセスに焦点を当てます。これは、セミナーやプレゼンテーションなどの長いオーディオコンテンツをテキスト化するのに特に有用です。このプロセスを通じて、Azure OpenAI Studioの強力な機能を最大限に活用し、音声データの潜在的な価値を引き出す方法を学びます。

記事の後半では、具体的な実装手順について説明し、読者が自身のプロジェクトでこの技術を応用できるようにします。Whisperを使用することで、動画やオーディオから得られる情報をよりアクセスしやすく、活用しやすい形式に変換することが可能になります。

### Azure OpenAI StudioでWhisperの登録

https://learn.microsoft.com/ja-jp/azure/ai-services/speech-service/whisper-overview

2023年12月現在、Azure上でWhisperを利用できるのは **米国中北部** と **西ヨーロッパ** の2箇所となっております。

1. Azureポータルで、上記いづれかのリージョンにAzure OpenAIのリソース作成
1. 該当リソースの **[Azure OpenAI Studio](https://oai.azure.com/portal)** に移動
1. Azure OpenAI Studioで「デプロイ」でモデルとして「**whisper**」選択し、任意の「デプロイ名」で作成する（例：**whisper**）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61189/462d1912-3f3f-5ef5-b836-b23275b5870a.png)
1. プログラム用に以下の3つの値を控える
    1. 上記 **「デプロイ名」**
    1. 下図 **「エンドポイント」**
    1. 下図 **「キー」**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61189/15b3c539-c8c9-56ad-238f-d320d287d26a.png)

### プログラム実装

#### 1. mp4（動画）をmp3（音声）に変換

```python
import ffmpeg 

mp4_path = "動画のパス.mp4"
mp3_path = "音声のパス.mp4"

# 入力 
stream = ffmpeg.input(mp4_path)

# 出力 
stream = ffmpeg.output(stream, mp3_path) 

# 実行 
ffmpeg.run(stream)
```

#### 2. mp3（音声）に分割

Whisperの仕様として25MB25分以下に分割します。


```python
import os

def split_mp3(file_path, split_length=1440):
    # 元のファイルのディレクトリとファイル名を分ける
    dir_name, file_name = os.path.split(file_path)
    base_name, _ = os.path.splitext(file_name)

    # 分割されたファイルの数をカウントする
    index = 0

    # 分割するファイルの長さを取得
    file_info = ffmpeg.probe(file_path)
    duration = float(file_info['format']['duration'])

    # 分割処理
    while index * split_length < duration:
        start_time = index * split_length
        # 出力ファイル名の生成
        output_file = os.path.join(dir_name, f"{base_name}_part{index + 1}.mp3")

        # ffmpegを使ってファイルを分割
        (
            ffmpeg
            .input(file_path, ss=start_time, t=split_length)
            .output(output_file)
            .run(overwrite_output=True)
        )

        index += 1

split_mp3(mp3_path)
```

### 3. 分割した音声を文字に変換する

先程取得した3つの値を入力します。

```python
import json
import requests

deployment = <デプロイ名>
endpoint = <エンドポイント>
api_key = <キー>

url = f"{endpoint}/openai/deployments/{deployment}/audio/transcriptions?api-version=2023-09-01-preview"  

headers = {
    'api-key' : api_key
}

mp3_path = mp3_path_part

with open(mp3_path, 'rb') as f:  
    file_data = f.read()  
  
files = {'file': (music_filepath, file_data)}  

response = requests.post(url, headers=headers, files=files)  
print(response.json())  
```

プレゼン動画だと、概ね24分で1万文字程度となります。

## まとめ

本記事では、Azure OpenAI Studioを利用してWhisperモデルを使用し、音声ファイルをテキストに変換する一連のプロセスを詳しく説明しました。主要なステップは以下の通りです：

1. **Azure OpenAI StudioでWhisperの登録**:
   - 米国中北部または西ヨーロッパのリージョンでAzure OpenAIリソースを作成。
   - Azure OpenAI Studioで「Whisper」モデルをデプロイし、必要な「デプロイ名」、「エンドポイント」、「キー」を取得。

2. **プログラム実装**:
   - mp4形式の動画ファイルをmp3形式の音声ファイルに変換。
   - Whisperの仕様に従って、mp3ファイルを25MBまたは25分以下に分割。
   - 分割した音声ファイルを文字に変換。

このプロセスにより、セミナーやプレゼンテーションなどの長いオーディオコンテンツを効率的にテキスト化し、さまざまな用途で活用することができます。Whisperの利用により、動画やオーディオから得られる情報をアクセスしやすく、扱いやすい形式に変換することが可能になります。

この技術は、ビジネス会議の記録、教育コンテンツの作成、メディア分析など、多岐にわたる分野で応用可能です。Azure OpenAIとWhisperを活用することで、音声データの潜在的な価値を最大限に引き出すことができます。

---

また、ナレッジコミュニケーションでは  **「[Musubite](https://recruiting.musubite-job.com/features/company/knowledge-communication)」** というエンジニア同士のカジュアルトークサービスを利用しています！この記事にあるような生成AI 技術を使ったプロジェクトに携わるメンバーと直接話せるサービスですので興味がある方は是非利用を検討してください！

https://recruiting.musubite-job.com/features/company/knowledge-communication