Skip to content

Linux DVB-T USB Tuner Driver

Overview

The DVB-T (Digital Video Broadcasting — Terrestrial) USB tuner driver enables ingestion of terrestrial TV streams from Linux DVB-T USB dongles. It interfaces with kernel DVB devices via /dev/dvb/ and produces transport stream URLs for FFmpeg HLS packaging.

Supported Hardware

  • RTL2832U-based USB dongles (e.g., ezcap, FlightAware Pro Stick)
  • Other chipsets with Linux DVB-T driver support
  • Any device exposing /dev/dvb/adapter*/frontend*

Architecture

LiveTvManager
├── HdHomeRunTunerDriver (SSDP discovery + HTTP API)
├── IptvTunerDriver (M3U playlist + XMLTV)
└── DvbtTunerDriver (Linux DVB API via /dev/dvb)
    ├── DvbtDevice (device descriptor)
    ├── DvbtDeviceScanner (/dev/dvb/ scanner)
    ├── DvbtSignalEngine (dvbv5-zap + FFmpeg)
    └── DvbtTunerDriverFactory (config builder)

Linux DVB API

The Linux DVB API provides access to digital TV hardware through device nodes in /dev/dvb/:

Device Structure

/dev/dvb/
├── adapter0/
│   ├── demux0       # Demultiplexer device
│   ├── dvr0         # Digital Video Recording device (for streaming)
│   ├── frontend0    # Tuner/frontend device
│   └── net0        # Network device (for DVR input)
├── adapter1/
│   └── ...

Frontend Device

The frontendN device controls the tuner:

  • Tunes to specific frequencies
  • Reports signal strength, SNR, BER
  • Provides access to transport stream via /dev/dvb/adapterX/dvrN

Configuration

Add DVB-T configuration to config/livetv.php:

php
'livetv' => [
    // ... existing hdhomerun config ...

    'dvbt' => [
        'enabled' => true,
        'ffmpeg_path' => '/usr/bin/ffmpeg',
        'dvbv5_zap_path' => '/usr/bin/dvbv5-zap',
        'default_modulation' => 'auto',
        'default_bandwidth_mhz' => 8,
    ],
],

Configuration Options

OptionTypeDefaultDescription
enabledbooltrueEnable DVB-T tuner support
ffmpeg_pathstring/usr/bin/ffmpegPath to FFmpeg binary
dvbv5_zap_pathstring/usr/bin/dvbv5-zapPath to dvbv5-zap binary
default_modulationstringautoDefault modulation type
default_bandwidth_mhzint8Default bandwidth in MHz

Modulation Types

DVB-T supports several modulation schemes:

ModulationDescriptionTypical Use
QPSKQuadrature Phase-Shift KeyingHierarchical modulation
QAM6464-state Quadrature Amplitude ModulationStandard definition
QAM256256-state Quadrature Amplitude ModulationHigh definition
DVB-TCOFDM with QPSK/QAM64/QAM256Legacy standard
DVB-T2Extended COFDMHD/SD with improved efficiency
autoLet the driver decideRecommended default

Frequency Ranges

DVB-T operates in VHF (174-230 MHz) and UHF (470-862 MHz) bands:

European UHF Channel Frequencies

ChannelFrequency (MHz)ChannelFrequency (MHz)
2147446674
2248247682
2349048690
2449849698
2550650706
............
4566669858

dvbv5-zap Usage

The dvbv5-zap tool is the standard Linux DVB tuning utility:

bash
# Tune to 474 MHz with auto modulation
dvbv5-zap -a 0 -f 474000000 -m auto -c /dev/null -d 0 -o output.ts

# Options:
#   -a <adapter>    Adapter index (0, 1, ...)
#   -f <freq>      Frequency in Hz
#   -m <mod>       Modulation (auto, QAM64, QAM256, QPSK, DVB-T, DVB-T2)
#   -c <config>    Config file (use /dev/null for defaults)
#   -d <frontend>  Frontend index
#   -o <output>   Output file or pipe

Reading Signal Status

Signal information is available via sysfs:

bash
# Signal strength (0-65535)
cat /sys/class/dvb/dvb0.frontend0/signal_strength

# SNR (0-65535)
cat /sys/class/dvb/dvb0.frontend0/snr

# Bit error rate
cat /sys/class/dvb/dvb0.frontend0/ber

# Uncorrected blocks
cat /sys/class/dvb/dvb0.frontend0/ucblocks

FFmpeg HLS Packaging

The transport stream from DVB-T is repackaged to HLS for web playback:

bash
# Read from DVR device and output HLS
ffmpeg -i /dev/dvb/adapter0/dvr0 \
  -c:v libx264 -c:a aac \
  -f hls -hls_time 4 -hls_list_size 6 \
  /var/www/html/livetv/stream.m3u8

Class Reference

DvbtDevice

Immutable descriptor for a DVB-T device:

php
$device = new DvbtDevice(
    adapterPath: '/dev/dvb/adapter0',
    adapterIndex: 0,
    frontendIndex: 0,
    modulation: 'auto',
    frequencyMin: 470000000,
    frequencyMax: 862000000
);

// Get frontend device path
$frontendPath = $device->getFrontendPath();  // /dev/dvb/adapter0/frontend0

// Get DVR device path for streaming
$dvrPath = $device->getDvrPath();  // /dev/dvb/adapter0/dvr0

// Check if frequency is supported
$isSupported = $device->isFrequencySupported(474000000);

DvbtDeviceScanner

Scans /dev/dvb/ for available adapters:

php
$scanner = new DvbtDeviceScanner($logger);
$devices = $scanner->scan();

foreach ($devices as $device) {
    echo "Found: {$device->adapterPath}\n";
}

DvbtSignalEngine

Handles tuning and streaming:

php
$engine = new DvbtSignalEngine(
    ffmpegPath: '/usr/bin/ffmpeg',
    dvbv5ZapPath: '/usr/bin/dvbv5-zap',
    logger: $logger
);

// Tune to frequency and get ingest URL
$ingestUrl = $engine->tune($device, 474000000, 'auto');

// Get stream URL for channel number
$streamUrl = $engine->getStreamUrl($device, 1);

// Probe signal strength
$signal = $engine->getSignalStrength($device);
// Returns: ['signal' => 50000, 'snr' => 45000, 'ber' => 0, 'ucblocks' => 0]

DvbtTunerDriver

Implements TunerDriverInterface for LiveTvManager integration:

php
$driver = DvbtTunerDriverFactory::build($config, $logger);

// Discover devices
$devices = $driver->discoverDevices();

// Get stream URL
$streamUrl = $driver->getStreamUrl($device, 21);  // Channel 21 = 474 MHz

DvbtTunerDriverFactory

Factory for creating driver instances:

php
// Build from config
$driver = DvbtTunerDriverFactory::build($livetvConfig, $logger);

// Build with explicit paths
$driver = DvbtTunerDriverFactory::buildDefault(
    ffmpegPath: '/usr/local/bin/ffmpeg',
    dvbv5ZapPath: '/usr/local/bin/dvbv5-zap',
    logger: $logger
);

Integration with LiveTvManager

LiveTvManager automatically discovers and registers DVB-T tuners:

php
$livetvConfig = include 'config/livetv.php';

// Create DVB-T driver if enabled
$dvbtDriver = DvbtTunerDriverFactory::build($livetvConfig, $logger);

// Create HDHomeRun driver (primary)
$hdhomerunDriver = HdHomeRunTunerDriverFactory::build($livetvConfig, $logger);

// Create LiveTvManager with multiple drivers
$manager = new LiveTvManager(
    $db,
    $channelManager,
    $guideManager,
    $recorder,
    $hdhomerunDriver,           // Primary driver
    $logger,
    [$dvbtDriver, $iptvDriver] // Additional drivers
);

// Discover all tuners
$tuners = $manager->discoverTuners();

Database Schema

The livetv_tuners table stores tuner information with type dvb_t:

ColumnTypeDescription
tuner_idVARCHAR(36)Unique identifier (e.g., dvbt_0_0)
nameVARCHAR(255)Display name
typeVARCHAR(20)Tuner type (dvb_t, hdhomerun, iptv)
statusVARCHAR(20)Current status
capabilitiesJSONTuner capabilities including frequency range
discovered_atDATETIMEDiscovery timestamp

Error Handling

The driver handles common error cases:

  • No /dev/dvb: Returns empty device list, logs warning
  • dvbv5-zap not found: Returns direct DVR device path as fallback
  • Tuning failed: Throws RuntimeException
  • Signal lost: Returns 0 values for signal metrics

Testing

Run the DVB-T tuner tests:

bash
./vendor/bin/phpunit tests/unit/LiveTv/Tuners/Dvbt/

See Also

BSD-3-Clause