Да будет запись в 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 года работы. Даже если это и произойдёт с телефоном, жалко уже не будет, заменю другим, а этого малыша с почестями провожу на покой — своё он уже с избытком мне отдаст.

Малыш трудится
Малыш трудится