コマンドラインで ffprobe の結果から音声コーデックを取得する
ffmpeg
を使って音声の抽出とか色々するスクリプトを書いてたんだけど、コーデックがわからないと音声を抽出できなかったので。
Ubuntu 20.04
そもそもだけど ffprobe
の結果って以下のような感じ。
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'input.mp4':
Metadata:
major_brand : isom
minor_version : 512
compatible_brands: isomiso2avc1mp41
encoder : Lavf58.51.101
Duration: 00:00:12.07, start: 0.000000, bitrate: 1486 kb/s
Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p, 1080x608, 1411 kb/s, 30 fps, 30 tbr, 90k tbn, 60 tbc (default)
Metadata:
handler_name : VideoHandler
Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 65 kb/s (default)
Metadata:
handler_name : SoundHandler
Input #0, flv, from 'input.flv':
Duration: 00:04:00.35, start: 0.000000, bitrate: 333 kb/s
Stream #0:0: Audio: mp3, 22050 Hz, mono, fltp, 65 kb/s
Stream #0:1: Video: flv1, yuv420p, 320x240, 30 fps, 30 tbr, 1k tbn
これらの Audio:
に続く aac
とか mp3
だけを取得したかった。
というわけで作ったのが以下のコマンド。
ffprobe input.mp4 2>&1 | awk 'match($0, /Audio: ([^ ]+)( \(.+\))?, /, m) {print m[1]}'
これを実行すると、ffprobe
の結果から音声コーデック (aac
とか mp3
) だけを抜き出せる。
まず 2>&1
だけど、これは ffprobe
が何故か結果をstderrに出してくるから、標準出力にまとめて後続の処理に渡せるようにしてる。
そしたら awk
で正規表現を使って目的の箇所を抜いてる。Audio:
から最初のカンマまでの間に対して、([^ ]+?)
で半角スペース以外の文字の連続をキャプチャしてる感じ。aac
の場合は aac (LC) (mp4a / 0x6134706D)
とかだから、うまいこと aac
だけを抜けるように頑張ってる。
あとは match()
の結果が m
に入ってるから、それを出力してる。丸括弧でキャプチャした文字列はインデックス1以降に入ってるから [1]
。
おまけ
引数で指定した動画ファイルから音声のみを audio.aac
とか audio.mp3
として出力するシェルスクリプト。
#!/bin/bash
cd `dirname $0`
VIDEO_FILE=$1
# 音声コーデック判定
AUDIO_CODEC=`ffprobe ${VIDEO_FILE} 2>&1 | awk 'match($0, /Audio: ([^ ]+)( \(.+\))?, /, m) {print m[1]}'`
if [ -z $AUDIO_CODEC ]; then
echo "音声コーデックの取得に失敗しました。"
exit 1
fi
EXTRACTED_AUDIO_FILE=audio.${AUDIO_CODEC}
if [[ -f ./${EXTRACTED_AUDIO_FILE} ]]; then
echo "${EXTRACTED_AUDIO_FILE} がすでに存在します。"
exit 1
fi
# 音声抽出
ffmpeg -i ${VIDEO_FILE} -vn -acodec copy ${EXTRACTED_AUDIO_FILE}
if [ "$?" -ne 0 ]; then
echo "音声抽出に失敗しました。"
exit 1
fi