Pull to refresh

Comments 39

Все очень интересно, хотя и тяжело для восприятия (особенно листинги на питоне). За подробное описание протоколов спасибо! Буду знать, как работает моя сетевая камера для видеонаблюдения — может, чего своего напишу для работы с ней (в стандартной программе не хватает детектора движения с настройками)
У меня есть долгосрочное желание написать свою систему видеонаблюдения. Простая система у меня уже есть, записывает видео с video4inux2 устройств с помощью ffmpeg. Хочу сделать её максимально модульной, чтобы кто угодно мог писать расширения для неё. Основная проблема в грамотном дизайне архитектуры.
> Основная проблема в грамотном дизайне архитектуры.

Судя по коду, врядли получится, извините.
Да, этот код сначала создавался без какой бы то нибыло проработки, особенно видно в rtsp_client.py. По хорошему переписать его надо. Плюс хорошо было бы отойти от использования питоновских листов в пользую простых массивов. Многие моменты отсутствуют необходимые для законченных решений, но этот код работает и используется. А вот построение архитектуры является моей основной проблемой.
rtsp_client.py это вообще похапня какая-то, если уж начистоту.

Но вообще непонятно, глядя в код, а чего, собственно, хочет автор?

Заморочиться на голом python'e врукопашную собственным rtsp клиентом в целях самообразования и «покопаться»? Тогда зачем читерствует twisted'ом, который снимает изрядную долю мороки.

А если автор хочет написать работающую систему для решения конкретных проблем, то почему не flumotion, почему не gstreamer? В такой код автор сам опухнет h264 и ffmpeg прикручивать, чего уж там «кто угодно мог писать расширения»…
Стояли вполне конкретные задачи, использовать собственный клиент оказалось легче и надёжднее, чем подключать готовые решения (я правда пробывал, включая OpenRTSP, gstreamer и ffmpeg). А когда код обрёл некую универсальность, то решил поделиться им с общественностью.
Твистед как раз для облегчения рутины, считаете нужно было пользоваться socket?

Я не говорю, что хочу создать систему основываясь на приведённом в статье коде, в этом случае действительно стоит по максимуму задействовать готовые библиотеки.

Кстати, к этому коду h264 прикрутить не сложно, в смыле сохранение видео потока без декодирования, который бы проигрывался в любом плеере. А ffmpeg у меня сейчас работает с модулем на С, который контролируется питоновским скриптом.

В любом случае спасибо за здоровую критику.
вот поэтому прежде чем выложить на хабр что-то из кода надо сто раз подумать. оформить как на выставку чтобы такие вот задроты не заипали своим перфекционизъмомъ.

У задротов прямо сейчас python код 24х365 тащит видео с 32 (пока) камер в разных концах города, перекодирует на лету в h264, раздает в браузеры и на мобильные устройства, пишет в архивы, хранит 2 недели и с сайта раздает архив любопытным или просто тем, кого въедут на перекрестке. Задроты как бы немного в теме и, в принципе, им было бы что на эту тему сказать, но… Раз не надо, то не надо.

А если кому-то вот такие вот…

051: to_send = """\
052: DESCRIBE rtsp://""" + self.config['ip'] + self.config['request'] + """ RTSP/1.0\r
053: CSeq: 2\r
054: Accept: application/sdp\r
055: User-Agent: Python MJPEG Client\r
056: \r
057: """

… изыски не кажутся похапнёй, то флаг им в руки.
Python, Gstreamer, x264, всё склеено собственным кодом (обвязки, мониторинг, обработка всяких реконнектов и т.п.)

32 камеры тащит машина (Sun Fire X4150) 8 ядер, 4 гига. Основная нагрузка — транскодинг (камеры отдают _не_ h264, приходится на лету перекодировать в то, что понимают флэш и яблоки).

Веб-морда на Pylons. нужный кусок архива по требованию достается из архива (дата-время начала, продолжительность куска).

Примерно такой же код у нас параллельно пишет (из эфира) и транслирует в городской пиринг 16 телеканалов. Отличается только непосредственно модуль забора сигнала, там естественно не с камеры по ip.

Архитектурно: несколько процессов на сущность (камера или канал) — хваталка сигнала, перекодировалка в то_что_нужно, писалка, раздавалка. Почему не потоки? Потому что потоки тут не нужны. Упал процесс, обслуживающий одну из камер, да черт с ним, остальных не тронуло.

Почему не vlc, «который все это умеет»? Потому что это дырявое ведро. Ненадежное в реальной жизни. И, кстати, в сухом остатке более прожорливое.

Самонаписанный код, аптаймы по полгода, пока админ не остановит. Аптаймы не машин, а именно самих процессов — никаких костылей типа «vlc в бесконечном цикле, если что, то рестартуем, и если памяти полтора гига сожрал, тоже рестартуем».

Код показать, естественно, не смогу.
Раз уж вы описали свою систему, можно несколько вопросов?
Скажите как у вас идёт обмен иформацией (те же видео данные) между процессами?
У меня сейчас система тоже многопроцессорная, настройка модуля захвата с v4l2 устройства после запуска осуществляется через стандартный ввод, а получение сырых видеоданных для обработки производится по UDP через lo или реальный канал, если захват идёт с удалённой машины (в этом случае уже после кодера).
Есть же ещё shared memory (которым, например, пользуется zoneminder) хотелось бы узнать на чём вы остановились.
Что вы используете в качестве сетевой прослойки: socket, twisted, gevent?
У вас кодеры тоже на питоне написаны?
Обёртка к gstreamer сразу на питоне или на C сначала?
> Скажите как у вас идёт обмен иформацией (те же видео данные) между процессами?

По UDP, всё, как у Вас.

> Есть же ещё shared memory (которым, например, пользуется zoneminder) хотелось бы узнать на чём вы остановились.

Изначально нам не хватало мощности (мы начали несколько лет назад, процессоры были другими) сложить весь транскодинг в одну машину. Поэтому (я там писал, что кроме камер кодируем еще телеканалы) делали так: 1 канал = 1 тазик. То есть захват шел «с удаленной машины», а стало быть shared memory в пролете. Ну а потом уже «зачем переделывать, если работает». Работает неплохо, плюс возможность при нужде утащить один из кубиков конструктора на другую машину, ниче не отломав при этом.

> Что вы используете в качестве сетевой прослойки: socket, twisted, gevent?

udpsink в gstreamer'е :)

> У вас кодеры тоже на питоне написаны?

Не совсем понял вопрос. С одной стороны да, процесс называется encoder.py :) С другой стороны, никто на голом питоне кодировщик в H264 не реализовывал, естественно. Просто соответствующим образом построенный pipeline для gstreamer'а, с элементом x264enc где-то в середине.

> Обёртка к gstreamer сразу на питоне или на C сначала?

Сразу gst-python, ниже лезть не понадобилось.
> Не совсем понял вопрос.
Это по сути один был вопрос про обёртку gstreamer. Надо было на одной строке их записать.

Спасибо, полезная информация.
Из подводных камней не могу не упомянуть только необходимость тщательного тестирования перед любым апгрейдом gstreamer, x264 и т.п. пакетов в дистрибутиве. Лучше всего, убедившись, что всё работает как надо, просто поставить on hold, жестоко зафиксировав установленные версии для пакетного менеджера. Иначе в один прекрасный день apt, pacman и иже с ними что-нибудь обновят, после чего кодировщик запросто начнет кушать раза в полтора больше CPU. Мы по загрузке ходили по лезвию ножа, едва укладываясь в железо, и 32 кодировщика на одной машине. Поэтому возрастание обжорства даже на 10% могло вылезти боком. 32*10% = «упёрлись и перестали успевать».

Поэтому лучше зафиксировать и не дышать. Если появятся веские основания для апдейта, то можно как следует проверить (в идеале сделать lvm снэпшот, чтобы в случае чего откатиться обратно вообще без геморроя), обновить и зафиксировать снова.
Благодарю.
Кстати, на наших машинах максимум 8 камер кодируются, в mpeg4, c x264 того же результата получить не удалось, сложно разобраться во всех этих тонких настройках кодека, битрейт получается ниже, картинка четче, но ресурсо затраты выше, если же их уменьшать, качество падает ниже mpeg4 варианта. Машины не серверные, только то, что есть в обычных магазинах.
А если 16 камер, то только уже при просмотре могут появиться артефакты (начиная где-то с 14 или 15 камеры).
Кодировать 32 камеры это, конечно, зверь машина.
У нас размер меньше. Это чисто мониторинг пробок, поэтому никакой нужды сжимать полный PAL D1 (и тем паче 720p) как бы и нет. Движется улица или стоит, прекрасно видно в CIF.

Тем более, что если просто так, «воровского форса ради» повысить разрешение до такой степени, что невзначай станут видны номера машин, можно огрести уже чисто юридических проблем.

Типа личные данные, публичный доступ, чёкаво, ктопозволил!
Как архив устроен?
Как храните, с какой глубиной, как выдаете фрагмент архива?
тогда что ж мы читаем его статью, а не Вашу? Вы не торопитесь её писать? так не надо п%%деть тогда.
>>Основная проблема в грамотном дизайне архитектуры.
Судя по коду, врядли получится, извините.

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

> тогда что ж мы читаем его статью, а не Вашу?

habrahabr.ru/blogs/image_processing/117735/#comment_3848756
А кодом сверкать мне NDA не позволит, как легко догадаться.

> Вы категорический неправы в этом, (даже если не считать это простым хамством!).

Автор, к слову, отреагировал куда конструктивнее, чем Вы. И, по большому счету, согласился.

> Я не говорю, что хочу создать систему основываясь на приведённом в статье коде,
> в этом случае действительно стоит по максимуму задействовать готовые библиотеки.
Если честно, то вам до _архитектуры_ ещё года 3-4. Это время уйдет на то, что бы понять, что это вообще всё была плохая идея.

Подобный процессинг на питоне имеет смысл только когда вы не ставите перед собой цель обслужить большое количество клиентов (> 500, если хочется какой-нибудь цифры).

То, что написано тут: github.com/erlyvideo/erlyvideo/ прожило уже немало времени и внедрений, что бы претендовать на звание «архитектуры».
Где же вы раньше были.
Замечательно что вы хотите написать что-то свое! У меня вопрос, чем вас zoneminder не устроил?
По большей части им были не довольны клиенты: не удобен в работе, не захватывает аудио. И может, конечно, это я его настраивать не умею, но при сбоях питания очень часто портится база так, что не посмотреть сохранённые ранее записи. Да и сама запись в кучу последовательных JPEG файлов несколько огорчает (даже с учётом возможности дельнейшего перекодирования, всёравно не феншуй). Сейчас где позволяет бесплатная лицензия (до 4 каналов) я использую AVReg (бывший linux-DVR), а если регистратор платный ставят, то обычно это либо GLOBOSS, либо Domination, но я ими не занимаюсь.

Так что поле свободных регистраторов ещё далеко не перепахано.
Да, пожалуй соглашусь. В ряде случаев слайдшоу не очень удобно, и на моей практике браузер через несколько часов падает.

Свой проект планируете выпускать под свободной лицензией?
Из браузеров по моим личным наблюдениям лучше всех с MJPEG справляется хром (может ещё и сафари или Konqueror, не пробывал их).

Да, по свободной.
Я писал свой детектор с помощью OpenCV. Все достаточно медленно, но в принципе реализуемо. Надо только сделать буфер чтоб при наличии движения включать запись некоторое время назад.
Просто о сложном. Спасибо, добавил в избранное!

P.S. C праздником всех!
Тоже года два назад копался с RTSP.
Камера была с IVA, хотел вытащить метаданные по IVA — ну с этим проблем не было.
Но не смог запустить декодирование h.264 видео под DirectShow там надо правильно настроить декодер вот с этим где-то я застопорился. Потом появились другие задачи, бросил.
Понятно, что задачу можно решить при помощи libvlc.
Интерено, что в моей камере тоже была эта LIVE555.
Похоже они все ее используют.
Тоже хочу заняться h.264 и MPEG4. Буду ffmpeg использовать для декодирования.
Большое спасибо за статью. Пришлась очень вовремя.
Вот у меня есть немного оффтопиковый вопрос про камеру: вы не пробовали подключаться к ней с нескольких клиентов (тех же VLC)? Как работает? Не тормозит? Да и вообще, общие впечатления от камеры какие?
Пожалуйста.
Только что подключил четыре VLC, ноут уже сильно торомзил. С одним клиентом задержка изображения составляла полторы секунды, с четырмя составила почти две с половиной секунды.
Камера мне очень нравится, шустрая, картинка хорошая, есть ночной режим. Много настроек. Может одновременно отдавать видео в нескольких форматах, может что-то записывать на microSD. Стоит такая порядка 15к, есть ещё подобная, купольная, она уже где-то 10к стоит.
Спасибо за быстрый ответ!
Присматриваюсь к камерам, надо чтобы было 720p и клиентов 5-6 могли к ней цепляться через интернет без значительных провалов в производительности. Поставлю и эту в список рассматриваемых.
Так можно же камеры прогнать через компьютер. У меня так на одном объекте 4 камеры работают, прога забирает с них изображения а далее раздаёт в интернет (в том числе и на сайт), можно регулировать частоту кадров и размер изображения. Раздаёт тоже MJPEG, но по HTTP. Если больше никакой специфики не нужно, то должны справится и другие проги такие как flumotion или ffserver.
Нет, рассчитывайте на то, что камеры наблюдения непригодны для подключения более одного клиента.

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

Так что советую придерживаться четкого правила: одна камера — одно подключение. Хочется мультиплексировать — ставьте erlyvideo и раздавайте видео с камеры на тысячи клиентов.
Спасибо, очень актуально и очень интересно.

Скажите пожалуйста, сколько будет стоить готовое решение для просмотра видео в браузере с удаленной сетевой камеры?
(короче хочется с работы видеть, что происходит дома.)
Бесплатно. На домашнем роутере пробрасываете наружу порт для камеры, далее заходите на свою камеру из-вне и смотрите изображение.
Ну, может только роутер придётся купить.
только запрос OPTIONS аналогичен в HTTP не GET, а запросу (surprise!) OPTIONS.
Спасибо, подправил.
Большое спасибо за статью и за сырец. Переписал на qt/c++ успешно работает на TRENDnet TV-IP512P.

PS
Мелкая очепятка в исходниках.
В main.py секция пароля 'password', а в файле rtsp_client.py 'pass'.
Only those users with full accounts are able to leave comments. Log in, please.