Недавно у меня возникла необходимость соорудить некое подобие видеонаблюдения. Требования были довольно простые:
- возможность наблюдать через интернет
- не обязателен режим реального времени, достаточно вечером просмотреть основные события за день (скажем, узнать, сидит ли кто-нибудь за вашим любимым компом, пока вы на работе)
- отсутствие необходимости тратить часы на отсмотр результатов
- максимально возможное качество картинки
- минимальная стоимость
Исходя из критериев, можно было бы остановиться на готовых решениях в виде IP-камер. Однако, проведенный на скорую руку анализ рынка показал, что в устройствах, стоимостью до $100, размер картинки редко превышает 640x480 точек, и, при этом, они не могут похвастать хорошими возможностями для настройки софта. То есть, вполне возможно, что купив такую камеру, вам придется мириться с кривизной заводской прошивки и невозможностью в полной мере реализовать свои замыслы.
В противовес готовым решениям, самоделка на Raspberry Pi – это достаточно недорого, куда более увлекательно, и гораздо более гибко, благодаря полноценной ОС на борту и терабайтам готового софта на любой вкус.
Для решения описанных задач был придуман следующий алгоритм работы:
В начале дня (по расписанию) в системе запускается процесс, который делает фотоснимки с некоторым интервалом (скажем, раз в минуту), сохраняет их локально на карту памяти и тут же выкладывает на какой-нибудь облачный диск по WebDAV протоколу. Это обеспечивает некоторое подобие «живого» наблюдения, которое, хоть и не требуется по условиям, но является приятным бонусом. В конце дня (тоже по расписанию) процесс фотосъемки прерывается и запускается сборка видеофайла из фотографий. По окончании сборки, видео выкладывается на тот же облачный диск, что дает возможность быстрого удаленного просмотра цельной avi-шки, без необходимости переключения между фото-файлами (10 часов работы, по кадру в минуту, дадут общий хронометраж видео – всего около минуты, при 10 fps).
В таком подходе, конечно, не реализуется видеонаблюдение в его привычном виде, но решаются все поставленные задачи. Кроме того отпадает необходимость покупать у провайдера выделенный IP, чтобы подключаться к камере напрямую, а также нет нужды заводить отдельный сервер видеонаблюдения, потому что его функции хранения и доступа к данным перекладываются на бесплатный сервис (например Яндекс.Диск).
Итак, железо:
- Raspberry Pi ($50-$60 в наших краях): я использовал model B, ту что c Ethernet, двумя USB и 256 Мб ОЗУ
- Logitech C270 ($20): относительно дешевая и популярная HD (1280x720) веб-камера, соответствующая спецификации UVC (как следствие, без проблем работающая в Linux системах)
- Зарядка от iPhone ($10): на самом деле айфон, конечно, ни при чем, подойдет любой источник питания с выходным током от 1А и разъемом micro-USB. Можно найти китайские импульсные зарядки не дороже $2 за штуку, только проверять их надо тщательно.
- SD карта на 4 Гб ($6): четыре гига — минимальный объем карты для комфортной работы.
- Корпус для малины ($1): сделан с помощью дремеля из более-менее подходящей коробки, купленной в строительном гипермаркете.
В сборе все выглядит примерно так:
Поскольку это мой первый опыт работы с Raspberry, чуть-чуть остановлюсь на вещах, возможно уже известных более продвинутым пользователям.
Первый нюанс – это питание периферийных устройств. Дело в том, что при включении Raspberry от одноамперного источника, USB портам достается совсем немного тока. В итоге у меня не получилось подключить одновременно веб-камеру и USB Wi-Fi dongle, или две веб-камеры: одно из устройств работало стабильно, а другое сначала вроде бы заводилось в системе, но через минуту просто отказывалось работать.
Второй нюанс – количество USB портов. Их в малинке всего два, а значит подключить камеру, клавиатуру и wi-fi одновременно не получится. Однако есть пара решений.
Во-первых можно подключить к Raspberry питающий USB хаб, а в него уже воткнуть всю необходимую периферию. У меня, например, все работало с таким:
Это увеличит число доступных портов и даст им всем достаточно тока, хотя и потребует занять еще одну розетку 220В.
Во-вторых, имеет смысл управлять малиной по SSH – тогда не нужно подключать ни клавиатуру, ни мышь, ни монитор. А если очень хочется увидеть графическую оболочку, то можно установить VNC server и получить удаленный доступ к рабочему столу. Делается это примерно так:
установка:
sudo apt-get install tightvncserver
запуск сервера на первом порту:
vncserver :1 -geometry 1200x700 -depth 16
Теперь подключиться к «малиновому» VNC можно клиентом из под рабочей ОС (под Windows, например, отлично работает UltraVNC )
Выбор и установка софта:
В качестве ОС я использовал Raspbian, как наиболее подходящую для непродвинутых пользователей. Нужно скачать образ системы и установить его на карту памяти с помощью специальной утилиты (Win32DiskImager под Windows). Все это подробно описано на странице загрузок официального сайта Raspberry: www.raspberrypi.org/downloads
После первого запуска системы имеет смысл сконфигурировать часовой пояс, чтобы время создания снимков отображалось корректно.
Конечно, это можно сделать и позже, командой
sudo dpkg-reconfigure tzdata
Для захвата фото с веб-камеры настоятельно рекомендую использовать mjpg-streamer. Эта утилита – единственная среди опробованных на данной конфигурации железа, смогла выдать фото в «правильном» разрешении. Остальные инструменты которые мне довелось испытать (motion, ffmpeg, streamer), никак не отдавали HD картинку, предлагая в лучшем случае только 640x480, а то и вовсе отказывались запускаться. К сожалению в виде исполняемых файлов mjpg-streamer не распространен, однако скомпилировать его оказывается не сложнее, чем установить готовый пакет. Чем и займемся (предполагается, что все операции производятся от имени пользователя pi).
Сначала стоит обновить локальный индекс пакетов, доступных для установки:
sudo apt-get update
Также можно запустить апгрейд уже установленных в системе пакетов, если нужно, хотя на практике все работает и без этого:
sudo apt-get upgrade
Чтобы вывести на фотографиях дату и время их создания, нам понадобится пакет imagemagick, в состав которого входит утилита convert. Она обладает поистине неограниченными возможностями по изменению изображений, так что написать в углу десяток цифр с ее помощью оказывается совершенно несложно. Этот же пакет понадобится и для компиляции mjpg-streamer, так что ставим его, не задумываясь:
sudo apt-get install imagemagick
Склейкой видео из набора фотографий занимается программа aviconv, которую мы тоже установим не самостоятельно, а вместе с пакетом libav-tools, без которого компиляция mjpg-streamer не будет успешной. Ставим:
sudo apt-get install libav-tools
Еще понадобится пакет libjpeg8-dev, который также содержит необходимые библиотеки для mjpg-streamer:
sudo apt-get install libjpeg8-dev
Для скачивания исходников c sourceforge понадобится subversion:
sudo apt-get install subversion
А само скачивание и компиляция mjpg-streamer делается так:
sudo svn co https://svn.code.sf.net/p/mjpg-streamer/code/mjpg-streamer/ mjpg-streamer
cd mjpg-streamer
make
Последний шаг – установка пакета для работы с удаленной файловой системой по WebDAV и, собственно, ее монтирование:
sudo apt-get install davfs2
sudo mkdir /mnt/dav
sudo mount -t davfs https://webdav.yandex.ru /mnt/dav -o uid=pi,gid=pi
В процессе монтирования нужно будет ввести имя пользователя и пароль.
Рабочий процесс шаг за шагом:
Теперь у нас есть все необходимое для дальнейшей работы. Вкратце опишу основные команды, не особо налегая на bash, чтобы не перегружать статью. Думаю, что описание автоматизированных скриптов для запуска отдельных операций может быть поводом для отдельного эссе.
Итак, запускаем mjpg-streamer:
cd mjpg-streamer
./mjpg_streamer -i "./input_uvc.so -r 1280x720 -f 1" -o "./output_file.so -f ./ -d 60000"
В таком режиме он будет раз в минуту (-d 60000) в текущем каталоге (-f ./) создавать файл с красивым именем, вроде такого: 2013_10_04_12_11_30_picture_000000000.jpg.
Для отрисовки временной метки на изображении используем скрипт примерно такого вида:
filename="2013_10_04_12_11_30_picture_000000000.jpg"
timestamp=`stat -c %y $filename`
convert $filename -fill black -draw "rectangle 1130,695 1270,715" -fill white -pointsize 15 -draw "text 1135,710 '${timestamp:0:19}'" ./out.jpg.
Он поставит метку в правом нижнем углу изображения и запишет результат в out.jpg. Получится примерно так:
Для записи на Яндекс.Диск просто копируем нужный файл в /mnt/dav:
cp out.jpg /mnt/dav
Стоит отметить, что само копирование на удаленную файловую систему осуществляется в 2 этапа: сначала файл копируется в локальный кэш где-то в /var/cache/davfs2, а дальше davfs уже занимается собственно переносом файла по сети. Это значит, что команда копирования завершится раньше, чем файл физически окажется доступен в Яндекс.Диске. Поэтому не расстраивайтесь, если не обнаружите на Яндексе только что скопированный файл – скорее всего нужно немного подождать.
Создание видео из набора jpeg-ов нуждается в подготовке: имена файлов должны представлять собой последовательность возрастающих чисел, подчиняющихся определенному шаблону. Вот скрипт, который переименует все jpg файлы в текущем каталоге по возрастанию времени их модификации, а затем запустит конвертацию в avi:
i=0
for f in `ls -tr *.jpg 2>/dev/null`
do
newf=`printf %06d $i`.jpg
echo $f "-->" $newf
mv $f $newf
i=$((i+1))
done
avconv -r 10 -i %06d.jpg -r 10 -vcodec mjpeg -qscale 1 out.avi
Надо сказать, что avconv – тоже очень мощная утилита, умеющая кодировать практически что угодно во что угодно с доброй сотней параметров. Однако стоит учитывать довольно скромные возможности по софтовому кодированию-декодированию видео у Raspberry, чтобы не возлагать на нее слишком много надежд. Например конвертация набора из примерно 600 файлов в фильм, сжатый в H.264, занимала у меня около двух часов. Поэтому в примере выше я использую кодирование в MJPEG, которое по сути ничего не сжимает, а только склеивает jpg друг с другом. Такая конвертация выполняется за несколько минут и не теряет исходного качества картинок.
Далее, при некоторой сноровке и навыках разработки bash скриптов, можно настроить полностью автоматизированную систему, которая будет, включаться и выключаться по расписанию, убирать за собой мусор, отслеживать доступность свободного места на удаленном диске и т.п. Также через диск можно организовать удаленное управление Raspberry, например, выкладывая в определенный каталог скрипты, которые малинка будет сама забирать и выполнять.
В завершение предлагаю пример самодельного timelapse видео. Обратите внимание, что время в правом нижнем углу — неверное. Это из-за того, что в Raspberry нет часов реального времени, и если ее включить без подключения к интернету, то будет использоваться последнее время работы, без учета часового пояса.