Не так давно обсуждали с коллегами разницу между возможностями command-line в Windows и Linux. Мне кажется так и не удалось донести мысль, что тот же powershell не смотря наличие нескольких хороших идей в большинстве своём остаётся для повседневных задач неудобным, неповоротливым монстром. И что пресловутый UNIX-way, с сотнями утилит на все случаи жизни гораздо практичнее и функциональнее. Сотни тысяч приложений, написанных в стиле максимальной конфигурируемости, позволяют как из кубиков собирать нужное и максимально удобное для себя родимого. Для иллюстрации подхода, попробую на примере записи скринкастов в GIF, показать насколько удобно можно собирать эти кубики.
Итак, хочется простого: возможности записи окна или выделенного региона в GIF, причём прерывать запись нужно по горячей клавише, что бы в конце не записывать как курсор идёт в трей и выключает запись. Ну и хочется, что бы результат складывался в нужную директорию с уникальным именем, а путь к нему копировался в буфер обмена. Ну и что бы работало мгновенно и без ненужных окошек. Вроде все желания понятные, а готового приложения ни под Windows, ни под Linux я не нашёл.
Ну что же, попробуем реализовать все хотелки сами. Для записи будем использовать шустрый byzanz, вряд ли он будет в дефолтной поставке, поэтому установим его:
Если посмотреть документацию byzanz-record, то видно, что сам по себе он не умеет ни создавать уникальный файл для сохранения, ни выбирать область для записи, зато всё можно передать через command-line, вплоть до такой мелочи - как записывать курсор мыши или нет (о чем готовые комбайны для скринкастов почему-то часто забывают). Например запись 5 сек в GIF без курсора делается вот так:
Идём дальше, что-бы каждый новый файл не перезаписывал предыдущий, добавим timestamp в имя файла, что бы получить путь вроде такого "~/tmp/image-2015-12-12T12-12-12.gif":
Что бы можно было выбирать окно, которое будем записывать, воспользуемся утилитой xwininfo из поставки xorg и создадим скрипт:
После вызова этого скрипта, курсор мыши изменится на "прицел", предлагая выбрать какое окно нужно записывать, после выбора мы получим его координаты и передадим в byzanz.
Теперь разберёмся с произвольным времени записи. Просто задать большой duration и потом принудительно завершать byzanz нельзя, т.к. он не запишет GIF до конца и последний не везде будет корректно воспроизводиться. Но если внимательно посмотреть на документацию, то там можно найти опцию:
Отлично, заставим byzanz запустить другое приложение и когда мы его прибьём, запись завершится, а GIF файл успешно допишется до конца. При этом нужно гарантировать, что если завершить запись мы по какой-то причине забыли, что бы не забивать диск, она должна сама закончится допустим через 5 минут (для моих нужд этого хватит с лихвой). Тут на помощь прийдет утилита "sleep", теперь строчка запуска будет выглядеть в скрипте вот так:
Теперь завершить запись можно простой командой "pkill sleep", т.к. я пользуюсь awesome, то мне не составит труда добавить горячую клавишу выполняющую эту команду, прописав в конфиг:
Ну и в качестве "изюминки" добавим нотификацию на экране о завершении записи (вдруг промахнусь с горячей клавишей завершения), а так же не забудем копирование пути к файлу в буфер обмена. Добавим в конец скрипта:
Итого конечный вариант выглядит вот так.
Для того, что бы записывать не всё окно, а какой-то регион, понадобится ещё одна небольшая утилита xrectsel:
Ну а дальше, всё как и раньше, конечный скрипт можно найти тут.
Для запуска приложений я пользуюсь rofi поэтому мне вышеописанный скрипты некуда прописывать не нужно, достаточно подложить в один из PATH путей.
Итого: я написал 2 скрипта общей длинной в 20 строк, добавил 1 строчку в конфиг и установил 2 небольшие утилиты. По времени - я писал скрипт сильно меньше, чем потратил на попытки найти уже готовое решение с такими свойствами. Причём получившиеся скрипты у меня теперь сохранены на GitHub, необходимые пакеты там же и в случае чего я восстановлю всё это в пару команд.
Что характерно на powershell вышеописанное частично можно реализовать, но с гораздо большими усилиями, а частично не реализуется вообще, без вкорячивания туда пары страниц кода на C#, ну а про возможность установить необходимые приложения из командной строки и говорить не буду.
Итак, хочется простого: возможности записи окна или выделенного региона в GIF, причём прерывать запись нужно по горячей клавише, что бы в конце не записывать как курсор идёт в трей и выключает запись. Ну и хочется, что бы результат складывался в нужную директорию с уникальным именем, а путь к нему копировался в буфер обмена. Ну и что бы работало мгновенно и без ненужных окошек. Вроде все желания понятные, а готового приложения ни под Windows, ни под Linux я не нашёл.
Ну что же, попробуем реализовать все хотелки сами. Для записи будем использовать шустрый byzanz, вряд ли он будет в дефолтной поставке, поэтому установим его:
yaourt -S byzanz
byzanz-record --cursor=false --duration=5 ~/tmp/image.gif
byzanz-record --cursor=false --duration=5 ~/tmp/image-$(date +%FT%H-%M-%S).gif
#!/bin/bash xwininfo=$(xwininfo -shape) getnum() { echo "$xwininfo" | grep "$1" | tr -cd [:digit:] } x=$(getnum "Absolute upper-left X:") y=$(getnum "Absolute upper-left Y:") w=$(getnum "Width:") h=$(getnum "Height:") path=~/tmp/image-$(date +%FT%H-%M-%S).gif byzanz-record --cursor=false --duration=5 --x=$x --y=$y --width=$w --height=$h $path
Теперь разберёмся с произвольным времени записи. Просто задать большой duration и потом принудительно завершать byzanz нельзя, т.к. он не запишет GIF до конца и последний не везде будет корректно воспроизводиться. Но если внимательно посмотреть на документацию, то там можно найти опцию:
-e, --exec=COMMAND Instead of specifying the duration of the animation, execute the given COMMAND and record until the command exits. This is useful both for benchmarking and to use more complex ways to stop the recording, like writing scripts that listen on dbus.
... byzanz-record --cursor=false --exec="sleep 5m" --x=$x --y=$y --width=$w --height=$h $path
awful.key({ modkey, "Shift" }, "e", function () awful.util.spawn("pkill sleep") end),
... printf $path | xsel -ib notify-send -u 'normal' 'Screencast-window' 'Finish'
Для того, что бы записывать не всё окно, а какой-то регион, понадобится ещё одна небольшая утилита xrectsel:
yaourt -S xrectsel
Для запуска приложений я пользуюсь rofi поэтому мне вышеописанный скрипты некуда прописывать не нужно, достаточно подложить в один из PATH путей.
Итого: я написал 2 скрипта общей длинной в 20 строк, добавил 1 строчку в конфиг и установил 2 небольшие утилиты. По времени - я писал скрипт сильно меньше, чем потратил на попытки найти уже готовое решение с такими свойствами. Причём получившиеся скрипты у меня теперь сохранены на GitHub, необходимые пакеты там же и в случае чего я восстановлю всё это в пару команд.
Что характерно на powershell вышеописанное частично можно реализовать, но с гораздо большими усилиями, а частично не реализуется вообще, без вкорячивания туда пары страниц кода на C#, ну а про возможность установить необходимые приложения из командной строки и говорить не буду.
О, мысль про выключение записи по клавише мне нравится, как-то не пришло в голову.
ОтветитьУдалитьА то я ж простой убунтоид, взял аналогичный скриптик отсюда http://askubuntu.com/a/201018 и немного мучаюсь с тем, что время записи надо указывать наперед - не всегда удобно.
Я собственно по мотивам тех скриптов и делал, добавив туда немного удобства для себя.
Удалить