1
0
mirror of https://github.com/spaam/svtplay-dl.git synced 2024-11-27 13:44:14 +01:00

m3u8: add support for ext-x-byterange x-map

add tests for x-map ext-byte-range
This commit is contained in:
Johan Andersson 2022-06-05 16:05:45 +02:00
parent 8a72c4d200
commit eac21b3979
4 changed files with 65 additions and 3 deletions

View File

@ -248,7 +248,7 @@ class HLS(VideoRetriever):
duration = 0
max_duration = 0
for index, i in enumerate(m3u8.media_segment):
if "duration" in i["EXTINF"]:
if "EXTINF" in i and "duration" in i["EXTINF"]:
duration = i["EXTINF"]["duration"]
max_duration = max(max_duration, duration)
total_duration += duration
@ -261,7 +261,10 @@ class HLS(VideoRetriever):
eta.increment()
progressbar(size_media, index + 1, "".join(["ETA: ", str(eta)]))
data = self.http.request("get", item, cookies=cookies)
headers = {}
if "EXT-X-BYTERANGE" in i:
headers["Range"] = f'bytes={i["EXT-X-BYTERANGE"]["o"]}-{i["EXT-X-BYTERANGE"]["o"] + i["EXT-X-BYTERANGE"]["n"] - 1}'
data = self.http.request("get", item, cookies=cookies, headers=headers)
if data.status_code == 404:
break
data = data.content
@ -426,7 +429,19 @@ class M3U8:
# 4.3.2.5. EXT-X-MAP
elif tag == "EXT-X-MAP":
info = _get_tuple_attribute(attr)
self.media_segment.insert(0, {"URI": info["URI"], "EXTINF": {"duration": 0}})
if "BYTERANGE" in info:
if "@" in info["BYTERANGE"]:
n, o = info["BYTERANGE"].split("@", 1)
info["EXT-X-BYTERANGE"] = {}
info["EXT-X-BYTERANGE"]["n"], info["EXT-X-BYTERANGE"]["o"] = (int(n), int(o))
else:
info["EXT-X-BYTERANGE"] = {}
info["EXT-X-BYTERANGE"]["n"] = int(attr)
info["EXT-X-BYTERANGE"]["o"] = 0
if "BYTERANGE" not in info:
info["EXTINF"] = {}
info["EXTINF"]["duration"] = 0
self.media_segment.insert(0, info)
# 4.3.2.6. EXT-X-PROGRAM-DATE-TIME"
elif tag == "EXT-X-PROGRAM-DATE-TIME":

View File

@ -0,0 +1,17 @@
#EXTM3U
#EXT-X-VERSION:6
#EXT-X-PLAYLIST-TYPE:VOD
#EXT-X-INDEPENDENT-SEGMENTS
#EXT-X-TARGETDURATION:10
#EXT-X-MEDIA-SEQUENCE:0
#EXT-X-MAP:URI="Frank---Kastaniegaarde_bfc1970adae844c180ae0c447e079c1e_5500_audio.mp4",BYTERANGE="748@0"
#EXTINF:10.005333,
#EXT-X-BYTERANGE:242398@2828
Frank---Kastaniegaarde_bfc1970adae844c180ae0c447e079c1e_5500_audio.mp4
#EXTINF:10.005333,
#EXT-X-BYTERANGE:242050@245226
Frank---Kastaniegaarde_bfc1970adae844c180ae0c447e079c1e_5500_audio.mp4
#EXTINF:10.005333,
#EXT-X-BYTERANGE:242104@487276
Frank---Kastaniegaarde_bfc1970adae844c180ae0c447e079c1e_5500_audio.mp4
#EXT-X-ENDLIST

View File

@ -0,0 +1,11 @@
#EXTM3U
#EXT-X-VERSION:6
#EXT-X-TARGETDURATION:17
#EXT-X-PLAYLIST-TYPE:VOD
#EXT-X-MAP:URI="video/init.mp4"
#EXTINF:11.378,
video/1.m4s
#EXTINF:10.677,
video/2.m4s
#EXTINF:10.944,
video/3.m4s

View File

@ -25,6 +25,12 @@ def parse(playlist):
return streams
def parse_m3u8(playlist):
with open(os.path.join(os.path.dirname(os.path.realpath(__file__)), "m3u8-playlists", playlist)) as fd:
manifest = fd.read()
return M3U8(manifest)
# Example HLS playlist, source:
# loosly inspired by
# https://devstreaming-cdn.apple.com/videos/streaming/examples/bipbop_4x3/bipbop_4x3_variant.m3u8
@ -130,3 +136,16 @@ def test_audio_bottom():
data = parse("audio-uri-bottom.m3u8")
assert data[2639].segments
assert data[2639].audio
def test_x_byterange():
data = parse_m3u8("ext-x-byterange.m3u8")
assert data.media_segment[0]["EXT-X-BYTERANGE"]["n"] == 748
assert data.media_segment[1]["EXT-X-BYTERANGE"]["n"] == 242398
assert data.media_segment[1]["EXT-X-BYTERANGE"]["n"] + data.media_segment[1]["EXT-X-BYTERANGE"]["o"] - 1 == 245225
def test_x_map():
data = parse_m3u8("x-map.m3u8")
assert data.media_segment[0]["URI"] == "video/init.mp4"
assert data.media_segment[2]["URI"] == "video/2s.m4s"