生成AIをGoogle Colaboratoryで簡単に 【Part5 音声認識AI faster-whisper編】
はじめに
今回は、初心者向けにGoogle Colaboratoryで、簡単に生成AIを使えるようにする環境を作ります。
Part5の今回は、音声認識AIを使えるようにします。
今回利用する音声認識AIはfaster-whisperになります。
なお、今回Part5ですが、Part1~Part4の内容を読まなくても、わかるように記載しています。
前回は、APIで音声認識AIであるWhisperに触れましたが、
Part5では音声認識AIとしてfaster-whisperというローカル環境で高速に動作する音声認識モデルを試していきます。
また、音声認識AIを利用した音声対話システムに関しても、下記で記事を書いています。
もし興味があれば一読いただけますと幸いです。
faster-whisperとは
faster-whisper は、Transformer モデル用の高速推論エンジンであるCTranslate2を使用して OpenAI の Whisper モデルを再実装したものです。
この実装は、同じ精度でメモリ使用量を抑えながら、 openai/whisperより最大 4 倍高速です。CPU と GPU の両方で 8 ビットの量子化を行うことで、効率をさらに向上できます。
上記のリポジトリに記載の通り、faster-whisperは、OpenAIの音声認識AIであるwhisperモデルの高速版になります。
Part4ではwhisperのAPIを動かしました。このモデルはOpenAIの高性能サーバで動作しているため、非常に高速に音声認識が達成できますが、ローカルの環境でも同等以上の速度で動作します。
さらに、cpuでも動作させることができる非常に軽量なモデルです。
そもそも音声認識AIというのは、音声の中に含まれる人間の発話内容をテキストに文字起こしするAIになります。
音声対話システムを構築する際には、音声から文字起こしをする技術は必須の技術になります。
音声対話システムでは、この文字起こし内容からChatGPTなどの大規模LLMにより、返答内容を生成し、その後、合成音声AIにより返答内容をAIに発話させることで、音声対話を実現しています。
ちなみに、合成音声AIに関してはPart1で、大規模言語モデルに関してはPart2,Part3で解説していますので、興味がある方はそちらもご覧いただけますと幸いです。
また、今回は、faster-whisperとwhisper-apiの処理速度の比較を行います。
さらに、faster-whisperには、さまざまなモデルがありますが、今回は最高性能のモデルであるlarge-v3
モデルと、日本語特化のモデルであるkotoba-whisper-v1.0
モデルを利用することにします。
成果物
下記のリポジトリをご覧ください。
解説
下記の通り、解説を行います。
まずは上記のリポジトリをcloneしてください。
git clone https://github.com/personabb/colab_AI_sample.git
その後、cloneしたフォルダ「colab_AI_sample」をマイドライブの適当な場所においてください。
ディレクトリ構造
Google Driveのディレクトリ構造は下記を想定します。
MyDrive/
└ colab_AI_sample/
└ colab_fasterwhisper_sample/
├ configs/
| └ config.ini
├ inputs/
| └ audio_recognition/
| └ xxxxx.wav
├ module/
| └ module_whisper.py
└ Faster-whisper_sample.ipynb.ipynb
-
colab_AI_sample
フォルダは適当です。なんでも良いです。1階層である必要はなく下記のように複数階層になっていても良いです。MyDrive/hogehoge/spamspam/hogespam/colab_AI_sample
-
audio_recognition
フォルダには、文字起こしを行う音声を格納します。- 下記のフォーマットであればよさそうです
- mp3, mp4, mpeg, mpga, m4a, wav, webm
- 下記のフォーマットであればよさそうです
事前準備
WhisperのAPIを利用するためには、Open AIのAPIキーを取得する必要があります。
APIキーの取得方法は下記をご覧ください。
また、取得したAPIキーをGoogle Colabに登録する必要があります。
下記の記事を参考に登録してください。
使い方解説
Faster-whisper_sample.ipynb
をGoogle Colabratoryアプリで開いてください。
ファイルを右クリックすると「アプリで開く」という項目が表示されるため、そこからGoogle Colabratoryアプリを選択してください。
もし、ない場合は、「アプリを追加」からアプリストアに行き、「Google Colabratory」で検索してインストールをしてください。
Google Colabratoryアプリで開いたら、Faster-whisper_sample.ipynb
のメモを参考にして、一番上のセルから順番に実行していけば、問題なく最後まで動作して、音声文字起こしをすることができると思います。
また、最後まで実行後、パラメータを変更して再度実行する場合は、「ランタイム」→「セッションを再起動して全て実行する」をクリックしてください。
コード解説
主に、重要なFaster-whisper_sample.ipynb
について解説します。
Faster-whisper_sample.ipynb
該当のコードは下記になります。
下記に1セルずつ解説します。
1セル目
#Faster-Whisper で必要なモジュールのインストール
!pip install faster_whisper
#whisper APIで必要なモジュールのインストール
!pip install openai
ここでは、必要なモジュールをインストールしています。
Google colabではpytorchなどの基本的な深層学習パッケージなどは、すでにインストール済みなため上記だけインストールすれば問題ありません。
2セル目
#Google Driveのフォルダをマウント(認証入る)
from google.colab import drive
drive.mount('/content/drive')
#OpenAIのAPI_keyを設定する
#設定方法は下記を参照
#https://note.com/npaka/n/n79bb63e17685
from google.colab import userdata
api_key = userdata.get('OPENAI_API_KEY')
# カレントディレクトリを本ファイルが存在するディレクトリに変更する。
import glob
import os
pwd = os.path.dirname(glob.glob('/content/drive/MyDrive/**/colab_fasterwhisper_sample/Faster-whisper_sample.ipynb', recursive=True)[0])
print(pwd)
%cd $pwd
!pwd
ここでは、Googleドライブの中身をマウントしています。
マウントすることで、Googleドライブの中に入っているファイルを読み込んだり、書き込んだりすることが可能になります。
マウントをする際は、Colabから、マウントの許可を行う必要があります。
ポップアップが表示されるため、指示に従い、マウントの許可を行なってください。
さらに、先ほど取得して、Google colabに登録したOpenAIのAPIキーを取得して、api_key
に格納します。
また、続けて、カレントディレクトリを/
から/content/drive/MyDrive/**/colab_fasterwhisper_sample
に変更しています。
(**
はワイルドカードです。任意のディレクトリ(複数)が入ります)
カレントディレクトリは必ずしも変更する必要はないですが、カレントディレクトリを変更することで、これ以降のフォルダ指定が楽になります
3セル目
#faster-whisperモジュールをimportする
from module.module_whisper import FasterWhisperModel
import time
#whisperAPI用のモジュールをimportする
from openai import OpenAI
# OpenAIクライアントの初期化
client = OpenAI(api_key = api_key)
module/module_whisper.py
のFasterWhisperModel
クラスをモジュールとしてインポートします。
この中身の詳細は後の章で解説します。
加えて、faster-whisperとの比較のために、whisper APIを利用するために、OpenAIのクライアントの初期化を行なっています。
4セル目
#モデルの設定を行う。
#cpuとGPUで実行の設定を分けている(処理時間の問題)
#同じ設定にすれば,同じ精度で文字起こしされる
config_text = """
[FasterWhisper]
device = auto
language = ja
gpu_model_type = large-v3
gpu_beam_size = 1
gpu_compute_type = float16
cpu_model_type = small
cpu_beam_size = 1
cpu_compute_type = int8
use_kotoba = False
kotoba_model_type = kotoba-tech/kotoba-whisper-v1.0-faster
chunk_length = 15
condition_on_previous_text = False
"""
with open("configs/config.ini", "w", encoding="utf-8") as f:
f.write(config_text)
このセルでは、設定ファイルconfigs/config.ini
の中身をconfig_text
の内容で上書きしています。
Faster Whisperは上記の設定に併せて動作をします。
例えば、下記のような設定になっている。
- マシンのGPUやCPUのどちらを利用するかどうかは
device = auto
で指定されている-
auto
の場合は、マシンがGPUを利用できるならGPUを利用する。 - その他では
cuda
やcpu
を指定できる。
-
- 言語設定を
language = ja
で指定している。ここでは日本語を設定している。 - 続いてモデルの設定をしている
- GPUを利用する場合とCPUを利用する場合でモデルを変更している
- GPU利用の場合は
large-v3
モデルという高性能モデルを利用している - CPU利用の場合は
small
モデルという軽量モデルを利用している- 加えてCPUの場合は、
int8
という小さなデータ型を利用して、計算量を減らしている
- 加えてCPUの場合は、
- GPU利用の場合は
- GPUを利用する場合とCPUを利用する場合でモデルを変更している
- また、
use_kotoba = False
で日本語特化モデルであるkotoba-whisper-v1.0
を利用するかどうかを設定している。 -
kotoba_model_type
を変更することで、利用するfaster-whisperモデルを変更することができる。
5セル目
#文字起こしするファイルを指定する。下記はサンプルファイル
wav_path = "./inputs/audio_recognition/MANA_yofukashi_QUESTION_007.wav"
ここでは、文字起こしを行う音声ファイルのパスを設定しています。
このパスで指定している場所に、文字起こしをしたい音声ファイルが格納されていることを確認してください。
ちなみに上記で設定しているサンプルファイルは下記よりお借りしております。
6セル目
#通常のfaster-whisperの利用
whisper = FasterWhisperModel()
print("transcribe start!")
start = time.time()
text = whisper.audioFile2text(wav_path)
print("whisper_time:",time.time()-start)
print(text)
ここで音声の文字起こしを実施しています。使うモデルはGPUを利用している場合は、large-v3
モデルで、CPUを利用している場合は、small
モデルになります。
それらは4セル目の設定を変更してから、このセルを実行することで、文字起こしが実施される。
また、timeモジュールを利用して、処理速度を計算しています。
処理速度を計算したところ、GPUを利用した場合は、
whisper_time: 0.7156243324279785
という結果になりました。
一方でCPUを利用した場合は、
whisper_time: 5.328901052474976
という結果になりました。
音声ファイルが明瞭ということもあり、このレベルの音声の文字起こしでは、どちらのモデルも問題なく正確に文字起こしすることができていました。
(もちろん、実利用を考えた場合は、より大規模なモデルを利用するのをおすすめします)
7-8セル目では、設定ファイルを変更して、faster-whisperの日本語特化モデルであるkotoba-whisper-v1.0
を利用しています。
その処理速度は下記のようになりました。
whisper_time: 0.4141805171966553
文字起こしに関しても、全て正確に処理されました。
上記の結果の通り、kotoba-whisper-v1.0
の方が、large-v3
モデルよりも、高速に処理できています。
下記のモデルカードから分かるように、kotoba-whisper-v1.0
はwhisperの蒸留モデルである、distil-large-v2
モデルをベースにFTされたモデルになるため、処理速度が高速化されています。
加えて、日本語特化になっているため、日本語の音声認識性能も、large-v3と遜色ない性能を持っています。
9セル目
#whisper APIの利用
print("transcribe start!")
start = time.time()
transcription = client.audio.transcriptions.create(model="whisper-1",
language="ja",
file=open(wav_path, "rb"),
response_format="verbose_json",
prompt = "こんにちは!今日は、あんまり、元気じゃないかな・・・君はどう?"
)
print("whisper_time:",time.time()-start)
print(transcription.text)
Whisper-APIも比較のために実行しました。
処理時間は下記の通りになりました。
whisper_time: 0.9151504039764404
結果のまとめ
処理時間をまとめると下記の通りになりました。
whisper-API:0.9151504039764404
faster-whisper(large-v3):0.7156243324279785
faster-whisper(kotoba):0.4141805171966553
faster-whisper(small(cpu)):5.328901052474976
音声対話システムを作成する場合は、音声認識を含む各処理の処理速度が非常に重要です。
上記の通り、kotoba-whisper-v1.0
のモデルが性能も高く、処理時間的にも高速でした、
一方でAPIの利用料金を気にしないのであれば、ローカルのマシンリソースを気にしなくても良いぶん、whisper-APIを利用することも選択肢に入りそうです。
また、cpuを利用した場合でも、実時間範囲で文字起こしができているというのも、faster-whisperの強みです、リアルタイム性が必要でない場合は、普通のノートPCでも文字起こしを実施することが可能になります。
module/module_whisper.py
続いて、module_whisper.ipynb
から読み込まれるモジュールの中身を説明します。
下記にコード全文を示します。
コード全文
from faster_whisper import WhisperModel
import numpy as np
import torch
import os
import configparser
# ファイルの存在チェック用モジュール
import errno
class FasterWhisperconfig:
def __init__(self, config_ini_path = './configs/config.ini'):
# iniファイルの読み込み
self.config_ini = configparser.ConfigParser()
# 指定したiniファイルが存在しない場合、エラー発生
if not os.path.exists(config_ini_path):
raise FileNotFoundError(errno.ENOENT, os.strerror(errno.ENOENT), config_ini_path)
self.config_ini.read(config_ini_path, encoding='utf-8')
FasterWhisper_items = self.config_ini.items('FasterWhisper')
self.FasterWhisper_config_dict = dict(FasterWhisper_items)
class FasterWhisperModel:
def __init__(self,device = None, config_ini_path = './configs/config.ini'):
FasterWhisper_config = FasterWhisperconfig(config_ini_path = config_ini_path)
config_dict = FasterWhisper_config.FasterWhisper_config_dict
if device is not None:
self.DEVICE = device
else:
device = config_dict["device"]
self.DEVICE = "cuda" if torch.cuda.is_available() else "cpu"
if device != "auto":
self.DEVICE = device
self.BEAM_SIZE = int(config_dict["gpu_beam_size"]) if self.DEVICE == "cuda" else int(config_dict["cpu_beam_size"])
self.language = config_dict["language"]
self.COMPUTE_TYPE = config_dict["gpu_compute_type"] if self.DEVICE == "cuda" else config_dict["cpu_compute_type"]
self.MODEL_TYPE = config_dict["gpu_model_type"] if self.DEVICE == "cuda" else config_dict["cpu_model_type"]
self.kotoba_chunk_length = int(config_dict["chunk_length"])
self.kotoba_condition_on_previous_text = config_dict["condition_on_previous_text"]
if self.kotoba_condition_on_previous_text == "True":
self.kotoba_condition_on_previous_text = True
else:
self.kotoba_condition_on_previous_text = False
if config_dict["use_kotoba"] == "True":
self.use_kotoba = True
else:
self.use_kotoba = False
if not self.use_kotoba:
self.model = WhisperModel(self.MODEL_TYPE, device=self.DEVICE, compute_type=self.COMPUTE_TYPE)
else:
self.MODEL_TYPE = config_dict["kotoba_model_type"]
#self.model = WhisperModel(self.MODEL_TYPE, device=self.DEVICE, compute_type=self.cotoba_compute_type)
self.model = WhisperModel(self.MODEL_TYPE)
def audioFile2text(self, file_path):
result = ""
if not self.use_kotoba:
segments, _ = self.model.transcribe(file_path, beam_size=self.BEAM_SIZE,language=self.language)
else:
segments, _ = self.model.transcribe(file_path, beam_size=self.BEAM_SIZE,language=self.language, chunk_length=self.kotoba_chunk_length, condition_on_previous_text=self.kotoba_condition_on_previous_text)
for segment in segments:
result += segment.text
return result
では一つ一つ解説していきます。
FasterWhisperconfigクラス
class FasterWhisperconfig:
def __init__(self, config_ini_path = './configs/config.ini'):
# iniファイルの読み込み
self.config_ini = configparser.ConfigParser()
# 指定したiniファイルが存在しない場合、エラー発生
if not os.path.exists(config_ini_path):
raise FileNotFoundError(errno.ENOENT, os.strerror(errno.ENOENT), config_ini_path)
self.config_ini.read(config_ini_path, encoding='utf-8')
FasterWhisper_items = self.config_ini.items('FasterWhisper')
self.FasterWhisper_config_dict = dict(FasterWhisper_items)
ここではconfig_ini_path = './configs/config.ini'
で指定されている設定ファイルをFasterWhisper_config_dict
として読み込んでいます。
辞書型で読み込んでいるため、設定ファイルの中身をpythonの辞書として読み込むことが可能になります。
FasterWhisperModelクラスのinitメソッド
class FasterWhisperModel:
def __init__(self,device = None, config_ini_path = './configs/config.ini'):
FasterWhisper_config = FasterWhisperconfig(config_ini_path = config_ini_path)
config_dict = FasterWhisper_config.FasterWhisper_config_dict
if device is not None:
self.DEVICE = device
else:
device = config_dict["device"]
self.DEVICE = "cuda" if torch.cuda.is_available() else "cpu"
if device != "auto":
self.DEVICE = device
self.BEAM_SIZE = int(config_dict["gpu_beam_size"]) if self.DEVICE == "cuda" else int(config_dict["cpu_beam_size"])
self.language = config_dict["language"]
self.COMPUTE_TYPE = config_dict["gpu_compute_type"] if self.DEVICE == "cuda" else config_dict["cpu_compute_type"]
self.MODEL_TYPE = config_dict["gpu_model_type"] if self.DEVICE == "cuda" else config_dict["cpu_model_type"]
self.kotoba_chunk_length = int(config_dict["chunk_length"])
self.kotoba_condition_on_previous_text = config_dict["condition_on_previous_text"]
if self.kotoba_condition_on_previous_text == "True":
self.kotoba_condition_on_previous_text = True
else:
self.kotoba_condition_on_previous_text = False
if config_dict["use_kotoba"] == "True":
self.use_kotoba = True
else:
self.use_kotoba = False
if not self.use_kotoba:
self.model = WhisperModel(self.MODEL_TYPE, device=self.DEVICE, compute_type=self.COMPUTE_TYPE)
else:
self.MODEL_TYPE = config_dict["kotoba_model_type"]
#self.model = WhisperModel(self.MODEL_TYPE, device=self.DEVICE, compute_type=self.cotoba_compute_type)
self.model = WhisperModel(self.MODEL_TYPE)
まず、設定ファイルの内容をconfig_dict
に格納しています。これは辞書型のため、config_dict["device"]
のような形で設定ファイルの内容を文字列として取得することができます。
あくまで、すべての文字を文字列として取得するため、int型やbool型にしたい場合は、適宜型変更をする必要があることに注意してください。
続いて下記の順番で処理を行います。
- モデルを動作させる
device
を指定する - 設定ファイルの各種設定を取得する
- モデルを定義する。
- 設定ファイルに合わせて、適切なモデルを定義する
FasterWhisperModelクラスのaudioFile2textメソッド
class FasterWhisperModel:
・・・
def audioFile2text(self, file_path):
result = ""
if not self.use_kotoba:
segments, _ = self.model.transcribe(file_path, beam_size=self.BEAM_SIZE,language=self.language)
else:
segments, _ = self.model.transcribe(file_path, beam_size=self.BEAM_SIZE,language=self.language, chunk_length=self.kotoba_chunk_length, condition_on_previous_text=self.kotoba_condition_on_previous_text)
for segment in segments:
result += segment.text
return result
ここでは、faster-whisperモデルのtranscribe
メソッドを呼び出して、音声認識をしています。
設定ファイルで指定したモデルに合わせて、適切な引数を使っています。
faster-whisperは30秒以上の音声に関しては、音声を分割して処理をするため、分割されて生成されたテキストをresult
変数に格納して、returnしています。
まとめ
今回は、初心者向けにGoogle Colaboratoryで、簡単に生成AIを使えるようにする環境を作りました。
Part5の今回は、生成AIの一つ、音声認識AIのfaster-whisperモデルを使えるようにしました。
その中で、前回のPart4で扱った、Whisper APIとの処理速度の比較などを行いました。
さらに、音声認識AIを利用した音声対話システムに関しても、下記で記事を書いています。
もし興味があれば一読いただけますと幸いです。
次回Part6では、画像生成AI Stable-Diffusionを使えるようにしたいと思います。
Discussion