forked from vitorgalvao/tiny-scripts
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathgfv
More file actions
executable file
·130 lines (109 loc) · 3.33 KB
/
Copy pathgfv
File metadata and controls
executable file
·130 lines (109 loc) · 3.33 KB
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
#!/bin/bash
readonly program="$(basename "${0}")"
readonly cap_fps='30'
function depends_on {
local dep="${1}"
if ! command -v "${dep}" &>/dev/null; then
echo -e >&2 "\n$(tput setaf 1)This script requires ${dep}. Please install it first.$(tput sgr0)\n"
exit 1
fi
}
function syntax_error {
echo -e "${program}: ${1}\nTry \`${program} --help\` for more information." >&2
exit 1
}
function get_output_path {
readonly local ext='gif'
readonly local input_path="${1}"
local output_path="${2}"
if [[ -n "${output_path}" ]]; then
[[ "${output_path##*.}" == "${ext}" ]] && echo "${output_path}" || echo "${output_path}.${ext}"
else
output_path="${input_path%.*}.${ext}"
while [[ -e "${output_path}" ]]; do
output_path="${output_path%.*}_$(date -u +'%Y.%m.%d.%H%M%S').${ext}"
done
echo "${output_path}"
fi
}
function usage {
echo "
Usage:
${program} [options] <file>
Options:
-f <integer>, --fps <integer> Frames per second. Default is auto-detected from video, capped at ${cap_fps}.
-w <interger>, --width <integer> Resize the gif proportionally.
-o, --output-file <file> File to output to. Default is saving next to the input file with same name.
-g, --gifski Use gifski for the conversion.
-h, --help Show this help.
" | sed -E 's/^ {4}//'
}
# available flags
args=()
while [[ "${1}" ]]; do
case "${1}" in
-h | --help)
usage
exit 0
;;
-f | --fps)
readonly chosen_fps="${2}"
shift
;;
-w | --width)
readonly width="${2}"
shift
;;
-o | --output-file)
readonly given_output_path="${2}"
shift
;;
-g | --gifski)
depends_on 'gifski'
readonly use_gifski='true'
;;
--)
shift
args+=("${@}")
break
;;
-*)
syntax_error "unrecognized option: ${1}"
;;
*)
args+=("${1}")
;;
esac
shift
done
set -- "${args[@]}"
if [[ "${#}" -eq 0 ]]; then
usage
exit 1
fi
readonly input_file="${1}"
readonly output_file="$(get_output_path "${input_file}" "${given_output_path}")"
depends_on 'ffmpeg'
# Set FPS
if [[ -z "${chosen_fps}" ]]; then
depends_on 'ffprobe'
readonly video_fps="$(ffprobe -loglevel error -select_streams v:0 -of default=noprint_wrappers=1:nokey=1 -show_entries stream=r_frame_rate "${input_file}" | bc)"
readonly fps="$([[ "${video_fps}" -gt "${cap_fps}" ]] && echo "${cap_fps}" || echo "${video_fps}")"
else
readonly fps="${chosen_fps}"
fi
# Make the animated gif
if [[ -z "${use_gifski}" ]]; then
[[ -z "${width}" ]] && width='-1' # Make width same as original video, if none given
readonly palette="$(mktemp).png"
ffmpeg -i "${input_file}" -filter_complex "fps=${fps},scale=${width}:-1:flags=lanczos,palettegen" "${palette}"
ffmpeg -i "${input_file}" -i "${palette}" -filter_complex "fps=${fps},scale=${width}:-1:flags=lanczos[x];[x][1:v]paletteuse" "${output_file}"
else
readonly tmp_dir="$(mktemp -d)"
echo 'Extracting images from video…'
ffmpeg -loglevel quiet -i "${input_file}" -filter_complex "fps=${fps}" "${tmp_dir}/output_mage%9d.png"
options=()
[[ -n "${width}" ]] && options+=('--width' "${width}")
options+=('--fps' "${fps}")
gifski "${tmp_dir}/"* "${options[@]}" --output "${output_file}"
fi