mirror of https://github.com/Free-TV/IPTV
Recognize raw audio/video streams, not just playlists, as alive
Some radio stations serve the live audio directly at the listed URL (Content-Type: audio/mpeg, audio/aacp, etc.) rather than an HLS/DASH manifest that points to one. probe() only checked for #EXTM3U/<MPD in the response body, so every one of these was misclassified as dead regardless of whether the station actually worked. Found while verifying replacement URLs for Irish radio stations: curl confirmed real audio bytes with correct audio/* Content-Type on all of them, but check_channels.py reported every single one as dead. Now checks the response's Content-Type first; a direct audio/video stream counts as alive without needing playlist syntax. Verified this doesn't regress playlist detection (existing HLS/DASH channels still classify correctly).pull/1169/head
parent
f2a1e1f9d4
commit
b05f8ef87f
|
|
@ -124,6 +124,17 @@ def looks_like_a_playlist(head):
|
|||
return "<MPD" in text[:2000]
|
||||
|
||||
|
||||
# some radio stations serve the live audio itself at the listed URL rather than
|
||||
# a playlist that points to one - that is a legitimate live source too, and a
|
||||
# station is not "gone" just because it skipped the manifest step
|
||||
STREAM_CONTENT_TYPES = ("audio/", "video/mp2t", "video/mpeg")
|
||||
|
||||
|
||||
def looks_like_a_raw_stream(content_type):
|
||||
"""Return True if `content_type` is a direct audio/video stream, not a manifest."""
|
||||
return content_type.lower().startswith(STREAM_CONTENT_TYPES)
|
||||
|
||||
|
||||
def probe(url, timeout):
|
||||
"""Open `url` once and report what the server did."""
|
||||
request = urllib.request.Request(url, headers={"User-Agent": USER_AGENT})
|
||||
|
|
@ -133,6 +144,7 @@ def probe(url, timeout):
|
|||
context.verify_mode = ssl.CERT_NONE
|
||||
try:
|
||||
with urllib.request.urlopen(request, timeout=timeout, context=context) as response:
|
||||
content_type = response.headers.get("Content-Type", "")
|
||||
head = response.read(3000).decode("utf-8", "ignore")
|
||||
except urllib.error.HTTPError as error:
|
||||
if error.code in GONE_CODES:
|
||||
|
|
@ -145,6 +157,8 @@ def probe(url, timeout):
|
|||
# response and then hung up mid-chunk (IncompleteRead) and similar
|
||||
# low-level protocol violations - a broken connection, not a bad URL
|
||||
return UNREACHABLE
|
||||
if looks_like_a_raw_stream(content_type):
|
||||
return OK
|
||||
return OK if looks_like_a_playlist(head) else GONE
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue