如何修复 ffmpeg 连接视频播放问题?

如何修复 ffmpeg 连接视频播放问题?

我想在我的视频中添加水印(在特定时间)。我研究了一些资料,上面说我需要(视频过滤器)重新编码整个视频才能添加水印,但我没有高端电脑来做这件事。如果我重新编码整个视频,大约需要 6 到 7 个小时。

不过,我想到了一些好主意。我创建了三个片段,第一个片段(19 分钟)是原始视频,第二个片段(21 秒)是需要水印的地方,第三个片段(15 分钟)也是原始视频。所以,我将水印放在第二个片段中,然后用 ffmpeg 将它们连接起来(注意:我没有重新编码所有片段。我只重新编码了第二个片段,并将它们与没有重新编码的视频合并在一起)。

但是,在播放第 2 段时,出现了卡顿等播放问题。不过,我在连接之前单独播放了这些片段,播放得很流畅。连接后,播放出现了问题。下面提供了这三个片段的 FFmpeg 详细信息

Segment 1 (Original video)


  libavutil      56. 70.100 / 56. 70.100
  libavcodec     58.134.100 / 58.134.100
  libavformat    58. 76.100 / 58. 76.100
  libavdevice    58. 13.100 / 58. 13.100
  libavfilter     7.110.100 /  7.110.100
  libswscale      5.  9.100 /  5.  9.100
  libswresample   3.  9.100 /  3.  9.100
  libpostproc    55.  9.100 / 55.  9.100
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'output_1.mp4':
  Metadata:
    major_brand     : isom
    minor_version   : 512
    compatible_brands: isomiso2avc1mp41
    encoder         : Lavf58.76.100
  Duration: 00:01:30.09, start: 0.000000, bitrate: 2258 kb/s
  Stream #0:0(und): Video: h264 (Main) (avc1 / 0x31637661), yuv420p(tv, bt709), 1280x720 [SAR 1:1 DAR 16:9], 2056 kb/s, 30 fps, 30 tbr, 90k tbn, 60 tbc (default)
    Metadata:
      handler_name    : VideoHandler
      vendor_id       : [0][0][0][0]
  Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 195 kb/s (default)
    Metadata:
      handler_name    : SoundHandler
      vendor_id       : [0][0][0][0]

Segment 2 (Watermark video)

  libavutil      56. 70.100 / 56. 70.100
  libavcodec     58.134.100 / 58.134.100
  libavformat    58. 76.100 / 58. 76.100
  libavdevice    58. 13.100 / 58. 13.100
  libavfilter     7.110.100 /  7.110.100
  libswscale      5.  9.100 /  5.  9.100
  libswresample   3.  9.100 /  3.  9.100
  libpostproc    55.  9.100 / 55.  9.100
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'output_2.mp4':
  Metadata:
    major_brand     : isom
    minor_version   : 512
    compatible_brands: isomiso2avc1mp41
    encoder         : Lavf58.76.100
  Duration: 00:00:22.10, start: 0.000000, bitrate: 5648 kb/s
  Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p(tv, bt709), 1280x720 [SAR 1:1 DAR 16:9], 5443 kb/s, 30 fps, 30 tbr, 15360 tbn, 60 tbc (default)
    Metadata:
      handler_name    : VideoHandler
      vendor_id       : [0][0][0][0]
  Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 196 kb/s (default)
    Metadata:
      handler_name    : SoundHandler
      vendor_id       : [0][0][0][0]


Segment 3 (Original video)

  libavutil      56. 70.100 / 56. 70.100
  libavcodec     58.134.100 / 58.134.100
  libavformat    58. 76.100 / 58. 76.100
  libavdevice    58. 13.100 / 58. 13.100
  libavfilter     7.110.100 /  7.110.100
  libswscale      5.  9.100 /  5.  9.100
  libswresample   3.  9.100 /  3.  9.100
  libpostproc    55.  9.100 / 55.  9.100
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'output_3.mp4':
  Metadata:
    major_brand     : isom
    minor_version   : 512
    compatible_brands: isomiso2avc1mp41
    encoder         : Lavf58.76.100
  Duration: 00:01:53.11, start: 0.000000, bitrate: 2269 kb/s
  Stream #0:0(und): Video: h264 (Main) (avc1 / 0x31637661), yuv420p(tv, bt709), 1280x720 [SAR 1:1 DAR 16:9], 2067 kb/s, 30 fps, 30 tbr, 90k tbn, 60 tbc (default)
    Metadata:
      handler_name    : VideoHandler
      vendor_id       : [0][0][0][0]
  Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 195 kb/s (default)
    Metadata:
      handler_name    : SoundHandler
      vendor_id       : [0][0][0][0]


Concated full video


  libavutil      56. 70.100 / 56. 70.100
  libavcodec     58.134.100 / 58.134.100
  libavformat    58. 76.100 / 58. 76.100
  libavdevice    58. 13.100 / 58. 13.100
  libavfilter     7.110.100 /  7.110.100
  libswscale      5.  9.100 /  5.  9.100
  libswresample   3.  9.100 /  3.  9.100
  libpostproc    55.  9.100 / 55.  9.100
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'output_merged.mp4':
  Metadata:
    major_brand     : isom
    minor_version   : 512
    compatible_brands: isomiso2avc1mp41
    encoder         : Lavf58.76.100
  Duration: 00:03:45.29, start: 0.000000, bitrate: 2596 kb/s
  Stream #0:0(und): Video: h264 (Main) (avc1 / 0x31637661), yuv420p(tv, bt709), 1280x720 [SAR 1:1 DAR 16:9], 2393 kb/s, 29.99 fps, 30 tbr, 90k tbn, 60 tbc (default)
    Metadata:
      handler_name    : VideoHandler
      vendor_id       : [0][0][0][0]
  Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 195 kb/s (default)
    Metadata:
      handler_name    : SoundHandler
      vendor_id       : [0][0][0][0]
      

更新 1-使用 FFMPEG 命令

Split command

ffmpeg -hide_banner -ss "0" -i "output.mp4" -t "90" -avoid_negative_ts make_zero -map "0:0" "-c:0" copy -map "0:1" "-c:1" copy -map_metadata 0 -movflags "+faststart" -ignore_unknown -f mp4 -y "tmp/output_1.mp4"

ffmpeg -hide_banner -ss "90" -i "output.mp4" -t "20" -avoid_negative_ts make_zero -map "0:0" "-c:0" copy -map "0:1" "-c:1" copy -map_metadata 0 -movflags "+faststart" -ignore_unknown -f mp4 -y "tmp/output_2.mp4"

ffmpeg -hide_banner -ss "110" -i "output.mp4" -t "111" -avoid_negative_ts make_zero -map "0:0" "-c:0" copy -map "0:1" "-c:1" copy -map_metadata 0 -movflags "+faststart" -ignore_unknown -f mp4 -y "tmp/output_3.mp4"


Applying watermark command

ffmpeg -hide_banner -i "tmp/output_2.mp4" -vf "drawtext='fontfile=DejaVu Sans\:style=Semibold:text=HelloWorld:fontcolor=white:fontsize=30:y=h-50*t:x=w-(t-4.5)*(w+tw)/15'" -vcodec libx264 -crf 15 -c:a copy "tmp/watermark_output_2.mp4"

Concat files command

ffmpeg -f concat -safe 0 -i "../filelist.txt" -c copy "output_merged.mp4"

更新-已上传2个输出视频。

第 1 段原始视频(未重新编码) https://drive.google.com/file/d/1Mg7rJxXGcxg25328flJ_CD9NJhfpFj37/view?usp=sharing

第 2 段水印视频(重新编码) - 水印从 4 秒开始,播放时没有任何问题。

https://drive.google.com/file/d/141KYQ1m94bIpxKj5n7_wCcbTOWQ9uO17/view?usp=sharing

第 3 部分原始视频(未重新编码)

https://drive.google.com/file/d/1fYkFvD6Yg81Un7YhfUJbSJ-VBk2qlFvJ/view?usp=sharing

连接完整视频(问题从出现水印时开始。(时间 00:01:28 分钟)

https://drive.google.com/file/d/1Tq6wXSWGSeAHBwfsV31-Qpt5BhJeWwSJ/view?usp=sharing

连接过程中重复出现错误

[mp4 @ 0x5594ce3c8280] Non-monotonous DTS in output stream 0:0; previous: 8099300, current: 1715482; changing to 8099301. This may result in incorrect timestamps in the output file.

答案1

正如评论和记录所示,使用Concat 解复用器,所有文件必须具有相同的流(相同的编解码器,相同的时间基准等),并且在您的情况下重新编码部分的时间基准是不同的。

还有其他问题:

  • 对于无需重新编码的连接,我们通常喜欢所有以关键帧
  • MP4容器不是设计为“分段”的,我们最好使用其他容器。

以下解决方案可能并不适用于所有情况,但我认为它适用于您的情况(H.264 视频编解码器和 AAC 音频编解码器):

我们最好-ss使用-t段复用器
我们也可以使用 FLV 容器格式(它更适合连接,并且解决了时间基准问题):

ffmpeg -i input.mp4 -c copy -f segment -segment_time 20 -segment_list list.txt -segment_list_type ffconcat %04d.flv

默认情况下,Segment Muxer 仅在关键帧处断开部分(-break_non_keyframes默认情况下为 false)

找到相关段并创建副本:copy 0001.flv original_0001.flv


在相关片段中添加水印(可能要手动调整时间):

ffmpeg -y -hide_banner -i "original_0001.flv" -vf "drawtext='fontfile=DejaVuSans.ttf:text=HelloWorld:fontcolor=white:fontsize=30:y=h-50*t:x=w-(t-4.5)*(w+tw)/15'" -vcodec libx264 -crf 15 -c:a copy "0001.flv"

(请注意,该style=Semibold参数给了我一个错误)。


将片段重新连接起来,无需重新编码(可以使用 MP4 输出文件格式):

ffmpeg -y -f concat -safe 0 -i list.txt -c copy output.mp4

相关内容