mirror of
https://github.com/spaam/svtplay-dl.git
synced 2024-11-27 21:54:17 +01:00
Add support for live svtplay using hls
This commit is contained in:
parent
786fc6a027
commit
939f277f86
@ -35,6 +35,9 @@ def templateelemt(element, filename, idnumber):
|
|||||||
else:
|
else:
|
||||||
start = 0
|
start = 0
|
||||||
timeline = element.find("{urn:mpeg:dash:schema:mpd:2011}SegmentTimeline")
|
timeline = element.find("{urn:mpeg:dash:schema:mpd:2011}SegmentTimeline")
|
||||||
|
if timeline is None:
|
||||||
|
return
|
||||||
|
|
||||||
rvalue = timeline.findall(".//{urn:mpeg:dash:schema:mpd:2011}S[@r]")
|
rvalue = timeline.findall(".//{urn:mpeg:dash:schema:mpd:2011}S[@r]")
|
||||||
selements = timeline.findall(".//{urn:mpeg:dash:schema:mpd:2011}S")
|
selements = timeline.findall(".//{urn:mpeg:dash:schema:mpd:2011}S")
|
||||||
selements.pop()
|
selements.pop()
|
||||||
|
@ -5,6 +5,8 @@ import sys
|
|||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import copy
|
import copy
|
||||||
|
import time
|
||||||
|
import datetime
|
||||||
|
|
||||||
from svtplay_dl.output import progressbar, progress_stream, ETA, output
|
from svtplay_dl.output import progressbar, progress_stream, ETA, output
|
||||||
from svtplay_dl.log import log
|
from svtplay_dl.log import log
|
||||||
@ -83,10 +85,11 @@ class HLS(VideoRetriever):
|
|||||||
return "hls"
|
return "hls"
|
||||||
|
|
||||||
def download(self):
|
def download(self):
|
||||||
if self.options.live and not self.options.force:
|
|
||||||
raise LiveHLSException(self.url)
|
|
||||||
|
|
||||||
if self.audio:
|
if self.audio:
|
||||||
|
if self.options.live:
|
||||||
|
raise LiveHLSException(self.url)
|
||||||
|
|
||||||
cookies = self.kwargs["cookies"]
|
cookies = self.kwargs["cookies"]
|
||||||
audio_data_m3u = self.http.request("get", self.audio, cookies=cookies).text
|
audio_data_m3u = self.http.request("get", self.audio, cookies=cookies).text
|
||||||
audio_m3u8 = M3U8(audio_data_m3u)
|
audio_m3u8 = M3U8(audio_data_m3u)
|
||||||
@ -98,12 +101,12 @@ class HLS(VideoRetriever):
|
|||||||
total_size = m3u8.media_segment[-1]["EXT-X-BYTERANGE"]["n"] + m3u8.media_segment[-1]["EXT-X-BYTERANGE"]["o"]
|
total_size = m3u8.media_segment[-1]["EXT-X-BYTERANGE"]["n"] + m3u8.media_segment[-1]["EXT-X-BYTERANGE"]["o"]
|
||||||
self._download_url(m3u8.media_segment[0]["URI"], total_size=total_size)
|
self._download_url(m3u8.media_segment[0]["URI"], total_size=total_size)
|
||||||
else:
|
else:
|
||||||
self._download(self.url)
|
self._download()
|
||||||
|
|
||||||
def _download(self, url):
|
def _download(self):
|
||||||
cookies = self.kwargs["cookies"]
|
cookies = self.kwargs["cookies"]
|
||||||
data_m3u = self.http.request("get", url, cookies=cookies).text
|
start_time = time.time()
|
||||||
m3u8 = M3U8(data_m3u)
|
m3u8 = M3U8(self.http.request("get", self.url, cookies=cookies).text)
|
||||||
key = None
|
key = None
|
||||||
|
|
||||||
if m3u8.encrypted:
|
if m3u8.encrypted:
|
||||||
@ -118,13 +121,20 @@ class HLS(VideoRetriever):
|
|||||||
return
|
return
|
||||||
|
|
||||||
decryptor = None
|
decryptor = None
|
||||||
eta = ETA(len(m3u8.media_segment))
|
size_media = len(m3u8.media_segment)
|
||||||
|
eta = ETA(size_media)
|
||||||
|
duration = 0
|
||||||
for index, i in enumerate(m3u8.media_segment):
|
for index, i in enumerate(m3u8.media_segment):
|
||||||
item = _get_full_url(i["URI"], url)
|
if "duration" in i["EXTINF"]:
|
||||||
|
duration += i["EXTINF"]["duration"]
|
||||||
|
item = _get_full_url(i["URI"], self.url)
|
||||||
|
|
||||||
if not self.options.silent:
|
if not self.options.silent:
|
||||||
|
if self.options.live:
|
||||||
|
progressbar(size_media, index + 1, ''.join(['DU: ', str(datetime.timedelta(seconds=int(duration)))]))
|
||||||
|
else:
|
||||||
eta.increment()
|
eta.increment()
|
||||||
progressbar(len(m3u8.media_segment), index+1, ''.join(['ETA: ', str(eta)]))
|
progressbar(size_media, index + 1, ''.join(['ETA: ', str(eta)]))
|
||||||
|
|
||||||
data = self.http.request("get", item, cookies=cookies)
|
data = self.http.request("get", item, cookies=cookies)
|
||||||
if data.status_code == 404:
|
if data.status_code == 404:
|
||||||
@ -149,6 +159,18 @@ class HLS(VideoRetriever):
|
|||||||
|
|
||||||
file_d.write(data)
|
file_d.write(data)
|
||||||
|
|
||||||
|
if (size_media == (index + 1)) and self.options.live:
|
||||||
|
while (start_time + i["EXTINF"]["duration"] * 2) >= time.time():
|
||||||
|
time.sleep(1.0)
|
||||||
|
|
||||||
|
start_time = time.time()
|
||||||
|
new_m3u8 = M3U8(self.http.request("get", self.url, cookies=cookies).text)
|
||||||
|
for n_m3u in new_m3u8.media_segment:
|
||||||
|
if n_m3u not in m3u8.media_segment:
|
||||||
|
m3u8.media_segment.append(n_m3u)
|
||||||
|
|
||||||
|
size_media = len(m3u8.media_segment)
|
||||||
|
|
||||||
file_d.close()
|
file_d.close()
|
||||||
if not self.options.silent:
|
if not self.options.silent:
|
||||||
progress_stream.write('\n')
|
progress_stream.write('\n')
|
||||||
|
@ -18,6 +18,7 @@ from svtplay_dl.fetcher.dash import dashparse
|
|||||||
from svtplay_dl.subtitle import subtitle
|
from svtplay_dl.subtitle import subtitle
|
||||||
from svtplay_dl.error import ServiceError
|
from svtplay_dl.error import ServiceError
|
||||||
|
|
||||||
|
URL_VIDEO_API = "http://api.svt.se/videoplayer-api/video/"
|
||||||
|
|
||||||
class Svtplay(Service, OpenGraphThumbMixin):
|
class Svtplay(Service, OpenGraphThumbMixin):
|
||||||
supported_domains = ['svtplay.se', 'svt.se', 'beta.svtplay.se', 'svtflow.se']
|
supported_domains = ['svtplay.se', 'svt.se', 'beta.svtplay.se', 'svtflow.se']
|
||||||
@ -25,7 +26,7 @@ class Svtplay(Service, OpenGraphThumbMixin):
|
|||||||
def get(self):
|
def get(self):
|
||||||
parse = urlparse(self.url)
|
parse = urlparse(self.url)
|
||||||
if parse.netloc == "www.svtplay.se" or parse.netloc == "svtplay.se":
|
if parse.netloc == "www.svtplay.se" or parse.netloc == "svtplay.se":
|
||||||
if parse.path[:6] != "/video" and parse.path[:6] != "/klipp":
|
if parse.path[:6] != "/video" and parse.path[:6] != "/klipp" and parse.path[:8] != "/kanaler":
|
||||||
yield ServiceError("This mode is not supported anymore. Need the url with the video.")
|
yield ServiceError("This mode is not supported anymore. Need the url with the video.")
|
||||||
return
|
return
|
||||||
|
|
||||||
@ -34,6 +35,19 @@ class Svtplay(Service, OpenGraphThumbMixin):
|
|||||||
if "accessService" in query:
|
if "accessService" in query:
|
||||||
self.access = query["accessService"]
|
self.access = query["accessService"]
|
||||||
|
|
||||||
|
if parse.path[:8] == "/kanaler":
|
||||||
|
res = self.http.get(URL_VIDEO_API + "ch-{0}".format(parse.path[9:]))
|
||||||
|
try:
|
||||||
|
janson = res.json()
|
||||||
|
except json.decoder.JSONDecodeError:
|
||||||
|
yield ServiceError("Can't decode api request: {0}".format(res.request.url))
|
||||||
|
return
|
||||||
|
videos = self._get_video(janson)
|
||||||
|
self.options.live = True
|
||||||
|
for i in videos:
|
||||||
|
yield i
|
||||||
|
return
|
||||||
|
|
||||||
match = re.search("__svtplay'] = ({.*});", self.get_urldata())
|
match = re.search("__svtplay'] = ({.*});", self.get_urldata())
|
||||||
if not match:
|
if not match:
|
||||||
yield ServiceError("Can't find video info.")
|
yield ServiceError("Can't find video info.")
|
||||||
@ -55,9 +69,6 @@ class Svtplay(Service, OpenGraphThumbMixin):
|
|||||||
return
|
return
|
||||||
janson = json.loads(match.group(1))["videoPage"]
|
janson = json.loads(match.group(1))["videoPage"]
|
||||||
|
|
||||||
if "live" in janson["video"]:
|
|
||||||
self.options.live = janson["video"]["live"]
|
|
||||||
|
|
||||||
if self.options.output_auto:
|
if self.options.output_auto:
|
||||||
self.options.service = "svtplay"
|
self.options.service = "svtplay"
|
||||||
self.options.output = self.outputfilename(janson["video"], self.options.output)
|
self.options.output = self.outputfilename(janson["video"], self.options.output)
|
||||||
@ -70,7 +81,7 @@ class Svtplay(Service, OpenGraphThumbMixin):
|
|||||||
vid = janson["video"]["programVersionId"]
|
vid = janson["video"]["programVersionId"]
|
||||||
else:
|
else:
|
||||||
vid = janson["video"]["id"]
|
vid = janson["video"]["id"]
|
||||||
res = self.http.get("http://api.svt.se/videoplayer-api/video/{0}".format(vid))
|
res = self.http.get(URL_VIDEO_API + vid)
|
||||||
try:
|
try:
|
||||||
janson = res.json()
|
janson = res.json()
|
||||||
except json.decoder.JSONDecodeError:
|
except json.decoder.JSONDecodeError:
|
||||||
@ -81,8 +92,6 @@ class Svtplay(Service, OpenGraphThumbMixin):
|
|||||||
yield i
|
yield i
|
||||||
|
|
||||||
def _get_video(self, janson):
|
def _get_video(self, janson):
|
||||||
if "live" in janson:
|
|
||||||
self.options.live = janson["live"]
|
|
||||||
if "subtitleReferences" in janson:
|
if "subtitleReferences" in janson:
|
||||||
for i in janson["subtitleReferences"]:
|
for i in janson["subtitleReferences"]:
|
||||||
if i["format"] == "websrt" and "url" in i:
|
if i["format"] == "websrt" and "url" in i:
|
||||||
|
Loading…
Reference in New Issue
Block a user