Велосипед на таймлайне

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


Под катом рассказал о своем непростом пути к записи и редактированию видео с помощью свободного ПО, скриптинга на Ruby и подручных средств.


Теория


Начал я с изучения теории о записи видеоблогов по англоязычным YouTube-роликам. А из русскоязычных материалов — довольно полезным оказался вот этот курс (в частности модуль про видеоблог и первое видео о построении кадра из модуля про репортаж). Также бегло ознакомился с популярными фичами проприетарных видеоредакторов, чтобы более осознанно подойти к выбору свободного редактора.


В свет не рискнул вкладываться: не хватает времени на его изучение и поиск оптимального варианта, а поверхностное изучение дешевых вариантов говорит о потенциальных граблях вроде мерцания и плохой цветопередачи. С дневным светом у меня не возникло больших трудностей, его хватает как раз на короткие ролики.


Видеоредактор


Существующие свободные инструменты видеомонтажа содержат ряд известных проблем: от неудачных решений в UI и подвисаний, превращающих редактирование в бесконечность, до утечек памяти, падений и неожиданных артефактов, которые появляются только после финального рендеринга.


Проблем очень много и потребовалось время на то, чтобы выбрать видеоредактор и изучить его баги, чтобы просто научиться справляться с базовыми вещами. В конечном счете остановился на Pitivi, просто потому что времени и так много потратил на поиски и эксперименты.


Звук из Flatpak


Поддерживаемый способ установки Pitivi требует Flatpak. Какое-то время я обходил его стороной, т.к. у меня в системе нет systemd и PulseAudio.


Оказывается systemd давно не требуется. Ну а PulseAudio — пришлось поставить и настроить было проще модифицировать Flatpak. Но правильней было бы поставить PulseAudio, просто это несколько нудно и непонятно стоит ли ожидать от него проблем с записью звука на имеющемся железе или нет.


Устанавливаем Pitivi, удаляем конфиги PulseAudio, запускаем:


$ sudo flatpak remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo
$ sudo flatpak install flathub org.pitivi.Pitivi
$ sudo find {/var/lib,~/.local/share}/flatpak/runtime -type f -name '*pulseaudio*.conf' -delete
$ flatpak run --device=alsa --branch=stable --arch=x86_64 --command=pitivi org.pitivi.Pitivi

Звука нет. Попробуем запустить что-нибудь попроще, например aplay:


$ sudo find /var/lib/flatpak/app/org.pitivi.Pitivi/x86_64 -type d -path '*/files/bin' -exec cp `which aplay` {} \;
$ flatpak run --device=alsa --branch=stable --arch=x86_64 --command=aplay org.pitivi.Pitivi /dev/urandom
ALSA lib dlmisc.c:162:(snd_dlsym_verify) unable to verify version for symbol _snd_pcm_empty_open                              
ALSA lib dlmisc.c:283:(snd1_dlobj_cache_get) symbol _snd_pcm_empty_open is not defined inside [builtin]                       
aplay: main:828: audio open error: No such device or address

Вероятно alsa-lib, входящий во Flatpak, был собран с --with-versioned. Быстрое решение — заменить libasound.so системным:


sudo find /var/lib/flatpak -type f -name libasound.so.2.0.0 -exec cp /usr/lib64/libasound.so.2.0.0 {} \;
find ~/.local/share/flatpak -type f -name libasound.so.2.0.0 -exec cp /usr/lib64/libasound.so.2.0.0 {} \; # если устанавливали от прав пользователя что-то

Для меня и этого оказалось недостаточно:


$ flatpak run --device=alsa --branch=stable --arch=x86_64 --command=aplay org.pitivi.Pitivi /dev/urandom
ALSA lib /var/tmp/portage/media-libs/alsa-lib-1.1.6-r1/work/alsa-lib-1.1.6/src/pcm/pcm_direct.c:1943:(snd1_pcm_direct_parse_open_conf) The field ipc_gid must be a valid group (create group audio)
aplay: main:828: audio open error: Invalid argument

Нужен еще конфиг ALSA:


$ sudo find /var/lib/flatpak -type d -name etc -exec cp /etc/asound.conf {} \;
$ find ~/.local/share/flatpak -type d -name etc -exec cp /etc/asound.conf {} \; # если устанавливали от прав пользователя что-то
$ flatpak run --device=alsa --branch=stable --arch=x86_64 --command=aplay org.pitivi.Pitivi /dev/urandom

Наконец-то можно использовать Pitivi.


Настройки рендеринга для Pitivi, к которым пришел в результате
  • container format: MP4
  • video
    • codec x264enc
    • advanced
      • encoding pass/type: constant quantizer
      • constant quantizer: 18
      • bitrate: 16384 kbit/s
      • speed quality preset: ultrafast
      • psychovisual tuning preset: film
  • audio
    • libav ALAC
  • на свой риск и страх использую «Never render from proxy files»
  • всё остальное — по умолчанию

Другие эффекты


Некоторые анимационные эффекты для текста я делаю с помощью скринкаста открытых на весь экран страниц, сверстанных с использованием reveal.js и animate.css. В reveal.js для некоторых слайдов добавляю звук перехода:


<section style="font-size: 5em">
  <audio data-autoplay src="/path/to/sound.wav"></audio>
  #1
</section>

Оказалось важно записывать скринкаст с 60 FPS, если текст очень большой. Скринкаст делаю так:


#!/bin/sh

SOUND_INPUT=shared_input_loopback
CHANNELS=2
SOUND_RATE=48000
FRAMERATE=60

DRAW_MOUSE=0
VIDEO_SIZE=$(xdpyinfo | awk '/dimensions:/ { print $2; exit }')
OUTPUT="${HOME}/video/screen/$(date --rfc-3339=seconds).mp4"

ffmpeg     -thread_queue_size 512     -video_size "${VIDEO_SIZE}"     -framerate "${FRAMERATE}"     -f x11grab     -draw_mouse "${DRAW_MOUSE}"     -i :0.0+0,0     -thread_queue_size 512     -f alsa     -ac "${CHANNELS}"     -i "${SOUND_INPUT}"      -ar "${SOUND_RATE}"     -vcodec libx264 -preset ultrafast -crf 18     -acodec alac     -f ipod     "${OUTPUT}"

В моем случае shared_input_loopback — это устройство из конфига asound.conf.


Еще вот эта надстройка над ffmpeg для переходов между клипами, оказалась полезной.


Запись видео


Под рукой оказался телефон Meizu MX4, на котором я решил использовать фронтальную камеру и записываться с помощью Open Camera. Потребовалось некоторое время, чтобы натренировать себя смотреть в камеру и контролировать своё положение в пространстве, не делая типичных ошибок, вроде обрезания головы. При этом говорить достаточно четко, громко, жестикулировать и генерировать хоть какую-то мимику. Но это было только начало.


Что же побудило меня сделать автоматическую нарезку видео, да еще и на этапе записи?


  1. Тормоза и баги Pitivi при редактировании, в особенности при использовании инструмента Ripple Move/Edit, приводящие к необходимости периодического перезапуска Pitivi.
  2. Конкретно для меня процесс ручной нарезки видео — это одна из наиболее скучных вещей. Понятно, что полностью автоматизировать это не очень-то возможно (по крайней мере без сценария, в котором явно не указаны паузы, необходимые для осознания сказанного), но хотя бы оптимизировать этот процесс можно.

Вот какие требования к будущему велосипеду я себе поставил:


  1. Запись видео с помощью Android-телефона, а звука — с помощью ноутбука.
  2. Управление фокусом камеры.
  3. Возможность остановить запись, чтобы сохранить или удалить последний записанный фрагмент.
  4. Скачивание видео с телефона через USB, с повторными попытками и докачкой, без блокирования возможности записывать следующий фрагмент.
  5. Синхронизация звука.
  6. Определение наличия голоса и выкидывание пауз.
  7. Возможность быстро проиграть последние записанные фрагменты видео, с уже выкинутыми паузами.

Зачем столько контроля над устройствами на этапе записи? Почему бы просто не запустить запись на несколько часов подряд, а уж потом редактировать? Причин много:


  1. Банальный недостаток места на дисках.
  2. Склонность телефона перегреваться и быстро разряжаться при длительной записи.
  3. Неисправность сенсорного экрана из-за того, что телефон побывал в воде. А управлять фокусом как-то надо. Да и очередное нажатие создавало бы ненужную вибрацию устройства.
  4. Проблемы с перекидыванием больших файлов из-за плохого питания USB-портов на моем ноутбуке. В теории это решаемо с помощью USB-хаба с дополнительным питанием. Использовать сеть — слишком медленное решение.
  5. Желание быстро пересмотреть последние записанные фрагменты, чтобы убедиться в отсутствии ошибок и оперативно перезаписать, пока планета не повернулась не тем местом перед солнцем.
  6. Желание выкидывать явно плохие дубли как можно раньше, чтобы не тратить на них время и место на диске в будущем.
  7. Необходимость синхронизировать длинные аудио, записанные телефоном и ноутбуком. Тут может возникнуть рассинхронизация с видео из-за того, что фреймы аудиопотоков выбрасываются как при записи с ноутбука, так и при записи с телефона (что наверняка можно как-то решить, но не хочется рисковать и тратить время на эксперименты). Проще синхронизировать мелкие фрагменты по отдельности, тогда возможная рассинхронизация не будет заметна.
  8. Необходимость обрабатывать ситуацию, когда Open Camera перезапускает запись из-за достижения размера видео 4 GiB. Вероятно пришлось бы модифицировать Open Camera. Если это ограничение на 4 GiB невозможно убрать или увеличить — пришлось бы кидаться событием в ноутбук, чтобы тот пометил, что в этом месте произошел перезапуск записи.

Проще записываться небольшими фрагментами и сделать примитивную автоматизацию всего что можно. В качестве основного языка для разработки велосипеда выбрал Ruby. На самом деле сейчас я бы, вероятно, выбрал Python, но на тот момент я как раз изучал Ruby, а новые для меня языки я обкатываю на таких вот странных экспериментах.


Автоматическая нарезка видео


Информации в сети на эту тему не очень много. Про исследование Stanford и Adobe поздно вспомнил (что не страшно, мне всё равно менее навороченное решение нужно).


Нарезка происходит в 2 этапа: на этапе записи — грубая, на этапе рендеринга — более точная, с возможностью вручную подкорректировать слишком сильно обрезанные фрагменты. Грубая реализована с помощью VAD из WebRTC. Более точная — с помощью Google Speech (если конкретней — с помощью модификации проекта autosub, для генерирования субтитров к видео). Уверен что найдутся и более удачные решения, просто это оказалось лучшим из того, что удалось сделать быстро.


Если хотите разработать что-то подобное с использованием ffmpeg — придерживайтесь принципа не пытаться сделать слишком много за один вызов ffmpeg. Делайте промежуточные файлы и контролируйте каждый шаг, чтобы потом не заниматься поиском странных негугливаемых багов, вроде неправильного разрезания или непримененного эффекта.


Запускаю я получившееся безобразие как-то так:


$ bin/vlog-recorder     --project /path/to/project     --debug true     --sound-settings ' --device=usb_card --format=dat' # аргументы к arecord

r - (RE)START recording
s - STOP and SAVE current clip
S - STOP and SAVE current clip, don't use auto trimming
d - STOP and DELETE current clip
p - PLAY last saved clip
f - FOCUS camera on center
h - show HELP
q / Ctrl+C - QUIT

[ stopped ] [ battery: 100% / 36°C ]

Аргументы к arecord мне нужны, чтобы явно указать устройство, дабы избежать периодических глюков, которые скорее всего происходят из-за ALSA-вского плагина dsnoop. Можно еще лог открыть, чтобы контролировать процесс скачивания файлов с телефона: tail -f /path/to/project/log.txt.


Быстро срендерить в одно видео для предпросмотра, можно так:


$ bin/vlog-render     --project /path/to/project     --language ru     --video-filters 'hqdn3d,hflip,curves=psfile=/path/to/curves.acv,vignette'     --speed 1.3     --fps 60     --preview true

Аргумент --video-filters — это фильтры, передаваемые в ffmpeg. Видео автоматически откроется в плеере mpv.


Можно также поменять местами или выкинуть оставшиеся ненужные дубли редактированием появившегося файла /path/to/project/render.conf, которые можно обнаружить благодаря распознанному голосу. Идея, кстати, не новая. Там же можно ускорить отдельные фрагменты и подредактировать неудачные разрезания видео, если такие есть. В следующий раз vlog-render перечитает render.conf и применит изменения.


Чтобы подготовить фрагменты для видеоредактора — нужно указать --preview false. Помимо фрагментов, которые будут лежать в output, он всё же объединит их в один файл output.mp4, потому что изначально я был не уверен:


  • буду ли я использовать мелкие клипы в Pitivi
  • или загружу одно длинное видео для дальнейшей нарезки (чтобы можно было применить ряд эффектов к «группе» клипов).

В основном использую первый вариант. Второй был полезен в одном видео с плохим светом: там я использовал лишь кусок output.mp4. Для второго варианта также может быть полезен скрипт vlog-play-segments: с помощью него можно быстро посмотреть все паузы между клипами в порядке убывания длительности. Это поможет более точно подредактировать render.conf и сэкономить потом время на редактировании этого длинного куска видео в Pitivi.


Получившиеся мелкие клипы можно загрузить одним разом на таймлайн в Pitivi: выделяем все импортированные клипы и тащим с помощью drag-n-drop.


Крепление для телефона


Заниматься поисками подходящей подставки под телефон не хотелось, да и руки уже чесались записать хоть что-нибудь. Берем попавшийся под руку кусок картона и вырезаем крепление для телефона под свои нужды:


Крепление для телефона

Подставка крепится на дисплей ноутбука, чтобы минимализировать расстояние между сценарием и камерой.


Запись звука


Приемлемый звук очень критичен. Под рукой оказался микрофон Boya BY-M1. Хоть его и рекламируют как всенаправленный микрофон, хороший звук на практике получается только когда используешь его как однонаправленный.


Стойку для микрофона сделать еще проще: берем попавшуюся под руку бутылку от гранатового сока, рулон скотча и собираем этот конструктор воедино:


Стойка для микрофона

Можно еще полотенце подложить под эту конструкцию, чтобы подавить часть вибраций от стола и заодно отрегулировать высоту.


Звуковая карта


В моем случае это ASUS Xonar U3. Оказалось, правда, что она не совместима с таким микрофоном: у микрофона штекер CTIA, рассчитанный на телефоны. Проблема решилась переходником в штекеры TRS для микрофона и наушников. И найти его было непросто: производители таких переходников редко пишут детали. В моем случае помог некий Cablexpert CCA-418W.


Еще одна проблема этой карты — в DC offset в правом канале при записи. Что никак не мешает, т.к. записываюсь я все равно в моно. А для софта, который не позволяет выставить моно сделал перенаправление хорошего канала в плохой, средствами ALSA.


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


Обработка звука


Звук редактирую в наушниках (в моем случае это Pioneer SE-M390), на громкости выше чем та, на которой обычно слушаю музыку. Алгоритм примерно такой:


  1. С помощью Pitivi рендерю отдельно звук (с использованием всё тех же ALAC и MP4). Зачастую делаю несколько отдельных дорожек, выбирая конкретные слои в Pitivi и временно удаляя ненужные.
  2. Если полученные файлы сразу же загрузить в Audacity — мы потеряем растяжения/сжатия аудиопотока, которые потом могут привести к рассинхронизации видео и аудио. Что неочевидно, это происходит не со всеми видео. Чтобы этого не случилось — просто применяем эти растяжения/сжатия: ffmpeg -async 1 -i input.mp4 output.flac
  3. Загружаем все дорожки в Audacity. Добавляем фоновую музыку, если нужно.
  4. Для всех дорожек устанавливаем желаемую громкость с помощью Gain.
  5. К дорожке с голосом применяем эффекты Noise Reduction (в моем случае двойной), Compressor, Equalization, Normalize по советам из этого видео.
  6. Выравниваем громкость у дорожки с голосом. Один из классических способов — это Amplify, Limiter и снова Normalize, однако таким подходом мне пока не удалось получить желаемое качество звука. Временно поступаю так: сначала делаю Gain всей дорожке так, чтобы наиболее громкая часть звучала без перегрузок, а далее вручную пытаюсь выровнить громкость на всей дорожке, с помощью применения Amplify для отдельных фрагментов.
  7. Микрофон иногда записывает звук с некими дефектами, которые похожи на щелчки. Их можно удалить с помощью эффекта Spectral edit multi tool. Чаще всего его приходится применять несколько раз подряд для выделенной области, с помощью Ctrl+R.
  8. Экспортируем из Audacity во FLAC и объединяем всё в один файл: ffmpeg -i sound.flac -an -i video.mp4 -c copy output.mkv
  9. По крайней мере первое видео я проверял на разных громкостях и разных устройствах.

Результат


Пользуясь случаем ослабления гаек в правилах, приглашаю посетить получившийся канал на YouTube, где я делюсь инсайтами об эффективном изучении программирования и смежных дисциплин.


Удачи в разработке программ и создании видеоблогов!

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


  1. Dene
    29.01.2019 14:39

    Я долго не мог понять, что меня смущает в видео. Качество ок, и в целом подача — тоже. Понравилось, но что-то неуловимо не давало покоя. Потом понял — обрезаются паузы с морганием. Вот этот неморгающий взгляд и оказался тем, что смущает. :) Не думаю, что нужно править в этом плане что-то. Просто интересное наблюдение.


  1. lmike
    29.01.2019 16:26

    Для сборки видео (но не для видео блога) использовал OpenShot, из свободного ПО.
    Из бесплатного очень понравился Davinci resolve, но для него нужно «готовить» видео/аудио и проприетарный драйвер
    Как-то (давно) смотрел Pitivi, глючал он


    1. alopatindev Автор
      29.01.2019 17:13

      У меня чесались руки попробовать проприетарные видеоредакторы (конкретней — DaVinci Resolve и Lightworks), но пока не удалось запустить их на моей машине: все загадочно падают при старте.


      1. lmike
        29.01.2019 18:08
        +1

        но пока не удалось запустить их на моей машине: все загадочно падают при старте
        без проприетарных дров так и будет.
        Для давинчи нужен OpenCl, дополнительно — инсталяция не учитывает «отсутствия» некоторых либ (нужно прописывать линки).
        «Сложности» будут и с поддерживаемыми форматами аудио/видео (DaVinci Resolve и Lightworks).
        Lightworks мне откровенно не понравился с т.з. интерфейса
        DaVinci Resolve очень мощный инструмент, легко искать обучающие материалы, для меня интерфейс показался интуитивным, там можно и со звуком манипуляции проделывать различные.
        Перекодирую (для него) чере ffmpeg:
        ffmpeg -i $1 -c:v dnxhd -profile:v dnxhr_sq  -acodec:0 pcm_s16le -f mov $1.mov


  1. Shtucer
    29.01.2019 18:22

    Две склейки в секунду? Это отвратительно. Более продуктивно было бы перечитать текст. Спикер должен быть живым человеком. Все эти вдохи-выдохи, придыхания вырезать не нужно. Если же слова-паразиты и прочие "ээээ" и "мээээ" создают проблемы при записи речи, есть два пути:


    1. Олд-скул. Работать над речью. Возможно даже с помощью специального человека. Это хороший путь, поскольку навык бегло и внятно говорить пригодится не только видео-блогеру.
    2. Хай-тек-яжепогромист. Разработать систему синтезирования речи. Такие уже есть, но они пока еще большее говно, чем дрыгающийся неморгающий спикер.
      … (Бонус от капитана) Маскировать склейки картинкой, например, слайдами. Куски, которые перекрывать не хочется, писать дублями без помарок. Впрочем, без помарок это ко всему относится. А кто говорил, что видео-блогер это легко?
      Да, еще же можно текст держать перед глазами, но тут свои заморочки.

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


    1. alopatindev Автор
      29.01.2019 20:23

      Спасибо за фидбек! Данные варианты рассматривал, но из-за недостатка времени пришлось выбирать между:
      — не начинать блог
      — временно делать с большим количеством склеек и в конечном счете, в процессе, натренироваться говорить более длинно.


      1. Shtucer
        29.01.2019 21:08

        не начинать блог

        потому что попытка — это первый шаг к провалу?


        временно делать с большим количеством склеек и в конечном счете, в процессе, натренироваться говорить более длинно.

        делать надо сразу хорошо. Большое количество склеек это ни хорошо, ни плохо, иногда это необходимость. Большое количество плохих склеек — это плохо. Если по звуку это худо-бедно прокатит, то с картинкой получается брак. Повторюсь, помарки в речи, непоставленное дыхание — это нормально, никто не ожидает, что видео-блогер будет говорить аки Левитан. У вас сейчас получается делать из живого вас какого-то гомункула. Будьте собой это всегда ценно. И потом, при просмотре собственного нередактированного видео всегда будут видны промашки, над которыми надо поработать.


        Я для себя вижу две главные проблемы русского видеоблогинга: нечего сказать и косноязычие. Иногда это пересекается и делается совсем невыносимо больно. Поэтому я смотрю в основном на иностранном языке, я там по крайней мере не замечаю косноязычия. Не, ну бывают, конечно… индусы, например, или соотечественники, но реже.


        Я ещё один вариант придумал. Оставить вашу разработку, но видео нещадно уничтожать, а звуковую дорожку с титрами методом липсинка присобачить к трёхмерному аватару. Там и виртуальная студия сама собой напрашивается… во перспективище!


  1. ser-mk
    30.01.2019 11:21

    Из опен сорсных, очень хорошо себя показал kdenlive. Все что надо для себя там нашел. На линуксе завелся сразу. А вот на окнах все очень нестабильно там))
    Мне вот для создания видео не хватает инструмента для создания анимаций, допустим плавно от одного конца схемы до другого нарисовать стрелочки или плавно отмасштабировать картинку в кадре.


    1. lmike
      30.01.2019 18:26

      не ОСС — в Davinci есть


    1. alopatindev Автор
      30.01.2019 20:52

      Мне идеологически Kdenlive тоже понравился, но для меня он работает очень нестабильно на GNU/Linux. В особенности когда комбинируешь обычные эффекты и те, что используют GPU.


      1. ser-mk
        30.01.2019 21:28

        А можно пример, нестабильной комбинации? Просто пока еще не натыкался на такое.