Reputation: 53
Using an arbitrary source video, I would like to INDEPENDENTLY fade in/fade out a minimum of three .png overlays/watermarks at various times throughout the video. I'm having trouble getting the syntax right for the filter chain.
In these failed attempts below, I'm using four transparent .png images all at 1920x1080 using the same sized source input video. No scaling/positioning needed, just the overlays fading in and out at the defined times.
I have the functionality working without fade, unsing 'enable', like so:
ffmpeg -i vid1.mp4 -loop 1 -i img1.png -i img2.png -i img3.png -i img4.png -filter_complex
"overlay=0:0:enable='between(t,8,11)' [tmp];
[tmp]overlay=0:0:enable='between(t,10,15)'[tmp1];
[tmp1]overlay=0:0:enable='between(t,15,138)'[tmp2];
[tmp2]overlay=0:0:enable='between(t,140,150)"
-c:v libx264 -c:a copy
-flags +global_header -shortest -s 1920x1080 -y out.mp4
I just want the same control, using fade in/out.
The following almost works as I'd like but I obviously don't want the entire output stream to fade out. I realize that adding the fade=out to lines 7, 8 & 9 is fading the combined output (starting at line 7), but this is as close as I've come where I see each overlay image actually fading. The defined fades in lines 3, 4 and 5 apparently don't affect anything, and that's where I defined them originally. When I copied them to the output stream, the fade works on each overlay image, but again I don't want it to affect the entire output stream, just the individual overlays.
ffmpeg -i vid1.mp4 -loop 1 -i img1.png -i img2.png -i img3.png -i img4.png -filter_complex
"[1:v]fade=out:st=3:d=1[watermark0];
[2:v]fade=out:st=4:d=1[watermark1];
[3:v]fade=out:st=5:d=1[watermark2];
[4:v]fade=out:st=6:d=1[watermark3];
[0:v][watermark0] overlay=0:0 [tmp0];
[tmp0][watermark1] overlay=0:0,fade=out:st=4:d=1 [tmp1];
[tmp1][watermark2] overlay=0:0,fade=out:st=6:d=1 [tmp2];
[tmp2][watermark3] overlay=0:0,fade=out:st=8:d=1 [out]" -map "[out]" -c:v libx264 -c:a copy
-flags +global_header -shortest -s 1920x1080 -y out.mp4
I've also tried 'split' with similar results to the above, but the fade only seems to work on the first image (this one uses fade in as well):
ffmpeg -i vid.mp4 -loop 1 -i img1.png -i img2.png -i img3.png -i img4.png -filter_complex
"[1:v]split=4[wm1][wm2][wm3][wm4];
[wm1]fade=in:st=1:d=1:alpha=1,fade=out:st=3:d=1:alpha=1[ovr1];
[wm2]fade=in:st=2:d=1:alpha=1,fade=out:st=4:d=1:alpha=1[ovr2];
[wm3]fade=in:st=3:d=1:alpha=1,fade=out:st=5:d=1:alpha=1[ovr3];
[wm4]fade=in:st=4:d=1:alpha=1,fade=out:st=6:d=1:alpha=1[ovr4];
[0:v][ovr1]overlay=0:0[base1];
[base1][ovr2]overlay=0:0[base2];
[base2][ovr3]overlay=0:0[base3];
[base3][ovr4]overlay=0:0[out]" -map "[out]"
-t 10 -c:v libx264 -c:a copy -flags +global_header -shortest -s 1920x1080 -y out.mp4
Any help is greatly appreciated! :)
Upvotes: 2
Views: 2160
Reputation: 1
firstly thank you for your answer and code it helped immensely for me to tinker with. I've posted my own code (take note I'm not a full expert on FFMPEG like youa re.) My task was to fade in and out 3 pairs of titles across a 20.760 second video - the titles were transparent PNGs. From your initial code I did the following:
a. Changed all "enable(t,start,end)" to "enable(t,0,999)" so they don't need to be adjusted or accounted for (if your video is shorter than 999 seconds) b. Used absolute fade straight in and out methods for each image. Though the processing time is longer, it allows you to set the absolute end and start time of each title. c. Added a -t 20.760 which represents the total length of the underlying video for which titles are to be added. This prevents an endless loop.
ffmpeg -i sourcevideo.mp4 -loop 1 -i servtit1.png -loop 1 -i servtit2.png -loop 1 -i servtit3.png -loop 1 -i servtit4.png -loop 1 -i servtit5.png -loop 1 -i servtit6.png -filter_complex
"[1]fade=t=in:st=0.5:d=1,fade=t=out:st=2.5:d=1[ovr1];
[2]fade=t=in:st=2.5:d=1,fade=t=out:st=4.44:d=1[ovr2];
[3]fade=t=in:st=6.8:d=1,fade=t=out:st=9.6:d=1[ovr3];
[4]fade=t=in:st=9.6:d=1,fade=t=out:st=12.4:d=1[ovr4];
[5]fade=t=in:st=12.5:d=1,fade=t=out:st=15.2:d=1[ovr5];
[6]fade=t=in:st=15.2:d=1,fade=t=out:st=17.9:d=1[ovr6];
[0:v][ovr1]overlay=0:0:enable='between(t,0,999)'[base1]; [base1]
[ovr2]overlay=0:0:enable='between(t,0,999)'[base2]; [base2]
[ovr3]overlay=0:0:enable='between(t,0,999)'[base3]; [base3]
[ovr4]overlay=0:0:enable='between(t,0,999)'[base4]; [base4]
[ovr5]overlay=0:0:enable='between(t,0,999)'[base5]; [base5]
[ovr6]overlay=0:0:enable='between(t,0,999)'[out]" -map "[out]" -c:v libx264 -c:a copy -flags +global_header -t 20.760 -shortest -y outputvideo.mp4
Thanks again for the assistance.
Upvotes: 0
Reputation: 92928
Use
ffmpeg -i vid.mp4 -loop 1 -i img1.png -loop 1 -i img2.png -loop 1 -i img3.png
-loop 1 -i img4.png -filter_complex
"[1]fade=st=0:d=1:alpha=1,fade=out:st=2:d=1:alpha=1,trim=0:3,setpts=PTS+12/TB[ovr1];
[2]fade=st=0:d=1:alpha=1,fade=out:st=2:d=1:alpha=1,trim=0:3,setpts=PTS+25/TB[ovr2];
[3]fade=st=0:d=1:alpha=1,fade=out:st=2:d=1:alpha=1,trim=0:3,setpts=PTS+44/TB[ovr3];
[4]fade=st=0:d=1:alpha=1,fade=out:st=2:d=1:alpha=1,trim=0:3,setpts=PTS+73/TB[ovr4];
[0:v][ovr1]overlay=0:0:enable='between(t,12,15)'[base1];
[base1][ovr2]overlay=0:0:enable='between(t,25,28)'[base2];
[base2][ovr3]overlay=0:0:enable='between(t,44,47)'[base3];
[base3][ovr4]overlay=0:0:enable='between(t,73,76)'[out]" -map "[out]"
-c:v libx264 -c:a copy -flags +global_header -shortest -s 1920x1080 -y out.mp4
A single image input, if not looped, is treated as a video input of one frame. I've added loops to the other images. This makes each input a video stream of indefinite duration.
For each image, a fade in and out is applied. For the time values here, assume you're applying at the start of the streams. Time offset for the overlays happen later. After the fades, trim the stream to keep video only till the fade-out has finished. Then apply a time offset to match the start for the overlay (to overlay an image starting at 33 seconds, it's PTS+33/TB
).
Then the overlays in series, just like you already did. I've added enable condition to shorten execution time.
Upvotes: 5