What Determines tvg-chno Channel Numbering in Free-TV/IPTV M3U8 Output
The tvg-chno attribute is extracted directly from the second pipe-delimited column of the source Markdown files and is omitted when the value is empty or "0".
The Free-TV/IPTV repository generates IPTV playlists from Markdown source files. The tvg-chno attribute that controls channel numbering in the final M3U8 output is determined by a specific parsing logic implemented in make_playlist.py.
How the Channel Number Is Parsed from Markdown
Column Structure in Source Files
Each channel entry in the repository's Markdown files (located in lists/*.md) follows a pipe-delimited format. Inside Channel.__init__ in make_playlist.py, the constructor splits each line on the pipe (|) character:
parts = md_line.split("|")
The mapping is explicit:
parts[1]→ number (line 100)parts[2]→ name (line 101)parts[3]→ URL (lines 102-104)parts[4]→ logo (lines 105-106)
The Channel Constructor Logic
The constructor stores the parsed value in self.number, then applies a conditional check to determine if it should become a channel number tag:
self.chno = self.number if self.number and self.number != "0" else None # line 107
If the field is empty or equal to the string "0", self.chno is set to None and no tvg-chno attribute is emitted in the final output.
How tvg-chno Is Generated in the M3U8 Output
The Conditional Output Logic
In Channel.to_m3u_line (line 16), the script checks the self.chno attribute before constructing the M3U8 line:
chno = f' tvg-chno="{self.chno}"' if self.chno else ""
This string is then inserted into the #EXTINF line between the logo tag and the group title. The resulting attribute appears only when the source Markdown contains a valid, non-zero number in the second column.
Practical Examples
Example 1: Valid Channel Number
Source entry in lists/playlist_italy.md:
|101|Rai 1|http://example.com/rai1.m3u8|<img src="http://logo.com/rai1.png"/>
Generated M3U8 output:
#EXTINF:-1 tvg-name="Rai 1" tvg-logo="http://logo.com/rai1.png" tvg-chno="101" group-title="Italy",Rai 1
http://example.com/rai1.m3u8
Example 2: Empty Channel Number
Source entry with empty second column:
||Sky Sports|http://example.com/sky.m3u8|<img src="http://logo.com/sky.png"/>
Generated output (note the missing tvg-chno):
#EXTINF:-1 tvg-name="Sky Sports" tvg-logo="http://logo.com/sky.png" group-title="Italy",Sky Sports
http://example.com/sky.m3u8
Example 3: Zero as Channel Number
Source entry with "0" in the number column:
|0|TV5MONDE|http://example.com/tv5.m3u8|<img src="http://logo.com/tv5.png"/>
Generated output (treated as "no number"):
#EXTINF:-1 tvg-name="TV5MONDE" tvg-logo="http://logo.com/tv5.png" group-title="France",TV5MONDE
http://example.com/tv5.m3u8
Summary
- The second pipe-delimited field in the Markdown source files drives the
tvg-chnoattribute. - Empty strings or the value "0" result in the omission of the
tvg-chnotag entirely. - The logic resides in
make_playlist.py, specifically in theChannelclass constructor andto_m3u_linemethod. - Editing the channel number in
lists/*.mdfiles directly controls the numbering in the generatedplaylists/*.m3u8files.
Frequently Asked Questions
What happens if the channel number column is empty?
If the second column is empty, the self.chno attribute is set to None in the Channel.__init__ method, and the tvg-chno attribute is completely omitted from the M3U8 output line.
Why is "0" treated differently from other numbers?
The string "0" is explicitly filtered out in line 107 of make_playlist.py (self.number != "0"), treating it as equivalent to an empty value. This allows maintainers to use "0" as a placeholder to intentionally suppress channel numbering for specific entries.
Which file contains the logic for generating tvg-chno?
The core logic resides in make_playlist.py in the root of the repository. The Channel class handles parsing in __init__ (lines 100-107) and M3U8 generation in to_m3u_line (line 16).
Can I manually edit channel numbers?
Yes. Since the tvg-chno value is taken directly from the second column of the Markdown files in lists/, you can modify these files to change channel numbering. The next run of the playlist generator will apply these changes to the output files.
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 →