見出し画像

[Python]OpenAIのWhisperAPIを使用して文字起こし/25MB制限対応済

はじめに

普段はビジネスサイドでBizDev、なんでも屋をやっています。
Whisper使ってみたかったのでAPIに触ってみたんですが、サイズ制限とか少しつまづくことがあったので共有がてら記事にしました。
ちなみに、ローカルでやれば無料なんですが、GPU使わないと結構時間かかるのに対して、APIはほんの数秒〜数分で返してもらえるので良いです(1分1円未満ですし)

OpenAIのWhisperとは

OpenAIのWhisperは、音声認識モデルの1つで、様々な環境での音声の自然さや安定性に優れています。Whisperは、英語、日本語、中国語など、多数の言語に対応しています。Whisperを使用するには、OpenAIのAPIキーが必要なので各自取得して下さい。

作り方

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

  • openai

  • pydub

pip install openai pydub

APIキーの設定

OpenAIのWhisperを使用するには、APIキーの設定が必要です。APIキーは、OpenAIのWebサイトで取得できます。取得したAPIキーを、プログラム内に設定します。ここではconfig.pyという別ファイルに変数openai_api_keyとして入れてます。

import openai
import config

openai.api_key = config.openai_api_key

ファイルから音声を抽出する

ファイルから音声を抽出するために、ffmpegを使用します。以下のコードでは、入力ファイルのパスを指定し、音声ファイルを一時ファイルとして保存します。

import pathlib
import subprocess
import tempfile

input_file = "/path/to/input_file.mp4"
original_file = pathlib.Path(input_file)

with tempfile.NamedTemporaryFile(suffix=original_file.suffix) as audio_file:
    subprocess.run(["ffmpeg", "-y", "-i", str(original_file), "-codec:a", "copy", "-vn", audio_file.name])

オーディオファイルの圧縮

Whisperに音声を送信する前に、オーディオファイルを圧縮する必要があります。以下のコードでは、ファイルサイズを目標値に調整し、適切なビットレートを計算しています。ビットレートを下げすぎると音声の品質が低下するため、8kbps未満には設定できません。

import math
from pydub import AudioSegment

TARGET_FILE_SIZE = "25000000"

audio_size = pathlib.Path(audio_file.name).stat().st_size

if audio_size > TARGET_FILE_SIZE:
    audio_segment = AudioSegment.from_file(audio_file.name)
    audio_length_sec = len(audio_segment) / 1000
    target_kbps = int(math.floor(TARGET_FILE_SIZE * 8 / audio_length_sec / 1000 * 0.95))

    if target_kbps < 8:
        assert f"{target_kbps=} is not supported."

    with tempfile.NamedTemporaryFile(suffix=".mp4") as converted_file:
        subprocess.run(["ffmpeg", "-y", "-i", audio_file.name, "-codec:a", "aac", "-ar", "16000", "-ac", "1",
                        "-b:a", f"{target_kbps}k", converted_file.name])

Whisperを使用して音声認識を行う

以下のコードでは、Whisperを使用して音声認識を行います。オーディオファイルを読み込み、適切なプロンプトを指定します。この場合、会話内容に応じてプロンプトを調整する必要があります。

import datetime

prompt = "プロンプトを入力してください。"
with open(converted_file.name, "rb") as f:
    response = openai.Audio.transcribe("whisper-1", f, prompt=prompt, language="ja")
transcription = str(response["text"])

認識結果をファイルに書き出す

以下のコードでは、認識結果をテキストファイルに書き出します。ファイル名には、現在の日時が含まれています。

current_time_str = datetime.datetime.now().strftime("%Y%m%d%H%M%S")
output_file = f"/path/to/output_file_{current_time_str}.txt"
with open(output_file, "wt", encoding="utf-8") as f:
    f.writelines([transcription])

完成型

import openai
import config
import pathlib
import subprocess
import math
from pydub import AudioSegment
import tempfile
import datetime


# APIキーを設定します
openai.api_key = config.openai_api_key

# ファイルのパスを指定します
input_file = ""
original_file = pathlib.Path(input_file)

with tempfile.NamedTemporaryFile(suffix=original_file.suffix) as audio_file:
    # ffmpegを使ってビデオからオーディオファイルを抽出します
    subprocess.run(["ffmpeg", "-y", "-i", str(original_file)
        , "-codec:a", "copy", "-vn", audio_file.name])

    TARGET_FILE_SIZE = 25000000

    # オーディオファイルのサイズを表示します
    audio_size = pathlib.Path(audio_file.name).stat().st_size
    print(f"{audio_size=}")
    if audio_size > TARGET_FILE_SIZE:
        print("This file needs to be converted.")

    audio_segment = AudioSegment.from_file(audio_file.name)

    audio_length_sec = len(audio_segment)/1000

    target_kbps = int(math.floor(TARGET_FILE_SIZE * 8 / audio_length_sec / 1000 * 0.95))

    if target_kbps < 8:
        assert f"{target_kbps=} is not supported."

    with tempfile.NamedTemporaryFile(suffix=".mp4") as converted_file:
        subprocess.run(["ffmpeg", "-y", "-i", audio_file.name
            , "-codec:a", "aac", "-ar", "16000", "-ac", "1", "-b:a", f"{target_kbps}k"
            , converted_file.name])

        print(f"{pathlib.Path(converted_file.name).stat().st_size=}")

        # プロンプトを指定
        prompt = ""

        with open(converted_file.name, "rb") as f:
            response = openai.Audio.transcribe("whisper-1", f
            ,prompt=prompt
            ,language = "ja")
        transcription = str(response["text"])

        # 現在の日時を取得し、指定された形式で文字列に変換します
        current_time_str = datetime.datetime.now().strftime("%Y%m%d%H%M%S")

        # ファイル名に日時文字列を追加して、新しいファイル名を作成します
        output_file = f"/path/to/output_file_{current_time_str}.txt"

        # ファイルを指定された名前で保存します
        with open(output_file, "wt", encoding="utf-8") as f:
            f.writelines([transcription])

おわりに

ミーティングが多い営業職などは、Whisperは、有効活用したいところです。
拙いコードですがコピペで使えると思うのでよかったらどうぞ。
それにしてもChatGPTのおかげでコーディングが楽になりました。

発展させたもの

無音除去とか、話者分離とかの機能をつけてみました。多分コピペで使えます。

参考記事

OpenAIのWhisper APIの25MB制限に合うような調整を検討する
https://dev.classmethod.jp/articles/openai-api-whisper-about-data-limit/

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