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