Стримим экран на несколько устройств по сети

Стримим экран на несколько устройств по сети

Возникла у меня необходимость выводить дашборд с мониторингом на несколько экранов в офисе. В распоряжении имеется несколько стареньких Raspberry Pi Model B+ и гипервизор с практически неограниченным количеством ресурсов.

По видимому Raspberry Pi Model B+ не обладает достаточной произвольностью чтобы держать постоянно запущенным браузер и отрисовывать большое количество графики в нем, из-за чего бывает, что страница частично глючит и часто вылетает.

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

Как известно все Raspberry имеют достаточно мощный видеопроцессор, который отлично подходит для аппаратного декодирования видео. Так появилась идея запускать браузер с дашбордом где-нибудь ещё, а на малинку передавать готовый поток с отрендеренной картинкой.

Плюс ко всему это должно было упростить управление, так как в данном случае вся настройка будет выполняться на одной виртуалке, которую проще обновлять и бэкапить.

Сказано – сделано.

Серверная часть

Мы воспользуемся готовым Cloud Image для Ubuntu. Не требуя установки, он содержит всё необходимое для быстрого развертывания виртуальной машины, а поддержка Cloud-Init помогает моментально настроить сеть, добавить ssh-ключи и быстро ввести ее в строй.

Разворачиваем новую виртуалку и первым делом установим на ней Xorg, nodm и fluxbox:

apt-get update
apt-get install -y xserver-xorg nodm fluxbox
sed -i 's/^NODM_USER=.*/NODM_USER=ubuntu/' /etc/default/nodm

Так же воспользуемся конфигом для Xorg, любезно предоставленным нам Diego Ongaro, добавив только новое разрешение 1920×1080, так как все наши мониторы будут использовать именно его:

cat > /etc/X11/xorg.conf <<EOT
Section "Device"
    Identifier      "device"
    Driver          "vesa"
EndSection

Section "Screen"
    Identifier      "screen"
    Device          "device"
    Monitor         "monitor"
    DefaultDepth    16
    SubSection "Display"
        Modes       "1920x1080" "1280x1024" "1024x768" "800x600"
    EndSubSection
EndSection

Section "Monitor"
    Identifier      "monitor"
    HorizSync       20.0 - 50.0
    VertRefresh     40.0 - 80.0
    Option          "DPMS"
EndSection

Section "ServerLayout"
    Identifier      "layout"
    Screen          "screen"
EndSection
EOT

systemctl restart nodm

Теперь установим Firefox, запускать мы его будем как system сервис, так что за одно и напишем unit-файл для него:

apt-get install -y firefox xdotool

cat > /etc/systemd/system/firefox.service <<EOT
[Unit]
Description=Firefox
After=network.target

[Service]
Restart=always
User=ubuntu
Environment="DISPLAY=:0"
Environment="XAUTHORITY=/home/ubuntu/.Xauthority"
ExecStart=/usr/bin/firefox -url 'http://example.org/mydashboard'
ExecStartPost=/usr/bin/xdotool search --sync --onlyvisible --class "Firefox" windowactivate key F11

[Install]
WantedBy=graphical.target
EOT

systemctl enable firefox
systemctl start firefox

Xdotool необходим нам для того что-бы запускать firefox сразу в полноэкранном режиме.
Используя параметр -url можно указать любую страницу чтобы она открывалась автоматически при запуске браузера.

На этом этапе наш киоск уже готов, но теперь нам нужно экспортировать картинку по сети на другие мониторы и устройства. Для этого мы воспользуемся возможностями Motion JPEG, формата который чаще используется для стриминга видео с большинства web-камер.

Для этого нам понадобится две вещи: FFmpeg с модулем x11grab, для захвата картинки с иксов и streamEye, который будет раздавать ее нашим клиентам:

apt-get install -y make gcc ffmpeg 

cd /tmp/
wget https://github.com/ccrisan/streameye/archive/master.tar.gz
tar xvf master.tar.gz 
cd streameye-master/
make
make install

cat > /etc/systemd/system/streameye.service <<EOT
[Unit]
Description=streamEye
After=network.target

[Service]
Restart=always
User=ubuntu
Environment="DISPLAY=:0"
Environment="XAUTHORITY=/home/ubuntu/.Xauthority"
ExecStart=/bin/sh -c 'ffmpeg -f x11grab -s 1920x1080 -i :0 -r 1 -f mjpeg -q:v 5 - 2>/dev/null | streameye'

[Install]
WantedBy=graphical.target
EOT

systemctl enable streameye
systemctl start streameye

Так как наша картинка не требует быстрого обновления, я указал частоту обновления: 1 фрейм в секунду (параметр -r 1) и качество сжатия: 5 (параметр -q:v 5)

Теперь пробуем зайти на http://your-vm:8080/, в ответ вы увидите постоянно обновляемый скриншот рабочего стола. Отлично! — то что и было нужно.

Клиентская часть

Здесь все еще проще, как я уже сказал использовать мы будем Raspberry Pi Model B+.

Первым делом установим на нее Arch Linux ARM, для этого следуем инструкции на официальном сайте.

Нам также потребуется выделить больше памяти для нашего видеочипа, для этого отредактируем в /boot/config.txt

gpu_mem=128

Загрузим нашу новую систему и не забыв инициализировать pacman keyring, установим OMXPlayer:

pacman -Sy omxplayer

Что примечательно, OMXPlayer может работать без иксов, по этому все что нам требуется — это написать unit-файл для него и запустить:

cat > /etc/systemd/system/omxplayer.service <<EOT
[Unit]
Description=OMXPlayer
Wants=network-online.target
After=network-online.target

[Service]
Type=simple
Restart=always
ExecStart=/usr/bin/omxplayer -r --live -b http://your-vm:8080/ --aspect-mode full

[Install]
WantedBy=multi-user.target
EOT

systemctl enable omxplayer
systemctl start omxplayer

В качестве параметра -b http://your-vm:8080/ мы передаем URL с нашего сервера.

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

В качестве бонуса можно установить полученную картинку в качестве скринсейвера на все компьютеры в офисе. Для этого вам понадобятся MPV и XScreenSaver:

mode:  one
selected: 0
programs:              
     "Monitoring Screen"  mpv --really-quiet --no-audio --fs       
      --loop=inf --no-stop-screensaver       
      --wid=$XSCREENSAVER_WINDOW        
      http://your-vm:8080/      n
    maze -root        n
    electricsheep --root 1       n

Теперь ваши коллеги будут очень довольны 🙂

Источник: habr.com