Да будет запись в mp4
Я начал замечать открытые щитки у себя на этаже, в голове пронеслись мысли про favourite guys в поисках запрещённых ресурсов, потому решил озаботиться круглосуточным видеонаблюдением лестничной площадки.
Заказал на Али недорогую рыбоглазую камеру и влепил её под потолок прямо над щитком. Но мой бюджет был ограничен, а в тумбочке лежит несколько неиспользуемых Андройд телефонов, их то я и решил применить в качестве NVR устройства, вместо покупки такового. А ещё телефоны меньше жрут и совсем не шумят, в отличие от хардварных версий записывающих устройств. Встроенной карты памяти на камере нет, поэтому нужно внешнее устройство.
Загуглил, попробовал несколько программ и остановился на одной из них, которая выглядела как самая зрелая, с большим количеством функций, да ещё и платной версией. Платную версию конечно же купить у нас нельзя, но скачать её патченную сестру с 4pda можно, что я и сделал. Алексей (автор), прости, но другого варианта у меня не было.
Какие у неё функции достоинства:
поддержка большого числа вендоров камер, в том числе ноу‑нейм с поддержкой голого протокола ONVIF и RTSP
поддержка сразу нескольких подключённых камер
запись по движению или по попаданию в кадр человека
запись на локальную карту, FTP, DropBox, ownCloud\NextCloud
уведомление в группу Телеграмм
встроенный веб сервер для доступа к логам, просмотру записей, простые метрики и простые настройки
поддержка протоколов H.264 и H.265
фоновый режим работы — программу можно свернуть, но она продолжит мониторить и писать по движению
выбор из нескольких muxer для компоновки видео
Я попробовал поставить программу на планшет, его же хотел повесить на стену в качестве монитора у двери — было бы удобно. Планшет Teclast P40HD 6 Gb с процессором Unisoc T606 (8-ядерный (2 x Cortex‑A75, 6 x Cortex‑A55) 1,6 ГГц) не потянул, программу просто выбивало на старте. Ок, подумал я, и расчехлил Asus Zenfone 8 (Snapdragon 888 — 8 ядер). Программа запустилась, изображение пошло, детекция движения есть. Но есть и одно но! Даже не так, а НО! Вероятно, алгоритм детекции движения использует ML, а тот в свою очередь на 100% утилизует процессор, да так, что под его нагревом при записи пропадают кадры, много кадров выпадает из записи. Уф, подумал я, никуда это не годится.
Недостатки использованной программы:
неоптимизированный алгоритм обнаружения движения и лиц (людей) в кадре, требующий очень серьёзного железа. Анализ идет на основном потоке с максимальным разрешением, а можно было бы сделать на субпотоке - его вполне достаточно для такой задачи.
запись с пропадаем кадров, а заявленный режим прямой записи H.264 потока в файл без необходимости декодирования не работает
не записывает звук. Точнее родной андройдовский муксер не пишет звук, а другие пишут звук, но сильно обрезают качество картинки.
Андройдовский же муксер наоборот, привирал в качестве. Если сравнить запись, сделанную с помощь ffmpeg, то размер с андройда сильно больше, но качество картинки не лучше.
не умеет в ftps протокол
Ну что же, я без работы (кстати, если у кого‑то есть работа c#/js лидом — напишите, пожалуйста), люблю программировать, почему бы нам (мне и моей тревожности ИИ) не сделать самим такую программу, подумал я, и помчали.
Как все было
Далее 14 абзацев потока воспоминаний и эмоций от разработки в паре с ИИ, их можно пропустить и перейти к вызовам и выводам.
Из темы видеонаблюдения я знаю примерно ничего, уверенно владею c# и несколько раз видел код для Android. А еще это повод попрактиковаться в использовании ИИ. Выбрал DeepSeek, он работает в РФ без ВПН, он очень дёшев, и в целом меня удовлетворяет качество ответов, модель DeepSeek V4 Pro. В качестве агента — Zed, как раз не так давно его здесь же хвалили, основной редактор — Visual Studio. Пробуем, что получится.
Начинаю общаться в чате (в веб версии, чтобы не тратить платные токены) с ИИ, спрашиваю про протокол ONIF, узнаю про протокол вещания RTSP, спрашиваю как на c# с ними работать. Первый ответ есть — библиотека SharpRtsp. Создаю проект, библиотека и консольный клиент, чтобы проверять гипотезы.
Итак, поток с камеры получаю, голые NAL юниты вижу. Дипсик помогает разобраться в видах и тапах юинов, чем отличается H.264 от H.265. Пробую делать запись. Нахожу библиотеку SharpMP4 того же автора, делаю тестовую запись, пока тоже без звука — картинка есть. ИИ делает код кольцевого буфера, который должен хранить n последних секунд вещания, чтобы запись начиналась не с момента движения, а за эти n секунд до неё. Качество удовлетворяет.
Двигаемся дальше. Никакой архитектуры, код лапша, но мы же проверяем гипотезы. Главный вопрос — а как обнаруживать движение? В голове взрослый вариант — нужно с помощью ML анализировать кадры, расшифрованное из потока изображение. Но я хочу использовать для этого не самый крутой телефон, в ходе инвентаризации мой выбор пал на Sharp Aquos 2 (Snapdragon 630, 4 ядра Cortex‑A53 на 2200 МГц и 4 ядра Cortex‑A53 на 1800 МГц., 4 Гб ОЗУ).
Прошу ИИ написать код анализатора на основе сырых NAL юнитов. Первый значимый код от ИИ в проект готов. Проверяю — много ложно‑положительных и ложно‑отрицательных детекций. Скармливаю логи, он анализирует, переписывает код. Снова не то. Ещё итерация. Опять нет. Голова уже не варит, не понимаю что он делает, просто мешанина какого-то кода, нужно сделать перерыв.
Пробую ещё и прихожу к выводу, что камера слишком шумит, сделать такой анализатор не получится. Торг прошёл, депрессия, принятие. Нужно анализировать изображение. Но как с этим справится телефон? И тут мне приходит осознание. Та программа использовала для анализа изображение с основного потока в полные 4К, но ведь камера шлёт ещё один дополнительный поток 640×480, этого вполне достаточно, чтобы распознать движение. Осталось только маленькая проблема — а где взять это изображение. Нашли библиотеку для декодирования H264 потока в изображения.
ИИ пишет анализатор на основе разбиения изображения на квадраты и сравнения средней яркости области. Первый же тест — восхищение, работает. Есть вопросы к коду, прошу сделать правки — стало сильно лучше.
Пора делать графический интерфейс. Выбираю .Net MAUI, кроссплатформенный интерфейс из коробки. ИИ пишет интерфейс, основное окно, окно просмотра логов и настроек. Я в восторге, я бы руками это несколько дней делал. На Windows все работает хорошо, запускаю на Sharp S2 — тормоза, на Asus со скрипом. Чешем затылки. MAUI тормоз из коробки, выкидываем, заменяем на Mono for Android. Вторая проблема — сам алгоритм. На i7 один кадр анализируется 4 мс, на Sharp S2 >100 мс. ИИ предлагает сделать правки, делает. Стало несколько лучше, но не на много. Поток идёт в 15 fps, а это 15 кадров в 1000 мс, тоесть 66 мс на кадр. Кровь из носа, но нужно уложиться в это ограничение, иначе ничего не выйдет.
Тут ИИ начал тупить и делать херню. Случился забавный момент, я придумал решение, но не захотел ему полностью объяснять, а по шагам реализовать, но эта тварь отказывалась! — «я не думаю, что этот код будет лучше и быстрее, оставляю все как есть, мой вариант вам подходит больше». Я был в ярости, выругался на него матом, он согласился наконец и сделал. Я допилил код руками, попросил его перечитать файл и оценить правки. «Красиво!». Красиво, красиво — была его оценка и ответ. Меня похвалил ИИ. Я не знаю что чувствовать. На Sharp S2 оценка одного кадра занимает около 40 мс, на i7 — 1 мс.
Ещё некоторое время мы допиливали приложение, научились декодировать звук из камерного протокола G711A в ААС, записывать это в mp4 поток. Пробовали стандартный muxer от Anrdoid, но как я говорил, он с качеством очень портачит, вернулся на SharpMP4. Храни, Макаронный Монстр, опенсурс!
Последним промтом было задание заполнить файл Readme.md, в том числе записать цели и задачи проекта, которые я, естественно ИИ не говорил.
Цель: создать лёгкое, автономное решение для круглосуточной записи с IP-камер по RTSP, которое.... Работает на слабых устройствах (Android-приставки, одноплатники, Raspberry Pi) без GPU.
Задача: заменить громоздкие NVR-системы простым .NET-приложением, которое можно запустить на любом Android-устройстве или Windows-машине.
Все это ИИ понял сам исходя из нашего с ним трёх недельного общения и успешно использовал в выводах, при этом, акцент жирным на словах "слабых устройствах" он сделал сам.
Какой вызов я решил
Самым сложным, конечно же, было создание детектора движения. Изначально по моему настоянию ИИ предложил анализировать I юниты. Это такие юниты в потоке вещания, которые передают изменение картинки по сравнению с предыдущим состоянием. Косвенно, по размеру юнита по сравнению с предыдущими и по его содержимому (много хаотичных нулей и единиц) можно понять, что на кадре присутствует движение. Метод оказался ненадёжным, т.к. моя камера слишком шумит.
Вторым решением стало декодирование второго, субпотока, разрешением 640x480 пикселей в изображения и анализ уже именно изображений. ИИ применил метод сравнения средней яркости блока, и это заработало. Мы долго обсуждали и выверяли с ним этот код, самым правильным и надёжным методом является использование медиан, но это очень тяжёлый алгоритм, телефону не хватает мощности его обрабатывать в отведённое время. Мы перешли на использование скользящего среднего (EMA), но тогда появилась проблема с ложным срабатываем в моменты включения и отключения освещения в подъезде, что было решено добавлением фильтра на всплески яркости. Код анализатора из красивого SOLID ООП превратился в C-лапшу с глобальными переменными ради оптимизации под запуск на слабых устройствах, но цель была достигнута - 40 мс на анализ кадра на старом телефоне, что меньше критического значения в 66 мс на кадр при 15 fps.
Детектором движения я полностью доволен. В камере есть свой детектор, он способен при обнаружении движения отправлять уведомление по протоколу Alarm. Работает это так: при возникновении движения отправляет json с сообщением «движение появилось», при окончании — «движение пропало», промежуточных keepalive не предусмотрено, поэтому я побоялся использовать его как основной источник, потому что не понимаю, как обрабатывать ситуацию, если по какой‑то причине потеряется сообщение об окончании. ОПЭ нескольких дней показала, что мой и встроенный детектор работают совершенно синхронно, ну кроме того, что я исключаю ложные срабатывания на включение и выключение освещения в подъезде, а камера нет.
Что умеет программа
работа только с протоколом сжатия видео H.265
анализ потока с камеры на наличие движения
запись видео при наличии движения, n секунд до начала движения и m после, все хранится в настройках
запись звука
наличие встроенного простого веб сервера
m3u плейлист для воспроизведения последних записей за 24 часа на vlc плеере
Что не умеет
нет поддержки H.264
пока нет ротации файлов (хранить не более n дней и\или m мб)
только одна камера, т.к. у меня одна. Может быть сделаю поддержку большего количества камер чисто ради спортивного интереса
нет фонового режима, приложение должно быть всегда запущено. Наверное можно и свернуть, но нужно подкрутить настройки телефона, чтобы ради экономии батареи он не убивал неактивные процессы
настройки чувствительности анализатора пока зашиты в код, наверное нужно вынести в настройки приложения
аутентификации у веб сервера нет, пока не планирую открывать к нему доступ из интернета
не умеет управлять движением камеры (PTZ), т.к. у меня камера статичная
нет пресетов по настройке изображений. Ума не приложу, как этим можно и зачем пользоваться
Вместо выводов
За три недели и примерно 40 часов чистого времени я сделал для себя приложение в незнакомом стеке (под Андройд), которое без ИИ даже не осмелился бы начать.
ИИ делал каркасы, писал MVP код, а потом доводил его до ума, делал ошибки и сам же их потом правил.
ИИ — это очень сильный помощник для разработчика. Как оценить его уровень, что это такое? С одной стороны, ИИ сильно умнее меня, его кругозор и набор инженерных практик, собранных с миллионов других разработчиков, превосходит тысячекратно мои возможности. С другой стороны, он ленивый и льстивый, если его не просить делать хорошо, он будет делать на отвали, как попало, лишь бы работало, соглашается почти со всем, что я ему говорю и сознательно (иронично, да?) допускает ошибки, создаёт технический долг. Я не использовал субагентов, у меня даже нет agent.md файла, личность ИИ уже на столько хороша, что нет никакой надобности давать ему ещё какие‑то дополнительные инструкции.
Я понимаю как тим лид, почему все увольняют разработчиков и почему мы становимся все меньше и меньше нужны. Мне не потребовалось три мидла и два жуна, чтобы сделать это приложение, они бы делали его куда дольше. Тем не мнее, не надо питать иллюзий, что средне статистический менеджер сможет написать программу сам с помощью ИИ без привлечения специалистов по разработке. Все демо кейсы с туду листами вызывают эйфорию, но в реальности же сделать качественно приложение с соблюдением всех нефункциональных требований, и даже функциональных, без создания дыр в безопасности и тонн техдолга, вряд ли под силу своре агентов, для работы с этим инструментом нужен инженер, который понимает в технологиях.
Ну и ссылка на репозитарий https://github.com/for7raid/RtspCameraRecorder
Дисклеймер. Проект писался почти полностью с помощью ИИ, однако данная статья принципиально написана только белково-жировой массой с извилинами, даже редактуру не делал, а все длинные тире ставит встроенный в хаброредактор типограф.
Всем бобра и макарошек с тефтельками.
P. S. За постоянно подключённый аккумулятор к сети не беспокоюсь. Видимо зависит от качества электроники, на стене сменил уже три планшета (ранее была погода и часы, но с закрытием Я.Погоды своего АПИ теперь только часы, ну то есть в прямом смысле работает как часы) и только у одного вздулся аккум через 2 или 3 года работы. Даже если это и произойдёт с телефоном, жалко уже не будет, заменю другим, а этого малыша с почестями провожу на покой — своё он уже с избытком мне отдаст.
