FFMPEG - convert into variable framerate by removing duplicate frames - ffmpeg

I have slideshow video (i.e. 10GB) 1080p quality (30 FPS), and each image lasts about 15 seconds ...
Is there any option with FFMPEG, to convert those 15 seconds periods from 30 FPS(because they are just duplicate frames) into i.e. 1 fps, thus, making the video small size...
the only periods that should keep original FPS is the fadeout period from image to image (that lasts 3 seconds... they are not duplicate frames, each frame is different because of fade-out effect).

You just need to re-encode with ffmpeg using a mid CRF value, like between 24-27. I-frames will be smaller but mainly P-frames which are static will only take few dozen bytes to store. Actually decimating the static frames and keeping the fade sequences at full FPS can be done but will be cumbersome and subject to trial and error. Just doing a simple re-encode will get you most of the size savings you would have gotten
Basic command is
ffmpeg -i in.mp4 -crf 25 -c:a copy out.mp4

Related

Segmenting a video live stream into videos of a fixed length using ffmpeg

I want to use an ffmpeg command to save segments of length 10 seconds from a video being streamed via HTTP using VLC.
The command I used to carry out the task is:
ffmpeg -i http://[Local IPv4 address]:8080 -f segment -segment_time 10 -vcodec copy -acodec copy -reset_timestamps 1 video%03d.mp4
However, the lengths of the output videos I'm receiving are around 8.333 or 16.666 seconds in duration. (The videos video000.mp4, video005.mp4, video010.mp4, video015.mp4... have duration of around 16.666 seconds and the remaining videos have duration of around 8.333 seconds).
I'm aware that the segmentation of input video happens based on the occurrences of keyframes in the video. It appears that the key frames in the video being streamed occur with an interval of around 8 seconds.
Is there a way to obtain video segments that are closer to 10 seconds in duration from the live stream of such a video?
Also, I occasionally get the "Non-monotonous DTS in output stream 0:0" warning while executing the above command. I tried using different flags (+genpts, +igndts, +ignidx) hoping that the warning message would not be displayed, but no luck. Is it possible that there is any correlation between this warning and the issue with lengths of the segments?

Reduce file size of a video with ffmpeg

So i'm tried to reduce video filesize by scale down video -vf 640:-2, but nothing changes. Scale down or up doesnt affect video filesize
I've read ffmpeg wiki about Scaling but it dont have any information about scale and filesize.
When i'm scale down images, filesize have big drop but for video, nothing changes
You can use -crf option to reduce final video size.
The range of the CRF scale is 0–51, where 0 is lossless (for 8 bit only, for 10 bit use -qp 0), 23 is the default, and 51 is worst quality possible.
-crf 23 (for default)
You have to use H.264 encoder. this will help almost all type of video. works batter in mp4 videos.

ffpmeg extracting frames produces too many images

I'm using FFMpeg to extract some png files from a video using the following command:
ffmpeg -i FILE.mp4 -vf "select=not(mod(n\,75))" -vsync vfr img_%03d.png
the source video has a duration of 2898 seconds and a framerate of 25 FPS. This means I should be grabbing a picture every 3 seconds for 966 pictures.
However, instead I'm getting 1158 pictures. After doing some math I've discovered that that is the within 2 pictures of what I would expect if I was grabbing the 75th frame from a 30 FPS video.
I've tried -framerate=25 but it still produces the same amount of pictures. The video does have a variable framerate, however using ffprobe it says that the max FPS is 25.47. So even if it was at the max FPS the whole video then I'd still only expect to see 984 pictures.
Is there anyway to tell FFMpeg that my source video is only 25 fps? Or am I missing something obvious?

Why are screenshots taken with ffmpeg uneven in time?

I'm using the following ffmpeg command to take screenshots every 5 seconds of a video file that is 85 seconds long:
ffmpeg -i out2.mp4 -vf fps=1/05 img%03d.jpg
I get 18 files When I look at the resulting screenshots, they are 5 seconds apart, but the first frame starts around 3 seconds, the second is then 8 seconds, and so on. How do I get it to start with the very first frame, and then go 5 seconds apart on subsequent frames?
You're the using the fps function, whose primary use is to change the framerate, not select specific frames. When using it to reduce framerate, it uses a regular cadence to retain frames. For 1/5, that's the middle frame in a 5-second segment.
Use the select filter.
ffmpeg -i out2.mp4 -vf select='lte(mod(t,5),0.01)' -vsync 0 img%03d.jpg

ffmpeg drop frames on purpose to lower filesize

Our security system records and archives our IP cameras streams with ffmpeg -use_wallclock_as_timestamps 1 -i rtsp://192.168.x.x:554/mpeg4 -c copy -t 60 my_input_video.avi
I run it with crontab every minute so it creates videos of 60 seconds (~15Mb) for each camera every minute. When an intrusion occurs, the camera sends a picture through FTP and a script called by incrontab:
1- forwards immediately the picture by email
2- selects the video covering the minute the intrusion occured, compress it with h264 (to ~2,6Mb) and sends it by email
It is working really well but if a thief crosses the path of various cameras, the connection to the SMTP server is not fast enough so video emails are delayed. I'd like to compress the videos even more to avoid that. I could lower the resolution (640x480 to 320x240 for example) but sometimes 640x480 is handy to zoom on something which looks to be moving...
So my idea is to drop frames in the video in order to lower the filesize. I don't care if the thief is walking like a "stop motion Lego" on the video, the most important is I know there is someone so I can act.
mediainfo my_input_video.avi says Frame rate = 600.000 fps but it is of course wrong. FPS sent by IP cameras are always false because it varies with the network quality; this is why i use "-use_wallclock_as_timestamps 1" in my command to record the streams.
with ffmpeg -i my_input_video.avi -vcodec h264 -preset ultrafast -crf 28 -acodec mp3 -q:a 5 -r 8 output.avi the video is OK but filesize is higher (3Mb)
with ffmpeg -i my_input_video.avi -vcodec h264 -preset ultrafast -crf 28 -acodec mp3 -q:a 5 -r 2 output.avi the filesize is lower (2,2Mb) but the video doesn't work (it is blocked at the first frame).
Creating a mjpeg video (mjpeg = not interlaced frames) in the middle of the process (first exporting to mjpeg with less frames and then exporting to h264) creates same results.
Do you know how I can get my thief to walk like a "stop motion Lego" to lower the filesize to a minimum?
Thanks for any help
What are your constraints file size wise? 2.6MB for 60 seconds of video seems pretty reasonable to me, thats about 350kbps, which is pretty low for video quality.
You need to specify the video bitrate -b:v 125000 (125kbps, should drop you to about 900kb) to control the bitrate/s you want the video encoded at. Your not giving FFMpeg enough hints as to how you want the video handled, so its picking arbitrary values you don't like. As you drop the frame rate, its just using up the buffers allocating more bits to each frame. (one big thing you need to keep in mind with this is, as you stretch the video out over a longer time period the more likely the scene will change significantly require an I frame (full encoded frame vs frame based on previous frame) so reducing the frame rate will help some, but may not help as much as you'd think).
Your "(it is blocked at the first frame)." is most likely an issue with you trying to start decoding a stream when it is not at an I frame and not an issue with your settings.

Resources