Data Streams

From Modding Fridays
Jump to navigation Jump to search

Prerequisites

Project examples

Installation

A data stream server consists out of the webserver nginx and the nginx-mod-rtmp module. To eventually stream the data to our server, we use a command line utility for audio and video called ffmpeg

nginx

Start with updating and upgrading Alpine Linux

sudo apk update && sudo apk upgrade -U

Followed by installing nginx

sudo apk add nginx

Firewall

PostmarketOS has a very strict firewall as stated in the PostmarketOS General Tips. If we want to eventually make our stream accessible locally, we need to disable the firewall. Run the following command to temporary disable the firewall.

sudo rc-service nftables stop

When we reboot the phone, the firewall will be enabled again. So in order to completely disable the firewall you can run the following command

sudo rc-update del nftables

Setting up a simple webpage

To eventually show our stream, we need to create a simple webpage. You can do this by changing the configuration of nginx. This is done by editing the nginx.conf file on the phone. In this tutorial we will be spending quite some time editing the nginx.conf file.


The following steps are almost an exact copy of the Alpine Linux wiki.


Create a new user and group named 'www' for nginx

sudo adduser -D -g 'www' www

Create a directory for storing our html files

sudo mkdir -p /var/www/html
sudo chown -R www:www /var/lib/nginx
sudo chown -R www:www /var/www

We may want to make backup of the original nginx.conf file before writing our own.

sudo mv /etc/nginx/nginx.conf /etc/nginx/nginx.conf.orig

Lets create a new nginx.conf file and add the following lines to display a simple HTML page which we will create later.

user                            www; # <-- the user we created
worker_processes                auto;

error_log                       /var/log/nginx/error.log warn;
pid                             /var/run/nginx/nginx.pid;

include                         /etc/nginx/modules/*.conf;
include                         /etc/nginx/conf.d/*.conf;

events {
    worker_connections          1024;
}

http {
    include                     /etc/nginx/mime.types;
    default_type                application/octet-stream;
    sendfile                    on;
    access_log                  /var/log/nginx/access.log;
    keepalive_timeout           3000;

    server {
        listen                  80;
        root                    /var/www/html; # <-- the location of our HTML files
        index                   index.html index.htm; # <-- the name of the HTML file that the browser will load
        server_name             localhost;
        client_max_body_size    32m;
        error_page              500 502 503 504  /50x.html;
        location = /50x.html {
              root              /var/lib/nginx/html;
        }
    }
}

Now we can finally create our HTML page! We will be saving this page in the /var/www/html/ directory, because we specified that as our root directory in the nginx.conf file.

Open a new file...

sudo nano /var/www/html/index.html

...and paste the following content:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <title>Data Streams</title>
</head>
<body>
    Woop!!
</body>
</html>

Now, after restarting nginx, your webpage should be visible by typing the phone's IP address in your browser! To restart nginx:

sudo rc-service nginx restart

NOTE: If you want to know more about creating webpages, there are some great quick start guides on HTML and CSS

nginx-mod-rtmp

sudo apk add nginx-mod-rtmp

After installing the nginx-mod-rtmp we need to add a configuration block to the nginx configuration file that tells nginx where the stream will be available. Open the configuration file found at /etc/nginx/nginx.conf and add the following contents to the end of the file.

rtmp {
        server {
                listen 1935;
                chunk_size 4096;
                allow publish 127.0.0.1;
                deny publish all;

                application live {
                        live on;
                        record off;
                        dash on;
                        dash_path /var/www/html/stream/dash;
                }
        }
}

We also need to add the following at the end of the http block in the nginx.conf file. This will allow us to stream in the MPEG-DASHformat, which we can show on webpages.

server {
    listen 8088;

    location /dash {
        types {
            application/dash+xml mpd;
            video/mp4 mp4;
            audio/mp4 m4a;
            video/mp4 m4v;
        }
        root /var/www/html/stream;
        add_header Access-Control-Allow-Origin *;
        add_header Cache-Control no-cache;
    }
}

Make sure to create the root folder which we will use for streaming

sudo mkdir /var/www/html/stream

And restart nginx to make sure everything is working

sudo rc-service nginx restart

ffmpeg

To stream an audio or video file to our rtmp server, we need to install ffmpeg.

sudo apk add ffmpeg

After installing we are almost ready to start streaming

Usage

Uploading files

If you've followed along with installing PostmarketOS, you've enabled the SSH daemon. This also allows us to upload files to your phone over SFTP. Open your favorite (S)FTP client (ex.: filezilla or cyberduck) and enter the ip address and username of your PostmarketOS installation. An example:

server: 192.168.2.130
port: 22
username: user
password: 147147

After connecting to your phone, you should be able to upload files. As an example, we're uploading a file named video.mp4 to the home folder of the user named user.

Streaming video files

Running the following ffmpeg command will stream video.mp4 to our rtmp server.

ffmpeg -stream_loop -1 -re -i video.mp4 -c:v copy -f flv rtmp://localhost/live/stream

However, we can not actually see the video we are streaming. For that we need to edit our webpage

Video stream webpage

The following code snippet is a simple webpage for showing a video stream. It uses the JavaScript library dashjs to display the stream. You can replace the code in /var/www/html/index.html with the code below to see your video when your run the ffmpeg command.

Open /var/www/html/index.html...

sudo nano /var/www/html/index.html

...and replace with the following

(make sure that you replace the const url ip with your own!)
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Data Streams</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/dashjs/4.7.1/dash.all.min.js"></script>
    <style>
        .video-container {
            max-width: 800px;
            margin: 20px auto;
        }
        video {
            width: 100%;
        }
    </style>
</head>
<body>
    <div class="video-container">
        <video id="videoPlayer" controls></video>
    </div>

    <script>
        (() => {
            const url = "http://10.13.37.160:8088/dash/stream.mpd";
            const player = dashjs.MediaPlayer().create();
            player.initialize(document.querySelector("#videoPlayer"), url, true);

            player.on("error", (e) => {
                console.error("Error playing stream:", e);
            });
        })();
    </script>
</body>
</html>

And restart nginx

sudo rc-service nginx restart

Run the ffmpeg command and visit your webpage by entering your phone's IP address in the browser bar. You should see your video playing!

References

Useful Links

FFmpeg guide

FFmpeg effects|filters|aesthetics|

Fun Stuff to experiment with

  • Maptastic: Javascript/CSS projection mapping utility. Put your internets on things!


Inspirational?

(Did not work with Oneplus 6 due X11/Wayland bugs)