FFmpeg - 连接可变长度的intro / outro固定段和单独的音轨

时间:2017-09-21 09:21:00

标签: ffmpeg

我正在尝试创建一个基于3个主要部分生成视频的应用: -

  1. 简介 - 可变长度视频(约20至30秒)
  2. 细分 - 来自"段视频的3个片段" - 这是一个固定长度的视频(总是400秒),其中包含100个独立的视频,所有视频的长度均为4秒,例如"段1" 04秒,"段3 "从812秒。
  3. Outro - 可变长度视频(约10至20秒)
  4. 用户从视频列表中选择前奏,片段和outro,应用将这些视频连接在一起(并随机提取3段)。用户还可以选择播放整个视频的音频文件。生成的文件应如下所示: -

    生成的视频

    VIDEO   | Intro (20 - 30) |  Seg 1 (4) |  Seg 2 (4) |  Seg 3 (4) |  Outro (10 - 20)  |
    --------+-----------------+------------+------------+------------+-------------------+
    AUDIO   |        Audio track which spans full video (e.g. 4 minutes long) ...        |
    

    我已经能够使用ffmpeg(有效)来共同破解以下内容: -

    ffmpeg -y \
      -i audio/audio-19.m4a \
      -i videos/intro/intro-23.mkv \
      -i videos/segments/segments-88.mkv \
      -i videos/outro/outro-12.mkv \
      -filter_complex \
        "[1:v]trim=0:30,setpts=PTS-STARTPTS[v0]; \
        [0:a]atrim=0:30,asetpts=PTS-STARTPTS[a0]; \
        [2:v]trim=20:24,setpts=PTS-STARTPTS[v1]; \
        [0:a]atrim=30:34,asetpts=PTS-STARTPTS[a1]; \
        [2:v]trim=60:64,setpts=PTS-STARTPTS[v2]; \
        [0:a]atrim=34:38,asetpts=PTS-STARTPTS[a2]; \
        [2:v]trim=132:136,setpts=PTS-STARTPTS[v3]; \
        [0:a]atrim=38:42,asetpts=PTS-STARTPTS[a3]; \
        [3:v]trim=0:20,setpts=PTS-STARTPTS[v4]; \
        [0:a]atrim=42:62,asetpts=PTS-STARTPTS[a4]; \
        [v0][a0][v1][a1][v2][a2][v3][a3][v4][a4]concat=n=5:v=1:a=1[out]" \
      -map "[out]" generated.mkv
    

    但是,此解决方案存在两个问题: -

    1. 我必须定义介绍视频([1:v]trim=0:30 ...)和outro视频([3:v]trim=0:20 ...)的长度 - 这些是可变的,最好如果我能简单地连接整个视频。
    2. 修剪每个音频轨道(使用来自每个视频长度的运行总计),例如[0:a]atrim=0:30 ... => [0:a]atrim=30:34 ... => [0:a]atrim=34:38 ... =>如果它只是简单地说 - "这里的音轨 - 根据生成的视频的长度进行修剪,将会容易得多。
    3. 非常感谢任何建议!

1 个答案:

答案 0 :(得分:1)

经过多次阅读,试验和错误,我得到了一个更好的解决方案: -

ffmpeg -y \
  -i audio/audio-19.m4a \
  -i videos/intro/intro-23.mkv \
  -i videos/segments/segments-88.mkv \
  -i videos/outro/outro-12.mkv \
  -filter_complex \
    "[2:v]trim=20:24,setpts=PTS-STARTPTS[s1]; \
     [2:v]trim=60:64,setpts=PTS-STARTPTS[s2]; \
     [2:v]trim=132:136,setpts=PTS-STARTPTS[s3]; \
     [1][s1][s2][s3][3]concat=n=5:v=1:a=0[outv]" \
  -map "[outv]" -map 0:a -shortest generated.mkv

使用此解决方案,我只修剪了段视频(例如[2:v]trim=20:24)并将时间戳重置为零(setpts=PTS-STARTPTS[s1] - 请参阅https://trac.ffmpeg.org/wiki/FilteringGuide了解为何需要这样做。对于3个段,这样做了3次。

concat复合过滤器仅连接视频

[1][s1][s2][s3][3]concat=n=5:v=1:a=0[outv]

它从介绍视频([1]),新创建的片段剪辑视频([s1][s2][s3])以及最后的outro视频([3])中抓取视频并将它们连接在一起。但是,它会忽略音频,即concat=n=5:v=1:a=0 (与之前的解决方案中的concat=n=5:v=1:a=1相比)并将其保存到名为[outv]的新视频流中。

有关连接的详细信息,请参阅https://ffmpeg.org/ffmpeg-filters.html#concat

最后,我们使用这个新的连续视频流 "[outv]"以及来自第一个输入文件(0:a)的音频来映射视频,即

-map "[outv]" -map 0:a -shortest generated.mkv

假设音频轨道长于生成的视频的长度,因此-shortest参数将输出修剪为最短流(即生成的视频的长度)。

这有助于我理解-map命令 -  https://ffmpeg.org/ffmpeg.html#Advanced-options