Pythonでサウンドを扱う
Pythonでサウンドを扱う方法がいろいろあってよくわからなかったので、ざっくりまとめ
基本的にはこちらのサイト Playing and Recording Sound in Python を参考にした。
再生
オーディオ再生するライブラリの一例
- playsound WAVとMP3ファイルを再生するためだけの簡単なパッケージ
- simpleaudio WAVファイルとNumPyアレイを再生できるライブラリ
- winsound WAVファイルとビープ音を再生できる、Windows用ライブラリ
- python-sounddevice、pyaudio WAVファイルを再生するPortAudioライブラリの提供
- pydub pyaudioも必要になるが、ffmpegをインストールすることで数行のコードで幅広いオーディオ形式を再生できる
playsound
playsound関数のみが実装されており、WAVファイルもしくはMP3ファイルを指定して再生する。
install
pip install playsound
usage
from playsound import playsound
playsound("sample.wav")
simpleaudio
WAVファイルもしくはNumPyアレイを再生する。再生中かどうかの判別も可能。
install
pip install simpleaudio
usage
import simpleaudio
wav_obj = simpleaudio.WaveObject.from_wave_file("sample.wav")
play_obj = wav_obj.play()
play_obj.wait_done()
# 再生中か確認する
if play_obj.is_playing():
print("still playing")
winsound
Windowsの場合、winsoundがデフォルトで使用可能? WAVファイルの再生およびビープ音の再生が可能。
usage
import winsound
winsound.PlaySound("sample.wav", winsound.SND_FILENAME)
# ビープ音の再生
import winsound
winsound.Beep(1000, 100) # 1000Hzのビープを100ms再生
python-sounddevice
PortAudioライブラリのバインドを提供。オーディオ信号、NumPyアレイを再生/録音するための機能を提供。
install
Anacondaを使用している場合、condaパッケージでインストールできる
conda install -c conda-forge python-sounddevice
usage
import sounddevice as sd
import wave
import numpy as np
wf = wave.open("sample.wav")
fs = wf.getframerate()
data = wf.readframes(wf.getnframes())
data = np.frombuffer(data, dtype='int16')
sd.play(data, fs)
status = sd.wait()
上記は一曲全体を一括で扱うが、リアルタイム処理などを行う場合はコールバック処理で短い単位ごとにオーディオ信号を扱う必要がある。
import sounddevice as sd
duration = 5.5
def callback(indata, outdata, frames, time, status):
if status:
print(status)
outdata[:] = indata
with sd.Stream(channels=2, callback=callback):
sd.sleep(int(duration * 1000))
pydub
install
pip install pydub
MP3等のWAV以外のファイルを使用する際には、ffmpegかlibavのインストールも必要。
さらに、オーディオの再生には以下のいずかれをインストールする必要あり(simpleaudioが推奨)
- simpleaudio
- pyaudio
- ffplay (ffmpegに同梱)
- avplay (libavに同梱)
usage
from pydub import AudioSegment
from pydub.playback import play
sound = AudioSegment.from_file("sample.wav", format="wav")
play(sound)
pyaudio
PortAudioライブラリのバインドを提供。クロスプラットフォーム上で簡単にオーディオ再生、録音が可能。
単純なオーディオの再生は他の方法に比べて複雑なため、単純にファイルを再生するだけであれば他の方法を選択した方がよい。
しかし、より低次元での制御を行うため入出力デバイスの設定やレイテンシの確認などが可能。また、callbackでも記述できるため、比較的複雑な処理を行う際に適している。
install
pip install pyaudio
# condaでも可能
conda install pyaudio
usage
import pyaudio
import wave
import sys
chunk = 1024
wf = wave.open("sample.wav", "rb")
p = pyaudio.PyAudio()
stream = p.open(format=p.get_format_from_width(wf.getsampwidth()), channels=wf.getnchannels(), rate=wf.getframerate(), output=True)
data = wf.readframes(chunk)
while data != '':
stream.write(data)
data = wf.readframes(chunk)
stream.stop_stream()
stream.close()
p.terminate()
録音
オーディオ録音できるライブラリの一例
- python-sounddevice マイクから録音し、NumPyアレイとして保持する
- pyaudio マイクから録音し、バイナリとして保持する
python-sounddevice
usage
import sounddevice as sd
from scipy.io.wavfile import write
record_second = 3
fs = 44100
myrecording = sd.rec(int(record_second * fs), samplerate=fs, channels=2)
write('output.wav', fs, myrecording)
pyaudio
usage
import pyaudio
import wave
chunk = 1024
format = pyaudio.paInt16
channels = 2
fs = 44100
record_second = 3
p = pyaudio.PyAudio()
stream = p.open(format=format, channels=channels, rate=fs, input=True, frames_per_buffer=chunk)
print("* recording")
frames = []
for i in range(int(fs / chunk * record_second)):
data = stream.read(chunk)
frames.append(data)
print("* done recording")
stream.stop_stream()
stream.close()
p.terminate()
wf = wave.open("output.wav", "wb")
wf.setnchannels(channels)
wf.setsampwidth(p.get_sample_size(format))
wf.setframerate(fs)
wf.writeframes(b''.join(frames))
wf.close()
デバイス
再生/録音デバイスを指定したいことがあるので、各ライブラリでの変更方法を確認。
python-sounddevice
使用可能なデバイス、選択されているデバイスを表示
import sounddevice as sd
sd.query_devices()
ターミナル上で下記コマンドでも可能。
python -m sounddevice
デバイスIDを、default.device
に設定するか、play()
や Stream()
に device引数 として割り当てることで、デバイスの選択が可能
import sounddevice as sd
sd.default.device = 1, 5