ffmpeg: create slideshow of unknown number of images with transition - ffmpeg

hope someone could help me with this. Kinda new with ffmpeg and a bit stumped.
Given an input of a set of numbered images in a folder, I want to generate a video with each image shown for 60 seconds. I would love to use a default transition between each images.
The following code, correctly generates an mp4 without transitions:
ffmpeg -framerate 1/60 -pattern_type glob -i "*.png" -vcodec libx264 \
-pix_fmt yuv420p -r 30 -threads 4 -crf 25 -refs 1 -bf 0 -coder 0 -g 25 \
-keyint_min 15 -movflags +faststart no_audio_output.mp4
But when I try to add a default transition (supported in the version of ffmpeg I'm using that is the 5.1):
ffmpeg -framerate 1/60 -pattern_type glob -i "WC*.png" -filter_complex
xfade=transition=circleopen:duration=5:offset=55 -vcodec libx264 \
-pix_fmt yuv420p -r 30 -threads 4 -crf 25 -refs 1 -bf 0 -coder 0 -g 25 \
-keyint_min 15 -movflags +faststart no_audio_output.mp4
I have as error:
Cannot find a matching stream for unlabeled input pad 1 on filter Parsed_xfade_0
I googled a lot but still the solution is unclear. All the examples I found have been designed to deal with a slideshow/input with a define number of pieces while in my case the folder could contain any number of images.
Thanks all for your help!

Related

FFMPEG Drawtext Time

I'm trying to set when the drawtext of this FFmpeg command starts, I've tried with start_number but looks like it will not do the trick.
ffmpeg -i 1.mp4 -acodec aac -keyint_min 20 -r 20 -vcodec libx264 -crf 22 -b 1000k -bt 1000k -y -v 0 -bf 16 -threads 0 -vf drawtext="start_number=20:fontfile=/home/admin/script/impact.ttf:text='My Text':fontsize=15:fontcolor=white:x=w-30*t:y=10" output.mp4
I've tried different approaches, but nothing seems to work
start_number is a parameter for used for an input image sequence/pattern.
If you want to draw a text on a video starting from the 3rd second you could use:
ffmpeg -i 1.mp4 -vf drawtext="text='My Text':enable=gt(t\,3)" output.mp4
Please notice that encoding parameters were omitted and you should add them to meet your requirements.

ffmpeg sorting order issue while creating video

I am able to successfully able to convert images to video using below command where all photos of
out directory is used.
$command1 = "ffmpeg -r 1/1 -framerate 25 -pattern_type glob -i 'out/*.jpg' -c:v libx264 -profile:v high -crf 20 -pix_fmt yuv420p -vf 'pad=ceil(iw/2)*2:ceil(ih/2)*2' out/1.mp4";
exec($command1);
However the photos are getting picked randomly and I want to pick them using sort order example.
Pic1.jpg, Pic2.jpg, Pic2.jpg ......
Please suggest what to do here?
You could try using a prefix start_number instead of -pattern_type glob.
As explained here, the * glob does not work as expected.
If your images are in these order:
Pic1.jpg, Pic2.jpg, Pic3.jpg and so on...
Use -start_number instead, the updated ffmpeg:
ffmpeg -r 1/1 -framerate 25 -start_number 1 -i 'out/Pic%d.jpg' -c:v libx264 -profile:v high -crf 20 -pix_fmt yuv420p -vf 'pad=ceil(iw/2)*2:ceil(ih/2)*2' out/1.mp4

FFMPEG: Encoding WEBM with fast-seek and copyts leads to wrong video length

I'm trying to convert a scene from a soft-subbed MKV file into a hard-subbed WEBM file with two-pass. The video encodes fine, but the file shows the wrong length when opened on a media player (it's showing as if I had encoded the original file from the starting point all the way to the end).
This is the command I'm using:
set timestamp=-ss 12:59.069 -to 16:14.277
ffmpeg -y %timestamp% -copyts -i source.mkv -shortest -c:v libvpx-vp9 -pass 1 -b:v 0 -crf 33 -threads 8 -speed 4 -tile-columns 6 -frame-parallel 1 -an -sn -vf scale=-1:720,subtitles=source.mkv -f webm NUL
ffmpeg -y %timestamp% -copyts -i source.mkv -shortest -c:v libvpx-vp9 -pass 2 -b:v 0 -crf 33 -threads 8 -speed 2 -tile-columns 6 -frame-parallel 1 -auto-alt-ref 1 -lag-in-frames 25 -c:a libopus -b:a 64k -sn -vf scale=-1:720,subtitles=source.mkv -f webm out.webm
When opening the video in MPC-BE, the video plays regularly until around the point shown on https://i.stack.imgur.com/6bRwc.png (which is where the scene I wanted to cut out ends) then it just skips to the end of the file, and this wrong length is giving me all sorts of issues when I try to use the encoded video.
Apparently, your player doesn't like a non-zero starting timestamp (at least in WebMs).
So, reset the timestamps before writing (I assume you're using copyts for the subtitles filter alignment).
In pass 2,
ffmpeg -y %timestamp% -copyts -i source.mkv -shortest -c:v libvpx-vp9 -pass 2 -b:v 0 -crf 33 -threads 8 -speed 2 -tile-columns 6 -frame-parallel 1 -auto-alt-ref 1 -lag-in-frames 25 -c:a libopus -b:a 64k -sn -vf scale=-1:720,subtitles=source.mkv -output_ts_offset -12:59.069 -f webm out.web
where the value for ts offset is the negative of your ss value.

FFMPEG avoid_negative_ts makes video start not from keyframe

Let's say I want to cut part of the mp4 video and resize it from 1280x720 to 854x480.
My command looks like this:
ffmpeg -ss 45 -i source.mp4 -ss 10 -to 20 \
-acodec aac -ar 44100 -ac 2 -c:v libx264 \
-crf 26 -vf scale=854:480:force_original_aspect_ratio=decrease,pad=854:480:0:0,setsar=1/1,setdar=16/9 \
-video_track_timescale 29971 -pix_fmt yuv420p \
-map_metadata 0 -avoid_negative_ts 1 -y dest.mp4
The problem is, when I don't use option avoid_negative_ts, resulting video has some issues with time bases etc, therefore it cannot be later converted by other libs, for example Swift's AVFoundation.
But when I use this option - video does not start with keyframe.
By using ffprobe I see start_time=0.065997 or other times other than 0.
How can I use option avoid_negative_ts and have a video that starts with keyframe?

ffmpeg complex_filter fadeout not working

Essensially what I am trying to do is concat a.mp4 with b.mp4, display my set of %c.png overlayed ontop for the entire duration of the video and also show d.png overlayed ontop but only for 1 second and then have it fade out. ALL of this works except that d.png remains overlayed and never fades out:
ffmpeg -i ./temp/a.mp4 -i media/b.mp4 -i media/splash/%c.png -i ./temp/d.png -y -filter_complex [0:v]scale=568x320,setpts=PTS-STARTPTS[v0];[1:v]scale=568x320,setpts=PTS-STARTPTS[v1];[2:v]scale=212:242,setpts=PTS-STARTPTS[v2];[3:v]trim=duration=0.5,fade=t=out:st=0:d=0.5[3:v];[v0][0:a][v1][1:a]concat=n=2:v=1:a=1[bg][a];[bg][v2]overlay=(W-w)/2:(H-h)/2,format=yuv420p[v];[v][3:v]overlay=(W-w)/2:(H-h)/2,format=yuv420p[v] -map [v] -map [a] -r 29.97 -vcodec libx264 -s 568x320 -flags +loop -b 400k -bufsize 4M -bt 256k -refs 1 -coder 0 -me_range 16 -subq 4 -partitions +parti4x4+parti8x8+partp8x8 -g 250 -keyint_min 25 -level 30 -qmin 10 -qmax 51 -qcomp 0.6 -trellis 2 -sc_threshold 40 -i_qfactor 0.71 -acodec aac -strict experimental -ab 80k -ar 48000 -ac 2 -strict experimental -f mp4 -metadata:s:v:0 rotate=90 ./temp/1428723401371.mp4
Lord Neckbeard, I know you're out there. I've been reading your stackoverflow posts on fade in/out with complex_filter for a few hours now and nothing I've tried has succeeded. Please Lord, accept the above as my humble offering to you and help me fadeout d.png after 1 second.
Try this:
ffmpeg -y -i a.mp4 -i b.mp4 -i c_%03d.png -loop 1 -i d.png -filter_complex \
"[0:v]scale=568:-2,setpts=PTS-STARTPTS[v0]; \
[1:v]scale=568:-2,setpts=PTS-STARTPTS[v1]; \
[2:v]scale=212:-1,setpts=PTS-STARTPTS[v2]; \
[3:v]trim=duration=0.5,fade=t=out:st=0:d=0.5[v3]; \
[v0][0:a][v1][1:a]concat=n=2:v=1:a=1[bg][a]; \
[bg][v2]overlay=(W-w)/2:(H-h)/2[bg2]; \
[bg2][v3]overlay=(W-w)/2:(H-h)/2,format=yuv420p[v]" \
-map "[v]" -map "[a]" -c:v libx264 -preset fast -c:a aac -strict experimental \
-ab 80k -metadata:s:v:0 rotate=90 -movflags +faststart output.mp4
Avoid using the same link labels for input and output in each filterchain:
Wrong: [v3]filter0,filter1[v3]
Right: [v3]filter0,filter1[foo]
Adding -loop 1 as an input option for d.png allowed the fade to work as expected. Otherwise it was acting as a single frame instead of a continuous stream. By default overlay will loop the last frame of the overlaid input, so that is why it just stayed there. That behavior can be changed with the eof_action overlay option.
By default the image file demuxer will use -framerate 25 for c_%03d.png, so you may want to add this as an input option with an appropriate value to change the frame rate and therefore the duration of particular input.
Use the x264 presets instead of listing a legion of encoding options. See FFmpeg Wiki: H.264 Encoding Guide.
Not all players will pay attention to the video stream rotation metadata.
Overlay filter has a setting for "repeatlast", it is set by default to be ON. set repeatlast=0 in your overlay filterchain and the main video will then be seen. Sorry I am a couple years too late, hopefully this answer will still help someone.

Resources