Introduction

locast2tuner provides an interface between locast.org and Plex Media Server (PMS) or Emby by acting like an HDHomerun or an m3u tuner and an XMLTV provider.

locast2tuner can emulate one or more digital tuners and provides geo cloaking across regions.

❗ Since locast.org uses Amazon CloudFront to stream, region restrictions imposed by CloudFront can not be circumvented. This means that locast2tuner might not work outside of the United States.

Features

  • Override your location using ZIP code or GPS coordinates
  • Multiple digital tuners in a single server, either as separate servers or as one (multiplexing)
  • Emulates either an HDHomerun or an m3u tuner
  • Provides locast EPG information as an XMLTV guide

Background

locast2tuner is a rewrite in Rust of locast2dvr, which in turn is a rewrite of locast2plex. Thanks to the locast2plex developers for writing it and figuring out how to stitch things together!

I rewrote locast2plex to be able to more easily add functionality, use libraries wherever possible (like HTTP, m3u, starting multiple devices, etc), heavily document, generally write clean code, and provide a better user experience (command line argument parsing, automatic download of FCC facilities, etc). And since python's GIL gave me a headache, I rewrote the whole thing in Rust.

Apart from the fact that everything is Rust now, the big difference between locast2tuner and locast2dvr is that locast2tuner does not require ffmpeg anymore. Actually, I completely dropped support for it and only implemented the direct mode that locast2dvr supports. Next to that, I removed a few debugging features (like --multiplex-debug), that don't seem to be used.

Even though this project started as a Locast to PMS interface, it's more focused on integrating locast with Emby, since Emby provides a bit more functionality when it comes to Live TV and Tuner (like m3u tuners, XMLTV, etc).

Getting Started

✋ Before you get started with installing and running locast2tuner, make sure you have an active locast.org account with an active donation.

Ubuntu/Debian

✋ Before you get started with installing and running locast2tuner, make sure you have an active locast.org account with an active donation.

Ubuntu/Debian packages are available for both amd64 and arm7 (Raspbian):

# Add the PPA key
curl -s "https://wouterdebie.github.io/ppa/KEY.gpg" | sudo apt-key add -

# Add the locast2tuner repository
sudo curl -o /etc/apt/sources.list.d/locast2tuner.list \
   "https://wouterdebie.github.io/ppa/sources.list"
sudo apt update

# Install locast2tuner
sudo apt install locast2tuner

Create a config file using the example. Don't forget to edit the config file!

sudo cp /etc/locast2tuner/config.example /etc/locast2tuner/config
# .. edit the config /etc/locast2tuner/config (e.g nano /etc/locast2tuner/config) ..

Finally, enable and start the service:

sudo systemctl enable locast2tuner
sudo systemctl start locast2tuner

MacOS

✋ Before you get started with installing and running locast2tuner, make sure you have an active locast.org account with an active donation.

A MacOS package is available though Homebrew:

# Add the homebrew tap
brew tap wouterdebie/repo

# Install locast2tuner
brew install locast2tuner

# Get the sample config
curl -o locast2tuner.config \
  https://raw.githubusercontent.com/wouterdebie/locast2tuner/main/assets/config.example

# .. edit locast2tuner.config ..

# Run locast2tuner
locast2tuner --config locast2tuner.config

Docker

✋ Before you get started with installing and running locast2tuner, make sure you have an active locast.org account with an active donation.

A Docker image is available from ghcr.io/wouterdebie/locast2tuner:latest and is built from this Dockerfile.

The container image is configured so that all configuration parameters can be set as environment variables set at runtime.

l2t_username and l2t_password are required parameters. The rest are optional.

If you'd like to use Docker Compose you can use the sample docker-compose.yml and edit it to match your settings:

version: "3"
services:
  locast2tuner:
    image: ghcr.io/wouterdebie/locast2tuner:latest
    container_name: locast2tuner
    environment:
      - l2t_username=username
      - l2t_password=password
#      - l2t_override_zipcodes=#####,##### (optional)
#      - l2t_multiplex=true (optional)
#      - l2t_remap=true (optional)
    ports:
      - 6077:6077
    restart: unless-stopped

To configure and run using docker-compose:

# Get the sample docker-compose.yml
curl -o docker-compose.yml \
  https://raw.githubusercontent.com/wouterdebie/locast2tuner/main/assets/docker/docker-compose.yml

# .. edit docker-compose.yml to match your settings ..

# Start the Docker container
docker-compose up -d

The path /app/config is available in the container and can be mounted from the host in order to use settings like l2t_remap_file or even l2t_config.

Upgrading

# Pull any new versions of images referenced in docker-compose.yml
docker-compose pull

# Restart any containers in `docker-compose.yml` with newly pulled images
docker-compose up -d

Run using Docker

# Pull latest locast2tuner image
docker pull ghcr.io/wouterdebie/locast2tuner:latest

docker create \
  --name=locast2tuner \
  -p 6077 \
  -e l2t_username=username \
  -e l2t_password=password \
  -e l2t_override_zipcodes=#####,##### \
  -e l2t_multiplex=true \
  -e l2t_remap=true \
  ghcr.io/wouterdebie/locast2tuner:latest

Upgrading

To upgrade the image:

# Pull the latest version of the locast2tuner container image
docker pull ghcr.io/wouterdebie/locast2tuner:latest

# Stop the existing container
docker stop locast2tuner

# Remove the existing container
docker rm locast2tuner

Unraid notes

The unraid image used to be managed by someone else, but has been consolidated in the regular locast2tuner distribution. Since images have moved, make sure you use the latest Unraid templates from https://github.com/RandomNinjaAtk/unraid-templates and that your docker-compose.yml has the image set to ghcr.io/wouterdebie/locast2tuner:latest.

Windows

Currently a Microsoft Windows x64 binaries are available in Github releases. Note that those binaries are just executables without any form of configuration. Work is ongoing to provide a proper installation package (MSI) that allows installing locast2tuner as a service.

From source

✋ Before you get started with installing and running locast2tuner, make sure you have an active locast.org account with an active donation.

The only build requirement locast2tuner has is Rust 1.50.0+.

Installing dependencies

  • MacOS: brew install rust
  • Linux: curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

Building

git clone https://github.com/wouterdebie/locast2tuner
cd locast2tuner
cargo build --release

Installing

You'll end up with a binary in ./target/release/locast2tuner. You can copy this to the directory of your choosing (/usr/local/bin is a good place to start).

Configuration

locast2tuner parameters can be specified as either command line arguments, as environment variables, or in a TOML configuration file that can be specified using the --config argument.

The precedence of parameters is command line arguments > environment variables > config file

Command line arguments

In order to specify command line arguments, use --argument value (e.g. --override_zipcodes 90210,30301). Note that underscores are retained.

Environment variables

Parameters can also be specified using environment variables. Environment variables are prefixed with l2t_ and should be exported in the format l2t_argument="value" (e.g. export l2t_override_zipcodes="90210,30301"). Note that underscores and lowercase are retained.

For boolean flags (like l2t_multiplex), use true or false as values.

Configuration file

The configuration file format is:

string_option = "<value1>"
flag = <true/false>
numerical_option = <number>
list_option = ["<value1>", "<value2>"]

Example:

username = "<Locast username>"
password = "<Locast password>"
verbose = 2
multiplex = true
override_zipcodes = ["85355", "90210"]

Configuration options

Please have a look at the example config file

OptionDescriptionDefault
username (required)Locast.org username
password (required)Locast.org password
bind_addressAddress of the interface to bind to. To bind to all interfaces, use 0.0.0.0127.0.0.1
cache_dirCache data location$HOME/.locast2tuner
cache_timeoutHow often (in seconds) the station cache is refreshed3600
daysDays of EPG data to fetch8, which is the maximum of data locast.org provides
device_firmwareDevice firmware that is reported to Plex or Embyhomerun3_atsc
device_modelDevice model that is reported to Plex or EmbyHDHR3-US
device_versionDevice version that is reported to Plex or Emby20170612
disable_station_cacheDisable caching of station information. By default locast2tuner caches station information for an hour (see cache_timeout). By disabling the cache, every request for station information will lead to a call to locast.org. Normally you shouldn't have to disable the cachefalse
disable_donation_checkDisable the donation check. This doesn't mean you can watch without a donation, but the donation check fails for Locast Cares accountsfalse
logfileLog to a specific fileBy default locast2tuner will not log to a file
multiplexNormally, when you override multiple zip codes, locast2tuner starts multiple instances (see "bind_address"), but with "multiplex = true", stations from multiple locations will be available through a single instancefalse
no_tvc_guide_stationDon't include tvc_guide_station in tuner.m3u. Having this field sometimes breaks things in Channels DVR.false
override_citiesCities to override the location. Please see locast.org for a current map of the supported regions. This should be a pipe separated list with cities and states. E.g. --override_cities "Los Angeles, CA\|Portland, OR"Unset. locast2tuner will use your external IP to determine your location
override_zipcodesZip codes to override the location. Please see locast.org for a current map of the supported regions. This should be a comma separated list. E.g. --override_zipcodes "90210,33101"Unset. locast2tuner will use your external IP to determine your location
portTCP port to bind to. The default is 6077. In case you override muliple zip codes, locast2tuner will bind to multiple ports, starting at the number specified below (or default 6077). Any additional instance will bind to a port incremented by 1. E.g. if you override 3 zip codes, 3 instances will be started and bound to 6077, 6078 and 6079. In order to only use one instance, use multiplex6077
quietDon't output anything to the terminalfalse
random_zipcodeWhen --override_cities is used, locast2tuner looks up a list of valid zip codes for each city and will pick the first valid zip code, with --random_zipcode a random valid zip code for the city specified will be picked.false
remapRemap channel numbers when multiplexing. In case you override multiple zip codes, Emby and Plex will sort channels by channel number, which means channels from different locations might be intermingled. In order circumvent this, you can use "remap = true". This causes locast2tuner to rewrite the channel number based on the amount of instances there are. Locast will remap a "channel_number" to "channel_number + 100 * instance_number", where the instance_number starts at 0. E.g. you override 3 zip codes, then the channels from the first location will be untouched (since 100*0 == 0), the stations for the second location will start at 100 (e.g. 2.1 CBS becomes 102.1 CBS) and the stations for the third location will start at 200 (e.g. 13.2 WWFF becomes 213.2 WWFF). Note that multiplex has to be enabled!false
remap_fileFile that can be used to do a custom remap. More info can be found here. Note that multiplex has to be enabled!Unset
skip_hlsInstead of using hls.locastnet.org, use the proxy closer to the destinationfalse

rust_backtrace | Enable RUST_BACKTRACE=1. In error logs, you might see "run with RUST_BACKTRACE=1 environment variable to display a backtrace". Instead of adding the environment variable, you can enable this behavior with rust_backtrace | false syslog | Log through syslogd | false tuner_count | The amount of tuners that is communicated to Plex. This will limit the amount of streams that Plex will Note that this is not a limitation in locast2tuner | 16 verbose | Verbosity. 0 = Info, 1 = Info + HTTP request lgos, 2 = Debug, 3 = Trace. In error logs, you might see "run with RUST_BACKTRACE=1 environment variable to display a backtrace". Setting the verbosity to 2 or 3 will also include the backtrace | 0

Displaying running config

You can display your running config (which could be a combination of a config file and command line parameters) by opening the /config path (e.g. http://127.0.0.1:6077/config). Normally the password is obfuscated, but if you add the query parameter show_password (e.g. http://127.0.0.1:6077/config?showpass), the password will become visible.

Advanced topics

The following chapters provide some more information on some of the more advanced features that locast2tuner provides.

Regions

locast2tuner can manipulate regions in various different ways. It can override the location you appear to be coming from and it supports using multiple locations at the same time.

Location overrides

By default locast2tuner uses your IP address to determine your location, but it also allows you to override the locast.org location you're creating a tuner for. This is done by mapping a zip code to geographical coordinates. Check locast.org for an up-to-date list of available locations.

There are two configuration options available to override the location:

OptionDescriptionExamples
override_zipcodesUse a comma separated list of zip codes--override_zipcodes "90210,55111"(cli)
$l2t_override_zipcodes="90210,55111" (env vars)
override_zipcodes = ["90210", "55111"](config file)
override_citiesUse a pipe separated list of "City, State"--override_cities "Los Angeles, CA\|Portland, OR"(cli)
$l2t_override_cities="Los Angeles, CA\|Portland, OR" (env vars)
override_cities = ["Los Angeles, CA", "Portland, OR"](config file)

A file with all available locast regions is included in the locast2tuner distribution.

Multiple instances

When using multiple locations, locast2tuner will start multiple instances. Those instances will be available on TCP ports starting at the value that is specified with the port (or the default 6077) argument and incremented by one. It will also generate UUIDs for each tuner.

PMS supports multiple devices, but does not support multiple Electronic Programming Guides (EPGs). Emby supports both. I personally use Emby since it allows for multiple EPGs.

Multiplexing

locast2tuner normally starts an HTTP instance for each Tuner, starting at port (default 6077). But with the option multiplex, it will start a single HTTP interface multiplexing all Tuners through one interface for both streaming and EPG.

For example: if you use --multiplex --override_zipcodes=90210,55111, all channels from both ZIP codes will be available, but multiplexed at http://localhost:6077.

This type of multiplexing makes sense in Emby, since you can add a single tuner at http://PORT:IP or http://PORT:IP/tuner.m3u and a single EPG at http://PORT:IP/epg.xml

Tuner Emulation

locast2tuner can act as both a HDHomerun device or as an m3u tuner. Plex mainly supports HDHomerun, while Emby supports both.

In case locast2tuner is used as an HDHomerun device it will copy the mpegts stream from locast.org to the Media server. This means that the video stream itself will be passed through locast2tuner.

When using locast2tuner as an m3u tuner, it will pass on the m3u from locast to the media server without any stream interference. This means that the media server will directly connect to the stream.

  • For use as a HDHomerun tuner, use IP:PORT (defaults to http://127.0.0.1:6077) to connect
  • For use as an m3u tuner, use http://IP:PORT/tuner.m3u (defaults to http://127.0.0.1:6077/tuner.m3u) as the URL to connect.

Electronic Programming Guide

locast2tuner also provides Electronic Programming Guide (EPG) information from locast.org. This is served in the XMLTV format. Emby and PMS both have support for XMLTV which can be used by adding http://IP:PORT/epg.xml (defaults to http://127.0.0.1:6077/epg.xml) as an XMLTV TV Guide Data Provider.

In case Multiplexing is used, all EPG data is multiplexed as well.

Remapping

In case you override multiple zip codes, Emby and Plex will sort channels by channel number, which means channels from different locations might be intermingled. In order circumvent this, you can remap channels. locast2tuner offers two ways of remapping channels: --remap and --remap_file. Note that these two options are mutually exclusive, but both can appear in a config file. If both appear, then the --remap option takes precedence.

❗ Remapping only works when using multiplex.

The easiest way is to use --remap option. This causes locast2tuner to rewrite the channel number based on the amount of instances there are. Locast will remap a "channel_number" to "channel_number + (100 * instance_number)", where the instance_number starts at 0. E.g. you override 3 zip codes, then the channels from the first location will be untouched (since 100 * 0 == 0). The stations for the second location will start at 100 (e.g. 2.1 CBS becomes 102.1 CBS) and the stations for the third location will start at 200 (e.g. 13.2 WWFF becomes 213.2 WWFF).

Another way to do remapping is to use the --remap_file <filename> option. You can specify a JSON file containing your remappings. To get your current mappings, you can go to http://PORT:IP/map.json. Copy that content to a JSON file (you'll want to pretty it up too to make it easier to work with) and you can edit that JSON file, save it, and then use --remap_file <filename> to load those remappings the next time you run locast2tuner. You will need to restart locast2tuner in order to see any changes you made (and you may need to recreate your tuner/EPG setup to have Plex or Emby reflect the right channels).

This is currently a manual edit process, so if you want to go this route, please be sure that the JSON content is valid JSON before trying to use it. A web-based remap editor is in the works.

Logging

locast2tuner has a few options for logging: directly to the terminal (default), logging to a file and logging through syslog. You can combine the way you want to log by specifying multiple options:

  • quiet: disable logging to the terminal
  • syslog: log through syslog
  • logfile <filename>: log to a file separately

Debugging

Media servers communicate with locast2tuner using HTTP. The following URLs might come in handy when debugging. By default these URLs are accessible on http://127.0.0.1:6077.

URLDescription
/ or /device.xmlHDHomerun device.xml
/discover.jsonHDHomerun discover.json
/epg.xmlElectronic Programming Guide in XMLTV format
/epgElectronic Programming Guide in JSON format. This format is mainly used for debugging and is pretty much all the data that was received from locast.org
/lineup_status.jsonHDHomerun lineup status
/lineup.jsonHDHomerun lineup.json
/lineup.postURL that HDHomerun uses to trigger a refresh. This doesn't do anything
/lineup.xmlHDHomerun lineup.xml
/map.jsonShows how channel mapping is currently configured
/tuner.m3uLineup for m3u tuners
/watch/{channel_id}.m3uRequest an m3u stream for a channel_id
/watch/{channel_id}Request an mpegts stream for a channel_id

You can open the above URLs in a browser and directly see the output.

In order to debug video streams, you can use ffplay (part of ffmpeg). E.g. ffplay http://127.0.0.1/watch/223892.m3u.

Quickstart Guides

The following quickstart guides should help you set up locast2tuner in combination with Emby or Plex.

Integrating with Emby

Emby supports both HDHomerun and m3u tuner modes, both of which are supported by locast2tuner. This guide will walk you through adding your working locast2tuner tuner to Emby in m3u mode.

  • In Emby, click the gear icon at the top right to go to settings.

gear icon

  • In the left side bar, scroll down and click "Live TV" under "Live TV."

live tv

  • You should be presented with this screen. Click the "+" sign beside "TV Sources."

setup screen

  • Enter the locast2tuner address manually. Click the "Type" dropdown box and select "M3U Tuner."

enter manually

  • Enter the URL of your locast2tuner server in http://IP_ADDR:PORT/tuner.m3u format and click "Connect." Below we are using http://10.19.71.3:6077/tuner.m3u.

If you are running locast2tuner in a Docker container in the same Docker network as PMS (or using docker-compose), you can enter the container name instead of the IP address.

enter address

  • Click "Save." Emby should now show your locast2tuner as a TV source"

tuner found

  • Emby and locast2tuner both support XMLTV guides. Click the "+" sign beside "TV Guide Data Providers" to add our guide.

channels found

  • Click the "Country" dropdown and select "United States" (locast only supports US markets currently).

  • Click the "Guide source" dropdown and select "XmlTV."

  • Click "Next."

add XMLTV source

In the "File or url" field, enter the URL to the XMLTV guide on locast2tuner in the format http://IP_ADDR:PORT/epg.xml and click "Save." Below we are using http://10.19.71.3:6077/epg.xml.

If you are running locast2tuner in a Docker container in the same Docker network as PMS (or using docker-compose), you can enter the container name instead of the IP address.

XMLTV guide

  • Allow Emby to download the guide data from locast2tuner and you should now have both the tuner and guide sources listed on the screen.

guide update

sources

  • You're done! On the Emby home screen, you should now see a Live TV section where you can jump to the guide to watch TV or set recordings.

emby home

guide

select show

watch show

Return to the locast2tuner project

Integrating with Plex Media Server

Plex Media Server (PMS) only supports HDHomerun mode which is supported by locast2tuner. This guide will walk you through adding your working locast2tuner tuner to PMS.

  • In PMS, click the tools icon at the top right to go to settings.

settings icon

  • In the left side bar, scroll down and click "Live TV & DVR" under "Manage."

live tv

  • You should be presented with this screen. If you have multiple servers in your PMS account, make sure that you focused on the local one. The name of the server in the below screenshot is "roddie."

  • Click "Set up Plex DVR"

setup screen

  • Enter the locast2tuner address manually. Click the link shown in the screenshot to do this.

enter manually

  • Enter the IP address and TCP port of your locast2tuner server in IP_ADDR:PORT format and click "Connect." Below we are using 10.19.71.3:6077.

If you are running locast2tuner in a Docker container in the same Docker network as PMS (or using docker-compose), you can enter the container name instead of the IP address.

enter address

  • PMS should then find your locast2tuner and display the location. Click "Continue."

tuner found

  • You'll then be shown a list of all of the channels that were found on your tuner. These are coming directly from Locast they should be accurate. You can click "Scan Channels" again if you think there are some missing. Otherwise, click "Continue."

channels found

  • PMS and locast2tuner both support XMLTV guides, so instead of pulling from a third-party source, click the link as shown in the screenshot.

add XMLTV source

For this field, enter the URL to the XMLTV guide on locast2tuner in the format http://IP_ADDR:PORT/epg.xml and click "Continue." Below we are using http://10.19.71.3:6077/epg.xml.

If you are running locast2tuner in a Docker container in the same Docker network as PMS (or using docker-compose), you can enter the container name instead of the IP address.

XMLTV guide

  • Verify that the mappings are correct between your locast2tuner channels and the guide channels (they should be), and click "Continue."

guide channel mapping

  • Wait for PMS to update the guide, which should only take a couple of minutes, and then click "View Guide" to go to your newly added TV guide.

adding guide data

view guide

  • You're done! You should now be able to click any show in the guide to either watch live or set a recording.

select show

watch show

You may sometimes experience a quick few second pause after the first couple of seconds before the show continues. This is expected in HDHomerun mode.

Return to the locast2tuner project

Frequently Asked Questions

I'm getting a "Login failed". What's up?

A few things could be up. First, make sure you can login to locast.org in a browser and make sure you have an active donation. If you haven't already, try running locast2tuner from the command line with a higher verbose level like:

locast2tuner -v3 --config /your/config --other_options_you_have_specified

It should show you why you couldn't log in. A 404 error means that your login credentials are unknown. Sometimes locast.org returns a HTTP 204, which means that login succeeded, but that no data was returned. This might happen sporadically and it seems to be an intermittent failure. Or it could have something to do with your network connection or a proxy that doesn't do what you want it to do.

Sponsoring

If you use locast2tuner and want to contribute by sponsoring, please leave a donation at my Sponsor Page. All of the money donated will go towards organizations that support women and underprivileged children in STEM education like BUILT BY GIRLS, Electric Girls, Project Exploration and others.