OpenAIが提供する音声認識ツール「Whisper」を使用した、ローカルPCでの音声ファイルの自動文字おこし方法をまとめました。Webサービスのような使用制限や課金はありません!
スピードの速いラジオ番組の文字おこしも精度よくできるので、以下の記事もこの方法で作成しています。
Whisperとは?
Whisperは、Open AIによって開発されたオープンソースの音声認識技術です(参考)。
AIにより音声データをテキストに変換する機能を搭載しています。背景ノイズがある環境でも精度が高いことや、多言語対応能力(100言語以上)で注目されています。
Pythonのライブラリも提供されており、数行のスクリプトで簡単に実行できます(!)
この記事では、Whisperを使用して音声ファイルをテキストに変換する方法について説明していきます。
出力形式の細かい指定はできなさそうだけど、どんな感じか少し味見したいなら writeout.ai のようなツールもあるみたい。この記事ではローカルでの使用方法を紹介するよ。
事前準備
CPUでも実行可能ですが、時間が相当かかるためGPU(CUDA)での実行をお勧めします。
今回はWindows PC + GPU の前提で説明を行っていきます。
CUDA環境の設定
下記の「ものものテック」様のサイトがよくまとまっていますので、参考にしながらインストールしていきます。pipを用いたインストール手順なのでAnacondaのインストールは不要で、Python をインストールさえしておけば問題ありません(筆者はver. 3.10.6 で動作確認しています)。
https://monomonotech.jp/kurage/memo/m230921_whisper_windows_cuda.html
お使いのGPUが対応しているCUDAバージョンに応じて、インストールするPytorchのバージョンが変わるため注意してください。
Python 及び whisper のインストール
下記のコマンドにより、Whisper のインストールを行います。
pip install -U openai-whisper
スクリプトの実行
MP3ファイルを読み込み、その内容をテキストに書き起こしてtxtファイルとして保存するソースコードを示します。 inputfile変数とoutputfile変数を適宜変更した後、Pythonスクリプト(.py)として保存してください。
なお入力ファイルの形式は、MP3だけでなく主要な音声ファイルフォーマットに対応しているようです(音声入力用にffmpegを使用している為)。
import whisper
import os
# 入力ファイル名(適宜変更する)
inputfile = "input.mp3"
# 出力ファイル名(適宜変更する)
outputfile = "output.txt"
script_path = os.path.abspath(__file__)
script_folder = os.path.dirname(script_path)
# 処理
model = whisper.load_model("medium", device="cuda")
result = model.transcribe(script_folder + "/" + inputfile, language="ja", verbose=True)
# セグメントごとに改行してテキストを取得
segments = result["segments"]
transcript = "\n".join(segment["text"] for segment in segments)
# txtへ書き出し
with open(script_folder + "/" + outputfile, "w", encoding='utf-8_sig') as f:
f.write(transcript)
CPUで実行する場合には、以下の部分を
model = whisper.load_model("medium", device="cuda")
このように書き換えます。(「device」の部分が変わっています)
model = whisper.load_model("medium", device="cpu")
例として、上記スクリプトを “transcript.py” というファイル名で保存した場合、下記のコマンドで実行します。
python transcript.py
GPUで実行されているか確認したいときは
GPUによる処理が行われているかどうかはタスクマネージャーで確認できます(「Dedicated GPU memory usage」 / 「専用GPUメモリ使用量」の欄)。
「nvidia-smi」コマンドでもいいですがこちらの方がわかりやすい。
使用中の期間だけ明らかにGPUのメモリ使用量が上がります。
実施結果例
以下のpodcastの(CM終了後の)冒頭1分間を入力した場合の結果を載せておきます。
モデルのサイズは「medium」(速度、精度共にそこそこ良い設定)を使用しています。
[00:00.000 --> 00:02.000] さあ本日もよろしくお願いいたします [00:02.000 --> 00:06.000] 6月末でございますが [00:06.000 --> 00:09.000] カフが上がっておりませんね [00:09.000 --> 00:13.000] カフが上がってなかったから入ってなかったですね声がね [00:13.000 --> 00:15.000] 上がってたら入ってたんですけど [00:15.000 --> 00:18.000] 大きく入ってないだけでそちらの方に [00:18.000 --> 00:19.000] 俺のマック入ってる [00:19.000 --> 00:21.000] いやそれじゃダメなんよちゃんと入らんと [00:21.000 --> 00:23.000] カフ無事なやっぱ [00:23.000 --> 00:25.000] 忘れた頃にね [00:25.000 --> 00:27.000] 忘れちゃいますね [00:28.000 --> 00:30.000] ということで6月末ですか [00:30.000 --> 00:32.000] ちょっと先日ですね [00:32.000 --> 00:39.000] ちょっと素敵な人を見てしまいました [00:39.000 --> 00:41.000] 見つけてしまいました [00:41.000 --> 00:43.000] ちょっと魅力的ななんて [00:43.000 --> 00:47.000] わーってなりましてですね [00:47.000 --> 00:49.000] 素敵な出会い [00:49.000 --> 00:51.000] ぜひ大人共有したいんですけども [00:51.000 --> 00:53.000] ミーガンって知ってる映画 [00:53.000 --> 00:55.000] 知ってる怖いやつだ [00:55.000 --> 01:00.000] 今絶賛上映中のミーガンっていう映画を見たいなと思って
日本語としておかしい部分も少しありますが、かなり高い精度で音声認識できています。笑い声等のノイズがあること、複数人がラフに会話している状況を考えるとかなり良い結果ではないでしょうか。
(参考)スクリプト解説
理解しなくても使えるので必要のない方は読み飛ばしてください。
ライブラリのインポートとパスの設定
import whisper
import os
# 入力ファイル名(適宜変更する)
inputfile = "input.mp3"
# 出力ファイル名(適宜変更する)
outputfile = "output.txt"
script_path = os.path.abspath(__file__)
script_folder = os.path.dirname(script_path)
import whisper
: Whisperライブラリのインポートimport os
: OSの機能にアクセスするために必要なライブラリです。ファイルパスの操作に使用します。inputfile = "input.mp3"
outputfile = "output.txt"
: 入出力ファイルの設定script_path = os.path.abspath(__file__)
: 現在実行中のスクリプト(transcript.py)の絶対パス取得script_folder = os.path.dirname(script_path)
: スクリプトが存在するフォルダのパスを取得
モデルのロード、音声の書き起こし
# 処理
model = whisper.load_model("medium", device="cuda")
result = model.transcribe(script_folder + "/" + inputfile, language="ja", verbose=True)
model = whisper.load_model("medium", device="cuda")
:- Whisperのモデルをロードします。
medium
サイズのモデルを使用し、cuda
によりGPUを使用する設定としています。
result = model.transcribe(script_folder + "/" + inputfile, language="ja", verbose=True)
- inputfile で指定した音声ファイルを書き起こし、結果を変数resultに格納します。
- 日本語なので
language="ja"
とします。 - 進捗状況は随時表示する設定です。
得られた情報からテキスト情報のみを抽出し、ファイルへ書き込む
# セグメントごとに改行してテキストを取得
segments = result["segments"]
transcript = "\n".join(segment["text"] for segment in segments)
segments = result["segments"]
- result 内の “segments”要素の内容を、変数segmentsに一時的に代入します。
transcript = "\n".join(segment["text"] for segment in segments)
:- 変数segmentsから、書き起こされたテキストのみを抽出します。
- 具体的にはsegments 内の各要素(辞書型)について、”text”要素の内容を抽出、各要素ごとに改行しながら結合し、transcript変数に代入します。
# txtへ書き出し
with open(script_folder + "/" + outputfile, "w", encoding='utf-8_sig') as f:
f.write(transcript)
- 変数 outputfile で指定したファイルに、抽出されたテキストを書き込みます。
参考
https://github.com/openai/whisper
https://github.com/openai/whisper/blob/main/whisper/transcribe.py
https://monomonotech.jp/kurage/memo/m230921_whisper_windows_cuda.html
コメント