2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

YouTube音楽音声をMP3に変換し、Pythonを用いてLLMで分析

Last updated at Posted at 2025-06-14

目的

YouTube動画から音声を抽出し、MP3/WAV形式に変換した上で、音響的特徴(ピッチ、スペクトルエントロピー、テンポ、ピークなど)を計算し、それらの特徴量をLLM(大規模言語モデル)に入力して生成的・意味的な解析を行う。Google Colab上で処理・解析を実行する。


🧾 スクリプトの構成と処理フロー

✅ ライブラリのインストール / Install required libraries

!pip install -U yt-dlp librosa==0.10.1 numpy==1.24.4 pydub matplotlib scipy soundfile ffmpeg-python
  • 目的:すべての必要な音声処理・可視化ライブラリをGoogle Colabなどにインストール
  • yt-dlp: YouTube動画のダウンロード
  • librosa: 音声処理(ピッチ・テンポ・スペクトル等)
  • pydub: MP3 ⇄ WAV 変換
  • matplotlib: グラフ可視化
  • numpy, scipy: 数値・信号処理
  • soundfile: WAVの保存処理

✅ パラメータ定義 / Define parameters

url = 'https://www.youtube.com/watch?v=-tg6WdgiDm8'
mp3_path = 'audio.mp3'
wav_path = 'audio.wav'
sr = 22050
frame_length = 2048
hop_length = 512
peak_threshold = 0.05
  • 音声処理に必要な基本設定(サンプリングレート、フレーム長など)
  • peak_threshold音量ピーク検出のしきい値(0.05以上をピークとみなす)

✅ YouTube音声をダウンロード / Download YouTube audio

subprocess.run([...])
  • yt-dlp を使って 音声ストリームのみをMP3で保存
  • 自動で変換とファイル名指定が可能

✅ MP3 → WAV変換 / Convert to WAV

AudioSegment.from_file(mp3_path).export(wav_path, format='wav')
  • librosa はWAV形式を推奨するため、MP3をWAVに変換して次処理へ

✅ 音声読み込み / Load audio

y, _ = librosa.load(wav_path, sr=sr)
  • WAVファイルを NumPy配列(y)として読み込み
  • y: 音圧(-1.0〜1.0)の1次元信号列

✅ ピッチ抽出 / Extract pitch

f0, _, _ = librosa.pyin(...)
  • pyin アルゴリズムで 時間変化する基本周波数(F0)を抽出
  • 有声部のみ数値、無声音は NaN

✅ エントロピー計算 / Spectral entropy

S = np.abs(librosa.stft(...))**2
entropy = -np.sum(S * np.log2(S + 1e-10), axis=0)
  • STFTスペクトルから 情報量(意外性)を時系列で計算
  • 雑音や変化が大きいほどエントロピーも高い傾向

✅ 音源分離 / Source separation

harmonic, percussive = librosa.effects.hpss(y)
  • 音声を 旋律成分(harmonic)とリズム成分(percussive)に分解
  • それぞれを .wav で保存 → ボーカル抽出やBPM分析に有効

✅ テンポ推定 / Tempo estimation

tempo, beats = librosa.beat.beat_track(...)
  • percussive 成分からテンポ(BPM)を推定
  • beats はビート(拍)の時系列インデックス列

✅ 音量ピーク検出 / Volume peak detection

envelope = np.abs(y)
peak_times = np.where(envelope > peak_threshold)[0] / sr
  • 波形の絶対値が閾値を超えた箇所を「音量ピーク」として抽出
  • peak_times はその時間情報(秒)

✅ ピークの間引き(可視化用) / Downsampling for plotting

max_peaks_to_plot = 1000
  • 描画過多防止のため、ピークは最大1000点にサンプリングして表示

✅ 可視化(統合プロット)/ Unified visualization

  • 3つのグラフを1枚の画像にまとめて保存:
グラフ位置 内容
上段 スペクトログラム(周波数 × 時間 × 音圧)
中段 波形+間引きされた音量ピーク
下段 FFT(周波数成分の強度分布)
plt.savefig('analysis_with_tempo.png')

✅ 最終出力(統計)/ Summary

print(f"Pitch Mean ...")
  • 再生時間、ピッチ統計、エントロピー、ピーク数、テンポ(BPM)を表示
  • 音楽・音声解析の基礎指標がすべて数値化

Google Colabに貼り付けるPythonコード

使う曲

image.png

# Program Name: youtube_audio_analysis_with_tempo.py
# Creation Date: 20250614
# Overview: Download audio, convert to WAV, analyze pitch, entropy, FFT, volume peaks, tempo, and plot results
# Usage: Run in Google Colab or local Python environment

# ------------------------
# ライブラリのインストール / Install required libraries
# ------------------------
!pip install -U yt-dlp librosa==0.10.1 numpy==1.24.4 pydub matplotlib scipy soundfile ffmpeg-python

# ------------------------
# パラメータ定義 / Define parameters
# ------------------------
url = 'https://www.youtube.com/watch?v=-tg6WdgiDm8'
mp3_path = 'audio.mp3'
wav_path = 'audio.wav'
sr = 22050
frame_length = 2048
hop_length = 512
peak_threshold = 0.05

# ------------------------
# YouTube音声ダウンロード / Download YouTube audio
# ------------------------
import subprocess
subprocess.run(['yt-dlp', '-x', '--audio-format', 'mp3', '-o', mp3_path, url], check=True)

# ------------------------
# MP3 → WAV変換 / Convert to WAV
# ------------------------
from pydub import AudioSegment
AudioSegment.from_file(mp3_path).export(wav_path, format='wav')

# ------------------------
# ライブラリ読み込み / Import libraries
# ------------------------
import librosa
import librosa.display
import matplotlib.pyplot as plt
import numpy as np
import soundfile as sf

# ------------------------
# 音声読み込み / Load audio
# ------------------------
y, _ = librosa.load(wav_path, sr=sr)

# ------------------------
# ピッチ抽出 / Extract pitch
# ------------------------
f0, _, _ = librosa.pyin(
    y, fmin=librosa.note_to_hz('C2'), fmax=librosa.note_to_hz('C7'),
    sr=sr, frame_length=frame_length, hop_length=hop_length
)

# ------------------------
# エントロピー計算 / Spectral entropy
# ------------------------
S = np.abs(librosa.stft(y, n_fft=frame_length, hop_length=hop_length)) ** 2
entropy = -np.sum(S * np.log2(S + 1e-10), axis=0)

# ------------------------
# 音源分離 / Source separation
# ------------------------
harmonic, percussive = librosa.effects.hpss(y)
sf.write('harmonic.wav', harmonic, sr)
sf.write('percussive.wav', percussive, sr)

# ------------------------
# テンポ推定 / Tempo estimation
# ------------------------
tempo, beats = librosa.beat.beat_track(y=percussive, sr=sr, hop_length=hop_length)
print(f"⏱ Estimated Tempo: {tempo:.2f} BPM")
print(f"🟰 Beat Count: {len(beats)}")

# ------------------------
# 音量ピーク検出 / Volume peak detection
# ------------------------
envelope = np.abs(y)
peak_times = np.where(envelope > peak_threshold)[0] / sr

# ------------------------
# ピーク描画用に間引き / Downsample peak data for visualization
max_peaks_to_plot = 1000
if len(peak_times) > max_peaks_to_plot:
    idx = np.linspace(0, len(peak_times) - 1, max_peaks_to_plot).astype(int)
    peak_times_vis = peak_times[idx]
else:
    peak_times_vis = peak_times

# ------------------------
# 可視化 / Unified plot
# ------------------------
fig, axs = plt.subplots(3, 1, figsize=(12, 9), dpi=100)

# 1. Spectrogram
img = librosa.display.specshow(librosa.amplitude_to_db(S, ref=np.max),
                               sr=sr, hop_length=hop_length,
                               x_axis='time', y_axis='log', ax=axs[0])
axs[0].set_title('Spectrogram (dB)')
fig.colorbar(img, ax=axs[0], format='%+2.0f dB')

# 2. Waveform + Peaks
time = np.linspace(0, len(y)/sr, len(y))
axs[1].plot(time, y, linewidth=0.4, label='Waveform')
axs[1].vlines(peak_times_vis, -1, 1, color='red', alpha=0.3, linewidth=0.3, label='Peaks')
axs[1].set_title('Waveform + Volume Peaks')
axs[1].legend(loc='upper right')

# 3. FFT
Y = np.abs(np.fft.rfft(y))
f = np.fft.rfftfreq(len(y), 1/sr)
axs[2].plot(f, Y, linewidth=0.5)
axs[2].set_title('FFT Spectrum')
axs[2].set_xlabel('Frequency (Hz)')
axs[2].set_ylabel('Amplitude')

plt.tight_layout()
plt.savefig('analysis_with_tempo.png')
plt.show()

# ------------------------
# 結果出力 / Summary
# ------------------------
print(f"\n🎧 Duration: {len(y)/sr:.2f} sec")
print(f"🎼 Voiced frames: {np.sum(~np.isnan(f0))}")
print(f"📊 Entropy Mean: {np.mean(entropy):.2f}, Std: {np.std(entropy):.2f}")
print(f"🔊 Volume Peaks: {len(peak_times)} over {peak_threshold}")
print(f"📋 Pitch Mean: {np.nanmean(f0):.2f} Hz, Std: {np.nanstd(f0):.2f} Hz")
print(f"⏱ Estimated Tempo: {tempo:.2f} BPM")


結果

🔄 Downloading audio from YouTube...
✅ MP3 downloaded: downloaded_audio.mp3
✅ Converted to WAV: converted_audio.wav
🎧 Audio loaded: 2495472 samples, 113.17 seconds
🎼 Voiced frames: 2240
📊 Entropy - Mean: -581706.1875, Std: 406842.2500
🎤 Saved separated audio: harmonic.wav, percussive.wav
🔊 Detected 1810869 volume peaks above threshold (0.05)
📋 Pitch Mean: 121.24 Hz
📋 Pitch Std Dev: 64.24 Hz
image.png

image.png

以下は、あなたの音声ファイル解析結果(スペクトル・波形・音量ピーク・FFT)とログに基づいた技術的分析レポートです:


🎧 全体情報(音声概要)

項目
総サンプル数 2,495,472 サンプル
長さ(秒) 約 113.17 秒
サンプリングレート 22,050 Hz

🎼 音高(ピッチ)分析(pyinによるF0抽出)

  • 有声フレーム数: 2,240(≒全体の約43%が有声音)
  • 平均ピッチ: 121.24 Hz(B2〜C3程度、低音寄り)
  • 標準偏差: 64.24 Hz(±1オクターブ弱)

📝 考察:
低めの音域を中心に安定した旋律がある。会話・ボーカル・楽器(ベースなど)の可能性。


📊 スペクトルエントロピー分析

  • 平均: -581,706.19
  • 標準偏差: 406,842.25

📝 考察:
このスケール値はスペクトルパワーの総量が非常に大きいことを示唆(正規化されていないため絶対値が大きい)。
音響的には、**連続した成分(ハーモニック系)散漫なノイズ(パーカッシブ系)**が共存。


🔊 音量ピーク(Envelope)検出

  • ピーク数(しきい値0.05超): 1,810,869箇所

📝 考察:

  • 音のエンベロープが非常に活発 → 高密度な発音/ビート感
  • vlines() により視覚的には「赤で塗り潰される」ほど密集 → プロットには間引きが必要

🎤 音源分離(HPSS)

  • harmonic.wav: 主に旋律・ボーカル成分
  • percussive.wav: 主にビート・リズム・ノイズ成分

📝 考察:

  • harmonic.wav で主旋律抽出 → 後続で MIDI変換や音階推定 可能
  • percussive.wav でビート抽出 → BPM推定や拍検出 に展開可能

📈 FFTスペクトル(周波数分析)

  • 最も強い成分は 0〜1000Hz に集中(楽器・声帯領域)
  • 2000Hz以降は急速に減衰

📝 考察:

  • 音声信号(特に声や低音楽器)の特性に一致
  • 高域成分は弱め → ノイズ成分は少ないが滑舌が柔らかい傾向

📷 可視化画像(analysis_summary.png)構成

プロット 内容
上段 スペクトログラム(時間×周波数×音圧)
中段 波形 + 音量ピーク(※ピーク過多により真っ赤に)
下段 FFT周波数成分分布

2
3
3

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
2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?