前回の記事で、YouTubeの動画から音声データをダウンロードする方法を紹介しました。
今回は、1つのmp3 に複数の曲が含まれている場合を想定し、pydub を使って無音部分で分割する方法を紹介します。
YouTubeでは、いろいろな方が著作権フリーのBGMをアップロードされていますが、中には1つの動画に十数曲含まれているケースも多いかと思います。
そんな時は、今回紹介する方法で1つ1つの曲に分割することができます。
無音部分で曲を分割するには、pydub と ffmeg が必要
pydub は、音声(オーディオ)ファイルに対して、色々な加工ができるライブラリであり、ffmeg は動画に関して様々な加工ができるライブラリです。
pydub のメソッドを使えば無音部分の検出と分割が可能ですが、内部で ffmeg を呼び出しているため、両方のインストールが必要となります。
pydub の詳細については、pydub 公式サイトに記載されていますので、必要に応じてご参照下さい。
インストール方法
pydub は pip にて簡単にインストールできます。
pip install pydub
一方、ffmpeg は公式サイトからZipファイルをダウンロード後、任意のフォルダに解凍し、OSの環境変数にそのパスを登録するという手順が必要です。
まず ffmpeg-master-latest-win64-gpl-shared.zip をダウンロードし、任意のフォルダに解凍します。
下記は download フォルダに解凍した例です。 bin フォルダの中にライブラリが含まれているため、これを任意のフォルダにコピーしてOSの環境変数のパスに登録します。
環境変数を登録しなくても、プログラムで下記のコードを実行すれば都度環境変数にパスが追加されるので、この方法でも構いません。
例えば、 bin の内容を 'C:/Users/hoge/ffmpeg/bin' にコピーしたのであれば、下記の様に記述できます。
1 2 3 |
import os path = 'C:/Users/hoge/ffmpeg/bin' os.environ['PATH'] += '' if path in os.environ['PATH'] else ';' + path |
bin へのパスが登録されていないと、pydub をインポートする時点でエラーになるためご注意下さい。
無音部分でのファイル分割
無音部分で分割するために、一旦音声ファイルを読み込みます。
これには、AudioSegment クラスの from_file メソッドを使います。
AudioSegment.from_file(ファイルのパス, format=音声フォーマットの種類)
尚、format には、wav、mp3、ogg、flv、mp4、raw が指定可能です。
次に、split_on_silence 関数を使って無音部分で分割します。
split_on_silence(読み込んだ音声データ,
min_silence_len=無音区間の最小長さ,
silence_thresh=無音の閾値,
keep_silence=分割後の前後に追加する無音の長さ)
パラメーター名 | 説明 |
---|---|
min_silence_len | 無音区間の最小長さを指定する。 pydubは、この長さよりも短い無音区間を無視する。 単位はミリ秒。 |
silence_thresh | 無音と判定するための閾値を指定する。 pydubは、この閾値以下の音量を無音として扱う。単位はデシベル。 |
keep_silence | 分割された音声ファイルの前後に追加される無音区間の長さを指定する。 単位はミリ秒。 |
無音分割のサンプルプログラム
以下はサンプルプログラムです。
split_on_silence に渡すパラメータは min_silence_len=2000, silence_thresh=-40, keep_silence=600 に設定していますが、多くの場合はこの値で分割できると思います。
ダメだった場合は、適宜変更して下さい。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
#ffmpeg の binフォルダのパスを設定(環境変数に登録していれば、この処理は不要) import os path = 'C:/Users/hoge/ffmpeg/bin' os.environ['PATH'] += '' if path in os.environ['PATH'] else ';' + path #pydub のインポート from pydub import AudioSegment from pydub.silence import split_on_silence #mp3ファイルの読み込み(C:/Users/hoge/Musicフォルダに bgm.mp3があることを想定) sound = AudioSegment.from_file('C:/Users/hoge/Music/bgm.mp3', format='mp3') #ファイル情報の表示 print(f'チャンネル数: {sound.channels}') print(f'サンプリング周波数: {sound.frame_rate} Hz') print(f'再生時間(秒): {sound.duration_seconds} 秒') print(f'音量: {sound.dBFS} dB') #mp3の分割(無音部分で区切る) chunks = split_on_silence(sound, min_silence_len=2000, silence_thresh=-40, keep_silence=600) #分割したデータ毎にファイル出力 for i, chunk in enumerate(chunks): chunk.export(f'C:/Users/hoge/Music/output_{i}.mp3', format='mp3') |
AudioSegment.from_file と split_on_silence は、音声ファイルの大きさやPCのスペックによっては数分ほどの処理時間が必要になりますので、気長にお待ちください。
音声データの波形をグラフ化する
ファイル分割とは関係ありませんが、pydub.from_file で読み込んだ音声ファイルを numpy で数値配列に変換することで時系列グラフが作成できます。
また、numpy の np.fft.fft を使うことで、周波数分析(フーリエ変換)した結果をグラフにすることもできます。
時系列グラフ
以下は時系列グラフを表示するためのサンプルプログラムです。
ここでは、'C:/Users/hoge/output_0.mp3' という音声ファイルを使ってグラフ化しています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
import matplotlib.pyplot as plt import numpy as np from pydub import AudioSegment import os path = 'C:/Users/hoge/ffmpeg/bin' os.environ['PATH'] += '' if path in os.environ['PATH'] else ';' + path # 音声ファイルを読み込み、データを取得する audio_file = AudioSegment.from_file('C:/Users/hoge/output_0.mp3') audio_data = np.array(audio_file.get_array_of_samples()) # 時系列のグラフを作成する plt.plot(audio_data) plt.xlabel('Time (ms)') plt.ylabel('Amplitude') plt.show() |
実行した結果は下記の通りです。
周波数解析(フーリエ変換)
先ほどのプログラムの「# 時系列のグラフを作成する」を下記にコードに置き換えると、周波数解析した結果のグラフが表示できます。
1 2 3 4 5 6 7 8 |
# フーリエ変換したグラフを作成する freq_data = np.fft.fft(audio_data) freq_data_magnitude = np.abs(freq_data) plt.plot(freq_data_magnitude) plt.xlabel('Frequency (Hz)') plt.ylabel('Magnitude') plt.show() |
実行結果は次の通りです。
まとめ
今回は、mp3 の音声ファイルに対して、無音部分で分割する方法として、pydub と ffmpeg を用いた方法について紹介しました。
pydub を使うと、mp3から無音部分を検出し、いとも簡単に分割してくれます。
pudub は mp3以外に、wav、ogg、flv、mp4、raw などの音声ファイルを扱うことができるため、単純にフォーマット変換の用途として利用することも可能です。
また、numpy と matplotlib を組み合わせると、時系列グラフや周波数解析のグラフを簡単に表示できますので、自作プログラムに大いに役立てていただければと思います。
コメント