Lie a few others I'm trying to watermark a video with an image (see FFmpeg - How to scale a video then apply a watermark?). Oh, and I'm transcoding the format too.
The difference is I want my image to be the exact same size as the video. I need to do this as a filter chain because each video is a different size and I'm using a single watermark image. Furthermore, the server it has to run on has an older version of ffmpeg so it doesn't recognise the -filter_complex option.
So far, I've gotten as far as
ffmpeg -y -i input_video.mov -vcodec libx264 -vf "movie=watermark.png [watermark]; [watermark] scale=main_w:main_h [scaled_watermark]; [in][scaled_watermark] overlay=0:0 [out]" output_video.m4v
The problem is that the main_w and main_h constants only seem to be recognised in the overlay filter graph and not in the scale filter graph.
So how do I find out the width and height of input_video.mov so that I can scale the watermark correctly?
Related
I have a generic process whose purpose is to take a video at any aspect ratio and generate a PNG from one of its frames. This frame should:
Be as large as possible, but no larger than 720x405 (16:9)
Maintain the aspect ratio of the video
Have no letterboxing
ffmpeg -y -nostats -ss 10 -i ./video.mp4 -max_muxing_queue_size 6400 -an -frames:v 1 -r 24/1 -vf "scale=w=720:h=405:force_original_aspect_ratio=decrease" -f image2 ./frame.png
When I give this command a video with a sample_aspect_ratio (SAR) of 4:3 and a display_aspect_ratio (DAR) of 16:9, I end up with a 540x405 (4:3) PNG where the image is horizontally compressed. Presumably force_original_aspect_ratio is looking at sample_aspect_ratio rather than display_aspect_ratio.
How do I ensure that the generated image maintains the same aspect ratio as the video (as displayed to the user)?
Insert a scale filter to convert frames to square pixels.
-vf "scale=iw*sar:ih,setsar=1,scale=w=720:h=405:force_original_aspect_ratio=decrease"
I've been trying to get this to work on and off for the past month and am very frustrated, so I'm hoping someone on here could help me. What I'm trying to do is very simple but I struggle with ffmpeg. I basically just want to take a folder of pictures, each of which have different sizes and some may be horizontal or vertical orientation, and put them into a video slideshow where they show for maybe 5-10 seconds each. No matter what I try, it always winds up stretching out the pictures to be out of the ratio and they just look funny. I noticed Windows 10 Photo program does this perfectly, but I want a programmatic approach and I don't think it has a commandline feature. Can someone help me tweak this ffmpeg commandline to work the way I need it to? Desired video output would be 1920x1080 in this case. Thanks!
ffmpeg -r 1/5 -start_number 0 -i "C:\Source_Directory_Pictures\Image_%d.jpg" -c:v libx264 -vf "pad=ceil(iw/2)*2:ceil(ih/2)*2" "F:\Destination_Output\Test_Output.mp4"
Use a combination of scale and pad to generate proportionally resized images centered onto a 1080p frame.
Use
ffmpeg -framerate 1/5 -start_number 0 -reinit_filter 0 -i "C:\Source_Directory_Pictures\Image_%d.jpg" -vf "scale=1920:1080:force_original_aspect_ratio=decrease:eval=frame,pad=1920:1080:-1:-1:eval=frame" -r 25 -c:v libx264 "F:\Destination_Output\Test_Output.mp4"
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.
I am trying to create a GIF from a bunch of JPEG images with different sizes while preserving the aspect ratios for each one of them. What I am trying to achieve is let's say we have a rectangle with 640x480 and the image should be centered in it and expanded to fill the dimensions as much as possible. The resulting gif should be as small as possible in dimensions and all the blank space should be in solid color.
ffmpeg -f image2 -i img_%d.jpg -vf scale=640x480:force_original_aspect_ratio=decrease output.gif
force_original_aspect_ratio=increase didn't help either.
Actually I tried lot of different options, but the result is pretty much the same. The options are applied on the first image of the sequence only, and all the other images are resized to the dimensions of the first one without preserving their own aspect ratio.
I just want to know is that doable with ffmpeg or should I look into custom image manipulation before the gif assembling?
Use
ffmpeg -i img_%d.jpg -vf scale='if(gt(a,640/480),640,-1)':'if(gt(a,640/480),-1,480)':eval=frame,pad=640:480:(ow-iw)/2:(oh-ih)/2 output.gif
You may want to use the palettegen and paletteuse filters for optimizing the GIF creation.
1
ffmpeg -i img_%d.jpg -vf scale='if(gt(a,640/480),640,-1)':'if(gt(a,640/480),-1,480)':eval=frame,pad=640:480:(ow-iw)/2:(oh-ih)/2,palettegen palette.png
2
ffmpeg -i img_%d.jpg -i palette.png -filter_complex "[0]scale='if(gt(a,640/480),640,-1)':'if(gt(a,640/480),-1,480)':eval=frame,pad=640:480:(ow-iw)/2:(oh-ih)/2[seq];[seq][1]paletteuse" output.gif
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