13 KiB
µStreamer
µStreamer - это маленький и очень быстрый сервер, который позволяет организовать трансляцию видео в формате MJPG с любого устройства V4L2 в сеть. Этот формат нативно поддерживается всеми современными браузерами и большинством приложений для просмотра видео (mplayer, VLC и так далее). µStreamer был разработан в рамках проекта Pi-KVM специально для стриминга с устройств видеозахвата VGA и HDMI с максимально возможным разрешением и FPS, которые только позволяет железо.
Функционально µStreamer очень похож на mjpg-streamer при использовании им плагинов input_uvc.so и output_http.so, однако имеет ряд серьезных отличий. Основные приведены в этой таблице:
| Фича | µStreamer | mjpg-streamer |
|---|---|---|
| Многопоточное кодирование JPEG | ||
| Аппаратное кодирование с помощью OpenMAX IL на Raspberry Pi | ||
| Поведение при физическом отключении устройства от сервера во время работы |
с надписью NO SIGNAL,пока устройство не будет подключено снова |
|
| Поддержка DV-таймингов - возможности изменения параметров разрешения трансляции на лету по сигналу источника (устройства видеозахвата) |
||
| Возможность пропуска фреймов при передаче статического изображения по HTTP для экономии трафика |
||
| Стрим через UNIX domain socket | ||
| Дебаг-логи без перекомпиляции, логгирование статистики производительности, возможность получения параметров трансляции по HTTP |
||
| Возможность сервить файлы встроенным HTTP-сервером |
||
| Вывод сигналов о состоянии стрима на GPIO с помощью libgpiod |
||
| Поддержка контролов веб-камер (фокус, движение сервами) и всяких настроек, типа яркости, через HTTP |
||
| Совместимость с API mjpg-streamer'а | :) |
Сносочки:
-
1Еще до написания µStreamer, я запилил патч, добавляющий в mjpg-streamer поддержку DV-таймингов и предотвращающий его зависание при отключении устройства. Однако патч, увы, далек от совершенства и я не гарантирую его стопроцентную работоспособность, поскольку код mjpg-streamer чрезвычайно запутан и очень плохо структурирован. Учитывая это, а также то, что в дальнейшем мне потребовались многопоточность и аппаратное кодирование JPEG, было принято решение написать свой стрим-сервер с нуля, чтобы не тратить силы на поддержку лишнего легаси. -
2Это фича позволяет в несколько раз снизить объем исходящего трафика при трансляции HDMI, однако немного увеличивает загрузку процессора. Суть в том, что HDMI - полностью цифровой интерфейс, и новый захваченный фрейм может быть идентичен предыдущему в точности до байта. В этом случае нет нужды передавать одну и ту же картинку по сети несколько раз в секунду. При использовании опции--drop-same-frames=20, µStreamer будет дропать все одинаковые фреймы, но не более 20 подряд. Новый фрейм сравнивается с предыдущим сначала по длине, а затем помощьюmemcmp().
TL;DR
Если вам нужно вещать стрим с уличной камеры и управлять ее параметрами - возьмите mjpg-streamer. Если же вам нужно очень качественное изображение с высоким FPS - µStreamer ваш бро.
Сборка
Для сборки вам понадобятся make, gcc, libevent с поддержкой pthreads, libjpeg8/libjpeg-turbo, libuuid и libbsd (только для Linux).
- Arch:
sudo pacman -S libevent libjpeg-turbo libutil-linux libbsd. - Raspbian:
sudo apt install libevent-dev libjpeg8-dev uuid-dev libbsd-dev. Добавьтеlibraspberrypi-devдля сборки сWITH_OMX=1иlibgpiodдляWITH_GPIO=1. - Debian:
sudo apt install build-essential libevent-dev libjpeg62-turbo-dev uuid-dev libbsd-dev. - Ubuntu 20.04 x86_64:
sudo apt install build-essential libevent-dev libjpeg62-dev uuid-dev libbsd-dev make gcc libjpeg8 libjpeg-turbo8 libuuid1 libbsd0.
На Raspberry Pi программу можно собрать с поддержкой OpenMAX IL. Для этого передайте make параметр WITH_OMX=1. Для включения сборки с поддержкой GPIO установите libgpiod и добавьте параметр WITH_GPIO=1. Если при сборке компилятор ругается на отсутствие функции pthread_get_name_np() или другой подобной, добавьте параметр WITH_PTHREAD_NP=0 (по умолчанию он включен). При аналогичной ошибке с функцией setproctitle() добавьте параметр WITH_SETPROCTITLE=0.
$ git clone --depth=1 https://github.com/pikvm/ustreamer
$ cd ustreamer
$ make
$ ./ustreamer --help
Для Arch Linux в AUR есть готовый пакет: https://aur.archlinux.org/packages/ustreamer. На Raspberry Pi програма автоматически собирается с поддержкой OpenMAX IL, если обнаружит нужные хедеры в /opt/vc/include.
Порт для FreeBSD: https://www.freshports.org/multimedia/ustreamer.
Использование
Будучи запущенным без аргументов, ustreamer попробует открыть устройство /dev/video0 с разрешением 640x480 и начать трансляцию на http://127.0.0.1:8080. Это поведение может быть изменено с помощью опций --device, --host и --port. Пример вещания на всю сеть по 80-м порту:
# ./ustreamer --device=/dev/video1 --host=0.0.0.0 --port=80
❗ Обратите внимание, что начиная с версии µStreamer v2.0 кросс-доменные запросы были выключены по умолчанию по соображениям безопасности. Чтобы включить старое поведение, используйте опцию --allow-origin=\*.
Рекомендуемый способ запуска µStreamer для работы с Auvidea B101 на Raspberry Pi:
$ ./ustreamer \
--format=uyvy \ # Настройка входного формата устройства
--encoder=omx \ # Использование аппаратного кодирования с помощью OpenMAX
--workers=3 \ # Максимум воркеров для OpenMAX
--persistent \ # Не переинициализировать устройство при таймауте (например, когда был отключен HDMI-кабель)
--dv-timings \ # Включение DV-таймингов
--drop-same-frames=30 # Экономим трафик
❗ Обратите внимание, что для использования --drop-same-frames для разных браузеров нужно использовать ряд специальных параметров в /stream (за деталями обратитесь к урлу /).
За полным списком опций обращайтесь ко встроенной справке: ustreamer --help.
Смотрите также
- Запуск с помощью systemd-сервиса.
- uStreamer Ansible Role: Использование Ansible для сборки и установки стримера как systemd-сервиса.
Лицензия
Copyright (C) 2018 by Maxim Devaev mdevaev@gmail.com
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program. If not, see https://www.gnu.org/licenses/.