3 #==============================================================================
5 # File ID: a15d6810-9d7d-11e9-b544-4f45262dc9b5
7 # Print total duration for multiple video/audio files.
9 # Author: Øyvind A. Holm <sunny@sunbase.org>
10 # License: GNU General Public License version 2 or later.
11 #==============================================================================
23 while test -n "$1"; do
25 -d|
--days) opt_days
=1; shift ;;
26 -F|
--no-frac) opt_no_frac
=1; shift ;;
27 -h|
--help) opt_help
=1; shift ;;
28 -q|
--quiet) opt_quiet
=$
(($opt_quiet + 1)); shift ;;
29 -u|
--unit) opt_unit
=$2; shift 2 ;;
30 -v|
--verbose) opt_verbose
=$
(($opt_verbose + 1)); shift ;;
31 -z|
--zero-terminated) opt_zero_terminated
=1; shift ;;
32 --version) echo $progname $VERSION; exit 0 ;;
35 if printf '%s\n' "$1" |
grep -q ^
-; then
36 echo "$progname: $1: Unknown option" >&2
44 opt_verbose
=$
(($opt_verbose - $opt_quiet))
46 if test "$opt_help" = "1"; then
47 test $opt_verbose -gt 0 && { echo; echo $progname $VERSION; }
50 Print total duration for multiple video/audio files. If no files are
51 specified on the command line, read from stdin.
53 Usage: $progname [options] [files]
58 Include days in the output format, "d:hh:mm:ss.ssss".
60 Don't use fractional seconds.
64 Be more quiet. Can be repeated to increase silence.
66 Instead of using the hh:mm:ss.ssss format, display the total
67 duration as UNIT. Valid values for UNIT are: seconds, minutes,
68 hours, days, weeks, months, years. Only the first two letters are
69 used, so the abbreviation "mi" for "minutes" is ok.
71 Increase level of verbosity. Can be repeated.
73 Filenames from stdin are separated by a zero byte (NUL) instead of
76 Print version information.
81 $progname <playlist.txt
82 find . -name '*.mp4' | $progname
83 find . -name '*.mp3' -print0 | $progname -z -u ho
89 if test -z "$(bc --version 2>/dev/null)"; then
90 echo "$progname: bc(1) not found" >&2
93 if test -z "$(ffprobe -version 2>/dev/null)"; then
94 echo "$progname: ffprobe(1) from FFmpeg not found" >&2
98 test "$opt_zero_terminated" = "1" && sep_str
='-0' || sep_str
='-d\n'
101 if test -n "$opt_unit"; then
102 case "$(echo $opt_unit | tr '[A-Z]' '[a-z]' | head -c 2)" in
106 da
) unit_div
=86400 ;;
107 we
) unit_div
=604800 ;;
108 mo
) unit_div
=2629746 ;;
109 ye
) unit_div
=31556952 ;;
110 *) echo "$progname: Invalid value in -u/--unit option" >&2
117 if test -n "$1"; then
125 |
xargs $sep_str -L1 \
126 ffprobe
-v quiet
-of csv
=p
=0 -show_entries format
=duration \
131 test -z "$secs" && secs
=0
133 if test "$opt_days" = "1"; then
134 d1_str
='days = floor(secs / 86400); secs -= days * 86400;'
135 d2_str
="print \"printf '%u:%02u:%02u:%02u' \","
136 d2_str
="$d2_str days, \" \", hours, \" \", mins, \" \", secs, \"; \";"
139 d2_str
="print \"printf '%02u:%02u:%02u' \","
140 d2_str
="$d2_str hours, \" \", mins, \" \", secs, \"; \";"
143 cat <<END | bc | sh | perl -pe 's/^\./0./'
146 /* From <http://phodd.net/gnu-bc/code/funcs.bc>, thanks */
157 /* From <http://phodd.net/gnu-bc/bcfaq.html#bczeroes>, thanks again */
161 for (scale = 0; scale <= os; scale++) {
174 print "echo ", floor(trunc(secs / $unit_div));
177 print "echo ", trunc(secs / $unit_div);
181 hours = floor(secs / 3600);
182 secs -= hours * 3600;
184 mins = floor(secs / 60);
190 $(test "$opt_no_frac" = "1" && echo "frac = 0;")
193 if (frac > 0) print "echo -n ", trunc(frac), "; ";
198 # vim: set ts=8 sw=8 sts=8 noet fo+=w tw=79 fenc=UTF-8 :