ffmpeg 视频合成,使用 alphamerge 对视频进行几何区域裁剪

做过视频合成的人都知道,视频合成的时候,有时候需要对视频进行裁剪,比如只需要视频的一部分,或者只需要视频的某个区域,这个时候就需要对视频进行裁剪。

如果只是要裁剪掉某个时间段,那比较简单,使用 ffmpeg 的 -ss 和 -t 参数就可以了,比如:

shell 复制代码
ffmpeg -i input.mp4 -ss 00:00:10 -t 00:00:20 -c copy output.mp4

如果是只需要视频中的某个区域怎么办呢?比如做绿幕视频合成,例如下面这个绿幕视频,其中内容是一只老虎,如果要将老虎叠加到另一个森林视频中合成。

这种视频可以使用 ffmpeg chromakey 滤镜来处理,根据色键来去除绿幕,然后叠加到其他视频上。

shell 复制代码
ffmpeg -i tiger.mp4 -i forest.mp4 -shortest -filter_complex "[1:v]scale=1920:1080,chromakey=0x15ff09:0.08:0.0[ckout];[0:v][ckout]overlay[out]" -map "[out]" -y output.mp4

这个命令中的 chromakey=0x15ff09:0.08:0.0 是一个 FFmpeg 中的滤镜,用于将视频中的某个颜色替换成透明。其中 0x15ff09 是要替换的颜色,0.08 是颜色的容差,0.0 是透明度。具体来说,这个滤镜会将颜色值为 0x15ff09 的像素替换成透明像素,容差为 0.08,透明度为 0.0。

但是这种方式的处理效果通常不太理想,如果主体形象中有绿色的部分,那么这部分也会被去除,导致主体形象出现空洞。

一般更建议使用 ffmpeg 的 alphamerge 滤镜来处理,如果要将 A.mp4 和 B.mp4 两个视频叠加合成。一般需要提供 A_mask.mp4 这样的视频,这个视频中的内容和 A.mp4 类似,包含其中的透明通道信息,如下所示:

可以使用下面的命令来合成视频:

shell 复制代码
ffmpeg -i digit.mp4 -i digit_mask.mp4 -i 1920.mp4 -filter_complex '[1][0]scale2ref[mask][main];[main][mask]alphamerge[vid];[vid][2:v]scale2ref=w=iw/2:h=ih/2[origin][digit];[digit][origin]overlay=x=-200:y=540[out]' -map 1:a -c:a copy -map [out] -y output.mp4

这种 mask 视频一般是和原视频一起生成的,时长也相同,这种 mask 视频就是专门用来抠像的,将视频中的绿幕去除,然后叠加到其他视频上。

那么如果我需要在视频中裁剪出一个区域,然后叠加到其他视频上,又该如何实现呢?

比如在人物的头部区域增加一个灰色的圆形区域,或者是圆角矩形,正方形等几何图形等。

依然可以使用 alphamerge 滤镜来实现, 在上一个命令的基础上,我们还需要动态生成一个包含几何区域的 PNG 图片来裁剪图形,除几何区域外,其他内容都是透明的。

现在,除了有 mask 视频之外,还有一个图片作为遮罩,需要使用两次 alphamerge 滤镜。现将人像抠出来,再在人像头部区域后面添加一个圆形区域,ffmpeg 合成命令如下:

shell 复制代码
ffmpeg -i digit.mp4 -i digit_mask.mp4 -i mask1920.png -i 1920.mp4 -filter_complex '[0][1]alphamerge[vid];[2][vid]overlay[vid2];[2]fps=25,loop=999:size=1[mask1920_fps];[mask1920_fps]format=rgba[msk];[msk]alphaextract[alfa];[vid2][alfa]alphamerge[rid];[3:v][rid]overlay[out]' -map 1:a -c:a copy -map [out] -y z.mp4

上面的命令需要的全部资源都在这里:

我们再借助 ChatGPT 来解释一下这行命令:

  1. -i digit.mp4:这是输入文件 digit.mp4,它是我们想要处理的视频文件。

  2. -i digit_mask.mp4:这是输入文件 digit_mask.mp4,它是一个视频文件,作为 digit.mp4 的遮罩(alpha 融合)。

  3. -i mask1920.png:这是输入文件 mask1920.png,它是一个图片文件,作为另一个遮罩。

  4. -i 1920.mp4:这是输入文件 1920.mp4,它是另一个视频文件,我们将在其上叠加遮罩。

  5. -filter_complex:这是复杂滤镜图形的开始。

  6. [0][1]alphamerge[vid]:这一步将 digit.mp4digit_mask.mp4 进行 alpha 融合,生成一个新的视频流 vid

  7. [2][vid]overlay[vid2]:这一步将 mask1920.png 和之前生成的 vid 进行叠加,生成另一个新的视频流 vid2。这一步是为了在数字人头像背后添加颜色形状。

  8. [2]fps=25,loop=999:size=1[mask1920_fps]:这一步将 mask1920.png 设置为持续循环的视频流,生成新的视频流 mask1920_fpsfps=25 设置 mask1920.png 的帧率为 25 帧/秒,loop=999:size=1mask1920.png 循环播放 999 次,但由于 size=1,实际上只有 1 帧。

  9. [mask1920_fps]format=rgba[msk]:这一步将之前生成的 mask1920_fps 转换为带有 alpha 通道的视频流,生成新的视频流 msk

  10. [msk]alphaextract[alfa]:这一步从视频流 msk 中提取 alpha 通道,生成新的视频流 alfa

  11. [vid2][alfa]alphamerge[rid]:这一步将 vid2alfa 进行 alpha 融合,得到一个新的视频流 rid。在这里,alfa 的 alpha 通道将被应用到 vid2 上,实现遮罩效果。

  12. [3:v][rid]overlay[out]:这一步将 1920.mp4rid 进行叠加,得到最终的输出视频流 out。在这里,rid 会覆盖 1920.mp4 的一部分区域,实现叠加效果。

  13. -map 1:a -c:a copy -map [out]:这一部分用于保留输入文件 digit_mask.mp4 的音频流,并将输出视频流 out 作为输出文件的视频流。

  14. -y z.mp4:这是输出文件的设置,z.mp4 是输出的视频文件名。

这样,整个命令实现了将 digit_mask.mp4mask1920.png 作为遮罩应用到 digit.mp41920.mp4 上,并输出为 z.mp4

相关推荐
m0_748255262 小时前
前端安全——敏感信息泄露
前端·安全
鑫~阳3 小时前
html + css 淘宝网实战
前端·css·html
Catherinemin3 小时前
CSS|14 z-index
前端·css
2401_882727575 小时前
低代码配置式组态软件-BY组态
前端·后端·物联网·低代码·前端框架
NoneCoder5 小时前
CSS系列(36)-- Containment详解
前端·css
anyup_前端梦工厂5 小时前
初始 ShellJS:一个 Node.js 命令行工具集合
前端·javascript·node.js
5hand5 小时前
Element-ui的使用教程 基于HBuilder X
前端·javascript·vue.js·elementui
GDAL6 小时前
vue3入门教程:ref能否完全替代reactive?
前端·javascript·vue.js
六卿6 小时前
react防止页面崩溃
前端·react.js·前端框架
z千鑫6 小时前
【前端】详解前端三大主流框架:React、Vue与Angular的比较与选择
前端·vue.js·react.js