Created
September 19, 2022 14:07
-
-
Save martinpickett/82236d7fcf96b32bea9ce9d13fe2ff64 to your computer and use it in GitHub Desktop.
Displays track information for an MKV file. Requires FFprobe and jq.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bash | |
# Function which does almost everything. It needs to be a function as it is recursively | |
# called if the input is a directory. | |
main () { | |
for i in "$@"; do | |
# Check to see if input is valid | |
checkInput "$i" | |
# If input is not valid then skip to next iteration of for loop | |
if [ "$?" -ne 0 ]; then | |
continue | |
fi | |
# Print header | |
printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' - | |
printf '%s\n' "$i" | |
printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' - | |
# Generate and format information | |
json=$(ffprobe -v error -show_entries stream -print_format json=compact=1 "$i") | |
codex_type=$(echo "$json" | jq '(.streams[] | select(.codec_type=="video" or .codec_type=="audio" or .codec_type=="subtitle") | .codec_type) | @text' | sed 's/\"//g' | tr '\n' ' ') | |
index=$(echo "$json" | jq '(.streams[] | select(.codec_type=="video" or .codec_type=="audio" or .codec_type=="subtitle") | .index) | @text' | sed 's/\"//g' | tr '\n' ' ') | |
language=$(echo "$json" | jq '(.streams[] | select(.codec_type=="video" or .codec_type=="audio" or .codec_type=="subtitle") | .tags.language) | @text' | sed 's/\"//g' | tr '\n' ' ') | |
codec_name=$(echo "$json" | jq '(.streams[] | select(.codec_type=="video" or .codec_type=="audio" or .codec_type=="subtitle") | if .codec_type=="audio" and .profile then .profile else .codec_name end) | @text' | sed 's/\"//g' | tr '\n' ',') | |
channel_layout=$(echo "$json" | jq '(.streams[] | select(.codec_type=="video" or .codec_type=="audio" or .codec_type=="subtitle") | .channel_layout) | @text' | sed 's/\"//g' | sed 's/null/-/g' | tr '\n' ',') | |
bitrate=$(echo "$json" | jq '.streams[].tags | to_entries | .[] | if .key|test("BPS*") then .value else empty end | @text' | sed 's/\"//g' | tr '\n' ' ') | |
no_of_elements=$(echo "$json" | jq '.streams[].tags | to_entries | .[] | if .key|test("NUMBER_OF_FRAMES*") then .value else empty end | @text' | sed 's/\"//g' | tr '\n' ' ') | |
default_flag=$(echo "$json" | jq '(.streams[] | select(.codec_type=="video" or .codec_type=="audio" or .codec_type=="subtitle") | .disposition.default) | @text' | sed 's/\"//g' | tr '\n' ' ') | |
forced_flag=$(echo "$json" | jq '(.streams[] | select(.codec_type=="video" or .codec_type=="audio" or .codec_type=="subtitle") | .disposition.forced) | @text' | sed 's/\"//g' | tr '\n' ' ') | |
track_title=$(echo "$json" | jq '(.streams[] | select(.codec_type=="video" or .codec_type=="audio" or .codec_type=="subtitle") | .tags.title) | @text' | sed 's/\"//g' | sed 's/null/-/g' | tr '\n' ',') | |
# Store information in arrays | |
read -ra codex_type_a <<< "$codex_type" | |
read -ra index_a <<< "$index" | |
read -ra language_a <<< "$language" | |
IFS=',' read -ra codec_name_a <<< "$codec_name" | |
IFS=',' read -ra channel_layout_a <<< "$channel_layout" | |
read -ra bitrate_a <<< "$bitrate" | |
read -ra no_of_elements_a <<< "$no_of_elements" | |
read -ra default_flag_a <<< "$default_flag" | |
read -ra forced_flag_a <<< "$forced_flag" | |
IFS=',' read -ra track_title_a <<< "$track_title" | |
# Print information | |
table="TYPE,INDEX,LANGUAGE,CODEC,CHANNEL LAYOUT,BITRATE,NO OF ELEMENTS,DEFAULT,FORCED FLAG,TITLE \n" | |
num_tracks=${#codex_type_a[@]} | |
num_tracks_offset=$(($num_tracks-1)) | |
for i in $( eval echo {0.."$num_tracks_offset"} ) | |
do | |
table+="${codex_type_a[$i]},${index_a[$i]},${language_a[$i]},${codec_name_a[$i]},${channel_layout_a[$i]},${bitrate_a[$i]},${no_of_elements_a[$i]},${default_flag_a[$i]},${forced_flag_a[$i]},${track_title_a[$i]} \n" | |
done | |
echo -e "$table" | column -t -s ',' | |
# Newline for formatting reasons | |
echo "" | |
done | |
} | |
# Function to check input validity. Returns 0 if valid, non-zero if not. | |
checkInput() { | |
# Check if input is a directory | |
# If it is look for mkv files in directory | |
if [ -d "$1" ]; then | |
for j in "$1"/*.mkv; do | |
if [ ! -f "$j" ]; then | |
echo "There are no mkv files in directory $1" | |
return 1 | |
else | |
main "$j" | |
fi | |
done | |
continue | |
fi | |
# Check if input file exists | |
if [ ! -f "$1" ]; then | |
echo "Input file $1 does not exist." | |
return 1 | |
fi | |
# Check input file is an mkv file | |
if [[ $1 != *.mkv ]]; then | |
echo "Input file $1 is not an mkv file. This script only supports mkv files." | |
return 1 | |
fi | |
return 0 | |
} | |
# Run main function | |
main "$@" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment