Screencasting GIF; la manière UNIX

57

Pour prendre une capture d' écran statique d'une partie de mon écran, j'utilise souvent scrotavec -s shot.png. C'est idéal pour ajouter des illustrations aux publications StackExchange. J'ai même trouvé ce script pour télécharger automatiquement une telle capture d'écran sur Imgur.com et mettre un lien dans mon presse-papiers X!

Passons à douze : comment puis-je créer de la même manière un screencast GIF?

Il existe des programmes comme recordmydesktop, byzanzet co comme discuté sur Ubuntu Ask qui visent à être « facile à utiliser », mais dans mon expérience sont bogués, inefficaces, la plupart du temps unscriptable et impropre à peu unique des choses comme ça.

Je veux juste sélectionner une zone et enregistrer un fichier GIF, avec une commande de console que je peux comprendre, et non une monstruosité mystérieuse et non graphique.

Comment puis-je faire ceci?

Anko
la source
2
Connexe: Comment créer des images GIF animées d’un screencast? de Ask Ubuntu.
Cristian Ciupitu
2
Pour tout ce qui concerne les terminaux, cela peut être la meilleure option: asciinema.org
Flatron

Réponses:

68

alors ok

GIF Vimcast!

J'ai commencé ffcast, ai fait vim, arrêté ffcast, puis converted .avi.gif.

J'ai exécuté les commandes d'enregistrement dans un autre terminal. Script poli pour votre $PATHà la fin de cette réponse.

Qu'est-il arrivé?

Capture

FFcast aide l'utilisateur à sélectionner de manière interactive une région d'écran et à transmettre la géométrie à une commande externe, telle que FFmpeg, pour l'enregistrement sur écran.

ffcastest le produit glorieux d' un piratage effectué par la communauté Arch Linux (principalement lolilolicon ). Vous pouvez le trouver sur GitHub (ou dans le AUR pour Arche ers). Sa liste de dépendances est juste bashet ffmpeg, bien que vous souhaitiez xrectsel( lien AUR ) pour la sélection interactive d'un rectangle.

Vous pouvez également ajouter des ffmpegindicateurs juste après la commande. J'ai réglé -r 15pour capturer à 15 images par seconde et -codec:v huffyuvpour l'enregistrement sans perte. (Jouez avec ceux-ci pour modifier le compromis taille / qualité.)

GIFFing

ImageMagick peut lire des .avividéos et a quelques astuces d'optimisation de GIF qui réduisent considérablement la taille du fichier tout en préservant la qualité: -layers Optimizeà convertInvoque le Optimiseur usage général. Le manuel ImageMagick contient également une page sur les optimisations avancées .

Script final

C'est ce que j'ai dans mes $PATH. Il enregistre dans un fichier temporaire avant la conversion.

#!/bin/bash
TMP_AVI=$(mktemp /tmp/outXXXXXXXXXX.avi)
ffcast -s % ffmpeg -y -f x11grab -show_region 1 -framerate 15 \
    -video_size %s -i %D+%c -codec:v huffyuv                  \
    -vf crop="iw-mod(iw\\,2):ih-mod(ih\\,2)" $TMP_AVI         \
&& convert -set delay 10 -layers Optimize $TMP_AVI out.gif

Merci au BenC pour son travail de détective dans la détermination des drapeaux corrects après la récente ffcastmise à jour.

Si vous souhaitez installer les dépendances sur une distribution basée sur Debian, Louis a rédigé des notes d’installation utiles .

Wheeeeee!

Anko
la source
1
J'ai créé une version qui ne nécessite pas bash, mais qui fonctionne sur tous les shell compatibles POSIX. Github.com/chilicuil/ffcast
Javier López
2
On dirait que la syntaxe de la ligne de commande ffcasta changé: github.com/lolilolicon/FFcast/issues/8
Jack O'Connor
1
Le moyen le plus simple de le faire est maintenant ffcast -s rec [filename], bien que cela ne donne pas les paramètres exacts que vous utilisez dans votre exemple. Malheureusement, pour donner les paramètres exacts, vous devez maintenant donner la ffmpegcommande complète . Votre appel sur la meilleure façon de mettre à jour cette réponse :)
Jack O'Connor
4
Basé sur les commentaires sur GH, ffcast -s % ffmpeg -f x11grab -show_region 1 -framerate 20 -video_size %s -i %D+%c -codec:v huffyuv -vf crop="iw-mod(iw\\,2):ih-mod(ih\\,2)" $TMP_AVIsemble faire l'affaire.
BenC
1
Quelques notes sur l'installation de certaines de ces choses pour ceux qui n'en ont pas déjà sur leur système
Louis Maddox
11

Pour moi, la réponse était d'utiliser ffcastavec ffmpegcomme suit:

ffcast -w % ffmpeg -f x11grab -show_region 1 -framerate 20 -video_size %s -i %D+%c -codec:v huffyuv -vf crop="iw-mod(iw\\,2):ih-mod(ih\\,2)" out.avi

J'avais ensuite l'habitude ffmpegde faire la conversion d'avi en gif - c'est très rapide et ça garde le framerate:

ffmpeg -i out.avi -pix_fmt rgb24 out.gif

Enfin, j’ai utilisé convert de la même manière que la réponse de @anko pour optimiser le gif, mais j’ai limité l’utilisation des ressources pour arrêter de quitter avec un message, et j’ai supprimé le délai, comme cela a déjà été fait:convertkilledffmpeg

convert -limit memory 1 -limit map 1 -layers Optimize out.gif out_optimised.gif
John Hamelink
la source
2

pour ma configuration (Ubuntu 16.04), ffcast ne fonctionne pas bien car il n’est pas mis à jour sur github depuis un bon moment.

donc j'ai mis en place un script en utilisant slop ( https://github.com/naelstrof/slop ) et ffmpeg.

un exemple:

yay ça marche

#!/bin/bash

read -r X Y W H G ID < <(slop -f "%x %y %w %h %g %i")
TMP_AVI=$(mktemp /tmp/outXXXXXXXXXX.avi)

ffmpeg -s "$W"x"$H" -y -f x11grab -i :0.0+$X,$Y -vcodec 
huffyuv -r 25 $TMP_AVI \
&& convert -set delay 5 -layers Optimize $TMP_AVI out.gif 
TC Zhang
la source
1

C'est pour cette raison que j'avais écrit un script de wrapper interactif pour les ordinateurs de bureau Unix. Après un an d'utilisation, je suis ravi de le partager ici!

Fait avec byzanz, gifsicle, xdotoolet le script est écrit dans php.

Exemple de sortie:

[1020px, largeur gif non redimensionnée 1020px, 70 secondes, 50 couleurs, 65Ko ]

entrez la description de l'image ici

Il fournit de bons gifs compressés et constitue une bonne vitrine pour cette question.

Ceci est une base assez simple, prête à être piratée par vous.

Fonctionnalités : Enregistrement GIF aux positions de la souris ou en plein écran, redimensionnement, compression, compression des couleurs, inversion / fusion, téléchargement giphy.com.

Pour commencer un enregistrement gif de 10 secondes: gif 10

Pour enregistrer plusieurs fois avec les mêmes paramètres: gif !

Pour démarrer un enregistrement gif plein écran de 5 secondes: gif 5 --fullscreen

Le script court, s'enregistre agréablement:

[ 45 secondes, largeur 645 pixels, couleurs pleines, 976 Ko ]
entrez la description de l'image ici

Script complet de 5 Ko:

#!/usr/bin/php

<?php
#> php xdotool byzanz gifsicle curl
#@ https://webdev23.github.io/gif/gif

echo "Usage: ./gif [time in seconds|!] [--fullscreen|-f]\n";
echo "--------------------------------------------------\n";
echo "Gif recorder tool\n";
echo "gif ! to call back last settings\n";
echo "Please move your mouse at the top left corner point\n";
echo "of the wanted gif area. Then press enter.\n";
echo "\n";

#~ Nico KraZhtest | 05/2017 | https://github.com/webdev23/gif
#~ Create fluid GIF's fastly
#~ You can set the gif record time as argument: ./gif 10
#~ Default record time is 1 seconde, or set it now:
   $recordTime = 1;
#~ ----------------

$t = @$argv[1];

$x1;$y1;$x2;$y2;$gw;$gh;$defc;$rw;

if (!isset($argv[1]) || @$argv[1] === "!") {
  $t = $recordTime;
}

if (@$argv[1] === "!") {
  $pos = file_get_contents("./.config/gif/pos");
  $pos = explode("\n", $pos);
  $x1 = $pos[0];
  $y1 = $pos[1];
  $x2 = $pos[2];
  $y2 = $pos[3];
  $gw = $pos[4];
  $gh = $pos[5];
  $t = $pos[6];
  @$GLOBALS['defc'] = $pos[7];
  @$GLOBALS['$rw'] = $pos[8];
   #~ echo $x1." ".$y1." ".$x2." ".$y2." ".$gw." ".$gh." ".$t." ".$defc." ".@$rw;
  }

else if (@$argv[2] === "fullscreen" || @$argv[2] === "--fullscreen" || @$argv[2] === "-f" || @$argv[2] === "f") {
  echo "############\nStarting fullscreen record\n";
  $fs = system("xdpyinfo  | grep 'dimensions:'");
  echo "\n";
  $fs = explode("    ",$fs);
  echo $fs[1];
  $fs = explode(" ",$fs[1]);
  echo $fs[0];
  $fs = explode("x",$fs[0]);
  echo $fs[0]."\n";
  echo $fs[1];
  $x1 = "0";
  $y1 = "0";
  $x2 = "fs";
  $y2 = "fs";
  $gw = $fs[0];
  $gh = $fs[1];
  $t = $argv[1];
  system("mkdir -p ./.config/gif/");
  system("cd ./.config/gif/ && \
          echo '$x1\n$y1\n$x2\n$y2\n$gw\n$gh\n$t\n\n\n\n' > pos");
  }

else {
  $stdin = fopen('php://stdin', 'r');
  $response = rtrim(fgets(STDIN));

  $p1 = system("xdotool getmouselocation");

  $pos1 = explode(" ",$p1);

  $x1 = $pos1[0];
  $x1 = explode(":",$x1);
  $x1 = $x1[1];
  echo "X1: ".$x1;

  $y1 = $pos1[1];
  $y1 = explode(":",$y1);
  $y1 = $y1[1];
  echo " Y1: ".$y1;

  echo "\nNow move your mousse at the bottom right corner.\nThen enter\n";

  $stdin = fopen('php://stdin', 'r');
  $response = rtrim(fgets(STDIN));

  $p2 = system("xdotool getmouselocation");

  $pos2 = explode(" ",$p2);

  $x2 = $pos2[0];
  $x2 = explode(":",$x2);
  $x2 = $x2[1];
  echo "X2: ".$x2;

  $y2 = $pos2[1];
  $y2 = explode(":",$y2);
  $y2 = $y2[1];
  echo " Y2: ".$y2;

  $gw = ($x2 - $x1);
  echo "\nGif width: ".$gw;

  $gh = ($y2 - $y1);
  echo "\nGif height: ".$gh;
  echo "\n".$x1." ".$y1." ".$x2." ".$y2." ".$gw." ".$gh." ".$t."\n";

  system("mkdir -p ./.config/gif/");
  system("cd ./.config/gif/ && \
          echo '$x1\n$y1\n$x2\n$y2\n$gw\n$gh\n$t\n\n\n\n' > pos");
  }

$unix = date_timestamp_get(date_create());

echo "\n".$unix." | Starting ".$t."s gif record\n";

@system("byzanz-record \
        -v             \
        --duration=$t  \
        --x=$x1        \
        --y=$y1        \
        --width=$gw    \
        --height=$gh   \
        ~/Pictures/gif$unix.gif");

$named = "gif".$unix;

echo "Saved as ~/Pictures/".$named.".gif\n";

echo "\nOptimize | How many colors to keep? (default 100, max 256) \n";

if (@$argv[1] === "!"){
  $pos = file_get_contents("./.config/gif/pos");
  $pos = explode("\n", $pos);
  $defc = $pos[7];
  }

if (!isset($defc)){
  $defc = readline("Colors: ");
  }

if (empty($defc)){
  $defc = "100";
  }

echo "\nKeeping ".$defc." colors\n";

system("gifsicle --verbose -i ~/Pictures/$named.gif -O5 --colors=$defc -o ~/Pictures/$named\_reduced.gif");

echo "\nOptimize | Resize width in pixels (default 360px) \n";

if (@$argv[1] === "!"){
  $pos = file_get_contents("./.config/gif/pos");
  $pos = explode("\n", $pos);
  $rw = $pos[8];
  }

if (!isset($rw)){
  $rw = readline("Width : ");
  }

if (empty($rw)){
  $rw = "360";
  }

echo "\nResized by ".$rw." pixels width\n";

@system("gifsicle --verbose -i ~/Pictures/$named\_reduced.gif --resize-width $rw -o ~/Pictures/".$named."_optimized.gif");

$opt = "~/Pictures/".$named."_optimized.gif";

usleep(5000000);

echo "\nSpecial | Reverse and merge?\n";

system("xdg-open ~/Pictures/".$named."_optimized.gif > /dev/null");

if (@$argv[1] === "!"){
  $pos = file_get_contents("./.config/gif/pos");
  $pos = explode("\n", $pos);
  $rev = $pos[9];
  }

if (!isset($rev)){
  $stdin = fopen('php://stdin', 'r');
  $rev = rtrim(fgets(STDIN));
  $rev = "1";
  }

if (!isset($rev)){
  $rev = "0";
  }

@system("cd ./.config/gif/ && sed -i '8s/.*/$defc/' pos");
@system("cd ./.config/gif/ && sed -i '9s/.*/$rw/' pos");
@system("cd ./.config/gif/ && sed -i '10s/.*/$rev/' pos");

if ($rev === "1"){
  @system("gifsicle                           \
            -i ~/Pictures/$named\_reduced.gif \
            '#-2-1'                           \
            -o ~/Pictures/".$named."_reversed.gif");

  $inv = "~/Pictures/".$named."_reversed.gif";

  usleep(400000);

  @system("gifsicle                           \
            -i ~/Pictures/$named\_reduced.gif \
          --append $inv                       \
          --resize-width $rw                  \
          -o ~/Pictures/".$named."_merged.gif");

  usleep(3000000);

  system("xdg-open ~/Pictures/".$named."_merged.gif > /dev/null");

  }

echo "\n####################";
echo "\nUpload to giphy.com?\n";

$stdin = fopen('php://stdin', 'r');
$response = rtrim(fgets(STDIN));

$m = "~/Pictures/".$named."_merged.gif";
$f = system("du -h $m");
$f = explode("  ",$f);
$f = $f[1];

$www = system('curl                         \
                --progress-bar              \
                -v                          \
                -F "file=@'.$f.'"           \
                -F "api_key=dc6zaTOxFJmzC"  \
                "http://upload.giphy.com/v1/gifs"');

$www = json_decode($www);

echo "\n\nhttps://i.giphy.com/".$www->data->id.".gif\n";

echo "\nThanks YOU!\n";

Possibilité d'inverser / fusionner pour créer des contenus artistiques.

Original (435kb)

entrez la description de l'image ici

Renversé, fusionné: (826kb)

entrez la description de l'image ici

Pour installer, en utilisant phi :

php <(curl https://webdev23.github.io/phi/phi) install https://webdev23.github.io/gif/gif

Plein écran:

[1920 * 1080px, gif 400px, 50 secondes , 100 couleurs, 2Mo ]

entrez la description de l'image ici

Source, avec quelques explications supplémentaires et des mises à jour potentielles: https://github.com/webdev23/gif

NVRM
la source