首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在linux服务器上将动画gif转换成视频,同时保持帧速率

在linux服务器上将动画gif转换成视频,同时保持帧速率
EN

Stack Overflow用户
提问于 2015-04-10 12:07:57
回答 1查看 7.2K关注 0票数 5

如何在linux服务器上以编程方式将动画gif转换为视频(例如H 264@MP4)?

我需要这样来处理用户生成的内容,这些内容应该作为几种定义的视频格式输出;因此,用户可能希望处理动画的gif文件。我已经有了一组使用avconv将视频文件转换为特定格式(如vpx@webm和H 264@MP4,缩放到特定分辨率)的php脚本,但因此我需要视频输入。

通常的方法似乎是提取gif的帧,然后对其进行编码,如下

代码语言:javascript
复制
convert file.gif file%03d.png 
avconv -i file%03d.png file.mp4

但是这会丢弃帧速率,这是由gif文件中的暂停信息决定的。可以用-r定义一个框架对象,但是

  • 这不尊重帧间的暂停,因为它们可能不同(例如第1帧100 as暂停,第2帧250 as暂停,第3帧100 as暂停,.)
  • 由于输入来自用户,它甚至可能有所不同,因为一些gifs可能有5fps,而另一些则有30 5fps。

我注意到avconv能够自己处理gifs,因此可能会尊重正确的暂停,但当我这样做时(就像How to convert GIF to Mp4 is it possible?中所描述的那样)。

代码语言:javascript
复制
avconv -i file.gif -r 30 file.mp4

avconv只接收gif的第一帧,同时它至少检测到该文件为视频:

代码语言:javascript
复制
Duration: 00:00:00.04, start: 0.000000, bitrate: N/A
  Stream #0.0: Video: gif, pal8, 640x480, 25 tbn

(例如gif 'file.gif‘有15帧,每帧都有100 has的暂停=> 1.5s持续时间,循环)

  • 我遗漏了什么?出什么事了?
  • 这个用例可能有更好的工具吗?
  • 像9 9gag这样的大型网站是用来将上传的gifs转换到视频中的吗?
EN

回答 1

Stack Overflow用户

发布于 2015-06-12 01:03:20

如果由于某种原因,您需要使用avconv和imagemagick,您可能需要尝试这样的方法:

代码语言:javascript
复制
ticks_per_frame = subprocess.check_output('identify -verbose -format %T_ {0}'.format(gif_path).split()).split('_')[:-1]
ticks_per_frame = [int(i) for i in ticks_per_frame]
num_frames = len(ticks_per_frame)
min_ticks = min(ticks_per_frame)

subprocess.call('convert -coalesce {0} tmp%d.png'.format(gif_path).split())

if len(set(ticks_per_frame)) > 1:
    num_dup = 0
    num_dup_total = 0
    for frame, ticks in enumerate(ticks_per_frame):
        num_dup_total += num_dup
        frame += num_dup_total
        num_dup = 0
        if ticks > min_ticks:
            num_dup = (ticks / min_ticks) - 1
            for i in range(num_frames + num_dup_total - 1, frame, -1):
                orig = 'tmp%d.png' % i
                new = 'tmp%d.png' % (i + num_dup)
                subprocess.call(['mv', orig, new])
            for i in range(1, num_dup + 1):
                curr = 'tmp%d.png' % frame
                dup = 'tmp%d.png' % (i + frame)
                subprocess.call(['cp', curr, dup])

framerate = (100 / min_ticks) if min_ticks else 10

subprocess.call('avconv -r {0} -i tmp%d.png -c:v libx264 -crf {1} -pix_fmt yuv420p \
-vf scale=trunc(iw/2)*2:trunc(ih/2)*2 -y {2}.mp4'.format(framerate, quality, STORAGE_DIR + mp4_name).split())

subprocess.call(['rm'] + glob('tmp*.png'))

因此,为gif的每一帧(通过标识)获取以厘米为单位的刻度,转换为多个pngs,然后在根据滴答值进行复制时遍历它们。别担心,png文件仍将保持连续的顺序。使用真正的FFmpeg仍然是最好的方法。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/29561033

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档