How to make ffmpeg automatically fill frames? - ffmpeg

I want to use ffmpeg to convert a sequence of images to a video, the images are got in realtime, the interval of getting image is changeable, maybe i get next image in 1 second or even 1 millisecond.
I want the target video in a special fps(like 100), now my implement is creating a loop, which fade ffmpeg last image then sleep(like 10ms).
Do you guys know some options could let ffmpeg fill frames automatically?
If that option do exist, i wonder is that possible to make video real fps is half of it is claimed.
My ffmpeg command likes follow:
ffmpeg -f image2pipe -r 100 -i pipe:0 -f flv -r 100 pipe:1

You can use
ffmpeg -f image2pipe -use_wallclock_as_timestamps 1 -i pipe:0 -f flv -vsync cfr -r 100 pipe:1
FFmpeg will set each incoming frame's timestamp to the time it is received. SInce the output rate is set and mode is constant frame rate, ffmpeg will duplicate the last frame till next input frame is received, or drop if two frames are less than 10ms apart. Change -r to 1000 to keep frames only a millisecond apart.

Related

Sync files timestamp with ffmpeg

I'm capturing video from 4 cameras connected with HDMI through a capture card. I'm using ffmpeg to save the video feed from the cameras to multiples jpeg files (30 jpeg per second per camera).
I want to be able to save the images with the capture time. Currently I'm using this command for one camera:
ffmpeg -f video4linux2 -pixel_format yuv420p -timestamps abs -I /dev/video0 -c:a jpeg -t 60 -ts_from_file 2 camera0-%5d.jpeg
It saves my file with the names camera0-00001.jpg, camera0-00002.jpg, etc.
Then I rename my file with camera0-HH-mm-ss-(1-30).jpeg based on the modified time of the file.
So in the end I have 4 files with the same time and same frame like this:
camera0-12-00-00-1.jpeg
camera1-12-00-00-1.jpeg
camera2-12-00-00-1.jpeg
camera3-12-00-00-1.jpeg
My issue is that the file may be offset from one to two frame. They may have the same name but sometime one or two camera may show different frame.
Is there a way to be sure that the capture frames has the actual time of the capture and not the time of the creation of the file?
You can use the mkvtimestamp_v2 muxer
ffmpeg -f video4linux2 -pixel_format yuv420p -timestamps abs -copyts -i /dev/video0 \
-vf setpts=PTS-STARTPTS -vsync 0 -vframes 1800 camera0-%5d.jpeg \
-c copy -vsync 0 -vframes 1800 -f mkvtimestamp_v2 timings.txt
timings.txt will have output like this
# timecode format v2
1521177189530
1521177189630
1521177189700
1521177189770
1521177189820
1521177189870
1521177189920
1521177189970
...
where each reading is the Unix epoch time in milliseconds.
I've switched to output frame count limit to stop the process instead of -t 60. You can use -t 60 for the first output since we are resetting timestamps there, but not for the second. If you do that, remember to only use the first N entries from the text file, where N is the number of images produced.

ffmpeg dump specific length of video after seeking PICT_TYPE_I keyframe

I have a flv video and want to dump let's say 3s length of the video after first keyframe PICT_TYPE_I meet after 00:39. I ready the document of ffmpeg seeking and quote here
ffmpeg -ss 00:23:00 -i Mononoke.Hime.mkv -frames:v 1 out1.jpg
This example will produce one image frame (out1.jpg) at the
twenty-third minute from the beginning of the movie. The input will be
parsed using keyframes, which is very fast. As of FFmpeg 2.1, when
transcoding with ffmpeg (i.e. not just stream copying), -ss is now
also "frame-accurate" even when used as an input option. Previous
behavior (seeking only to the nearest preceding keyframe, even if not
precisely accurate) can be restored with the -noaccurate_seek option.
So I think if I use this command (put -ss before -i)
ffmpeg -noaccurate_seek -ss 00:39 -i input.flv -r 10 -s 720x400 -t 3.12 dump.flv
And this should dump a video that last 3.12s and begin with the first keyframe after 00:39 right? after all, this is what I need.
But the result is dump.flv not start with a keyframe, ie a PICT_TYPE_I frame.
I know I could find all keyframe start time with ffprobe and re-calculate the -ss seeking time to achieve this. But is there a better way?
If audio is of no concern, you can use
ffmpeg -ss 39.00 -i in.flv -vf select='if(eq(pict_type,I),st(1,t),gt(t,ld(1)))',setpts=N/FRAME_RATE/TB -an -t 3.12 out.flv
Here, the select filter discards all frames before the first keyframe which is after the seek point. The t value controls the total duration selected.
Do note that video duration is quantized i.e. a 25 fps video can have duration in steps of 0.04s.

FFmpeg Slideshow issues

trying to get my head around ffmpeg to create a slideshow where each image is displayed for ~5 seconds with some audio. created a bat file to run the following so far:
ffmpeg -f image2 -i image-%%03d.jpg -i music.mp3 output.mpg
It gets the images and displayes them all very fast in the first second of the video, it then plays out the rest of the audio while showing the last image.
I want to make the images stay up longer (about 5 seconds), and stop the video after the last frame (not playing the rest of the song), are either of these things possible? i could hack the frame rate thing i guess by having hundreds of the same image in order to keep it up longer, but this is far from ideal!
Thanks
The default encoder for mpg output, mpeg1video, is strict about the allowed frame rates, so an input and an output -r are required:
ffmpeg -r 1/5 -i image-%03d.jpg -i music.mp3 -r 25 -qscale:v 2 -shortest -codec:a copy output.mpg
The input images will have a frame rate of 1 frame every 5 seconds and the output will duplicate frames to reach 25 frames per second.
-f image2 is generally not required.
-qscale:v can control output quality. A sane range is 2-5.
-shortest will make the output duration the same as the shortest input duration.
-codec:a copy copy your MP3 audio instead of re-encoding.
MPEG-1 video has more modern alternatives. See the FFmpeg and x264 Encoding Guide for more info.
Also see:
* FFmpeg FAQ: How do I encode single pictures into movies?
* FFmpeg Wiki: Create a video slideshow from images
You could use the filter fps instead of output framerate
ffmpeg -r 1/5 -i img%03d.png -i musicfile -c:v libx264 -vf fps=25 -pix_fmt yuv420p out.mp4
This however skips the last image for me strangely.

FFmpeg frame rate when converting from GIF to MP4

I have a GIF image. I am trying to convert it to MP4.
ffmpeg -f image2 -r {delay_time_of_gif_between_each_frame}/1 -i temp/%05d.png -vcodec libx264 video.mp4
This MP4 is not running at the same speed when compared to the original GIF. How do I make it to run with the same speed?
It seems I am making mistakes with the -r property. I played with it but don't get anything useful. I even removed it. Still it isn't working.
If you already know the time of delay between subsequent frames, then you need to take the inverse of it to convert it to a frame rate. For example, if the time between each frame is 40ms (or 0.04s), then the inverse would be 1 divided by 0.04, thus 25 fps.
You can not simply divide the time between frames by 1, since division by 1 will give you the same result as before.
So, try either of these again:
ffmpeg -f image2 -r 1/0.04 -i temp/%05d.png -c:v libx264 out.mp4
ffmpeg -f image2 -r 25 -i temp/%05d.png -c:v libx264 out.mp4
Note that the default input frame rate for image2 is 25 anyway, but this was just for illustration.
Also, you can change the frame rate of the output video as well, by putting -r after the input file, which should make a difference.
ffmpeg -f images -i temp/%05d.png -c:v libx264 -r 25 out.mp4
Although this question is somewhat older:
Current versions of ffmpeg automatically determine the delays between the frames according to the information in the gif images, so no need to set the frame rate in the command.

ffmpeg frame grabbing slow on mp4 files

The following ffmpeg frame grab command takes a long time to grab an image from the mp4 file.
ffmpeg.exe -itsoffset -200 -i C:\93844428.mp4 -vcodec mjpeg -vframes 1 -y -an -f rawvideo -s 640x360 C:\test\out1.jpg
For a 20MB file (about 2 minutes of video) it takes up to about 6 seconds to find the image depending on what offset (in seconds) you ask to grab it.
For a 100MB it can anything in many minutes if you request a large offset.
This only appears to be an issue with mp4 files.
Is there anything that can be done to improve this?
This logic is inefficient to do a frame grab. Don't use itsoffset. If you want frame at a particular location use the -ss switch to set the time offset you want the frame from.

Resources