docs(demo): cut the window out of the gif with real transparency
vhs cannot emit a transparent margin, so make demo now masks everything outside the rounded window rect via imagemagick before gifsicle. Also force --no-conserve-memory: the huge-GIF fallback roughly doubles the optimized size.
- commit
- a87ac1a82071261946a05ccfa8bc962b5d32548e
- author
- brice · · 2026-07-24 17:32 UTC
- parent
- 2ec25e2
- signature
- GPG Verified
CD88F9E564E0102646FB6077A1A07C7C7C3E349D· arch-gpg Verified for the committer email
3 files · +16 -3
M Makefile +15 -2
| @@ -28,8 +28,21 @@ mocks: | |||
| 28 | 28 | demo: | |
| 29 | 29 | docker build -f scripts/demo/Dockerfile -t vev-demo . | |
| 30 | 30 | ./scripts/demo/run.sh demo.tape | |
| 31 | + | # vhs cannot emit a transparent margin, so cut the window out after the | |
| 32 | + | # fact: everything outside the rounded window rect becomes GIF | |
| 33 | + | # transparency. The geometry mirrors demo.tape (1200x750 canvas, margin | |
| 34 | + | # 20, border radius 10); keep them in sync. | |
| 35 | + | docker run --rm --entrypoint magick -v "$(CURDIR)/scripts/demo/out:/out" vev-demo \ | |
| 36 | + | -size 1200x750 xc:black -fill white \ | |
| 37 | + | -draw "roundrectangle 20,20 1179,729 10,10" /out/mask.png | |
| 38 | + | docker run --rm --entrypoint magick -v "$(CURDIR)/scripts/demo/out:/out" vev-demo \ | |
| 39 | + | -limit memory 8GiB -limit map 12GiB /out/demo.gif -coalesce \ | |
| 40 | + | null: \( /out/mask.png -alpha off \) -compose CopyOpacity \ | |
| 41 | + | -layers composite /out/demo-masked.gif | |
| 31 | 42 | # --lossy above 30 smears the near-identical darks of the window chrome | |
| 32 | - | # (margin fill, window bar, terminal background) into visible banding. | |
| 33 | - | docker run --rm --entrypoint gifsicle -v "$(CURDIR)/scripts/demo/out:/out" vev-demo -O3 --lossy=30 -o /out/demo.gif /out/demo.gif | |
| 43 | + | # (window bar vs terminal background) into visible banding, and the | |
| 44 | + | # conserve-memory fallback for huge inputs roughly doubles the output. | |
| 45 | + | docker run --rm --entrypoint gifsicle -v "$(CURDIR)/scripts/demo/out:/out" vev-demo --no-conserve-memory -O3 --lossy=30 -o /out/demo.gif /out/demo-masked.gif | |
| 46 | + | rm scripts/demo/out/demo-masked.gif scripts/demo/out/mask.png | |
| 34 | 47 | mkdir -p docs/assets | |
| 35 | 48 | cp scripts/demo/out/demo.gif docs/assets/demo.gif | |
| @@ -28,8 +28,21 @@ mocks: | |||||
| 28 | demo: | 28 | demo: | ||
| 29 | docker build -f scripts/demo/Dockerfile -t vev-demo . | 29 | docker build -f scripts/demo/Dockerfile -t vev-demo . | ||
| 30 | ./scripts/demo/run.sh demo.tape | 30 | ./scripts/demo/run.sh demo.tape | ||
| 31 | + | # vhs cannot emit a transparent margin, so cut the window out after the | |||
| 32 | + | # fact: everything outside the rounded window rect becomes GIF | |||
| 33 | + | # transparency. The geometry mirrors demo.tape (1200x750 canvas, margin | |||
| 34 | + | # 20, border radius 10); keep them in sync. | |||
| 35 | + | docker run --rm --entrypoint magick -v "$(CURDIR)/scripts/demo/out:/out" vev-demo \ | |||
| 36 | + | -size 1200x750 xc:black -fill white \ | |||
| 37 | + | -draw "roundrectangle 20,20 1179,729 10,10" /out/mask.png | |||
| 38 | + | docker run --rm --entrypoint magick -v "$(CURDIR)/scripts/demo/out:/out" vev-demo \ | |||
| 39 | + | -limit memory 8GiB -limit map 12GiB /out/demo.gif -coalesce \ | |||
| 40 | + | null: \( /out/mask.png -alpha off \) -compose CopyOpacity \ | |||
| 41 | + | -layers composite /out/demo-masked.gif | |||
| 31 | # --lossy above 30 smears the near-identical darks of the window chrome | 42 | # --lossy above 30 smears the near-identical darks of the window chrome | ||
| 32 | - | # (margin fill, window bar, terminal background) into visible banding. | 43 | + | # (window bar vs terminal background) into visible banding, and the |
| 33 | - | docker run --rm --entrypoint gifsicle -v "$(CURDIR)/scripts/demo/out:/out" vev-demo -O3 --lossy=30 -o /out/demo.gif /out/demo.gif | 44 | + | # conserve-memory fallback for huge inputs roughly doubles the output. |
| 45 | + | docker run --rm --entrypoint gifsicle -v "$(CURDIR)/scripts/demo/out:/out" vev-demo --no-conserve-memory -O3 --lossy=30 -o /out/demo.gif /out/demo-masked.gif | |||
| 46 | + | rm scripts/demo/out/demo-masked.gif scripts/demo/out/mask.png | |||
| 34 | mkdir -p docs/assets | 47 | mkdir -p docs/assets | ||
| 35 | cp scripts/demo/out/demo.gif docs/assets/demo.gif | 48 | cp scripts/demo/out/demo.gif docs/assets/demo.gif | ||
M docs/assets/demo.gif +0 -0 binary file: no text diff
binary file: no text diff
M scripts/demo/Dockerfile +1 -1
| @@ -14,7 +14,7 @@ RUN pacman -Sy --noconfirm archlinux-keyring \ | |||
| 14 | 14 | && sed -i '/^NoExtract.*usr\/share\/man/d' /etc/pacman.conf \ | |
| 15 | 15 | && pacman -Syu --noconfirm \ | |
| 16 | 16 | vhs ttyd ffmpeg chromium \ | |
| 17 | - | btop fastfetch gifsicle \ | |
| 17 | + | btop fastfetch gifsicle imagemagick \ | |
| 18 | 18 | eza neovim man-db man-pages coreutils \ | |
| 19 | 19 | nodejs npm ncurses \ | |
| 20 | 20 | ttf-jetbrains-mono-nerd \ | |
| @@ -14,7 +14,7 @@ RUN pacman -Sy --noconfirm archlinux-keyring \ | |||||
| 14 | && sed -i '/^NoExtract.*usr\/share\/man/d' /etc/pacman.conf \ | 14 | && sed -i '/^NoExtract.*usr\/share\/man/d' /etc/pacman.conf \ | ||
| 15 | && pacman -Syu --noconfirm \ | 15 | && pacman -Syu --noconfirm \ | ||
| 16 | vhs ttyd ffmpeg chromium \ | 16 | vhs ttyd ffmpeg chromium \ | ||
| 17 | - | btop fastfetch gifsicle \ | 17 | + | btop fastfetch gifsicle imagemagick \ |
| 18 | eza neovim man-db man-pages coreutils \ | 18 | eza neovim man-db man-pages coreutils \ | ||
| 19 | nodejs npm ncurses \ | 19 | nodejs npm ncurses \ | ||
| 20 | ttf-jetbrains-mono-nerd \ | 20 | ttf-jetbrains-mono-nerd \ | ||