![删除 gif 的第 n 帧(每 n 帧删除一帧)](https://linux22.com/image/46133/%E5%88%A0%E9%99%A4%20gif%20%E7%9A%84%E7%AC%AC%20n%20%E5%B8%A7%EF%BC%88%E6%AF%8F%20n%20%E5%B8%A7%E5%88%A0%E9%99%A4%E4%B8%80%E5%B8%A7%EF%BC%89.png)
我.gif
用 ffmpeg 录制了屏幕。我已经用gifsicle
和imagemagick
对其进行了一些压缩,但它仍然很大。我的目的是通过每 2 帧删除一帧来使其变小,从而使帧总数减半。
我找不到一种方法来做到这一点,无论是 withgifsicle
还是 with imagemagick
。man
页面没有帮助。
如何从.gif
动画中每n
帧删除一帧?
答案1
可能有更好的方法来做到这一点,但这就是我要做的
首先,将动画分成几帧
convert animation.gif +adjoin temp_%02d.gif
然后,用一个小的 for 循环从 n 个帧中选择一个,循环遍历所有帧,检查它是否能被 2 整除,如果能,则将其复制到新的临时文件中。
j=0; for i in $(ls temp_*gif); do if [ $(( $j%2 )) -eq 0 ]; then cp $i sel_`printf %02d $j`.gif; fi; j=$(echo "$j+1" | bc); done
如果您希望保留所有不可整除的数字(因此如果您想删除而不是保留每个第 n 帧),请替换-eq
为-ne
。
完成后,从所选帧创建新动画
convert -delay 20 $( ls sel_*) new_animation.gif
您可以轻松制作一个小脚本convert.sh
,就像这样
#!/bin/bash
animtoconvert=$1
nframe=$2
fps=$3
# Split in frames
convert $animtoconvert +adjoin temp_%02d.gif
# select the frames for the new animation
j=0
for i in $(ls temp_*gif); do
if [ $(( $j%${nframe} )) -eq 0 ]; then
cp $i sel_`printf %02d $j`.gif;
fi;
j=$(echo "$j+1" | bc);
done
# Create the new animation & clean up everything
convert -delay $fps $( ls sel_*) new_animation.gif
rm temp_* sel_*
然后只需调用,例如
$ convert.sh youranimation.gif 2 20
答案2
有一个替代版本膜生物反应器的答案,作为 bash 函数:
gif_framecount_reducer () { # args: $gif_path $frames_reduction_factor
local orig_gif="${1?'Missing GIF filename parameter'}"
local reduction_factor=${2?'Missing reduction factor parameter'}
# Extracting the delays between each frames
local orig_delay=$(gifsicle -I "$orig_gif" | sed -ne 's/.*delay \([0-9.]\+\)s/\1/p' | uniq)
# Ensuring this delay is constant
[ $(echo "$orig_delay" | wc -l) -ne 1 ] \
&& echo "Input GIF doesn't have a fixed framerate" >&2 \
&& return 1
# Computing the current and new FPS
local new_fps=$(echo "(1/$orig_delay)/$reduction_factor" | bc)
# Exploding the animation into individual images in /var/tmp
local tmp_frames_prefix="/var/tmp/${orig_gif%.*}_"
convert "$orig_gif" -coalesce +adjoin "$tmp_frames_prefix%05d.gif"
local frames_count=$(ls "$tmp_frames_prefix"*.gif | wc -l)
# Creating a symlink for one frame every $reduction_factor
local sel_frames_prefix="/var/tmp/sel_${orig_gif%.*}_"
for i in $(seq 0 $reduction_factor $((frames_count-1))); do
local suffix=$(printf "%05d.gif" $i)
ln -s "$tmp_frames_prefix$suffix" "$sel_frames_prefix$suffix"
done
# Assembling the new animated GIF from the selected frames
convert -delay $new_fps "$sel_frames_prefix"*.gif "${orig_gif%.*}_reduced_x${reduction_factor}.gif"
# Cleaning up
rm "$tmp_frames_prefix"*.gif "$sel_frames_prefix"*.gif
}
用法:
gif_framecount_reducer file.gif 2 # reduce its frames count by 2