Заметки по видеонаблюдению

Более-менее оформил уже свою систему видеонаблюдения дома и придомовой территории, теперь время оформить получившиеся при этом наработки.

Прежде всего – камеры. Выбор на сейчас достаточно широкий; цены начинаются буквально от пары десятков долларов – прошло то время, когда я покупал VGA-камеру с убогой картинкой за 70, а HD (которая на голову обходила ту VGA) за сотню с небольшим. Картинка же даже на той HD сейчас кажется весьма паршивой, что уж говорить про VGA?

В целом, хотелось толковую камеру за вменяемые деньги, так как камер планировалось больше десятка и цена ощутимо скажется на кошельке. Что-то, что не будет стоить, как самолет, без лишних функций – мне не требовалась поворотная камера или картинка в 8 Мп, но при этом картинка должна быть достаточно качественной; камера должна уметь работать ночью и днем, а также питаться через PoE.

Тред на ЛОРе не особо помог – предложенная камера от Hikvision была какой-то полумифической; а брать китайский noname с жалобами на нагрев не особо хотелось, чтобы не разгребать проблемы потом еще и с этой стороны. Однако для себя я все же решил остановиться на Hikvision и посмотреть на их модельный ряд.

Итог – заказал для пробы DS-2CD1021-I и DS-2CD1121-I(D) – первая “традиционная”, вторая – купольная. Обе с нужными мне характеристиками и за цену порядка 60$.

Еще был новый для меня параметр, по которому приходилось выбирать камеры – фокусное расстояние: камеры одной модели предлагались в нескольких исполнениях. Мне нужен был максимально широкий обзор (как минимум, у меня на то время не было никаких предпочтений на этот счет), поэтому камеры брал с линзой 2.8 мм, что давало обзор 90 градусов.

Опробовал обе камеры. Картинка была сходной. Купольный тип камеры – в целом, интересен, но в итоге все же остановился на традиционной – как оказалось в дальнейшем, не зря. Во-первых, у купольной настройка положения объектива делается только в двух плоскостях, а у традиционной – в трех (лево-право/вверх-вниз и вокруг оси объектива). Разместить купольную на подшивке крыши было бы нельзя – а несколько таких точек у меня было. Во-вторых, как заметил уже позже, у 1021 была подсветка EXIR – какой-то более продвинутый вариант, дающий более равномерную засветку. Впрочем, как оказалось, гораздо больше сказывается окружающий рельеф. Ну и в-третьих, в админке купольной не нашел даже функции обновления прошивки, которая была у обычной.

Тут стоит сделать несколько заметок по админке.

Во-первых, внешне нет никаких возможностей ресетнуть камеру, если что не так. Есть пароль, задаваемый при первом запуске и там же – 3 контрольных вопроса для восстановления пароля. К сохранению пароля стоит отнестись внимательно.

Во-вторых, заявленной работы с NAS’ом так и не нашел. Есть только FTP.

Далее, сама админка достаточно кривая. Видео в предпросмотре у меня не показывалось нигде, кроме IE в виртуалке. Там же приходилось настраивать OSD, ибо без каких-то левых плагинов ни под какой версией Firefox или Chromium я сделать это не мог. То же относится и к motion-зонам, хотя я их и не использовал. Вот так вот – древний Dlink DCS-2103 может, а современный Hikvision не осилил. Причем, из-за плагина не работает в итоге вся страница настройки – т.е., например, просто сменить имя камеры не выйдет. Разметка страниц местами плывет – причем, в купольной в большей степени – там кривой была даже страница настройки видеорежима. Видеопотоков 2 – основной, на полных параметрах камеры и дополнительный, с максимальным разрешением 640×480 и двумя кодеками на выбор – mjpeg и h264. На деле mjpeg был настолько убогий, что в наилучшем качестве сильно забивал полутона и градиенты: то, что в реальном мире выглядело как просто полутемный, но достаточно хорошо видимый объект, на mjpg был просто черным пятном. В итоге оба кодека оставил h264. В дополнение есть опция выбора кодека h264+, обещающая ощутимое сокращение расхода места на диске. На деле заставить работать с этим потоком хоть чем-то не вышло и пришлось откатиться обратно на обычный h264.

Битрейт поставил максимальный; FPS – 25 кадров. Сначала, правда, ставил 15 кадров – вроде как достаточно, но на первых камерах, где случайно остались 25 fps картинка была более привлекательной на движениях, поэтому перенастроил все на 25. На вторичном потоке оставил 4 fps.

Да, чуть не забыл. Еще из недостатков – накладываемый на вторичный видеопоток OSD. Отключить его отдельно для этого потока нельзя. Соответственно, если нужно отображение времени на видео – а оно обычно нужно – то имеем на вторичном потоке постоянно меняющуюся область. Еще и размером на пол-экрана даже при использовании самого малого шрифта. Приходилось решать этот вопрос с помощью маски. Выпадает часть картинки, но что ж делать…

На сейчас в работе 11 камер – 10 традиционных и одна купольная. Разницы в работе не замечаю.

Запитка всех камер, как и планировалось, делается по витой паре. Камера умеет как пассивный PoE – запитываю камеру через обычные гигабитные PoE инжекторы/сплиттеры, купленный когда-то на ebay, в которых питание подается через контакты 4/5-7/8 (вариант B), так и тот, в котором питание подается как дифференциал между сигнальными парами – 1/2-3/6 (вариант А).

Кабель – практически везде FTP cat 5e. В одном месте по одному кабелю подключены 2 камеры – как раз здесь используется возможность запитки вариантом А. Есть несколько камер, где используется имеющиеся коммуникации – телефонный кабель ТППэп на 20 жил. В этом случае между зданиями сигнал идет по этому кабелю, а далее уже до камеры – с помощью витой пары.

ТППэп в данном случае представляет собой 10 витых пар – в одних источниках указывается 3-я категория, в других – 2-я. Так или иначе, при тестировании подключения по 8 проводам свич показал наличие гигабитного линка. Подключенная там же камера работает без проблем. Подключение же более удаленного участка вызвало проблемы – камеры запитывались, но линк не светился. Попутно были выявлены проблемы с обжимкой витой пары, но в целом – все начинало работать только при установке промежуточного свича  в точке стыка ТПП и витой пары. В качестве эксперимента максимально обрезал телефонный кабель. Итог – одна камера начала нормально опознаваться и работать с запиткой из дома. Вторая (которая при этом находилась ближе к точке стыка) так и осталась проблемной – линк держится на грани срыва; работает это все только на одном свиче из трех, а при запитке из дома линк пропадает совсем. Сейчас питание идет по свободным парам телефонного кабеля и в точке стыка стоит инжектор. Тем не менее, даже со всеми ухищрениями нормальная картинка с камеры есть только на вторичном потоке; при захвате первичного зачастую появляются артефакты. Модернизацией буду заниматься уже по весне, ибо сейчас приходилось ковыряться в коробке, иногда засыпанной снегом. Возможно, если поменять камеры местами с какой-то другой, то попадется более удачный экземпляр.

Достаточно внезапной проблемой стала ночная съемка. Погода сейчас – температура около нуля, то дождь моросит, то мелкий снежок, то туман. И все это вылезло немного с неожиданной стороны – пролетая мимо камеры, где расположена и подсветка, и сам объектив, частицы засвечиваются и камера это все ловит. В итоге на камере от легких снежинок до полной “заснеженности” картинки. Раньше с этим не сталкивался, ибо как-то так само-собой вышло, что камера и подсветка были разными сущностями, в итоге подсветка была, но перед объективом ничего не засвечивалось. Как быть в этом случае – пока не знаю. Можно расставить внешние прожекторы, но их надо чем-то питать – а это необходимость, собственно, питания, плюс кабелей к прожекторам. Опять же, вопрос автономности и управления режимом день/ночь (не гонять же все днем). Камеры с выходом на внешнюю подсветку (полноценный прожектор с питанием от камеры или хотя бы управление внешним по сигналу с камеры) как-то сходу не нашлись.

Софт и железо.

Тут, как и раньше, motion. Сначала, во время тестирования первых двух камер, просто начал настраивать motion по образцу своего первого сервера видеонаблюдения. Присматриваясь к разным камерам, попутно глянул видеорегистраторы. При цене порядка 100$ были мысли даже взять – пусть будет самостоятельная коробочка, которая будет делать все, что нужно, писать данные на диск и рисовать сетку картинок с камер. Потом поинтересовался веб-интерфейсами к motion и открыл для себя motioneye… В итоге развернул на железе бывшей криптоноды motion+motioneye. Результат весьма понравился :). Достаточно подробное конфигурирование motion через веб-интерфейс, рисование масок для камер, выполнение внешних команд и так далее. Зачем тогда тот видеорегистратор? :). Потребление же отдельной такой машинки на C60 было порядка 20 Вт (до 15 Вт система, плюс пара дисков) и было вполне соизмеримо с потреблением выделенного видеорегистратора.

Подход в motion пришлось применить старый – работаем со вторым потоком, а по событию вызываем ffmpeg, который дампит основной поток на диск.

По ресурсам AMD C60 нормально вытягивал примерно 7 камер. 9 днем работали нормально, но ночью, когда упомянутый выше “снег” заставлял все камеры срабатывать на движение, ресурсов уже не хватало. Процентов 120 уходило на треды motion, еще процентов по 10 – на ffmpeg. В итоге в таком режиме в веб-интерфейсе все отрисовывалось с ощутимой задержкой – отставание картинки было на минуту и больше.

Так как планировалось в итоге еще больше камер – C60 пришлось бы заменить на что-то более мощное – например, на такую же материнку, как на сервере, с j4005. Однако я тут очередной раз заморочился общим потреблением железа – сервер, 3 свича, NAS, видеорегистратор, камеры и все остальные сопутствующие железки в ночном режиме потребляли уже более 200 Вт, что много. Было решено скрестить NAS+криптоноду и видеорегистратор и собрать это все на железе старого сервера – на Athlon 740 + 32 GB RAM. Проблема с местом решалась естественным путем, ибо база – NAS и 4 диска по 3 ТБ с возможностью поставить еще больше. Ресурсов процессора теперь тоже завались. Чтобы оставить потребление во вменяемых рамках – задал для всех ядер политику powersave:

rain@meganas:~$ cat /etc/rc.local
#!/bin/sh -e
for i in $(awk '/processor/{print $3}' /proc/cpuinfo) ; do cpufreq-set -c $i -g powersave ; done

Как оказалось, вызов команды без указания всех ядер меняет политику только на одном, а остальные продолжают скакать по частотам. Возможно, на старом сервере это было одной из ошибок (там ставил powersave при отключении питания на UPS’ке), а может что-то поменялось между Debian 7 и Debian 9.

Так или иначе, все было запущено в рамках нового железа – теперь это был 4-ядерный процессор, залоченный на 1400 МГц для каждого ядра. Потребление не сказать, что сильно поменялось – на сейчас, при 11 работающих камерах, выходит около 205 Вт ночью и примерно 170 днем. Однако по ресурсам теперь стало сильно свободнее.

Камеры потребляют примерно 2,4Вт днем и до 4,5 при работе подсветки.

Если вернуться к софту, то всплыли такие особенности.

Во-первых, motion в последних версиях достаточно активно и неплохо развивается. Появилось разделение потоков (версия 4.1) – он научился работать с вторичным потоком с камеры для детекции движения и с основным – для захвата видео. Однако проба такого варианта (точнее, просто указание адреса в netcam_highres, даже без дальнейшего захвата видео) на C60 показало увеличение потребления ресурсов тредами motion до полутора раз – чисто из-за того, что тред, работающий с потоком высокого разрешения постоянно кэшировал этот поток для возможности дальнейшего сохранения без потерь кадров, если обычный поток определит в дальнейшем, что было движение. Использование более мощного компьютера, конечно, решало бы проблему, но зачем, если можно просто сохранить старый подход ценой потери пары кадров? Кроме того, motion в версии 4.1 так и не научился не перекодировать видеопоток, так что ресурсов уходило бы немеряно. А вот с версии 4.2 наконец-то завезли movie_passthrough, так что заботу о кодировании видео можно максимально переложить на саму камеру.

Но тут вылезла другая проблема – изменился формат опций, а motioneye пока заточен под старый вариант. Пришлось пока оставить 4.1.1, как самую актуальную версию.

Что же касается самого motioneye… Поначалу все выглядело хорошо. Были отдельные шероховатости – например, движок чувствительности на минимальном значении в 0.1% в конфиге motion’а задавал порог сразу в 300 пикселов, а мне нужно было только 50-70. Пришлось задать это напрямую руками в конфиге и потом не трогать тот блок опций в интерфейсе, чтобы не перезаписались мои значения.

Основной проблемой стало то, что почему-то не прерывалась запись потока, плюс плодились сами потоки. На выходе я получал многогигабайтные файлы, почти не отличающиеся по времени. Такого поведения на старом сервере не было, тот работал идеально. Конфиги были очень похожими, в чем причина – я долго не мог понять. Пришлось писать свой скрипт-обертку вокруг ffmpeg, который бы делал максимум проверок и максимально подробно логировал бы действия.

Сам скрипт помог проблеме не сильно, хотя, как минимум, он подчищал оставшиеся от предыдущих запусков процессы ffmpeg. Но в итоге я все же заметил проблему – dmesg был завален сообщениями о сегфолтах и трапах в motion. Так как motioneye был развернут и на старом сервере, глянул этот момент и там (там у сервера был приличный аптайм). И выяснилось, что ранее никаких сегфолтов не было, все началось именно после установки motioneye.

Конфиги тредов на старом сервере не поменялись вообще (кроме разве что вызова скрипта, который рисовал красную рамку вокруг камеры с зарегистрированным движением – это никак не могло сказываться). Файл motion.conf тоже почти не изменился – добавились лишь комментарии для парсинга со стороны motioneye, плюс включился веб-интерфейс в самом motion (порт 7999). Последнее и стало источником проблемы. Отключение прослушивания порта 7999 практически полностью устраняло сегфолты. Однако любое изменение со стороны motioneye (например, перезапуск motion для применения новой маски для камеры) перезаписывало значение. Чтобы оно перезаписывалось всегда нулем – нужно поправить соответствующий параметр в motioneye.conf. Нужно ли отключать функцию самого веб-интерфейса – пока не понял; однако с момента нахождения проблемы было только 2 сегфолта у motion и последние пару дней все работает совсем стабильно:

[ +0,000005] ml5[6397]: segfault at ff00000000 ip 00007f165bbb9a84 sp 00007f163aaab6c8 error 6 in libpthread-2.24.so[7f165bbb3000+18000]
[ +0,043738] ml7[6398]: segfault at ff00000000 ip 00007f165bbb9a84 sp 00007f1639aa96c8 error 6 in libpthread-2.24.so[7f165bbb3000+18000]
[ +0,777188] ml11[6399]: segfault at ff00000000 ip 00007f165bbb9a84 sp 00007f1632ff96c8 error 6 in libpthread-2.24.so[7f165bbb3000+18000]
[ +0,077842] ml6[6400]: segfault at ff00000000 ip 00007f165bbb9a84 sp 00007f163a2aa6c8 error 6 in libpthread-2.24.so[7f165bbb3000+18000]
[ +0,025022] ml10[6401]: segfault at ff00000000 ip 00007f165bbb9a84 sp 00007f16337fa6c8 error 6 in libpthread-2.24.so[7f165bbb3000+18000]
[ +0,045763] ml4[6402]: segfault at ff00000000 ip 00007f165bbb9a84 sp 00007f1633ffb6c8 error 6 in libpthread-2.24.so[7f165bbb3000+18000]
[ +0,024165] ml5[6404]: segfault at ff00000000 ip 00007f165bbb9a84 sp 00007f163aaab6c8 error 6 in libpthread-2.24.so[7f165bbb3000+18000]
[ +0,044513] ml7[6405]: segfault at ff00000000 ip 00007f165bbb9a84 sp 00007f1639aa96c8 error 6 in libpthread-2.24.so[7f165bbb3000+18000]
[ +0,781551] ml11[6406]: segfault at ff00000000 ip 00007f165bbb9a84 sp 00007f1632ff96c8 error 6 in libpthread-2.24.so[7f165bbb3000+18000]
[ +0,065083] ml6[6407]: segfault at ff00000000 ip 00007f165bbb9a84 sp 00007f163a2aa6c8 error 6 in libpthread-2.24.so[7f165bbb3000+18000]
[дек26 22:18] r8169 0000:03:00.0 eth0: link down
[ +8,520061] r8169 0000:03:00.0 eth0: link up
[ +2,647060] r8169 0000:03:00.0 eth0: link down
[ +2,326261] r8169 0000:03:00.0 eth0: link up
[дек27 04:14] show_signal_msg: 39 callbacks suppressed
[ +0,000006] ml9[5076]: segfault at 7f8c3d54e35a ip 000056445381426c sp 00007f8c3fffe970 error 6 in motion[5644537f4000+4c000]
[дек27 04:22] ml1[17518]: segfault at 7f0f3f57475b ip 000055d6fd8f927a sp 00007f0f5d871970 error 6 in motion[55d6fd8d9000+4c000]
[дек27 21:43] r8169 0000:03:00.0 eth0: link down
[ +8,625961] r8169 0000:03:00.0 eth0: link up
[ +2,535865] r8169 0000:03:00.0 eth0: link down
[ +2,232988] r8169 0000:03:00.0 eth0: link up
[дек28 00:39] r8169 0000:03:00.0 eth0: link down
[ +8,978803] r8169 0000:03:00.0 eth0: link up
[ +2,534350] r8169 0000:03:00.0 eth0: link down
[ +2,170527] r8169 0000:03:00.0 eth0: link up
[дек29 10:17] r8169 0000:03:00.0 eth0: link down
[ +8,517503] r8169 0000:03:00.0 eth0: link up
[ +2,644449] r8169 0000:03:00.0 eth0: link down
[ +2,265935] r8169 0000:03:00.0 eth0: link up

Теперь понятна причина проблемы с висящими ffmpeg: motion вылетал, ffmpeg становился сиротой и жил дальше сам по себе, убить его было некому, так как motion, запущенный заново со стороны motioneye, про этот ffmpeg ничего не знал. В лучшем случае, если та же камера детектила движение, запускался новый ffmpeg, и – если повезет и motion не вылетит, то команда завершения убьет оба процесса – старый и новый.

Причем, необходимость в web-интерфейсе motion’а для motioneye не ясна: картинку он рисует самостоятельно, конфиги парсит и переписывает тоже сам; процессом motion’а тоже управляет самостоятельно. Я пока еще ни разу не наткнулся на ситуацию, когда что-то бы не работало без этой опции.

На пока вроде все; продолжаю наблюдать и донастраивать систему 🙂

6 мыслей о “Заметки по видеонаблюдению”

  1. Судя по
    data.setdefault(‘webcontrol_port’, settings.MOTION_CONTROL_PORT)
    data.setdefault(‘webcontrol_html_output’, True)
    data.setdefault(‘webcontrol_localhost’, settings.MOTION_CONTROL_LOCALHOST)
    data.setdefault(‘webcontrol_parms’, 2) # the advanced list of parameters will be available
    отключить остальные “подозрительные” параметры без правки исходников не удастся.

  2. Аналог данных камер на 3 Мп – DS-2CD1031-I, на 4 – DS-2CD1041-I. Последняя, правда, значится как “проектное оборудование”. Что означает – не вполне ясно. Цена в магазинах ощутимо дороже. Если 3 Мп дороже 2 Мп на 33%, то 4 против 3 – уже на 46%. Судя по всему, 3 Мп выходит оптимальным вариантом для точек, где требуется чуть более высокое разрешение. Заявлено разрешение 2304х1296 – правда, только 20 fps против 25 на остальных потоках. Похоже, это уже предел железа.

  3. Заметка по смежной теме: сдох БП на удаленной камере, камера отвалилась. motion на это обижался и сегфолтился. Убрал 3-й тред из 4-х в motion. Виртуальный ID треда для motioneye у 4-го остался вроде как 4-й, а вот в motion произошел сдвиг, который я не учел. В итоге моему скрипту ffdump.sh передавался из thread-4.conf ID 3. Исходя из этого он парсил thread-3.conf на предмет путей, логинов и паролей и пытался писать с той самой дохлой камеры вместо нужной.

  4. Для обхода падений motion’а пришлось задействовать monit с таким конфигом:
    check file syslog with path /var/log/kern.log
    start program = “/usr/sbin/service motioneye start”
    stop program = “/usr/sbin/service motioneye stop”
    ignore content = “monit”
    if content = “traps: ml” then restart
    if content = “ml.*: segfault” then restart

Добавить комментарий для rain Отменить ответ