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:
scripts/constants.ts– Centralizes paths such asSTREAMS_DIRandPUBLIC_DIRused across all commandsscripts/api/load.ts– ExportsloadData()for fetching channel metadata from the iptv-org API packagescripts/core/playlistParser.ts– Contains thePlaylistParserclass that converts raw M3U files intoStreamobjectsscripts/models/Stream.ts– Data model representing individual streams with methods likegetChannel()andgetVerticalResolution()scripts/models/Playlist.ts– Handles serialization ofCollection<Stream>back into valid M3U format
The Command Execution Flow
Every playlist command follows a consistent five-step pipeline:
- Bootstrap – Initialize
Loggerand import constants fromscripts/constants.ts - Load API data – Call
loadData()to pull fresh channel, country, and language metadata - Read raw streams – Use
Storageto list M3U files fromSTREAMS_DIR, then parse them withPlaylistParserinto aCollection<Stream> - Process the collection – Apply transformations using
@freearhey/coreutilities (filter, sort, deduplicate) - Generate output – Convert the final collection to M3U string via
Playlistmodel 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
LoggerandloadData(), parse streams usingPlaylistParser, apply transformations viaCollectionutilities, and export with thePlaylistmodel. - Key files include
scripts/constants.tsfor paths,scripts/core/playlistParser.tsfor parsing, andscripts/models/Stream.tsfor data access. - Custom logic typically involves filtering
Collection<Stream>by properties likechannel.country.iso_3166_1orgetVerticalResolution(). - Register custom commands in
package.jsonusingtsxto 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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →