Streaming live TV with Tvheadend on a Raspberry Pi

Stephen Grier · December 2, 2025

TV gateway devices like HDHomerun and VBox TV Gateway make it possible to take live TV broadcasts from sources such as terrestrial DVB, cable or satellite and stream them across your home network to devices such as smart phones, tablets or computers.

As a fun hack project, it is possible to make your own TV gateway using a Raspberry Pi, a digital TV tuner dongle, and a great piece of open source software called Tvheadend.

For this project I’m going to use:

  • A Raspberry Pi 5 with 4GB of RAM - Tvheadend will run perfectly fine on a RPi4 or even a RPi3, but I had a Raspberry Pi 5 lying around so I used that.

  • An XBox Digital TV tuner, which I picked up second hand on Ebay for ~£7

  • The Tvheadend TV streaming server software

There are other good options for TV tuners, such as the Hauppauge WinTV-dualHD. However, these cost in the region of £70 in the UK. It’s possible to pick up an XBox Digital TV tuner second hand from Ebay for £6-7, so I went with one of these. They work perfectly well with most Linux distros, and they’re so cheap it’s easy to buy two or three of them if needed.

Another option here is the Raspberry Pi TV HAT, which costs around £20 in the UK. With the right case this might make a nice neat setup.

I used Raspberry Pi OS for this project because I already had it installed on the MicroSD card in my Raspberry Pi, but other Linux distros should work just as well.

Getting the XBox Digital TV tuner working

Most linux distros include the necessary driver for the XBox TV tuner. However, it does also need firmware to be uploaded to the device. You’ll need to download the firmware and place it in the /lib/firmware/ directory before plugging the dongle into the Pi’s USB port. You can download the firmware from here.

wget https://github.com/armbian/firmware/raw/refs/heads/master/dvb-demod-mn88472-02.fw
mv dvb-demod-mn88472-02.fw /lib/firmware/

If you plug the XBox TV tuner into one of the Pi’s USB ports you should see something like the following:

[ 9398.811021] usb 1-2: new high-speed USB device number 3 using xhci-hcd
[ 9398.949486] usb 1-2: New USB device found, idVendor=045e, idProduct=02d5, bcdDevice= 1.10
[ 9398.949492] usb 1-2: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[ 9398.949496] usb 1-2: Product: Xbox USB Tuner
[ 9398.949499] usb 1-2: Manufacturer: Microsoft Corp.
[ 9398.949501] usb 1-2: SerialNumber: 008691290814
[ 9398.950579] dvb-usb: found a 'Microsoft Xbox One Digital TV Tuner' in cold state, will try to load a firmware
[ 9398.950628] dvb-usb: downloading firmware from file 'dvb-usb-dib0700-1.20.fw'
[ 9399.022440] dib0700: firmware started successfully.
[ 9399.547287] dvb-usb: found a 'Microsoft Xbox One Digital TV Tuner' in warm state.
[ 9399.547403] dvb-usb: will pass the complete MPEG2 transport stream to the software demuxer.
[ 9399.547634] dvbdev: DVB: registering new adapter (Microsoft Xbox One Digital TV Tuner)
[ 9399.547639] usb 1-2: media controller created
[ 9399.547879] dvbdev: dvb_create_media_entity: media entity 'dvb-demux' registered.
[ 9399.730784] mn88472 15-0018: Panasonic MN88472 successfully identified
[ 9399.733910] tda18250 15-0060: NXP TDA18250BHN/M successfully identified
[ 9399.738094] usb 1-2: DVB: registering adapter 0 frontend 0 (Panasonic MN88472)...
[ 9399.738106] dvbdev: dvb_create_media_entity: media entity 'Panasonic MN88472' registered.
[ 9399.738468] dvb-usb: Microsoft Xbox One Digital TV Tuner successfully initialized and connected.

Connect an aerial cable from your aerial to the aerial port on the XBox TV tuner.

You can test the tuner is working using the w_scan utility:

w_scan -ft -cGB
...
482000: (time: 00:06.323)         signal ok:	QAM_AUTO f = 482000 kHz I999B8C999D999T999G999Y999 (0:0:0)

If you see lines in your output saying signal ok then the tuner is successfully picking up a DVB-T signal. If you don’t then it isn’t, and something is wrong with your setup.

Installing Tvheadend

Create the iptv user on the host

Tvheadend will be running in a docker container, so it’s not essential for the iptv user to exist on the host, but it we will be mapping a volume from the host to the container and so it will be useful to map the UIDs of the files that Tvheadend will create to a user that exists on the host. Create the user like so:

sudo useradd -d /home/iptv -s /usr/sbin/nologin -u 1001 -U iptv
echo "iptv:iptv" | sudo chpasswd

The second command here will change the password for the iptv user to iptv. You may want to set it to something else. I think it may also be fine to lock the password for the user. I haven’t tested that.

Create the directory structure for Tvheadend

I’m going to map two volumes from the host to the Tvheadend container: one for its configuration and data files; and a second for it to store any recorded content. I want these to live on the host in /var/local/iptv/TVHeadend, so create the directory structure like so:

sudo mkdir -p /var/local/iptv/TVHeadend/{data,recordings}
sudo chown -R iptv:iptv /var/local/iptv

Prepare a docker compose config file

As mentioned already, I will be running Tvheadend as a docker container, as this is probably the quickest and easiest way to get Tvheadend running. To do this, create a docker compose config file like so:

cat > docker-compose.yml <<EOF
version: "3.5"
services:
  tvheadend:
    image: linuxserver/tvheadend:arm64v8-latest
    container_name: tvheadend
    environment:
      - PUID=1001
      - PGID=1001
      - TZ=Etc/UTC
      - RUN_OPTS= #optional
    volumes:
      - /var/local/iptv/TVHeadend/data:/config
      - /var/local/iptv/TVHeadend/recordings:/recordings
    ports:
      - 9981:9981
      - 9982:9982
    devices:
      - /dev/dvb:/dev/dvb
    restart: unless-stopped
EOF

This will tell docker compose to create one container using the linuxserver/tvheadend image from dockerhub. I’m using the image tag arm64v8-latest because I’m using a Raspberry Pi 5, but you can change that if you’re using a different platform.

As mentioned already, this will map two volumes into the container from the data and recordings directories we created earlier. These will persist across container restarts so we don’t lose our config when we reboot the host.

The config will also map the /dev/dvb device from the host, which is used to communicate with the XBox TV tuner dongle, into the container so that Tvheadend can use it as its tuner.

Finally, this will also map two ports from the host into the container, one for port 9981, which is the HTTP port that we will use to access Tvheadend’s web configurator; and port 9982, which is Tvheadend’s HTSP port. HTSP is the hypertext streaming protocol that Tvheadend provides for streaming content.

Start Tvheadend container

We should now be able to start Tvheadend by doing:

docker-compose up -d

Configuring Tvheadend

Once the Tvheadend container has started you should now be able to access the configuration interface in your browser at http://[IP address of your rpi:9981/. You will probably want to give your Raspberry Pi a fixed IP address and a DNS name to make it easier when configuring streaming clients, but I won’t be covering that here.

Tvheadend’s configurator is not very user friendly, but once you understand a few basic concepts it’s not too difficult to get working.

Set a default language

Go to Configuration -> General -> Base

Under Web Interface Settings set Default language to your chosen language.

Also under Web Interface Settings set Default view level to Expert as some of the options we need to set are only visible in the expert view.

Then under EPG Settings select English from the Available list, then click the right arrow to add it to the Selected list.

Be sure to click Save before moving onto the next step.

Add a user for streaming

It is possible to allow any client on your network to stream content from Tvheadend without authentication. However, it is recommended to add authentication credentials for each client.

Go to Configuration -> Users -> Access Entries

Click the Add button. Set a username (I’ve used iptv here).

Select the drop-down list next to Change parameters and select the following options: Rights, Channel number range, Channel tags, PVR configurations and Streaming profiles.

Select the checkbox next to Web interface. This will allow the user to access the Tvheadend web interface, which we don’t need, but it also allows it to access the electronic programme guide (EPG), which it will need.

Select the drop-down next to Streaming and select all thee options Basic, Advanced and HTSP.

If you want the user to be able to pause and record content though Tvheadend’s PVR functionality then you will want to select all the options under Video recorder. I don’t have any proper storage attached to my Raspberry Pi at this point so I’m not going to enable these.

In the Streaming profiles drop-down, select all options.

Under DVR configuration profiles select (Default profile).

Click Apply at the bottom. A new row will appear in the access entries list. You can click Cancel to close the new user dialog.

You now need to set a password for the new user. Click on the Passwords tab, and then click the Add button.

The Username must match the username of the user you added above. Set the Password to whatever you want. Then in the Persistent authentication select Enable.

Click Apply, then OK, then Cancel.

Add a network

A network in Tvheadend is really a carrier network - a medium over which a signal is broadcast. For example, it could be a digital terrestrial broadcast (DVB-T or DVB-T2 in the UK or ATSC-T in the US), cable TV (DVB-C) or satellite (DVB-S). I’m using a DVB-T tuner, so I’ll be creating a DVB-T network.

Go to Configuration -> DVB Inputs -> Networks.

Click the Add button and from the drop-down liast select DVB-T Network.

Under Basic Settings select the checkbox next to Enabled. Set a network name; I’ve called mine DVB-T.

Now, from the Pre-defined muxes drop-down list select the profile that most closely matches your country and transmitter. This is the most important bit of the whole configuration to get right so it’s worth understanding what muxes are.

Muxes are channel frequencies transmitted on the carrier network. With digital broadcasts, usually multiple services are multiplexed together on a single frequency, hence the term mux.

It is really important to select the correct transmitter for your location. There are often several transmitters covering each area, but usually one will provide a stronger signal. If you are in the UK like me, the best way to find out which transmitter to use is to use the ukfree.tv website and clicking on some of the transmitters close to your location. This will show the coverage from each transmitter. Pick the one that provides the best coverage for your location. This is not always your nearest transmitter.

In my case I get the best signal from the Crystal Palace transmitter, so I select United Kingdom: uk-CrystalPalace from the pre-defined muxes list.

The ukfree.tv website also provides details on the frequencies broadcast by each transmitter and the services (or channels) multiplexed on each one. For example, the details for the Crystal Palace transmitter can be seen here.

Click Apply, then OK, then Cancel to close the dialog. You can see the pre-defined muxes that have been created on the Muxes tab.

Associate the network with your adaptor

Assuming you’ve passed the device for your TV tuner dongle into the docker container correctly, it should be visible in the TV adapters tab.

You must associate the network you configured above with the adapter. Click on the adapter from the list. Your dongle might provide devices for multiple mediums; mine provides both a DVB-T and a DVB-C device. Click the DVB-T device.

Click the checkbox next to Enabled. Then select the network you created above from the Networks drop-down and click Save. The device should now appear as bold.

If everything is configured correctly, Tvheadend should now start scanning all the muxes for services. If you click the Muxes tab you should see the Scan status change from IDLE to ACTIVE.

It may take a minute or two for Tvheadend to complete the scan, but when complete all muxes should have a Scan result of either OK or FAIL. If you’ve chosen the right transmitter for your area most or all should be OK. If not you may need to try a different transmitter.

Unsticking stuck muxes

Sometimes Tvheadend gets stuck scanning muxes. You can tell if there are stuck muxes from the Networks tab by looking at the Scan queue column of the network. If after several minutes this is anything other than zero you have stuck muxes.

On the Muxes tab, you can identify which muxes are stuck. These will have a scan status of ACTIVE and a scan result of NONE.

To unstick these stuck muxes, click on the stuck mux and click the Edit button. In the Advanced Settings section change Scan status to IDLE and click Apply. Now change Scan status to ACTIVE and click Apply, then Save. The scan result for the mux should now change to either OK or FAILED. Repeat for any other stuck muxes.

Map services

If Tvheadend correctly scanned your muxes it should have found a number of services. A service in Tvheadend is a data stream that is multiplexed on a mux, which could be a TV channel, a radio channel or digital teletext. Before we can watch a TV channel, we first must map our services to channels.

Go to Configuration -> Channel / EPG -> Channels, then select the Map services drop-down and select Map all services.

In the dialog, it’s a good idea to tick the Merge same name option to avoid mapping channels multiple times. Also, tick the Create type-based tags, Create provider name tags and Create network name tags options.

Click Map services. A Service Mapper tab should appear with a progress bar. When the mapping is complete, return to the Channels tab; you should now see all the TV and radio channels you expect.

Configure an EPG grabber

We’re going to need an electronic programme guide (EPG) to give us all the metadata about the programmes being broadcast on all our channels.

Go to Configuration -> Channel / EPG -> EPG Grabber Modules. There are many modules that can grab EPG data from various sources. You can have multiple grabbers enabled if you wish with different priorities. However, I just want the Over-the-air: UK: Freeview grabber because that matches the content my tuner is picking up.

Once you’ve enabled the grabbers you want, click the Save button. Now go to the Electronic Programme Guide tab; you should see a list of programmes and their progress. If you click on one of then you should see metadata about the programme including start and end times and a description.

Test viewing a channel in Tvheadend

You can test viewing a TV channel in the Tvheadend web interface. From the Electronic Programme Guide tab, click the Watch TV button on the right. Select a channel from the Select channel drop-down list. You may also need to select a specific streaming profile for this to work; I had to select webtv-vp8-vorbis-webm as the others wouldn’t work.

All being well you should see live TV!

Test streaming live TV on an android device

There are a number of apps for android devices that can stream from Tvheadend. One is Kodi, which is an excellent open source media player. There is also dream Player for TVheadend.

Here’s what Kodi’s channel list looks like when connected to Tvheadend. The EPG data and channel icons have come from Tvheadend. Pretty isn’t it!

And this is what live TV looks like in Kodi:

Streaming to multiple clients

It is possible to stream different channels from Tvheadend to different clients simultaneously. However, for each tuner it is only possible to stream channels from the same mux, because a tuner can only be tuned to a single frequency. If you want to stream channels from different muxes to multiple clients simultaneously you will need additional tuners. Thankfully, the XBox digital TV tuners I’m using are really cheap to pick up second hand and it’s easy to connect two or three of them to a Raspberry Pi.

References and credits

  1. How to set up Tvheadend with your DVB-T2 receiver
  2. UKFree.tv details about Crystal Palace transmitter
  3. Watch TV ANYWHERE in your house using IPTV via a RASPBERRY PI and TVHEADEND youtube video

Twitter, Facebook