====== ffprobe ====== The normal text output of ''ffprobe'' goes to stderr, so you usually need to add ''2>&1'' to parse the output. The alternative is to use the complex ffprobe options to format the output which then goes to stdout. Start with a look at this page: https://trac.ffmpeg.org/wiki/FFprobeTips ===== Show metadata tags===== ffprobe -v quiet "$in" -print_format json -show_entries stream_tags:format_tags (for ''-print_format'', there is also ''flat'', ''xml'', ''csv'', etc.) ===== Show video format===== ffprobe -v warning -select_streams v -show_entries stream=codec_name,height,width,pix_fmt -of csv=p=0 "$in" ===== Has alpha channel? ===== https://stackoverflow.com/questions/69029439/a-good-way-to-detect-alpha-channel-in-a-video-using-ffmpeg-ffprobe for f in *.mov; do pixfmt=$(ffprobe -v 0 -select_streams v:0 -show_entries stream=pix_fmt -of compact=p=0:nk=1 "$f") alpha=$(ffprobe -v 0 -show_entries pixel_format=name:flags=alpha -of compact=p=0 | grep "$pixfmt|" | grep -oP "(?<=alpha=)\d") if (( alpha )); then echo "$f : yes, has alpha"; else echo "$f : NO"; fi done ===== List audio tracks ===== ffprobe "$in" 2>&1 | perl -nle '/^\s+Stream #(\d+:\d+).*?: Audio/ && print $1' with codec and number of channels: ffprobe "$in" 2>&1 | perl -nle '/^\s+Stream #(\d+:\d+).*?: Audio: (\S+).*(?:(\d+)\s+channels)?/ && print join("\t", $1, $2, $3)' or to have the tracks in a Bash array: audio_tracks=( $(ffprobe "$in" 2>&1 | perl -nle '/^\s+Stream #(\d+:\d+): Audio/ && print $1') ) or the "official" way: ffprobe -v quiet -select_streams a -show_entries stream=index -of csv=p=0 "$in" ffprobe -v quiet -select_streams a -show_entries stream=index,codec_name,channels -of csv=p=0 "$in" audio_tracks=( $(ffprobe -v quiet -select_streams a -show_entries stream=index -of csv=p=0 "$in") ) ===== List subtitles ===== ffprobe -v quiet -select_streams s -show_entries stream=index,codec_name:stream_tags=language -of csv=p=0 "$in" (but for mkv, better see [[mkv]]) ===== Check Volume ===== For example to detect silent tracks/channels ffmpeg -i "$in" -map 0:a -af "astats=measure_overall=none:measure_perchannel=Max_level" -f null - ffmpeg -i "$in" -map 0:a -af "astats=measure_overall=none:measure_perchannel=Max_level" -f null - 2>&1 | grep -E '(Channel|Max level):' ffmpeg -i "$in" -vn -sn -dn -map 0:a -af "astats=measure_overall=none" -f null - 2>&1 \ | perl -nle 'if (($id, $var, $val)=/^\[Parsed_astats_0 \@ 0x([\da-f]+)] (Channel|Max level): ([\d\.]+)/) { if ($var=~/Channel/) { if (!$t || $id ne $h{$t}{id}) {$t++; $h{$t}{id}=$id;} $c=$val;} elsif ($var=~/level/) {print "$t.$c $var = $val";} }' Or with ''volumedetect'', but it mixes all channels into a single value ffmpeg -i "$in" -map 0:a -af "volumedetect" -f null - 2>&1 | grep max_volume ===== Audio checksums ===== for track in $(ffprobe -v error -select_streams a -show_entries stream=index -of csv=p=0 "$in"); do \ ffmpeg -i "$in" -vn -map 0:$track -c:a copy -f md5 - 2>/dev/null \ | while read md5; do \ printf "%32s Audio Track %2d %s\n" $md5 $track "$in"; \ done; \ done ===== Timecode ===== ffprobe -v error -show_entries stream=index,codec_name:stream_tags=timecode -of csv=p=0 "$in" ===== Other options ===== -sections Print sections structure and section information, and exit. The output is not meant to be parsed by a machine. -show_data_hash algorithm Show a hash of payload data, for packets with -show_packets and for codec extradata with -show_streams.