動画から文字起こし
zoom会議の議事役をすっぽかしてしまい、面倒でpythonでやってみたら思ってたより簡単だったので、備忘録に。googleのSpeech Recognitionを用いる。
mp4からwavへの変換
zoomの録画ファイルはmp4だが、Speech Recognitionがwavファイルがデフォルトになっている模様なので、wavに変換する。これはffmpegが簡単だった。terminalで以下のコマンドで一発。
# running in terminal
ffmpeg -i input_file.mp4 -acodec pcm_s
16le -ar 44100 -ac 2 output_file.wav
ffmpegを入れていない場合、Macなら以下。Windowsは製品版を用いればよい。
brew install ffmpeg
テキストへの変換
Speech Recognitionは最大60秒のファイルしか処理できない。そこでwavファイルを分割し、一つずつテキスト化した後、それを結合する。以下は一気にコード。下の参考リンクのコードではエラーが出て動かなかったので、少し修正済み(cut_wavs_strの部分は特に)。
# import libraries
import os
import glob
import shutil
import subprocess
import speech_recognition as sr
# split audio file
import wave
import math
import struct
from scipy import fromstring, int16
def cut_wav(wavf, time = 60):
wr = wave.open(wavf, "r")
ch = wr.getnchannels()
width = wr.getsampwidth()
fr = wr.getframerate()
fn = wr.getnframes()
total_time = 1.0*fn/fr
integer = math.floor(total_time)
t = int(time)
frames = int(ch*fr*t)
num_cut = int(integer/t)
data = wr.readframes(wr.getnframes())
wr.close()
X = fromstring(data, dtype = int16)
os.remove(wavf)
outf_list = []
for i in range(num_cut):
output_dir = "output/cut_wav/"
os.makedirs(output_dir, exist_ok = True)
outf = output_dir + str(i).zfill(3) + ".wav"
start_cut = i*frames
end_cut = i*frames + frames
Y = X[start_cut:end_cut]
outd = struct.pack("h"*len(Y), *Y)
ww = wave.open(outf, "w")
ww.setnchannels(ch)
ww.setsampwidth(ch)
ww.setframerate(fr)
ww.writeframes(outd)
ww.close()
outf_list.append(outf)
return outf_list
# audio to text
def cut_wavs_str(outf_list):
output_text = ""
for fwav in outf_list:
print(fwav)
r = sr.Recognizer()
text = ""
with sr.AudioFile(fwav) as source:
audio = r.record(source)
try:
text = r.recognize_google(audio, language = "ja-JP")
except sr.UnknownValueError:
print("Google Speech Recognition could not understand the audio")
except sr.RequestError as e:
print(f"Could not request results from Google Speech Recognition service; {e}")
output_text = output_text + text + "\n"
os.remove(fwav)
return output_text
# wav to text
def wav_to_text(wav_file):
shutil.rmtree("output/cut_wav/")
os.makedirs("output/cut_wav/", exist_ok = True)
cut_wavs = cut_wav(wav_file)
out_text = cut_wavs_str(cut_wavs)
txt_file = "output/" + "out_text" + ".txt"
f = open(txt_file, "w")
f.write(out_text)
f.close()
wav_to_text("output_file.wav")
精度
まあ、自力で全部聞き取るよりはマシ、といったところ。上の方法だとlocalでできるので気楽ではある。多分これも日本語よりも英語の方が全然精度がいいんだろうなぁ。
関連記事
PythonによるWebスクレイピング
PythonでのスクレイピングとCSVファイルへ書き込み
情報量とは何か?
参照リンク
pythonで長い音声・動画からの文字起こしを実装する
短い音声ファイルでの音声からの文字起こしはできましたので,本稿では長い音声・動画での文字起こし(できるだけ無料で)に実装したいです.
コメント