1#!/bin/sh
2
3# file identification script
4#
5# manual usage:
6#   mpv_identify.sh foo.mkv
7#
8# sh/dash/ksh/bash usage:
9#   . mpv_identify.sh FOO_ foo.mkv
10# will fill properties into variables like FOO_length
11#
12# zsh usage:
13#   mpv_identify() { emulate -L sh; . mpv_identify.sh "$@"; }
14#   mpv_identify FOO_ foo.mkv
15# will fill properties into variables like FOO_length
16#
17# When multiple files were specified, their info will be put into FOO_* for the
18# first file, FOO_1_* for the second file, FOO_2_* for the third file, etc.
19
20__midentify__main() {
21
22    case "$0" in
23        mpv_identify.sh|*/mpv_identify.sh)
24            # we are NOT being sourced
25            [ -n "$1" ] && set -- '' "$@"
26            ;;
27    esac
28
29    if [ "$#" -lt 2 ]; then
30        cat >&2 <<EOF
31Usage 1 (for humans only): $0 filename.mkv
32will print all property values.
33Note that this output really shouldn't be parsed, as the
34format is subject to change.
35
36Usage 2 (for use by scripts): see top of this file
37
38NOTE: for mkv with ordered chapters, this may
39not always identify the specified file, but the
40file providing the first chapter. Specify
41--no-ordered-chapters to prevent this.
42EOF
43        return 2
44    fi
45
46    local LF="
47"
48
49    local nextprefix="$1"
50    shift
51
52    if [ -n "$nextprefix" ]; then
53        # in case of error, we always want this unset
54        unset "${nextprefix}path"
55    fi
56
57    local allprops="
58        filename
59        path
60        stream-start
61        stream-end
62        stream-length
63
64        demuxer
65
66        length
67        chapters
68        editions
69        titles
70        duration
71
72        audio
73        audio-bitrate
74        audio-codec
75        audio-codec-name
76
77        video
78        angle
79        video-bitrate
80        video-codec
81        video-format
82        video-aspect
83        container-fps
84        width
85        height
86        dwidth
87        dheight
88
89        sub
90    "
91    # TODO add metadata support once mpv can do it
92
93    local propstr="X-MIDENTIFY-START:$LF"
94    local key
95    for key in $allprops; do
96        propstr="${propstr}X-MIDENTIFY: $key \${=$key}$LF"
97        key="$(printf '%s\n' "$key" | tr - _)"
98        unset "$nextprefix$key"
99    done
100
101    local fileindex=0
102    local prefix=
103    local line
104    while IFS= read -r line; do
105        case "$line" in
106            X-MIDENTIFY-START:)
107                if [ -n "$nextprefix" ]; then
108                    prefix="$nextprefix"
109                    if [ "$fileindex" -gt 0 ]; then
110                        nextprefix="${prefix%${fileindex}_}"
111                    fi
112                    fileindex="$((fileindex+1))"
113                    nextprefix="${nextprefix}${fileindex}_"
114                    for key in $allprops; do
115                        key="$(printf '%s\n' "$key" | tr - _)"
116                        unset "$nextprefix$key"
117                    done
118                else
119                    if [ "$fileindex" -gt 0 ]; then
120                        printf '\n'
121                    fi
122                    fileindex="$((fileindex+1))"
123                fi
124                ;;
125            X-MIDENTIFY:\ *)
126                local key="${line#X-MIDENTIFY: }"
127                local value="${key#* }"
128                key="${key%% *}"
129                key="$(printf '%s\n' "$key" | tr - _)"
130                if [ -n "$nextprefix" ]; then
131                    if [ -z "$prefix" ]; then
132                        echo >&2 "Got X-MIDENTIFY: without X-MIDENTIFY-START:"
133                    elif [ -n "$value" ]; then
134                        eval "$prefix$key"='"$value"'
135                    fi
136                else
137                    if [ -n "$value" ]; then
138                        printf '%s=%s\n' "$key" "$value"
139                    fi
140                fi
141                ;;
142        esac
143    done <<EOF
144$(${MPV:-mpv} --term-playing-msg="$propstr" --vo=null --ao=null \
145              --frames=1 --quiet --no-cache --no-config -- "$@")
146EOF
147}
148
149__midentify__main "$@"
150