How to Edit IPTV Playlists Programmatically Using iptv-org/iptv

You can edit IPTV playlists programmatically by leveraging the TypeScript classes in the iptv-org/iptv repository to parse M3U files, update stream metadata using the reference database, and serialize the results back to disk.

The iptv-org/iptv repository provides a robust toolkit for managing Internet Protocol Television (IPTV) streams. If you need to edit IPTV playlists programmatically—whether to fix missing channel identifiers, batch-update metadata, or automate playlist maintenance—the repository's internal scripts expose a clean API for parsing, manipulating, and saving M3U files without manual intervention.

Core Workflow for Programmatic Playlist Editing

The repository implements a seven-step pipeline in scripts/commands/playlist/edit.ts that you can replicate or extend in your own automation.

1. Load Reference Data

Before modifying any playlist, the system loads the central JSON database that maps channel IDs to metadata, categories, and feeds.

  • Function: loadData() in scripts/api.ts
  • Output: Populates lookup collections including categoriesKeyById and feedsGroupedByChannel
  • Source: JSON files stored in temp/data

2. Parse the M3U File

The PlaylistParser class converts raw M3U text into typed Stream objects that you can manipulate programmatically.

  • Class: PlaylistParser in scripts/core/playlistParser.ts
  • Method: parseFile(filepath)
  • Process: Uses iptv-playlist-parser to extract entries, then instantiates Stream objects via Stream.fromPlaylistItem

3. Identify Streams Missing Metadata

The workflow filters for streams that lack a tvg-id, which is the unique identifier required for channel matching.

4. Search for Matching Channels

For each unidentified stream, the system queries the loaded database using fuzzy text matching on the stream title.

  • Function: searchChannels(query) in scripts/api.ts
  • Engine: Uses the same sdk.SearchEngine that powers the CLI's interactive selector

5. Update Stream Objects

Once a match is selected, the Stream instance is mutated in-place to add the tvg-id and optional feed identifier.

  • Format: channelId@feedId (concatenated string)
  • Class: Stream in scripts/models/stream.ts
  • Persistence: The toString() method handles M3U serialization when writing back

6. Serialize and Save

The modified collection is converted back to M3U format and written to disk using the storage abstraction.

Code Examples

Running the Built-in CLI Command

You can invoke the repository's edit command from your own Node.js scripts to leverage the interactive workflow:

import { execSync } from 'node:child_process';
import path from 'node:path';

const playlistPath = path.resolve('streams/us.m3u');

// Launches the interactive selector defined in edit.ts
execSync(`npm run playlist:edit -- ${playlistPath}`, { stdio: 'inherit' });

Custom Script for Batch Updates

For fully automated editing without prompts, import the underlying classes directly:

import { Storage } from '@freearhey/storage-js';
import { PlaylistParser } from './scripts/core/playlistParser';
import { loadData, searchChannels } from './scripts/api';
import { Stream } from './scripts/models/stream';

// 1. Load reference data
await loadData();

// 2. Parse the target playlist
const storage = new Storage();
const parser = new PlaylistParser({ storage });
const streams = await parser.parseFile('streams/us.m3u');

// 3. Fix missing tvg-ids automatically
for (const stream of streams.all()) {
  if (stream.tvgId) continue;

  const matches = searchChannels(stream.title);
  if (matches.count() === 0) continue;

  const chosen = matches.first();
  const feedId = chosen.feeds?.[0]?.id ?? '';
  stream.tvgId = feedId ? `${chosen.id}@${feedId}` : chosen.id;
}

// 4. Write the updated playlist back
const { Playlist } = await import('./scripts/models/playlist');
const updatedM3U = new Playlist(streams).toString();
storage.saveSync('streams/us.m3u', updatedM3U);

Key Source Files and Classes

File Role Key Exports
scripts/commands/playlist/edit.ts CLI entry point that orchestrates the full editing workflow Interactive prompt logic, file I/O
scripts/api.ts Data layer that loads the JSON database and provides search functionality loadData(), searchChannels(), data collections
scripts/core/playlistParser.ts M3U parsing engine PlaylistParser class, parseFile() method
scripts/models/stream.ts Domain model for individual streams Stream class, tvgId property, toString() serialization
scripts/models/playlist.ts Container for multiple streams Playlist class, toString() for M3U generation

Summary

  • The iptv-org/iptv repository provides a complete TypeScript toolkit to edit IPTV playlists programmatically without manual M3U editing.
  • The workflow involves loading reference data via loadData(), parsing M3U files with PlaylistParser, manipulating Stream objects to update tvg-id values, and serializing back through the Playlist class.
  • You can either run the built-in CLI command (npm run playlist:edit) for interactive editing or import the underlying classes (scripts/api.ts, scripts/core/playlistParser.ts, scripts/models/stream.ts) to build fully automated pipelines.

Frequently Asked Questions

How do I parse an M3U playlist file programmatically in Node.js?

Use the PlaylistParser class from scripts/core/playlistParser.ts. Instantiate it with a Storage object, then call parseFile(filepath) to convert the M3U text into a collection of typed Stream objects that you can manipulate directly.

What is the tvg-id field and why is it important for IPTV playlists?

The tvg-id is a unique identifier that maps a stream to a specific channel in the reference database. According to the iptv-org/iptv source code, streams lacking this ID cannot be matched to EPG data or channel metadata, which is why the edit.ts command specifically targets missing tvg-id values for correction.

Can I automate playlist editing without interactive prompts?

Yes. Instead of running the CLI command, import the underlying modules from scripts/api.ts and scripts/models/stream.ts directly. Load the reference data with await loadData(), iterate over the parsed streams, update the tvgId property programmatically, and serialize the results using the Playlist class's toString() method.

Where does the repository store its channel reference data?

The reference data is loaded from JSON files located in the temp/data directory (populated by the build process). The loadData() function in scripts/api.ts reads these files to create lookup collections like categoriesKeyById and feedsGroupedByChannel, which power the search functionality used during playlist editing.

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 →