I'm trying to add a border over many images by overlaying the border as a watermark.
My input image is 5.13x7.63 inches but the output is 16.03x23.84 inches. How do I prevent this and get output as the same size as input?
The command I'm using is:
ffmpeg -i input.png -vf "movie=border.png [watermark]; [in][watermark] overlay=0:0 [out]" output.png
where input.png and border.png are the same dimensions and in the same folder.
I was expecting the output to be the same size as input.
Apparently ffmpeg cant control the dpi of an image. When adding borders, it takes my 300dpi image and turns it into a 72dpi one but with larger dimensions. You can use photoshop to resize to the original dpi and dimensions. Use actions to automate and batch process it if you have a lot of images
Related
I found some posts explaining how to turn any video horizontal by adding blurred borders using FFMpeg, but I want to convert videos to vertical 1080x1920. I don't want it to enlarge the video, nor crop if a dimension is bigger than either 1080 or 1920 dimension. Instead, I want it to shrink the video until it fits fully inside 1080x1920, and then I want it to add blurred borders to the empty areas.
This is the snippet I found, but when I tried reversing the numbers, it actually cropped the video.
ffmpeg -I input.mp4 -lavfi "[0:v]scale=1920*2:1080*2,boxblur=luma_radius=min(h\,w)/20:luma_power=1:chroma_radius=min(cw\,ch)/20:chroma_power=1[bg];[0:v]scale=-1:1080[ov];[bg][ov]overlay=(W-w)/2:(H-h)/2,crop=w=1920:h=1080" output.mp4
Simple method:
ffmpeg -i input.mp4 -filter_complex "[0:v]boxblur=40,scale=1080x1920,setsar=1[bg];[0:v]scale=1080:1920:force_original_aspect_ratio=decrease[fg];[bg][fg]overlay=y=(H-h)/2" -c:a copy output.mp4
"Simple" because it forces the background to 1080x1920 and ignores aspect ratio. So the background it will looked stretched, but it is blurred so much nobody will care or notice.
To get a 200x100 thumbnail from a video, I do ffmpeg -ss 100 -i /tmp/video.mp4 -frames:v 1 -s 200x100 image.jpg. But if the source video isn't in the same aspect ratio as 200x100, the thumbnail gets distorted (either stretched or squished, horizontally or vertically) and it looks bad.
Is there a way that ffmpeg can figure out for example that a 500x200 video is 100px too wide, and remove 50px from the right and 50px from the left, making the video 400x200? And because 400x200 is the same aspect ratio as 200x100, the thumbnail would have no distortion.
I know there are other tools that can do this to the thumbnails generated by ffmpeg, but I'd prefer doing it within ffmpeg and not having to process the thumbnails again.
You can use the force_original_aspect_ratio option in the scale filter.
ffmpeg -ss 100 -i /tmp/video.mp4 -frames:v 1 -q:v 2 -vf "scale=200:100:force_original_aspect_ratio=increase,crop=200:100" image.jpg
If your thumbnail size is 200x100 fixed, then run
ffmpeg -ss 100 -i /tmp/video.mp4 -vf "scale='if(gt(dar,200/100),100*dar,200)':'if(gt(dar,200/100),100,200/dar)',setsar=1,crop=200:100" -frames:v 1 image.jpg
The scale filter checks the aspect ratio of the source and scale so that one dimension fits the 200x100 canvas and the other overshoots, unless it's a perfect match. Then the crop filter crops it to 200x100 from the center thus taking care of the out of bounds region.
In using the scale filter with ffmpeg, I see many examples similar to this:
ffmpeg -i input.mov -vf scale="'if(gt(a,4/3),320,-2)':'if(gt(a,4/3),-2,240)'" output.mov
What does the variable a signify?
From the ffmpeg scale options docs.
a The same as iw / ih
where
iw Input Width ih Input Height
My guess after reading https://trac.ffmpeg.org/wiki/Scaling%20(resizing)%20with%20ffmpeg is that a is the aspect ratio of the input file.
The example given on the webpage gives you an idea how to use it:
Sometimes there is a need to scale the input image in such way it fits
into a specified rectangle, i.e. if you have a placeholder (empty
rectangle) in which you want to scale any given image. This is a
little bit tricky, since you need to check the original aspect ratio,
in order to decide which component to specify and to set the other
component to -1 (to keep the aspect ratio). For example, if we would
like to scale our input image into a rectangle with dimensions of
320x240, we could use something like this:
ffmpeg -i input.jpg -vf scale="'if(gt(a,4/3),320,-1)':'if(gt(a,4/3),-1,240)'"
output_320x240_boxed.png
In the ffmpeg wiki "Scaling (resizing) with ffmpeg", they use this example:
ffmpeg -i input.jpg -vf scale="'if(gt(a,4/3),320,-1)':'if(gt(a,4/3),-1,240)'" output.png
The purpose of the gt(a,4/3) is, as far as I can tell, to determine the orientation (portrait or landscape) of the video (or image, in this case).
This wouldn't work for some strange aspect ratios (7:6, for an example, where gt(a,4/3) would incorrectly turn false.
It seems to me better to use the height and width of the video, so the above line would instead be:
ffmpeg -i input.jpg -vf scale="'if(gt(iw,ih),320,-1)':'if(gt(iw,ih),-1,240)'" output.png
I already have found out how to scale the thumbnail to stay within specified bounding dimensions while maintaining aspect ratio. For example, to get the frame shown at 6 seconds into the input.mp4 video file, and scale it to fit into 96x60 (16:10 aspect ratio):
ffmpeg -y -i input.mp4 -ss 6 -vframes 1 -vf scale="'if(gt(a,16/10),96,-1)':'if(gt(a,16/10),-1,60)'" output.png
This is fine, it works.
Next, I would like to do the same, but if the video's aspect ratio is not exactly 16:10, then I would like to force the output image to have an aspect ratio of 16:10 by taking the above transformation, and filling or padding the space with white. That is, I want the output to be as if I took, say, a 96x48 image, and laid it over a 96x60 white background, resulting in white bars above and below the 96x48 image.
Ideally, I do not want to resort to using another tool or library, such as ImageMagick. It would be best if ffmpeg could do this on its own.
Here's what I went with. For the -vf argument:
-vf "scale='if(gt(a,16/10),96,-1)':'if(gt(a,16/10),-1,60)', pad=w=96:h=60:x=(ow-iw)/2:y=(oh-ih)/2:color=white"
This applies two filters in sequence, separated by a comma.
target_H = 2436
target_W = 1124
ffmpeg -i 1.mp4 -ss 1 -vframes 1 -vf "scale=min(iw*2436/ih\,1124):min(2436\,ih*1124/iw),pad=1124:2436:(1124-iw)/2:(2436-ih)/2:green" output.png
I need to generate thumbnails for videos, automatically. I cannot predict the format of the video, but I need the thumbnail to be 220x120 pixels, always. Using -s 220x120 produces a weird stretch, just like -vf "scale=220:120". I'd like the stretching to be uniform, either cutting away top and bottom if the video is too high or adding black borders.
This is an example using a picture, same filter can be applied to video:
ow=220
oh=120
ffmpeg -i foo.png \
-vf "scale=max($ow\,a*$oh):max($oh\,$ow/a),crop=$ow:$oh" bar.png
Regardless of aspect ratio, this will:
scale down until width or height fits "the box"
crop down the other until it fits as well
The commas inside needs to be escaped so they aren't interpreted as filter separators.
§ Crop
§ Scale