Обновить

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

В нынешних реалиях интересней было бы замаскировать трафик VPN под поток JPEG-video

В теории да, на уровне RTP это расширяемо. В RTP заголовке payload type 96–127 это "свободная зона". Число ничего само по себе не означает, пока стороны не договорились, что за формат за ним скрывается.

В SDP можно указать:

a=rtpmap:96 JPEG/90000

После этого PT=96 начинает означать "JPEG по RFC 2435", в рамках этой сессии.

Но программный encoder на ESP32-S3 для JPEG XL будет кушать CPU и память, и придется писать свой плеер, потому что на сегодняшний день нет стандартизированного RTP payload.

Интересно. А можете поподробней про аппаратное "Для экспериментов я использовал готовый модуль... " То есть как подключить, что подсоединить к ПК, что открыть на компьютере для отображения видео по вашему протоколу.

Модуль и проект в репозитории, это просто пример. Их можно (и нужно) подстроить под свои задачи: другую камеру, микроконтроллер.

Я не стал вдаваться в детали аппаратной части, потому что хотел объяснить, как работают RTP/JPEG и как они выглядят на уровне байтов.

На официальном сайте есть инструкция, как подключить его и начать с ним работать в Arduino IDE https://wiki.seeedstudio.com/xiao_esp32s3_getting_started/.

Я использовал ESP-IDF (Espressif IoT Development Framework) это официальный фреймворк и SDK от компании Espressif для разработки прошивок, через расширение в VS Code https://docs.espressif.com/projects/esp-idf/en/stable/esp32/get-started/index.html#installation

А чтобы включить стрим, нужно просто открыть файл SDP в VLC, в репозитории я положил их для примера.

Подскажите, много ли доработок потребуется, чтобы запустить это на esp32cam c камерой от AI Thinker?

Спорное утверждение, что транспорт RTP UDP лучше для MJPEG потока, чем обычный HTTP. Но в образовательных целях статья отличная. Все особенности JPEG внутри RTP описаны довольно подробно и точно.

На реализацию того же самого на языке go можно посмотреть тут
https://github.com/AlexxIT/go2rtc/blob/master/pkg/mjpeg/rtp.go

Пару лет назад пришлось попотеть.

Кстати у браузера Chrome был (и возможно всё ещё есть баг), что он отображает MJPEG поток с задержкой в 1 кадр. То есть отображает прошлый кадр только когда прийдёт следующий. Чтоб эту задержку победить - можно написать свой собственный MJPEG клиент. Он тоже есть в вышеупомянутом проекте.

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

У вас довольно известный и мощный проект.

Нашёл место о котором вы говорите
https://github.com/pikvm/ustreamer/blob/94752dde757cabde0e629f8b75d29e09e5ef2140/src/ustreamer/http/server.c#L647-L653

Какой-нибудь "маргинальный браузер" это как раз мой проект :)
Я не стал делать поддержку MJPEG без Content-Length. Были даже пользователи, которые жаловались на это. Возможно это как раз ваши пользователи.

У меня конечно есть поддержка автоматического поиска конца JPEG кадра. Но она работает только для формата, где кадры идут один за другим, без HTTP multipart заголовков. Возможно стоит усложнить код и MPJPEG формата (как его именует FFmpeg).

Кстати в таких глобальных проектах как ваш правильнее писать комменты на английском языке.

Я не стал делать поддержку MJPEG без Content-Length. Были даже пользователи, которые жаловались на это. Возможно это как раз ваши пользователи.

Вряд ли мои. Логика с отправкой заголовков наперед и отключением Content-Length по умолчанию выключена, и предполагается, что она должна включаться явным образом из JS для нужного браузера. В КВМ я его включаю для всех браузеров на Blink - у них у всех одинаковые баги, и им всем не нужен Content-Length. У WebKit другие баги, а вот у FF все работает нормально.

Кстати в таких глобальных проектах как ваш правильнее писать комменты на английском языке.

Я просто пишу как бог на душу положит в конкретный момент %)

Очень круто, мое почтение.

Правда, я хочу оспорить тезис про то, что MJPEG не пригоден для реального времени %) Браузеры именно что отрисовывают кадр "как только - так сразу", и все проблемы были в основном из-за не слишком шустрых серверов.

Собственно, я автор PiKVM, и первой проблемой много лет назад, с которой я столкнулся, когда начал его делать - тормознутость всех существующих mjpeg-серверов. Пришлось писать свой с нуля, специально проектируя его для нулевой задержки на каждом этапе и обходя родовые травмы браузеров (камент выше). Оказалось, что MJPEG можно сделать настолько реалтаймовым, что будет даже комфортно работать с этим потоком, как за удаленным рабочим столом. Можно даже применить некоторые оптимизации, чтобы сильно уменьшить трафик - сделать фреймрейт динамическим, если не отправлять одни и те же фреймы, если экран не меняется (но при этом не реже определенного значения, чтобы браузер не отстрелил соединение по таймауту).

Работает это просто прекрасно, но мы уже перешли на H.264, а MJPEG остался для легаси VNC и дубовой совместимости.

Не сравнивали производительность с вот этой реализацией https://github.com/esp-cpp/camera-streamer ? Там тоже RTP over UDP, и еще RTSP дополнительно.

Еще интересно, современные ESP32 сколько FPS уже выдать могут ? Старая ESP32CAM могла только до 30FPS в mjpeg упаковать и отправить по WiFi, и то в самом низком разрешении (320х240).

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

Публикации