I'm poking at things a bit more with AI's help (AI's doing almost everything). I was able to get program descriptions out of the PSIP but not program name. Does anyone know if program name is likely to be missing from the stream, or do (A)I have more work to do here?
How Program Descriptions Are Obtained from HDHomeRun Flex 4K
Here's the complete process we discovered and implemented:
1. Capture the Raw Broadcast Stream
The HDHomeRun receives ATSC 1.0 digital TV signals over the air. We capture the raw MPEG transport stream using:
bashhdhomerun_config [device_ip] set /tuner0/channel auto:[rf_channel]
hdhomerun_config [device_ip] save /tuner0 [filename.ts]
2. Transport Stream Structure
The broadcast contains 188-byte packets with different PIDs (Packet IDs) carrying different data:
Video/Audio: PIDs like 0x0031, 0x0034 (the actual TV content)
PSIP Data: PIDs 0x1FFB (standard) or alternate PIDs like 0x1E00, 0x1D00 (in your area)
3. PSIP Tables Containing EPG Data
The program information is split across three table types:
TVCT (Terrestrial Virtual Channel Table) - Table ID 0xC8
Contains: Channel numbers (2.1, 2.2, etc.), channel names (KREM-HD, Crime, Grit)
Links channels to source_ids for matching with events
EIT (Event Information Table) - Table ID 0xCB
Contains: Event timing (start times, durations)
Should contain titles but in your broadcasts only has placeholder data
ETT (Extended Text Table) - Table ID 0xCC
Contains: Program descriptions/plot summaries
Linked to events via source_id and event_id
4. Data Extraction Process
The extractor:
Reads transport stream packets
Identifies PSIP packets by table ID
Reassembles sections that span multiple packets
Parses each table type according to ATSC A/65 specification
Combines data: matches ETT descriptions to EIT events using source_id
5. Your Local Broadcast Limitation
Your Spokane-area broadcasters transmit:
✓ Channel information (TVCT)
✓ Schedule timing (EIT)
✓ Program descriptions (ETT)
✗ Program titles (missing from EIT)
The descriptions exist because broadcasters include them in the ETT for viewer information, but they've chosen not to transmit program titles, possibly to save bandwidth or because they assume viewers use other guide sources.
6. Technical Discovery Process
We found your PSIP data uses non-standard PIDs (not 0x1FFB) through analysis, which required adapting the standard ATSC parsing to check alternate PIDs, demonstrating that different regions/broadcasters may implement ATSC differently while still being technically compliant.
$ python3 complete_epg_extractor.py channel15.ts
Processed 769,416 packets
Found 3 channels
Found 408 events
Found 10 event descriptions
Channel lineup:
6.1 'KHQ-HD' - 205 programs
6.2 'KHQSWX' - 203 programs
6.3 'KHQNEWS' - 0 programs
Sample programs:
6.1 21:00 - Actor Jessica St Claire joins Drew and Ross on the
6.1 11:30 - Members of the NBC news team report on the latest
6.2 21:00 - Program 13787
6.2 12:00 - Program 13785
PSIP Program Description Found
Re: PSIP Program Description Found
It's highly unlikely that the program name would be missing from the EIT on a major network affiliate.
Re: PSIP Program Description Found
Plugged in a TV with ATSC tuner and confirmed that program titles are being transmitted. More poking around -- I have a full EPG coming off the stream now. Credit to Claude. If you can keep AI boxed in, it can do a lot of good work. My EPG is online!
# Tune to physical channel
subprocess.run([
'hdhomerun_config',
device_ip, # IP address, NOT device ID
'set',
'/tuner0/channel',
f'auto:{physical_channel}'
])
# Capture transport stream with PSIP
subprocess.Popen([
'hdhomerun_config',
device_ip, # IP address, NOT device ID
'save',
'/tuner0',
output_file
])
1. **Standard PSIP PIDs**:
- `0x1FFB` - Base PID for PSIP
- `0x1D00-0x1D07` - EIT (Event Information Table)
- `0x1E00-0x1E80` - ETT (Extended Text Table)
2. **Non-Standard EIT Format** (Table ID 0xCB):
- Title field contains only 'e' (0x65)
- Actual titles are embedded in descriptor areas
- Requires special parsing to extract titles from ASCII text in descriptors
3. **Table Types**:
- `0xC8` - TVCT (Terrestrial Virtual Channel Table) - Channel lineup
- `0xCB` - EIT (Event Information Table) - Program schedule with non-standard titles
- `0xCC` - ETT (Extended Text Table) - Program descriptions
#### Non-Standard Title Extraction
```python
def parse_eit_nonstandard(self, data):
# Skip the 'e' in title field
title_len = data[offset]
offset += 1 + title_len # Skip the 'e'
# Extract title from descriptor area
desc_area = data[offset:offset+200]
# Find ASCII text (actual title)
for j in range(len(desc_area) - 10):
if 32 <= desc_area[j] < 127: # ASCII printable
# Extract title string
title = desc_area[j:end].decode('ascii')
```
# Tune to physical channel
subprocess.run([
'hdhomerun_config',
device_ip, # IP address, NOT device ID
'set',
'/tuner0/channel',
f'auto:{physical_channel}'
])
# Capture transport stream with PSIP
subprocess.Popen([
'hdhomerun_config',
device_ip, # IP address, NOT device ID
'save',
'/tuner0',
output_file
])
1. **Standard PSIP PIDs**:
- `0x1FFB` - Base PID for PSIP
- `0x1D00-0x1D07` - EIT (Event Information Table)
- `0x1E00-0x1E80` - ETT (Extended Text Table)
2. **Non-Standard EIT Format** (Table ID 0xCB):
- Title field contains only 'e' (0x65)
- Actual titles are embedded in descriptor areas
- Requires special parsing to extract titles from ASCII text in descriptors
3. **Table Types**:
- `0xC8` - TVCT (Terrestrial Virtual Channel Table) - Channel lineup
- `0xCB` - EIT (Event Information Table) - Program schedule with non-standard titles
- `0xCC` - ETT (Extended Text Table) - Program descriptions
#### Non-Standard Title Extraction
```python
def parse_eit_nonstandard(self, data):
# Skip the 'e' in title field
title_len = data[offset]
offset += 1 + title_len # Skip the 'e'
# Extract title from descriptor area
desc_area = data[offset:offset+200]
# Find ASCII text (actual title)
for j in range(len(desc_area) - 10):
if 32 <= desc_area[j] < 127: # ASCII printable
# Extract title string
title = desc_area[j:end].decode('ascii')
```