Pythonのlibrosaライブラリは、音声データの分析・可視化・特徴量抽出を簡単に行える強力なツールです。この記事では、基本的な使い方から実践的な音声処理までを解説します。
音声処理ライブラリの比較
| ライブラリ | 用途 | 特徴 | インストール |
|---|---|---|---|
librosa | 音声分析・MIR | 特徴量抽出が豊富 | pip install librosa |
pydub | 音声編集 | フォーマット変換が簡単 | pip install pydub |
soundfile | 音声読み書き | 高速・多フォーマット対応 | pip install soundfile |
scipy.io.wavfile | WAV読み書き | 標準ライブラリ | 不要 |
pyaudio | リアルタイム処理 | ストリーミング対応 | pip install pyaudio |
librosaの主な機能
| 機能 | 関数 | 用途 |
|---|---|---|
| 音声読み込み | librosa.load() | 音声ファイルの読み込み |
| 波形表示 | librosa.display.waveshow() | 時間領域の可視化 |
| スペクトログラム | librosa.stft() | 周波数領域への変換 |
| メルスペクトログラム | librosa.feature.melspectrogram() | 人間の聴覚に基づく特徴量 |
| MFCC | librosa.feature.mfcc() | 音声認識の特徴量 |
| テンポ検出 | librosa.beat.beat_track() | BPMとビート位置の推定 |
| ピッチ検出 | librosa.pyin() | 基本周波数の推定 |
インストール
# librosaと可視化用ライブラリをインストール
pip install librosa matplotlib numpy
音声データの読み込み
import librosa
import librosa.display
import matplotlib.pyplot as plt
import numpy as np
# 音声ファイルを読み込む
audio_path = 'example.wav'
y, sr = librosa.load(audio_path, sr=None) # sr=Noneで元のサンプリングレートを維持
print(f"サンプルデータの長さ: {len(y)}")
print(f"サンプリングレート: {sr} Hz")
print(f"音声の長さ: {len(y) / sr:.2f} 秒")
# サンプリングレートを指定して読み込み(リサンプリング)
y_22k, sr_22k = librosa.load(audio_path, sr=22050) # 22.05kHzにリサンプリング
# 音声の一部のみ読み込み(offsetとdurationで指定)
y_partial, sr = librosa.load(audio_path, offset=1.0, duration=5.0) # 1秒目から5秒間
読み込みパラメータ
| パラメータ | 説明 | デフォルト値 |
|---|---|---|
sr | サンプリングレート | 22050 |
mono | モノラル変換 | True |
offset | 開始位置(秒) | 0.0 |
duration | 読み込み時間(秒) | None(全体) |
音声の可視化
波形の表示
import librosa
import librosa.display
import matplotlib.pyplot as plt
# 音声ファイルを読み込み
y, sr = librosa.load('example.wav')
# 波形を描画
plt.figure(figsize=(12, 4))
librosa.display.waveshow(y, sr=sr, alpha=0.8)
plt.title('Waveform')
plt.xlabel('Time (s)')
plt.ylabel('Amplitude')
plt.tight_layout()
plt.show()
# ステレオ音声の場合
y_stereo, sr = librosa.load('stereo.wav', mono=False)
fig, axes = plt.subplots(2, 1, figsize=(12, 6))
for i, channel in enumerate(['Left', 'Right']):
librosa.display.waveshow(y_stereo[i], sr=sr, ax=axes[i])
axes[i].set_title(f'{channel} Channel')
plt.tight_layout()
plt.show()
スペクトログラムの表示
import librosa
import librosa.display
import matplotlib.pyplot as plt
import numpy as np
y, sr = librosa.load('example.wav')
# 短時間フーリエ変換(STFT)
D = librosa.stft(y, n_fft=2048, hop_length=512)
# 振幅スペクトログラム(デシベル表示)
S_db = librosa.amplitude_to_db(np.abs(D), ref=np.max)
# スペクトログラムを描画
plt.figure(figsize=(12, 6))
librosa.display.specshow(S_db, sr=sr, hop_length=512, x_axis='time', y_axis='log')
plt.colorbar(format='%+2.0f dB')
plt.title('Spectrogram')
plt.tight_layout()
plt.show()
メルスペクトログラム
メルスペクトログラムは人間の聴覚特性に基づいた周波数スケールで、音声認識や音楽分類で広く使用されます。
import librosa
import librosa.display
import matplotlib.pyplot as plt
import numpy as np
y, sr = librosa.load('example.wav')
# メルスペクトログラムを計算
S = librosa.feature.melspectrogram(y=y, sr=sr, n_mels=128, fmax=8000)
# デシベル単位に変換
S_dB = librosa.power_to_db(S, ref=np.max)
# メルスペクトログラムを表示
plt.figure(figsize=(12, 6))
librosa.display.specshow(S_dB, sr=sr, x_axis='time', y_axis='mel', fmax=8000)
plt.colorbar(format='%+2.0f dB')
plt.title('Mel Spectrogram')
plt.tight_layout()
plt.show()
音声特徴量の抽出
MFCC(メル周波数ケプストラム係数)
MFCCは音声認識で最も広く使われる特徴量です。
import librosa
import librosa.display
import matplotlib.pyplot as plt
import numpy as np
y, sr = librosa.load('example.wav')
# MFCCを計算(13次元)
mfccs = librosa.feature.mfcc(y=y, sr=sr, n_mfcc=13)
print(f"MFCC shape: {mfccs.shape}") # (n_mfcc, time_frames)
# MFCCを可視化
plt.figure(figsize=(12, 6))
librosa.display.specshow(mfccs, sr=sr, x_axis='time')
plt.colorbar()
plt.title('MFCC')
plt.ylabel('MFCC Coefficients')
plt.tight_layout()
plt.show()
# デルタ(一次微分)とデルタデルタ(二次微分)も計算
mfcc_delta = librosa.feature.delta(mfccs)
mfcc_delta2 = librosa.feature.delta(mfccs, order=2)
# 特徴量を結合
features = np.vstack([mfccs, mfcc_delta, mfcc_delta2])
print(f"Combined features shape: {features.shape}") # (39, time_frames)
ゼロ交差率
ゼロ交差率は音声/無音声の判定やノイズ検出に有効です。
import librosa
import matplotlib.pyplot as plt
y, sr = librosa.load('example.wav')
# ゼロ交差率を計算
zcr = librosa.feature.zero_crossing_rate(y)
# フレームごとの時間軸を作成
times = librosa.times_like(zcr, sr=sr)
# 可視化
fig, axes = plt.subplots(2, 1, figsize=(12, 6))
# 波形
librosa.display.waveshow(y, sr=sr, ax=axes[0])
axes[0].set_title('Waveform')
# ゼロ交差率
axes[1].plot(times, zcr[0], color='green')
axes[1].set_title('Zero Crossing Rate')
axes[1].set_xlabel('Time (s)')
axes[1].set_ylabel('Rate')
plt.tight_layout()
plt.show()
スペクトル特徴量
import librosa
import numpy as np
y, sr = librosa.load('example.wav')
# スペクトル重心(音の明るさ)
spectral_centroids = librosa.feature.spectral_centroid(y=y, sr=sr)
# スペクトル帯域幅
spectral_bandwidth = librosa.feature.spectral_bandwidth(y=y, sr=sr)
# スペクトルロールオフ(エネルギーの95%が含まれる周波数)
spectral_rolloff = librosa.feature.spectral_rolloff(y=y, sr=sr)
# スペクトルコントラスト
spectral_contrast = librosa.feature.spectral_contrast(y=y, sr=sr)
# RMS(Root Mean Square)エネルギー
rms = librosa.feature.rms(y=y)
print(f"Spectral Centroid shape: {spectral_centroids.shape}")
print(f"RMS shape: {rms.shape}")
テンポとビートの検出
import librosa
import librosa.display
import matplotlib.pyplot as plt
y, sr = librosa.load('music.wav')
# テンポとビート位置を検出
tempo, beat_frames = librosa.beat.beat_track(y=y, sr=sr)
print(f"推定テンポ: {tempo:.1f} BPM")
# ビートフレームを時間に変換
beat_times = librosa.frames_to_time(beat_frames, sr=sr)
# 波形とビート位置を可視化
plt.figure(figsize=(12, 4))
librosa.display.waveshow(y, sr=sr, alpha=0.6)
plt.vlines(beat_times, -1, 1, color='r', alpha=0.7, linestyle='--', label='Beats')
plt.title(f'Waveform with Beats (Tempo: {tempo:.1f} BPM)')
plt.legend()
plt.tight_layout()
plt.show()
# オンセット検出(音の立ち上がり)
onset_frames = librosa.onset.onset_detect(y=y, sr=sr)
onset_times = librosa.frames_to_time(onset_frames, sr=sr)
ピッチ検出
import librosa
import matplotlib.pyplot as plt
import numpy as np
y, sr = librosa.load('vocal.wav')
# pYINアルゴリズムでピッチを検出
f0, voiced_flag, voiced_probs = librosa.pyin(
y,
fmin=librosa.note_to_hz('C2'), # 最低周波数
fmax=librosa.note_to_hz('C7'), # 最高周波数
sr=sr
)
# 時間軸を作成
times = librosa.times_like(f0, sr=sr)
# ピッチを可視化
fig, axes = plt.subplots(2, 1, figsize=(12, 8))
# 波形
librosa.display.waveshow(y, sr=sr, ax=axes[0])
axes[0].set_title('Waveform')
# ピッチ曲線
axes[1].plot(times, f0, color='blue', linewidth=1)
axes[1].set_title('Pitch (F0)')
axes[1].set_xlabel('Time (s)')
axes[1].set_ylabel('Frequency (Hz)')
axes[1].set_ylim([0, 500])
plt.tight_layout()
plt.show()
# 音名に変換
notes = librosa.hz_to_note(f0[~np.isnan(f0)])
print(f"検出された音名(一部): {notes[:10]}")
音声の変換
ピッチシフト
import librosa
import soundfile as sf
y, sr = librosa.load('example.wav')
# ピッチを2半音上げる
y_shifted_up = librosa.effects.pitch_shift(y=y, sr=sr, n_steps=2)
# ピッチを3半音下げる
y_shifted_down = librosa.effects.pitch_shift(y=y, sr=sr, n_steps=-3)
# 保存
sf.write('pitch_up.wav', y_shifted_up, sr)
sf.write('pitch_down.wav', y_shifted_down, sr)
タイムストレッチ
import librosa
import soundfile as sf
y, sr = librosa.load('example.wav')
# 1.5倍速(ピッチを変えずに速度を上げる)
y_fast = librosa.effects.time_stretch(y=y, rate=1.5)
# 0.75倍速(スロー再生)
y_slow = librosa.effects.time_stretch(y=y, rate=0.75)
# 保存
sf.write('fast.wav', y_fast, sr)
sf.write('slow.wav', y_slow, sr)
ハーモニック・パーカッシブ分離
import librosa
import soundfile as sf
y, sr = librosa.load('music.wav')
# ハーモニック成分とパーカッシブ成分に分離
y_harmonic, y_percussive = librosa.effects.hpss(y)
# それぞれを保存
sf.write('harmonic.wav', y_harmonic, sr)
sf.write('percussive.wav', y_percussive, sr)
実践的な例
音声ファイルの特徴量抽出パイプライン
import librosa
import numpy as np
from typing import Dict, Any
def extract_features(file_path: str) -> Dict[str, Any]:
"""音声ファイルから特徴量を抽出"""
# 音声を読み込み
y, sr = librosa.load(file_path, sr=22050)
# 基本情報
duration = len(y) / sr
# MFCC(平均と標準偏差)
mfccs = librosa.feature.mfcc(y=y, sr=sr, n_mfcc=13)
mfcc_mean = np.mean(mfccs, axis=1)
mfcc_std = np.std(mfccs, axis=1)
# スペクトル特徴量
spectral_centroid = np.mean(librosa.feature.spectral_centroid(y=y, sr=sr))
spectral_bandwidth = np.mean(librosa.feature.spectral_bandwidth(y=y, sr=sr))
spectral_rolloff = np.mean(librosa.feature.spectral_rolloff(y=y, sr=sr))
# ゼロ交差率
zcr = np.mean(librosa.feature.zero_crossing_rate(y))
# RMSエネルギー
rms = np.mean(librosa.feature.rms(y=y))
# テンポ
tempo, _ = librosa.beat.beat_track(y=y, sr=sr)
return {
'duration': duration,
'tempo': tempo,
'mfcc_mean': mfcc_mean,
'mfcc_std': mfcc_std,
'spectral_centroid': spectral_centroid,
'spectral_bandwidth': spectral_bandwidth,
'spectral_rolloff': spectral_rolloff,
'zero_crossing_rate': zcr,
'rms_energy': rms
}
# 使用例
features = extract_features('example.wav')
print(f"Duration: {features['duration']:.2f}s")
print(f"Tempo: {features['tempo']:.1f} BPM")
print(f"Spectral Centroid: {features['spectral_centroid']:.2f} Hz")
音声の類似度計算
import librosa
import numpy as np
from scipy.spatial.distance import cosine
def compute_audio_similarity(file1: str, file2: str) -> float:
"""2つの音声ファイルの類似度を計算(0-1、1が最も類似)"""
# 両方の音声を読み込み
y1, sr1 = librosa.load(file1, sr=22050)
y2, sr2 = librosa.load(file2, sr=22050)
# MFCCを計算
mfcc1 = librosa.feature.mfcc(y=y1, sr=sr1, n_mfcc=13)
mfcc2 = librosa.feature.mfcc(y=y2, sr=sr2, n_mfcc=13)
# 平均を取って特徴ベクトルに
feat1 = np.mean(mfcc1, axis=1)
feat2 = np.mean(mfcc2, axis=1)
# コサイン類似度を計算
similarity = 1 - cosine(feat1, feat2)
return similarity
# 使用例
similarity = compute_audio_similarity('audio1.wav', 'audio2.wav')
print(f"類似度: {similarity:.4f}")
よくあるエラーと対処法
import librosa
# FileNotFoundError: 音声ファイルが見つからない
# 対処: パスを確認し、絶対パスを使用
import os
audio_path = os.path.abspath('example.wav')
if os.path.exists(audio_path):
y, sr = librosa.load(audio_path)
# audioreadのエラー: 対応していないフォーマット
# 対処: ffmpegをインストール
# pip install ffmpeg-python
# または: conda install -c conda-forge ffmpeg
# メモリエラー: 長い音声ファイル
# 対処: 分割して処理
def process_long_audio(file_path: str, chunk_duration: float = 30.0):
"""長い音声を分割して処理"""
duration = librosa.get_duration(path=file_path)
results = []
for offset in np.arange(0, duration, chunk_duration):
y, sr = librosa.load(file_path, offset=offset, duration=chunk_duration)
# 各チャンクを処理
features = librosa.feature.mfcc(y=y, sr=sr)
results.append(features)
return results
まとめ
| 用途 | 推奨関数 |
|---|---|
| 音声読み込み | librosa.load() |
| 波形表示 | librosa.display.waveshow() |
| スペクトログラム | librosa.stft() + specshow() |
| 音声認識の特徴量 | librosa.feature.mfcc() |
| テンポ検出 | librosa.beat.beat_track() |
| ピッチ検出 | librosa.pyin() |
| 音声変換 | librosa.effects.* |
librosaを使うことで、音声データの分析から特徴量抽出、可視化まで幅広い処理が可能です。音声認識、音楽情報検索、音声合成などの応用に活用できます。