1
0
mirror of https://github.com/spaam/svtplay-dl.git synced 2024-11-24 12:15:40 +01:00

Add support for live svtplay using hls

This commit is contained in:
dalgr 2018-01-07 20:52:19 +01:00 committed by Johan Andersson
parent 786fc6a027
commit 939f277f86
3 changed files with 51 additions and 17 deletions

View File

@ -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()

View File

@ -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:
eta.increment() if self.options.live:
progressbar(len(m3u8.media_segment), index+1, ''.join(['ETA: ', str(eta)])) progressbar(size_media, index + 1, ''.join(['DU: ', str(datetime.timedelta(seconds=int(duration)))]))
else:
eta.increment()
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')

View File

@ -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: