Monitor viewer-numbers for your HLS stream

1 April 2023

Monitor viewer-numbers for your HLS stream

I was looking for a way to show the amount of viewers from a HLS stream. Been searching, high, been searching low. Eventually I found an excellent solution. It's super simple, it's free, and it simply just works! This setup works great with Nginx 1.23 running on Ubuntu 22.04. Please keep in mind that the instructions on this page are tried here on Ubuntu. I haven't tried Apache yet. What we're going to do here is download a script from GitHub. Create a system service that calls the script in the background. The script monitors a Nginx log in real time, that we will need to specify. This all results in a simple counter file that will contain the number of viewers. Depending on the viewers joining or leaving the stream, the number in the counter file will constantly be updated. Each different IP address will be considered as one viewer. We can use the content of that file by including its content in a web page. Before I forget to mention it, these instructions are valid for this repository: https://github.com/ben-pearce/nginx-hls-viewers

Add extra logging line to Nginx config

All the folder and file locations can be whatever you want. I'm just showing an example of how I did it. So let's get started by editing the configuration file for the website that is serving the HLS files. This can be found in /etc/nginx/nginx.conf, or, more likely, a vhost config file located in /etc/nginx/sites-available/

sudo nano /etc/nginx/sites-available/yourwebsite

Don't remove anything from your current file. The content that's in it is there for a reason. The example below is not anything that you can just copy/paste, so you'll have to use your brain to figure out what to do exactly. I know it can be hard sometimes to use your brain. It can be done, however! I'm assuming your some parts of the config below will look similar to what you already see in your vhost config for the web that hosts the HLS files. The thing that is important here is that we're going to ask nginx to log all requests for everything in the /hls location into a new log file. The lines about the location for /hls/count that you find below, is not actually required, but I found it may come in handy.

erver {
    listen 80;
    server_name example.com;

    access_log  /var/log/nginx/access.log;
    error_log   /var/log/nginx/error.log;

    location / {
        index index.html;
        root /var/www;
    }

    # Make count file available via HTTP ex. http://example.com/hls/count/
    location /hls/count {
        add_header 'Content-Type' 'text/plain charset=UTF-8';
        alias /var/www/html/count.hls;
    }

    location /hls {
        # Set HLS traffic to go to its own log file
        access_log  /var/log/nginx/hls_access.log;             # <<--- ADD THIS LINE UNDER /HLS

        alias /your/location/for/hls;
        add_header 'Cache-Control' 'no-cache';
        add_header 'Access-Control-Allow-Origin' '*' always;
        add_header 'Access-Control-Expose-Headers' 'Content-Length';
        types {
            application/dash+xml mpd;
            application/vnd.apple.mpegurl m3u8;
            video/mp2t ts;
            text/html html;
        }
        if ($request_method = 'OPTIONS') {
            add_header 'Access-Control-Allow-Origin' '*';
            add_header 'Access-Control-Max-Age' 1728000;
            add_header 'Content-Type' 'text/plain charset=UTF-8';
            add_header 'Content-Length' 0;
            return 204;
        }
    }
}

After saving the file, make sure you use the command nginx -t to see if the configuration will be accepted by nginx. If all is good, restart nginx: systemctl restart nginx.

In case you don't already have it installed, go ahead and install Python3 and Curl.

Install requirements for running the script

sudo apt install python3-dev curl

Now we're going to use curl to download the script from GitHub. Store it anywhere you like. In this example, I've chosen to place it in a folder /livestream.

sudo mkdir /livestream
cd /livestream
curl https://raw.githubusercontent.com/ben-pearce/nginx-hls-viewers/main/main.py > counter.py

Running the script manually

Now you can run the script to see if it works. But before you do, you may want to make sure your live-stream is running, and that the HLS files are available for watching the stream. You will need to set some variables in the next line, so pay attention here. -I points to the location of the log file. -O points to where the viewer numbers should be written to.

python3 counter.py -I /var/log/nginx/hls_access.log -O /livestream/views.hls

Now check if the number in the file /livestream/views.hls changes when viewers start watching the stream. Be your own viewer, go ahead and open it in your browser, and go ahead and open it on your mobile as well. But first disconnect your mobile from your WiFi network, since you'll need a new, different IP address, so the script will see you as a new viewer. Now enter the following command to monitor the count.hls file.

tail -f views.hls

Install the script as a daemon service

You now have access to the real-time, reasonably accurate viewer numbers of your stream. When a peer is idle for 10 minutes or more, the peer will be removed as a viewer. An optional next step is to have the script run in the background, continuously as a systemd service. Use the example below to create such a daemon service.

sudo nano /etc/systemd/system/counter-hls.service
[Unit]
Description=HLS live view count service
After=network.target

[Service]
ExecStart=/usr/bin/python3 /livestream/counter.py -I /var/log/nginx/hls_access.log -O /livestream/views.hls
Restart=always

[Install]
WantedBy=multi-user.target

Save the file and now enable and start the service by entering these commands:

sudo systemctl daemon-reload
sudo systemctl enable counter-hls.service
sudo systemctl start counter-hls.service

Create a page to show the viewer numbers

The script now runs in the background, and the views.hls file should be updated in real-time now when new viewers join the stream. Now you can be as creative as you want when you will decide how you want to use the data in the counter file. I decided to make a simple web page that automatically refreshes every five seconds, and show the number of viewers on it. Due to safety reasons, the system user that my website runs on, only has access to the web folder root, and subfolders. But the views.hls file is stored in a location the web user has no access to. I don't want to mess with user rights and such, so I simply make a symlink from the web root folder to the views.hls file. In my case, I used this command:

ln -s /livestream/views.hls  /var/www/html/views.hls

Here is the content of the webpage I use. It is really basic, and feel free to do with it whatever you want. The only thing that is important here is the including of the views.hls file.

nano /var/www/html/views.html
<!DOCTYPE html>
<html>
  <head>
    <title>HLS Viewer Count</title>
    <style>
      body {
        font-family: Arial, sans-serif;
        font-size: 24px;
        text-align: center;
      }
      h1 {
        font-size: 36px;
        margin-bottom: 20px;
      }
    </style>
  </head>
  <body>
    <h1>HLS Viewer Count</h1>
    <p>Current viewers: <span id="viewer-count"></span></p>
    <script>
      function loadViewerCount() {
        var xhr = new XMLHttpRequest();
        xhr.onreadystatechange = function() {
          if (xhr.readyState === XMLHttpRequest.DONE) {
            if (xhr.status === 200) {
              document.getElementById("viewer-count").innerHTML = xhr.responseText;
            } else {
              console.log("Error: " + xhr.status);
            }
          }
        };
        xhr.open("GET", "/views.hls", true);
        xhr.send();
      }
      loadViewerCount();
      setInterval(loadViewerCount, 5000); // Refresh viewer count every 5 seconds
    </script>
  </body>
</html>

Now open the web page in your browser and you're done! Congratulations!

In the Netherlands we have a saying that would be fitting here, and translated to English it says: A child can do the laundry. I realize how silly that sounds in English, but that makes it funny. It means something like: it was easy enough.

Pick a star to rate this
Table of Contents

Leave a Reply

Your email address will not be published. Required fields are marked *

Unrelated Content

26 June 2025
Why Self-Hosting Your Livestream Is Safer, Cheaper, and More Flexible Than Commercial Platforms

With livestreaming more popular than ever, platforms like YouTube Live, Twitch, Vimeo, and Facebook Live have become household names. But are they really the best option for everyone? If you're a tech-savvy creator, a privacy-conscious broadcaster, or someone who just wants full control, self-hosting your own livestream server might be a better choice. In this […]

READ MORE
27 November 2020
Motivation behind this website

For every service that is offered for a lot of money on the internet, there's always a free or much cheaper alternative, especially if you embrace open-source software. For live-streaming this is also very much the case. We love that,

READ MORE
23 January 2021
Introduction to the new how-to article in the Knowledge Base.

I wrote a new guide on setting up your own live-stream server. Mostly due to your requests. I took the opportunity to simplify and shorten the guide a bit. If you follow this guide step by step, and use your brain a tiny bit, you'll be fine. This guide has so far been tested on […]

READ MORE
25 January 2021
Optimizing First-Frame Bitrate for HLS

When responding to an HLS request, the streaming server determines which video quality (i.e., ts file) the client will attempt to play before switching to a lower or higher quality video. This switch depends on available bandwidth and device type. Switching to the wrong quality first degrades the user experience considerably. For instance, sending a […]

READ MORE
25 January 2021
Adaptive Bit-rate Streaming

“What is adaptive streaming?” This question often leads to answers filled with technical terms like “HLS”, “MPEG-DASH”, “segments” and “codec“. This article is written for people who need to understand the principles, but don’t need to actually implement the technology. If you are looking for specific technical information on adaptive streaming then I recommend you read up on it on this website and elsewhere.

READ MORE
2 February 2021
About Bradmax Video Player WordPress plugin

Let's talk about our favorite video player plugin for WordPress. Here are some reasons why Bradmax Player is our favorite. And below that are detailed instructions on how to set it up. Setting it up may at first seem a bit awkward, but it really isn't. First you must obviously install the Bradmax Player plugin […]

READ MORE
Copyright © 2025. 
All rights reserved.
linkedin facebook pinterest youtube rss twitter instagram facebook-blank rss-blank linkedin-blank pinterest youtube twitter instagram