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

Original author: kvaps
  • Translation
  • Tutorial


Возникла у меня необходимость выводить дашборд с мониторингом на несколько экранов в офисе. В распоряжении имеется несколько стареньких 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, добавив только новое разрешение 1920x1080, так как все наши мониторы будут использовать именно его:


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 -r 1 -i :0 -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\

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

  • +11
  • 6.9k
  • 5
Share post
AdBlock has stolen the banner, but banners are not teeth — they will be back

More
Ads

Comments 5

    +1
    Где видео, где картинки работы?
    Я похожую задачу делал тупо написав сервер на VB6. :)
      0
      К сожалению фоткать тут особо нечего, raspberry — она и в африке raspberry.
      A дашборда содержит конфидециальные данные)
      +1
      У нас малинка с qt-ишной реинкорнацией хромиума на eglfs прекрасно гоняет довольно увесистые странички 24/7. Большой телик с ней висит на стене и рисует графики и таблички текущих показателей производства. Хром умирает, если его поверх иксов гонять
        +1
        Использовал uzbl на малинках. Имеет внешнее управление через fifo-файл.
        Раз в месяц мог зависнуть, поэтому в крон по ночам добавил перезапуск браузера.
        Была еще странная идея через малинку вывести определенный софт, запущенный через RDP, но потом необходимость отпала.
          0
          а чем не устроил NDI? и захватывать удобно и клиентов сколько угодно

          Only users with full accounts can post comments. Log in, please.