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

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:

The Command Execution Flow

Every playlist command follows a consistent five-step pipeline:

  1. Bootstrap – Initialize Logger and import constants from 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:

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:

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():

// 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:

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 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:

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 and register it in 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:

{
  "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:

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 for paths, scripts/core/playlistParser.ts for parsing, and 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 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, 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 or format.ts. After creating your TypeScript file, register it in 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.

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →