Streamlining Home Entertainment: How to Use a Linux Machine for Streaming Content to Smart TVs and More
Tags: streaming, docker, nginx, obs
Published: 2024-01-06 16:09:10

## Introduction

Hey there! Ever thought about turning your old laptop or a Raspberry Pi into a personal streaming powerhouse? You're not alone. Many of us find the idea of ditching the limitations of traditional smart TV platforms (think annoying ads, blocked content, and less-than-stellar USB playback) pretty appealing.

In this guide, I'll walk you through a slightly intricate but rewarding journey to set up your own streaming service. This might be a bit of a lengthy read, but stick with me. By the end, you’ll be able to stream content directly from your laptop to your TV, bypassing those smart TV nuances and enjoying your media just the way you like it.

Let’s dive in and transform the way you experience home entertainment!

## Overview of the Setup

We start by adding a new sound interface. This solution eliminates the distraction of audio playing in the speakers of the laptop, channeling all sound directly to OBS for a seamless streaming experience. Then, we install Docker, establishing isolated environments for some of the services of our system. This isolation ensures operational efficiency and prevents interference with other processes on the machine. Next, OBS takes the center stage, adeptly capturing and transmitting both audio and video. It's the key player that brings your content to life, offering user-friendly customization for an optimized streaming setup. Finally, Nginx acts as a versatile powerhouse, adeptly juggling two critical roles. It not only serves as a reverse proxy for OBS, managing the live video streams, but also doubles as a web server. This dual functionality enables Nginx to host the webpage through which your content is accessed, completing the circle of our streaming service. Together, these components interlink and work in harmony, creating a robust and versatile home streaming solution.

In the following sections, we’ll delve deeper into each component, explaining the setup process. Get ready to transform your old laptop or Raspberry Pi into a streaming powerhouse!

## Requirements and Preparations

Fine-tuning our setup to match the specific environment of an old laptop, we're demonstrating that high-end hardware isn't a necessity for a functional home streaming service. The chosen machine is a modest Intel i3 with 4GB of RAM, illustrating that even older computers can effectively handle streaming tasks. This setup runs on Ubuntu, a user-friendly operating system that's ideal for such projects. While this guide primarily focuses on Ubuntu, users with different Linux distributions can still follow along, though they might encounter slight variations in the setup process.

Before diving into the streaming setup, updating your Ubuntu system is crucial. Start by opening a terminal; you can usually do this by searching for 'Terminal' in your system's applications menu or by using the shortcut `Ctrl + Alt + T`. In the terminal, run the following commands to update your system:

```bash
sudo apt update
sudo apt upgrade
```

This process ensures your system is secure and functions smoothly, paving the way for a successful setup. As we proceed, basic command line familiarity will be beneficial, but don't worry—I'll provide all the necessary commands, making it easy to follow along. We'll be configuring an external sound interface to optimize audio output for OBS and installing Docker to run Nginx in a container. This approach keeps our setup clean and modular. Embrace this project with patience and a willingness to learn; it's an exciting journey into the realm of home streaming. With these preparations, we're ready to start building our streaming system, beginning with the new sound interface installation. Let's get started!

## Adding a New Sound Interface

Enhancing your streaming setup begins with the addition of a virtual sound interface, a key move for a clean audio experience. This step-by-step guide will help you create a virtual audio streamer on your Linux system, perfect for directing audio to OBS and keeping your laptop's speakers silent.

First, we need to check if PulseAudio, a powerful sound server, is already installed on your machine. Open your terminal and enter:

```bash
sudo apt update
sudo apt install pulseaudio
```

After confirming PulseAudio's installation, the next move is to modify its configuration to add a new virtual sound interface. Using a text editor like Nano, open the PulseAudio configuration file:

```bash
sudo nano /etc/pulse/default.pa
```

Scroll to the end of the file and add the following line:

```
load-module module-null-sink sink_name=VirtualSink sink_properties=device.description=Virtual_Audio_Streamer
```

This command instructs PulseAudio to create a new virtual audio output named 'VirtualSink' with the description 'Virtual_Audio_Streamer'. Save the changes and exit the editor. For these changes to take effect, a system restart is necessary.

Once your system is back up, navigate to your sound settings, accessible through the system settings or control panel. In the output section, you will now find 'Virtual_Audio_Streamer' alongside other audio interfaces. Set it as the default output device.

By setting 'Virtual_Audio_Streamer' as the default, the system audio is routed to this virtual sink, meaning you won't hear any sound from your laptop's speakers. Instead, all audio is directed to this virtual interface, ready for OBS to capture.

## Installing Docker

Setting up docker on Linux is a straighforward process if you follow the official documentation. If your linux distro is ubuntu you can use the next link [Docker's official installation guide ubuntu](https://docs.docker.com/engine/install/ubuntu/) and if it is debian or raspberry pi 64 bit, you can use the next link [Docker's official installation guide ubuntu](https://docs.docker.com/engine/install/debian/).

I install following the instructions in **Install using the apt repository** section. I never had any issues with this method and its quite simple.

I find important to follow **post-installation steps** just after finishing instalation. This includes adding your user to the Docker group to avoid needing to use `sudo` for every Docker command. Execute the following commands in your terminal:

```bash
sudo groupadd docker
sudo usermod -aG docker $USER
```

These commands create a new group named 'docker' and add your user to this group. To apply these changes, restart your system. This ensures that your user permissions are updated correctly.

After restarting, you should verify the installation, check if Docker and Docker Compose are correctly installed by running:


```bash
docker version
docker compose version
```
These commands will display the version of Docker and Docker compose installed on your system, confirming that the installation was successful.

By following these steps, you'll have Docker up and running on your system. Docker is an extremely powerful tool for containerization, allowing you to run applications in isolated environments. This will be especially useful for our streaming service setup, where Docker will manage the Nginx server in a container.

## Installing OBS Studio on Ubuntu

Installing OBS Studio on your Ubuntu/Debian system is a straightforward process, perfect for beginners, and involves using Ubuntu's or Debian's PPA to ensure easy installation and updates. Type the following command in the terminal to add the OBS Studio PPA:

```
sudo add-apt-repository ppa:obsproject/obs-studio
```

This step connects your system to the OBS Studio repository. After adding the PPA, update your system's package list and install **OBS studio**:

```
sudo apt update
sudo apt install obs-studio
```

After installing OBS Studio, hold off on launching it right away. We need to set up Nginx first, as it's a crucial part of our streaming setup. Once Nginx is up and running, we'll circle back to OBS Studio to configure it for streaming. This ensures a smooth integration between your streaming software and the server.

## Creating a Web Interface for Streaming

In this part of our setup, we'll create a web interface for the streaming service using Docker and Nginx. This will involve setting up a directory structure and configuring files.

I will not explain how every item works. Docker compose file is quite simple and straightforward, but nginx configuration file was quite tricky as I did not have any previous experience with rtmp and I had to make many different tries till I got a working solution. Web page is also very simple, I did not dedicate much time to this one, I just add a html page with a video player. I did play with other two or three different video players and this one from [https://github.com/videojs/video.js](https://github.com/videojs/video.js), is the one that I liked most and just works fine.

First we need to create a directory for the project. I will use ~/stream-service in my setup:

```bash
mkdir ~/stream-service
```

We will create three directories: ./conf for nginx configuration file, ./hls for the streaming content that will be generated by obs and ./web for hosting index.html file.

```bash
cd ~/stream-service
mkdir conf hls web
```

We will also add in project root folder a docker compose file. This will launch nginx service and redirect container ports to host ports. We will also add a **restart: always** line so that the service is started automatically when we switch on the laptop. So, create a file called ~/stream-service/docker-compose.yml with the next content:

```yml
services:
  nginx:
    image: tiangolo/nginx-rtmp:latest-2023-10-16
    container_name: obs-nginx
    restart: always
    ports:
      - "1935:1935"
      - "80:80"
    volumes:
      - ./conf/obs.conf:/etc/nginx/nginx.conf
      - ./hls:/mnt/hls
      - ./web:/web
```

Create also the file ~/stream-service/conf/obs.conf file with the next content:

```nginx
worker_processes auto;
rtmp_auto_push on;
events {}

rtmp {
    server {
        listen 1935;

        application live {
            live on;
            record off;
            hls on;
            hls_path /mnt/hls;
            hls_fragment 3;
            hls_playlist_length 60;
        }
    }
}

http {
    sendfile off;
    tcp_nopush on;
    # aio on;
    directio 512;
    default_type application/octet-stream;

    server {
        listen 80;

        location / {
            # Disable cache
            add_header 'Cache-Control' 'no-cache';

            # CORS setup
            add_header 'Access-Control-Allow-Origin' '*' always;
            add_header 'Access-Control-Expose-Headers' 'Content-Length';

            # allow CORS preflight requests
            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;
            }

            types {
                text/html html htm;
                application/dash+xml mpd;
                application/vnd.apple.mpegurl m3u8;
                video/mp2t ts;
            }

            index index.html;
            root /mnt/hls;
        }

        location /index.html {
            alias /web/index.html;
        }

    }
}
```

Lastly create the ~/stream-service/web/index.html file with the next content:

```html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>Live Stream</title>
    <link href="https://vjs.zencdn.net/7.8.4/video-js.css" rel="stylesheet" />
  </head>
  <body>
    <video id="my-video" class="video-js" controls preload="auto" width="640" height="360" data-setup="{}">
      <source src="/stream.m3u8" type="application/x-mpegURL" />
      <p class="vjs-no-js">
        To view this video please enable JavaScript, and consider upgrading to a web browser that
        <a href="https://videojs.com/html5-video-support/" target="_blank">supports HTML5 video</a>
      </p>
    </video>

    <script src="https://vjs.zencdn.net/7.8.4/video.js"></script>
  </body>
</html>
```

Finally, change the web pages file permission. Otherwise nginx will not be able to serve it:

```
chmod 777 ~/stream-server/web/index.html
```

## Launching the services

With configuration files ready, in a terminal execute next instructions:

```
cd ~/stream-service
docker compose up
```

The second command will take some time. It needs to download nginx image and start the service. Once ready you should see a text similar to **Attaching to obs-nginx** in the terminal.

Once everything is up and running, your streaming service will be accessible via the web interface (`index.html`). As users visit your webpage, they can view the content streamed through OBS and processed by your Nginx server.

Before being able to access the web page, you will need to know the ip address of your laptop. This can be obtained with the next instruction in the terminal:

```
ip address
```

As we have docker installed you will see many networks. The network we are seeking it's typically named something like `eth0` (for wired connections) or `wlp2s0` or `wlan0` (for wireless connections int laptop or raspberry pi). In my case it's `wlp2s0` with the IP address `192.168.1.104`. Now I can access to `http://192.168.1.104/index.html`, but the browser will just tell me that **The media could not be found...**.

## Configuring OBS for Streaming

Finally we need to configure OBS studio. Once we have the rest setup it is quite easy. We start by launching OBS stduio. If it's the first time you're opening OBS, you might see the Auto-Configuration Wizard. You can use this to set up your stream, or you can configure it manually in the settings. I will explain the second method.

In the OBS main window, find the 'Settings' button, usually located in the lower right corner. Click on it to open the settings window. Once the popup window opens, we select the stream tab (second in the left part of the window). And set the next settings:

```
Service: Custom
Server: rtmp://localhost/live
Stream Key: stream
```

After entering these details, click 'Apply' and then 'OK' to save your streaming settings.

Now, you need to set up your video and audio sources in OBS. Before doing it you can open a media and start playing it. Afterwards,  click the '+' button under the 'Sources' window and select the media you are playing. OBS automatically captures your primary desktop audio and microphone. You can adjust these and add additional audio sources in the 'Audio Mixer' section. Once your sources are set up, you're ready to go live. Just click the 'Start Streaming' button in OBS. Your content should now be streaming to your Nginx server and accessible through your configured web interface.

Now you can open in a devices browser the web address configured in the previous section and you should be able to play the media in your other device.

## Final Notes

If you encounter issues or the stream isn't accessible on your smart TV, make sure your TV is connected to the same network as your streaming server. Also, check if any firewall or network settings are blocking access to the server. And still, if you're having difficulties or if there's something in this guide that isn't clear, please feel free to post your questions or concerns below. Your feedback is valuable and can help improve this guide. I'll try to provide advice or update the article to address common issues.

By following this guide, you've taken a big step in enhancing your home entertainment system. This DIY approach not only offers a customized viewing experience but also expands your technical skills. Enjoy your new streaming capability, and happy streaming!