How to Organize IPTV Channels by Source Type (ATSC, DVB-S, Pluto) in Free-TV/IPTV
The Free-TV/IPTV repository organizes channels by source type using HTML <h2> headings within Markdown files in the lists/ directory, where the make_playlist.py script filters for rows containing the [>] marker to generate M3U playlists regardless of the heading structure.
Organizing IPTV channels by source type—such as ATSC, DVB-S, or Pluto—ensures clean separation of broadcast origins in the Free-TV/IPTV repository. This open-source project stores channel data as Markdown tables within country-specific files, using simple HTML heading tags to denote source categories. Understanding how the playlist generator interprets these files allows contributors to structure content correctly without breaking the automated build process.
How Channel Organization Works in Free-TV/IPTV
The repository maintains channel data in the lists/ directory as individual Markdown files (e.g., lists/usa.md, lists/uk.md). Each file represents a country and contains one or more tables listing available streams.
Source type organization relies on HTML <h2> headings inserted above table sections. Common headings include <h2>ATSC</h2>, <h2>DVB-S</h2>, and <h2>Pluto</h2>. These headings serve as visual separators for human editors; the generator script does not parse them programmatically but treats all valid rows uniformly.
The make_playlist.py script scans every .md file in lists/ and generates M3U playlists by looking for the [>] marker in table rows. Only rows containing this marker are converted to playlist entries, while the surrounding HTML headings are ignored during processing.
Step-by-Step Guide to Organizing Channels by Source Type
Locate and Open the Country File
Navigate to the lists/ directory and open the relevant country file. For United States channels, edit lists/usa.md. The file should contain an <h1> heading with the country name, followed by sections demarcated by <h2> tags.
Insert Source Type Headings
Add or locate the appropriate <h2> heading for your source type. If adding ATSC channels, ensure the section begins with <h2>ATSC</h2>. For satellite streams, use <h2>DVB-S</h2>, and for Pluto TV streams, use <h2>Pluto</h2>. You can create new source type headings arbitrarily; the generator will include any valid rows beneath them.
Add Channel Rows with the Stream Marker
Insert a Markdown table row under the appropriate heading, ensuring it contains the [>] marker in the Link column. This marker is required for the channel to be included in the output.
Example: Adding an ATSC channel to lists/usa.md
<h2>ATSC</h2>
| # | Channel | Link | Logo | EPG id |
|---|------------------|------------------------------------|--------------------------------------|--------|
| 1 | Example TV Ⓨ | [>](https://example.com/stream.m3u8) | <img height="20" src="https://i.imgur.com/xyz.png"/> | ExampleTV.us |
Example: Adding a Pluto TV channel
<h2>Pluto</h2>
| # | Channel | Link | Logo | EPG id |
|---|------------------|----------------------------------------------------------------------|--------------------------------------|--------|
| 1 | Pluto Sports | [>](https://service-stitcher.pluto.tv/v1/stitch/embed/hls/channel/abcd1234/master.m3u8) | <img height="20" src="https://i.imgur.com/abcd.png"/> | PlutoSports.us |
Understanding the Playlist Generation Logic
The make_playlist.py script handles the conversion from Markdown tables to M3U format. Located in the repository root, it performs the following operations:
- Directory Scanning: Iterates through
lists/for all*.mdfiles usingfor filename in sorted(os.listdir(lists_dir)):. - Group Extraction: Identifies the country group by detecting the first
<h1>tag in the file. - Row Filtering: Skips any line that does not contain
[>], effectively ignoring header rows, empty lines, and section headings. - Channel Construction: For valid rows, it instantiates a
Channelobject:channel = Channel(group, line, country_code). - M3U Output: Converts the channel to M3U format via
channel.to_m3u_line()and writes to the master playlist and per-country files inplaylists/.
Because the script uses if "[>]" not in line: continue to filter rows, the <h2> source type headings are never processed as data—they exist solely to help contributors maintain logical groupings within the Markdown source.
Extending Source Types Beyond ATSC, DVB-S, and Pluto
The architecture supports arbitrary source type classifications. If you need to add a new category—such as "Satellite-IP" or "Local-FM"—simply insert a new <h2> heading with your desired label:
<h2>Satellite-IP</h2>
The generator will automatically include any table rows with [>] found beneath this heading. This extensibility ensures the repository can adapt to emerging broadcast technologies without requiring modifications to make_playlist.py.
Summary
- File Location: Channel data resides in
lists/*.mdas Markdown tables. - Source Separation: Use
<h2>HTML headings (e.g.,<h2>ATSC</h2>) to visually separate source types. - Inclusion Marker: Every stream row must contain
[>]in the Link column to be processed. - Generator Behavior: The
make_playlist.pyscript ignores headings and filters exclusively for the[>]marker, writing valid entries toplaylists/. - Flexibility: New source types can be added by creating new
<h2>sections without changing the build logic.
Frequently Asked Questions
What happens if I add a custom source type heading?
The generator will treat it like any other section. Since make_playlist.py only checks for the [>] marker and ignores HTML tags, channels placed under a custom <h2> heading (e.g., <h2>CustomSource</h2>) will be included in the playlist automatically. The heading serves purely as an organizational aid for editors.
Why does the script require the [>] marker in table rows?
The [>] marker acts as a validation filter. According to the logic in make_playlist.py, the line if "[>]" not in line: continue ensures that only intentional stream entries are processed, skipping header rows, placeholder text, or incomplete entries. This prevents malformed URLs from entering the generated M3U files.
Can I move channels between source type sections without breaking the build?
Yes. Since the generator does not parse <h2> headings when assigning groups, moving a channel row from <h2>ATSC</h2> to <h2>Pluto</h2> only affects the visual organization of the Markdown file. The channel will still be written to the same country playlist (e.g., playlist_usa.m3u8) as long as the row retains the [>] marker and remains within the same country file.
How does the generator handle the country group name?
The script extracts the country name from the first <h1> tag encountered in the file (e.g., <h1>USA</h1>). This value becomes the group parameter passed to the Channel class constructor. All valid channels within that file inherit this group identifier, ensuring proper categorization in the output M3U regardless of the <h2> source type headings used within the file.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →