ffmpeg transcode video from different sizes to 4:3 - ffmpeg

We have some videos that have different scale and aspect ratio and we'd like to convert them to a fix 640x480 size (4/3 ar letterbox padding if necessary).
Two sizes are occurs very often: 853 × 480, 1280 × 720.
I made some research and tries before write this question but didn't get the expected result.
For example:
ffmpeg -i video.mp4 -vf "scale=640:480,pad=640:480:(ow-iw)/2:(oh-ih)/2,setdar=4/3" -c:a copy output.mp4
setdar=4/3 seems to required because if I omitted the result remain the original aspect ratio.
Are there any solution for different size conversion?

The generic filterchain for fitting a video in a WxH canvas is
"scale=iw*sar:ih,scale=640:480:force_original_aspect_ratio=decrease,pad=640:480:-1:-1"
The first scale filter makes sure the video is not kept anamorphic. If you know the video is square-pixels, you can skip it. The 2nd filter fits the video in a canvas of 640x480 using the force_original_aspect_ratio option.

Related

Create PNG from video with ffmpeg and force_original_aspect_ratio - resulting PNG is squashed to sample_aspect_ratio (instead of display_aspect_ratio)

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"

FFMpeg to resize any video to fit 1080x1920 vertical, without cropping, instead by shrinking and adding blurred borders?

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.

How can ffmpeg scale videos to the same size, preserving their aspect ratio?

(I have searched similar questions and haven't found anything that works the way I describe here.)
I have a number of videos of varying sample and display aspect ratios(and different framerates and timebases). I want to concatenate them into one long video, like a playlist, which means re-encoding them. I want them to scale up or down to fit within the desired output size (768x432), preserving their aspect ratio by pillarboxing when necessary.
I've tried -vf scale=768:432:force_original_aspect_ratio=decrease,pad=768:432:(ow-iw)/2:(oh-ih)/2, which produces a 768x432 16:9 video from a 16:9 input... but squishes it vertically and adds pillarboxing anyway. (The input is 720x480 with a 32:27 sample aspect ratio. Input of a 10:11 SAR, 4:3 DAR 704x480 video works.)
The scale filter does not adjust for the SAR of the input. You'll have to use expressions for this:
scale='if(gt(dar\,768/432),768,oh*dar)':'if(gt(dar\,768/432),ow/dar,432)',setsar=1,pad=...
From what I can recall of my own testing this should work for both 16:9 and non-16:9 video, i think the syntax and order of the setsar function does impact the result
-filter_complex "scale=768:432:force_original_aspect_ratio=decrease,setsar=sar=1,pad=768:432:(ow-iw)/2:(oh-ih)/2"
If that works and you want to convert in as high a quality as possible the I'd suggest you try -filter_complex "scale=768:432:force_original_aspect_ratio=decrease:flags=lanczos+full_chroma_int+accurate_rnd,scale=trunc(iw/2)*2:trunc(ih/2)*2,setsar=sar=1,pad=768:432:(ow-iw)/2:(oh-ih)/2"

Encoding with FFMPEG stretches frames

I am trying to encode video with FFMPEG into H.265, but I have a problem with a weird stretching. Input video is 1920x1080 and output has the same resolution, but when I compare both images on same timestamp, encoded video seems to be stretched by few pixels (it is visibly wider on both sizes despite the fact resolution is same). It seems that this stretching introduces ugly bluriness in whole video. It seems like FFMPEG crop few pixels from left and right (probably black pixels at the edge of video) and stretches content to fill those missing pixels and preserve same resolution.
I did not find any way how to disable this behavior. I tried to change encoder from x265 to x264 to see if that is the problem, but result was still stretched.
I used this command line parameters:
ffmpeg -i input.mkv -c:v libx265 -preset medium -crf 23 -t 30 output.mp4
-t 30 is there to test result visual quality on small sample of length 30 seconds.
Does anyone have any idea why this happens and how to fix it? Most visual quality is lost because of this deformation and not because of recompression, which I proved by encoding with -crf 0, which is basically lossless and result was still blurred.
EDIT: Link to full console output: https://pastebin.com/gpMD5Qec

Add a scaled watermark to a video using ffmpeg

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?

Resources