Скринкасты терминала. Запись действий в консоли Linux

image-loader.svg
Копипаст из чужой консоли

Скринкаст консольной сессии в маленьком анимированном 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 тоже умеет записывать видео с экрана.

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

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

image-loader.svg
Peek

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

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

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


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

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

image-loader.svg
Использование псевдотерминала командой 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:






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

image-loader.svg

Вот этот конкретный 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 и другие.

image-loader.svg

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

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

image-loader.svg
FlexClip

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

А каким инструментом пользуетесь вы и пользуетесь ли вообще?

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

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

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

© Habrahabr.ru