pydubの動作チェック
今回製作したへんてこなモジュール?はLinuxで実行して動作確認しております。そのため、WindowsやMacからでは動作しない可能性があります。使う前にpydubが動作可能であるかテストしてみてください。
from pydub import AudioSegment
from pydub.playback import play
audio = AudioSegment.from_mp3("audio.mp3")
play(audio)
適当なaudio.mp3を同じフォルダにおいて実行して音が鳴ればおkです。
もちろんpydubやsimpleaudioは事前にpip経由等でインストールしておいてください。
背景
pyaudioはwavしか再生できず、pydubはmp3が読み込めるがバックグラウンド再生を指定することが出来ない。
調べた所pygameが使えるということだが、使い方が悪いのか再生が重たくノイズが入ってうまく再生できなかった。
解決法
pydubのソースを読んでみると、中でsimpleaudioで再生してwaitしているみたいなので、これをなくせばバックグラウンド再生ができる。ということで、pydubとsimpleaudioを適当に組み合わせたらうまいこといろいろ再生できる環境が作れそうだということがわかりました。
というわけで、mp3やwavファイルなどのコーデックにも対応して、なおかつバイナリデータからバックグラウンドも再生できる単純なクラスを書いてみました。
結果
pydubとsimpleaudioを組み合わせた結果、以下のようなものを作ればいろいろと対応できそうです。
# バイナリデータを読み込む場合の一時ファイル用
from tempfile import NamedTemporaryFile
from pydub import AudioSegment
import simpleaudio
class SoundPlayer:
"""SoundPlayer module."""
@classmethod
def play(cls, filename, audio_format="mp3", wait=False, stop=False):
"""Play audio file."""
if stop:
simpleaudio.stop_all()
seg = AudioSegment.from_file(filename, audio_format)
playback = simpleaudio.play_buffer(
seg.raw_data,
num_channels=seg.channels,
bytes_per_sample=seg.sample_width,
sample_rate=seg.frame_rate
)
if wait:
playback.wait_done()
@classmethod
def play_from_buffer(cls, audio_content, audio_format="mp3", wait=False, stop=False):
"""Play from buffer."""
with NamedTemporaryFile() as fd:
fd.write(audio_content)
# Revert head of file. It is neccesary to play audio.
fd.seek(0)
cls.play(fd.name, audio_format=audio_format, wait=wait, stop=stop)
使い方
mp3ファイルを再生する
SoundPlayer.play(file_name)
wavファイルを再生する
SoundPlayer.play(file_name, audio_format="wav")
バイナリデータのmp3を再生する
たとえばgoogleのAPIから返された音声データはmp3のバイナリで変数に代入されて帰ってくるので
そのままでは再生できない。そのため一時ファイルに一度書き出せば再生できる。
SoundPlayer.play_from_buffer(audio_content)
再生中の音を止めてから再生する
SoundPlayer.play(file_name, stop=True)
再生が終わるまでまつ
SoundPlayer.play(file_name, wait=True)
おわりに
pydubにバックグラウンド再生のオプションが搭載されればこのようなものはいらなくなりますが、いつになるやら。同じようなことで困ってる方がいましたら何かの参考になれば幸いです。