Как стать автором
Обновить

Python, Go или… готовим сырой видеопоток с полсотни камер

Уровень сложностиСредний
Время на прочтение8 мин
Количество просмотров11K
Всего голосов 20: ↑19 и ↓1+20
Комментарии22

Комментарии 22

В сторону gstreamer не смотрели? Он вроде как раз под потоковую работу с видео заточен

В определенный момент косились в его сторону, но время серьезно поджимало и экспериментировать не стали. Сделали выбор в пользу знакомого стека. Решили, что иначе можем нарваться на новые, непонятные подводные камни.

Есть приблуда от nvidia и intel. DeepStream и DLStreamer соответственно.

Советую использовать интеловские. в DS много багов лик и оч странных решений в ключевых плагинах.

Например, можно взять ThreadPool ... Такой подход позволяет ускорить обработку кадров и эффективно управлять большим объемом данных. Однако, в случае неупорядоченных потоков, такого рода параллельная обработка может привести к трудностям с поддержанием правильного порядка кадров, не говоря о том, что этот вариант требует дополнительных усилий для управления синхронизацией.

Для каждого кадра вы же храните timestamp, значит не должно быть проблем с параллельным препроцессингом. Порядок кадров по timestamp можно будет восстановить.

Для выполнения различных операций, связанных с видеопотоками, включая захват, обработку и анализ видеоданных мы используем OpenCV. Библиотеку удалось оптимизировать для работы с GPU.

Можете объяснить как вам удалость запустить функции библиотеки OpenCV на GPU?

"для работы с GPU", а не на GPU.
Тут речь о том, чтобы:
1. собирать ffmpeg оптимизированный под gpu: https://docs.nvidia.com/video-technologies/video-codec-sdk/12.0/ffmpeg-with-nvidia-gpu/index.html
2. Собрать OpenCV с включенным ffmpeg-ом в конфигурациях сборки. Если в системе несколько версий ffmpeg-а, то указать конкретно нашу в конфигурациях. Если в дальнейшем предполагается работа на питоне, то конфигурировать сборку питон версии.

В статье из Википедии про RTSP, ссылку на которую Вы привели, сказано, что видео по RTSP не передаётся, для этого есть протокол RTP. Мой опыт разработки плеера для систем видеонаблюдения это подтверждает. По RTSP клиент и сервер договариваются о передаче данных и управляют ей командами PLAY, PAUSE и т.п. Сам видеопоток идет как раз по RTP. Что за пакеты Вы складывали в буфер FFmpeg? У FFmpeg есть библиотеки libavformat, libavcodec и т.п. и, соответственно, возможность встраивания в другой софт. Она прекрасно умеет парсить RTSP и даже декодировать видео на GPU через DirectX Video Acceleration (DXVA2). Поглядите исходники VLC, там всё есть. Единственная проблема, с которой мне пришлось столкнуться (лет 15 назад я это писал) - это какие-то глобальные константы внутри libavcodec, из-за чего вызов libavcodec_decode приходилось оборачивать в мьютексы. Возможно, уже все исправили, 15 лет прошло с тех пор.

Ваше описание архитектуры приложения довольно поверхностное, но кажется, там много неоптимального.

Это скорее статья про ошибки, которые могут наделать новички, они часто используют OpenCV на питоне. Если глубоко разбираться в видеонаблюдении можно сделать красивее. У нас такой задачи не было, на этом этапе просто нужен был более менее оптимальный ридер, который не убивает CPU, GPU и оперативку.

В основе ffmpeg-а лежит libavcodec, и с ним можно работать напрямую. Мы об этом думали, но не хватало опыта конкретно в этом аспекте, опять же, все уперлось в сроки.

Насчет буфера, мы действительно туда ничего не кладем, ffmpeg это делает сам. Кто конкретно создает пакеты (ffmpeg или libavcodec) в буфер с ходу не скажу, так как мы работаем с этими библиотеками не напрямую, а через OpenCV. Но буфер там есть, и его нужно прокручивать, так это реализовано в OpenCV.

4218R всего 8 камер...?HEVC?FULL HD 25FPS?Както маловато...

У меня DL380GEN8, 4x4650v2 120 камер вывозит без GPU с процессингом в OpenCv, на питоне но правда с трюком... Часть камер декодит только I фрэймы через PyAv, но в целом заключение верное Python,GIL, смерть. У меня LXC контейнер поднят под каждый процессинг. Нейронки.. Triton, TRT, ONNX на отдельном сервере. Но 600FPS nvdec с "1650" вы правы грех не использовать).

Шёл 2023 год, а байки про GIL всё еще кочуют между статьями. Про существование контейнеризации, Threading, Multiprocessing и Asyncio авторы статей всё еще не подозревают и продолжают копировать один и тот же текст в надежде срубить классов на одной и той же байке.

А какой у вас кодек на входе, раз вы позволяете себе играть с кадрами до ffmpeg?

P. S. Кажется большую часть описанного можно заменить gstreamer пайплайном. Я бы даже сказал, что всё, кроме отправки в redis

На входе кодек H264. Для дальнейшей оптимизации действительно планируем работу уже через gstreamer.

Пожалуйста поправьте меня, если я что-то не так понимаю. К вам идёт поток кадров в h264 и вы делаете пропуск ещё закодированных кадров? Как такое вообще работает?

Если пропустил P фрэйм, жди следующего I фрэйма и декодируй стрим дальше. В частности можешь держать поток в сонном режиме делая demux и раскодируя только I кадры. Если обнаружил движение между I - начинай декодировать полностью.

Через pyav я такой подход реализовывал.

Лет 5 назад видел подобное на c#, было что-то под 200 потоков в 2 мегабита на сервер, все на cpu, сколько ядер не помню

Видеоридер - это же один микросервис? Из статьи это не слишком понятно. Если несколько - то зачем, и как между ними передаются сырые кадры?


В целом, непонятно, зачем в этой задаче OpenCV. Навскидку, у вас 3 как минимум 3 опции было:
1. Всю вашу логику прореживания кадров сделать в фильтр-чейне ffmpeg, и сделать на питоне запускалку ffmpeg-ов, по одному под кажду камеру, ну и jpeg-и потом закидывать в редис.
2. Всё то же самое, только вместо ffpmeg взять gstreamer, как предлагали выше.
3. Более сложный путь, но с максимальным контролем - взять/сделать cgo биндинги для libav и написать всю логику на гошке, а libav использовать для демультиплексирования, декодирования и кодирования.

С этой точки зрения все верно, OpenCV действительно можно было бы не использовать, как и бекэнд ffpmeg. У нас в этом была «историческая нужда» и ограничение по срокам, не было задачи все переделать. Вместо OpenCV можно было бы попробовать общаться напрямую с библиотеками, такой вариант более удобен и оптимизирован. По поводу использования gstreamer`а — да, есть вероятность, что в будущей версии мы так и поступим, снова пересобрав видеоридер на Python. Сама статья написана скорее в контексте рассказа о том, с какими ошибками нам пришлось столкнуться, и какое решение было реализовано.

Для декорирования видео у карты какой то свой отдельный блок, его загрузка рисуется в Taskmanager Windows. Не знаю уж, что вы оптимизировали в языках, но если натравить на ртсп ffmpeg и брать кадры через пайп то уже 60 камер по 1280х720 полностью загружают современные видеокарты. Именно карту, все остальное свободно. Cuda при этом не используется, только блок декодирования. И неважно, кто запускает ffmpeg, у меня есть проект с с++ и python, от языка это не зависит, ведь вся нагрузка в другом процессе. Вытащить из пайп кадры может любой калека

В общем как-то совсем ваша информация с моим опытом не стыкуется. 40 fullhd просто кладут карту на лопатки, даже при дешифровки пяти кадров в секунду.

Что касается Cuda, продублирую ссылку из ответа выше. Cuda в нашем случае помогает компиляции ffpmeg, а сама оптимизация позволяет задействовать на этом фреймворке половину вычислительных процессов. С++ использовать тоже не обязательно, но процесс уже был запущен — питоновская версия была переписана на Golang, а он нам не подходил. Видеоридер, переписанный на С++ требовал сборки ffmpeg, работающей на GPU с подключением OpenCV. Таким образом, проблема питоновской версии была в отсутствии многопоточности и в том, что на этапе подключения нашей команды, этой версии уже не существовало. Логично предположить, что текущую версию видеоридера можно пересобрать на питоне, с учетом новых моментов и подключения gstreamer.

Есть опыт подобный. Идея с микросервисом норм. Заюзайте только GoCv либу. Подключение делали через ffmpeg. Opencv неплохо но имеет буферизацию которая не подходит тут по кейсу. Но остальные функции у нее можно брать.

Имел опыт создание такого же проекта с видеопотоками и трекингом обьектов. Только я изначально стал писать на С++ и реализовал свои так называемые видеоридеры через ffmpeg api + nvidia codec sdk, все это работало в параллельных cuda steam‘ах на множестве видеокарт. Только к меня архитектура была связана видеоридером и инференсом нейронки, т.к. декодированные на гпу кадры можно было без выгрузки на цпу передавать нейронке.

На питоне можно делать только прототип проекта чтоб быстро на коленке что-то накалякать, для серьезных продакшен задач он не подходит. Да он вообще до мало чего подходит, если честно. Единственный его плюс это легкий вкат для новичков

Зарегистрируйтесь на Хабре, чтобы оставить комментарий