Automate TV guides to XMLTV format. Easy to use, up-to-date. See below for getting started.
A note on this fork: This project traces back to the original zap2xml work by Jef LeCompte (@jef), and this fork also builds on the many improvements Jesse Mann (@jesmannstl) made in his version. I'm maintaining this fork for my own use and will do my best to keep it alive and honor the work that came before it. Thank you to Jef and Jesse for what they contributed.
A version of the original Perl implementation is preserved in the historical-perl branch if you're interested in that.
See the Wiki for guides on Installation in node.js, How to Run, Scheduling, and using Docker.
Need help? See Finding a lineup or Dish and DirecTV lineups, or drop a line in the Discussions.
Use --config=path/to/listings.yml to fetch multiple TV lineups in a single run. See the Multi-Listing Config wiki page for the full YAML format, precedence rules, and Docker setup.
Add --merge to also write every listing combined into a single XMLTV file. Channels are deduplicated by channel ID, and programmes by channel and start time, so stations carried by more than one lineup appear once.
listings:
- name: dtv
lineupId: USA-DITV751-X
postalCode: "80020"
outputFile: dtv.xml
- name: ota
lineupId: USA-OTA80020
postalCode: "80020"
outputFile: ota.xml
merge:
enabled: true
outputFile: merged.xml
keepIndividual: true
dedupe: first| Option | Env | Description |
|---|---|---|
--merge |
MERGE |
Write all listings combined into one file |
--mergeOutputFile=FILE |
MERGE_OUTPUT_FILE |
Merged file name (implies --merge, default merged.xml) |
--mergeDedupe=MODE |
MERGE_DEDUPE |
Which duplicate to keep: first (default) or last |
--noKeepIndividual |
MERGE_KEEP_INDIVIDUAL=false |
Only write the merged file, skipping per-listing files |
By default the per-listing files are still written alongside the merged one. This works in single-listing mode too, though with one listing the merged file is just a copy.
- Changed default Sort option to the Channel Number in Lineup if available
- Added '--stationid' to sort the previous way by StationID
- Added
--sortnameto sort by the Call Sign
- Changed URL pull to match output from page when stopped working
- Added Display Name with Channel Number and Call Sign to mirror previous Perl Script
- Added
--nextpvroption to list Channel Number Call Sign first
- Restored
<episode-num system="dd_progid">tag that Plex uses that was missing. - Fixed Sorting so output is listed by Channel ID (common station/gracenote id) then by date/time.
- Reordered Program fields to match original Perl script output
--postalCodenot required as long as Country and lineup Id correct except Over the Air- Moved
<date>above<category>to match original Perl output. Corrected where Movie Release Year is properly displayed. - Added
<length>tag. - Updated channel logo no longer has fixed width so can display in better quality
- Added Valid Country Codes that can be used
- Added
--mediaportaloption to use<episode-num system="xmltv_ns">before others so Media Portal will display Season/Episode properly
Changes from jef's original (by jesmannstl)
- Added Category if available (Movie, Sports, News, Talk, Family etc)
- Added Category "Series" to all programs that did not return a category
- Added additional Season Episode formats for various players
- Added year as Season for programs that only list an episode number like daily cable news
- Added
<date>tag to all programs without an aired date normalized to America/New York - Added xmltv_ns with the date aired as Season YYYY Episode MMYY to Non Movie or Sports with no other Season/Episode like local news so would have the ability to record as Series is most players.
- Added URL to program details from old Perl function.
- Added --appendAsterisk to add * to title on programs that are New and/or Live
- Added
<previously-shown />tag to programs that are not<New>and/or<Live> - Updated
affiliateIdafterorbebbstopped working - Updated Docker with these changes use APPEND_ASTERISK: TRUE for the --appendAsterisk option
Changes in this fork from jessman's fork
- Docker image uses Bun runtime instead of Node.js - smaller image, and probably some (likely unnoticeable with typical use) performance/memory usage improvements!
- Ability to fetch multiple lineups using a single
zap2xmlinstance - no longer have to run multiple containers to fetch multiple lineups! (see Multi-Listing Config) --mergecombines all listings into one deduplicated XMLTV file, so you don't need a separate merge step for multi-lineup setups