Python
ffmpeg
音楽
python3
音声処理

動画中の音声を編集するために音声を結合したり音量を調整したりする必要があったので、その時調べたことをまとめておきます。

python3.6 + pydub (+ffmpeg)を使っています。

動画から音声を抜き出す

これはffmpegを使いました。
pythonからffmpegを呼び出します。

import os, sys
import subprocess

cmd = "ffmpeg -y -i {} -ab {}k -ac {} {}".format(input_file, bitrate, channnel, output_file)
resp = subprocess.check_output(cmd, shell=True)

pydubを使う

ここからpydubを使って音声ファイルを編集します。
インストールは

$ pip install pydub

で入るから楽!

ただしffmpegが必要なので注意!

音声を読み込む

import pydub
from pydub import AudioSegment

base_sound = AudioSegment.from_file(input.mp3, format="mp3")  # 音声を読み込み
length_seconds = base_sound.duration_seconds  # 長さを確認
base_sound.export("./result.mp3", format="mp3")  # 保存する

1部分を切り出す

first_five_second = base_sound[:5*1000]
last_ten_second = base_sound[10*1000:]

音を結合する

concated_sound = first_five_second + last_ten_second  # 元の音声の最初と最後を結合

効果音をつける(音声を重ねる)

effect_sound = AudioSegment.from_file(effect.mp3, format="mp3")  # 効果音を読み込み
start_time_ms = 5 * 1000  # 効果音を5秒時点から鳴らす
result_sound = base_sound.overlay(effect_sound, start_time_ms)  # ベースの音声に効果音をつける

音量を変える

loud_sound = base_sound + 6  # 音量を6dbだけ上げる
quiet_sound = base_sound - 10  # 音量を10db下げる

でも、普通「音量を4デシベル上げたい」ってよりは「音量を1.5倍にしたい」って感じじゃないでしょうか?(音声処理を専門でやっている方々は違うかもしれませんが...)

本当にこれでいいのかどうか自信がないので、詳しい方がいらっしゃいましたら教えていただけると嬉しいです。

from pydub.utils import db_to_float, ratio_to_db
ratio = 0.8  # 0.8倍の音量にしたい
quiet_sound = base_sound + ratio_to_db(ratio)

これで本当にあっているのかどうか確かめるために、音量を確かめてみました。
でも、音量関係の指標もいくつかあって、

base_sound.rms
base_sound.dBFS
base_sound.max

の3つを見つけました。
うーん、どれを参考にすればいいんだろ...

この辺りの話は全く知らなかったので調べてみたら、rmsは

ソース:http://sleepfreaks-dtm.com/dtm-mix-technique/level-metering/

簡単に言ってしまえば、平均的な信号レベルの大きさを表す指標ということになります。
実効値とも呼ばれ、単位は”dB”です。
音圧の大きさの指標として用いられることが多いように思います。

らしい。

そしてrmsってなんの略かと思ったら、機械学習をやっている人ならおなじみのRootMeanSquareの略でした!

ってことは、サウンド全体の平均的な音量を調節するにはこれを使えば良さそう!

自分が持ってる音楽で以下を試しました。

delta = ratio_to_db(0.8)  # 音量を0.8倍にしたい
sound_quiet = sound_base + delta  # 音量を調節
result_ratio = sound_quiet.rms / sound_base.rms
print(resul_tratio)  # 0.7998836532867947が返ってきた

元のサウンドと比べてrms値がほぼ0.8倍になっているので、問題なしとします。

sound.maxの値を使って調整するやり方も考えられましたが、返り値の単位がよくわからないので却下。

最後に

pydubのソースコードをみてみたら、audioopというモジュールを使ったりして操作しているようです。
https://docs.python.jp/3/library/audioop.html

このあたりは時間があったら調べたい。