How to Test IPTV Stream URLs Before Adding Them to the Playlist
The Free-TV/IPTV repository automatically validates every stream URL through a CI pipeline that runs m3u-linter for syntax checking and iptv-checker with FFmpeg to verify stream availability, latency, and geo-blocking before any pull request can be merged.
Testing IPTV stream URLs before adding them to a playlist prevents broken links and geo-restricted content from reaching end users. The Free-TV/IPTV repository implements a robust validation workflow that contributors can replicate locally to ensure their submissions meet quality standards. This guide explains how the automated testing works and how to run the same checks on your local machine.
Automated CI Validation in Free-TV/IPTV
Every pull request that modifies a .md file in the lists/ directory triggers the Test IPTV file quality workflow defined in .github/workflows/test_playlist.yml. This CI pipeline performs two distinct validation layers before allowing a merge.
M3U Syntax Validation
The workflow uses the m3u-linter tool to parse the generated playlist.m3u8 file and enforce strict formatting rules. The linter checks for proper header syntax, attribute quoting, and playlist structure according to the project's M3u-linter.config.json configuration. If the generated playlist contains malformed entries, the CI job fails immediately.
Stream Availability Testing
The iptv-checker utility probes each URL using FFmpeg to verify actual stream accessibility. According to lines 47-51 in .github/workflows/test_playlist.yml, the checker runs with a concurrency of 100 workers and a 120-second timeout per stream:
# As implemented in the CI workflow
iptv-checker -o output -p 100 -t 120000 playlist.m3u8
The tool reports dead streams, measures latency, identifies GeoIP-blocking issues, and writes a detailed JSON summary to the output/ directory. Line 49 of the same workflow file ensures FFmpeg is installed as a prerequisite for the checker.
Local Testing Workflow for Contributors
You can replicate the exact CI validation locally before submitting a pull request. This ensures that changes to lists/*.md files will pass automated testing.
-
Clone the repository and generate the playlist:
git clone https://github.com/Free-TV/IPTV.git && cd IPTV python3 make_playlist.pyThis script processes the markdown tables in
lists/*.mdand buildsplaylist.m3u8, injecting country codes and filtering only entries marked with[>](as handled inmake_playlist.pylines 53-55). -
Validate M3U syntax:
npm install -g m3u-linter m3u-linter -c M3u-linter.config.json playlist.m3u8 -
Install FFmpeg and the stream checker:
sudo apt-get install -y ffmpeg # Required by iptv-checker npm install -g iptv-checker -
Test all stream URLs:
iptv-checker -o output -p 100 -t 120000 playlist.m3u8This probes every URL with 100 concurrent workers and a 120-second timeout per stream, matching the CI configuration.
-
Inspect the results:
cat output/report.json | jq '.'Look for entries with
"status":"dead"or"geoBlocked":trueto identify problematic URLs. -
Fix and iterate:
Update failing URLs in the appropriate
lists/*.mdfile, regenerate the playlist withpython3 make_playlist.py, and repeat steps 2-5 until the report shows only healthy streams.
Quick Ad-Hoc Testing for Single URLs
For rapid verification of a single stream without running the full suite, use FFprobe to check codec and stream metadata:
ffprobe -v error -show_entries stream=codec_name,width,height -of default=noprint_wrappers=1:nokey=1 "$URL"
If the command returns codec information and exits with status 0, the stream is reachable and playable. A non-zero exit code indicates network errors, 404 responses, or authentication failures.
Understanding the Test Results
The output/report.json file generated by iptv-checker contains detailed metadata for each tested URL. Healthy streams show "status":"online" with low latency values, while failed entries indicate specific failure modes:
- Dead streams: URLs that timeout or return connection errors
- Geo-blocked streams: URLs that reject connections based on source IP location (marked
"geoBlocked":true) - Slow streams: URLs exceeding the 120-second threshold
According to the contribution guidelines in README.md lines 174-176, any URL flagged as unreachable or geo-blocked must be resolved before the PR can be merged, maintaining the repository's policy of providing working, freely accessible content.
Summary
- Free-TV/IPTV automatically tests every URL via GitHub Actions in
.github/workflows/test_playlist.ymlusingm3u-linterandiptv-checker. - Run
python3 make_playlist.pylocally to generateplaylist.m3u8from thelists/*.mdsource files before testing. - Use
iptv-checker -o output -p 100 -t 120000 playlist.m3u8to replicate CI testing with 100 concurrent workers and 120-second timeouts. - Check
output/report.jsonfor"status":"dead"or"geoBlocked":true"entries to identify problematic streams. - Use
ffprobefor quick single-URL validation without installing the full checker suite.
Frequently Asked Questions
How long does the stream testing take?
The iptv-checker processes URLs concurrently using 100 workers, so a typical playlist of several hundred channels completes in 5-10 minutes depending on network latency. Individual streams timeout after 120 seconds if unresponsive.
Can I test streams without installing Node.js?
While m3u-linter and iptv-checker require Node.js, you can validate single URLs using FFprobe (which only requires FFmpeg). For full playlist validation, the Node.js tools are necessary to replicate the exact CI environment used by Free-TV/IPTV.
What does the [>] marker mean in the markdown files?
The make_playlist.py script (lines 53-55) only includes channels marked with [>] in the generated playlist.m3u8. This marker indicates the stream is confirmed working and should be included in public playlists, while unmarked entries are treated as draft or unverified.
Why does my stream pass locally but fail in the CI?
The CI environment may use different network routing or IP geolocation that triggers geo-blocking rules not present in your local network. Additionally, some streams block datacenter IPs (common for GitHub Actions runners) while allowing residential connections. Check the geoBlocked field in the JSON report to confirm.
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 →