# How to Build Custom IPTV Playlist Commands in the iptv-org/iptv Repository

> Learn to build custom IPTV playlist commands using the iptv-org/iptv repository's TypeScript framework. Master logger setup, data loading, stream parsing, and playlist export.

- Repository: [iptv-org/iptv](https://github.com/iptv-org/iptv)
- Tags: how-to-guide
- Published: 2026-02-25

---

**The iptv-org/iptv repository provides a TypeScript command framework under `scripts/commands/playlist/` that lets you build custom IPTV playlist commands by bootstrapping a `Logger`, loading API data with `loadData()`, parsing streams via `PlaylistParser`, transforming collections with `@freearhey/core` utilities, and exporting results through the `Playlist` model.**

The iptv-org/iptv project maintains one of the largest collections of publicly available IPTV streams, organized through a modular command-line architecture. When you need to build custom IPTV playlist commands—whether to filter by country, resolution, or specific channel metadata—you can extend this existing framework without modifying the core parsing logic.

## Understanding the Playlist Command Architecture

### Core Components and File Structure

The command framework resides in `scripts/commands/playlist/` with shared utilities distributed throughout the `scripts/` directory. The essential modules include:

- **[`scripts/constants.ts`](https://github.com/iptv-org/iptv/blob/main/scripts/constants.ts)** – Centralizes paths such as `STREAMS_DIR` and `PUBLIC_DIR` used across all commands
- **[`scripts/api/load.ts`](https://github.com/iptv-org/iptv/blob/main/scripts/api/load.ts)** – Exports `loadData()` for fetching channel metadata from the iptv-org API package
- **[`scripts/core/playlistParser.ts`](https://github.com/iptv-org/iptv/blob/main/scripts/core/playlistParser.ts)** – Contains the `PlaylistParser` class that converts raw M3U files into `Stream` objects
- **[`scripts/models/Stream.ts`](https://github.com/iptv-org/iptv/blob/main/scripts/models/Stream.ts)** – Data model representing individual streams with methods like `getChannel()` and `getVerticalResolution()`
- **[`scripts/models/Playlist.ts`](https://github.com/iptv-org/iptv/blob/main/scripts/models/Playlist.ts)** – Handles serialization of `Collection<Stream>` back into valid M3U format

### The Command Execution Flow

Every playlist command follows a consistent five-step pipeline:

1. **Bootstrap** – Initialize `Logger` and import constants from [`scripts/constants.ts`](https://github.com/iptv-org/iptv/blob/main/scripts/constants.ts)
2. **Load API data** – Call `loadData()` to pull fresh channel, country, and language metadata
3. **Read raw streams** – Use `Storage` to list M3U files from `STREAMS_DIR`, then parse them with `PlaylistParser` into a `Collection<Stream>`
4. **Process the collection** – Apply transformations using `@freearhey/core` utilities (filter, sort, deduplicate)
5. **Generate output** – Convert the final collection to M3U string via `Playlist` model and save to filesystem

## How to Build Custom IPTV Playlist Commands

### Step 1: Bootstrap the Environment

Start by importing the core dependencies and initializing the logger:

```typescript
import { Logger, Collection } from '@freearhey/core';
import { Storage } from '@freearhey/storage-js';
import { PlaylistParser } from '../../core';
import { loadData } from '../../api';
import { Stream } from '../../models';
import { STREAMS_DIR, PUBLIC_DIR } from '../../constants';

async function main() {
  const logger = new Logger();
  await loadData(); // Load channel metadata from iptv-org/api
  // ... rest of command
}

```

### Step 2: Load and Parse Stream Data

Instantiate `Storage` pointing to `STREAMS_DIR` and parse all M3U files:

```typescript
const storage = new Storage(STREAMS_DIR);
const parser = new PlaylistParser({ storage });
const files = await storage.list('**/*.m3u');
let streams = await parser.parse(files);

```

The `parser.parse()` method returns a `Collection<Stream>` where each `Stream` object contains methods like `getChannel()`, `getVerticalResolution()`, and `title` properties.

### Step 3: Apply Custom Transformations

This is where you implement your custom logic. The `Collection` class from `@freearhey/core` provides chainable methods like `filter()`, `sortBy()`, and `uniq()`:

```typescript
// Example: Filter for US channels only
const usCountryCode = 'us';
streams = streams.filter((s: Stream) => {
  const channel = s.getChannel();
  return channel && channel.country?.iso_3166_1?.toLowerCase() === usCountryCode;
});

// Example: Sort by title ascending, then resolution descending
streams = streams.sortBy(
  [(s: Stream) => s.title, (s: Stream) => s.getVerticalResolution()],
  ['asc', 'desc']
);

```

### Step 4: Generate and Save the Output

Convert the processed collection back to M3U format using the `Playlist` model:

```typescript
const { Playlist } = require('../../models');
const playlist = new Playlist(streams, { public: true });
const m3u = playlist.toString();

const outPath = `${PUBLIC_DIR}/custom/output.m3u`;
await storage.save(outPath, m3u);
logger.info(`Custom playlist written to ${outPath}`);

```

## Practical Examples of Custom Commands

### Filter by Country Code

To build a command that generates country-specific playlists (e.g., only US streams), implement the filtering logic shown in Step 3 using `channel.country.iso_3166_1`. Save the file as [`scripts/commands/playlist/us-only.ts`](https://github.com/iptv-org/iptv/blob/main/scripts/commands/playlist/us-only.ts) and add the npm script `"playlist:us-only": "tsx scripts/commands/playlist/us-only.ts"`.

### Filter by Resolution (HD Only)

For a high-definition-only playlist, filter streams by vertical resolution:

```typescript
const hdStreams = streams.filter((s: Stream) => s.getVerticalResolution() >= 720);

```

This checks the `Stream.getVerticalResolution()` method which parses the stream's metadata. Save this as [`scripts/commands/playlist/hd-only.ts`](https://github.com/iptv-org/iptv/blob/main/scripts/commands/playlist/hd-only.ts) and register it in [`package.json`](https://github.com/iptv-org/iptv/blob/main/package.json) as `playlist:hd-only`.

## Integrating Custom Commands into npm Scripts

To make your custom command executable via npm, add it to the `scripts` section of [`package.json`](https://github.com/iptv-org/iptv/blob/main/package.json):

```json
{
  "scripts": {
    "playlist:generate": "tsx scripts/commands/playlist/generate.ts",
    "playlist:format": "tsx scripts/commands/playlist/format.ts",
    "playlist:custom-us": "tsx scripts/commands/playlist/custom.ts",
    "playlist:hd-only": "tsx scripts/commands/playlist/hd-only.ts"
  }
}

```

Run your command with:

```bash
npm run playlist:custom-us

```

## Summary

- The **iptv-org/iptv** repository provides a TypeScript command framework under `scripts/commands/playlist/` for processing M3U playlists.
- To **build custom IPTV playlist commands**, bootstrap with `Logger` and `loadData()`, parse streams using `PlaylistParser`, apply transformations via `Collection` utilities, and export with the `Playlist` model.
- Key files include [`scripts/constants.ts`](https://github.com/iptv-org/iptv/blob/main/scripts/constants.ts) for paths, [`scripts/core/playlistParser.ts`](https://github.com/iptv-org/iptv/blob/main/scripts/core/playlistParser.ts) for parsing, and [`scripts/models/Stream.ts`](https://github.com/iptv-org/iptv/blob/main/scripts/models/Stream.ts) for data access.
- Custom logic typically involves filtering `Collection<Stream>` by properties like `channel.country.iso_3166_1` or `getVerticalResolution()`.
- Register custom commands in [`package.json`](https://github.com/iptv-org/iptv/blob/main/package.json) using `tsx` to execute TypeScript directly.

## Frequently Asked Questions

### How do I filter streams by country when building custom IPTV playlist commands?

To filter by country, access the `country` property on the channel object returned by `stream.getChannel()`. Compare `channel.country.iso_3166_1` against your target country code (e.g., `'us'`). Use the `Collection.filter()` method from `@freearhey/core` to apply this predicate across all loaded streams.

### What is the purpose of the `loadData()` function in custom playlist commands?

The `loadData()` function, located in [`scripts/api/load.ts`](https://github.com/iptv-org/iptv/blob/main/scripts/api/load.ts), initializes the local cache of channel metadata from the iptv-org API package. It populates data models for countries, languages, regions, and channels, enabling methods like `stream.getChannel()` and `stream.getVerticalResolution()` to return accurate metadata during stream processing.

### Can I sort streams by resolution when generating custom playlists?

Yes. The `Stream` model provides `getVerticalResolution()`, which returns the pixel height (e.g., 720, 1080). Use `Collection.sortBy()` from `@freearhey/core`, passing an array of iterate functions such as `[(s: Stream) => s.title, (s: Stream) => s.getVerticalResolution()]` and sort orders like `['asc', 'desc']` to organize streams by title and quality.

### Where should I save my custom playlist command files?

Place new command files in the `scripts/commands/playlist/` directory, following the naming convention of existing commands like [`generate.ts`](https://github.com/iptv-org/iptv/blob/main/generate.ts) or [`format.ts`](https://github.com/iptv-org/iptv/blob/main/format.ts). After creating your TypeScript file, register it in [`package.json`](https://github.com/iptv-org/iptv/blob/main/package.json) under the `scripts` section using the `tsx` runner (e.g., `"playlist:custom": "tsx scripts/commands/playlist/custom.ts"`) to enable execution via `npm run`.