Замечательная штука, этот ZoneMinder (описание на русском можно почитать тут: www.openkazan.info/node/1360) С помощью одной-двух обычных вебкамер (а так же аналоговых с платой видеозахвата и IP-камер) позволяет организовать видеонаблюдение (с детектированием движения, зонами охраны, просмотром реал-тайм через интернет через любой браузер, даже через iPhone можно, проверено). Вот только когда дело доходит до просмотра всех событий за день-неделю-месяц становится ну очень утомительно: каждое событие (т.е. зарегистрированное движение) записывается отдельно и просматривать его надо отдельно. Видео тоже можно создать стандартными средствами, но опять же по одному для каждого события. А у меня, например, с каждой камеры их по 1000-2000 штук в день. Напряжно очень.
Впрочем, проблема легко решилась bash-скриптом и кроном.
В интернетах не сразу, но нагуглился скрипт, который выполнял поиск по дате изменения файлов, работающий в 3 этапа:
- Поиск и копирование всех файлов изменившихся с %date%,
- Переименование картинок нужный формат
- Кодирование видео-файла на основе найденных картинок.
Ссылку я к сожалению уже потерял…
Слабыми и неуклюжими местами показалась отсутствие гибкости в выборе временных диапазонов, точнее ограничения в них команды find. Ну и ненужное копированиие и переименование в два этапа.
Да и зачем пользоваться find, если пути известны, а данные о файлах с картинками лежат в базе MySQL, а она очень приятно (вкупе с awk) работает в консоли.
Короче родилось вот такое решение:
~/bin/mkvideo:
#!/bin/bash # камера по-умолчанию, если запущен без параметров cam_default=Office1 #дата по-умолчанию - вчера workdate_default=`date -d yesterday` workdate=$1 cam=$2 if [ "Z"$1 = "Z" ]; then workdate=$workdate_default fi if [ "Z"$2 = "Z" ]; then cam=$cam_default fi # путь до ZM inpath=/var/cache/zoneminder/events/${cam} # Где хранить картинки (временно) jpgpath=~/jpg # Куда складывать видеофайлы videopath=~/video mydate=`date -d "${workdate}" +%Y-%m-%d` filename=${cam}-${mydate}.avi zmdatabase=zm echo workdate is ${mydate} mkdir -p ${jpgpath} 2>/dev/null mkdir -p ${videopath} 2>/dev/null # Выборка нужных файлов из базы данных # по вкусу (если есть пароль) подкрутить парамерты mysql -u user --password=password files=`mysql ${zmdatabase} -s -e \ "select eventid,right(concat('00',frameid),3) from Frames where date(timestamp)='${mydate}' order by eventid,frameid" \ | awk '{print($1"/"$2"-capture.jpg");}'` i=0 for f in ${files} do # проверка на размер файла, ZM иногда пишет картинки с нулевым размером # а ffmpeg потом спотыкается if [ `ls -l ${inpath}/${f} | awk '{print $5}'` -gt 0 ]; then i=$((i+1)) p=$(printf %.8d $i) cp -p ${inpath}/$f ${jpgpath}/$p.jpg fi done rm ${videopath}/${filename} 2>/dev/null # Кодируем видео из картинок ffmpeg -r 100 -an -i ${jpgpath}/%08d.jpg -vcodec h263p -b 1500k ${videopath}/${filename} #Удаляем старые файлы rm ${jpgpath}/*.jpg 2>/dev/null |
Качество сжатия и фпс ессно подкрутить по вкусу. Запускать с параметрами
$ ./mkvideo date cam |
дата может быть today, yesterday, 2010-12-01
название камеры с учетом регистра как задано в ZoneMinder
Если камера одна, прописать ей по-умолчанию в начале скрипта и в крон пихать без параметров сразу после 00:00 по местному времени, будет создаваться видеофайл всех событий за вчерашний день.
Путем изменения запроса к MySQL можно легко собирать видео за определенный час, неделю, месяц (это правда долго)