はじめに
the cabs のライブ、申し込みすら叶わなかったその悔しさを胸に、Pythonで音を分析してみました。この記事では、信号処理による解析の過程と結果をお届けします。
参考リンクまとめ
使う曲
the cabsの『2月の兵隊』は、私が浪人生活を共に過ごした曲です。
(ハヌマーンの猿の学生と共にずっと聴いてました笑笑)
Pythonコード
YouTubeの音楽動画から音声をMP3形式で抽出し、波形やスペクトログラムによって可視化を行った後、テンポ(BPM)の推定、MFCCに基づく構造クラスタリング、ピッチ推定、そしてスペクトル重心やRMSに基づいた感情スコア(焦燥感・浮遊感)の算出までを一貫して行います。
# 完全統合版:YouTube → MP3 → 可視化 → テンポ解析 → 構造解析 → ピッチ/感情マッピング
# --- Step 1: ライブラリのインストール(Colab再起動後用) ---
!pip install yt-dlp pydub librosa scikit-learn --quiet
!apt install ffmpeg -y
# --- Step 2: YouTubeからMP3をダウンロード ---
import yt_dlp
import os
from pydub import AudioSegment
# ダウンロードするYouTube動画のURL
url = "https://www.youtube.com/watch?v=soLFVWKc5B4" # 任意のYouTube動画URL
# 出力パス設定
output_path = "downloaded_audio.%(ext)s"
# yt-dlpの設定オプション
ydl_opts = {
'format': 'bestaudio/best', # 最も良い音質を選択
'outtmpl': output_path, # 出力ファイル名設定
'postprocessors': [{
'key': 'FFmpegExtractAudio', # MP3形式に変換
'preferredcodec': 'mp3', # MP3形式で保存
'preferredquality': '192', # 音質設定
}],
'quiet': True # 出力を抑制
}
# YouTubeから音声をダウンロードしてMP3に変換
with yt_dlp.YoutubeDL(ydl_opts) as ydl:
ydl.download([url])
# ダウンロードしたファイルの名前を変更
os.rename("downloaded_audio.mp3", "audio.mp3")
print("MP3変換完了") # 成功メッセージ
# --- Step 3: 音声読み込みと可視化 ---
import librosa
import librosa.display
import matplotlib.pyplot as plt
import numpy as np
# 音声ファイルを読み込み(サンプルレートは元のまま)
y, sr = librosa.load("audio.mp3", sr=None)
# 波形表示
plt.figure(figsize=(12, 3))
librosa.display.waveshow(y, sr=sr) # 波形の可視化
plt.title("Waveform") # タイトル
plt.xlabel("Time (s)") # X軸ラベル
plt.ylabel("Amplitude") # Y軸ラベル
plt.grid(True) # グリッド表示
plt.show() # 表示
# スペクトログラムの表示
plt.figure(figsize=(12, 4))
D = librosa.amplitude_to_db(np.abs(librosa.stft(y)), ref=np.max) # スペクトルのdB表示
librosa.display.specshow(D, sr=sr, x_axis='time', y_axis='log') # スペクトログラムの可視化
plt.colorbar(format='%+2.0f dB') # カラーバー表示
plt.title("Spectrogram")
plt.tight_layout() # レイアウト調整
plt.show()
# --- Step 4: テンポ解析 ---
tempo, beat_frames = librosa.beat.beat_track(y=y, sr=sr) # テンポと拍の位置を抽出
print(f" 推定テンポ: {float(tempo):.2f} BPM") # 推定されたBPM(ビート/分)
# --- Step 5: 拍ごとの構造解析 + ピッチ + 感情指標 ---
from scipy.cluster.hierarchy import linkage, fcluster
from sklearn.preprocessing import StandardScaler
from scipy.spatial.distance import cdist
# MFCC(メル周波数ケプストラム係数)の抽出と標準化
mfcc = librosa.feature.mfcc(y=y, sr=sr, n_mfcc=13) # MFCCを13次元で抽出
mfcc_scaled = StandardScaler().fit_transform(mfcc.T) # 標準化
# 階層クラスタリングによる楽曲の構造推定
Z = linkage(mfcc_scaled, method='ward') # クラスタリング
clusters = fcluster(Z, t=4, criterion='maxclust') # 4つのセクションに分ける
# ピッチの推定
pitches, magnitudes = librosa.piptrack(y=y, sr=sr) # ピッチとその強度を抽出
pitch_values = pitches[magnitudes > np.median(magnitudes)] # 強度が中央値以上のピッチを取得
pitch_mean = np.mean(pitch_values) if len(pitch_values) > 0 else 0 # 平均ピッチを計算
# 感情スコア指標計算
centroid = librosa.feature.spectral_centroid(y=y, sr=sr)[0] # スペクトル重心
rms = librosa.feature.rms(y=y)[0] # RMS(Root Mean Square)
# 感情スコアの計算
emotion_score = {
"焦燥感 (agitation)": float(tempo) * np.mean(centroid) * np.mean(rms), # 焦燥感の計算
"浮遊感 (floating)": (1.0 / (1 + np.mean(centroid))) * (1.0 / (1 + np.std(rms))) # 浮遊感の計算
}
# 楽曲構造の可視化(クラスタごとに色分け)
plt.figure(figsize=(12, 2))
plt.plot(clusters, color='purple') # クラスタの表示
plt.title("Estimated Song Structure Segments") # タイトル
plt.xlabel("Frame Index") # X軸ラベル
plt.ylabel("Section Cluster") # Y軸ラベル
plt.grid(True) # グリッド表示
plt.tight_layout() # レイアウト調整
plt.show()
# 感情スコアをDataFrame化して表示
import pandas as pd
emotion_df = pd.DataFrame.from_dict(emotion_score, orient='index', columns=["Score"]) # DataFrameに変換
emotion_df.index.name = "Emotion" # インデックス名設定
# 感情スコアを表形式で表示
from IPython.display import display
display(emotion_df) # 表形式で表示
結果
曲の解析レポート
① 波形(Waveform)
- 時間軸(x軸):0秒〜約2分40秒
- 振幅(y軸):-1.0〜+1.0 の範囲
-
特徴:
- 冒頭と終盤に数回、無音(または静音)部分が確認できます(振幅が急激に0近くになる)。
- 全体としてダイナミックレンジ(音量の強弱差)が狭い=マスタリングされている可能性が高い。
- 波形がほぼフラットに近い → 圧縮された音像(音圧の高いEDMやポップ系に多い)。
② スペクトログラム(Spectrogram)
- x軸:時間(秒)
- y軸:周波数(0Hz〜16kHz超)
- 色:明るい=音が強い(+0 dB)、暗い=音が弱い(-80 dB)
-
特徴:
- 64〜512 Hz付近が特に強く、安定的 → 低音(ベースやキック)が中心。
- その上(1kHz〜8kHz)も中〜高域が活発 → ボーカルやシンセ、ハイハットの存在。
- 無音区間(黒く抜けた帯)が数箇所ある → 曲のブレイクまたは展開の切り替え部分。
- 周波数成分が常に満遍なく存在しており、音の密度が高い。
③ 構造セグメント(Estimated Song Structure Segments)
- x軸:フレーム番号(≒時間)
- y軸:クラスタ(1〜4のセクション番号)
-
特徴:
- 曲全体を4つのセクションに分類(クラスタリング)。
- セクションの切り替えが多く、繰り返しも見られる → リフレイン構造あり(例:サビの再登場)。
- 12500〜13000付近の連続したクラスタ3〜4は、印象的な展開(ブリッジや間奏など)を示唆。
- 最終的にはクラスタ2で終わっている → 導入と同じセクションに戻るパターンの可能性。
総合評価と推定ジャンル
項目 | 推定内容 |
---|---|
テンポ感 | 速め(おそらく160〜180 BPM) |
音圧 | 非常に高い(圧縮強め) |
構成 | セクションが多く、展開に富む |
ジャンル傾向 | EDM・アニメOP・J-pop・ロック系にも該当し得る |
感情表現 | 焦燥感・推進力・高揚感が強い |