使用 MPlayer 和 MEncoder 在视频上叠加图像
在 升级后有哪些问题? 的持续讨论中,我尝试运行我的 logo-overlay 脚本,以便将 Linux Journal 徽标添加到视频中,正如您可能猜到的那样,它没有工作。 在这种情况下,我事先得到了警告...
当我说我事先得到了警告时,我的意思是我的帖子的一位读者/评论员提醒我,我正在 ffmpeg 中使用的功能(“vhook”功能)正在被弃用,并且已经从开发主干中删除。 当然,我当时没有采取任何措施,因为嘿,它对我来说是有效的。 好吧,现在它不行了!
最新版本的 ffmpeg 已经用 “avfilters” 机制取代了 “vhook”。 这些不是实际的叠加功能,而是将 “过滤器” 引入处理链的方式。 新的 “avfilters” 据说包含一个 “overlay” 过滤器,但 avfilter 功能似乎没有编译到 openSUSE 版本的 ffmpeg 中。 我从开发存储库下载了最新的 ffmpeg,并配置和构建了它,并启用了 avfilters,但这也没有生成叠加过滤器。 此外,我在下载的源代码中找不到任何看起来像是 overlay 过滤器的东西。 我不想花太多时间试图弄清楚这一点,所以我开始寻找另一种解决方案。
我开始查看 mencoder(mplayer 项目的一部分),并注意到-vf bmovl选项,它是位图叠加(bmovl)视频过滤器(-vf)。 我最初的尝试似乎没有奏效,但幸运的是,其他人已经弄清楚了,并在这里记录了它 here。 我认为在这里重现它的核心内容并添加一些我自己的解释,以及展示更多可以使用此功能完成的事情会很有用。 以下内容本质上与您在上面的链接中找到的内容相同,它将位图叠加到视频上并输出新视频。
logo=logo.png
logo_width=600
logo_height=500
input_video=input.ogv
output_video=output.raw
rm -f $output_video
rm -f tfifo
rm -f tlogo.rgba
mkfifo tfifo
# Convert logo to RGBA.
convert $logo tlogo.rgba
# Copy logo to fifo.
(echo "RGBA32 $logo_width $logo_height 0 0 0 1" ; cat tlogo.rgba ) >tfifo &
# Convert input video with overlay from fifo.
mencoder -oac pcm -ovc raw -vf bmovl=0:0:tfifo -o $output_video $input_video
rm -f tfifo
rm -f tlogo.rgba
Mencoder 与 ffmpeg 非常相似,都可以进行视频编码/转换。 它的一个功能是能够将来自 fifo 的数据叠加到视频之上。 在这种情况下,我正在获取我想要叠加的徽标,并将其转换为 RGBA32 格式(这本质上只是未压缩/未编码的图像数据,每个像素 32 位)。 然后,mencoder fifo 命令和 RGBA32 数据被馈送到 fifo
(echo "RGBA32 $logo_width $logo_height 0 0 0 1" ; cat tlogo.rgba ) >tfifo &
Mencoder 在前台运行,并在转换输入视频的同时叠加来自 fifo 的数据。
mencoder -oac pcm -ovc raw -vf bmovl=0:0:tfifo -o $output_video $input_video
请注意,为了使其有任何价值,您的徽标(叠加位图)需要具有 alpha 通道,即除了徽标所在的位置之外,它需要在任何地方都是透明的。
这里感兴趣的选项是-vf bmovl=0:0:tfifo选项。 这告诉 mencoder 应用视频过滤器 (-vf) 到转换/编码,在这种情况下是位图叠加过滤器 (bmovl)。 bmovl 选项是hidden:opaque:fifo,其中
- hidden指定叠加的位图应该是隐藏的还是可见的,这里 0 表示可见(不隐藏)。
- opaque指定叠加的位图是否应该允许视频显示出来,还是应该阻止它,这里 0 表示透明(不透明),以便徽标位图的透明部分不会阻止视频的其余部分。
- fifo只是 fifo 文件的名称,这里是tfifo.
同样值得关注的是 fifo 命令,它在 fifo 中位图数据之前RGBA32 $logo_width $logo_height 0 0 0 1。 RGBA32 指定数据是 RGBA32 格式,其参数为 “width height xpos ypos alpha clear”,其中
- width / height指定位图数据的宽度和高度(以像素为单位,而不是字节)。 位图文件(.rgba 文件)应为width * height * 4字节大小。 这里指定了徽标叠加图像的大小。
- xpos / ypos指定位图数据要叠加在视频中的 X 和 Y 位置。 这里位置很简单,是 0,0。
- alpha允许您修改位图的 alpha 值(见下文)。 这里 0 表示不更改位图的 alpha 值。
- clear指定是否在应用新的位图数据之前清除 fifo 中的现有位图数据,或者新的位图数据是否覆盖在现有位图数据的顶部。 这里 1 表示清除数据,这可能是多余的,因为我们只有一个位图图像,但以防万一默认情况下有垃圾,我们指定 1 来清除它。
alpha 选项可能需要更多解释。 alpha 选项的值介于 -255 和 255 之间。 从 -1 到 -255 的值使您的位图越来越透明,允许更多视频显示出来,在 -255 时,您的位图完全透明,只有视频可见。 从 1 到 255 的值使您的位图越来越不透明,允许更少的视频显示出来,在 255 时,您的位图完全不透明,并且在位图所在的区域中看不到任何视频。
为了回顾一下,mencoder/mplayer fifo 不是单个命令 fifo,它可以接受多个命令和位图(如果命令需要位图数据)。 因此,通过传递增加或减少的 alpha 值,我们可以淡入和淡出视频上的位图叠加。 例如,我们可以使用以下命令序列在播放视频的顶部淡入然后淡出位图
rm -f tfifo
rm -f overlay.rgba
mkfifo tfifo
convert overlay.png overlay.rgba
(
alpha=-255
fade=20
while [[ $alpha -le 0 ]]
do
(echo "RGBA32 200 200 0 0 $alpha 1"; cat overlay.rgba) >tfifo
sleep 0.1
let t=alpha+fade
if [[ $alpha -ne 0 && $t -gt 0 ]]; then t=0; fi
alpha=$t
done
sleep 0.5
while [[ $alpha -ge -255 ]]
do
(echo "RGBA32 200 200 0 0 $alpha 1"; cat overlay.rgba) >tfifo
sleep 0.1
let t=alpha-fade
if [[ $alpha -ne 0 && $t -le -255 ]]; then t=-255; fi
alpha=$t
done
) &
pid=$!
mplayer -vf bmovl=0:0:tfifo video.ogv
rm -f tfifo
rm -f overlay.rgba
if kill -0 $pid; then kill -9 $pid; fi
您会注意到此脚本使用 mplayer 而不是 mencoder。 我最初的想法是,我可以使用 mencoder 来叠加位图序列,因为视频是由 mencoder 编码的,并将视频保存在新文件中,但到目前为止,我还没有能够实现这一点。 Mencoder 只是编码,因此它不会以数据出现在 fifo 中的速率对事物进行排序:它只是尽可能快地进行,这意味着大多数 fifo 命令都会丢失。 可能有办法使其工作,但我尚未找到。 请参阅附件 video 以获取脚本运行的示例。
回到最初的问题,即在视频上叠加 LJ 徽标。 使用 mencoder 结果证明是一个不太有用的解决方案,因为除了我的叠加脚本中断之外,我的视频录制解决方案 (xvidcap) 在升级后也已损坏。 它捕获视频,但在播放时会变得断断续续。 因此,这需要我更换录制程序并开始使用 recordmydesktop 来录制视频。 它工作得相当好(上次我尝试时没有),尽管 xvidcap 具有更好的 UI。
但是,recordmydesktop 仅捕获 .ogv 视频,而 mencoder 不会输出 .ogv 文件。 因此,我必须将徽标叠加到捕获的 .ogv 文件上并输出原始视频。 然后我必须使用 ffmpeg 将带有徽标的原始视频转换回 .ogv(和 .mp4),以便我同时拥有 .ogv 和 .mp4 文件。 不幸的是,ffmpeg 搞砸了转换后的 .ogv 文件中的音频/视频同步,因此使用该操作序列效果不佳。
我的最终解决方案将等到下次。 对于这个曲折的故事,我深感抱歉。