Converting video from 60 FPS to 25 FPS without slowing it - bash

I am trying to encode video through ffmpeg in Linux system. Original video has 60 FPS and I need to change it to 25, but when I do so, video is slower than original.
When I change it to 30, everything is fine (I guess it's easier for encodder to play every second frame than compute it to 25). How can I achieve that video will have 25 FPS with same speed as original video?
Currently I am using this command:
ffmpeg -i "test.mkv" -r 30 -vcodec libx264 -x264-params keyint=10:scenecut=0 -an -bsf:v dump_extra -video_size hd720 test2.mp4
Thank you for your help!

What does "video is slower than original" mean?
I try this:
ffmpeg -i BQTerrace_1920x1080_60.mp4 -r 25 -vcodec libx264 -x264-params keyint=10:scenecut=0 -an -bsf:v dump_extra BQTerrace_1920x1080_25.mp4
The output video isn't slower than original video, but it looks more unsmoother than original video. This is because that the output video has less frames than original video per second.
In my case, the total frames, frame rate, and video time are:
BQTerrace_1920x1080_60.mp4: 600 frames, 60 fps, 10s
BQTerrace_1920x1080_25.mp4: 250 frames, 25 fps, 10s

Related

Timelapse (1/6 fps) from slo-mo (240 fps) with ffmpeg

I recorded slo-mo video on an iPhone SE (2) by mistake instead of timelapse.
I know there's a lot of answers to this question here, but I'm trying again and again and always something's wrong (like a video that has a correct total no. of frames, but lasts 3 hours and is basically a freeze :D )
My recent command was
ffmpeg -i IMG_2174.MOV -vf framestep=1440,setpts=N/120/TB -c:v libx264
-preset slow -crf 22 -an -r 30 IMG_2174.timelapse.MOV
but it resulted in a one-second-long video, so way over-timelapsed. Should be several seconds IINM. The source video is 30 minutes long #240fps, 17GB.
Thx.
This command seems to do the trick:
ffmpeg -i IMG_2174.MOV -vf framestep=1440,setpts=N/30/TB -c:v libx264 -preset slow -crf 22 -an -r 30 IMG_2174.timelapse.MOV
Here is the explanation for OP's self-answer.
ffmpeg -i IMG_2174.MOV
-vf framestep=1440,setpts=N/30/TB
-r 30 -c:v libx264 -preset slow -crf 22 -an IMG_2174.timelapse.MOV
Given input video at 240 fps cfr:
framestep=1440 keep every 1440th frame, yielding 240/1440 = 1/6 fps
setpts=N/30/TB speeds up the video by x180 (30 / 1/6)
-r 30 output option: match the new pts interval set above
For a vfr video, framestep=1440 likely results in incorrect timing (though on the average correct). For such video, replace the framestep filter with fps=1/6 filter so it picks the frames based on pts rather than frame count.
[edit note: iPhone's slo-mo recording does keep 240fps cfr so the OP's solution is 100% correct, edited down just to mention a vfr-correct approach]

ffmpeg speed up video from 25 to 60 fps dropping frames

I'm trying to speed up a video from 25fps to 60 fps. I want the same exact number of frames, just presented to me faster and whatever gets me 60 of them per second.
ffmpeg -i Spider.mov -r 62500/1000 -filter:v "setpts=PTS*0.4" -c:v libx264 Spider4k60.mov
This works and doesn't drop or duplicate any frames. But my player won't do 62.5 fps.
But when I tried:
ffmpeg -i Spider.mov -r 60 -filter:v "setpts=PTS/2.4" -c:v libx264 -y Spider4k60.mov
even though that is the correct fraction (60/25=2.4) I get about one dropped and one duplicated frame per second.
Likewise:
ffmpeg -i Spider.mov -r 60 -filter:v "setpts=PTS*0.416666666667" -c:v libx264 -y Spider4k60.mov
gives me the same.
Any thoughts? I would think PTS/2.4 would be the proper solution.
Timestamps are denominated in terms of a timebase which is the clock-keeping scale.
setpts will assign the value nearest to the expression value which is possible in the stream timebase. When compressing timestamps, like here, make sure that enough resolution is available using the settb filter.
For 25 and 60, 300 is LCM but let's pick something higher, like 6000.
-filter:v "settb=1/6000,setpts=PTS/2.4"
If your video is constant frame rate, this will do what you want. If it's VFR, it's possible that -r 60 will still cause frames to be dropped/duped. Add -vsync vfr for that.

How to create a full length video from images with FFmpeg?

I have more than a thousand images that I want to transform into a 3 minutes video. I tried using this line ffmpeg -r 30 -i "E:/White-box-Cartoonization/test_code/cartoonized_images/$flower%03d.bmp" -c:v libx264 -pix_fmt yuv420p out.mp4 it worked but creates only a 5 seconds video. What do I need to do to turn it into a full length 3 minutes video?
If you have 1250 images and want an output duration of 180 seconds:
ffmpeg -framerate 1250/180 -i input%03d.bmp -c:v libx264 -vf format=yuv420p output.mp4
This example results in a frame rate of 6.94. Some players can't handle such low frame rates. If your player does not like it then add the -r output option to make a normal output frame rate. ffmpeg will duplicate the frames but the output will look the same.
ffmpeg -framerate 1250/180 -i input%03d.bmp -c:v libx264 -vf format=yuv420p -r 25 output.mp4
For 3 minutes of video at 30 frames per second (-r parameter) you'd need 30*60*3 images: 5400 images.
Your source parameter specifies there would be only 3 digits, so you have a maximum of 1000 source images:
$flower%03d.bmp => $flower000.bmp .. $flower999.bmp
1000 images at 30 frames per second should give about 30 seconds of video ... if you actually have $flowerxxx.bmp files.
You might need a 4th digit in there somewhere.
$flower%04d.bmp

FFMPEG: Youtube streaming quality and speed issues

I am trying to make a reliable stream from my Icecast/Shoutcast servers to Youtube live. The command that I use is:
ffmpeg -v verbose -framerate 30 -loop 1 -i /var/image.jpg -re -i http://127.0.0.1:4700/radio -c:v libx264 -preset ultrafast -b:v 2250k -maxrate 6000k -bufsize 6000k -c:a copy -ab 128k -s 1920x1080 -framerate 30 -g 60 -keyint_min 60 -f flv rtmp://a.rtmp.youtube.com/live2/xxx
As you can see I am using recommended bitrate for Youtube, insert keyframes every 2 seconds and streaming at 30 frames per second.
The stream is working but after running for some time two thing are happening:
FFMPEG speed falls from 1x to something like 0.998x
Youtube starts complaining that video stream speed is slow, markes the quality as bad and sometimes video starts buffering.
Why is this happening? CPU load is normal, connectivity is ok (the stream is running on a 1Gg/s dedicated server).
Since in my example above I am streaming a single image as a logo of the stream I also tried to generate a short 30 seconds video with that image and broadcast that video instead of an image, but that did not help as well.
The command I used for conversion:
ffmpeg -framerate 30 -loop 1 -i /var/image.jpg -c:v libx264 -preset ultrafast -tune stillimage -b:v 2250k -minrate 2250k -maxrate 6000k -bufsize 6000k -framerate 30 -g 60 -keyint_min 60 -t 30 out4.mp4
And broadcast with
ffmpeg -stream_loop -1 -i out4.mp4 -re -i http://127.0.0.1:4700/radio -c:v copy -c:a copy -framerate 30 -g 60 -keyint_min 60 -f flv rtmp://a.rtmp.youtube.com/live2/xxx
ffmpeg version is 4.1.1
Are you sure that your original stream is really keeping up with the wall-clock?
Depending on how it's encoded there are possibilities that it gets heavily skewed. This ultimately leads to buffer under (or overruns if it's too fast) and the player complaining/skipping.
Can you try and dump several hours worth of stream to a file and then stream that with FFmpeg? If that works, then it's a strong indication that your original stream timing (sample rate) is off.
Getting the sample rate right is why professional/expensive sound cards use high precision Quartz-Crystal controlled oscillators. Purely virtual processing (e.g. files get encoded into a stream) can easily get skewed, especially inside virtual machines. Also, cheap USB sound cards are often among the worst offenders in terms of frequency accuracy and stability.
FFmpeg might have an option to deal with too slow input. Keywords could be 'padding' or 'missing samples'.
Youtube's error saying "...buffer....." is not a buffer issue on your PC, but simply data you are sending to youtube is too small.
1)note that [-preset ultrafast] and [-preset fast] does not make big difference.
2) change your ffmpeg comannd for broadcast one. like, [-b:v 2250k] to [-b:v 15000k],and set fps to 12→[-r 12] option.
I's gonna be.
ffmpeg -stream_loop -1 -i out4.mp4 -re -i http://127.0.0.1:4700/radio -preset fast -r 12 -framerate 30 -g 60 -video_track_timescale 1000 -b:v 15000k -f flv rtmp://a.rtmp.youtube.com/live2/xxx
I hope this will be good for you !!(^v^)Y

Create time lapse video from other video

Using avconv (or even ffmpeg, so I can use as a reference), how can I create a time lapse video by taking only anchor/reference frames from another video? Most information I find is on how to create a time lapse video by combining images, and I'd like to do it by extracting frames from a video. Say, if a video is 30 seconds long at 30 FPS, I'd like to take 60 out of those 900 frames (900/60 = every 15 seconds) to produce a 2 second video.
To take every 15th frame, use
ffmpeg -i in.mp4 -vf select='not(mod(n,15))',setpts=N/FRAME_RATE/TB out.mp4
Another method is to use the framestep filter
ffmpeg -i in.mp4 -vf framestep=15,setpts=N/FRAME_RATE/TB out.mp4
I had a H264 video from a camera and after lots of attempts found following command that produce 16x faster video with good result and 60 FPS (option -r) that is good for the YouTube timelapse
ffmpeg -i video.avi -r 60 -filter:v "setpts=0.0625*PTS" -vcodec libx264 -an timelapse.avi
You can check the result here https://www.youtube.com/watch?v=azhRqKQ7kCU
Since you are asking for 1/15 frame it will be 1/15 ~= 0.06667 with 30 FPS result video you will need command
ffmpeg -i video.avi -r 30 -filter:v "setpts=0.06667*PTS" -vcodec libx264 -an timelapse.avi

Resources