将两个视频叠加到静态图像上?

14
我有两个视频,想将它们合并成一个视频,在其中两个视频都会位于静态背景图像上方。(类似于这个)。我的要求是使用的软件必须是免费的,在OSX上运行,并且不需要重复编码多次。我还希望能够通过命令行或脚本执行此操作,因为我会经常使用它。(但这不是绝对必要的。)
我尝试了几个小时的ffmpeg,但它似乎不太适合后期处理。我可以通过叠加功能可能把它组合在一起,但到目前为止,我还没有找到如何做到这一点,除了将图像痛苦地转换为视频(这需要比我的视频长度长2倍的时间!)然后在另一个渲染步骤中将两个视频叠加到其上。
有什么建议吗?谢谢!
更新:
在LordNeckbeard的帮助下,我能够通过单个ffmpeg调用实现所需的结果!不幸的是,编码速度非常慢,每秒钟编码1秒的视频需要6秒。我相信这是由于背景图像引起的。有什么加速编码的技巧吗?以下是ffmpeg日志:
MacBook-Pro:Video archagon$ ffmpeg -loop 1 -i underlay.png -i test-slide-video-short.flv -i test-speaker-video-short.flv -filter_complex "[1:0]scale=400:-1[a];[2:0]scale=320:-1[b];[0:0][a]overlay=0:0[c];[c][b]overlay=0:0" -shortest -t 5 -an output.mp4
ffmpeg version 1.0 Copyright (c) 2000-2012 the FFmpeg developers
  built on Nov 14 2012 16:18:58 with Apple clang version 4.0 (tags/Apple/clang-421.0.60) (based on LLVM 3.1svn)
  configuration: --prefix=/opt/local --enable-swscale --enable-avfilter --enable-libmp3lame --enable-libvorbis --enable-libopus --enable-libtheora --enable-libschroedinger --enable-libopenjpeg --enable-libmodplug --enable-libvpx --enable-libspeex --mandir=/opt/local/share/man --enable-shared --enable-pthreads --cc=/usr/bin/clang --arch=x86_64 --enable-yasm --enable-gpl --enable-postproc --enable-libx264 --enable-libxvid
  libavutil      51. 73.101 / 51. 73.101
  libavcodec     54. 59.100 / 54. 59.100
  libavformat    54. 29.104 / 54. 29.104
  libavdevice    54.  2.101 / 54.  2.101
  libavfilter     3. 17.100 /  3. 17.100
  libswscale      2.  1.101 /  2.  1.101
  libswresample   0. 15.100 /  0. 15.100
  libpostproc    52.  0.100 / 52.  0.100
Input #0, image2, from 'underlay.png':
  Duration: 00:00:00.04, start: 0.000000, bitrate: N/A
    Stream #0:0: Video: png, rgb24, 1024x768, 25 fps, 25 tbr, 25 tbn, 25 tbc
Input #1, flv, from 'test-slide-video-short.flv':
  Metadata:
    author          : 
    copyright       : 
    description     : 
    keywords        : 
    rating          : 
    title           : 
    presetname      : Custom
    videodevice     : VGA2USB Pro V3U30343
    videokeyframe_frequency: 5
    canSeekToEnd    : false
    createdby       : FMS 3.5
    creationdate    : Mon Aug 16 16:35:34 2010
    encoder         : Lavf54.29.104
  Duration: 00:50:32.75, start: 0.000000, bitrate: 90 kb/s
    Stream #1:0: Video: vp6f, yuv420p, 640x480, 153 kb/s, 8 tbr, 1k tbn, 1k tbc
Input #2, flv, from 'test-speaker-video-short.flv':
  Metadata:
    author          : 
    copyright       : 
    description     : 
    keywords        : 
    rating          : 
    title           : 
    presetname      : Custom
    videodevice     : Microsoft DV Camera and VCR
    videokeyframe_frequency: 5
    audiodevice     : Microsoft DV Camera and VCR
    audiochannels   : 1
    audioinputvolume: 75
    canSeekToEnd    : false
    createdby       : FMS 3.5
    creationdate    : Mon Aug 16 16:35:34 2010
    encoder         : Lavf54.29.104
  Duration: 00:50:38.05, start: 0.000000, bitrate: 238 kb/s
    Stream #2:0: Video: vp6f, yuv420p, 320x240, 204 kb/s, 25 tbr, 1k tbn, 1k tbc
    Stream #2:1: Audio: mp3, 22050 Hz, mono, s16, 32 kb/s
File 'output.mp4' already exists. Overwrite ? [y/N] y
using cpu capabilities: none!
[libx264 @ 0x7fa84c02f200] profile High, level 3.1
[libx264 @ 0x7fa84c02f200] 264 - core 119 - H.264/MPEG-4 AVC codec - Copyleft 2003-2011 - http://www.videolan.org/x264.html - options: cabac=1 ref=3 deblock=1:0:0 analyse=0x3:0x113 me=hex subme=7 psy=1 psy_rd=1.00:0.00 mixed_ref=1 me_range=16 chroma_me=1 trellis=1 8x8dct=1 cqm=0 deadzone=21,11 fast_pskip=1 chroma_qp_offset=-2 threads=3 sliced_threads=0 nr=0 decimate=1 interlaced=0 bluray_compat=0 constrained_intra=0 bframes=3 b_pyramid=2 b_adapt=1 b_bias=0 direct=1 weightb=1 open_gop=0 weightp=2 keyint=250 keyint_min=25 scenecut=40 intra_refresh=0 rc_lookahead=40 rc=crf mbtree=1 crf=23.0 qcomp=0.60 qpmin=0 qpmax=69 qpstep=4 ip_ratio=1.40 aq=1:1.00
Output #0, mp4, to 'output.mp4':
  Metadata:
    encoder         : Lavf54.29.104
    Stream #0:0: Video: h264 ([33][0][0][0] / 0x0021), yuv420p, 1024x768, q=-1--1, 25 tbn, 25 tbc
Stream mapping:
  Stream #0:0 (png) -> overlay:main
  Stream #1:0 (vp6f) -> scale
  Stream #2:0 (vp6f) -> scale
  overlay -> Stream #0:0 (libx264)
Press [q] to stop, [?] for help

更新2:

它可以工作了!一个重要的调整是将underlay.png输入移动到输入列表的末尾。这大大提高了性能。这是我的最终ffmpeg调用。(结尾处的映射对于这个特定的安排并不是必需的,但我有时会有一些额外的音频输入,我想将它们映射到我的输出。)

ffmpeg
    -i VideoOne.flv
    -i VideoTwo.flv
    -loop 1 -i Underlay.png
    -filter_complex "[2:0] [0:0] overlay=20:main_h/2-overlay_h/2 [overlay];[overlay] [1:0] overlay=main_w-overlay_w-20:main_h/2-overlay_h/2 [output]"
    -map [output]:v
    -map 0:a
    OutputVideo.m4v
1个回答

58

在ffmpeg中,复杂的滤镜图看起来可能很复杂,但是只要你尝试几次就会有意义。您需要熟悉滤镜图语法。首先阅读Filtering IntroductionFiltergraph Description。您不必完全理解它,但这将帮助您理解以下示例。

示例

two videos over static image

使用scale视频过滤器来缩放(调整大小)输入到指定的尺寸,然后使用overlay视频过滤器将视频放在静态图像上方。
ffmpeg -loop 1 -i background.png -i video1.mp4 -i video2.mp4 -filter_complex \
"[1:v]scale=(iw/2)-20:-1[a]; \
 [2:v]scale=(iw/2)-20:-1[b]; \
 [0:v][a]overlay=10:(main_h/2)-(overlay_h/2):shortest=1[c]; \
 [c][b]overlay=main_w-overlay_w-10:(main_h/2)-(overlay_h/2)[video]" \
-map "[video]" output.mkv

这是什么意思

无过滤选项:

  • -loop 1 连续循环下一个输入,即background.png

  • background.png 背景图像。stream specifier[0:v],大小为1280x720。

  • video1.mp4 第一个视频输入(在示例图像中为Big Buck Bunny)。流规范符为[1:v],大小为640x360。

  • video2.mp4 第二个视频输入(在示例图像中为varmints)。流规范符为[2:v],大小为640x360。

过滤选项

  • -filter_complex 这是启动复杂过滤器图的选项。

  • [1:v]scale=(iw/2)-20:-1[a] 这将采用名为video1.mp4的视频,别名为[1:v],并对其进行缩放。 iw 是输入宽度的别名,在此情况下,它的值为 640。我们将其分成一半,并减去额外的 20 个像素作为填充,以使叠加的每个视频周围有空间。-1 表示自动计算保留纵横比的值。当然,您可以省略这些花哨的内容,手动提供值,例如 scale=320:240。然后使用输出链接标签命名为 [a],以便稍后引用此输出。

  • [2:v]scale=(iw/2)-20:-1[b] 与上面相同,但使用名为video2.mp4的视频作为输入,并将输出链接标签命名为[b]

  • [0:v][a]overlay=10:(main_h/2)-(overlay_h/2):shortest=1[c] 使用 background.png 作为第一个叠加层输入,并使用我们第一个缩放过滤器的结果,别名为 [a],作为第二个叠加层输入。将 [a] 放在 [0:v] 上方。main_h 是别名为 主高度 的变量,它指的是背景输入([0:v])的高度。overlay_h 是别名为叠加高度的变量,它指的是前景([a])的高度。此示例将 Big Buck Bunny 放在左侧。shortest=1 将强制输出在最短的输入终止时终止;否则,由于 background.png 在循环,它将永远循环。将此过滤器的结果命名为 [c]

  • [c][b]overlay=overlay_w*2:overlay_h:shortest=1[video] 使用 [c] 作为第一个叠加层输入,[b] 作为第二个叠加层输入。使用叠加参数 overlay_woverlay_h(叠加输入的宽度和高度)。此示例将 verminy varmints 放在右侧。将输出标记为 [video]

  • -map "[video]" 将过滤器的输出映射到输出文件。虽然不一定需要在过滤器图的末尾使用 [video] 链接标签,但建议在映射时明确指定。

音频

拥有两个独立的音频流

默认情况下,只有在流选择中定义的第一个输入音频通道将用于输出。您可以使用-map选项从第二个视频输入添加额外的音轨(输出将有两个音频流)。此示例将流复制音频而不重新编码:

ffmpeg -loop 1 -i background.png -i video1.mp4 -i video2.mp4 -filter_complex \
"[1:v]scale=(iw/2)-20:-1[a]; \
 [2:v]scale=(iw/2)-20:-1[b]; \
 [0:v][a]overlay=10:(main_h/2)-(overlay_h/2):shortest=1[c]; \
 [c][b]overlay=main_w-overlay_w-10:(main_h/2)-(overlay_h/2)[video]" \
-map "[video]" -map 1:a -map 2:a -codec:a copy output.mkv

合并两个音频流

或者使用amergepan音频滤镜将两个音频输入合并为一个(假设两个输入都是立体声且您需要立体声输出):

ffmpeg -loop 1 -i background.png -i video1.mp4 -i video2.mp4 -filter_complex \
"[1:v]scale=(iw/2)-20:-1[a]; \
 [2:v]scale=(iw/2)-20:-1[b]; \
 [0:v][a]overlay=10:(main_h/2)-(overlay_h/2):shortest=1[c]; \
 [c][b]overlay=main_w-overlay_w-10:(main_h/2)-(overlay_h/2)[video]" \
 [1:a][2:a]amerge,pan=stereo:c0<c0+c2:c1<c1+c3[audio]" \
-map "[video]" -map "[audio]" output.mkv

还可以看看


实际上,忘掉我之前的问题。当我使用vf时,我将我的25fps视频覆盖在没有背景图像的8fps视频上,这使得最终视频为8fps。从ffmpeg日志中可以看出,默认情况下图像以25fps渲染,这就是为什么我的filter_complex调用返回一个25fps视频的原因。 - Archagon
1
@Archagon,你正在使用libx264进行编码,因此可以使用比默认的medium更快的预设。请参阅FFmpeg和x264编码指南中的CRF部分,了解示例和更多信息。 - llogan
1
@Archagon 这里有一个将两个立体声输入合并成一个立体声输出的示例:ffmpeg -i input1 -i input2 -filter_complex "amerge,pan=stereo:c0<c0+c2:c1<c1+c3" ... 你可以根据自己当前的命令进行修改,更多信息请参阅 amergepan 的文档。 - llogan
2
这就像是FFMpeg的罗塞塔石。非常感谢! - R. Navega
1
你不知道我做了多少次搜索,阅读了多少文档,或者尝试了多少方法,在找到这个答案之前,它最终帮助我理解并解决了我的问题。谢谢! - David Conrad
显示剩余8条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接