Pythonで音声を扱いたいときに便利なのが PyAudio ライブラリです。
PyAudioを使うと、マイクからの入力を録音したり、音声データを再生したり、リアルタイムで処理したりできます。
本記事では、インストール方法から基礎的な使い方、サンプルコード、高度な設定例、最後に演習問題とその解答例まで幅広く解説します。初心者の方にもわかりやすいように、順を追って丁寧に説明していきます。
PyAudioとは
PyAudioは、PortAudioというC言語ベースのクロスプラットフォーム音声入出力ライブラリのPythonバインディングです。
Windows、macOS、Linuxで動作し、数行のコードで音声のキャプチャや再生を実現できます。
- クロスプラットフォーム対応
- リアルタイム処理が可能
- 比較的シンプルなAPI
インストール方法
PyAudioを使うには、まずPortAudio本体とPyAudioパッケージをインストールします。以下の手順を参考にしてください。
PortAudioのインストール
Windows
公式サイトからバイナリを取得するか、conda install portaudio
macOS
brew install portaudio
Linux(Ubuntuなど)
sudo apt-get update sudo apt-get install portaudio19-dev
PyAudioのインストール
pip install pyaudio
基本的な録音・再生の流れ
PyAudioで音声を扱う場合、以下の3ステップが基本です。
- ストリームの作成
音声入出力の設定(サンプリングレート、チャネル数、フォーマットなど) - ストリームの開始と読み書き
stream.read() で録音、stream.write() で再生 - ストリームの終了・解放
stream.stop_stream() → stream.close() → p.terminate()
サンプルコード:録音→保存→再生
以下の例は、マイクから音声を2秒間録音し、WAVファイルに保存、その後再生を行うシンプルなコードです。
import pyaudio
import wave
# 録音設定
FORMAT = pyaudio.paInt16 # 16ビット整数
CHANNELS = 1 # モノラル
RATE = 44100 # サンプリングレート
CHUNK = 1024 # フレームサイズ
RECORD_SECONDS = 2 # 録音時間
WAVE_OUTPUT_FILENAME = "output.wav"
# PyAudioオブジェクト生成
p = pyaudio.PyAudio()
# 録音用ストリーム開始
stream = p.open(format=FORMAT,
channels=CHANNELS,
rate=RATE,
input=True,
frames_per_buffer=CHUNK)
print("Recording...")
frames = []
for _ in range(int(RATE / CHUNK * RECORD_SECONDS)):
data = stream.read(CHUNK)
frames.append(data)
print("Finished recording.")
# ストリーム停止・解放
stream.stop_stream()
stream.close()
p.terminate()
# WAVファイルに保存
wf = wave.open(WAVE_OUTPUT_FILENAME, 'wb')
wf.setnchannels(CHANNELS)
wf.setsampwidth(p.get_sample_size(FORMAT))
wf.setframerate(RATE)
wf.writeframes(b''.join(frames))
wf.close()
# 再生
wf = wave.open(WAVE_OUTPUT_FILENAME, 'rb')
p = pyaudio.PyAudio()
stream = p.open(format=p.get_format_from_width(wf.getsampwidth()),
channels=wf.getnchannels(),
rate=wf.getframerate(),
output=True)
print("Playing back...")
data = wf.readframes(CHUNK)
while data:
stream.write(data)
data = wf.readframes(CHUNK)
stream.stop_stream()
stream.close()
p.terminate()
print("Done.")
open() メソッドで指定できる主なストリームプロパティについて
よく使うものを中心に詳しく解説します。
プロパティ名 | 型/値の例 | 説明 |
---|---|---|
format | pyaudio.paInt16 pyaudio.paFloat32 など | 音声データのサンプル形式(フォーマット)を指定します。 – paInt16:16 ビット符号付き整数(最も一般的) – paInt24:24 ビット整数 – paInt32:32 ビット整数 – paFloat32:32 ビット浮動小数点 – paUInt8:8 ビット符号なし整数 |
channels | 1(モノラル) 2(ステレオ) | オーディオチャンネル数を指定します。 – 1:モノラル – 2:ステレオ 複数チャンネル(サラウンド音声など)を扱いたい場合は、さらに大きな値も可能です。 |
rate | 44100 16000 | サンプリングレート(Hz 単位)を指定します。 – 44100:CD 品質 – 48000:プロ向けオーディオ品質 – 8000~16000:音声通話品質 |
frames_per_buffer | 1024 2048 | バッファあたりのフレーム数(読み書き単位のサイズ)を指定します。 小さくするとリアルタイム性が向上する反面、CPU 負荷が増加します。 |
input | True/False | 入力(録音)ストリームとして開くかどうかを指定します。True を指定するとマイクなどから音声を読み取れるようになります。 |
output | True/False | 出力(再生)ストリームとして開くかどうかを指定します。True を指定するとスピーカーなどへ音声を書き込めるようになります。 |
input_device_index | 0, 1, … | 利用する入力デバイス(マイク)のインデックス番号を指定します。 複数のオーディオデバイスがある場合に、pyaudio.PyAudio().get_device_info_by_index(i) で一覧を取得して設定します。 |
output_device_index | 0, 1, … | 利用する出力デバイス(スピーカー)のインデックス番号を指定します。 |
stream_callback | callback 関数 | 非同期・コールバック方式でストリームを動かす場合に、データ処理用のコールバック関数を指定します。 |
start/stop | 内部メソッド | ストリームの開始・停止を行うメソッドです。stream.start_stream()、stream.stop_stream() を呼んで制御します。 |
各プロパティの選び方ガイド
format
- 一般的な音声録音/再生は paInt16 で十分。
- 高精度・科学用途なら paFloat32、軽量・音声通話なら paUInt8 や低レートフォーマットも検討。
channels
ステレオ音声を扱いたい場合は必ず 2。モノラルでよければ 1 を指定して処理量を抑えましょう。
rate
音楽用途は 44100 Hz、動画用途は 48000 Hz、通話用途は 8000~16000 Hz が目安です。
frames_per_buffer
1024~2048 あたりがバランス良く、リアルタイム処理・遅延が気になるなら 512 以下に。
デバイスインデックス
環境依存エラーを避けるため、明示的にインデックス指定しておくと堅牢です。
# 例
p = pyaudio.PyAudio()
for i in range(p.get_device_count()):
info = p.get_device_info_by_index(i)
print(i, info['name'], '(入力)' if info['maxInputChannels'] > 0 else '')
ストリームの詳細設定
非同期コールバック方式
大きなバッファを用意せず、イベント駆動でリアルタイム処理したい場合には、コールバック方式を使います。
import pyaudio
def callback(in_data, frame_count, time_info, status):
# ここでin_dataを加工可能
return (in_data, pyaudio.paContinue)
p = pyaudio.PyAudio()
stream = p.open(format=pyaudio.paInt16,
channels=1,
rate=44100,
input=True,
frames_per_buffer=1024,
stream_callback=callback)
stream.start_stream()
# 5秒間待機
import time; time.sleep(5)
stream.stop_stream()
stream.close()
p.terminate()
トラブルシューティング
webrtcvad.Error: Error while processing frame
ほとんどの場合「VAD に渡している音声バッファの長さ(またはフォーマット)が正しくない」ことが原因です。
WebRTC VAD が受け付けるオーディオは以下の条件に厳密に合致している必要があります。
- フレーム長:10 ms、20 ms、または 30 ms
- サンプリングレート:8 kHz、16 kHz、32 kHz、または 48 kHz
- フォーマット:モノラルの 16bit PCM
例えば 16 kHz、30 ms の場合、必要なバッファサイズは以下になります。
サンプル数 = RATE × (フレーム長 [ms] / 1000)
- RATE = 16000
- フレーム長 = 30 ms
- サンプル数 = 16000 × 30/1000 = 480 samples
→ frames_per_buffer=480 にする必要があります。
OSError: [Errno -9996] Invalid output device (no default output device)
出力デバイスが見つからない。p.get_device_count() や p.get_device_info_by_index() で確認。
録音時のノイズや遅延
frames_per_buffer の値を小さくすると遅延は減るが、CPU負荷は上がる。
インストール時のビルドエラー(特にWindows)
公式のホイールファイルを利用するか、Visual Studio Build Toolsが必要。
演習問題
以下の課題に挑戦してみましょう。
- ステレオ録音
モノラルではなくステレオ(2チャンネル)で3秒間録音し、stereo.wav に保存してください。 - 音声の正規化
録音した音声の振幅を最大限に引き上げる正規化処理を実装し、正規化後のWAVを出力してください。 - リアルタイム音声反響エフェクト
コールバック方式を使い、入力音声に簡単なエコー(反響)効果をリアルタイムで付加して再生してください。
演習問題の解答例
1. ステレオ録音
import pyaudio
import wave
FORMAT = pyaudio.paInt16
CHANNELS = 2 # ステレオ
RATE = 44100
CHUNK = 1024
RECORD_SECONDS = 3
WAVE_OUTPUT_FILENAME = "stereo.wav"
p = pyaudio.PyAudio()
stream = p.open(format=FORMAT,
channels=CHANNELS,
rate=RATE,
input=True,
frames_per_buffer=CHUNK)
frames = []
for _ in range(int(RATE / CHUNK * RECORD_SECONDS)):
data = stream.read(CHUNK)
frames.append(data)
stream.stop_stream()
stream.close()
p.terminate()
wf = wave.open(WAVE_OUTPUT_FILENAME, 'wb')
wf.setnchannels(CHANNELS)
wf.setsampwidth(p.get_sample_size(FORMAT))
wf.setframerate(RATE)
wf.writeframes(b''.join(frames))
wf.close()
2. 音声の正規化
import wave
import struct
# 読み込み
wf = wave.open('output.wav', 'rb')
frames = wf.readframes(wf.getnframes())
wf.close()
# 16ビットPCMを整数列に変換
samples = struct.unpack('<' + 'h'*(len(frames)//2), frames)
max_amp = max(abs(s) for s in samples)
factor = 32767 / max_amp # 正規化係数
# 正規化
normalized = [int(s * factor) for s in samples]
normalized_frames = struct.pack('<' + 'h'*len(normalized), *normalized)
# 書き出し
wf = wave.open('normalized.wav', 'wb')
wf.setnchannels(1)
wf.setsampwidth(2)
wf.setframerate(44100)
wf.writeframes(normalized_frames)
wf.close()
3. リアルタイム音声反響エフェクト
import pyaudio
from collections import deque
FORMAT = pyaudio.paInt16
CHANNELS = 1
RATE = 44100
CHUNK = 1024
DELAY_CHUNKS = 5 # 約(1024/RATE)*5 秒の遅延
delay_buffer = deque([b'\x00' * CHUNK * 2] * DELAY_CHUNKS, maxlen=DELAY_CHUNKS)
def callback(in_data, frame_count, time_info, status):
# 古いデータを取得
echo_data = delay_buffer[0]
# 新しいデータをバッファに追加
delay_buffer.append(in_data)
# ミックスして返す(音量調整に注意)
mixed = bytearray(len(in_data))
for i in range(0, len(in_data), 2):
orig = struct.unpack_from('<h', in_data, i)[0]
echo = struct.unpack_from('<h', echo_data, i)[0]
val = int(orig * 0.8 + echo * 0.2)
struct.pack_into('<h', mixed, i, max(min(val, 32767), -32768))
return (bytes(mixed), pyaudio.paContinue)
p = pyaudio.PyAudio()
stream = p.open(format=FORMAT,
channels=CHANNELS,
rate=RATE,
input=True,
output=True,
frames_per_buffer=CHUNK,
stream_callback=callback)
stream.start_stream()
import time; time.sleep(5)
stream.stop_stream()
stream.close()
p.terminate()
以上がPythonのPyAudioライブラリを使った音声処理の入門ガイドです。
基礎から実践までを一通り学習し、演習問題で手を動かして理解を深めてみてください。
音声処理の世界は奥が深く、リアルタイム分析や音声認識、機械学習との組み合わせなど、応用範囲は無限大です。ぜひ次のステップとして、より高度なアルゴリズムやライブラリに挑戦してみましょう!