アニメーションGIFから1つおきのフレームを削除する方法は?


22

アニメーションgifに変換したいビデオがいっぱいのフォルダーがあります。ffmpeg / avconvはそれを直接行うのが悪いので、代わりに各フレームをpngとして出力してからimagemagickを使用してgifに戻すことにより、ビデオをgifに変換します。問題は、これによりファイルサイズの点で大きなgifが生成されることです。これを解決するには、gifに変換するときにすべての画像ファイルをスキップするか、gifからフレームを削除することにより、gifから2番目またはn番目のフレームごとに「ドロップ」します。imagemagickまたは他のコマンドラインユーティリティを使用してUbuntu(13.04)でこれを行うにはどうすればよいですか?

回答:


14

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でテストしました。

ここに画像の説明を入力してください

スクリプトを実行した後の結果は次のとおりです。

ここに画像の説明を入力してください

もちろん、このスクリプトは防弾ではありませんが、正しい方向に導くはずです。


削除ループを単純化できることに注意してくださいlet i=0; while [[ $i -lt $(($numframes / 2)) ]]; do gifsicle $2 --delete "#$i" -o $2; let i=i+1; done
Ilmari Karonen

1
実際、ループはまったく必要ありませんgifsicle "$1" --unoptimize $(seq -f "#%g" 0 2 $numframes) -O2 -o "$2"。1回の呼び出しでループを実行します。
イルマリカロネン

実際、コマンドラインからこのスクリプトを実行する方法がわかりません。私はそれをgifdrop.shファイルとして保存し、in.gifと呼ばれるgifで使用法(./gifdrop.sh in.gif out.gif)の指示に従って実行しようとしましたが、不明なコマンドgifdrop
mheavers

@mheaversはファイルを実行可能にしましたか?chmod +x gifdrop.sh
JohnB

1
macOS上でより良く動作します:github.com/colindean/hejmo/blob/master/scripts/…-grepの代わりにperlを使用するバージョンで、デフォルトでGNU grepがインストールされていないmacOSで動作します。また、ファイル名のスペースを処理します。
コリンディーン

27

次に、JohnBのスクリプトよりもgifsicle を使用した簡単なソリューションを示します。

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

このコマンドは、ほとんどのUnixシェルで機能するはずです。私はそれをbashでテストしました。交換するinput.gifoutput.gif、入力と出力ファイル名を持つ、と99アニメーションのフレーム数を持ちます。(もっと大きな数字を使用しても構いませんが、gifsicleはそれについて文句を言います。)

いくつかのメモ:

  • -Uスイッチは、各フレームは単独で表し、他のものに依存しないように、前のものと入力アニメーションのフレームをマージします。アニメーションでほとんど何もする前にこれを本当にやりたいです。そうしないと、散らかった結果になる可能性があります。(入力アニメーションが既に最適化されていない場合、gifsicleはそれに関する警告を出力することがありますが、これも完全に無害です。)

  • 逆に、-O2スイッチは出力アニメーションを再最適化して、ファイルサイズを最小化します。JohnBのサンプルアニメーションを使用すると、出力サイズが27%縮小されます。

  • seqコマンドは、ちょうど2のステップでカウントアップ、0から99までの数字の列を出力する-f "#%g"ことが印刷可能#gifsicleは、ファイル名の代わりにフレーム選択としてそれを理解する各番号の前に。`seqコマンドの前後のバックティック()により、その出力がgifsicleコマンドラインのパラメーターとして含まれます。

gifの速度を上げたくない場合は、を使用gifsicle -I input.gifして現在のフレーム遅延を取得し、2倍してを使用できますgifsicle -d ${delay} ...


うまくできました!本当に必要な場合は、スクリプトからgrepを使用して、フレーム数を正確に指定することができます(そして、コマンドの巨大なものを1つ作成できます)。それとも、アニメーションGIFのフレーム数を返す簡単な方法があるのでしょうか?
JohnB

3
私は@JohnB、コマンドの巨獣を作ってしまった-gifsicle input.gif `seq -f "#%g" 0 2 $(identify input.gif | tail -1 | cut -d "[" -f2 - | cut -d "]" -f1 -)` --unoptimize -O2 -o output.gif
Kasra Rahjerdi

バージョン1.71のWindows 7 x64では、次のようになりましたuseless unoptimization-related input option。だから私は2つのステップでそれをしました(Git Bash内から):1. gifsicle -U -o unoptimized.gif input.gif2.gifsicle unoptimized.gif `seq -f "#%g" 0 2 99` -O2 -o output.gif
feklee 14

11

この回答は、コマンドライン/オープンソースの要件が存在する前に投稿されましたが、将来的に他の誰かを助けるかもしれないので、私はそれを残しています


Photoshopを使用する

これはオープンソースまたはコマンドラインのソリューションではありませんが、Photoshopでこれを行うことができます。

ファイルインポートビデオフレームをレイヤーに...

ビデオをインポートする

__フレームごとに制限」がトリックを行います


0

これがバッチスクリプト処理を使用した私のソリューションです...

最初に、キャプチャされた元のアニメーションgifをinput.gifファイルにコピーしてから、コマンドインタープリターを起動して入力します。

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

input.txtを調べて、アニメーションの長さ-含まれているフレームの数を確認してください...

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

次に、test.batを編集して作成し、変数len = specify_length_number_from_input.txtの値を変更してtest.batを保存します...

test.bat:

@echo off
set /A len=166
set /A i=1
set /A ii=0
:loop
if %i%==%len% goto :eof
if %ii%==0 (set /A ii=1) else (set /A ii=0)
set /A iii=%ii%*%i%
if %i%==%iii% echo gifsicle -b input.gif --delete "#1" --done
set /A i=%i%+1
goto :loop

最後にprocess1.batとprocess2.batを開始し、奇数フレームごとにトリミングされたアニメーションがファイルinput.gifに処理されます

process1.bat:

gifsicle -b -U input.gif
test.bat > input.bat

process2.bat:

call "input.bat"
gifsicle -b -O2 input.gif
erase "input.bat"

0

新しい洗練された説明が必要だと思います(フレーム遅延も考慮すべき重要なことです)...この新しいプロセスでは、このリンクからJREPL.BATをダウンロードする必要があります:http : //www.dostips.com /forum/viewtopic.php?t=6044

まず、キャプチャしたgifをinput.gifファイルにコピーしてから、コマンドインタープリターを起動して次のように入力します。

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

input.txtを調べて、アニメーションの長さを確認します-含まれているフレームの数...フレームの遅延も調べます。0.07秒であれば、この行にオプション-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から何を削除するかを完全に制御できることです(2番目のフレーム(1,2,166)、3番目ごと(1,3,166)など)。バッチライン、ただし(1,3,166)を指定する場合は、それに応じてprocess.cmdから-d14(遅延オプション)を変更して、変更を反映する(7msec * 3/2 = 10)必要があるため、(7msec * 2 / 1 = 14)、遅延のオプションは-d10 ...

他のファイル(たとえば、1秒おきのフレームを削除する場合):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 -

process.cmd:

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

ヘルパーのreadmeファイル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
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.