ffmpeg-effect - annna - Annna the nice friendly bot. | |
git clone git://bitreich.org/annna/ git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws6… | |
Log | |
Files | |
Refs | |
Tags | |
README | |
--- | |
ffmpeg-effect (6929B) | |
--- | |
1 #!/bin/sh | |
2 # modify a video input file with an effect. | |
3 # requirements: ffmpeg, ffprobe. | |
4 | |
5 ffmpeg_common="${FFMPEG_EFFECT_COMMON:-ffmpeg -n -loglevel error}" | |
6 ffprobe_common="${FFMPEG_EFFECT_FFPROBE:-ffprobe -v error -of default=no… | |
7 mediadir="${FFMPEG_EFFECT_MEDIA_DIR:-/home/annna/bin/modules/filter-medi… | |
8 repeats=5 | |
9 | |
10 usage() { | |
11 printf 'usage: %s [-n REPEATS] FILTER infile outfile\n' "${0##*/… | |
12 exit 1 | |
13 } | |
14 | |
15 is_image() { | |
16 mimetype="$(file -ib "$1")" | |
17 case "${mimetype}" in | |
18 image/*) | |
19 return 0;; | |
20 esac | |
21 return 1 | |
22 } | |
23 | |
24 has_audio() { | |
25 ffprobe "$1" 2>&1 | grep -qE 'Stream .* Audio: ' | |
26 } | |
27 | |
28 replace_audio() { | |
29 $ffmpeg_common -i "$1" -i "$2" \ | |
30 -c:v copy -map 1:v:0 -map 0:a:0 -shortest \ | |
31 "$3" </dev/null | |
32 } | |
33 | |
34 side_by_side() { | |
35 $ffmpeg_common -i "$1" -i "$2" \ | |
36 -filter_complex " | |
37 amix=inputs=2:duration=shortest; \ | |
38 [1:v][0:v] scale2ref=oh*mdar:h=in_h:[v1][v0]; | |
39 [v0][v1] hstack=shortest=1, | |
40 scale='2*trunc(iw/2)':'2*trunc(ih/2)'" \ | |
41 -shortest \ | |
42 "$3" </dev/null | |
43 } | |
44 | |
45 mix_audio() { | |
46 if has_audio "$2"; then | |
47 $ffmpeg_common -i "$1" -i "$2" \ | |
48 -filter_complex "amerge=inputs=2" \ | |
49 "$3" </dev/null | |
50 else | |
51 replace_audio "$1" "$2" "$3" | |
52 fi | |
53 } | |
54 | |
55 mix_audio_video() { | |
56 if has_audio "$2"; then | |
57 $ffmpeg_common -i "$2" \ | |
58 -i "$1" \ | |
59 -filter_complex " | |
60 [0:v] scale=w=${4:-1920}:h=${5:-1080}, p… | |
61 [video0][1:v] blend=all_mode=average:sho… | |
62 amix=inputs=2:duration=shortest:weights=… | |
63 "$3" </dev/null | |
64 else | |
65 $ffmpeg_common -i "$2" \ | |
66 -i "$1" \ | |
67 -filter_complex " | |
68 [0:v] scale=w=${4:-1920}:h=${5:-1080}, p… | |
69 [video0][1:v] blend=all_mode=average:sho… | |
70 "$3" </dev/null | |
71 fi | |
72 } | |
73 | |
74 replace_face() { | |
75 face_replacement="$1" | |
76 input="$2" | |
77 output="$3" | |
78 | |
79 if is_image "$input" | |
80 then | |
81 ext="${input##*.}" | |
82 tmp=/tmp/replace_face_$$.$ext | |
83 else | |
84 tmp="/tmp/replace_face_$$.mkv" | |
85 fi | |
86 | |
87 $HOME/.local/bin/deface "$input" --replacewith img \ | |
88 --replaceimg "$face_replacement" -o "$tmp" >/dev/null 2>… | |
89 if has_audio "$input"; | |
90 then | |
91 replace_audio "$input" "$tmp" "$output" | |
92 rm -f "$tmp" | |
93 else | |
94 mv "$tmp" "$output" | |
95 fi | |
96 } | |
97 | |
98 process_filter() { | |
99 # Filters which do not require image2mkv | |
100 case "$1" in | |
101 smith) | |
102 replace_face "${mediadir}/smith.png" "$2" "$3" | |
103 return 0;; | |
104 wat) | |
105 replace_face "${mediadir}/wat.png" "$2" "$3" | |
106 return 0;; | |
107 zucc) | |
108 replace_face "${mediadir}/zucc.png" "$2" "$3" | |
109 return 0;; | |
110 esac | |
111 | |
112 # extend duration if less than a second or image | |
113 if is_image "$2" | |
114 then | |
115 tmp=/tmp/ffmpeg-effect.$$.mkv | |
116 trap 'rm -f "$tmp"' EXIT INT TERM HUP | |
117 $ffmpeg_common -loop 1 -i "$2" -t 20 -vf "pad=ceil(iw/2)… | |
118 set -- "$1" "$tmp" "$3" | |
119 fi | |
120 | |
121 case "$1" in | |
122 amplify) | |
123 $ffmpeg_common -i "$2" -filter:a "volume=10" "$3";; | |
124 banjo) | |
125 replace_audio "${mediadir}/banjo.mp3" "$2" "$3";; | |
126 bounce) | |
127 repeats=0 | |
128 $ffmpeg_common -i "$2" \ | |
129 -filter_complex "[0:v]reverse[vrev];[0:v][vrev]c… | |
130 -filter_complex "[0:a]areverse[arev];[0:a][arev]… | |
131 -map "[v]" -map "[a]" \ | |
132 "$3" </dev/null;; | |
133 breakingnews) | |
134 mix_audio "${mediadir}/breakingnews.opus" "$2" "$3";; | |
135 celtify) | |
136 mix_audio "${mediadir}/broceliande.ogg" "$2" "$3";; | |
137 concatenate) | |
138 mix_audio "${mediadir}/concatenate.mp3" "$2" "$3";; | |
139 crimetv) | |
140 mix_audio "${mediadir}/crimetv.opus" "$2" "$3";; | |
141 curb) | |
142 mix_audio "${mediadir}/curb.opus" "$2" "$3";; | |
143 daybowbow) | |
144 replace_audio "${mediadir}/day-bow-bow.ogg" "$2" "$3";; | |
145 deathmetal) | |
146 mix_audio "${mediadir}/artificial-brain.opus" "$2" "$3";; | |
147 developers) | |
148 mix_audio "${mediadir}/developers.opus" "$2" "$3";; | |
149 dontdoit) | |
150 mix_audio "${mediadir}/dontdoit.mp3" "$2" "$3";; | |
151 dontsaytoyourmother) | |
152 mix_audio "${mediadir}/dont-say-to-your-mother.opus" "$2… | |
153 doomify) | |
154 mix_audio "${mediadir}/doom.mp3" "$2" "$3";; | |
155 dutchapprove) | |
156 mix_audio_video "${mediadir}/krul.mkv" "$2" "$3" 524 480… | |
157 french) | |
158 mix_audio_video "${mediadir}/french-friday.mp4" "$2" "$3… | |
159 FRENCH) | |
160 mix_audio_video "${mediadir}/french-thursday.mp4" "$2" "… | |
161 imam) | |
162 mix_audio "${mediadir}/imam.mp3" "$2" "$3";; | |
163 lop|loop|looop|loooop) | |
164 # Mr. Fibonacci | |
165 [ "$1" == "lop" ] && repeats=3 | |
166 [ "$1" == "loop" ] && repeats=5 | |
167 [ "$1" == "looop" ] && repeats=8 | |
168 [ "$1" == "loooop" ] && repeats=13 | |
169 i=0 | |
170 input="" | |
171 while test $i -lt $repeats; do | |
172 input="$input -i $2" | |
173 i=$((i + 1)) | |
174 done | |
175 $ffmpeg_common $input \ | |
176 -filter_complex "concat=n=${repeats}:v=1:a=1 [v]… | |
177 "$3" </dev/null;; | |
178 mow) | |
179 mix_audio "${mediadir}/lawn-mower.mp3" "$2" "$3";; | |
180 namflashback) | |
181 mix_audio "${mediadir}/namflashback.opus" "$2" "$3";; | |
182 news) | |
183 mix_audio "${mediadir}/news.opus" "$2" "$3";; | |
184 pullmyfinger) | |
185 mix_audio "${mediadir}/fart.opus" "$2" "$3";; | |
186 reverse) | |
187 $ffmpeg_common -i "$2" \ | |
188 -vf reverse -af areverse \ | |
189 "$3" </dev/null;; | |
190 richardstrauss) | |
191 mix_audio "${mediadir}/richardstrauss.opus" "$2" "$3";; | |
192 sadviolin) | |
193 mix_audio "${mediadir}/sad-violin.opus" "$2" "$3";; | |
194 science) | |
195 replace_audio "${mediadir}/accelerating-science.mp3" "$2… | |
196 scrollify) | |
197 mix_audio "${mediadir}/elder_scrolls.mp3" "$2" "$3";; | |
198 sendtohell|amsterdamify) | |
199 mix_audio_video "${mediadir}/hell.mkv" "$2" "$3" 1920 10… | |
200 sexify) | |
201 mix_audio "${mediadir}/careless_whisper.mp3" "$2" "$3";; | |
202 slavify) | |
203 replace_audio "${mediadir}/remove-kebab.opus" "$2" "$3";; | |
204 slowdown) | |
205 $ffmpeg_common -i "$2" \ | |
206 -filter_complex "[0:v]setpts=2.0*PTS[v];[0:a]ate… | |
207 "$3" </dev/null;; | |
208 speedup) | |
209 $ffmpeg_common -i "$2" \ | |
210 -filter_complex "[0:v]setpts=0.5*PTS[v];[0:a]ate… | |
211 "$3" </dev/null;; | |
212 techno) | |
213 replace_audio "${mediadir}/techno.mp3" "$2" "$3";; | |
214 technodrugs) | |
215 $ffmpeg_common -i "${mediadir}/techno.mp3" -i "$2" \ | |
216 -filter:v "tmix=frames=9:weights='0.2 0.4 0.6 0.… | |
217 -map 1:v:0 -map 0:a:0 -shortest \ | |
218 "$3" </dev/null;; | |
219 thin) | |
220 $ffmpeg_common -i "$2" \ | |
221 -vf "scale=iw/4:ih,setsar=1" \ | |
222 "$3" </dev/null;; | |
223 torture) | |
224 side_by_side "${mediadir}/clockworkorange.mkv" "$2" "$3"… | |
225 trumpapprove) | |
226 mix_audio "${mediadir}/trump-approves.opus" "$2" "$3";; | |
227 usa) | |
228 mix_audio_video "${mediadir}/american-asmr.mkv" "$2" "$3… | |
229 USA) | |
230 mix_audio_video "${mediadir}/american-ambiente.mp4" "$2"… | |
231 USAUSA) | |
232 mix_audio "${mediadir}/USAUSA.opus" "$2" "$3";; | |
233 wide|widen) | |
234 $ffmpeg_common -i "$2" \ | |
235 -vf "scale=iw*4:ih,crop=iw/4:ih:iw/4:ih,setsar=1… | |
236 "$3" </dev/null;; | |
237 ww1) | |
238 mix_audio "${mediadir}/ww1.mp3" "$2" "$3";; | |
239 yellow) | |
240 mix_audio "${mediadir}/yellow.opus" "$2" "$3";; | |
241 *) usage;; | |
242 esac | |
243 } | |
244 | |
245 while getopts 'hn:' opt; do | |
246 case $opt in | |
247 h) usage;; | |
248 n) n="$OPTARG";; | |
249 *) break;; | |
250 esac | |
251 done | |
252 shift $((OPTIND - 1)) | |
253 if [ "$#" -lt 3 ] || [ ! -r "$2" ]; then | |
254 usage | |
255 fi | |
256 | |
257 if process_filter "$1" "$2" "$3"; then | |
258 printf '%s\n' "$3" | |
259 else | |
260 exit $? | |
261 fi | |
262 |