GIF-Screencasting; auf UNIX-Weise

57

Um einen statischen Screenshot eines ausgewählten Teils meines Bildschirms aufzunehmen, verwende ich häufig scrotmit -s shot.png. Dies eignet sich hervorragend zum Hinzufügen von Illustrationen zu StackExchange-Posts. Ich habe sogar festgestellt, dass dieses Skript einen solchen Screenshot automatisch auf Imgur.com hochlädt und einen Link in meine X-Zwischenablage legt!

Drehen wir dies auf zwölf : Wie erstelle ich auf ähnliche Weise einen GIF-Screencast?

Es gibt Programme wie recordmydesktop, byzanz& co wie besprochen auf Ubuntu Fragen , die darauf abzielen „benutzerfreundlich“ zu sein, aber in meiner Erfahrung sind fehlerhaft, ineffizient, vor allem unscriptable und nicht geeignet für kleine einmalige Dinge wie diese.

Ich möchte nur einen Bereich auswählen und ein GIF aufzeichnen, mit einem Konsolenbefehl, den ich verstehen kann, und nicht mit einer geheimen, nicht beschreibbaren GUI-Monstrosität.

Wie kann ich das machen?

Anko
quelle
2
Verwandte Themen: Wie erstelle ich animierte GIF-Bilder eines Screencasts? von Ask Ubuntu.
Cristian Ciupitu
2
Für Terminal-bezogene Dinge
Flatron

Antworten:

68

OK dann

GIF-Vimcast!

Ich begann ffcast, hat vim, zu beenden ffcast, dann converted .avi.gif.

Ich habe die Aufnahmebefehle in einem anderen Terminal ausgeführt. Poliertes Skript für Sie $PATHam Ende dieser Antwort.

Was ist passiert?

Erfassen

FFcast unterstützt den Benutzer bei der interaktiven Auswahl eines Bildschirmbereichs und übergibt die Geometrie zur Bildschirmaufnahme an einen externen Befehl, z. B. FFmpeg.

ffcastist das glorreiche Produkt von Hacking in der Arch Linux-Community (hauptsächlich Lolilolicon ). Sie können es finden auf Github (oder in der AUR für Arch ers). Die Abhängigkeitsliste ist einfach bashund ffmpeg, obwohl Sie möchten xrectsel( AUR-Link ) für die interaktive Rechteckauswahl.

Sie können ffmpegFlags auch direkt nach dem Befehl anhängen . Ich habe die -r 15Aufnahme auf 15 Bilder pro Sekunde und -codec:v huffyuvfür verlustfreie Aufnahmen eingestellt. (Spielen Sie mit diesen, um den Kompromiss zwischen Größe und Qualität zu optimieren.)

GIFfing

ImageMagick kann .aviVideos lesen und hat einige GIF-Optimierungs-Tricks, die die Dateigröße drastisch reduzieren und gleichzeitig die Qualität erhalten: Das, -layers Optimizeum convertden Universal-Optimierer aufzurufen. Das ImageMagick-Handbuch enthält auch eine Seite mit erweiterten Optimierungen .

Letztes Drehbuch

Das habe ich in meinem $PATH. Es zeichnet vor der Konvertierung in eine temporäre Datei auf.

#!/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

Vielen Dank an BenC für die Detektivarbeit bei der Ermittlung der korrekten Flags nach dem letzten ffcastUpdate.

Wenn Sie die Abhängigkeiten auf einer Debian-basierten Distribution installieren möchten, hat Louis hilfreiche Installationshinweise geschrieben .

Wheeeeee!

Anko
quelle
1
Ich habe eine Version erstellt, die kein bash erfordert, aber auf jeder POSIX-kompatiblen Shell funktioniert. Github.com/chilicuil/ffcast
Javier López
2
Die Befehlszeilensyntax von scheintffcast sich geändert zu haben: github.com/lolilolicon/FFcast/issues/8
Jack O'Connor
1
Der einfachste Weg, dies zu tun, ist jetzt ffcast -s rec [filename], obwohl dies nicht die genauen Einstellungen angibt, die Sie in Ihrem Beispiel verwenden. Um genaue Einstellungen vornehmen zu können, müssen Sie jetzt leider den gesamten ffmpegBefehl eingeben. Ihr Anruf über den besten Weg, um diese Antwort zu aktualisieren :)
Jack O'Connor
4
Basierend auf den Kommentaren zu 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_AVIscheint dies der Trick zu sein.
BenC
1
Einige Hinweise zur Installation einiger dieser Dinge für andere, ohne diese bereits auf ihrem System
Louis Maddox
11

Für mich war die Antwort ffcastmit ffmpegso zu verwenden:

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

Ich habe dann ffmpegdie Konvertierung von avi nach gif gemacht - es ist sehr schnell und die Framerate bleibt erhalten:

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

Schließlich habe ich convert in der gleichen Weise wie @anko ‚s Antwort der gif zu optimieren, aber ich ein Limit auf die Ressourcennutzung zu stoppen convertmit einer austretenden killedNachricht, und ich entfernt , um die Verzögerung , wie ffmpegbereits das behandelt:

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

Für mein Setup (Ubuntu 16.04) funktioniert ffcast nicht gut, da es für eine Weile nicht mehr auf Github aktualisiert wurde.

Also habe ich ein Skript mit slop ( https://github.com/naelstrof/slop ) und ffmpeg erstellt.

ein Beispiel:

yay es funktioniert

#!/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
quelle
1

Aus diesem Grund habe ich ein interaktives Wrapper-Skript für Unix-Desktops geschrieben, und nach einem Jahr der Nutzung teile ich es gerne dort!

Hergestellt mit byzanz, gifsicle, xdotool, und das Skript geschrieben php.

Beispielausgabe:

[1020px, nicht verkleinerte GIF-Breite 1020px, 70 Sekunden, 50 Farben, 65 KB ]

Bildbeschreibung hier eingeben

Es bietet gute komprimierte Gifs und ist ein gutes Schaufenster für diese Frage.

Dies ist eine ziemlich einfache Basis, die bereit ist, von Ihnen gehackt zu werden.

Funktionen : GIF-Aufzeichnung an Mauspositionen oder im Vollbildmodus, Größenänderung, Komprimierung, Farbkomprimierung, Umkehren / Zusammenführen, giphy.com-Curl-Upload.

So starten Sie einen 10-Sekunden-GIF-Datensatz: gif 10

So zeichnen Sie mehrere Male mit denselben Parametern auf: gif !

So starten Sie einen 5-Sekunden-GIF-Datensatz im Vollbildmodus: gif 5 --fullscreen

Skript läuft und zeichnet sich angenehm auf:

[ 45 Sekunden, Breite 645px, Vollfarben, 976 KB ]
Bildbeschreibung hier eingeben

Vollständiges 5-KB-Skript:

#!/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";

Reverse / Merge-Fähigkeit, um künstlerische Inhalte zu erstellen.

Original (435 KB)

Bildbeschreibung hier eingeben

Umgekehrt, zusammengeführt: (826kb)

Bildbeschreibung hier eingeben

So installieren Sie mit phi :

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

Vollbild:

[1920 * 1080px, GIF 400px, 50 Sekunden , 100 Farben, 2 MB ]

Bildbeschreibung hier eingeben

Quelle mit weiteren Erläuterungen und möglichen Updates: https://github.com/webdev23/gif

NVRM
quelle