出力から一部の情報を抽出する

出力から一部の情報を抽出する

ffmpeg出力から一部の情報を抽出しようとしています。

ffmpeg出力の例:

configuration:  --enable-memalign-hack --enable-mp3lame --enable-gpl --disable-vhook --disable-ffplay --disable-ffserver --enable-a52 --enable-xvid --enable-faac --enable-faad --enable-amr_nb --enable-amr_wb --enable-pthreads --enable-x264 
libavutil version: 49.0.0
libavcodec version: 51.9.0
libavformat version: 50.4.0
built on Apr 15 2006 04:58:19, gcc: 4.0.1 (Apple Computer, Inc. build 5250)
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'file.mov':
Duration: 00:01:32.0, start: 0.000000, bitrate: 63489 kb/s
Stream #0.0(eng): Audio: pcm_s16le, 48000 Hz, stereo, 1536 kb/s
Stream #0.1(eng), 29.97 fps(r): Video: Apple ProRes 422, 1280x720
Must supply at least one output file

期間、フレームレート、コーデック、サイズのみを含む文字列を返したいです。たとえば、次のようになります。

[00:01:32_29.97_Apple ProRes 422_1280x720]

私はこれから始めようとしました(他のヒントから):

ffmpeg -i file.mov 2>&1 | sed -n 's/Duration: \(.*\), start/\1/gp'

言葉を得なさい。しかし、これはただDurationandを「削除」します, start。つまり:

00:01:32.0: 0.000000, bitrate: 63489 kb/s

ApplePS:またそれを削除したいですApple ProRes 422:-)

ありがとうございます!

更新:次のコマンドを使用してコーデックを抽出できました。

sed -n "s/.*\Video: \(.*\),.*/\1/p"

しかし、(a)サイズとフレームレートを取得する方法と(b)検索を1行にまとめる方法がわかりません...

答え1

awk:魔法のようですが、より良いです。

#!/usr/bin/awk -f
/Duration/ {sub(/,/, "", $2); fields["dur"] = $2}
/fps/ { fields["fps"] = $3 }
/Video/ { 
        sub(/.*Video:/, "", $0);
        sub(/\W*Apple\W*/, "", $0);
        split($0, arr, ", ")
        fields["codec"] = arr[1]; 
        fields["res"] = arr[2]; 
}
END {
        printf "[%s_%s_%s_%s]\n", 
                fields["dur"], 
                fields["fps"], 
                fields["codec"],  
                fields["res"]
}

答え2

sedから1行の一部を抽出するには、行全体を一致させ、逆参照を使用して保持したいビットを印刷します。 (sedに\+演算子がない場合は代わりにfoo*を使用してくださいfo\+。)

$ … | sed -n -e 's/^.*Duration: *\([^,]*\).*$/\1/p' \
             -e 's/^.* \([0-9.]\+\) fps(r).* Video: \([^,]\+\).*, *\([0-9]\+x[0-9]\+\).*$//'
00:01:32.0
29.97 Apple ProRes 422 1280x720

どのテキストがどのグループに入るかを決定する方法が複数ある場合、前のグループの長さはできるだけ長くなります。たとえば、2番目の式の先頭では、^.* \([0-9.]\+\) fps空白の後の数字と一致します。式がある場合、^.*\([0-9.]\+\) fpsグループ内の1つの数字のみが一致し、前の数字は吸収されます.*。代わりに、2番目の式の終わりに一致する項目がなくなったとき、つまり最初の数字ではなく数字の後にのみ始まり、\([0-9]\+\).*$グループ内にすべての数字を入れます。.*[0-9]\+

可能ですが、sedは複数の行を結合したり後処理を実行したりするのが得意ではありません。単純なテキスト置換以上の機能が必要な場合awkに切り替え

答え3

同じsedコマンドに複数の式を追加できます。ビデオポップから「Apple」を抽出するために何かを追加すると、まだ両方の一致と代替アイテムの両方が印刷されます。

唯一の問題は、2つの異なる行で印刷されることですが、いつでも|xargs echoよりエレガントに印刷できます。

答え4

sedwith-eオプションを使用して、次のように複数の条件を組み合わせることができます。

sed -e <expression1> -e <expression2> ...

関連情報