簡體   English   中英

在保留幀頻的同時將gif動畫轉換為linux服務器上的視頻

[英]convert animated gif to video on linux server while preserving frame rate

如何在Linux服務器上以編程方式將動畫gif轉換為視頻(例如h264 @ mp4)?

我需要它來處理用戶生成的內容,這些內容應該以幾種定義的視頻格式輸出; 因此,用戶可能需要處理動畫gif文件。 我已經有一組可用的php腳本,可以使用avconv將視頻文件轉碼為特定格式(例如vpx @ webm和h264 @ mp4,縮放至特定分辨率),但是在此之前,我需要視頻輸入。

通常的方法似乎是提取gif的幀,然后對其進行編碼,例如

convert file.gif file%03d.png 
avconv -i file%03d.png file.mp4

但這會丟棄由gif文件中的暫停信息確定的幀速率。 可以使用-r為avconv定義幀速率,但是

  • 這不考慮幀之間的暫停,因為它們之間可能有所不同(例如,第一幀暫停100毫秒,第二幀暫停250毫秒,第三幀暫停100毫秒,...)
  • 由於輸入來自用戶,它甚至可能有所不同,因為某些gif可能具有5fps,而其他gif可能具有30fps

我注意到avconv能夠自行處理gif,因此可以尊重正確的暫停,但是當我這樣做時(就像在如何將GIF轉換為Mp4中類似描述的那樣,有可能嗎?

avconv -i file.gif -r 30 file.mp4

avconv只會將gif的第一幀作為鏡頭,而它至少會將文件檢測為視頻:

Duration: 00:00:00.04, start: 0.000000, bitrate: N/A
  Stream #0.0: Video: gif, pal8, 640x480, 25 tbn

(示例gif'file.gif'具有15幀,每幀具有100ms暫停=> 1.5s持續時間,循環播放)

  • 我想念什么? 怎么了
  • 對於這種用例,可能有更好的工具嗎?
  • 什么是大型網站(例如9gag)用於將上傳的gif轉換為視頻?

另一個Avconv錯誤(YAAB)

ffmpeg具有更好的GIF解復用支持(和改進的GIF編碼 )。 我建議拋棄avconv並獲取ffmpeg (來自FFmpeg的真實版本;而不是來自Libav的舊騙子)。 靜態構建很容易,或者您當然可以進行編譯

ffmpeg -i in.gif -c:v libx264 -pix_fmt yuv420p -movflags +faststart out.mp4

有關更多示例,請參見FFmpeg Wiki:H.264編碼指南

如果由於某些原因需要使用avconv和imagemagick,則可能需要嘗試如下操作:

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每一幀的滴答聲(通過標識),以厘秒為單位,轉換為多個png,然后在基於滴答值進行重復的同時遍歷它們。 不用擔心,png文件仍將保持連續的順序。 使用真正的FFmpeg仍然是最好的方法。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM