概要
vosk を使って音声ファイルを文字起こししたテキストファイルを作るスクリプトを作成した。
備忘のため記事を残す。下記リポジトリの README と同等程度の情報です。
リポジトリ
音声文字起こしツール
音声ファイル(.wav)に対して、文字起こしした結果をテキストファイル(.txt)に出力する。
使い方
動作確認
- Python 3.12.6
- macOS 14.4
モデルをダウンロードする
https://alphacephei.com/vosk/models からモデルをダウンロードする。
vosk-model-ja-0.22 をダウンロードし、このディレクトリに展開している。ほかのモデルを使う場合は、-m
オプションで指定する。
ライブラリのインストール
pip install -r requirements.txt
コマンド実行
usage: main.py [-h] -i INPUT_FILENME -o OUTPUT_FILENAME [-m MODEL_PATH]
音声ファイル(.wav)に対して、文字起こしした結果をテキストファイル(.txt)に出力する
options:
-h, --help show this help message and exit
-i INPUT_FILENME, --input_filenme INPUT_FILENME
入力ファイルのパス
-o OUTPUT_FILENAME, --output_filename OUTPUT_FILENAME
出力ファイルのパス
-m MODEL_PATH, --model_path MODEL_PATH
モデルファイルのパス
スクリプト
リポジトリ内の main.py
import vosk
import wave
import time
import json
from logging import getLogger, INFO, StreamHandler, Formatter
logger = getLogger(__name__)
logger.setLevel(INFO)
formatter = Formatter("[%(asctime)s] [%(levelname)s] %(message)s")
handler = StreamHandler()
handler.setFormatter(formatter)
handler.setLevel(INFO)
logger.addHandler(handler)
# 引数の音声ファイル(.wav)に対して、文字起こしした結果をテキストファイル(.txt)に出力する
# モデルファイルのパス
MODEL_PATH = "vosk-model-ja-0.22"
# 1回の音声認識に使うフレーム数
FRAME_SPAN = 4000
# 進捗を表示する間隔
NOTIFY_TIME_INTERVAL = 10
def main(input_filename, output_filename, model_path):
# モデルファイルのパス
model = vosk.Model(model_path)
logger.info(f"Loaded Model: {model_path}")
# 音声ファイルを開く
wf = wave.open(input_filename, "rb")
logger.info(f"Open: {input_filename}")
all_frames = wf.getnframes()
# 開始時間を記録
start_time = time.time()
# 前回の通知時間を記録
last_notify_time = start_time
read_frames = 0
# 音声認識器を作成
rec = vosk.KaldiRecognizer(model, wf.getframerate())
# 音声認識の実行
results = []
while True:
data = wf.readframes(FRAME_SPAN)
read_frames += FRAME_SPAN
if len(data) == 0:
break
if rec.AcceptWaveform(data):
result = rec.Result()
json_dict = json.loads(result)
text = json_dict["text"]
if text != "":
results.append(text)
logger.debug(f"Result: {text}")
# 進捗を表示
last_notify_time = print_progress(read_frames, all_frames, start_time, last_notify_time)
# 結果をテキストファイルに出力
with open(output_filename, "w") as f:
for result in results:
f.write(result + "\n")
logger.info(f"Output to {output_filename}")
def print_progress(read_frames, all_frames, start_time, last_notify_time):
if read_frames > all_frames:
return last_notify_time
if time.time() - last_notify_time < NOTIFY_TIME_INTERVAL:
return last_notify_time
current_time = time.time()
elapsed_time = current_time - start_time
progress = (read_frames / all_frames) * 100
logger.info(f"[{elapsed_time:.1f}s] {progress:.2f}%")
return current_time
if __name__ == "__main__":
# 引数を取得する
import argparse
parser = argparse.ArgumentParser(
description="音声ファイル(.wav)に対して、文字起こしした結果をテキストファイル(.txt)に出力する"
)
parser.add_argument("-i", "--input_filenme", help="入力ファイルのパス", required=True)
parser.add_argument("-o", "--output_filename", help="出力ファイルのパス", required=True)
parser.add_argument("-m", "--model_path", help="モデルファイルのパス", default=MODEL_PATH)
args = parser.parse_args()
main(args.input_filenme, args.output_filename, args.model_path)
スクリプト解説
vosk の利用について
vosk-api に各言語のサンプルコードが記載されている。
Python版: https://github.com/alphacep/vosk-api/tree/master/python
引数の扱い argparse
標準ライブラリの argparse を利用した。
実行時の pyenv について
実行時は pyenv を利用している。
pyenv の環境準備・利用
# 実行ディレクトリに venv ディレクトリが用意される
python -m venv venv
# venv の環境を利用する
source ./venv/bin/activate
...
pip install vosk Wave
pip freeze > requirements.txt
...
pip install -r requirements.txt
...
# venv の環境だと `deactivete` コマンドが実行できる
# `deactivete` コマンドを実行すると環境を抜けられる
deactivete