ffmpeg image scale then crop not working - ffmpeg

I want to generate an image from a video, but first i want to scale it to a certain width/height then crop it to a set square size, the problem is that my new version ffmpeg doesnt seem to work with scaling first.
ffmpeg version 2.8.6-1ubuntu2
fails:
ffmpeg -y -i input.mp4 -an -ss 5 -s 150x150 -vf scale=-1:150,crop=150:150 -vframes 1 output-small.jpg
Invalid too big or non positive size for width '150' or height '150'
works:
ffmpeg -y -i input.mp4 -an -ss 5 -s 150x150 -vf crop=150:150,scale=-1:150 -vframes 1 output-small.jpg
However i cannot settle for the second command because i am generating images that could be larger then the original size (i'm creating a few different sizes for each image), therefore scale MUST come first. Anybody have any idea what changed or what i am doing wrong here?

This may be happening because your video is portrait, and so the scaled image has width smaller than 150px. Hence the crop fails.
Also, you should skip the -s option, otherwise you're triggering two scaler executions.
Try
ffmpeg -y -i input.mp4 -ss 5 -vf scale='if(gt(iw,ih),-1,150)':'if(gt(iw,ih),150,-1)',crop=150:150 -vframes 1 output-small.jpg

Related

How to create a ffmpeg filter that zooms by a set value over a time while playing the video?

I'd like to create a zoom effect where I start at 1 * inputwidth and end with 1.1 * inputwidth over a set time.
I tried using zoompan but it:
pauses the frame, zooms in over the amount of time specified, continues sound while zooming.
zooms to the top-left corner, instead of center.
leaves the frame smaller than it was before. Do I need to upscale afterwards?
$ ffmpeg -i in.mp4 -t 10 \
-vf "fps=60,zoompan=z='if(lte(it,2),it/2*0.1+1,1.1)':d=1,scale=iw:ih" out.mp4
I tried using scale with crop, but then I get the error shown below. I assume this isn't to be as a function of time.
$ ffmpeg -i in.mp4 -t 10 \
-vf "fps=60, scale='t/5*2*iw':-1, crop='iw/2*t/5':'ih/2*t/5'" out.mp4
Expressions with frame variables 'n', 't', 'pos' are not valid in init eval_mode.
If there's an other tool besides ffmpeg, that would be fine, except it should not be a gui-only way.
You are looking in the right direction for what you want. There are a few things off with the commands you've specified
zoompan itself needs an fps option. The fps filter just interpolates the outcome of zoompan. You need to add fps=60 to zoompan (match this to the input video).
ffmpeg -i in.mp4 -t 10 \
-vf "zoompan=fps=60:z='if(lte(it,2),it/2*0.1+1,1.1)':d=1,scale=iw:ih" out.mp4
This will make the video not go out of sync.
the top-left zoom, is because x and y are both 0. To zoom at center add x='iw/2-(iw/zoom/2)':y='ih/2-(ih/zoom/2)'
ffmpeg -i in.mp4 -t 10 \
-vf "zoompan=fps=60:z='if(lte(it,2),it/2*0.1+1,1.1)':x='iw/2-(iw/zoom/2)':y='ih/2-(ih/zoom/2)':d=1,scale=iw:ih" out.mp4
Assuming your video is bigger than 720p, the default for zoompan output size is s=hd720 that's why it's smaller. To keep it in 1080p add s=hd1080
ffmpeg -i in.mp4 -t 10 \
-vf "zoompan=fps=60:z='if(lte(it,2),it/2*0.1+1,1.1)':x='iw/2-(iw/zoom/2)':y='ih/2-(ih/zoom/2)':d=1:s=hd1080,scale=iw:ih" out.mp4
This should be the full command
ffmpeg -i in.mp4 -t 10 \
-vf "zoompan=fps=60:z='if(lte(it,2),it/2*0.1+1,1.1)':x='iw/2-(iw/zoom/2)':y='ih/2-(ih/zoom/2)':d=1:s=hd1080,scale=iw:ih" out.mp4

ffmpeg - multiple output with thumbnails

I would like ffmpeg to do the following:
read an input mp4 (-i movie.mp4)
skip the first 5 seconds (-ss 5)
find scene changes and display the frame numbers (-vf "select=gt(scene\, 0.4, showinfo))
output #1 - a gif file (output.gif)
output #2 - a contact sheet with all the thumbnails (-vf "select scale=320:-1, tile=12x200" thumbnails.png)
This will generate the thumbnails:
ffmpeg -hide_banner -i d:/Test/movie01.mp4 -ss 5 -vf "select=gt(scene\,0.4), showinfo, scale=320:-1, tile=12x200" -vsync 0 thumbnails%03d.png
this will generate the gif:
ffmpeg -hide_banner -i d:/Test/movie01.mp4 -ss 5 -vf "select='not(mod(n,60))',setpts='N/(30*TB)', scale=320:-1" -vsync 0 output.gif
I would like to do both at once with 2 more features:
set fps and resolution for the gif; I would like the gif to represent the whole movie in X seconds, at Y fps (I know the duration of the input movie so I can calculate how often a frame needs to be captured)
set the width only for the thumbnail picture (tile=12 for example) and let ffmpeg determine the appropriate height
I have tried to compose a command line from what I read on this page: https://trac.ffmpeg.org/wiki/Creating%20multiple%20outputs, using the split / map commands but I couldn't get it to work
Use
ffmpeg -ss 5 -i input.mp4
-vf "select='not(mod(n,60))',setpts=N/Y/TB',scale=320:-1" -r Y output.gif
-vf "select='gt(scene\,0.4)',showinfo,scale=320:-1,tile=12x200" -vsync 0 thumbnails%03d.png
tile requires both W and H to be set.

I can't overlay and center a video on top of an image with ffmpeg. The output is 0 seconds long

I have an mp4 that I want to overlay on top of a jpeg. The command I'm using is:
Ffmpeg -y -i background.jpg -i video.mp4 -filter_complex "overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2" -codec:a copy output.mp4
But for some reason, the output is 0 second long but the thumbnail does show the first frame of the video centred on the image properly.
I have tried using -t 4 to set the output's length to 4 seconds but that does not work.
I am doing this on windows.
You need to loop the image. Since it loops indefinitely you then must use the shortest option in overlay so it ends when video.mp4 ends.
ffmpeg -loop 1 -i background.jpg -i video.mp4 -filter_complex \
"overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2:shortest=1" \
-codec:a copy -movflags +faststart output.mp4
See overlay documentation for more info.
Well you should loop the image until the video duration. So to do the you need to add -loop 1 before the input image. Then the image will have a infinite duration. So to control it specify -shortest before the output file which will trim all the streams to the shortest duration among them. Else you can use -t to trim the image duration to the video length. This will do what you want.
Hope this helps!

FFMPEG scale down image

This is for you FFMPEG gurus!
I have video that I take a screenshot image of. This works fine:
ffmpeg -i sourceMovie.mp4 -ss 0 -vframes 1 destImage.jpg
But I was hoping to also scale down the image to 150 px wide, in one fell swoop. Apparently, I should add
scale=150:-1
But where and how do I insert that in the command?
I have tried everything; nothing works ...
scale is a VideoFilter, so you use "-vf":
ffmpeg -i sourceMovie.mp4 -ss 0 -vframes 1 -vf "scale=150:-1" destImage.jpg

How to extract the 1st frame and restore as an image with ffmpeg?

Anyone knows the trick?
And how to install ffmpeg ? yum install mpeg only returns this:
======================================================================================== Matched: mpeg ========================================================================================
libiec61883.i386 : Streaming library for IEEE1394
libiec61883.x86_64 : Streaming library for IEEE1394
qffmpeg-devel.i386 : Development package for qffmpeg
qffmpeg-devel.x86_64 : Development package for qffmpeg
qffmpeg-libs.i386 : Libraries for qffmpeg
qffmpeg-libs.x86_64 : Libraries for qffmpeg
I've cobbled up this command line from various answers that works great for me to get the absolutely first frame out from a video. I use this to save a thumbnail screenshot for the video.
ffmpeg -i inputfile.mkv -vf "select=eq(n\,0)" -q:v 3 output_image.jpg
Explanation:
The select filter -vf "select=eq(n\,0)" is to select only frame #0.
-q:v allows you to set the quality of the output jpeg between 1 and 31. Lower the number, higher the quality. 2 - 5 works good, I use 3.
Note: This will get you an image with the same size as the video. To get a thumbnail, you can use the scale filter to get a thumbnail to fit whatever width you need, like so:
ffmpeg -i inputfile.mkv -vf "select=eq(n\,0)" -vf scale=320:-2 -q:v 3 output_image.jpg
The above command will give you a thumbnail jpeg that will be scaled to match width of 320, and height will be calculated to match the aspect ratio.
It's on the manpage:
* You can extract images from a video, or create a video from many
images:
For extracting images from a video:
ffmpeg -i foo.avi -r 1 -s WxH -f image2 foo-%03d.jpeg
This will extract one video frame per second from the video and will
output them in files named foo-001.jpeg, foo-002.jpeg, etc. Images
will be rescaled to fit the new WxH values.
If you want to extract just a limited number of frames, you can use
the above command in combination with the -vframes or -t option, or in
combination with -ss to start extracting from a certain point in time.
But of course you have to install it first. I'm on Debian and don't use yum.
[update for the other question]
i=1
for avi in *.avi; do
ffmpeg -i $avi -vframes 1 -f image2 /tmp/$i.jpg; i=$((i+1))
done
Tested and works.
[update for yet another question...]
for flv in *.flv; do
ffmpeg -i $flv -vframes 1 -f image2 ${flv%%.flv}.jpg
done
An easy to grok solution that works for me is
ffmpeg -i <input> -vframes 1 <output>.jpeg
Note that I do get an error "[swscaler # 0x111652000] deprecated pixel format used, make sure you did set range correctly" but according to a little reading (see for example https://stackoverflow.com/a/43038480/1241736) that can safely be ignored.
It's works for me
ffmpeg -i sample-mp4-file.mp4 -ss 1 -vframes 1 output.jpg

Resources