Aller au contenu

VHS : générer des GIFs de terminal (CLI)

Mise à jour :

logo vhs

VHS est un outil en ligne de commande créé par Charmbracelet qui permet de générer des GIFs et vidéos de sessions terminal à partir d’un fichier déclaratif. Plutôt que de filmer votre écran, vous décrivez le scénario : commandes tapées, sorties attendues, pauses, style visuel. L’outil rejoue ensuite ce script pour produire un rendu propre, reproductible et versionnable.

Prérequis & installation

Cette section commence par l’installation des prérequis système, puis explique plusieurs méthodes d’installation de VHS. L’objectif est que même un débutant en ligne de commande puisse exécuter une première tape en quelques minutes.

Étape 1 : Installer les prérequis

Avant d’installer vhs, assurez-vous que les composants indispensables sont disponibles :

  • ffmpeg : encode les images successives en GIF / MP4 / WebM
  • ttyd : fournit un terminal pseudo‑graphique contrôlé par VHS (souvent installé automatiquement par les paquets)
  • Un shell : bash / zsh / fish (bash par défaut sur la plupart des distributions)

Installation de ffmpeg

Commandes d’installation selon l’OS :

Terminal window
# Debian / Ubuntu
sudo apt update && sudo apt install -y ffmpeg curl git
# Fedora / Rocky / Alma / RHEL
sudo dnf install -y ffmpeg curl git
# Arch Linux
sudo pacman -Syu --needed ffmpeg git curl
# macOS (si Homebrew pas encore installé) - facultatif
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
brew install ffmpeg
# Windows (PowerShell) - installation ffmpeg via winget
winget install Gyan.FFmpeg

Vérifiez ensuite :

Terminal window
# Version (utile pour diagnostiquer un build manquant de codecs)
ffmpeg -version

Si ffmpeg est absent, l’encodage échouera (GIF/vidéo non produits).

Installation de ttyd

ttyd est optionnel mais recommandé pour des rendus plus réalistes (curseur, sélection, etc.). Il est recommandé d’installer une version récente (>= 1.7.2). Le plus simple étant d’installer le dernier binaire précompilé depuis la page des releases GitHub.

Terminal window
# Exemple pour Linux x86_64
curl -L https://github.com/tsl0922/ttyd/releases/latest/download/ttyd-linux-x86_64.tar.gz -o ttyd
sudo install ttyd /usr/local/bin/
ttyd --version
ttyd version 1.7.7-40e79c7

Étape 2 : Installer VHS

Choisissez UNE méthode (la plus simple pour vous). Les résultats sont équivalents.

Méthode A – Homebrew (macOS & Linux)

Terminal window
brew install vhs
vhs --version

Méthode B – Gestionnaire de paquets distribution

Arch Linux :

Terminal window
sudo pacman -Syu vhs

Méthode C – Windows (winget / Scoop)

Terminal window
# Winget
winget install charmbracelet.vhs
# Ou Scoop
scoop install vhs

Méthode D – Binaire précompilé (rapide)

La méthode la plus universelle, sans gestionnaire de paquets. Téléchargez le binaire et installez‑le manuellement.

Terminal window
curl -L https://github.com/charmbracelet/vhs/releases/latest/download/vhs_Linux_x86_64.tar.gz -o vhs.tar.gz
tar -xf vhs.tar.gz
sudo mv vhs /usr/local/bin/
vhs --version

Adapter le nom du fichier selon votre OS / architecture.

Méthode E – Depuis la source (Go)

La méthode la plus flexible si vous avez Go installé.

Terminal window
go install github.com/charmbracelet/vhs@latest

Étape 3 : Tests post‑installation

Terminal window
# Afficher la version installée
vhs --version
# Générer une tape de test minimale et produire un GIF
cat > quick.tape <<'EOF'
Output quick.gif
Set TypingSpeed 120ms
Type "echo VHS OK"
Enter
Sleep 1s
EOF
vhs quick.tape && ls -lh quick.gif

Si quick.gif est créé sans erreur, l’environnement est opérationnel. Votre fichier .gif devrait ressembler à ceci :

Aperçu du GIF

Étape 4 : Dépannage rapide

  • GIF vide ou non généré : vérifier ffmpeg -version
  • Erreur de dépendance : ajouter la directive Require ffmpeg en tête de la tape pour échouer tôt
  • Thème non appliqué : s’assurer que la directive Set Theme est placée avant toute commande Type
  • Commande lente imprévisible : remplacer pause fixe par Wait après la commande

Ecriture d’une tape VHS

Le cœur de VHS : un fichier texte avec extension .tape décrivant la session. Chaque ligne est une instruction.

Structure générale :

Output ./demo.gif
Set FontSize 16
Set TypingSpeed 120ms
Require ffmpeg
Type "echo 'Bonjour VHS'"
Enter
Sleep 500ms
Type "uname -s"
Enter

Principales instructions

  • Output <chemin> : définit le fichier de sortie. Format selon extension (.gif, .mp4, .webm, .png -> séquence)
  • Set <Paramètre> <Valeur> : personnalisation (police, thème, vitesse, curseur, dimensions)
  • Type "texte" : simule la frappe humaine d’une chaîne
  • Enter : envoie la touche Entrée
  • Sleep <durée> : pause (ex: 500ms, 2s)
  • Wait : attend la fin de la sortie précédente (utile pour des commandes longues)
  • Require <binaire> : vérifie la présence d’une dépendance avant exécution
  • Hide / Show : masquer temporairement une portion pour ne pas l’afficher
  • Source <fichier.tape> : inclure un sous-script (modularisation)

Bonnes pratiques structure

  • Grouper les Set en début de fichier
  • Toujours définir explicitement Output
  • Utiliser Require pour des dépendances critiques (ffmpeg, git)
  • Préférer Sleep courts + Wait plutôt que des pauses longues arbitraires
  • Versionner le .tape, ignorer les rendus (.gitignore)

Enregistrement actif : vhs record

Si vous préférez partir d’une capture réelle, VHS propose :

Terminal window
# Enregistrer une session interactive et générer un fichier .tape
vhs record > session.tape

Vous tapez vos commandes normalement, puis terminez avec Ctrl+D. Le fichier généré peut être nettoyé pour :

  • Retirer les fautes de frappe
  • Ajuster les temporisations (Sleep)
  • Ajouter des Set cohérents (police, thème, vitesse de frappe)

Cette approche hybride (record puis édition) combine vitesse et précision.

Génération du GIF / vidéo

Une fois la tape prête :

Terminal window
# Génère le média selon l'extension Output
vhs demo.tape

Formats supportés :

  • .gif : diffusion web / README
  • .mp4 : taille réduite, réseaux sociaux
  • .webm : optimisation web moderne
  • .png (dossier) : spritesheet potentielle / post‑traitement

Changez simplement l’extension dans l’instruction Output pour obtenir un autre format, sans modifier le reste du scénario.

Paramètres Set disponibles

Résumé des principaux réglages supportés (à placer avant toute commande non‑Set / non‑Output).

  • Set Shell <bash|zsh|fish|...> : shell utilisé pour exécuter les commandes
  • Set Width <px> / Set Height <px> : dimensions du terminal rendu
  • Set FontSize <px> : taille des caractères
  • Set FontFamily "Nom" : police monospacée (doit être installée côté système ou embarquée)
  • Set LetterSpacing <px> : espacement horizontal entre lettres
  • Set LineHeight <ratio> : interligne (ex: 1.4)
  • Set TypingSpeed <durée> : délai entre frappes (ex: 120ms, 0.1 secondes)
  • Set Theme { JSON } ou Set Theme "Nom" : thème 16 couleurs + foreground/background/cursor
  • Set Padding <px> : espace interne autour de la zone terminal
  • Set Margin <px> : marge externe du cadre vidéo
  • Set MarginFill "#RRGGBB" : couleur de fond de la marge
  • Set WindowBar <Colorful|ColorfulRight|Rings|RingsRight|None> : barre décorative
  • Set BorderRadius <px> : arrondi des coins (souvent avec marge + couleur)
  • Set Framerate <fps> : fréquence de capture (ex: 30, 60)
  • Set PlaybackSpeed <facteur> : accélération ou ralentissement de lecture finale (ex: 1.2)
  • Set LoopOffset <frames|%> : frame de début de boucle GIF (thumbnails plus dynamiques)
  • Set CursorBlink <true|false> : clignotement du curseur
  • Set CursorStyle <Block|Underline|Bar> : forme du curseur

Astuce : regrouper tous les Set et Require en tête de fichier pour éviter qu’ils ne soient ignorés.

Paramètres d’affichage utiles

Set Width 1000
Set Height 600
Set FontSize 18
Set Theme Dracula
Set TypingSpeed 120ms
Set CursorStyle Block

Publication et partage

VHS propose un hébergement intégré :

Terminal window
# Génération + upload immédiat si --publish est présent
vhs demo.tape --publish

Ou après génération :

Terminal window
# Publication d'un fichier existant
vhs publish demo.gif

La commande retourne une URL partageable (https://vhs.charm.sh/...). Avantages :

  • Pas besoin de committer des fichiers lourds
  • Rendu optimisé (hébergement Charm)
  • Mise à jour automatisable (CI)

Alternative : héberger dans un dépôt GitHub (assets release) ou un CDN (Cloudflare R2 / S3) pour contrôle complet.

Automatisation & intégration CI (GitHub Actions)

Automatiser la régénération garantit que vos GIFs restent synchronisés avec le code source. Exemple de workflow minimal :

name: Generate VHS assets
on:
push:
paths:
- "demo/*.tape"
workflow_dispatch:
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup VHS
run: |
sudo apt-get update
sudo apt-get install -y ffmpeg
curl -fsSL https://raw.githubusercontent.com/charmbracelet/vhs/main/install.sh | bash
sudo mv bin/vhs /usr/local/bin/vhs
- name: Generate GIFs
run: |
for f in demo/*.tape; do vhs "$f"; done
- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: vhs-gifs
path: demo/*.gif

Bonnes pratiques CI :

  • Ne pas stocker les GIFs générés dans Git (poids, diffs inutiles)
  • Versionner uniquement les .tape
  • Publier via --publish ou artifacts compressés
  • Ajouter un job périodique (schedule) si dépendances externes évoluent

Astuces & bonnes pratiques

  • Définir une vitesse de frappe modérée : Set TypingSpeed 90ms (lisible)
  • Utiliser Wait après des commandes réseau ou build
  • Ajouter un prompt minimaliste pour lisibilité (Set Prompt "$ " si supporté)
  • Masquer secrets / tokens : segment sous HideShow
  • Externaliser des blocs récurrents (Source ./fragments/init.tape)
  • Documenter les choix dans des commentaires en amont du fichier .tape (lignes commençant par #)
  • Contrôler la police : préférer une police monospacée lisible (JetBrains Mono, Fira Code)
  • Vérifier le poids final des GIFs (optimisation possible via gifsicle)

Optimisation du poids des GIFs

Réduire la taille des GIFs améliore les performances de chargement dans la documentation.

  • Limiter les dimensions : éviter > 1200px de largeur si non nécessaire
  • Réduire la durée : supprimer les pauses excessives (Sleep > 2s)
  • Ajuster Framerate : 30 fps suffisent souvent, 24 fps acceptable pour commandes lentes
  • Palette optimisée : certains thèmes très colorés augmentent la palette → préférer un thème sobre
  • Utiliser PlaybackSpeed : 1.1 ou 1.2 fluidifie sans rendre illisible
  • Post‑traitement : gifsicle -O3 demo.gif -o demo-opt.gif
  • Format alternatif : proposer aussi .webm ou .mp4 (nettement plus léger) et garder GIF comme fallback
  • Découper : plusieurs courtes démonstrations plutôt qu’un long scénario monolithique

Exemple pipeline local :

Terminal window
# Optimisation après génération GIF
vhs demo.tape
gifsicle -O3 demo.gif -o demo-opt.gif

Organisation d’un répertoire demo/

demo/
00-intro.tape
10-installation.tape
20-flux-base.tape
fragments/
palette.tape
header.tape

Exemple de modularisation

# Fichier principal
Output ./workflow.gif
Source ./fragments/header.tape
Source ./fragments/palette.tape
Type "make build"
Enter
Wait
Type "./bin/outillage --help"
Enter

Sécurité & qualité documentaire

  • Éviter de montrer des chemins utilisateurs privés (/home/user) → utiliser comptes génériques
  • Purger l’historique de commandes sensibles
  • Indiquer dans la doc la commande pour régénérer : vhs chemin.tape
  • Ajouter un badge ou une phrase : “Ce GIF est généré automatiquement via CI”

Plus d’infos