-
Notifications
You must be signed in to change notification settings - Fork 46
/
Copy pathtile-thumbnails
executable file
·183 lines (150 loc) · 5.87 KB
/
tile-thumbnails
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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
#!/bin/sh
#===============================================================================
# tile-thumbnails
# create an image with thumbnails from a video
#===============================================================================
# dependencies:
# ffmpeg ffprobe awk bc
#===============================================================================
# script usage
#===============================================================================
usage()
{
echo "\
# create an image with thumbnails from a video
$(basename "$0") -i input -s 00:00:00.000 -w 000 -t 0x0 -p 00 -m 00 -c color -f fontcolor -b boxcolor -x on -o output.png
-i input.(mp4|mkv|mov|m4v|webm)
-s seek into the video file : default 00:00:05
-w thumbnail width : 160
-t tile layout format width x height : 4x3 : default 4x3
-p padding between images : default 7
-m margin : default 2
-c color = https://ffmpeg.org/ffmpeg-utils.html#color-syntax : default black
-f fontcolor : default white
-b boxcolor : default black
-x on : default off, display timestamps
-o output.png : optional argument
# if option not provided defaults to input-name-tile-date-time.png"
exit 2
}
#===============================================================================
# error messages
#===============================================================================
INVALID_OPT_ERR='Invalid option:'
REQ_ARG_ERR='requires an argument'
WRONG_ARGS_ERR='wrong number of arguments passed to script'
#===============================================================================
# check the number of arguments passed to the script
#===============================================================================
[ $# -gt 0 ] || usage "${WRONG_ARGS_ERR}"
#===============================================================================
# getopts check the options passed to the script
#===============================================================================
while getopts ':i:s:w:t:p:m:c:b:f:x:o:h' opt
do
case ${opt} in
i) infile="${OPTARG}";;
s) seek="${OPTARG}";;
w) scale="${OPTARG}";;
t) tile="${OPTARG}";;
p) padding="${OPTARG}";;
m) margin="${OPTARG}";;
c) color="${OPTARG}";;
f) fontcolor="${OPTARG}";;
b) boxcolor="${OPTARG}";;
x) timestamp="${OPTARG}";;
o) outfile="${OPTARG}";;
h) usage;;
\?) usage "${INVALID_OPT_ERR} ${OPTARG}" 1>&2;;
:) usage "${INVALID_OPT_ERR} ${OPTARG} ${REQ_ARG_ERR}" 1>&2;;
esac
done
shift $((OPTIND-1))
#===============================================================================
# variables
#===============================================================================
# input, input name
infile_nopath="${infile##*/}"
infile_name="${infile_nopath%.*}"
# ffprobe get fps and duration
videostats=$(ffprobe \
-v error \
-select_streams v:0 \
-show_entries stream=r_frame_rate:format=duration \
-of default=noprint_wrappers=1 \
"${infile}")
# fps
fps=$(echo "${videostats}" | awk -F'[=//]' '/r_frame_rate/{print $2/$3}')
# duration
duration=$(echo "${videostats}" | awk -F'[=/.]' '/duration/{print $2}')
# check if tile is null
if [ -z "${tile}" ]; then
: # tile variable not set : = pass
else
# tile variable set
# tile layout
tile_w=$(echo "${tile}" | awk -F'x' '{print $1}')
tile_h=$(echo "${tile}" | awk -F'x' '{print $2}')
# title sum
tile_sum=$(echo "${tile_w} * ${tile_h}" | bc)
fi
# defaults
seek_default='00:00:05'
scale_default='160'
tile_layout_default='4x3'
tile_default='12'
padding_default='7'
margin_default='2'
color_default='black'
fontcolor_default='white'
boxcolor_default='black'
timestamp_default='off'
pts_default='5'
pts=$(printf "%s %s\n" "${seek}" | awk '{
start = $1
if (start ~ /:/) {
split(start, t, ":")
seconds = (t[1] * 3600) + (t[2] * 60) + t[3]
}
printf("%s\n"), seconds
}')
outfile_default="${infile_name}-tile-$(date +"%Y-%m-%d-%H-%M-%S").png"
# duration * fps / number of tiles
frames=$(echo "${duration} * ${fps} / ${tile_sum:=${tile_default}}" | bc)
#===============================================================================
# functions
#===============================================================================
# contact sheet - no timestamps
tilevideo () {
ffmpeg \
-hide_banner \
-stats -v panic \
-ss "${seek:=${seek_default}}" \
-i "${infile}" \
-frames 1 -vf "select=not(mod(n\,${frames})),scale=${scale:=${scale_default}}:-1,tile=${tile:=${tile_layout_default}}:padding=${padding:=${padding_default}}:margin=${margin:=${margin_default}}:color=${color:=${color_default}}" \
"${outfile:=${outfile_default}}"
}
# contact sheet - timestamps
timestamp () {
ffmpeg \
-hide_banner \
-stats -v panic \
-ss "${seek:=${seek_default}}" \
-i "${infile}" \
-frames 1 -vf "drawtext=text='%{pts\:hms\:${pts:=${pts_default}}}':x='(main_w-text_w)/2':y='(main_h-text_h)':fontcolor=${fontcolor:=${fontcolor_default}}:fontsize='(main_h/8)':boxcolor=${boxcolor:=${boxcolor_default}}:box=1,select=not(mod(n\,${frames})),scale=${scale:=${scale_default}}:-1,tile=${tile:=${tile_layout_default}}:padding=${padding:=${padding_default}}:margin=${margin:=${margin_default}}:color=${color:=${color_default}}" \
"${outfile:=${outfile_default}}"
}
#===============================================================================
# check option passed to script
#===============================================================================
if [ "${timestamp}" == on ]; then
timestamp "${infile}" # -x on
elif [ ! -z "${fontcolor}" ]; then
timestamp "${infile}" # -f
elif [ ! -z "${boxcolor}" ]; then
timestamp "${infile}" # -b
elif [ -z "${timestamp}" ]; then
tilevideo "${infile}" # no timestamp
else
tilevideo "${infile}" # no timestamp
fi