# How the make_playlist.py Script Generates M3U8 Files for IPTV

> Learn how make_playlist.py generates M3U8 files for IPTV. This Python script transforms Markdown channel lists into compliant playlists by parsing entries and creating EXTINF metadata.

- Repository: [Free TV/IPTV](https://github.com/Free-TV/IPTV)
- Tags: how-to-guide
- Published: 2026-06-26

---

**The [`make_playlist.py`](https://github.com/Free-TV/IPTV/blob/main/make_playlist.py) script converts Markdown channel listings from the `lists/` directory into standards-compliant M3U8 playlists by parsing pipe-delimited entries and constructing EXTINF metadata lines for each channel.**

The Free-TV/IPTV repository maintains curated television channel data as human-readable Markdown files. To transform these text-based listings into machine-readable playlists that modern IPTV clients can consume, the repository relies on [`make_playlist.py`](https://github.com/Free-TV/IPTV/blob/main/make_playlist.py), a Python utility that orchestrates the generation of M3U8 files. This script bridges the gap between editable markdown syntax and the structured EXTINF format required by streaming applications.

## Mapping Countries to ISO Codes

Before processing channels, the script establishes a geographic reference system. The `COUNTRY_CODES` dictionary (defined in lines 6-91 of [`make_playlist.py`](https://github.com/Free-TV/IPTV/blob/main/make_playlist.py)) maps folder names like `usa` or `france` to two-letter **ISO country codes**. These codes populate the `tvg-country` attribute in each EXTINF line, enabling IPTV clients to filter channels by region.

## Parsing Markdown with the Channel Class

At the heart of the conversion logic sits the `Channel` class (lines 94-114). This class transforms a raw markdown line into a structured Python object capable of emitting M3U8-compliant output.

The constructor accepts three parameters: the current group title, the raw markdown line, and an optional country code. It splits the line on the pipe (`|`) delimiter to extract:
- The channel number
- The channel name  
- The stream URL (wrapped in parentheses)
- The logo URL (extracted from an `<img src="...">` tag)
- An optional EPG identifier

If an EPG ID is present, the script stores it for later inclusion in the `tvg-id` attribute.

## Building EXTINF Lines

Each `Channel` instance generates its M3U8 representation through the `to_m3u_line()` method (lines 114-120). This method constructs a string following the exact M3U8 specification:

```

#EXTINF:-1 tvg-name="..." tvg-logo="..." tvg-id="..." tvg-chno="..." tvg-country="..." group-title="...",ChannelName
URL

```

The method dynamically includes optional attributes only when data is present, ensuring clean output without empty parameters.

## Orchestrating Playlist Creation

The `main()` function (lines 123-161) serves as the execution coordinator, handling file system operations and iteration logic.

### Path and Directory Setup

The script first determines repository paths (lines 123-130):
- `base_dir`: The repository root
- `lists/`: The source directory containing markdown files
- `playlists/`: The output directory (created if missing)

### EPG Header Construction

The script reads [`epglist.txt`](https://github.com/Free-TV/IPTV/blob/main/epglist.txt) to build the master playlist header (lines 131-135). This produces the line:

```

#EXTM3U x-tvg-url="url1, url2, ..."

```

This header precedes every generated playlist, informing clients where to fetch electronic program guide data.

### Processing Country Files

For each `*.md` file in `lists/` (excluding [`README.md`](https://github.com/Free-TV/IPTV/blob/main/README.md)), the script:
1. Derives a country key from the filename (e.g., [`usa.md`](https://github.com/Free-TV/IPTV/blob/main/usa.md) → `usa`)
2. Looks up the corresponding ISO code via `COUNTRY_CODES`
3. Opens a matching output file at `playlists/playlist_<country>.m3u8` (lines 136-145)

### Converting Channel Entries

Within each markdown file, the script processes lines sequentially (lines 150-158):
- **Group detection**: Lines containing `<h1>` tags establish new `group-title` values for subsequent channels
- **Channel markers**: Only lines containing `"[>]"` are treated as channel entries
- **Dual output**: Each channel appends to both the per-country playlist and the master `playlist.m3u8`

## Running the Generator

Execute the script from the repository root:

```bash
python3 make_playlist.py

```

The script produces two categories of output:
- `playlist.m3u8`: The global playlist aggregating every channel
- `playlists/playlist_<country>.m3u8`: Individual files for each country code (e.g., `playlist_usa.m3u8`, `playlist_uk.m3u8`)

A generated EXTINF entry appears as:

```text
#EXTINF:-1 tvg-name="BBC One" tvg-logo="https://example.com/logo.png" tvg-id="bbc_one" tvg-chno="101" tvg-country="GB" group-title="United Kingdom",BBC One
http://stream.example.com/bbc_one.m3u8

```

## Summary

- The `COUNTRY_CODES` dictionary (lines 6-91) maps regions to ISO codes for the `tvg-country` attribute
- The `Channel` class (lines 94-114) parses pipe-delimited markdown and extracts logos from HTML tags
- The `to_m3u_line()` method (lines 114-120) generates compliant EXTINF metadata strings
- The `main()` function (lines 123-161) coordinates file I/O, EPG header injection, and dual playlist output
- Input markdown files reside in `lists/`; output M3U8 files write to `playlists/` and the repository root

## Frequently Asked Questions

### What is the M3U8 format used for in IPTV?

M3U8 is a UTF-8 encoded playlist format that streaming applications use to organize media URLs. IPTV clients read these files to populate channel lists, display electronic program guide (EPG) data, and handle stream switching. The Free-TV/IPTV repository generates M3U8 files specifically to ensure compatibility with popular players like VLC, Kodi, and dedicated IPTV applications.

### How does the script handle EPG data?

The script reads [`epglist.txt`](https://github.com/Free-TV/IPTV/blob/main/epglist.txt) to construct the `x-tvg-url` header attribute (lines 131-135), which points clients to XMLTV program guide sources. Individual channels may specify `tvg-id` attributes in their markdown definitions, allowing the generated playlists to link specific streams to their corresponding EPG entries for program scheduling and metadata.

### What determines the group-title attribute in the generated playlists?

The `group-title` attribute derives from `<h1>` headings within the source markdown files. When [`make_playlist.py`](https://github.com/Free-TV/IPTV/blob/main/make_playlist.py) encounters an HTML header tag while iterating through a country file (lines 150-153), it updates the current group context. All subsequent channels inherit this group title until the script encounters a new `<h1>` tag, creating logical channel groupings like "News" or "Sports" in the final M3U8 output.

### Can I run make_playlist.py without the full repository?

No, the script depends on the repository structure present in Free-TV/IPTV. It specifically requires the `lists/` directory containing markdown channel definitions and the [`epglist.txt`](https://github.com/Free-TV/IPTV/blob/main/epglist.txt) file for EPG URL generation. Attempting to run the script outside this context will fail when the code attempts to locate these resources (lines 123-130).