Stream screen to multiple devices over the network

Stream screen to multiple devices over the network

I had a need to display a dashboard with monitoring on several screens in the office. There are several old Raspberry Pi Model B + and a hypervisor with an almost unlimited amount of resources.

Apparently the Raspberry Pi Model B+ does not have enough randomness to keep the browser constantly running and rendering a lot of graphics in it, because of which it happens that the page is partially buggy and often crashes.

There was a fairly simple and elegant solution, which I want to share with you.

As you know, all Raspberries have a fairly powerful video processor, which is great for hardware video decoding. So the idea came up to launch a browser with a dashboard somewhere else, and transfer a ready-made stream with a rendered picture to the raspberry.

Plus, this should have simplified management, since in this case all configuration will be performed on one virtual machine, which is easier to update and backup.

No sooner said than done.

Server part

We use ready Cloud Image for Ubuntu. Requiring no installation, it contains everything you need to quickly deploy a virtual machine, and CloudInit support helps to instantly set up a network, add ssh keys and quickly put it into operation.

We deploy a new virtual machine and first of all install it on it 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

We will also use the config for Xorg, kindly granted us Diego Ongaro, adding only a new resolution 1920 Γ— 1080, since all our monitors will use it:

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

Now we will install Firefox, we will run it as a system service, so for one thing we will write a unit file for it:

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

We need Xdotool in order to run firefox immediately in full screen mode.
Using the parameter -url you can specify any page so that it opens automatically when the browser starts.

At this stage, our kiosk is ready, but now we need to export the image over the network to other monitors and devices. To do this, we will use the possibilities Motion JPEG, a format more commonly used for streaming video from most webcams.

For this we need two things: ffmpeg with module x11grab, for capturing pictures from X's and streamEye, which will distribute it to our clients:

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

Since our picture does not require a fast update, I specified the refresh rate: 1 frame per second (parameter -r 1) and compression quality: 5 (parameter -q:v 5)

Now let's try to go to http://your-vm:8080/, in response you will see a constantly updated screenshot of the desktop. Great! β€” what was needed.

Client part

It's still easier here, as I said, we will use the Raspberry Pi Model B +.

First of all, let's install it ArchLinux ARM, for this we follow instructions on the official site.

We will also need to allocate more memory for our video chip, for this we will edit in /boot/config.txt

gpu_mem=128

Let's boot our new system and don't forget to initialize the pacman keyring, install OMXPlayer:

pacman -Sy omxplayer

Remarkably, OMXPlayer can work without x, so all we need is to write a unit file for it and run:

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

As a parameter -b http://your-vm:8080/ we are passing the url from our server.

That's all, a picture from our server should immediately appear on the connected screen. In case of any problems, the stream will be automatically restarted and clients will reconnect to it.

As a bonus, you can install the resulting picture as a screensaver on all computers in the office. For this you will need 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

Now your colleagues will be very happy πŸ™‚

Source: habr.com

Add a comment