LoginSignup
86
79

More than 3 years have passed since last update.

Pythonでサウンドを扱う

Last updated at Posted at 2020-02-11

Pythonでサウンドを扱う

Pythonでサウンドを扱う方法がいろいろあってよくわからなかったので、ざっくりまとめ

基本的にはこちらのサイト Playing and Recording Sound in Python を参考にした。

再生

オーディオ再生するライブラリの一例

  • playsound WAVとMP3ファイルを再生するためだけの簡単なパッケージ
  • simpleaudio WAVファイルとNumPyアレイを再生できるライブラリ
  • winsound WAVファイルとビープ音を再生できる、Windows用ライブラリ
  • python-sounddevicepyaudio 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()

実行例
b985e173.png

ターミナル上で下記コマンドでも可能。

python -m sounddevice

デバイスIDを、default.device に設定するか、play()Stream() に device引数 として割り当てることで、デバイスの選択が可能

import sounddevice as sd
sd.default.device = 1, 5
86
79
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
86
79