µStreamer — это легкий и очень быстрый сервер для потоковой передачи видео MJPEG с любого устройства V4L2 в сеть. Все новые браузеры имеют встроенную поддержку этого формата видео, а также большинство видеоплееров, таких как mplayer, VLC и т. д. µStreamer — это часть проекта PiKVM, предназначенного для потоковой передачи аппаратных данных скринкаста VGA и HDMI с максимально возможным разрешением и частотой кадров.
µStreamer очень похож на mjpg-streamer с плагинами input_uvc.so
и output_http.so
, однако есть некоторые существенные различия. Ключевые из них:
Особенность | µСтример | mjpg-стример |
---|---|---|
Многопоточное кодирование JPEG | ✔ | ✘ |
Аппаратное кодирование изображения на Малине Пи | ✔ | ✘ |
Поведение, когда устройство отключается во время потоковой передачи | ✔ Показывает черный экранNO SIGNAL на немпока не будет повторно подключено | ✘ Останавливает потоковую передачу 1 |
Поддержка DV-таймингов - возможность изменения разрешения на лету по исходному сигналу | ✔ | ☹ Частично да 1 |
Возможность пропуска кадров при потоковой передаче статические изображения по HTTP для экономии трафика | ✔ 2 | ✘ |
Потоковая передача через доменный сокет UNIX | ✔ | ✘ |
Активация системного сокета | ✔ | ✘ |
Журналы отладки без перекомпиляции, журнал статистики производительности, доступ к параметрам потоковой передачи HTTP | ✔ | ✘ |
Возможность обслуживания файлов со встроенным HTTP-сервером | ✔ | ☹ Только обычные файлы |
Сигнализация о состоянии потока на GPIO с помощью libgpiod | ✔ | ✘ |
Доступ к элементам управления веб-камерой (фокус, сервоприводы) и настройки, такие как яркость, через HTTP | ✘ | ✔ |
Совместимость с API mjpg-streamer | ✔ | :) |
Сноски:
1
Задолго до µStreamer я сделал патч, чтобы добавить поддержку DV-таймингов в mjpg-streamer и предотвратить его зависание при отключении устройства. Увы, патч далек от совершенства и я не могу гарантировать, что он будет работать каждый раз - исходный код mjpg-streamer очень сложен и его структуру трудно понять. Учитывая это, а также потребность в многопоточности и аппаратном ускорении JPEG в будущем, я решил создать собственный потоковый сервер с нуля вместо поддержки устаревшего кода.
2
Эта функция позволяет в несколько раз сократить исходящий трафик при потоковой передаче по HDMI, но немного увеличивает загрузку процессора. Идея состоит в том, что HDMI — это полностью цифровой интерфейс, и каждый захваченный кадр может быть побайтно идентичен предыдущему. Нет необходимости транслировать одно и то же изображение по сети несколько раз в секунду. Если включена опция --drop-same-frames=20
, µStreamer отбросит все совпадающие кадры (с ограничением в 20 подряд). Каждый новый кадр сопоставляется с предыдущим сначала по длине, а затем с помощью memcmp()
.
Если вы собираетесь вести прямую трансляцию с веб-камеры на заднем дворе и вам нужно ею управлять, используйте mjpg-streamer. Если вам нужно качественное изображение с высоким FPS – µStreamer для победы.
Вам необходимо загрузить µStreamer в вашу систему и собрать его из исходных кодов.
Вам понадобятся make
, gcc
, libevent
с поддержкой pthreads
, libjpeg9
/ libjpeg-turbo
и libbsd
(только для Linux).
sudo pacman -S libevent libjpeg-turbo libutil-linux libbsd
.sudo apt install libevent-dev libjpeg62-turbo libbsd-dev
. Добавьте libgpiod-dev
для WITH_GPIO=1
и libsystemd-dev
для WITH_SYSTEMD=1
и libasound2-dev libspeex-dev libspeexdsp-dev libopus-dev
для WITH_JANUS=1
.libjpeg62-turbo
на libjpeg62-turbo-dev
.sudo apt install build-essential libevent-dev libjpeg-dev libbsd-dev
.sudo apk add libevent-dev libbsd-dev libjpeg-turbo-dev musl-dev
. Постройте с помощью WITH_PTHREAD_NP=0
. Чтобы включить поддержку GPIO, установите libgpiod и передайте опцию WITH_GPIO=1
. Если компилятор сообщает об отсутствующей функции pthread_get_name_np()
(или аналогичной), добавьте опцию WITH_PTHREAD_NP=0
(она включена по умолчанию). Для аналогичной ошибки с setproctitle()
добавьте опцию WITH_SETPROCTITLE=0
.
Самый удобный процесс — клонировать репозиторий µStreamer Git в вашу систему. Если у вас не установлен Git и вы не хотите его устанавливать, вы можете загрузить и разархивировать исходные коды с GitHub с помощью wget https://github.com/pikvm/ustreamer/archive/refs/heads/master.zip
.
$ git clone --depth=1 https://github.com/pikvm/ustreamer
$ cd ustreamer
$ make
$ ./ustreamer --help
Предполагая, что у вас есть клон µStreamer, как описано выше, вы можете обновить µStreamer следующим образом.
$ cd ustreamer
$ git pull
$ make clean
$ make
Для аппаратного кодирования M2M на Raspberry Pi вам необходимо ядро не ниже 5.15.32. Поддержка OpenMAX и MMAL в старых ядрах устарела и удалена.
Без аргументов ustreamer
попытается открыть /dev/video0
с разрешением 640x480 и начать потоковую передачу по адресу http://127.0.0.1:8080
. Вы можете переопределить это поведение, используя параметры --device
, --host
и --port
. Например, чтобы транслировать в мир, запустите:
# ./ustreamer --device=/dev/video1 --host=0.0.0.0 --port=80
❗ Обратите внимание: поскольку в µStreamer v2.0 междоменные запросы по умолчанию отключены по соображениям безопасности. Чтобы включить старое поведение, используйте опцию --allow-origin=*
.
Рекомендуемый способ запуска µStreamer с устройством захвата на базе TC358743 на Raspberry Pi:
$ ./ustreamer
--format=uyvy # Device input format
--encoder=m2m-image # Hardware encoding on V4L2 M2M driver
--workers=3 # Workers number
--persistent # Suppress repetitive signal source errors (for example when HDMI cable was disconnected)
--dv-timings # Use DV-timings
--drop-same-frames=30 # Save the traffic
❗ Обратите внимание, что для использования --drop-same-frames
для разных браузеров вам необходимо использовать некоторые конкретные параметры URL /stream
(подробнее см. URL /
).
Вы всегда можете просмотреть полный список опций с помощью ustreamer --help
.
Добавьте следующие строки в /boot/firmware/usercfg.txt:
gpu_mem=128
dtoverlay=tc358743
Проверьте размер CMA:
$ dmesg | grep cma-reserved
[ 0.000000] Memory: 7700524K/8244224K available (11772K kernel code, 1278K rwdata, 4320K rodata, 4096K init, 1077K bss, 281556K reserved, 262144K cma-reserved)
Если он меньше 128 МБ, добавьте в /boot/firmware/cmdline.txt следующее:
cma=128M
Сохраните изменения и перезагрузитесь.
Запустить контейнер:
$ docker run --device /dev/video0:/dev/video0 -e EDID=1 -p 8080:8080 pikvm/ustreamer:latest
Затем войдите в веб-интерфейс по порту 8080 (например, http://raspberrypi.local:8080).
$ docker run --rm pikvm/ustreamer:latest
--format=uyvy
--workers=3
--persistent
--dv-timings
--drop-same-frames=30
Добавьте -e EDID=1
, чтобы установить HDMI EDID перед запуском ustreamer. Используйте вместе с -e EDID_HEX=xx
для указания пользовательских данных EDID.
Пример использования камеры Raspberry Pi v3 (требуется libcamerify
, которая находится в libcamera-tools
и libcamera-v4l2
(установите обе) на Raspbian):
$ sudo modprobe bcm2835-v4l2
$ libcamerify ./ustreamer --host :: --encoder=m2m-image
Для камеры v2 вы можете использовать тот же трюк с libcamerify
, но включите устаревший режим камеры в raspi-config
.
Пример использования камеры Raspberry Pi v1:
$ sudo modprobe bcm2835-v4l2
$ ./ustreamer --host :: -m jpeg --device-timeout=5 --buffers=3 -r 2592x1944
❗Обратите внимание, что новые модели камер имеют другое максимальное разрешение. Вы можете увидеть поддерживаемые разрешения в документации PiCamera.
❗ Если у вас низкая частота кадров, возможно, камера переключена в режим фото, в котором частота кадров низкая (но изображение более высокого качества). Это связано с тем, что bcm2835-v4l2
переключается в режим фото при разрешении выше 1280x720
. Чтобы обойти эту проблему, передайте параметры модуля max_video_width
и max_video_height
следующим образом:
$ modprobe bcm2835-v4l2 max_video_width=2592 max_video_height=1944
µStreamer поддерживает потоковую передачу с эффективной полосой пропускания с использованием сжатия H.264 и сервера Janus WebRTC. Подробную информацию см. в руководстве по интеграции Janus.
Когда uStreamer находится за прокси-сервером Nginx, его поведение буферизации приводит к задержке в видеопотоке. Можно отключить буферизацию Nginx, чтобы устранить дополнительную задержку:
location /stream {
postpone_output 0;
proxy_buffering off ;
proxy_ignore_headers X-Accel-Buffering;
proxy_pass http://ustreamer;
}
Утилиты v4l2 предоставляют инструменты для управления настройками и информацией USB-веб-камеры. Скрипты можно использовать для внесения изменений и запускать их вручную или с помощью cron. Например, запуск cron для изменения настроек экспозиции в определенное время суток. Пакет доступен во всех дистрибутивах Linux и обычно называется v4l-utils
.
v4l2-ctl --list-devices
.v4l2-ctl -d /dev/video0 --list-ctrls
.v4l2-ctl -d /dev/video0 --list-formats-ext
.v4l2-ctl -d /dev/video0 --get-ctrl=exposure_auto
.v4l2-ctl -d /dev/video0 --set-ctrl=exposure_auto=1
. Здесь вы можете найти больше примеров. Документация доступна в man v4l2-ctl
.
Copyright (C) 2018-2024 Максим Деваев [email protected]
Эта программа является свободным программным обеспечением: вы можете распространять ее и/или изменять в соответствии с условиями Стандартной общественной лицензии GNU, опубликованной Фондом свободного программного обеспечения, либо версии 3 Лицензии, либо (по вашему выбору) любой более поздней версии.
Данная программа распространяется в надежде, что она будет полезна, но БЕЗ КАКИХ-ЛИБО ГАРАНТИЙ; даже без подразумеваемой гарантии ТОРГОВОЙ ПРИГОДНОСТИ или ПРИГОДНОСТИ ДЛЯ ОПРЕДЕЛЕННОЙ ЦЕЛИ. Дополнительную информацию см. в Стандартной общественной лицензии GNU.
Вместе с этой программой вы должны были получить копию Стандартной общественной лицензии GNU. Если нет, см. https://www.gnu.org/licenses/.