見出し画像

OpenAIの「Whisper」を使って文字起こししてみた()

お疲れ様です。De:Lです。先日愛媛FCの情報交換会の様子が愛媛FC公式Youtubeから公開されました。早速見てみたんですが、文字列でしっかり読み込みたいな思いまして。。。

せっかくなので最近話題のOpenAI社のWhisperという音声認識モデルを使って、文字起こしに挑戦してみました。

なお

  1. Pythonの開発環境が整っている。(このnoteではColabで作っています。)

  2. 文字起こししたい音声ファイルがmp3で用意できている。

の2点は既に完了しているものとして話を進めます。

参考サイト

Whisperの導入

!pip install git+https://github.com/openai/whisper.git

Colabだとそのままこのコードを入れるだけで大丈夫です。

本体コード

import whisper
import wave
import struct
import math
import os
from scipy import fromstring, int16
import glob
import pydub
from pydub import AudioSegment
import numpy as np
from google.colab import files

#wavへ変換
s = pydub.AudioSegment.from_mp3("ファイル名.mp3")
s.export("converted.wav", format="wav")

#whisper準備
model = whisper.load_model("medium")


#読み込むファイル名
f_name = "converted"

#切り取り時間[sec]
cut_time = 30

# 保存するフォルダの作成
file = os.path.exists("output")

if file == False:
  os.mkdir("output")

def voice_cut(filename,time): 
  # ファイルを読み出し
  wavf = filename + '.wav'
  wr = wave.open(wavf, 'r')
  # waveファイルが持つ性質を取得
  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)  # 秒数[sec]
  frames = int(ch * fr * t)
  num_cut = int(integer//t)
  
  # waveの実データを取得し、数値化
  data = wr.readframes(wr.getnframes())
  wr.close()
  X = fromstring(data, dtype=int16)
  
  for i in range(num_cut):
    # 出力データを生成
    outf = 'output/' + str(i) + '.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(width)
    ww.setframerate(fr)
    ww.writeframes(outd)
    ww.close()

  translated_arguments = list()
  filess = glob.glob("/content/output/*")
  for file in filess:
    result = model.transcribe(file)
    translated_arguments.append(result["text"])

  with open("translated_argument.txt","w") as f:
    for item in translated_arguments:
      f.write(item)
  files.download("translated_argument.txt") 

voice_cut(f_name,cut_time)

備考

プログラムの中でいじれる場所はcut_timeですね。本コードでは30秒に設定しています。つまり30秒毎に音声ファイルを分割して、Whisperに入力しています。

元来Whisperは任意の音声ファイルを認識できるものでしたが、長さが短いものに限られる(一度の入力で容量の限界がある)というネックがありました。

従って、音声ファイルを分割し、文字起こししたものを再び文章化するという手法を取りました。

その点、分割ポイントは30秒でピッタリで分けているので、その近辺は文章の繋ぎが変になってしまいます。

注意です。

精度はこんなもんです。正直まぁまぁです。
修正は必須です。まぁ一から書くよりは圧倒的に楽かなと。

その他参考サイト


この記事が気に入ったらサポートをしてみませんか?