Skip to main content

Overview

Dispatcharr emulates an HDHomeRun network tuner device, enabling seamless integration with media servers like Plex, Emby, and Jellyfin. This compatibility layer allows any application that supports HDHomeRun devices to use Dispatcharr as a live TV source.

What is HDHomeRun?

HDHomeRun is a popular network-attached TV tuner device that allows you to watch and record live TV over your local network. Many media center applications have built-in support for HDHomeRun devices, making it an ideal protocol for IPTV integration.

How Emulation Works

Dispatcharr implements the HDHomeRun HTTP API, providing the same endpoints and response formats that physical HDHomeRun devices use. When media servers scan for tuners, they discover Dispatcharr and interact with it just like a real HDHomeRun device.

Emulated Device Specifications

  • Model Number: HDTC-2US
  • Firmware: hdhomerun3_atsc
  • Firmware Version: 20200101
  • Device ID: 12345678 (default) or dispatcharr-hdhr-{profile} for named profiles
  • Tuner Count: Configurable (default: 10)
  • Source Type: Cable
The tuner count represents how many concurrent streams can be active simultaneously. This can be configured in Dispatcharr settings.

API Endpoints

Dispatcharr provides the following HDHomeRun-compatible endpoints:

Device Discovery

Endpoint: GET /hdhr/discover.json Endpoint (Profile): GET /hdhr/{profile}/discover.json Returns device information and capabilities. Response:
{
  "FriendlyName": "Dispatcharr HDHomeRun",
  "ModelNumber": "HDTC-2US",
  "FirmwareName": "hdhomerun3_atsc",
  "FirmwareVersion": "20200101",
  "DeviceID": "12345678",
  "DeviceAuth": "test_auth_token",
  "BaseURL": "http://YOUR_SERVER:9191/hdhr",
  "LineupURL": "http://YOUR_SERVER:9191/hdhr/lineup.json",
  "TunerCount": 10
}
Implementation Reference: apps/hdhr/api_views.py:DiscoverAPIView (line 47-95)
# Default DeviceID
device_ID = "12345678"

# Profile-specific DeviceID
if profile is not None:
    device_ID = f"dispatcharr-hdhr-{profile}"
    friendly_name = f"Dispatcharr HDHomeRun - {profile}"

Channel Lineup

Endpoint: GET /hdhr/lineup.json Endpoint (Profile): GET /hdhr/{profile}/lineup.json Returns the list of available channels with stream URLs. Response:
[
  {
    "GuideNumber": "1",
    "GuideName": "ABC HD",
    "URL": "http://YOUR_SERVER:9191/proxy/ts/stream/channel-uuid",
    "Guide_ID": "1",
    "Station": "1"
  },
  {
    "GuideNumber": "2.1",
    "GuideName": "CBS HD",
    "URL": "http://YOUR_SERVER:9191/proxy/ts/stream/channel-uuid",
    "Guide_ID": "2.1",
    "Station": "2.1"
  }
]
Implementation Reference: apps/hdhr/api_views.py:LineupAPIView (line 98-135)
# Default: All channels
channels = Channel.objects.all().order_by("channel_number")

# With profile: Filtered channels
if profile is not None:
    channel_profile = ChannelProfile.objects.get(name=profile)
    channels = Channel.objects.filter(
        channelprofilemembership__channel_profile=channel_profile,
        channelprofilemembership__enabled=True,
    ).order_by("channel_number")

Lineup Status

Endpoint: GET /hdhr/lineup_status.json Returns the current status of the channel lineup. Response:
{
  "ScanInProgress": 0,
  "ScanPossible": 0,
  "Source": "Cable",
  "SourceList": ["Cable"]
}
Implementation Reference: apps/hdhr/api_views.py:LineupStatusAPIView (line 138-152)

Device XML

Endpoint: GET /hdhr/device.xml Returns device information in XML format (used by some older clients). Response:
<?xml version="1.0" encoding="utf-8"?>
<root>
    <DeviceID>12345678</DeviceID>
    <FriendlyName>Dispatcharr HDHomeRun</FriendlyName>
    <ModelNumber>HDTC-2US</ModelNumber>
    <FirmwareName>hdhomerun3_atsc</FirmwareName>
    <FirmwareVersion>20200101</FirmwareVersion>
    <DeviceAuth>test_auth_token</DeviceAuth>
    <BaseURL>http://YOUR_SERVER:9191/hdhr</BaseURL>
    <LineupURL>http://YOUR_SERVER:9191/hdhr/lineup.json</LineupURL>
</root>
Implementation Reference: apps/hdhr/api_views.py:HDHRDeviceXMLAPIView (line 155-177)

Stream Proxy

Endpoint: GET /proxy/ts/stream/{channel_uuid} Proxies the actual IPTV stream. This endpoint handles:
  • Stream authentication
  • Failover management
  • Transcoding (if configured)
  • Client tracking
  • Bandwidth monitoring
Implementation Reference: apps/output/views.py (stream handling logic)

Using Channel Profiles

Channel profiles allow you to create multiple virtual HDHomeRun devices, each with different channel lineups:
1

Create Channel Profile

In Dispatcharr:
  1. Navigate to SettingsChannel Profiles
  2. Click Add Profile
  3. Name your profile (e.g., “sports”, “news”, “kids”)
  4. Assign channels to the profile
  5. Save the profile
2

Access Profile-Specific Endpoints

Use the profile name in the URL:
http://YOUR_SERVER:9191/hdhr/sports/discover.json
http://YOUR_SERVER:9191/hdhr/sports/lineup.json
3

Configure in Media Server

Add as separate tuner devices in your media server, each with its own profile URL.

Example: Multiple Profile Setup

Profile Name: sports
Discover URL: http://192.168.1.100:9191/hdhr/sports/discover.json
Lineup URL: http://192.168.1.100:9191/hdhr/sports/lineup.json
Device Name: Dispatcharr HDHomeRun - sports

Network Discovery

HDHomeRun devices are typically discovered on the network using UDP broadcast. However, Dispatcharr requires manual configuration because:
  1. HTTP-Only Implementation: Dispatcharr implements only the HTTP API, not the UDP discovery protocol
  2. Container Networking: Docker/containerized deployments may not support UDP broadcast
  3. Explicit Control: Manual configuration gives you precise control over device URLs

Manual Configuration Steps

When adding Dispatcharr to your media server:
  1. Select manual/custom HDHomeRun device
  2. Enter the discovery URL: http://YOUR_SERVER:9191/hdhr/discover.json
  3. The media server will query this endpoint and configure the device

Technical Implementation Details

Tuner Count Calculation

The tuner count represents concurrent stream capacity:
def calculate_tuner_count(minimum=1, unlimited_default=10):
    # Returns configured stream limit or default
    # Used in discover.json response
    return tuner_count
This value is reported to media servers and affects:
  • Maximum simultaneous recordings
  • Concurrent stream limits
  • Resource allocation

Channel Number Formatting

Dispatcharr intelligently formats channel numbers:
if channel.channel_number == int(channel.channel_number):
    # No decimal component: "5" instead of "5.0"
    formatted_channel_number = str(int(channel.channel_number))
else:
    # Has decimal component: "5.1", "5.2", etc.
    formatted_channel_number = str(channel.channel_number)
This ensures compatibility with media servers expecting both major and subchannel numbers.

Stream URL Generation

Each channel gets a unique stream URL:
stream_url = request.build_absolute_uri(f"/proxy/ts/stream/{ch.uuid}")
# Example: http://192.168.1.100:9191/proxy/ts/stream/abc123-def456-uuid
The UUID ensures:
  • Unique identification of each channel
  • Secure stream access
  • Proper routing through Dispatcharr’s proxy

Compatibility

Dispatcharr’s HDHomeRun emulation is compatible with:
ApplicationSupport LevelNotes
Plex✅ FullAuto-discovery with host network mode
Emby✅ FullManual configuration recommended
Jellyfin✅ FullNative HDHomeRun support
Channels DVR✅ FullAdd as custom source
Kodi✅ PartialVia PVR IPTV Simple Client
VLC✅ FullM3U export preferred
MythTV⚠️ UntestedShould work with manual config

Troubleshooting

Device Not Discovered

Auto-discovery requires host network mode or specific network configuration. Use manual device configuration for reliability.
Solution:
  1. Use manual/custom device configuration
  2. Enter discovery URL directly: http://YOUR_IP:9191/hdhr/discover.json
  3. Verify network connectivity between services

Empty Channel Lineup

Check:
  • Channels are created in Dispatcharr
  • Channel numbers are assigned
  • Channels are enabled
  • Profile filter (if using profiles)
Test:
curl http://YOUR_SERVER:9191/hdhr/lineup.json
Should return JSON array with channels.

Streams Don’t Play

Verify:
  1. Test stream URL directly in VLC:
    http://YOUR_SERVER:9191/proxy/ts/stream/CHANNEL_UUID
    
  2. Check Dispatcharr logs for stream errors
  3. Verify source streams are accessible
  4. Check stream profile configuration

Profile-Specific Issues

Common Mistakes:
  • Profile name mismatch (case-sensitive)
  • Profile has no enabled channels
  • Using default URL instead of profile URL
Verify Profile:
curl http://YOUR_SERVER:9191/hdhr/PROFILE_NAME/lineup.json

Advanced Configuration

Custom Base URL

If accessing Dispatcharr through a reverse proxy or custom domain:
# Dispatcharr automatically builds URLs based on request
base_url = request.build_absolute_uri(f'/{uri_parts}/')
Ensure your reverse proxy passes correct headers:
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;

Multiple Instances

Run multiple Dispatcharr instances on different ports:
services:
  dispatcharr-main:
    image: ghcr.io/dispatcharr/dispatcharr:latest
    ports:
      - "9191:9191"
  
  dispatcharr-backup:
    image: ghcr.io/dispatcharr/dispatcharr:latest
    ports:
      - "9192:9191"
Each instance appears as a separate HDHomeRun device.

Security Considerations

  • Authentication: HDHomeRun protocol doesn’t include authentication. Use network-based access control in Dispatcharr.
  • Firewall: Limit access to port 9191 to trusted networks
  • HTTPS: Use reverse proxy with SSL for encrypted access