事の発端:ファイル名変換をミスった
この動画なんだっけ?wmv?avi? mpegts ?
ファイル名の変換をミスった。拡張子がトンだ。もうしにたい。仕方ないのでコーデック情報見ながら各種データの拡張子を探ることに
動画のストリーム情報の解析がめんどくさい。
ffmpeg で動画の情報を見るには ffprobe を使う。
ffprobe -i movie.mov
まぁこれだけでも見るだけなら 標準エラーにffmpeg と同じ情報が出てきてログ見たらわかるんだけど。もっと手軽にほしいところだけ見たいな的な。
ネット見てたら、ffmpeg/ffprobe のエラーストリームへログをgrep してたりしてたいへんだ。
JSON で取り出す
-print_format json
ffprobe には show_format があってJSONでストリーム情報を取り出せる。
ffprobe -i movie.mov -show_streams -print_format json
これで、ストリーム情報を取り出せる。
うるさいログを黙らせる。
サポートしてるフォーマットとかの情報がうるさいので黙らせる。-loglevel quiet
で指定する。
ffprobe -i movie.mov -loglevel quiet -show_streams -print_format json
-print_format json
と jq
を組み合わせる。
ここまで来たら後は楽ちん。 jq と組合あせて戦う。
takuya@Desktop$ ffprobe -loglevel quiet -show_streams -print_format json "$f" | jq '.streams[] | {"index":.index,"codec_type":.codec_type,"codec_name":.codec_name} ' -r { "index": 0, "codec_type": "audio", "codec_name": "aac" } { "index": 1, "codec_type": "video", "codec_name": "h264" } { "index": 2, "codec_type": "data", "codec_name": null } { "index": 3, "codec_type": "data", "codec_name": null } takuya@Desktop$
動画のコーデック情報を取り出す。
ffprobe -loglevel quiet -show_streams -print_format json "$i" | jq .streams[0].codec_name -r
最後にこれを関数にする。
function ffmpeg_show_video_codec() f=$1 ffprobe -loglevel quiet -show_streams -print_format json "$f" | jq .streams[0].codec_name -r }
コレで行けそうですね。
追記1 XML + XPATHの方が簡単かも
json と jq はどうしても煩雑なので、 XML+XPATH のほうが楽だった。
XML で出力する -print_format xml
XML で出力してXPATHの方が //
の省略記法があるので圧倒的に楽
ffprobe /Users/takuya/.Desktops/2017-02-10/IMG_4046.MOV-1.mov -loglevel quiet -show_streams -print_format xml | xpath '//stream/@codec_name'
やっぱりJSONめんどくさいんだよ。読みやすいけど、コードが煩雑。廃れてほしい。*1
追記 XML / JSON 以外のフォーマット
などがある
追記 他に見れるもの
formats 以外に見れるものもある。
ffprobe の man を眺めているとアレコレあるみたい
-show_data -show_data_hash algorithm -show_error -show_format -show_format_entry name -show_entries section_entries -show_packets -show_frames -show_streams -show_programs -show_chapters
時間無くて調べきれない。-show_programs
番組のprogram_id などが見れる TS のストリーム情報などはコッチ見た方がいいのかな。
追記
動画の拡張子を wmv / mp4 にわける。
#!/usr/bin/env bash for i in ./movies/* ; do name=$(ffprobe -loglevel quiet -show_streams -print_format json "$i" | jq .streams[0].codec_name -r) echo $name $i case "$name" in wmv*) : echo mv "$i" "${i/.*/.wmv}" # mv "$i" "${i/.*/.wmv}" ;; h264|aac|mpeg4) : echo mv "$i" "${i/.*/mp4}" ;; esac done
覚えにくいので、bash alias や function にしてコマンドにした。
alias ffmpeg_info_json ='$ ffprobe -loglevel quiet -show_streams -print_format json -i '