Whisperモデルに入力する音声ファイルを色々加工して、文字起こし精度を上げる実験をしていて
ラウドネスノーマライズがまあまあうまく行きました。
pylnでラウドネスノーマライズ
import pyloudnorm as pyln
import soundfile as sf
# ファイル読み込み
y, sr = sf.read("path_to_your_audio_file.wav")
# ラウドネスノーマライズ
meter = pyln.Meter(sr)
loudness = meter.integrated_loudness(y)
target_loudness = -26.0 # (LUFS単位)デフォルトの-23よりもうちょっと小さくしてみました。
normalized_audio = pyln.normalize.loudness(data, loudness, target_loudness)
# 出力
sf.write("normalized_audio.wav", normalized_audio, rate)
結果確認
Audacityで波形を見てみます。
上がオリジン波形、
下がラウドネスノーマライズ後の波形です。
通常の振幅ノーマライズをしてしまうと、
なんかぶつかったときとかの大きな衝撃音(ほぼ振幅1)を基準値にしてしまうので、
ほとんど波形が増幅されません。
実際の音声部をそこそこ大きくしたいので、ラウドネス知覚レベルのノーマライズを行いました。
精度上昇の確認
2時間の音声ファイルに対して、
オリジン波形をWhisperモデルで文字起こししたものと、ラウドネスノーマライズしたもので比較しました。
(1) wordのprobで比較。
文字起こしの精度、ここでは誤変換なく正しく文字起こしできているかの精度を見るために、word内のprob値を参照します。
# 結果のJSONから収集
word_porb_list = []
for seg in result_json["segments"]:
for w in seg["words"]:
word_porb_list.append(w["probability"])
# グラフ化
pd.options.display.float_format = '{:.6f}'.format
plt.hist(np.array(word_porb_list), bins=100)
plt.xlim(0.0, 1.0)
plt.show()
# 統計量も表示
pd.DataFrame(word_porb_list).describe()
正直、図からは改善の様子がわかりません。
describe()結果を見ると、
meanが落ちているので、全てのwordの文字起こし精度が良くなっているわけではないですが、
25%と中央値(50%)の精度が上がっているので、(0.30ポイントと、0.26ポイント)
全体的に精度が微増しているような傾向が見られます。
もうすこし詳しく確認します。
変換精度 0.7超えについて確認
ただしく変換できてそうな、推定確率0.7を超えた要素のみを取得してみます。
tmp = np.array(word_porb_list)
tmp = tmp[tmp >= 0.7]
plt.hist(tmp, bins=100)
plt.xlim(0.7, 1.0)
plt.show()
pd.DataFrame(tmp).describe()
やっぱり図からは見えてこないほどの微増ですが、
count数が、全体で10サンプル差だったのが、
0.7以上のそれは、35サンプル差に増えています
雑に25サンプルの誤り変換を修正できたと考えられます。
実際に、下記のようなちょっとした誤変換を修正できていました
誤:トランプロジェクトに合うような、
正:そのプロジェクトに合うような
ちょっとおまじないライクにラウドネスノーマライズして振幅増幅してWhisperにかけるとよいかもしれません