Копипаст из чужой консоли

Скринкаст консольной сессии в маленьком анимированном gif — самый простой и быстрый способ продемонстрировать свои действия в консоли. Такую анимацию легко запостить в чате или опубликовать на веб-страничке, она весит совсем мало. Но это неоптимальный вариант.

Существуют специализированные инструменты именно для консольных скринкастов. Для этого они задействуют встроенный псевдотерминал Linux, то есть PTY. Самые продвинутые добавляют спецэффекты типа подсветки нажатий клавиш и, самое главное, позволяют выделить мышкой и скопировать текст прямо из «видео».

Записываем видео/анимацию


Итак, начнём с классики. Когда хочется показать свои действия другому человеку, первая мысль — записать экран в видео mp4 / webm или анимацию gif. Казалось бы, логичный вариант.

Можно использовать ffmpeg, который пишет видео и автоматически конвертирует его в mp4 или webm. Например, так:

ffmpeg -f x11grab -r 25 -s 800x600 -i :0.0 ~/vid_tst1.mp4

Полученное видео тоже можно сконвертировать в GIF тем же ffmpeg.

Теоретически gif-анимацию можно сгенерировать вручную bash-скриптом. Команда magick import -window сохраняет скриншоты, а convert склеивает из них анимацию:

convert -delay 20 -loop 0 *.jpg scr_cst1.gif

Но этот конвейер добавляет лаги во время записи. А однажды ImageMagick вообще закрашился на этапе конвертации. Наверное, картинки не влезли в память. В этот момент стало понятно, что нужен какой-то специализированный инструмент, более заточенный под нашу задачу.

В принципе, подойдёт любая программа для захвата видео с экрана, типа навороченной OBS Studio или более простой SimpleScreenRecorder (SSR). Любопытно, что популярный медиаплеер VLC тоже умеет записывать видео с экрана.


SimpleScreenRecorder используют для записи не только видео, но и разговоров в мессенджерах. Например, запись рабочей планёрки можно прослушать позже в удобное для себя время и на удобной скорости

Минималистичный вариант для маленьких скринкастов — Peek.


Peek

Можно вспомнить ещё Gifine. Да, такой софт отлично справляется с записью красивых скринкастов под Linux. Но это не самый оптимальный вариант именно для консоли, потому что такие программы не оптимизированы для записи конкретно текста. Они записывают полноценное видео. Файлы получаются большими по размеру, а процесс записи/конвертирования иногда нагружает CPU не меньше, чем наш допотопный скрипт с ImageMagick.

Так что для консоли лучше взять специальный инструмент.

Запись псевдотерминала


Пользователи Linux наверняка знакомы с командами screen, script и ttyrec. Они обе используют одну и ту же функцию Unix: псевдотерминал (PTY) для записи и последующего воспроизведения сессий.

Псевдотерминал — это пара псевдоустройств (slave и master). Первое эмулирует консоль, а второе предоставляет средства управления. Псевдотерминалы дают программам возможность действовать в качестве посредника между пользователем, дисплеем и оболочкой. Это позволяет прозрачно перехватывать ввод пользователя (клавиатура) и вывод в терминал (дисплей). Команда screen использует её для перехвата специальных комбинаций клавиш, таких как Ctrl-A, и изменения вывода для отображения оконных id и других сообщений.


Использование псевдотерминала командой script

Поэтому для записи консольных сессий под Linux было бы логично использовать PTY как нативную функцию этой операционной системы, что и делают программы такого типа. Среди них устаревшая ttyrec и ряд инструментов на её основе — это Ttyrec2gif, Seq2gif, Recterm и другие. Но их вряд ли стоит использовать на современных системах по причине некоторых ограничений легаси. Например, поддержка терминалов только 80×24.

Рекордеры консоли нового поколения используют более современный стек: например, Ttystudio, ShowTerm, TermRecord, Terminal-Recorder и Asciinema.

Asciinema


Asciinema сохраняет вывод PTY в памяти вместе с метками времени, включая весь текст и невидимые escape/control последовательности в исходном виде. По окончании записи сохраняется файл в формате asciicast. Он же по умолчанию публикуется в открытом доступе на сайте asciinema.org. Там скринкасты доступны по стандартному URL типа asciinema.org/a/20055. Конечно, дефолтные настройки можно изменить.

Для просмотра используется интегрированный плеер asciinema-player. Во время просмотра такой скринкаст можно поставить на паузу, скопипастить текст, а затем запустить дальше.

Установка и использование Asciinema максимально просты. Установка:

brew install asciinema

Если планируете отправлять скринкасты на сервер, нужно пройти аутентификацию:

asciinema auth
Open the following URL in a browser to register your API token and assign any recorded asciicasts to your profile:
https://asciinema.org/connect/1d80abbc-22fc-19a0-b1a1-a3b69cfa0d0a

Старт записи:

asciinema rec --stdin

После этого записываются все наши действия в консоли, а также дополнительно все нажатия клавиш на клавиатуре (опция --stdin). По окончании записи набираем exit или жмём Ctrl-D.

По умолчанию скринкаст заливается на сервер, прописанный в настройках (например, asciinema.org). Чтобы этого избежать, нужно запускать запись с указанием файла:

asciinema rec [filename]

Впоследствии запись можно залить на сервер вручную:

asciinema upload asciicast.json

Недостаток собственного формата в том, что его не выложишь в открытый доступ, как гифку, а для просмотра требуется отдельный плеер.

Но зато плеер очень маленький, так что asciinema player легко интегрировать в любое приложение как модуль из пакета npm. Ну или интегрировать на сайт, как это сделано на бесплатном хостинге скринкастов asciinema.org.

Просто берём плеер asciinema-player.min.js и загружаем в него записанный скринкаст. В нашем случае это 20055.json:

<head>
<link rel="stylesheet" type="text/css" href="asciinema-player.css" />
</head>
<body>
<div id="player"></div>
<script src="asciinema-player.min.js"></script>
<script>
AsciinemaPlayer.create(
'20055.json',
document.getElementById('player'),
{ cols: 80, rows: 24 }
);
</script>

С точки зрения посетителя, интегрированный плеер выглядит так:



Вот этот конкретный 38,907319-секундный скринкаст 20055.json с псевдографикой Python весит 2,091 МБ. Для сравнения, гифка с его записью получилась на 2,665 МБ.

Но текстовый JSON при желании можно сжать ещё в несколько раз без потери информации, а гифку — уже нельзя (по сути, вся текстовая информация из терминала была утеряна при переводе в графический формат).

И самое главное, что из скринкаста легко скопировать любой текст, в том числе вводимые команды и результат их выполнения. Скажем, вот скринкаст 139514.json с брутфорсом газетной головоломки про рельсы. Останавливаем его на 00:11 — и просто копируем консоль в текстовом виде:

Puzzle: 54-14343245-14134544-48EW.53NE
1 4 1 3 4 5 4 4 1 4 1 3 4 5 4 4
┌─┬─┬─┬─┬─┬─┬─┬─┐ ┌─┬─┬─┬─┬─┬─┬─┬─┐
8 │ │ │ │━│ │ │ │ │ 5 8 │ │┏│━│━│┓│ │ │ │ 5
├─┼─┼─┼─┼─┼─┼─┼─┤ ├─┼─┼─┼─┼─┼─┼─┼─┤
7 │ │ │ │ │ │ │ │ │ 4 7 │ │┃│ │ │┗│━│┓│ │ 4
├─┼─┼─┼─┼─┼─┼─┼─┤ ├─┼─┼─┼─┼─┼─┼─┼─┤
6 │ │ │ │ │ │ │ │ │ 2 6 │ │┃│ │ │ │ │┃│ │ 2
├─┼─┼─┼─┼─┼─┼─┼─┤ ├─┼─┼─┼─┼─┼─┼─┼─┤
A │━│ │ │ │ │ │ │ │ 3 A │━│┛│ │ │ │ │┃│ │ 3
├─┼─┼─┼─┼─┼─┼─┼─┤ ├─┼─┼─┼─┼─┼─┼─┼─┤
4 │ │ │ │ │ │ │ │ │ 4 4 │ │ │ │ │┏│━│┛│ │ 4
├─┼─┼─┼─┼─┼─┼─┼─┤ ├─┼─┼─┼─┼─┼─┼─┼─┤
3 │ │ │ │ │┗│ │ │ │ 3 3 │ │ │ │ │┗│ │ │ │ 3
├─┼─┼─┼─┼─┼─┼─┼─┤ ├─┼─┼─┼─┼─┼─┼─┼─┤
2 │ │ │ │ │ │ │ │ │ 4 2 │ │ │ │ │ │ │ │ │ 4
├─┼─┼─┼─┼─┼─┼─┼─┤ ├─┼─┼─┼─┼─┼─┼─┼─┤
1 │ │ │ │┃│ │ │ │ │ 1 1 │ │ │ │┃│ │ │ │ │ 1
└─┴─┴─┴─┴─┴─┴─┴─┘ └─┴─┴─┴─┴─┴─┴─┴─┘
1 2 3 B 5 6 7 8 1 2 3 B 5 6 7 8

Такого не может сделать ни одна программа для видеозаписи экрана.

Asciinema работает в Linux, macOS и *BSD.

Ускорение в 50 раз


Разработкой программы с 2012 года занимается польский разработчик Мартин Кулик. Недавно он неожиданно переписал программу с нуля на JavaScript и Rust (компилируется в WASM), отказавшись от любимого ClojureScript. В результате размер бандла JS уменьшился вчетверо с 570 до 140 КБ, а интерпретатор виртуальной консоли стал работать в 50 раз (!) быстрее.

Сам Мартин приводит такие цифры (в Chrome 88): в старом плеере эмулятор терминала обрабатывал 0,3–0,8 мегабайта текста в секунду, а в новой версии обрабатывает 24–37 МБ, то есть налицо ускорение в 45–73 раза.

Речь идёт о парсинге текстового потока в виртуальной консоли, включая управляющие команды, а также управление виртуальным экранным буфером, который был узким местом в пропускной способности предыдущей версии плеера. Интерпретатор преобразует этот поток в графику на экране.

Дополнительное ускорение интерфейса получено за счёт перехода с React.js на SolidJS, одну из самых быстрых библиотек UI на сегодняшний день.

Если подвести итог, то по набору функций у Asciinema практически нет конкурентов среди всех программ для записи скринкастов из консоли. Это вообще уникальный инструмент, который позволяет сохранять скринкасты практически в текстовом виде, то есть в минимальном размере. Для воспроизведения используется собственный плеер с интерпретатором виртуального терминала, написанный на Rust.

Скринкасты под Windows


Хотя мы рассматриваем в основном скринкасты под Linux, но у разработчиков под Windows тоже есть удобные инструменты для записи скринкастов gif. Таких программ немало. Можно вспомнить великолепную программу ShareX, а также GifCam, Gif Screen Recorder, ScreenToGif, LICEcap, InstaGiffer и другие.



Но чтобы программа создавалась конкретно для записи текстовой консоли — такого под Windows, кажется, ещё не делали. Впрочем, в последних версиях Win11 уже можно пробовать запускать полноценное окружение Linux и все привычные инструменты, включая ту же Asciinema.

Если совсем не хочется ничего устанавливать, то можно записать маленький скринкаст прямо из браузера, в онлайн-редакторах вроде FlexClip или Online Screen Recorder.


FlexClip

Только нужен нормальный браузер с поддержкой некоторых стандартов HTML5.
А каким инструментом пользуетесь вы и пользуетесь ли вообще?

НЛО прилетело и оставило здесь промокоды для читателей нашего блога:

15% на все тарифы VDS (кроме тарифа Прогрев) — HABRFIRSTVDS.

20% на выделенные серверы AMD Ryzen и Intel Core HABRFIRSTDEDIC.

Комментарии (8)


  1. ivan386
    07.02.2022 11:26
    +4

    Теоритически для показа можно использовать формат SVG с анимацией. В нём так-же текст может оставаться текстом.


  1. drWhy
    07.02.2022 11:33
    +2

    Для скринкастов терминалов и gui без фотореалистичных изображений png подходит лучше, чем gif — степень сжатия будет лучше, при том что изображение останется исходным и не будет артефактов в виде точек, возникающих из-за оптимизации палитры. Желательно, чтобы промежуточный формат сжатия также был без потерь, а лучше обойтись вовсе без него.

    К сжатию выхлопа терминала вероятно как-то можно приспособить компрессор NNCP Фабриса Беллара.


  1. vaniacer
    07.02.2022 11:37
    +4

    Использовал asciinema для своих проектов:
    piu-piu https://asciinema.org/a/DDLzQOgSrqVa3yS6zBoc37rhj
    и
    sshto https://asciinema.org/a/PQMuRvfmxlHUc4oZMN76LY2V4
    Для sshto подошло идеально, для piu-piu не очень т.к. из-за массивного вывода текста в терминал файл очень быстро растет, а ограничение на размер файла у asciinema 2Mb если мне не изменяет память.


    1. namikiri
      07.02.2022 12:02
      +1

      Первый проект знатно повеселил и напомнил ROFLCopter


  1. Oriolidae
    07.02.2022 14:39

    LICEcap понравился.. скринкасты для документаций или баг репортов


  1. saboteur_kiev
    07.02.2022 17:48
    +1

    Отлично, нарисовал видеодемку к своему скрипту https://asciinema.org/a/SORBcJ1hndJ9QluGa5FVnoPHl

    Я как-то думал, что такое должно быть, но все было лень погуглить, а тут прямо все расписано по полочкам.


  1. Crimento
    08.02.2022 15:06
    +1

    Скринкастами не приходилось, а вот для псевдоскринов из терминала очень нравится ray.so, выглядит очень красиво.


  1. 0xd34df00d
    09.02.2022 08:22
    +1

    С asciinema лично у меня проблема была в том, что он как-то криво записывал цветовую тему в neovim, и результат выглядел исключительно вырвиглазно. В итоге мой выбор — ffmpeg-запись в lossless с последующим созданием h264- и av1-вариантов.


    Заодно не требует js на сайте.