# Channel Class Structure in Free-TV/IPTV: How It Processes Markdown Table Data

> Understand the Channel class structure in Free-TV/IPTV. Learn how it processes markdown table data to create M3U playlist format for your channels. Explore the make_playlist.py repository.

- Repository: [Free TV/IPTV](https://github.com/Free-TV/IPTV)
- Tags: internals
- Published: 2026-06-17

---

**The `Channel` class in [`make_playlist.py`](https://github.com/Free-TV/IPTV/blob/main/make_playlist.py) parses pipe-delimited markdown table rows to extract channel metadata and serializes it into M3U playlist format using the `to_m3u_line()` method.**

The Free-TV/IPTV repository converts markdown tables containing TV channel listings into standard M3U playlists using a specialized `Channel` class. This class serves as the data transformation layer, handling the extraction of URLs, logos, and electronic program guide (EPG) identifiers from raw markdown syntax according to the source implementation.

## Channel Class Structure and Initialization

The `Channel` class is defined in **[`make_playlist.py`](https://github.com/Free-TV/IPTV/blob/main/make_playlist.py)** between lines 94 and 120. It acts as a data container and formatter for individual TV channels extracted from markdown tables.

The constructor signature is:

```python
def __init__(self, group, md_line, country_code="")

```

**Parameters:**
- **`group`**: A string representing the channel category (e.g., "United Kingdom")
- **`md_line`**: A raw string from the markdown table containing pipe-separated values
- **`country_code`**: An optional ISO country code string (defaults to empty)

During initialization, the class performs the following operations:

1. **Strips whitespace** from the input line and splits it on the pipe character (`|`)
2. **Extracts positional fields** from the resulting array:
   - Position 1: Channel number
   - Position 2: Channel name
   - Position 3: Markdown link containing the stream URL
   - Position 4: HTML image tag containing the logo URL
   - Position 5: Optional EPG identifier
3. **Cleans the URL** by extracting text from within the parentheses of the `[>](url)` markdown syntax
4. **Extracts the logo URL** by parsing the `src="..."` attribute from the HTML image tag
5. **Stores the channel number** as `chno`, but only if it is not "0"
6. **Preserves the country code** for later use in M3U generation

The class stores these values as instance attributes: `group`, `country_code`, `number`, `name`, `url`, `logo`, `chno`, and `epg`.

## How the Channel Class Processes Markdown Table Data

The repository stores channel listings in markdown files using pipe-delimited tables. A typical row looks like this:

```markdown
| 1 | BBC One | [>](http://example.com/playlist.m3u8) | <img src="https://example.com/logo.png"> | epg_id |

```

When the script processes these files, the `Channel` class handles the parsing through direct string manipulation rather than external libraries. The parsing logic in `__init__` uses simple `split`, `find`, and slicing operations to maintain a lightweight dependency footprint.

**Field extraction details:**
- **URL extraction**: Locates the text between `(` and `)` in the markdown link syntax
- **Logo extraction**: Parses the HTML `<img>` tag to retrieve the value within `src="..."`
- **Empty handling**: Missing or empty optional fields are stored as empty strings or filtered out during M3U generation

The main processing loop in `main()` (around line 55 of [`make_playlist.py`](https://github.com/Free-TV/IPTV/blob/main/make_playlist.py)) identifies valid channel rows by checking for the presence of the `[>]` marker before instantiating the `Channel` class.

## Converting Channels to M3U Format with to_m3u_line()

The `to_m3u_line()` method serializes the parsed channel data into a valid M3U playlist entry. This method constructs the `#EXTINF` metadata line followed by the stream URL.

The method builds the output string by conditionally including attributes:

- **`tvg-name`**: Always includes the channel name
- **`tvg-logo`**: Always includes the logo URL
- **`tvg-id`**: Includes the EPG identifier only if `epg` is present
- **`tvg-chno`**: Includes the channel number only if `chno` is not empty (ignores "0" values)
- **`tvg-country`**: Includes the country code only if provided during initialization
- **`group-title`**: Always includes the group name

The output format follows this structure:

```python
#EXTINF:-1 tvg-name="{name}" tvg-logo="{logo}" [tvg-id="{epg}"] [tvg-chno="{chno}"] [tvg-country="{country}"] group-title="{group}",{name}
{url}

```

## Integration with the Playlist Generation Pipeline

The `Channel` class integrates into the broader pipeline defined in `main()`. The workflow proceeds as follows:

1. **Detection**: The script iterates through markdown files in the `lists/` directory and identifies lines containing `[>]` as channel data rows
2. **Instantiation**: For each valid line, it creates a `Channel` instance: `Channel(group, line, country_code)`
3. **Serialization**: Calls `channel.to_m3u_line()` to generate the M3U entry
4. **Output**: Appends the generated line to both the master `playlist.m3u8` and country-specific playlists in `playlists/playlist_*.m3u8`

This design maintains **single-responsibility principles**: the `Channel` class handles only data extraction and formatting, while the surrounding script manages file I/O and iteration logic.

## Summary

- The `Channel` class in **[`make_playlist.py`](https://github.com/Free-TV/IPTV/blob/main/make_playlist.py)** (lines 94-120) transforms markdown table rows into structured channel data
- It extracts **number**, **name**, **URL**, **logo**, and **EPG** fields by splitting pipe-delimited strings and parsing markdown/HTML syntax
- The **`to_m3u_line()`** method generates standard M3U playlist entries with conditional attributes for channel numbers, country codes, and EPG identifiers
- The class ignores "0" values for channel numbers and omits optional attributes when empty, keeping output clean
- Integration occurs in **`main()`** around line 55, where lines containing `[>]` trigger `Channel` instantiation and M3U generation

## Frequently Asked Questions

### What markdown table format does the Channel class expect?

The `Channel` class expects pipe-delimited rows where the first cell is the channel number, the second is the name, the third contains a markdown link `[>](url)` with the stream URL, the fourth contains an HTML image tag `<img src="...">` with the logo, and the fifth is an optional EPG identifier. The class splits on the `|` character and processes the resulting array indices 1 through 5.

### How does the Channel class handle missing or optional fields?

The class uses defensive parsing: if the channel number is "0" or empty, it stores an empty `chno` attribute and omits `tvg-chno` from the M3U output. Similarly, if the EPG field is empty or the country code is not provided, those attributes are excluded from the final `#EXTINF` line. This ensures the generated playlists only contain relevant metadata.

### What is the difference between the number and chno attributes in the Channel class?

The `number` attribute stores the raw value from the markdown table (including "0"), while `chno` stores the validated channel number used for M3U output. If the raw number equals "0", `chno` remains empty, preventing invalid channel numbers from appearing in the playlist metadata.

### How does the Channel class extract URLs from markdown link syntax?

The class uses string manipulation to locate the URL within the markdown link format `[>](http://example.com/stream.m3u8)`. It finds the positions of the opening `(` and closing `)` parentheses and extracts the substring between them. Similarly, for logos, it parses the `src="..."` attribute from the HTML image tag using string slicing operations.