@@ -58,8 +58,11 @@ FFMPEG\_USE\_GIFSICLE\_ENGINE
5858~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5959
6060Equivalent to USE\_ GIFSICLE\_ ENGINE, but for the FFmpeg engine. It defaults to
61- ``False ``. If ``True ``, it will perform any image operations on animated gifs
62- (e.g. cropping and resizing) using gifsicle (by way of ``GIF_ENGINE ``).
61+ ``False ``. If ``True ``, gifsicle runs as a final ``-O3 `` optimization pass
62+ (plus ``GIFSICLE_ARGS ``) over the gif produced by ffmpeg, reducing file size.
63+ All geometry (cropping, resizing) is applied by ffmpeg at the target size, so
64+ the gifsicle pass performs no resizing of its own and runs file-to-file on
65+ disk — the full animation is never buffered in the Python heap.
6366
6467FFMPEG\_ HANDLE\_ ANIMATED\_ GIF
6568~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -88,6 +91,80 @@ Specifies whether H265 format should be used automatically if the
8891source image is an animated gif and the request accepts it (via
8992``Accept: video/* ``). It defaults to ``False ``.
9093
94+ FFMPEG\_ GIF\_ PIPELINE
95+ ~~~~~~~~~~~~~~~~~~~~~
96+
97+ Selects the gif-to-gif transcode pipeline. It defaults to ``'legacy' ``.
98+
99+ ``'legacy' ``
100+ The ``palettegen ``/``paletteuse `` pipeline. ffmpeg applies all geometry
101+ (crop, resize) at the **target ** size, writes intermediates to disk, and
102+ — when ``FFMPEG_USE_GIFSICLE_ENGINE `` is enabled — runs a final
103+ geometry-free ``gifsicle -O3 `` optimization pass. Only the final output
104+ bytes ever enter the Python heap, so memory stays bounded regardless of
105+ the source animation's resolution or frame count.
106+
107+ ``'gifski' ``
108+ Streams frames from ffmpeg directly into the `gifski `__ encoder at the
109+ target size, producing noticeably higher-quality gifs much faster. Inputs
110+ that gifski cannot represent are routed back to the ``legacy `` path
111+ automatically:
112+
113+ - **variable per-frame delays ** (gifski emits a constant frame rate),
114+ - **target sizes above ** ``GIFSKI_MAX_TARGET_PIXELS ``,
115+ - and any request when the ``gifski `` binary is not available.
116+
117+ Visibly-transparent gifs are decoded to PNG frames first (gifski
118+ preserves alpha from PNG input); opaque gifs and video sources stream
119+ through a ``yuv4mpegpipe ``.
120+
121+ .. note ::
122+ gifski is licensed under the `AGPL-3.0 `__. thumbor-video-engine
123+ invokes it as an unmodified subprocess (aggregation, not linking) and
124+ never declares it as a dependency. You must install the ``gifski ``
125+ binary yourself to use this pipeline, and your deployment is
126+ responsible for AGPL compliance.
127+
128+ .. __ : https://gif.ski/
129+ .. __ : https://www.gnu.org/licenses/agpl-3.0.html
130+
131+ GIFSKI\_ PATH
132+ ~~~~~~~~~~~~
133+
134+ Path to the gifski binary. It defaults to ``None ``, in which case gifski is
135+ looked up on ``PATH ``. Only used when ``FFMPEG_GIF_PIPELINE `` is ``'gifski' ``.
136+
137+ GIFSKI\_ QUALITY
138+ ~~~~~~~~~~~~~~~
139+
140+ Quality (1–100) passed to gifski (``--quality ``). Defaults to ``90 ``.
141+
142+ GIFSKI\_ MAX\_ TARGET\_ PIXELS
143+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
144+
145+ Above this output size (target ``width * height ``), the gifski pipeline routes
146+ through the legacy path instead. gifski's quantizer working set grows with
147+ output dimensions, while the legacy path's memory stays bounded — this trades
148+ a bit of wall time for bounded subprocess memory on large outputs. Defaults to
149+ ``1440000 `` (1600×900). A value of ``0 `` disables the switch.
150+
151+ GIFSKI\_ GIFSICLE\_ PASS
152+ ~~~~~~~~~~~~~~~~~~~~~~
153+
154+ If ``True ``, run a final geometry-free ``gifsicle -O3 `` pass (plus
155+ ``GIFSICLE_ARGS ``, e.g. ``--lossy ``) over gifski's output to further reduce
156+ file size. Defaults to ``False ``.
157+
158+ MAX\_ ANIMATION\_ PIXELS
159+ ~~~~~~~~~~~~~~~~~~~~~~
160+
161+ Maximum total pixels (``width * height * frame_count ``) allowed for an animated
162+ gif. Animations over this limit fail with a ``400 `` response. thumbor's
163+ ``MAX_PIXELS `` is per-frame and does not bound frame count, so a high-frame-count
164+ gif can still consume large amounts of memory; this gate, evaluated cheaply at
165+ load time from a single-pass header parse (no frame decoding), bounds the total.
166+ Defaults to ``0 ``, which disables the check.
167+
91168FFPROBE\_ PATH
92169~~~~~~~~~~~~~
93170
0 commit comments