家族が録音したデータをいちいち聞いてまとめるのが大変で負担になっているということだったので、最近流行りのAIを使って文字起こしをするシステムを作ってみました。
文字起こしをしてくれるクラウドサービスなどもあるようでしたが、今回はオープンソースで使えるwhisperを使ってみました。
whisperはOpenAI社の作った自動文字起こしするためのAIで、日本語に対応した学習モデルも公開されています。
whisper + python で思ったよりもかなり簡単にできてしまったので驚いています。家族も大満足なので、おすすめです。
作ったシステムの概要
音声データをフォルダに入れておいて、定期的にサーバから音声ファイルを確認して、文字起こしがされていなければそのファイルを文字起こしして結果のテキストファイルを特定のフォルダに書き出す、というものです。
文字起こし自体はpythonで実現しました。
定期的な処理は自宅のサーバ(ubuntu)のcronで定期実行しています。
文字起こしにはそれなりに時間がかかるので、夜間に実行するようにしています。
必要なソフトウェアのインストール
以下のブログを参考にさせていただきました。
以下、前提としてpythonの環境構築はできているものとします。
今回はubuntu 20.04で実行しています。
whisperのインストール
githubに公開されているものをpipコマンドでインストールします。
$ pip install git+https://github.com/openai/whisper.git
ちょっと時間がかかります。
このインストールが完了した時点では学習モデルはダウンロードされていません。
ffmpegのインストール
今回、iphoneで録音したデータをNASに保存してもらい、その文字起こしを行いました。
iphoneの標準のアプリで録音されたデータはm4aという拡張子で、ubuntu標準ではコーデックがないようなので、ffmpegをインストールしておきます。
$ sudo apt-get install ffmpeg
Pythonスクリプト(文字起こし)
文字起こしスクリプトはpythonで実装しました。
文字起こしした結果のテキストファイルは指定のフォルダパスに、音声ファイルのファイル名の拡張子を.txtに変えたファイル名で保存するようにしています。
毎回すべての音声ファイルを文字起こしするといろいろと無駄なので、音声ファイルとテキストファイルの一覧を比較し、テキストファイル(文字起こしの結果ファイル)がないもののみ文字起こしするようにしています。
whisperの文字起こし結果は音声ファイルの時間なども含まれていますが、文字起こししたテキストのみ保存しています。
以下が最終的なファイルです。
- # -*- encoding:utf-8 -*-
- #----------------------------------------------------
- # auto_whisper.py
- #
- # generate trascription file from audio data.
- # ---------------------------------------------------
- import glob
- import os
- import re
- import whisper
- # audio file types
- audio_types = "(m4a|mp3|wav)"
- # filepath
- audio_folder_path = "音声ファイルのフォルダパス"
- text_folder_path = "出力テキストファイルのフォルダパス"
- # audio file list
- audio_file_list = []
- for audio_file in glob.glob(audio_folder_path+"/*"):
- if re.match('.+\.'+audio_types+'$', audio_file):
- audio_file_list.append(audio_file)
- # text file list
- text_file_list = []
- for text_file in glob.glob(text_folder_path+"/*"):
- if re.match('.+\.txt$', text_file):
- text_file_list.append(os.path.splitext(os.path.basename(text_file))[0])
- # pick up audio files that have not yet been transcripted.
- transcript_file_list = []
- for audio_file in audio_file_list:
- if os.path.splitext(os.path.basename(audio_file))[0] in text_file_list:
- print(audio_file, "ari")
- else:
- print(audio_file, "nashi")
- transcript_file_list.append(audio_file)
- # transcript files
- if bool(transcript_file_list):
- # load model
- model = whisper.load_model("small")
- print("transcripting...")
- # transcript files
- for transcript_file in transcript_file_list:
- print("trascripting: "+ transcript_file)
- # output file
- output_file_path = text_folder_path + "/" + os.path.splitext(os.path.basename(transcript_file))[0] + ".txt"
- f = open(output_file_path, 'w')
- result = model.transcribe(transcript_file, verbose=True, language='ja')
- f.write(result["text"])
- f.close()
- # end
定期実行
定期実行はシンプルにcronを使っています。
処理時間がかかるので夜間に実行するようにしています。