如何从动画 gif 中删除每一秒帧?

平面设计 动画 批量处理 gif 自动化
2022-01-17 07:08:36

我有一个文件夹,里面装满了我想转换为动画 gif 的视频。ffmpeg/avconv 在直接做这件事上做得很糟糕,所以我把视频转换为 gif,首先将每个帧输出为 png,然后使用 imagemagick 转换回 gif。问题是这会导致文件大小较大的 gif。为了解决这个问题,我想从 gif 中“删除”每一秒或第 n 帧,方法是在转换为 gif 时跳过每个图像文件或从 gif 中删除帧。如何使用 imagemagick 或其他命令行实用程序在 Ubuntu (13.04) 上执行此操作?

4个回答

这是使用gifsicle比 JohnB 的脚本更简单的解决方案:

gifsicle -U input.gif `seq -f "#%g" 0 2 99` -O2 -o output.gif

这个命令应该在大多数 Unix shell 中工作;我已经在 bash 中对其进行了测试。input.gif和替换output.gif为输入和输出文件名,以及99动画中的帧数。(可以使用更大的数字,但 gifsicle 会抱怨它。)

一些注意事项:

  • -U开关会将输入动画中的帧与前面的帧合并,这样每一帧都是独立的,不依赖于任何其他帧。你真的想在对动画做任何事情之前这样做,否则你可能会得到混乱的结果。(如果您的输入动画已经未优化,gifsicle 可能会打印一个警告,但这也是完全无害的。)

  • 相反,-O2开关重新优化输出动画以最小化文件大小。使用 JohnB 的示例动画,它将输出大小缩小了 27%。

  • seq命令仅输出从 0 到 99 的数字序列,以 2 为步长计数。这-f "#%g"使得它在每个数字之前打印一个#,这使得 gifsicle 将其理解为帧选择而不是文件名。seq 命令周围的反引号 ( `) 导致其输出作为参数包含在 gifsicle 命令行中。

如果您不希望 gif 加速,可以使用gifsicle -I input.gif获取当前帧延迟,将其乘以 2 并使用gifsicle -d ${delay} ....

使用 bash 脚本

要从命令行执行此操作,您可以使用名为Gifsicle的实用程序。没有内置的方法可以删除每隔一帧,因此您需要使用一些脚本来弄脏您的手。

这是我为只制作一个 GIF 而制作的快速脚本:

#!/bin/bash
# This script will take an animated GIF and delete every other frame
# Accepts two parameters: input file and output file
# Usage: ./<scriptfilename> input.gif output.gif

# Make a copy of the file
cp $1 $2

# Get the number of frames
numframes=`gifsicle $1 -I | grep -P "\d+ images" --only-matching | grep -P "\d+" --only-matching`

# Deletion
let i=0
while [[ $i -lt $numframes  ]]; do
    rem=$(( $i % 2 ))
     
    if [ $rem -eq 0 ]
    then
        gifsicle $2 --delete "#"$(($i/2)) -o $2 
    fi

    let i=i+1 
done

我用一个简单的倒计时 GIF 对其进行了测试:

在此处输入图像描述

这是通过脚本运行后的结果:

在此处输入图像描述

这个脚本当然不是万无一失的,但它应该引导你朝着正确的方向前进。

注意此答案是在有命令行/开源要求之前发布的,但我将其保留,因为它可能会在未来对其他人有所帮助


使用 Photoshop

这不是开源或命令行解决方案,但您可以使用 Photoshop 执行此操作:

文件导入视频帧到图层...

导入视频

限制到每 __ 帧”将为您解决问题

我认为我需要新的更复杂的解释(帧延迟也是应该考虑的重要因素)......对于这个新过程,您需要从这个链接下载 JREPL.BAT:http: //www.dostips.com /forum/viewtopic.php?t=6044

首先将捕获的 gif 复制到 input.gif 文件中,然后启动命令解释器并键入:

gifsicle input.gif -I "#-1" >input.txt

查看 input.txt 并查看动画的长度 - 它包含多少帧......还查看帧的延迟,如果它的 0.07s 意味着您应该将选项 -d14 (7msec*2) 放入这一行在 process.cmd : gifsicle -b -U -d14 input.gif ,编辑后保存 process.cmd

然后编辑 test.bat 并从此行更改变量 166 的值以匹配动画帧数:对于 /L %%i IN (1,2,166) DO echo "#%%i">> input.bat ,之后编辑保存 test.bat...

然后启动 process.cmd 并将每个奇数帧的裁剪动画处理成文件 input.gif

PS这种方法的优点还在于您可以完全控制要从gif中删除的内容(每隔一帧(1,2,166)或每隔三帧(1,3,166)),依此类推,只需更改中间的数字即可批处理行,但请注意,如果指定 (1,3,166),则应相应更改 process.cmd 中的 -d14 (延迟选项)以反映更改 (7msec*3/2 = 10),而不是 (7msec*2 /1 = 14),延迟选项应该是 -d10...

其他文件(例如每隔一帧删除一次): test.bat :

@echo off
echo gifsicle -b input.gif --delete>> input.bat
for /L %%i IN (1,2,166) DO echo  "#%%i">> input.bat
echo  --done>> input.bat
call jrepl.bat "\n" "" /x /m /f input.bat /o -

进程.cmd:

gifsicle -b -U -d14 input.gif
call "test.bat"
call "input.bat"
gifsicle -b -O3 input.gif
erase "input.bat"

和助手自述文件 input.txt :

* input.gif 166 images
  logical screen 1366x768
  global color table [256]
  background 15
  loop forever
  + image #165 1x1 at 1365,767 transparent 15
    disposal asis delay 0.07s