この記事は最終更新日から1年以上が経過しています。情報が古くなっている可能性があります。
諸事情で 100 個近くある WAV ファイル(1秒~20秒くらい)を16bit・サンプルレート48000kHz・1チャンネル(モノラル)に変換、さらにノーマライズ(音量を正規化)して大きすぎない音量に変換する必要があった。
最初は ffmpeg (dynaudnorm) を使ってやってみたがうまく効かず、ffmpeg-normalize も 3 秒以内の音声はノーマライズできないとかで断念。最後に音声編集コマンドラインソフト界のスイミーなんたららしい SoX というソフトを使ってノーマライズさせてみる事にした。
…がこれがかなりの曲者で、ffmpeg みたいな引数を想像していたらどうも引数のタイプごとに入力ファイルの前に記述だとかそもそも引数が数年のうちに変わってるとかなんとかで、2時間くらいエラーと格闘したりかなり大変だった(正直全然分かってない)。
コマンド
sox "input.wav" -b 16 "output.wav" channels 1 norm gain -8 rate 48k
これで一発。あとは適当にバッチ組むなりpython書くなりして自動化しませう…
コマンドの解説
- “input.wav”
- 言わなくても分かるであろう入力元(変換元)のファイルの指定。
- -b 16
- ビット深度を16Bitにする。
- 出力ファイルよりも前に書かないとエラーになるらしい。
- “output.wav”
- 言わなくても分かるであろう出力(変換先)のファイルの指定。
- SoX は ffmpeg とかとか違い、input と output の後に各種引数をつなげるそう。
- 日本語ドキュメントも少ないしかなりはまった。
- channels 1
- 音声チャンネルを1チャンネルにする。
- 要するにこの引数でステレオ→モノラルに出来る。
- norm
- ノーマライズ処理。この引数を挟むだけで良いらしい。
- 細かな音量調整は後の方で別途やってね、ってことっぽい。
- gain -8
- 音量調整。gain 3 とかにすると 3dB(?)分音量が上がる。
- 逆に例のように gain -8 とかにすると音量が 8dB(?)分下がる。
- 結構音量デカめでノーマライズされるので、適宜この引数で音量を下げる。
- rate 48k
- サンプリングレートを指定する。
- この引数どこのドキュメントにも書いてない…。
- 48000kHz なら 48k 、 44100kHz なら 44k で良いはず。
機能としては素晴らしいんだけどどうしてこうもコマンドが複雑なんだか…
ffmpeg でできるならそっちでやったほうが絶対に楽だと思う。
コメント
今回はノーマライズと音量調整だけでしたのでSoXで十分でしたが、ほかにも色々弄るときはRaw PCMを出力させてそれを弄ると楽です。
ffmpegでサンプルレート48000kHz・1チャンネルなRaw PCMを出すならこんな感じです。
ffmpeg -i “input.wav” -acodec pcm_s32le -ar 48k -ac 1 -f s32le “output.raw”
弄ったときの値の精度を確保するため、Raw PCMのビット深度は32bit int(pcm_s32le)かfloat(pcm_f32le)にすることをお勧めします。
あとは、Raw PCMに処理を適用するスクリプトを適当に書けば、波形を弄り放題です。
私の場合はPHPに慣れているので、PHP CLIで書くことが多いですね。
unpack()でRaw PCMバイナリデータから配列を作り、その配列に対して色々処理をして、最後にpack()で配列からRaw PCMバイナリデータへ、という感じで書いてます。
Raw PCMからwavに戻すときはこんな感じで書けばOKです。
ffmpeg -f s32le -ar 48k -ac 1 -i “input.raw” -acodec pcm_s16le -ar 48k -ac 1 -f wav “output.wav”
もし機会がありましたら是非お試しください。