Timelapse трансляция в режиме полу-реального времени.
Хочу очень коротенько поделиться как я организовал трансляцию через интернет ускоренного видео (timelapse по-аглицки, также извесное под названием "цейтраферная съемка") в режиме полу-реального времени. Образец можно наблюдать здесь: http://flagman.ru/strogino. Сразу оговорюсь, в чем собственно полу-реальность состоит. Поскольку сжать время в "реальном времени" невозможно, то транслируется ролик, котоый в несколько минут показывает ускоренные (скажем в 12 раз) события последнего полу-часа или иного интервала, по выбору автора. Ролик обновляется через сравнительно короткие интервалы времени, например, каждые 3 минуты. При соизмеримой продолжительности самого ролика, такое отставание от реальности не слишком существенно.
Итак, для реализации данной задачи использованы следующее оборудование и софт:
1. Компьютер с прцессором Intel Core 2 Duo 2.4GHz и 2GiB памяти и портом FireWire IEEE1394 . (Машина справлятся с кодированием и раздачей видео с загрузкой процессора 70-80%, Посетители единичные, так что объединение этих функций на одной машине пока оправдано.)
2. Видеокамера Canon HV20. Также подойдут и более поздние модели HV30 и HV40. Данная камера способна выдавть видео в формате HDV 1440х1080 через интерфейс FireWire. К сожалению, захват видео с камер с HDMI выходом представляет на сегодняшний день большую проблему, доступные по цене платы практически отсутствуют, а сопрягать их с OpenSource программами сложно или вообще невозможно.
3. Опреационная система Linux. Любая разновидность сгодится для наших целей. Можно конечно и под Windows и под MacOS, и конечно под FreeBSD, для особых любителей, попоробовать это повторить, но большого смысла не вижу.
4. Программа ffmpeg скомпилированная с поддержкой кодеков x264 и VP8, а также драйвером IEC61883. Если, указанные кодеки включены в стандарнтые дистрибутивы, которые можно установить из репозиториев, то поддержка расширенной версии FireWire нет, так что от компиляции из исходных кодов отвертеться не выйдет. Да это не так уж и сложно, как кажется на первый взгляд. Моя версия программы скомпилирована со следующими ключами:
--enable-libx264 --enable-postproc \
--enable-avfilter --enable-libvpx --enable-libfreetype \
--enable-libdc1394 --enable-libopenjpeg --enable-libiec61883
5. Программа mkvmerge. Ее компилировать не обязательно - берем стандартную из репозиториев. Если формат webm вы поддерживать не собираетесь, то можно и вовсе без нее обойтись.
Теперь, собственно, сами скрипты, которые и выполняют всю работу.
Надо сделать три скрипта (это по минимуму, для контроля движения камеры, например, как описано здесь: понадобятся дполнительные скрипты). Один для захвата видео, а другой для его пререупаковки в ролики разумной длины и третий, который стартует при старте компьютера эти первые два запускает в нужное время.
Итак. Оболочка, запускаемая при загрузке системы:
#!/bin/bash
echo $(date +"%d-%m-%Y %H %M -- старт lapse_main.sh") >> ~/script/lapse.log #запись в лог оначале сессии
#запускаем захват видео в отдельном окне терминала
mate-terminal -e ~/script/lapse_ff_hdv.sh
# Запускаем Arduino для панаромирования
mate-terminal -e ~/script/arduino_control.sh
cd ~/video
#Запускаем цикл сборки
while :
do
{
# Запускаем сборку видео
mate-terminal -e ~/script/lapse_ff_assembly.sh
#ждем готовности нового куска видео
inotifywait -e modify -t 300 ~/video/lapse.m3u8
#проверяем дождались или нет, если нет - грохаем ffmpeg захвата видео и пишем жалобу в лог файл.
inotexitcode=$?
echo "inotexitcode = $inotexitcode"
if [ "$inotexitcode" -ne 0 ];
then killall ffmpeg; echo "- убиваем ffmpeg $?" ;echo "- убиваем ffmpeg" >> ~/script/lapse_ff.log
else echo "ffmpeg работает"
fi
sleep 20
}
done
Скрипт захвата видео:
#!/bin/bash
while :
do
echo $(date +"%d-%m-%Y %H %M -- старт ffmpeg-hdv") >> ~/script/lapse_ff.log
ffmpeg -y -f iec61883 -i 0 -dvtype hdv \
-vf "setpts=(1/24)*PTS, scale=1440:810, \
drawtext=fontfile=/usr/share/fonts/truetype/freefont/FreeSerif.ttf:fontcolor=cyan:fontsize=24:x=8:y=8:expansion=1:text=%{localtime\\\:%d-%m-%Y %H %M} h264 flagman.ru/strogino" \
-map 0:v -an -c:v libx264 -preset:v slow -profile:v high -x264opts keyint=125:level=4.1 -b:v 1500k -r:v 25 -force_fps -flags -global_header -fflags +genpts -f hls -hls_time 5 -hls_list_size 20 -hls_wrap 20 ~/video/lapse.m3u8 \
-vf "setpts=(1/24)*PTS, scale=1440:810, \
drawtext=fontfile=/usr/share/fonts/truetype/freefont/FreeSerif.ttf:fontcolor=cyan:fontsize=24:x=8:y=8:expansion=1:text=%{localtime\\\:%d-%m-%Y %H %M} VP8 flagman.ru/strogino" \
-map 0:v -an -c:v libvpx -minrate 1500K -maxrate 1500K -b:v 1500K -g 125 -flags +global_header -fflags +genpts -f segment -segment_list_size 20 -segment_time 5 -segment_time_delta 1 -segment_wrap 20 ~/video/w%03d.webm
#-map 0:v -vf "drawtext=fontfile=/usr/share/fonts/truetype/freefont/FreeSerif.ttf:fontcolor=blue:fontsize=24:x=8:y=8:expansion=1:text=%{localtime\\\:%d-%m-%Y %H %M} JPG flagman.ru/strogino" \
#-f image2 -q 0 -r 1/10 -updatefirst 1 ~/video/2sec.jpg
echo $(date +"%d-%m-%Y %H %M -- вылет ffmpeg-hdv") >> ~/script/lapse_ff.log
sleep 10
done
Скрипт окончательной сборки видео:
cd ~/video
#убиваем старые линки
rm tmp/* -f
# делаем правильно нумерованные линки на .ts файлы во временной поддиректории
x=1; for i in $(ls -t *ts); do counter=$(printf %02d $x); ln -f "$i" tmp/v"$counter".ts; x=$(($x+1)); done
# теперь тоже самое для .webm файлов
x=1; for i in $(ls -t w*webm); do counter=$(printf %02d $x); ln -f "$i" tmp/w"$counter".webm; x=$(($x+1)); done
#собираем mp4
cd tmp
nice ffmpeg -y -i "concat:v20.ts|v19.ts|v18.ts|v17.ts|v16.ts|v15.ts|v14.ts|v13.ts|v12.ts|v11.ts|v10.ts|v09.ts|v08.ts|v07.ts|v06.ts|v05.ts|v04.ts|v03.ts|v02.ts" -c copy ~/video/lapse0.mp4
#собираем VP8
nice mkvmerge -q -o ~/video/lapse0.webm w20.webm +w19.webm +w18.webm +w17.webm +w16.webm +w15.webm +w14.webm +w13.webm +w12.webm +w11.webm +w10.webm +w09.webm +w08.webm +w07.webm +w06.webm +w05.webm +w04.webm +w03.webm +w02.webm
cd ..
#перепаковываем mp4 в flv
nice ffmpeg -y -i ~/video/lapse0.mp4 -c:v copy -an ~/video/lapse0.flv
# двигаем готовые файлы на раздачу
mv -f ~/video/lapse0.mp4 ~/video/lapse.mp4
mv -f ~/video/lapse0.flv ~/video/lapse.flv
mv -f ~/video/lapse0.webm ~/video/lapse.webm
Не слишком коротко получилось. :)