ffmpeg 在动画 GIF 的最后一帧减少时间延迟

标签 ffmpeg animated-gif

我正在尝试使用 ffmpeg 和 x264 将动画 GIF 转换为 MP4 文件。但是,我似乎受到了 this bug 的影响。在 ffmpeg 中导致 GIF 的最后一帧的延迟时间被忽略。对于非常短的 GIF,这是一个相当大的问题。

作为一种解决方法,我在想我应该能够手动告诉 ffmpeg 在最后一帧卡住一段时间,特别是该帧的适当持续时间(我可以从 GIF 中提取)。但是,我似乎找不到这样做的好方法。有什么建议么?我真的很希望能够做到这一点,而不必在将 GIF 放入 ffmpeg 之前将其拆分为帧,因为这会使 GIF 的帧率非常不稳定(而且速​​度会慢得多)。

我使用的是 ffmpeg 2.3 版,虽然我也尝试过使用最新的 git 代码,但没有任何改进。我正在使用的完整 ffmpeg 命令如下所示:

ffmpeg -i animation.gif -vf "scale=trunc(in_w/2)*2:trunc(in_h/2)*2" -c:v libx264 -b:v 2000k -y -pix_fmt yuv420p -f mp4 animation.mp4

这是一些控制台输出:
ffmpeg version 2.3 Copyright (c) 2000-2014 the FFmpeg developers
  built on Aug 11 2014 21:19:46 with gcc 4.8 (Ubuntu 4.8.2-19ubuntu1)
  configuration: --enable-gpl --enable-libass --enable-libfreetype --enable-libtheora --enable-libvorbis --enable-libx264
  libavutil      52. 92.100 / 52. 92.100
  libavcodec     55. 69.100 / 55. 69.100
  libavformat    55. 48.100 / 55. 48.100
  libavdevice    55. 13.102 / 55. 13.102
  libavfilter     4. 11.100 /  4. 11.100
  libswscale      2.  6.100 /  2.  6.100
  libswresample   0. 19.100 /  0. 19.100
  libpostproc    52.  3.100 / 52.  3.100
Input #0, gif, from 'animation.gif':
  Duration: N/A, bitrate: N/A
    Stream #0:0: Video: gif, bgra, 500x375, 100 tbr, 100 tbn, 100 tbc
[libx264 @ 0x239ea00] using cpu capabilities: MMX2 SSE2Fast SSSE3 SSE4.2 AVX
[libx264 @ 0x239ea00] profile High, level 3.1
[libx264 @ 0x239ea00] 264 - core 142 - H.264/MPEG-4 AVC codec - Copyleft 2003-2014 - 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=6 lookahead_threads=1 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=abr mbtree=1 bitrate=2000 ratetol=1.0 qcomp=0.60 qpmin=0 qpmax=69 qpstep=4 ip_ratio=1.40 aq=1:1.00
Output #0, mp4, to 'animation.mp4':
  Metadata:
    encoder         : Lavf55.48.100
    Stream #0:0: Video: h264 (libx264) ([33][0][0][0] / 0x0021), yuv420p, 500x374, q=-1--1, 2000 kb/s, 100 fps, 12800 tbn, 100 tbc
    Metadata:
      encoder         : Lavc55.69.100 libx264
Stream mapping:
  Stream #0:0 -> #0:0 (gif (native) -> h264 (libx264))
Press [q] to stop, [?] for help
frame=    7 fps=0.0 q=-1.0 Lsize=       7kB time=00:00:00.05 bitrate=1222.1kbits/s dup=5 drop=0    
video:7kB audio:0kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 13.542441%
[libx264 @ 0x239ea00] frame I:1     Avg QP:34.86  size:  3657
[libx264 @ 0x239ea00] frame P:3     Avg QP:30.86  size:   744
[libx264 @ 0x239ea00] frame B:3     Avg QP:33.33  size:    49
[libx264 @ 0x239ea00] consecutive B-frames: 42.9%  0.0%  0.0% 57.1%
[libx264 @ 0x239ea00] mb I  I16..4: 10.2% 78.3% 11.6%
[libx264 @ 0x239ea00] mb P  I16..4:  1.2%  5.0%  0.8%  P16..4: 11.7%  3.3%  1.2%  0.0%  0.0%    skip:76.8%
[libx264 @ 0x239ea00] mb B  I16..4:  0.0%  0.1%  0.0%  B16..8:  3.7%  0.0%  0.0%  direct: 0.0%  skip:96.2%  L0:23.5% L1:76.5% BI: 0.0%
[libx264 @ 0x239ea00] final ratefactor: 20.31
[libx264 @ 0x239ea00] 8x8 transform intra:77.0% inter:79.4%
[libx264 @ 0x239ea00] coded y,uvDC,uvAC intra: 39.5% 0.0% 0.0% inter: 2.7% 0.0% 0.0%
[libx264 @ 0x239ea00] i16 v,h,dc,p: 38% 27%  7% 28%
[libx264 @ 0x239ea00] i8 v,h,dc,ddl,ddr,vr,hd,vl,hu: 35% 12% 13%  7%  6% 10%  4%  8%  5%
[libx264 @ 0x239ea00] i4 v,h,dc,ddl,ddr,vr,hd,vl,hu: 38% 11% 14%  5%  8% 10%  5%  7%  2%
[libx264 @ 0x239ea00] i8c dc,h,v,p: 100%  0%  0%  0%
[libx264 @ 0x239ea00] Weighted P-Frames: Y:0.0% UV:0.0%
[libx264 @ 0x239ea00] ref P L0: 99.1%  0.7%  0.3%
[libx264 @ 0x239ea00] ref B L0: 85.0% 15.0%
[libx264 @ 0x239ea00] ref B L1: 95.4%  4.6%
[libx264 @ 0x239ea00] kb/s:689.83

最佳答案

所以我设法修改this answer , 建议使用 nullsrc带有覆盖过滤器。 nullsrc导致透明 GIF 出现问题,所以我使用了 color反而:

ffmpeg -i animation.gif -filter_complex "color=c=white:s=340x240:d=0.300 [base]; [base][0:v] overlay" -c:v libx264 -b:v 2000k -y -pix_fmt yuv420p -f mp4 animation.mp4

由于覆盖过滤器的默认操作是在覆盖源在基本源之前用完时保留覆盖的最后一帧,这有效地欺骗 ffmpeg 使最后一帧的持续时间正确。然而,这样做的缺点是它需要事先知道 GIF 的尺寸和正确的持续时间(这可以通过图像魔术来完成)。

此外,原始命令我们使用缩放过滤器来确保 GIF 在每个边缘上具有偶数个像素(因为 yuv420p 需要这个)。新命令使用 color尺寸会自动处理这个问题,因此在设置尺寸时,您必须将 GIF 尺寸向下舍入到最接近的偶数。

关于ffmpeg 在动画 GIF 的最后一帧减少时间延迟,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25258592/

相关文章:

bash - bash中的while循环只执行一次

android - MediaMetadataRetriever getFrameAtTime 仅返回第一帧

java - FFmpeg 在转码后的 AAC 文件中添加 0.05 秒的静音?

ios - 如何从 Objective-C 调用 C 函数

ios - 如何在 FFmpeg 命令中指定图像

MacOS 10.7.4 上的 Java 系统托盘图标不显示动画 gif

java - 将 JTextField/JTextArea 堆叠在 ImageIcon 之上

php - 如何使用 PHP 提取动画 GIF 的帧

c++ - Gif在闪烁

ffmpeg - 如何 --enable-protocol=SRT 的 ffmpeg?