[Python][音声認識]pythonを利用して動画ファイルから文字起こしをする方法

formal man with tablet giving presentation in office python
Photo by Andrea Piacquadio on Pexels.com

動画から文字起こし

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で長い音声・動画からの文字起こしを実装する
短い音声ファイルでの音声からの文字起こしはできましたので,本稿では長い音声・動画での文字起こし(できるだけ無料で)に実装したいです.

コメント

タイトルとURLをコピーしました