Transmisión de pantalla GIF; la manera UNIX

57

Para tomar una captura de pantalla estática de una parte seleccionada de mi pantalla, a menudo la uso scrotcon -s shot.png. Esto es ideal para agregar ilustraciones a las publicaciones de StackExchange. ¡Incluso encontré este script para cargar automáticamente una captura de pantalla de este tipo en Imgur.com y poner un enlace en mi portapapeles X!

Cambiemos esto a doce : ¿Cómo creo de manera similar un screencast GIF?

No son programas como recordmydesktop, byzanzy co como se discute en Ask Ubuntu que pretenden ser "fácil de usar", pero en mi experiencia son errores, ineficiente, sobre todo unscriptable e inadecuada para el pequeño de una sola vez cosas como esta.

Solo quiero seleccionar un área y grabar un GIF, con un comando de consola que pueda entender, no una monstruosidad de GUI inescrutable arcana.

¿Cómo puedo hacer esto?

Anko
fuente
2
Relacionado: ¿Cómo crear imágenes GIF animadas de un screencast? de Ask Ubuntu.
Cristian Ciupitu
2
Para cualquier cosa relacionada con terminales, esta puede ser la mejor opción: asciinema.org
Flatron

Respuestas:

68

OK entonces

GIF vimcast!

Comencé ffcast, hice vim, salí ffcast, luego converted .avi.gif.

Ejecuté los comandos de grabación en otra terminal. Guión pulido para usted $PATHal final de esta respuesta.

¿Que pasó?

Capturar

FFcast ayuda al usuario a seleccionar de forma interactiva una región de pantalla y transfiere la geometría a un comando externo, como FFmpeg, para la grabación de pantalla.

ffcastes el glorioso producto de algún hackeo en la comunidad Arch Linux (principalmente lolilolicon ). Lo puede encontrar en GitHub (o en el AUR de Arch ERS). Su lista de dependencias es justa bashy ffmpeg, aunque querrá xrectsel( enlace AUR ) para la selección interactiva de rectángulos.

También puede agregar ffmpegbanderas justo después del comando. Configuré -r 15capturar a 15 cuadros por segundo y -codec:v huffyuvpara una grabación sin pérdidas. (Juegue con estos para modificar el equilibrio tamaño / calidad).

GIFfing

ImageMagick puede leer .avivídeos y tiene algunos trucos de optimización GIF que reducen drásticamente el tamaño del archivo, mientras que la preservación de la calidad: El -layers Optimizeque convertinvoca el optimizador de propósito general. El manual de ImageMagick también tiene una página sobre optimizaciones avanzadas .

Guión final

Esto es lo que tengo en mi $PATH. Graba en un archivo temporal antes de convertir.

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

Gracias a BenC por el trabajo de detective en descubrir las banderas correctas después de la ffcastactualización reciente .

Si desea instalar las dependencias en una distribución basada en Debian, Louis ha escrito útiles notas de instalación .

Wheeeeee!

Anko
fuente
1
He creado una versión que no requiere bash, pero que trabaja en cualquier shell compatible con POSIX github.com/chilicuil/ffcast
Javier López
2
Parece que la sintaxis de la línea de comando ffcastha cambiado: github.com/lolilolicon/FFcast/issues/8
Jack O'Connor
1
La forma más sencilla de hacerlo es ahora ffcast -s rec [filename], aunque eso no proporciona la configuración exacta que está utilizando en su ejemplo. Desafortunadamente, para dar configuraciones exactas, ahora tiene que dar el ffmpegcomando completo . Su llamada sobre la mejor manera de actualizar esta respuesta :)
Jack O'Connor
44
Basado en los comentarios sobre 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_AVIparece hacer el truco.
BenC
1
Algunas notas sobre la instalación de algunas de estas cosas para cualquier otra persona sin estas ya en su sistema
Louis Maddox
11

Para mí, la respuesta fue utilizar ffcastcon ffmpegeste modo:

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

Luego solía ffmpeghacer la conversión de avi a gif: es muy rápido y mantiene intacta la velocidad de fotogramas:

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

Por último, utilicé convertir de la misma manera que la respuesta de @anko para optimizar el gif, pero establecí un límite en el uso de recursos para dejar de salir con un mensaje, y eliminé la demora como ya se ha manejado:convertkilledffmpeg

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

para mi configuración (ubuntu 16.04), ffcast no funciona bien ya que no se actualiza en github durante bastante tiempo.

entonces puse un script usando slop ( https://github.com/naelstrof/slop ) y ffmpeg.

un ejemplo:

yay está funcionando

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

Había escrito una secuencia de comandos de envoltura interactiva para escritorios Unix por esta razón, y después de un año de uso, ¡estoy feliz de compartirla allí!

Hecho con byzanz, gifsicle, xdotool, y el guión está escrito en php.

Salida de ejemplo:

[1020 px, ancho de gif no redimensionado 1020 px, 70 segundos, 50 colores, 65 Kb ]

ingrese la descripción de la imagen aquí

Proporciona buenos gifs comprimidos y es un buen escaparate para esta pregunta.

Esta es una base bastante simple, lista para ser hackeada por ti.

Funcionalidades : registro GIF en posiciones del mouse o pantalla completa, cambio de tamaño, compresión, compresión de color, inversión / fusión, carga de rizos de giphy.com.

Para comenzar un registro gif de 10 segundos: gif 10

Para grabar varias veces con los mismos parámetros: gif !

Para iniciar un registro gif de 5 segundos a pantalla completa: gif 5 --fullscreen

Guión corriendo, grabándose gratamente a sí mismo:

[ 45 segundos, ancho 645px, colores completos, 976kb ]
ingrese la descripción de la imagen aquí

Guión completo de 5 kb:

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

Capacidad inversa / fusión, para crear cosas artísticas.

Original (435 kb)

ingrese la descripción de la imagen aquí

Invertido, fusionado: (826kb)

ingrese la descripción de la imagen aquí

Para instalar, usando phi :

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

Pantalla completa:

[1920 * 1080px, gif 400px, 50 segundos , 100 colores, 2Mb ]

ingrese la descripción de la imagen aquí

Fuente, con más explicaciones y posibles actualizaciones: https://github.com/webdev23/gif

NVRM
fuente