-
Notifications
You must be signed in to change notification settings - Fork 0
/
mkv-ls
executable file
·132 lines (113 loc) · 3.28 KB
/
mkv-ls
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
#!/bin/bash
set -eo pipefail
shopt -s nullglob
throw() {
printf '%s: %s\n' "${0##*/}" "$1" >&2
return 1
}
if [[ $1 =~ ^(--help|-h)$ ]]; then
cat >&2 <<'EOF'
Usage: mkv-ls [--attachments|-a] [<path...>]
Lists the tracks in an mkv for muxing with mkvmerge or mkv-batch, including
track name, language, and whether it's the default track. (`mkvmerge -i` does
not show this, and `mkvinfo` prints too much.)
If multiple files given, mkv-ls will group identical track listings, displaying
each group's filenames in an escaped format that can be passed to mkv-batch.
Directories are expanded to contained *.mkv files (non-recursive). If no paths
are given, the current directory is used (equivalent to `mkv-ls *.mkv`).
Note: Video title is not shown when grouping.
Options:
--attachments, -a Show attachments as well (cover, fonts, etc.)
EOF
exit 1
fi
paths=()
paths_given=
attachments=
while (( $# > 0 )); do
if [[ $1 =~ ^--attachments|-a$ ]]; then
attachments=1
elif [[ -f "$1" ]]; then
paths+=("$1")
paths_given=1
elif [[ -d "$1" ]]; then
paths+=("$1"/*.mkv)
paths_given=1
else
throw "'$1' does not exist"
fi
shift
done
if [[ ! $paths_given ]]; then
paths=(*.mkv)
fi
list_tracks() {
jq_track_name='.properties.track_name // ""'
if (( ${#paths[@]} > 1 )); then
# Hide video title when grouping since it may contain episode number, etc.
jq_track_name='if .type == "video" then "" else '"$jq_track_name"' end'
fi
mkvmerge -J "$1" | \
jq -r '
if .tracks | type != "array" then
"\"\(.file_name)\" is not an mkv\n" | halt_error
else
.tracks[] | (
(.id | tostring) + "\t" +
.type + "\t" +
.codec + "\t" +
.properties.language + "\t" +
(if .properties.default_track then "✓" else "" end) + "\t" +
(if .properties.forced_track then "✓" else "" end) + "\t" +
('"$jq_track_name"')
)
end
' | column -ts $'\t' -N 'TID,Type,Codec,Lang,Def,For,Name'
if [[ $attachments ]]; then
echo
mkvmerge -J "$1" | \
jq -r '
if .attachments | length > 0 then
.attachments[] | (
(.id | tostring) + "\t" +
.content_type + "\t" +
.file_name
)
else
"(no\t\u0008atta\t\u0008\u0008chments)" # \u008 is the backspace character
end
' | column -ts $'\t' -N 'AID,Type,Name'
fi
}
if (( ${#paths[@]} == 1 )); then
list_tracks "${paths[0]}"
else
grouped_filenames=()
grouped_tracks=()
for f in "${paths[@]}"; do
printf '\e[30;1m%s\e[m' "${f:0:$(tput cols)}"
track_list=$(list_tracks "$f")
escaped_name=$(printf '%q' "$f")
# Look for identical track list
found=
for i in "${!grouped_tracks[@]}"; do
if [[ ${grouped_tracks[i]} == "$track_list" ]]; then
# Add file name to group
grouped_filenames[i]="${grouped_filenames[i]} $escaped_name"
found=1
fi
done
# Add new group if none found
if [[ ! $found ]]; then
grouped_filenames+=("$escaped_name")
grouped_tracks+=("$track_list")
fi
printf '\r\e[K'
done
# Print groups
for i in "${!grouped_tracks[@]}"; do
(( i > 0 )) && echo
printf '\e[30;1m%s\e[m\n' "${grouped_filenames[i]}"
echo "${grouped_tracks[i]}"
done
fi