Skip to content

Replace gifsicle GIF pipeline with gifski#1282

Open
artisticmedic wants to merge 1 commit into
wulkano:mainfrom
artisticmedic:gifski-gif-export
Open

Replace gifsicle GIF pipeline with gifski#1282
artisticmedic wants to merge 1 commit into
wulkano:mainfrom
artisticmedic:gifski-gif-export

Conversation

@artisticmedic

Copy link
Copy Markdown

Summary

Kap's GIF export ran ffmpeg palettegen → paletteuse → gifsicle. On Apple Silicon the bundled gifsicle is x86_64-only, so it runs under Rosetta and triggers the macOS Intel deprecation warning — and it's the slowest part of the export.

This PR replaces that pipeline with gifski, a multithreaded GIF encoder that ships a universal (x86_64 + arm64) binary.

How it works

gifski's binary statically links FFmpeg, so it reads the recording directly. convertToGif now runs ffmpeg only to trim the selected range (gifski can't trim), then hands the clip to gifski for fps resampling, scaling, and encoding. No intermediate frames — which also removes the per-frame argument list that overflowed ARG_MAX on long recordings.

Benchmarks

Native arm64: ~1.2–1.5× faster and ~15% smaller output than the old pipeline, plus no Rosetta.

Notes for reviewers

  • The npm gifski package is frozen at 1.7.1 (unmaintained since 2022). scripts/download-gifski.js fetches the official universal 1.34.0 release on postinstall, verified against a pinned SHA-256, into vendor/gifski (gitignored, packaged via asarUnpack). macOS-only, uses curl + tar that ship with macOS.
  • GIF frame delays use 1/100s units, so fps is capped at 50.
  • The existing "Lossy GIF compression" setting now maps to gifski --quality.
  • gifski merges duplicate frames, so the GIF tests now assert playback duration rather than a constant nominal frame rate.
  • gifsicle dependency removed (large drop in yarn.lock).

🤖 Generated with Claude Code

Kap's GIF export ran ffmpeg palettegen -> paletteuse -> gifsicle. On Apple
Silicon the bundled gifsicle is x86_64-only, so it runs under Rosetta and
triggers the macOS Intel deprecation warning; it is also the slowest export
path.

Replace it with gifski, a multithreaded GIF encoder that ships a universal
(x86_64 + arm64) binary. gifski's binary statically links FFmpeg, so it reads
the recording directly: convertToGif now runs ffmpeg only to trim the selected
range (gifski can't trim), then hands the clip to gifski for fps resampling,
scaling, and encoding -- no intermediate frames, which also removes a per-frame
argument list that overflowed ARG_MAX on long recordings.

Benchmarks (native arm64): ~1.2-1.5x faster and ~15% smaller than the old
pipeline, plus no Rosetta.

- The npm gifski package is frozen at 1.7.1; scripts/download-gifski.js fetches
  the official universal 1.34.0 release on postinstall, verified against a
  pinned SHA-256, into vendor/gifski (gitignored, packaged via asarUnpack).
- GIF frame delays use 1/100s units, so fps is capped at 50.
- The "Lossy GIF compression" setting now maps to gifski --quality.
- gifski merges duplicate frames, so the GIF tests assert playback duration
  rather than a constant nominal frame rate.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant