FFmpeg:如何将带有黑色帧的水平非全高清视频渲染为 1920x1080 的视频,背景模糊

FFmpeg: How to render horizontal non full hd video with black frames, to video in 1920x1080, with blurred background

示例视频:

期望的结果:

完整的命令可能如下:

ffmpeg -y -i in.jpg -filter_complex "scale=1920:1080,setsar=1:1,crop=1584:896:172:92,split[crp0][crp1];[crp0]scale=1920:1080,setsar=1:1,gblur=sigma=30[blur];[blur][crp1]overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2" out.jpg

该命令应用您发布的图像(名为 in.jpg)。


示例输出:


过滤器链:

  • scale=1920:1080,setsar=1:1 - 将输入调整为 1920x1080(setsar 用于固定宽高比)。
  • crop=1584:896:172:92 - 裁剪黑框内的部分。
  • split[crp0][crp1] - 将裁剪后的输出拆分为两个相同的流(两个相同的图像)。
  • [crp0]scale=1920:1080,setsar=1:1,gblur=sigma=30[blur] - 将裁剪后的图像调整为 1920x1080 并对调整后的图像进行模糊处理。
    将模糊图像存储在临时变量 [blur].
  • [blur][crp1]overlay= ... - 在模糊图像上叠加 [crp1]

视频文件的工作方式相同。
示例:

ffmpeg -y -i in.mp4 -filter_complex "scale=1920:1080,setsar=1:1,crop=1584:896:172:92,split[crp0][crp1];[crp0]scale=1920:1080,setsar=1:1,gblur=sigma=30[blur];[blur][crp1]overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2" -vcodec libx264 -pix_fmt yuv420p -acodec copy out.mp4

使用 cropdetect 过滤器查找 crop 参数:

cropdetect 过滤器的描述:

Auto-detect the crop size.
It calculates the necessary cropping parameters and prints the recommended parameters via the logging system.
The detected dimensions correspond to the non-black area of the input video.

cropdetect 结果与 Linux 结合使用在 this post 中有所描述。

我想在Windows10中使用,结果发现this example,
但它不起作用...


以下代码有效(使用 ffmpeg 版本 4.4。1-full_build-www.gyan.dev):

ffmpeg -hide_banner -i in.jpg -vf scale=1920:1080,setsar=1:1,cropdetect=skip=0 -t 1 -f null - 2>&1 | findstr /R /C:"crop=" > log.txt
for /F "tokens=14* delims= " %%i in (log.txt) do set crop=%%i
echo %crop%

使用 %crop% 和 FFmpeg 命令:

ffmpeg -y -i in.jpg -filter_complex "scale=1920:1080,setsar=1:1,%crop%,split[crp0][crp1];[crp0]scale=1920:1080,setsar=1:1,gblur=sigma=30[blur];[blur][crp1]overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2" out.jpg

不写入批处理文件 log.txt:

@echo off
setlocal EnableExtensions EnableDelayedExpansion
set count=1
for /F "tokens=2* delims==" %%F in ('"ffmpeg -hide_banner -i in.jpg -vf scale=1920:1080,setsar=1:1,cropdetect=skip=0 -t 1 -f null - 2>&1"') do (
  set var!count!=%%F
  set /a count=!count!+1
)
echo %var1%

ffmpeg -y -i in.jpg -filter_complex "scale=1920:1080,setsar=1:1,crop=%var1%,split[crp0][crp1];[crp0]scale=1920:1080,setsar=1:1,gblur=sigma=30[blur];[blur][crp1]overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2" out.jpg
endlocal