Metadata-Version: 2.4
Name: iptv-stream-validator
Version: 0.1.0
Summary: Check whether IPTV/M3U stream endpoints respond, and parse M3U playlists.
Author: iptv2live
License-Expression: MIT
Project-URL: Homepage, https://iptv2live.com
Project-URL: Documentation, https://iptv2live.com
Keywords: iptv,m3u,m3u8,playlist,stream,validator
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Internet
Classifier: Topic :: Multimedia :: Video
Classifier: Topic :: Software Development :: Quality Assurance
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Dynamic: license-file

# iptv-stream-validator

A small Python package for validating IPTV stream endpoints and parsing M3U / M3U8 playlists. It uses only the Python standard library, has no runtime dependencies, and supports Python 3.9+.

## What the package does

- **Parses M3U / M3U8 playlists** — extended playlists with `#EXTINF` metadata (title, duration, `tvg-id`, `group-title`, and other `key="value"` attributes) as well as plain URL-only lists.
- **Checks stream endpoints over HTTP(S)** — one lightweight request per URL that stops after the response status line and headers, without downloading the media body.
- **Records HTTP status and response time** for every check.
- **Applies configurable timeouts** so dead endpoints cannot stall a validation run.
- **Reports failures as data** — every check returns a `ValidationResult`, so DNS errors, refused connections, timeouts, and HTTP errors are results, not exceptions.
- **Produces JSON-ready output** — results and playlist entries serialize to plain dictionaries, and `summarize_results()` aggregates a whole run into counts, failed URLs, and median/average response times.

## Installation

The distribution name is `iptv-stream-validator`. Once published on PyPI:

```bash
pip install iptv-stream-validator
```

To install from a checkout of this repository (the package is pure Python, standard library only):

```bash
pip install .
```

There are no runtime dependencies.

## Basic Python usage

```python
from iptv_stream_validator import StreamValidator, summarize_results

validator = StreamValidator(timeout=5)

results = validator.validate_many(
    [
        "https://example.com/streams/news.m3u8",
        "http://example.com:8080/live/sports.ts",
    ]
)

for result in results:
    print(result.to_json())

print(summarize_results(results))
```

`StreamValidator` sends a `GET` request by default (many streaming servers reject `HEAD`) but never reads the response body — the connection is closed as soon as the status line and headers arrive. Pass `method="HEAD"` if you prefer HEAD requests.

## M3U playlist validation example

Parse a playlist and check the syntactic validity of its URLs before doing any network I/O:

```python
from iptv_stream_validator import parse_m3u, is_valid_stream_url

playlist_text = """#EXTM3U
#EXTINF:-1 tvg-id="cnn.us" group-title="News",CNN
https://example.com/streams/cnn.m3u8
#EXTINF:-1 tvg-id="bbc.uk",BBC One
https://example.com/streams/bbc.m3u8
"""

entries = parse_m3u(playlist_text)

for entry in entries:
    print(entry.title, entry.attributes, entry.url)
    print("  URL looks valid:", is_valid_stream_url(entry.url))
```

Output:

```
CNN {'tvg-id': 'cnn.us', 'group-title': 'News'} https://example.com/streams/cnn.m3u8
  URL looks valid: True
BBC One {'tvg-id': 'bbc.uk'} https://example.com/streams/bbc.m3u8
  URL looks valid: True
```

Playlists can also be read straight from a file with `parse_m3u_file(path)`, and `extract_urls(text)` returns just the URL list. A playlist whose text contains no URL lines raises `PlaylistError`.

## Stream endpoint validation example

Combining the two modules — parse a playlist, then validate every endpoint it contains:

```python
from iptv_stream_validator import StreamValidator, parse_m3u, summarize_results

with open("playlist.m3u", "r", encoding="utf-8") as handle:
    entries = parse_m3u(handle.read())

validator = StreamValidator(timeout=5)
results = validator.validate_many(entry.url for entry in entries)

for entry, result in zip(entries, results):
    state = "OK" if result.ok else "FAIL"
    print(f"{state}  {entry.title or entry.url}  {result.error or result.status}")

summary = summarize_results(results)
print(f"{summary['ok']}/{summary['total']} endpoints responded")
print(f"median response time: {summary['median_response_time']}s")
```

## Timeout and error handling

- The timeout (default 10 seconds, configurable via `StreamValidator(timeout=...)`) covers DNS resolution, connection setup, and waiting for the response status line.
- `validate()` catches network-level problems (`URLError`, DNS failures, refused connections, socket timeouts) and HTTP error statuses, and returns them inside the `ValidationResult` — it does not raise for a broken endpoint.
- HTTP `4xx`/`5xx` responses are reported as failures with their status code, since the endpoint answered but the URL is not usable as a stream.
- Redirects are followed by default; if the final URL differs from the requested one it is recorded in `result.final_url`.
- Invalid constructor arguments (unknown method, non-numeric timeout, empty user agent) raise `ValueError`/`TypeError` immediately.

```python
result = validator.validate("https://example.com/streams/down.m3u8")
if not result.ok:
    print(result.error)  # e.g. "timed out after 5s" or "HTTP 404 Not Found"
```

## Example output

A single result (`result.to_json()`):

```json
{
  "url": "https://example.com/streams/news.m3u8",
  "ok": true,
  "status": 200,
  "response_time": 0.184371,
  "error": null,
  "final_url": null
}
```

A failed check:

```json
{
  "url": "https://example.com/streams/down.m3u8",
  "ok": false,
  "status": null,
  "response_time": 5.001293,
  "error": "timed out after 5s",
  "final_url": null
}
```

A run summary (`summarize_results(results)`):

```python
{
    "total": 3,
    "ok": 2,
    "failed": 1,
    "failed_urls": ["https://example.com/streams/down.m3u8"],
    "median_response_time": 0.211054,
    "average_response_time": 0.197713,
}
```

## Limitations

- Checks are sequential; validating thousands of URLs takes correspondingly long. Run multiple processes or threads yourself if you need concurrency.
- A successful HTTP response does not prove the payload is playable media — the content is not inspected or decoded. Some servers accept any request path with a 200 response; treat results as a first-pass filter, not a guarantee.
- Endpoints that require specific headers (cookies, referers, unusual user agents) can be configured via `user_agent`, but anything more elaborate needs custom code on top of this package.
- `is_valid_stream_url()` is a syntactic check only (HTTP/HTTPS scheme, non-empty host); it performs no network requests.
- The parser covers the common `#EXTINF`-based IPTV playlist layout. Other directives (`#EXTVLCOPT`, `#EXTGRP`, `#KODIPROP`, ...) are ignored rather than interpreted.
- No M3U variant-specific handling beyond `#EXTINF` metadata: no XMLTV merging, no EPG lookup, no deduplication of streams.

## License

MIT — see [LICENSE](LICENSE).

## Additional IPTV playlist / player resources

- [IPTV2Live](https://iptv2live.com) — IPTV playlist and player reference site; this project's homepage and documentation are hosted there.
- [HLS (HTTP Live Streaming), RFC 8216](https://datatracker.ietf.org/doc/html/rfc8216) — the specification behind `.m3u8` media playlists.
- [VideoLAN VLC](https://www.videolan.org/vlc/) — a widely used player for M3U playlists and network streams.
- [FFmpeg](https://ffmpeg.org/) — the standard toolkit for inspecting and re-streaming media (e.g. `ffprobe` for checking whether a URL yields playable media).
- [iptv-org/iptv](https://github.com/iptv-org/iptv) — a large, publicly maintained collection of M3U playlists, useful as realistic test input.
