To resize a video with FFmpeg while preserving the aspect ratio and avoiding black borders, you must use the
scale filter with negative dimensions or explicit aspect ratios. This ensures that the output video fills the screen without cropping content unexpectedly. The process involves calculating the correct scaling factors to maintain the original proportions of the source material.
Understanding Aspect Ratio Preservation
When resizing videos, the most common mistake is forcing specific width and height values that do not match the source's aspect ratio. This results in stretched images or black bars (pillarboxing or letterboxing). To avoid this, FFmpeg allows you to specify one dimension and let it calculate the other automatically. You can achieve this by using
-1 for the unknown dimension or by specifying the aspect ratio directly.
For example, if you want to scale a video to a width of 1920 pixels while maintaining its original height proportion, you would use
scale=1920:-1. Conversely, if you need a specific height, such as 1080 pixels, you would use
scale=-1:1080. This method guarantees that the video retains its original shape without distortion. It is crucial to understand that "without black borders" implies that the output resolution should perfectly match the scaled dimensions, which are derived from the source's aspect ratio. If you force a resolution that does not match the calculated aspect ratio, FFmpeg will either crop the image or add padding, depending on additional filters used.
The Two-Pass Encoding Process
Two-pass encoding is primarily used for variable bitrate (VBR) codecs like H.264 (libx264) and H.265 (libx265) to optimize quality at a target file size. In the first pass, FFmpeg analyzes the video complexity and generates statistics. In the second pass, it uses these statistics to encode the video more efficiently. While simple resizing might not strictly require two passes for constant bitrate (CBR) settings, it is highly recommended for achieving the best visual quality-to-size ratio.
To perform a two-pass encode, you run the command twice. The first pass outputs no video file but creates a log file. The second pass reads this log file to apply the optimized encoding settings. Here is how you structure the commands for the first pass:
ffmpeg -i input.mp4 -vf "scale=1920:-1" -c:v libx264 -pass 1 -f null /dev/null
Note that on Windows, you replace
/dev/null with
NUL. The
-f null flag tells FFmpeg to discard the output video stream, keeping only the internal statistics needed for the second pass. Once the first pass completes, you run the second pass command, adding the
-pass 2 flag and specifying the output filename:
ffmpeg -i input.mp4 -vf "scale=1920:-1" -c:v libx264 -pass 2 -c:a aac -b:a 192k output.mp4
In this second command, we also include audio encoding (
-c:a aac) because the first pass did not produce an audio stream. It is essential to match all video and audio parameters between the two passes exactly, except for the pass number and the output file path. Any discrepancy can lead to errors or suboptimal results.
Handling Audio Streams
Audio handling is often overlooked during multi-pass encoding. In the first pass, audio is typically ignored or passed through unchanged if not explicitly encoded. However, in the second pass, you must ensure the audio is encoded correctly. Using
-c:a copy in the second pass will simply copy the audio stream from the input, which is efficient if you do not need to re-encode it. If you need to change the audio codec or bitrate, specify it explicitly as shown in the example above. Always verify that the audio duration matches the video duration after processing to avoid sync issues.
Avoiding Black Borders and Cropping
Sometimes, users desire a video that fits a specific resolution without any black borders, even if it means cropping some of the original image. This is different from maintaining the aspect ratio. If you strictly want to avoid black borders and fill the entire frame, you might need to use the
crop filter in conjunction with
scale. For instance, if you are scaling to 1920x1080 but your source is 4:3, scaling to fit the width will leave black bars on the sides. To remove them, you can crop the top and bottom:
ffmpeg -i input.mp4 -vf "scale=1920:1080,crop=iw:iw*9/16" output.mp4
However, this approach changes the aspect ratio and cuts off content. The original question emphasizes maintaining aspect ratio *and* avoiding black borders, which is technically contradictory unless the target resolution matches the source aspect ratio exactly. If the target resolution is fixed (e.g., 1920x1080), you cannot have both a different aspect ratio source and no black borders without cropping. Therefore, the standard interpretation is to scale the video so that it fits within the target bounds without stretching, accepting that black borders may appear if the aspect ratios differ, OR to scale to the exact aspect ratio of the target resolution. The most robust solution for "no black borders" is to ensure the output resolution is calculated based on the source aspect ratio, rather than forcing a standard HD or FHD resolution.
Advanced Scaling Filters
FFmpeg offers various scaling algorithms. The default is usually bicubic, but you can specify others like
lanczos for higher quality, especially when downscaling. Add
flags=lanczos to your scale filter:
scale=1920:-1:flags=lanczos. This can improve sharpness and reduce artifacts. Additionally, you can chain multiple filters. For example, you might want to normalize brightness before scaling:
format=yuv420p,scale=1920:-1:flags=lanczos. Ensure the pixel format is compatible with your output container;
yuv420p is widely supported.
Common Pitfalls and Solutions
One frequent issue is forgetting to set the pixel format. Some players struggle with certain pixel formats, leading to playback issues. Adding
-pix_fmt yuv420p ensures maximum compatibility. Another pitfall is mismatched audio and video streams in multi-pass encoding. Always double-check that the audio codec and parameters are identical in both passes. If you encounter errors related to the log file, ensure that the working directory is accessible and that the first pass completed successfully without errors.
Add Moving Logo to Long Video Using FFMPEG provides insights into complex filter chains that can be combined with scaling operations. Similarly,
Converting Transparent MOV to WebM with FFmpeg demonstrates handling alpha channels, which requires careful attention to pixel formats and codecs, relevant if your resized video includes transparency.
Frequently Asked Questions
Why do I get black bars when resizing?
Black bars appear because the source aspect ratio does not match the target resolution. To fix this, calculate the target resolution based on the source aspect ratio or use the crop filter to remove the bars, acknowledging that this will cut off parts of the video.
Can I skip the first pass if I don't care about file size?
Yes, if you are using a constant bitrate (CBR) or do not need optimal quality-per-bitrate, you can skip the first pass. Simply remove the
-pass 1 and
-pass 2 flags and provide the output filename directly in a single command.
How do I scale a video to a specific height?
Use the scale filter with
-1 for the width and the desired height for the vertical dimension, like
scale=-1:720. This maintains the aspect ratio while setting the height to 720 pixels.
What is the best scaling algorithm for downscaling?
The
lanczos algorithm is generally considered the best for downscaling due to its high quality and sharpness. Specify it using
flags=lanczos within the scale filter options.
Why does my audio go out of sync after two-pass encoding?
This usually happens if the audio parameters differ between the two passes or if the video encoding time varies significantly. Ensure that
-c:a and its associated flags are identical in both commands, and verify that the input files are identical.