PythonでMP3再生(スピード・その他の比較)
今回の内容は、音声処理パッケージの処理の速度などを、(あくまで当方のWindows11PC環境の上で)比較してみた結果です。単に、ライブラリの説明を読んでいるだけではわからない、実践して比較して見ないとわからない問題もあるのだなと痛感しました。
試行錯誤の末
前回までsnykAdvisorのスコア見ながらの試行錯誤
・・・の末、音声ファイルの再生機能にはsounddevice を中心に使おう、と方針を固めていたところです。
これまでpygame, playsound3,just_playback といったところを使ってきました。特にjust_playback をベースに自分なりのPlayerクラスを書いていました。
それと同じ機能をsounddeviceで実現するには?
兎に角、まずはpip install sounddevice し、まずは単純なmp3ファイルの再生から試します。
実際に動かすと問題発生
import librosa
import sounddevice as sd
y, sr = librosa.load("test.mp3")
sd.play(y, sr)
sd.wait()
これで一応、音は出るのです。けれども、どうも鳴りはじめるまでが極端に遅いと感じました。
そこで、実行時間を比較検証してみることにしました。
時間測定の方法
import time
start_time = time.time()
# 処理をここに
end_time = time.time()
print(f"{end_time-start_time:.3f}秒")
テスト用のmp3
「good morning」と喋るだけのファイル。duration確認小数点以下3桁
import librosa
y, sr = librosa.load("test.mp3")
print(f"{librosa.get_duration(y=y, sr=sr):.3f}秒")
小数点以下3桁で切ることにしました 音声ファイル自体の長さ(duration)は1.056秒です。
これを読み込んでから再生が終わるまでにかかった時間を求める。
1.056+α秒になるわけですが、αが小さいほど良い。
組み合わせ比較
ファイル処理librosa 再生sounddevice
import time
import librosa
import sounddevice as sd
start_time = time.time()
# 処理をここに
y, sr = librosa.load("test.mp3")
sd.play(y, sr)
sd.wait()
end_time = time.time()
print(f"{end_time-start_time:.3f}秒")
結果は、3回試して、4.370秒、4.369秒、4.224秒・・・うーんかかりすぎ。一本が長い音楽を聴くなら、出だしで少しくらい「じらされて」もいいですけど、学習教材の再生用には全く不向き。
ファイル処理soundfile 再生sounddevice
前のは、sounddeviceが悪いのか、それともlibrosaが悪いのか、わからなかったので、ファイル処理をlibrosa⇒soundfileに変更してテスト。
import time
import sounddevice as sd
import soundfile as sf
start_time = time.time()
# 処理をここに
y, sr = sf.read("test.mp3")
sd.play(y, sr)
sd.wait()
end_time = time.time()
print(f"{end_time-start_time:.3f}秒")
1.621秒、1.360秒、1.352秒。・・librosaよりずっと速いです。これなら実用的です。遅いのはsounddeviceのせいじゃなかった!
ファイル処理・再生playsound3
import time
from playsound3 import playsound
start_time = time.time()
# 処理をここに
playsound("test.mp3")
end_time = time.time()
print(f"{end_time-start_time:.3f}秒")
2.212秒、1.424秒、1.440秒。まあ、速いことは速いのだけれど再生の出だしが切れる。そういえばplaysound3で出だしの音が切れること、とその回避策については以前書いています
・・・というような妙なことを(パッケージを適切に選べば)やらなくて済みそうですね。
ファイル処理・再生just_playback
import time
from just_playback import Playback
start_time = time.time()
# 処理をここに
playback = Playback()
playback.load_file("test.mp3")
playback.play()
while playback.active:
time.sleep(0.1)
end_time = time.time()
print(f"{end_time-start_time:.3f}秒")
1.339秒、1.298秒、1.296秒。再生は早いが、これも音声の出だしが切れる。
ファイル処理pydub 再生sounddevice
import time
import sounddevice as sd
from pydub import AudioSegment
start_time = time.time()
# 処理をここに
audio = AudioSegment.from_file("test.mp3")
audio_data = audio.get_array_of_samples()
sr = audio.frame_rate
sd.play(audio_data, samplerate=sr)
sd.wait()
end_time = time.time()
print(f"{end_time-start_time:.3f}秒")
1.644秒、1.418秒、1.422秒。おや、pydubはlibrosaと違って速いんだな。
念のため、最初にやったlibrosa+sounddeviceの速度を再確認。
10.677秒、4.387秒、4.493秒。遅い。(最初の10秒越えは何だ・・。)
雑感
librosaは機能は多いが、処理スピードが必要な場面には不向き。
just_playback playsound3での再生は音声の出だしが切れることがある。
結論
mp3再生するだけなら
・ファイル処理soundfile 再生sounddevice
ファイル加工で必要なら
・ファイル加工処理pydub 再生sounddevice
という組み合わせがよさそうだと現時点では判断しています。