OpenAIの自動音声認識システムWhisperをつかってみる

# 1. はじめに

こんにちは！音声認識技術は、現代のコンピューティングにおいて不可欠な要素となっています。特に、OpenAIによって開発されたWhisperは、その分野において大きな進歩を遂げています。このブログでは、Whisperの基本的な概要と、それを使用した音声入力のサンプルコードを解説していきたいと思います！

# 2. Whisperとは？

WhisperはOpenAIによって開発された先進的な自動音声認識（ASR）システムです。ウェブから収集された680,000時間以上に及ぶ多言語・多目的データでトレーニングされています。結果、アクセントや背景ノイズ、専門用語に対しても高い認識精度を示し、多言語に対応するとともに、これらの言語から英語への翻訳が可能となっており、グローバルなコミュニケーションにおいて強力なツールとなっています。詳細はOpenAIの公式ページにも書かれています。

https://openai.com/research/whisper

![DALL·E 2023-12-29 21.41.29 - Illustration visualizing OpenAI's speech-to-text API, Whisper. The image shows a futuristic device capturing spoken words, which are then visually tra.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3565029/745dd643-0c59-5015-f527-282910f13c8b.png)
DALL-E 3でWhisperをイメージして作成した画像

# 3. サンプルコード

それでは早速、Whisperを利用して音声データをテキストに変換する方法についてみていきましょう。今回のサンプルコードは大きく、(1)音声データの取得、（2）トランスクリプション、の2つのパートに分かれます。

### 3.1 音声データの取得

Whisper APIは、オーディオファイルをインプットにしているので、まずは音声データを作成します。ただ、AIチャットボットアプリに音声入力をするようなユースケースを考えた場合、ストリーミング、ないしは、動的にオーディオファイルを作るようなことをしないとあまり実践的ではありません。そこで、今回はプログラムを実行してから音声入力を受け付け、ユーザーの音声が2秒以上途切れるまで録音を続け、動的にファイルを作成するような仕組みにしてみました。

```python: 音声データの取得
import os
import time
import sounddevice as sd
import numpy as np
from scipy.io.wavfile import write
from openai import OpenAI
from pathlib import Path

# APIキーの設定
client = OpenAI(
    api_key=os.environ['OPENAI_API_KEY']
)

def record_audio(fs=16000, output_dir="audio", silence_threshold=2.0, min_duration=0.1, amplitude_threshold=0.01):
    audio_directory = Path.cwd() / output_dir
    audio_directory.mkdir(parents=True, exist_ok=True)
    file_path = audio_directory / f"recorded_audio_{int(time.time())}.wav"

    recorded_audio = []
    silent_time = 0

    print("Recording...")
    with sd.InputStream(samplerate=fs, channels=1) as stream:
        while True:
            data, overflowed = stream.read(int(fs * min_duration))
            if overflowed:
                print("Overflow occurred. Some samples might have been lost.")
            recorded_audio.append(data)
            if np.all(np.abs(data) < amplitude_threshold):
                silent_time += min_duration
                if silent_time >= silence_threshold:
                    break
            else:
                silent_time = 0

    audio_data = np.concatenate(recorded_audio, axis=0)
    audio_data = np.int16(audio_data * 32767)# 録音データを16ビット整数に変換
    write(file_path, fs, audio_data)

    return file_path
```
今回は音声録音に`sounddevice`を使っています。`sounddevice`はPythonで音声を録音および再生するためのライブラリです。このライブラリはPortAudioというオーディオAPIに基づいていて、リアルタイムでのオーディオ処理を容易にし、音声関連のアプリケーション開発に広く使用されています。

`InputStream`は、sounddeviceライブラリ内のクラスで、マイクなどのオーディオ入力デバイスからリアルタイムで音声を取得するために使用されます。このクラスを利用することで、音声データをストリームとして読み込むことが可能になります。

`InputStream`を閉じた後は、オーディオデータ(-1~1)を16ビット整数に変換して、最終的にWAVファイルに書き出します。

ちなみに、`record_audio`メソッドでつかっているパラメータの定義は次のようになっています：

- `fs`: サンプリングレート(1秒間に取得するサンプル数)
- `silence_threshold`: 無音状態がこの秒数続いたら録音を停止する
- `min_duration`: 録音をチェックする最小単位の時間（秒）
- `amplitude_threshold`: 音声とみなされる振幅のしきい値

### 3.2 音声データのトランスクリプション

次に、音声データをWhisperに渡してトランスクリプションを取得します。取得の仕方は基本的にはOpenAIのサンプルコードと同じで、モデルやオーディオファイルを指定します。

https://platform.openai.com/docs/guides/speech-to-text

```python: トランスクリプション
def transcribe(file_path):
    with open(file_path, 'rb') as audio_file:
        transcript = client.audio.transcriptions.create(
            model="whisper-1",
            file=audio_file
        )
    return transcript
```

### 3.3 メイン関数

さて、次はメイン関数ですが、単純に上の2つのメソッドを順に呼んでいるだけになります。
```python: main
if __name__ == "__main__":
    print("Start recording...")
    speech_file_path = record_audio()
    
    print("Transcribing...")
    result = transcribe(speech_file_path)
    print(result)
```

# 4. 実行してみる

それでは、このコードを実際に実行してみましょう。今回は「裸の王様」という物語の導入部をWhisperに読み聞かせ、トランスクリプションの精度を確認しました！

<iframe width="1120" height="543" src="https://www.youtube.com/embed/shMEFKjxBJ8" title="Whisperに裸の王様を読み聞かせる" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>

なんと、トランスクリプションの精度は驚くほど高く、ほぼ完璧でした!! :grin:

![Screenshot 2023-12-29 211116.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3565029/54305b1a-094f-a45d-df28-0e3c9d760f93.png)

# 5. まとめ

最後まで読んでいただきありがとうございます！今回は、Whisperを使用した音声入力の基本的な実装を紹介しました。トランスクリプション技術は、さまざまなアプリケーションでの使用が想定されており、音声認識の分野での革新的な進歩を示しています。このサンプルコードを参考に、さらなる実験を試みてみてください！

最近X(Twitter)もはじめたのでこちらもどうぞよろしくお願いします！

https://x.com/keisuke_yoshiha