def UpdateVideoItem(self, item): """Updates an existing MediaItem with more data. Arguments: item : MediaItem - the MediaItem that needs to be updated Returns: The original item with more data added to it's properties. Used to update none complete MediaItems (self.complete = False). This could include opening the item's URL to fetch more data and then process that data or retrieve it's real media-URL. The method should at least: * cache the thumbnail to disk (use self.noImage if no thumb is available). * set at least one MediaItemPart with a single MediaStream. * set self.complete = True. if the returned item does not have a MediaItemPart then the self.complete flag will automatically be set back to False. """ Logger.Debug('Starting UpdateVideoItem for %s (%s)', item.name, self.channelName) data = UriHandler.Open(item.url, proxy=self.proxy, additionalHeaders=item.HttpHeaders) json = JsonHelper(data) videoInfo = json.GetValue("content", "videoInfos") part = item.CreateNewEmptyMediaPart() if "HLSurlHD" in videoInfo: # HLSurlHD=http://srfvodhd-vh.akamaihd.net/i/vod/potzmusig/2015/03/potzmusig_20150307_184438_v_webcast_h264_,q10,q20,q30,q40,q50,q60,.mp4.csmil/master.m3u8 for s, b in M3u8.GetStreamsFromM3u8(videoInfo["HLSurlHD"], self.proxy): item.complete = True # s = self.GetVerifiableVideoUrl(s) part.AppendMediaStream(s, b) elif "HLSurl" in videoInfo: # HLSurl=http://srfvodhd-vh.akamaihd.net/i/vod/potzmusig/2015/03/potzmusig_20150307_184438_v_webcast_h264_,q10,q20,q30,q40,.mp4.csmil/master.m3u8 for s, b in M3u8.GetStreamsFromM3u8(videoInfo["HLSurl"], self.proxy): item.complete = True # s = self.GetVerifiableVideoUrl(s) part.AppendMediaStream(s, b) if "downloadLink" in videoInfo: # downloadLink=http://podcastsource.sf.tv/nps/podcast/10vor10/2015/03/10vor10_20150304_215030_v_podcast_h264_q10.mp4 part.AppendMediaStream(videoInfo["downloadLink"], 1000) return item
def UpdateJsonVideoItem(self, item): data = UriHandler.Open(item.url, proxy=self.proxy) json = JsonHelper(data) m3u8Url = json.GetValue("playlist") if m3u8Url != "https://embed.kijk.nl/api/playlist/.m3u8": part = item.CreateNewEmptyMediaPart() for s, b in M3u8.GetStreamsFromM3u8(m3u8Url, self.proxy, appendQueryString=True): if "_enc_" in s: Logger.Warning("Found encrypted stream. Skipping %s", s) continue item.complete = True # s = self.GetVerifiableVideoUrl(s) part.AppendMediaStream(s, b) return item Logger.Warning("No M3u8 data found. Falling back to BrightCove") videoId = json.GetValue("vpakey") # videoId = json.GetValue("videoId") -> Not all items have a videoId url = "https://embed.kijk.nl/video/%s?width=868&height=491" % ( videoId, ) referer = "https://embed.kijk.nl/video/%s" % (videoId, ) part = item.CreateNewEmptyMediaPart() # First try the new BrightCove JSON data = UriHandler.Open(url, proxy=self.proxy, referer=referer) brightCoveRegex = '<video[^>]+data-video-id="(?<videoId>[^"]+)[^>]+data-account="(?<videoAccount>[^"]+)' brightCoveData = Regexer.DoRegex(Regexer.FromExpresso(brightCoveRegex), data) if brightCoveData: Logger.Info("Found new BrightCove JSON data") brightCoveUrl = 'https://edge.api.brightcove.com/playback/v1/accounts/%(videoAccount)s/videos/%(videoId)s' % \ brightCoveData[0] headers = { "Accept": "application/json;pk=BCpkADawqM3ve1c3k3HcmzaxBvD8lXCl89K7XEHiKutxZArg2c5RhwJHJANOwPwS_4o7UsC4RhIzXG8Y69mrwKCPlRkIxNgPQVY9qG78SJ1TJop4JoDDcgdsNrg" } brightCoveData = UriHandler.Open(brightCoveUrl, proxy=self.proxy, additionalHeaders=headers) brightCoveJson = JsonHelper(brightCoveData) streams = filter(lambda d: d["container"] == "M2TS", brightCoveJson.GetValue("sources")) if streams: # noinspection PyTypeChecker streamUrl = streams[0]["src"] for s, b in M3u8.GetStreamsFromM3u8(streamUrl, self.proxy): item.complete = True part.AppendMediaStream(s, b) return item
def UpdateVideoItem(self, item): """ Accepts an item. It returns an updated item. Usually retrieves the MediaURL and the Thumb! It should return a completed item. """ Logger.Debug('Starting UpdateVideoItem for %s (%s)', item.name, self.channelName) if not item.url.endswith("m3u8"): data = UriHandler.Open(item.url, proxy=self.proxy) jsonData = Regexer.DoRegex(self.mediaUrlRegex, data) if not jsonData: Logger.Error("Cannot find JSON stream info.") return item json = JsonHelper(jsonData[0]) Logger.Trace(json.json) stream = json.GetValue("source", "hls") Logger.Debug("Found HLS: %s", stream) else: stream = item.url part = item.CreateNewEmptyMediaPart() for s, b in M3u8.GetStreamsFromM3u8(stream, self.proxy): item.complete = True # s = self.GetVerifiableVideoUrl(s) part.AppendMediaStream(s, b) # var playerConfig = {"id":"mediaplayer","width":"100%","height":"100%","autostart":"false","image":"http:\/\/www.ketnet.be\/sites\/default\/files\/thumb_5667ea22632bc.jpg","brand":"ketnet","source":{"hls":"http:\/\/vod.stream.vrt.be\/ketnet\/_definst_\/mp4:ketnet\/2015\/12\/Ben_ik_familie_van_R001_A0023_20151208_143112_864.mp4\/playlist.m3u8"},"analytics":{"type_stream":"vod","playlist":"Ben ik familie van?","program":"Ben ik familie van?","episode":"Ben ik familie van?: Warre - Aflevering 3","parts":"1","whatson":"270157835527"},"title":"Ben ik familie van?: Warre - Aflevering 3","description":"Ben ik familie van?: Warre - Aflevering 3"} return item
def UpdateLiveItem(self, item): """ Accepts an item. It returns an updated item. Usually retrieves the MediaURL and the Thumb! It should return a completed item. """ Logger.Debug('Starting UpdateVideoItem for %s (%s)', item.name, self.channelName) data = UriHandler.Open(item.url, proxy=self.proxy) data = data[data.index('{'):] json = JsonHelper(data) sid = json.GetValue("sid") # The i= is the same as the one from the RTMP stream at the page of ATV.sr: # http://edge1.tikilive.com:1935/rtmp_tikilive/34967/amlst:mainstream/jwplayer.smil?id=dIzAVAVL2dirCfJgAPEb&i=YXBwTmFtZT1QbGF5ZXImY0lEPTM0OTY3JmNOYW1lPUFUViUyME5ldHdvcmtzJm9JRD0xMzY1NTUmb05hbWU9YXR2bmV0d29ya3Mmc0lkPWJwaHR2bXR2OXI4M2N1Mm9sZ2Q5dWx1aWs2JnVJRD0wJnVOYW1lPUd1ZXN0OWFmYTE= # videoUrl = "http://edge2.tikilive.com:1935/html5_tikilive/34967/amlst:mainstream/playlist.m3u8" \ # "?i=8xbrQERMXS2dTUKuAPbW&i=YXBwTmFtZT1QbGF5ZXImY0lEPTM0OTY3JmNOYW1lPUFUViUyME5ldHdvcm" \ # "tzJm9JRD0xMzY1NTUmb05hbWU9YXR2bmV0d29ya3Mmc0lkPWJwaHR2bXR2OXI4M2N1Mm9sZ2Q5dWx1aWs2JnVJRD0wJnVOYW1lPUd1ZXN0YzExZmE=&id=%s" \ # % (sid,) videoUrl = "http://edge2.tikilive.com:1935/html5_tikilive/34967/amlst:mainstream/playlist.m3u8" \ "?i=YXBwTmFtZT1QbGF5ZXImY0lEPTM0OTY3JmNOYW1lPUFUViUyME5ldHdvcmtzJm9JRD0xMzY1NTUmb05hbW" \ "U9YXR2bmV0d29ya3Mmc0lkPWZvODRpbDNlN3FzNjh1ZXQycWwyZWF2MDgxJnVJRD0wJnVOYW1lPUd1ZXN0MTNiNjk=&id=%s" \ % (sid,) part = item.CreateNewEmptyMediaPart() for s, b in M3u8.GetStreamsFromM3u8(videoUrl, self.proxy): item.complete = True # s = self.GetVerifiableVideoUrl(s) part.AppendMediaStream(s, b) item.complete = True return item
def UpdateVideoItem(self, item): Logger.Debug('Starting UpdateVideoItem for %s (%s)', item.name, self.channelName) # we need to fetch the actual url as it might differ for single video items data, secureUrl = UriHandler.Header(item.url, proxy=self.proxy) secureUrl = secureUrl.rstrip("/") secureUrl = "%s.mssecurevideo.json" % (secureUrl, ) data = UriHandler.Open(secureUrl, proxy=self.proxy, additionalHeaders=item.HttpHeaders) secureData = JsonHelper(data, logger=Logger.Instance()) mzid = secureData.GetValue(secureData.json.keys()[0], "videoid") assetUrl = "https://mediazone.vrt.be/api/v1/vrtvideo/assets/%s" % (mzid, ) data = UriHandler.Open(assetUrl, proxy=self.proxy) assetData = JsonHelper(data, logger=Logger.Instance()) for streamData in assetData.GetValue("targetUrls"): if streamData["type"] != "HLS": continue part = item.CreateNewEmptyMediaPart() for s, b, a in M3u8.GetStreamsFromM3u8(streamData["url"], self.proxy, mapAudio=True): item.complete = True if a: audioPart = a.rsplit("-", 1)[-1] audioPart = "-%s" % (audioPart, ) s = s.replace(".m3u8", audioPart) # s = self.GetVerifiableVideoUrl(s) part.AppendMediaStream(s, b) return item
def UpdateLiveStream(self, item): Logger.Debug("Updating Live stream") # let's request a token token = self.__GetToken() # What is the channel name to play channel = self.channelCode if self.channelCode == "q2": channel = "2be" elif self.channelCode == "stievie": channel = item.metaData["channelId"] url = "https://stream-live.medialaan.io/stream-live/v1/channels/%s/broadcasts/current/video/?deviceId=%s" % ( channel, uuid.uuid4() # Could be a random int ) auth = {"Authorization": "apikey=%s&access_token=%s" % (self.__apiKey, token)} data = UriHandler.Open(url, proxy=self.proxy, noCache=True, additionalHeaders=auth) jsonData = JsonHelper(data) hls = jsonData.GetValue("response", "url", "hls") if not hls: return item part = item.CreateNewEmptyMediaPart() for s, b in M3u8.GetStreamsFromM3u8(hls, self.proxy): item.complete = True # s = self.GetVerifiableVideoUrl(s) part.AppendMediaStream(s, b) return item
def UpdateLiveItem(self, item): """ Accepts an item. It returns an updated item. Usually retrieves the MediaURL and the Thumb! It should return a completed item. """ Logger.Debug('Starting UpdateVideoItem for %s (%s)', item.name, self.channelName) data = UriHandler.Open(item.url, proxy=self.proxy) data = data[data.index('{'):] json = JsonHelper(data) sid = json.GetValue("sid") videoUrl = "http://edge2.tikilive.com:1935/html5_tikilive/34967/amlst:mainstream/playlist.m3u8" \ "?i=YXBwTmFtZT1QbGF5ZXImY0lEPTM0OTY3JmNOYW1lPUFUViUyME5ldHdvcmtzJm9JRD0xMzY1NTUmb05hbW" \ "U9YXR2bmV0d29ya3Mmc0lkPWZvODRpbDNlN3FzNjh1ZXQycWwyZWF2MDgxJnVJRD0wJnVOYW1lPUd1ZXN0MTNiNjk=&id=%s" \ % (sid,) part = item.CreateNewEmptyMediaPart() for s, b in M3u8.GetStreamsFromM3u8(videoUrl, self.proxy): item.complete = True # s = self.GetVerifiableVideoUrl(s) part.AppendMediaStream(s, b) item.complete = True return item
def UpdateVideoItem(self, item): """Updates an existing MediaItem with more data. Arguments: item : MediaItem - the MediaItem that needs to be updated Returns: The original item with more data added to it's properties. Used to update none complete MediaItems (self.complete = False). This could include opening the item's URL to fetch more data and then process that data or retrieve it's real media-URL. The method should at least: * cache the thumbnail to disk (use self.noImage if no thumb is available). * set at least one MediaItemPart with a single MediaStream. * set self.complete = True. if the returned item does not have a MediaItemPart then the self.complete flag will automatically be set back to False. """ Logger.Debug("Updating a (Live) video item") part = item.CreateNewEmptyMediaPart() for s, b in M3u8.GetStreamsFromM3u8(item.url, self.proxy, appendQueryString=True): item.complete = True # s = self.GetVerifiableVideoUrl(s) part.AppendMediaStream(s, b) item.complete = True return item
def UpdateVideoItem(self, item): """Updates an existing MediaItem with more data. Arguments: item : MediaItem - the MediaItem that needs to be updated Returns: The original item with more data added to it's properties. Used to update none complete MediaItems (self.complete = False). This could include opening the item's URL to fetch more data and then process that data or retrieve it's real media-URL. The method should at least: * cache the thumbnail to disk (use self.noImage if no thumb is available). * set at least one MediaItemPart with a single MediaStream. * set self.complete = True. if the returned item does not have a MediaItemPart then the self.complete flag will automatically be set back to False. """ videoData = UriHandler.Open(item.url, proxy=self.proxy) if not videoData: return item videoData = JsonHelper(videoData) videoInfo = videoData.GetValue("data", "attributes") part = item.CreateNewEmptyMediaPart() # Somehow only this specific user-agent works (dunno why)! part.HttpHeaders[ "user-agent"] = "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-GB; rv:1.9.2.13) Gecko/20101203 Firefox/3.6.13 (.NET CLR 3.5.30729)" m3u8url = videoInfo["streaming"]["hls"]["url"] m3u8data = UriHandler.Open(m3u8url, self.proxy) for s, b, a in M3u8.GetStreamsFromM3u8(m3u8url, self.proxy, appendQueryString=False, mapAudio=True, playListData=m3u8data): item.complete = True if a: audioPart = a.split("-prog_index.m3u8", 1)[0] audioId = audioPart.rsplit("/", 1)[-1] s = s.replace("-prog_index.m3u8", "-{0}-prog_index.m3u8".format(audioId)) part.AppendMediaStream(s, b) vttUrl = M3u8.GetSubtitle(m3u8url, self.proxy, m3u8data) # https://dplaynordics-vod-80.akamaized.net/dplaydni/259/0/hls/243241001/1112635959-prog_index.m3u8?version_hash=bb753129&hdnts=st=1518218118~exp=1518304518~acl=/*~hmac=bdeefe0ec880f8614e14af4d4a5ca4d3260bf2eaa8559e1eb8ba788645f2087a vttUrl = vttUrl.replace("-prog_index.m3u8", "-0.vtt") part.Subtitle = SubtitleHelper.DownloadSubtitle(vttUrl, format='srt', proxy=self.proxy) return item
def __UpdateItemFromVideoReferences(self, item, videos, subtitles=None): item.MediaItemParts = [] part = item.CreateNewEmptyMediaPart() if self.localIP: part.HttpHeaders.update(self.localIP) for video in videos: videoFormat = video.get("format", "") if not videoFormat: videoFormat = video.get("playerType", "") videoFormat = videoFormat.lower() if "dash" in videoFormat or "hds" in videoFormat: Logger.Debug("Skipping video format: %s", videoFormat) continue Logger.Debug("Found video item for format: %s", videoFormat) url = video['url'] if len(filter(lambda s: s.Url == url, part.MediaStreams)) > 0: Logger.Debug("Skippping duplicate Stream url: %s", url) continue if "m3u8" in url: altIndex = url.find("m3u8?") # altIndex = videoUrl.find("~uri") if altIndex > 0: url = url[0:altIndex + 4] for s, b in M3u8.GetStreamsFromM3u8(url, proxy=self.proxy, headers=part.HttpHeaders): part.AppendMediaStream(s, b) elif video["url"].startswith("rtmp"): # just replace some data in the URL part.AppendMediaStream(self.GetVerifiableVideoUrl(video["url"]).replace("_definst_", "?slist="), video[1]) else: part.AppendMediaStream(url, 0) if subtitles: Logger.Info("Found subtitles to play") for sub in subtitles: subFormat = sub["format"].lower() url = sub["url"] if subFormat == "websrt": subUrl = url # elif subFormat == "webvtt": # Logger.Info("Found M3u8 subtitle, replacing with WSRT") # start, name, index = sub[-1].rsplit("/", 2) # subUrl = "%s/%s/%s.wsrt" % (start, name, name) else: # look for more continue part.Subtitle = subtitlehelper.SubtitleHelper.DownloadSubtitle(subUrl, format="srt", proxy=self.proxy) # stop when finding one break item.complete = True return item
def UpdateVideoItem(self, item): """Updates an existing MediaItem with more data. Arguments: item : MediaItem - the MediaItem that needs to be updated Returns: The original item with more data added to it's properties. Used to update none complete MediaItems (self.complete = False). This could include opening the item's URL to fetch more data and then process that data or retrieve it's real media-URL. The method should at least: * cache the thumbnail to disk (use self.noImage if no thumb is available). * set at least one MediaItemPart with a single MediaStream. * set self.complete = True. if the returned item does not have a MediaItemPart then the self.complete flag will automatically be set back to False. """ Logger.Debug('Starting UpdateVideoItem for %s (%s)', item.name, self.channelName) videoId = item.url[item.url.rfind("/") + 1:] url = "http://embed.kijk.nl/?width=868&height=491&video=%s" % ( videoId, ) referer = "http://www.kijk.nl/video/%s" % (videoId, ) # now the mediaurl is derived. First we try WMV data = UriHandler.Open(url, proxy=self.proxy, referer=referer) Logger.Trace(self.mediaUrlRegex) objectData = Regexer.DoRegex(self.mediaUrlRegex, data)[0] Logger.Trace(objectData) # seed = "61773bc7479ab4e69a5214f17fd4afd21fe1987a" # seed = "0a2b91ec0fdb48c5dd5239d3e796d6f543974c33" seed = "0b0234fa8e2435244cdb1603d224bb8a129de5c1" amfHelper = BrightCove(Logger.Instance(), objectData[0], objectData[1], url, seed) # , proxy=ProxyInfo("localhost", 8888) item.description = amfHelper.GetDescription() part = item.CreateNewEmptyMediaPart() for stream, bitrate in amfHelper.GetStreamInfo(): if "m3u8" in stream: for s, b in M3u8.GetStreamsFromM3u8(stream, self.proxy): item.complete = True # s = self.GetVerifiableVideoUrl(s) part.AppendMediaStream(s, b) part.AppendMediaStream(stream.replace("&mp4:", ""), bitrate) item.complete = True return item
def UpdateLiveItem(self, item): """Updates an existing MediaItem with more data. Arguments: item : MediaItem - the MediaItem that needs to be updated Returns: The original item with more data added to it's properties. Used to update none complete MediaItems (self.complete = False). This could include opening the item's URL to fetch more data and then process that data or retrieve it's real media-URL. The method should at least: * cache the thumbnail to disk (use self.noImage if no thumb is available). * set at least one MediaItemPart with a single MediaStream. * set self.complete = True. if the returned item does not have a MediaItemPart then the self.complete flag will automatically be set back to False. """ Logger.Debug('Starting UpdateLiveItem for %s (%s)', item.name, self.channelName) item.MediaItemParts = [] part = item.CreateNewEmptyMediaPart() spoofIp = self._GetSetting("spoof_ip", "0.0.0.0") if spoofIp: for s, b in M3u8.GetStreamsFromM3u8( item.url, self.proxy, headers={"X-Forwarded-For": spoofIp}): part.AppendMediaStream(s, b) # data = UriHandler.Open(item.url, proxy=self.proxy, additionalHeaders={"X-Forwarded-For": spoofIp}) else: for s, b in M3u8.GetStreamsFromM3u8(item.url, self.proxy): part.AppendMediaStream(s, b) # data = UriHandler.Open(item.url, proxy=self.proxy) item.complete = True return item
def UpdateLiveVideo(self, item): if "m3u8" not in item.url: Logger.Error("Cannot update live stream that is not an M3u8: %s", item.url) part = item.CreateNewEmptyMediaPart() for s, b in M3u8.GetStreamsFromM3u8(item.url, self.proxy): item.complete = True # apparently they split up M3u8 streams and audio streams, so we need to fix that here # this is an ugly fix, but it will work! s = s.replace(".m3u8", "-audio_track=96000.m3u8") part.AppendMediaStream(s, b) return item
def __GetVideoStreams(self, videoId, part): """ Fetches the video stream for a given videoId @param videoId: (integer) the videoId @param part: (MediaPart) the mediapart to add the streams to @return: (bool) indicating a successfull retrieval """ # hardcoded for now as it does not seem top matter dscgeo = '{"countryCode":"%s","expiry":1446917369986}' % ( self.language.upper(), ) dscgeo = HtmlEntityHelper.UrlEncode(dscgeo) headers = {"Cookie": "dsc-geo=%s" % (dscgeo, )} # send the data http, nothing, host, other = self.baseUrl.split("/", 3) subdomain, domain = host.split(".", 1) url = "https://secure.%s/secure/api/v2/user/authorization/stream/%s?stream_type=hls" \ % (domain, videoId,) data = UriHandler.Open(url, proxy=self.proxy, additionalHeaders=headers, noCache=True) json = JsonHelper(data) url = json.GetValue("hls") if url is None: return False streamsFound = False if "?" in url: qs = url.split("?")[-1] else: qs = None for s, b in M3u8.GetStreamsFromM3u8(url, self.proxy): # and we need to append the original QueryString if "X-I-FRAME-STREAM" in s: continue streamsFound = True if qs is not None: if "?" in s: s = "%s&%s" % (s, qs) else: s = "%s?%s" % (s, qs) part.AppendMediaStream(s, b) return streamsFound
def UpdateVideoItem(self, item): """Updates an existing MediaItem with more data. Arguments: item : MediaItem - the MediaItem that needs to be updated Returns: The original item with more data added to it's properties. Used to update none complete MediaItems (self.complete = False). This could include opening the item's URL to fetch more data and then process that data or retrieve it's real media-URL. The method should at least: * cache the thumbnail to disk (use self.noImage if no thumb is available). * set at least one MediaItemPart with a single MediaStream. * set self.complete = True. if the returned item does not have a MediaItemPart then the self.complete flag will automatically be set back to False. """ Logger.Debug('Starting UpdateVideoItem for %s (%s)', item.name, self.channelName) # http://www.foxsports.nl/divadata/Output/VideoData/564939.xml # http://www.foxsports.nl/divadata/Output/VideoData/604652.xml data = UriHandler.Open(item.url, proxy=self.proxy, additionalHeaders=item.HttpHeaders) videoId = Regexer.DoRegex('data-videoid="(\d+)" ', data)[-1] data = UriHandler.Open("http://www.foxsports.nl/divadata/Output/VideoData/%s.xml" % (videoId,), proxy=self.proxy, additionalHeaders=item.HttpHeaders) streams = Regexer.DoRegex('<uri>([^>]+)</uri>', data) part = item.CreateNewEmptyMediaPart() for stream in streams: if stream.endswith("m3u8"): for s, b in M3u8.GetStreamsFromM3u8(stream, self.proxy): item.complete = True # s = self.GetVerifiableVideoUrl(s) part.AppendMediaStream(s, b) # elif stream.endswith("mp4"): # part.AppendMediaStream(stream, 4000) else: Logger.Debug("Not using: %s", stream) return item
def UpdateVideoItemFeeds(self, item): """ Accepts an item. It returns an updated item. Usually retrieves the MediaURL and the Thumb! It should return a completed item. """ Logger.Debug('Starting UpdateVideoItem for %s', item) # rtmpt://vrt.flash.streampower.be/een//2011/07/1000_110723_getipt_neefs_wiels_Website_EEN.flv # http://www.een.be/sites/een.be/modules/custom/vrt_video/player/player_4.3.swf data = UriHandler.Open(item.url, proxy=self.proxy) json = JsonHelper(data) if item.MediaItemParts == 1: part = item.MediaItemParts[0] else: part = item.CreateNewEmptyMediaPart() streamItems = json.GetValue("channel", "items") if not streamItems: return item mediaUrlMedium = streamItems[0]["item"].get("ipad_url", "") mediaUrlLow = streamItems[0]["item"].get("iphone_url", "") if mediaUrlLow == mediaUrlMedium and "m3u8" in mediaUrlLow: Logger.Debug("Found M3u8 playlists for streams: %s", mediaUrlLow) for s, b in M3u8.GetStreamsFromM3u8(mediaUrlLow, self.proxy): item.complete = True # s = self.GetVerifiableVideoUrl(s) part.AppendMediaStream(s, b) else: if mediaUrlMedium != "": # not all have seperate bitrates, so these are estimates part.AppendMediaStream( self.GetVerifiableVideoUrl( mediaUrlMedium.replace("mp4:", "/mp4:")), 960) if mediaUrlLow != "": # not all have seperate bitrates, so these are estimates part.AppendMediaStream( self.GetVerifiableVideoUrl( mediaUrlLow.replace("mp4:", "/mp4:")), 696) item.complete = True return item
def UpdateVideoItem(self, item): """Updates an existing MediaItem with more data. Arguments: item : MediaItem - the MediaItem that needs to be updated Returns: The original item with more data added to it's properties. Used to update none complete MediaItems (self.complete = False). This could include opening the item's URL to fetch more data and then process that data or retrieve it's real media-URL. The method should at least: * cache the thumbnail to disk (use self.noImage if no thumb is available). * set at least one MediaItemPart with a single MediaStream. * set self.complete = True. if the returned item does not have a MediaItemPart then the self.complete flag will automatically be set back to False. """ Logger.Debug('Starting UpdateVideoItem for %s (%s)', item.name, self.channelName) xmlData = UriHandler.Open(item.url, proxy=self.proxy) # <ref type='adaptive' device='pc' host='http://manifest.us.rtl.nl' href='/rtlxl/network/pc/adaptive/components/videorecorder/27/278629/278630/d009c025-6e8c-3d11-8aba-dc8579373134.ssm/d009c025-6e8c-3d11-8aba-dc8579373134.m3u8' /> m3u8Urls = Regexer.DoRegex("<ref type='adaptive' device='pc' host='([^']+)' href='/([^']+)' />", xmlData) if not m3u8Urls: Logger.Warning("No m3u8 data found for: %s", item) return item m3u8Url = "%s/%s" % (m3u8Urls[0][0], m3u8Urls[0][1]) part = item.CreateNewEmptyMediaPart() # prevent the "418 I'm a teapot" error part.HttpHeaders["user-agent"] = "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:45.0) Gecko/20100101 Firefox/45.0" # Remove the Range header to make all streams start at the beginning. Logger.Debug("Setting an empty 'Range' http header to force playback at the start of a stream") part.HttpHeaders["Range"] = '' for s, b in M3u8.GetStreamsFromM3u8(m3u8Url, self.proxy): item.complete = True part.AppendMediaStream(s, b) return item
def UpdateLiveItem(self, item): data = UriHandler.Open(item.url, proxy=self.proxy, additionalHeaders=item.HttpHeaders) mediaRegex = 'data-media="([^"]+)"' mediaInfo = Regexer.DoRegex(mediaRegex, data)[0] mediaInfo = HtmlEntityHelper.ConvertHTMLEntities(mediaInfo) mediaInfo = JsonHelper(mediaInfo) Logger.Trace(mediaInfo) part = item.CreateNewEmptyMediaPart() hlsUrl = mediaInfo.GetValue("streamUrl") if hlsUrl is not None and "m3u8" in hlsUrl: Logger.Debug("Found HLS url for %s: %s", mediaInfo.json["streamName"], hlsUrl) # from debug.router import Router # data = Router.GetVia("be", hlsUrl, proxy=self.proxy) for s, b in M3u8.GetStreamsFromM3u8(hlsUrl, self.proxy): part.AppendMediaStream(s, b) item.complete = True else: Logger.Debug("No HLS url found for %s. Fetching RTMP Token.", mediaInfo.json["streamName"]) # fetch the token: tokenUrl = "%s/api/media/streaming?streamname=%s" % ( self.baseUrl, mediaInfo.json["streamName"]) tokenData = UriHandler.Open(tokenUrl, proxy=self.proxy, additionalHeaders=item.HttpHeaders, noCache=True) tokenData = JsonHelper(tokenData) token = tokenData.GetValue("token") Logger.Debug("Found token '%s' for '%s'", token, mediaInfo.json["streamName"]) rtmpUrl = "rtmp://rtmp.rtbf.be/livecast/%s?%s pageUrl=%s tcUrl=rtmp://rtmp.rtbf.be/livecast" % ( mediaInfo.json["streamName"], token, self.baseUrl) rtmpUrl = self.GetVerifiableVideoUrl(rtmpUrl) part.AppendMediaStream(rtmpUrl, 0) item.complete = True item.isGeoLocked = not mediaInfo.GetValue("geoLocRestriction", fallback="world") == "world" return item
def UpdateVideoItem(self, item): """ Accepts an item. It returns an updated item. Usually retrieves the MediaURL and the Thumb! It should return a completed item. """ Logger.Debug('Starting UpdateVideoItem for %s (%s)', item.name, self.channelName) # rtmpt://vrt.flash.streampower.be/een//2011/07/1000_110723_getipt_neefs_wiels_Website_EEN.flv # http://www.een.be/sites/een.be/modules/custom/vrt_video/player/player_4.3.swf # now the mediaurl is derived. First we try WMV data = UriHandler.Open(item.url) urls = Regexer.DoRegex(self.mediaUrlRegex, data) part = item.CreateNewEmptyMediaPart() for url in urls: if not url[1] == "": mediaurl = "%s//%s" % ( url[0], url[1] ) # the extra slash in the url causes the application name in the RTMP stream to be "een" instead of "een/2011" else: mediaurl = url[0] mediaurl = mediaurl.replace(" ", "%20") if "rtmp" in mediaurl: mediaurl = self.GetVerifiableVideoUrl(mediaurl) # In some cases the RTMPT does not work. Let's just try the RTMP first and then add the original if the RTMP version fails. part.AppendMediaStream(mediaurl.replace("rtmpt://", "rtmp://"), 650) elif "rtsp" in mediaurl: part.AppendMediaStream(mediaurl, 600) elif mediaurl.startswith("http") and "m3u8" in mediaurl: # http://iphone.streampower.be/een_nogeo/_definst_/2013/08/1000_130830_placetobe_marjolein_Website_Een_M4V.m4v/playlist.m3u8 mediaurl = mediaurl.rstrip() for s, b in M3u8.GetStreamsFromM3u8(mediaurl, self.proxy): part.AppendMediaStream(s, b) else: Logger.Warning("Media url was not recognised: %s", mediaurl) item.complete = True return item
def __UpdateVideo(self, item, data): regex = 'data-file="([^"]+)' m3u8Url = Regexer.DoRegex(regex, data)[-1] if ".m3u8" not in m3u8Url: Logger.Info("Not a direct M3u8 file. Need to log in") url = "https://api.viervijfzes.be/content/%s" % (m3u8Url, ) # We need to log in if not self.loggedOn: self.LogOn() # add authorization header authenticationHeader = { "authorization": self.__idToken, "content-type": "application/json" } data = UriHandler.Open(url, proxy=self.proxy, additionalHeaders=authenticationHeader) jsonData = JsonHelper(data) m3u8Url = jsonData.GetValue("video", "S") # Geo Locked? if "geo" in m3u8Url.lower(): # set it for the error statistics item.isGeoLocked = True part = item.CreateNewEmptyMediaPart() for s, b in M3u8.GetStreamsFromM3u8(m3u8Url, self.proxy): if int(b) < 200: Logger.Info("Skipping stream of quality '%s' kbps", b) continue item.complete = True # s = self.GetVerifiableVideoUrl(s) part.AppendMediaStream(s, b) item.complete = True return item
def UpdateVideoItem(self, item): """Updates an existing MediaItem with more data. Arguments: item : MediaItem - the MediaItem that needs to be updated Returns: The original item with more data added to it's properties. Used to update none complete MediaItems (self.complete = False). This could include opening the item's URL to fetch more data and then process that data or retrieve it's real media-URL. The method should at least: * cache the thumbnail to disk (use self.noImage if no thumb is available). * set at least one MediaItemPart with a single MediaStream. * set self.complete = True. if the returned item does not have a MediaItemPart then the self.complete flag will automatically be set back to False. """ Logger.Debug('Starting UpdateVideoItem for %s (%s)', item.name, self.channelName) # load the details. part = item.CreateNewEmptyMediaPart() # prevent the "418 I'm a teapot" error part.HttpHeaders[ "user-agent"] = "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:45.0) Gecko/20100101 Firefox/45.0" for s, b in M3u8.GetStreamsFromM3u8(item.url, self.proxy): part.AppendMediaStream(s, b) item.complete = True return item
def UpdateLiveItem(self, item): # http://services.vrt.be/videoplayer/r/live.json?_1466364209811= channelData = UriHandler.Open( "http://services.vrt.be/videoplayer/r/live.json", proxy=self.proxy) channelData = JsonHelper(channelData) url = None for channelId in channelData.json: if channelId not in item.url: continue else: url = channelData.json[channelId].get("hls") if url is None: Logger.Error("Could not find stream for live channel: %s", item.url) return item Logger.Debug("Found stream url for %s: %s", item, url) part = item.CreateNewEmptyMediaPart() for s, b in M3u8.GetStreamsFromM3u8(url, self.proxy): item.complete = True # s = self.GetVerifiableVideoUrl(s) part.AppendMediaStream(s, b) return item
def UpdateVideoItem(self, item): """ Accepts an item. It returns an updated item. Usually retrieves the MediaURL and the Thumb! It should return a completed item. """ Logger.Debug('Starting UpdateVideoItem for %s (%s)', item.name, self.channelName) # noinspection PyStatementEffect """ data-video-id="1613274" data-video-type="video" data-video-src="http://media.vrtnieuws.net/2013/04/135132051ONL1304255866693.urlFLVLong.flv" data-video-title="Het journaal 1 - 25/04/13" data-video-rtmp-server="rtmp://vrt.flash.streampower.be/vrtnieuws" data-video-rtmp-path="2013/04/135132051ONL1304255866693.urlFLVLong.flv" data-video-rtmpt-server="rtmpt://vrt.flash.streampower.be/vrtnieuws" data-video-rtmpt-path="2013/04/135132051ONL1304255866693.urlFLVLong.flv" data-video-iphone-server="http://iphone.streampower.be/vrtnieuws_nogeo/_definst_" data-video-iphone-path="2013/04/135132051ONL1304255866693.urlMP4_H.264.m4v" data-video-mobile-server="rtsp://mp4.streampower.be/vrt/vrt_mobile/vrtnieuws_nogeo" data-video-mobile-path="2013/04/135132051ONL1304255866693.url3GP_MPEG4.3gp" data-video-sitestat-program="het_journaal_1_-_250413_id_1-1613274" """ # now the mediaurl is derived. First we try WMV data = UriHandler.Open(item.url) descriptions = Regexer.DoRegex('<div class="longdesc"><p>([^<]+)</', data) Logger.Trace(descriptions) for desc in descriptions: item.description = desc data = data.replace("\\/", "/") urls = Regexer.DoRegex(self.mediaUrlRegex, data) part = item.CreateNewEmptyMediaPart() for url in urls: Logger.Trace(url) if url[0] == "src": flv = url[1] bitrate = 750 else: flvServer = url[1] flvPath = url[2] if url[0] == "rtmp-server": flv = "%s//%s" % (flvServer, flvPath) bitrate = 750 elif url[0] == "rtmpt-server": continue #flv = "%s//%s" % (flvServer, flvPath) #flv = self.GetVerifiableVideoUrl(flv) #bitrate = 1500 elif url[0] == "iphone-server": flv = "%s/%s" % (flvServer, flvPath) if not flv.endswith("playlist.m3u8"): flv = "%s/playlist.m3u8" % (flv, ) for s, b in M3u8.GetStreamsFromM3u8(flv, self.proxy): item.complete = True part.AppendMediaStream(s, b) # no need to continue adding the streams continue elif url[0] == "mobile-server": flv = "%s/%s" % (flvServer, flvPath) bitrate = 250 else: flv = "%s/%s" % (flvServer, flvPath) bitrate = 0 part.AppendMediaStream(flv, bitrate) item.complete = True return item
def __UpdateVideoItem(self, item, videoId): # we need a token: token = self.__GetToken() # deviceId = AddonSettings.GetClientId() mediaUrl = "https://vod.medialaan.io/vod/v2/videos/" \ "%s" \ "/watch?deviceId=%s" % ( videoId, uuid.uuid4() ) auth = "apikey=%s&access_token=%s" % (self.__apiKey, token) headers = {"Authorization": auth} data = UriHandler.Open(mediaUrl, proxy=self.proxy, additionalHeaders=headers) jsonData = JsonHelper(data) dashInfo = jsonData.GetValue("response", "dash-cenc") if self.__dashStreamsSupported and dashInfo: Logger.Debug("Using Dash streams to playback") dashInfo = jsonData.GetValue("response", "dash-cenc") licenseUrl = dashInfo["widevineLicenseServerURL"] streamUrl = dashInfo["url"] sessionId = jsonData.GetValue("request", "access_token") licenseHeader = { "merchant": "medialaan", "userId": self.__userId, "sessionId": sessionId } licenseHeader = JsonHelper.Dump(licenseHeader, False) licenseHeaders = "x-dt-custom-data={0}&Content-Type=application/octstream".format(base64.b64encode(licenseHeader)) kodiProps = { "inputstreamaddon": "inputstream.adaptive", "inputstream.adaptive.manifest_type": "mpd", "inputstream.adaptive.license_type": "com.widevine.alpha", "inputstream.adaptive.license_key": "{0}?specConform=true|{1}|R{{SSM}}|".format(licenseUrl, licenseHeaders or "") } part = item.CreateNewEmptyMediaPart() stream = part.AppendMediaStream(streamUrl, 0) # noinspection PyTypeChecker for k, v in kodiProps.iteritems(): stream.AddProperty(k, v) else: Logger.Debug("No Dash streams supported or no Dash streams available. Using M3u8 streams") m3u8Url = jsonData.GetValue("response", "hls-encrypted", "url") if not m3u8Url: m3u8Url = jsonData.GetValue("response", "uri") # m3u8Url = jsonData.GetValue("response", "hls-drm-uri") # not supported by Kodi part = item.CreateNewEmptyMediaPart() # Set the Range header to a proper value to make all streams start at the beginning. Make # sure that a complete TS part comes in a single call otherwise we get stuttering. byteRange = 10 * 1024 * 1024 Logger.Debug("Setting an 'Range' http header of bytes=0-%d to force playback at the start " "of a stream and to include a full .ts part.", byteRange) part.HttpHeaders["Range"] = 'bytes=0-%d' % (byteRange, ) for s, b in M3u8.GetStreamsFromM3u8(m3u8Url, self.proxy): item.complete = True # s = self.GetVerifiableVideoUrl(s) part.AppendMediaStream(s, b) return item
def GetStreamsFromNpo(url, episodeId, proxy=None, headers=None): """ Retrieve NPO Player Live streams from a different number of stream urls. @param url: (String) The url to download @param episodeId: (String) The NPO episode ID @param headers: (dict) Possible HTTP Headers @param proxy: (Proxy) The proxy to use for opening Can be used like this: part = item.CreateNewEmptyMediaPart() for s, b in NpoStream.GetStreamsFromNpo(m3u8Url, self.proxy): item.complete = True # s = self.GetVerifiableVideoUrl(s) part.AppendMediaStream(s, b) """ if url: Logger.Info("Determining streams for url: %s", url) episodeId = url.split("/")[-1] elif episodeId: Logger.Info("Determining streams for VideoId: %s", episodeId) else: Logger.Error("No url or streamId specified!") return [] # we need an hash code tokenJsonData = UriHandler.Open("http://ida.omroep.nl/app.php/auth", noCache=True, proxy=proxy, additionalHeaders=headers) tokenJson = JsonHelper(tokenJsonData) token = tokenJson.GetValue("token") url = "http://ida.omroep.nl/app.php/%s?adaptive=yes&token=%s" % ( episodeId, token) streamData = UriHandler.Open(url, proxy=proxy, additionalHeaders=headers) if not streamData: return [] streamJson = JsonHelper(streamData, logger=Logger.Instance()) streamInfos = streamJson.GetValue("items")[0] Logger.Trace(streamInfos) streams = [] for streamInfo in streamInfos: Logger.Debug("Found stream info: %s", streamInfo) if streamInfo["format"] == "mp3": streams.append((streamInfo["url"], 0)) continue elif streamInfo["contentType"] == "live": Logger.Debug("Found live stream") url = streamInfo["url"] url = url.replace("jsonp", "json") liveUrlData = UriHandler.Open(url, proxy=proxy, additionalHeaders=headers) liveUrl = liveUrlData.strip("\"").replace("\\", "") Logger.Trace(liveUrl) streams += M3u8.GetStreamsFromM3u8(liveUrl, proxy, headers=headers) elif streamInfo["format"] == "hls": m3u8InfoUrl = streamInfo["url"] m3u8InfoData = UriHandler.Open(m3u8InfoUrl, proxy=proxy, additionalHeaders=headers) m3u8InfoJson = JsonHelper(m3u8InfoData, logger=Logger.Instance()) m3u8Url = m3u8InfoJson.GetValue("url") streams += M3u8.GetStreamsFromM3u8(m3u8Url, proxy, headers=headers) elif streamInfo["format"] == "mp4": bitrates = {"hoog": 1000, "normaal": 500} url = streamInfo["url"] if "contentType" in streamInfo and streamInfo[ "contentType"] == "url": mp4Url = url else: url = url.replace("jsonp", "json") mp4UrlData = UriHandler.Open(url, proxy=proxy, additionalHeaders=headers) mp4InfoJson = JsonHelper(mp4UrlData, logger=Logger.Instance()) mp4Url = mp4InfoJson.GetValue("url") bitrate = bitrates.get(streamInfo["label"].lower(), 0) if bitrate == 0 and "/ipod/" in mp4Url: bitrate = 200 elif bitrate == 0 and "/mp4/" in mp4Url: bitrate = 500 streams.append((mp4Url, bitrate)) return streams
def UpdateVideoItem(self, item): """Updates an existing MediaItem with more data. Arguments: item : MediaItem - the MediaItem that needs to be updated Returns: The original item with more data added to it's properties. Used to update none complete MediaItems (self.complete = False). This could include opening the item's URL to fetch more data and then process that data or retrieve it's real media-URL. The method should at least: * cache the thumbnail to disk (use self.noImage if no thumb is available). * set at least one MediaItemPart with a single MediaStream. * set self.complete = True. if the returned item does not have a MediaItemPart then the self.complete flag will automatically be set back to False. """ Logger.Debug('Starting UpdateVideoItem for %s (%s)', item.name, self.channelName) data = UriHandler.Open(item.url, proxy=self.proxy) Logger.Trace(data) if 'livestart":-' in data: Logger.Debug("Live item that has not yet begun.") json = JsonHelper(data, Logger.Instance()) secondsToStart = json.GetValue("video", "livestart") if secondsToStart: secondsToStart = -int(secondsToStart) Logger.Debug("Seconds till livestream: %s", secondsToStart) timeLeft = "%s:%02d:%02d" % (secondsToStart / 3600, (secondsToStart % 3600) / 60, secondsToStart % 60) Logger.Debug("Live items starts at %s", timeLeft) lines = list(LanguageHelper.GetLocalizedString(LanguageHelper.NoLiveStreamId)) lines[-1] = "%s ETA: %s" % (lines[-1], timeLeft) XbmcWrapper.ShowDialog(LanguageHelper.GetLocalizedString(LanguageHelper.NoLiveStreamTitleId), lines) else: XbmcWrapper.ShowDialog(LanguageHelper.GetLocalizedString(LanguageHelper.NoLiveStreamTitleId), LanguageHelper.GetLocalizedString(LanguageHelper.NoLiveStreamId)) return item item.MediaItemParts = [] mediaPart = item.CreateNewEmptyMediaPart() spoofIp = self._GetSetting("spoof_ip", "0.0.0.0") if spoofIp is not None: mediaPart.HttpHeaders["X-Forwarded-For"] = spoofIp # mediaPart.UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:17.0) Gecko/20100101 Firefox/17.0" # isLive = False if '"live":true' in data or "/live/" in item.url: mediaPart.AddProperty("IsLive", "true") Logger.Debug("Live video item found.") # isLive = True else: Logger.Debug("Normal (not live, or possible was live) video item found") # replace items #videos = map(lambda v: self.__ReplaceClist(v), videos) jsonVideoData = JsonHelper(data) videos = jsonVideoData.GetValue("video", "videoReferences") # videos = Regexer.DoRegex(self.mediaUrlRegex, data) for video in videos: playerType = video.get("playerType", "") if "dash" in playerType: continue if video["url"].startswith("rtmp"): # just replace some data in the URL mediaPart.AppendMediaStream(self.GetVerifiableVideoUrl(video["url"]).replace("_definst_", "?slist="), video[1]) elif "m3u8" in video["url"]: Logger.Info("SVTPlay.se m3u8 stream found: %s", video["url"]) # apparently the m3u8 do not work well for server www0.c91001.dna.qbrick.com if "www0.c91001.dna.qbrick.com" in video["url"]: continue # m3u8 we need to parse. Get more streams from this file. videoUrl = video["url"] altIndex = videoUrl.find("m3u8?") # altIndex = videoUrl.find("~uri") if altIndex > 0: videoUrl = videoUrl[0:altIndex + 4] for s, b in M3u8.GetStreamsFromM3u8(videoUrl, self.proxy, headers=mediaPart.HttpHeaders): item.complete = True mediaPart.AppendMediaStream(s, b) elif "f4m" in video["url"]: Logger.Info("SVTPlay.se manifest.f4m stream found: %s", video["url"]) #if "manifest.f4m?start=" in video["url"]: # # this was a live stream, convert it to M3u8 # # http://svt06-lh.akamaihd.net/z/svt06_0@77501/manifest.f4m?start=1386566700&end=1386579600 # # to # # http://svt06hls-lh.akamaihd.net/i/svt06_0@77501/master.m3u8?__b__=563&start=1386566700&end=1386579600 # m3u8Url = video["url"].replace("-lh.akamaihd.net/z", "hls-lh.akamaihd.net/i").replace("manifest.f4m?", "master.m3u8?__b__=563&") # Logger.Info("Found f4m stream for an old Live stream. Converting to M3U8:\n%s -to -\n%s", video["url"], m3u8Url) # videos.append((m3u8Url, 0)) # continue # for now we skip these as they do not yet work with XBMC continue # http://svtplay8m-f.akamaihd.net/z/se/krypterat/20120830/254218/LILYHAMMER-003A-mp4-,c,d,b,e,-v1-4bc7ecc090b19c82.mp4.csmil/manifest.f4m?hdcore=2.8.0&g=TZOMVRTEILSE #videoDataUrl = video["url"] # videoUrl = "%s?hdcore=2.8.0&g=TZOMVRTEILSE" % (videoDataUrl,) #videoUrl = "%s?hdcore=2.10.3&g=IJGTWSVWPPKH" % (videoDataUrl,) # metaData = UriHandler.Open(videoUrl, proxy=self.proxy, referer=self.swfUrl) # Logger.Debug(metaData) # The referer seems to be unimportant # header = "referer=%s" % (urllib.quote(self.swfUrl),) # videoUrl = "%s|%s" % (videoUrl, header) #mediaPart.AppendMediaStream(videoUrl, video[1]) else: Logger.Info("SVTPlay.se standard HTTP stream found.") # else just use the URL mediaPart.AppendMediaStream(video["url"], video["bitrate"]) subtitle = Regexer.DoRegex('"url":"([^"]+.wsrt)"|"url":"(http://media.svt.se/download/[^"]+.m3u8)', data) for sub in subtitle: if sub[-1]: Logger.Info("Found M3u8 subtitle, replacing with WSRT") start, name, index = sub[-1].rsplit("/", 2) subUrl = "%s/%s/%s.wsrt" % (start, name, name) else: subUrl = sub[0] mediaPart.Subtitle = subtitlehelper.SubtitleHelper.DownloadSubtitle(subUrl, format="srt", proxy=self.proxy) item.complete = True return item
def UpdateChannelItem(self, item): """ Updates an existing MediaItem with more data. Arguments: item : MediaItem - the MediaItem that needs to be updated date : String - the json content of the item's URL Returns: The original item with more data added to it's properties. Used to update none complete MediaItems (self.complete = False). This could include opening the item's URL to fetch more data and then process that data or retrieve it's real media-URL. The method should at least: * cache the thumbnail to disk (use self.noImage if no thumb is available). * set at least one MediaItemPart with a single MediaStream. * set self.complete = True. if the returned item does not have a MediaItemPart then the self.complete flag will automatically be set back to False. """ Logger.Debug('Starting UpdateChannelItem for %s (%s)', item.name, self.channelName) data = UriHandler.Open(item.url, proxy=self.proxy) json = JsonHelper(data, logger=Logger.Instance()) videos = json.GetValue("videoReferences") Logger.Trace(videos) item.MediaItemParts = [] part = item.CreateNewEmptyMediaPart() spoofIp = self._GetSetting("spoof_ip", "0.0.0.0") if spoofIp is not None: part.HttpHeaders["X-Forwarded-For"] = spoofIp for video in videos: # bitrate = video['bitrate'] url = video['url'] # player = video['playerType'] # if "ios" in player: # bitrate += 1 if "akamaihd" in url and "f4m" in url: continue # these are not supported as they return a 503 error #noinspection PyUnreachableCode #url = url.replace("/z/", "/i/").replace("/manifest.f4m", "/master.m3u8") if len(filter(lambda s: s.Url == url, part.MediaStreams)) > 0: Logger.Debug("Skippping duplicate Stream url: %s", url) continue if "m3u8" in url: for s, b in M3u8.GetStreamsFromM3u8(url, proxy=self.proxy, headers=part.HttpHeaders): part.AppendMediaStream(s, b) else: part.AppendMediaStream(url, 0) item.complete = True return item
def UpdateVideoItem(self, item): """Updates an existing MediaItem with more data. Arguments: item : MediaItem - the MediaItem that needs to be updated Returns: The original item with more data added to it's properties. Used to update none complete MediaItems (self.complete = False). This could include opening the item's URL to fetch more data and then process that data or retrieve it's real media-URL. The method should at least: * cache the thumbnail to disk (use self.noImage if no thumb is available). * set at least one MediaItemPart with a single MediaStream. * set self.complete = True. if the returned item does not have a MediaItemPart then the self.complete flag will automatically be set back to False. """ Logger.Debug('Starting UpdateVideoItem for %s (%s)', item.name, self.channelName) data = UriHandler.Open(item.url, proxy=self.proxy, additionalHeaders=item.HttpHeaders) videoId = Regexer.DoRegex('data-video="([^"]+)"', data)[-1] url = "https://mediazone.vrt.be/api/v1/canvas/assets/%s" % (videoId, ) data = UriHandler.Open(url, proxy=self.proxy, additionalHeaders=item.HttpHeaders) json = JsonHelper(data) geoLocked = str(json.GetValue("metaInfo", "allowedRegion").lower()) hideGeoLocked = AddonSettings.HideGeoLockedItemsForLocation(geoLocked) if hideGeoLocked: geoRegion = AddonSettings.HideGeoLockedItemsForLocation( geoLocked, True) Logger.Warning( "Found GEO Locked item for region '%s'. Current region is '%s'", geoLocked, geoRegion) return item part = item.CreateNewEmptyMediaPart() for video in json.GetValue("targetUrls"): videoType = video["type"].lower() url = video["url"] if videoType == "progressive_download": bitrate = 1000 elif videoType == "hls": for s, b in M3u8.GetStreamsFromM3u8(url, self.proxy): # s = self.GetVerifiableVideoUrl(s) part.AppendMediaStream(s, b) continue elif videoType == "rtmp": # url=rtmp://vod.stream.vrt.be/mediazone_canvas/_definst_/mp4:2015/11/mz-ast-79a551d6-2621-4a0f-9af0-a272fb0954db-1/video_1296.mp4 url = url.replace("_definst_/mp4:", "?slist=") bitrate = 1100 else: Logger.Debug("Found unhandled stream type '%s':%s", videoType, url) continue part.AppendMediaStream(url, bitrate) item.complete = True return item
def UpdateVideoItem(self, item): """Updates an existing MediaItem with more data. Arguments: item : MediaItem - the MediaItem that needs to be updated Returns: The original item with more data added to it's properties. Used to update none complete MediaItems (self.complete = False). This could include opening the item's URL to fetch more data and then process that data or retrieve it's real media-URL. The method should at least: * set at least one MediaItemPart with a single MediaStream. * set self.complete = True. if the returned item does not have a MediaItemPart then the self.complete flag will automatically be set back to False. """ Logger.Debug('Starting UpdateVideoItem for %s (%s)', item.name, self.channelName) # User-agent (and possible other headers), should be consistent over all M3u8 requests (See #864) headers = { # "User-Agent": AddonSettings.GetUserAgent(), "User-Agent": "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-GB; rv:1.9.2.13) Gecko/20101203 Firefox/3.6.13 (.NET CLR 3.5.30729)", # "Origin": "https://www.viafree.se" } if self.localIP: headers.update(self.localIP) if True: data = UriHandler.Open(item.url, proxy=self.proxy, additionalHeaders=headers or None) else: from debug.router import Router data = Router.GetVia("se", item.url, self.proxy) json = JsonHelper(data) # see if there was an srt already if item.MediaItemParts: part = item.MediaItemParts[0] if part.Subtitle and part.Subtitle.endswith(".vtt"): part.Subtitle = SubtitleHelper.DownloadSubtitle( part.Subtitle, format="webvtt", proxy=self.proxy) else: part.Subtitle = SubtitleHelper.DownloadSubtitle( part.Subtitle, format="dcsubtitle", proxy=self.proxy) else: part = item.CreateNewEmptyMediaPart() for q in ("high", 3500), ("hls", 2700), ("medium", 2100): url = json.GetValue("streams", q[0]) Logger.Trace(url) if not url: continue if ".f4m" in url: # Kodi does not like the f4m streams continue if url.startswith("http") and ".m3u8" in url: for s, b in M3u8.GetStreamsFromM3u8(url, self.proxy, headers=headers): part.AppendMediaStream(s, b) if not part.MediaStreams and "manifest.m3u8": Logger.Warning( "No streams found in %s, trying alternative with 'master.m3u8'", url) url = url.replace("manifest.m3u8", "master.m3u8") for s, b in M3u8.GetStreamsFromM3u8(url, self.proxy, headers=headers): part.AppendMediaStream(s, b) # check for subs # https://mtgxse01-vh.akamaihd.net/i/201703/13/DCjOLN_1489416462884_427ff3d3_,48,260,460,900,1800,2800,.mp4.csmil/master.m3u8?__b__=300&hdnts=st=1489687185~exp=3637170832~acl=/*~hmac=d0e12e62c219d96798e5b5ef31b11fa848724516b255897efe9808c8a499308b&cc1=name=Svenska%20f%C3%B6r%20h%C3%B6rselskadade~default=no~forced=no~lang=sv~uri=https%3A%2F%2Fsubstitch.play.mtgx.tv%2Fsubtitle%2Fconvert%2Fxml%3Fsource%3Dhttps%3A%2F%2Fcdn-subtitles-mtgx-tv.akamaized.net%2Fpitcher%2F20xxxxxx%2F2039xxxx%2F203969xx%2F20396967%2F20396967-swt.xml%26output%3Dm3u8 # https://cdn-subtitles-mtgx-tv.akamaized.net/pitcher/20xxxxxx/2039xxxx/203969xx/20396967/20396967-swt.xml&output=m3u8 if "uri=" in url and not part.Subtitle: Logger.Debug("Extracting subs from M3u8") subUrl = url.rsplit("uri=")[-1] subUrl = HtmlEntityHelper.UrlDecode(subUrl) subData = UriHandler.Open(subUrl, proxy=self.proxy) # subUrl = None subs = filter(lambda line: line.startswith("http"), subData.split("\n")) # for line in subData.split("\n"): # if line.startswith("http"): # subUrl = line # break if subs: part.Subtitle = SubtitleHelper.DownloadSubtitle( subs[0], format='webvtt', proxy=self.proxy) elif url.startswith("rtmp"): # rtmp://mtgfs.fplive.net/mtg/mp4:flash/sweden/tv3/Esport/Esport/swe_skillcompetition.mp4.mp4 oldUrl = url if not url.endswith(".flv") and not url.endswith(".mp4"): url += '.mp4' if "/mp4:" in url: # in this case we need to specifically set the path # url = url.replace('/mp4:', '//') -> don't do this, but specify the path server, path = url.split("mp4:", 1) url = "%s playpath=mp4:%s" % (server, path) if oldUrl != url: Logger.Debug("Updated URL from - to:\n%s\n%s", oldUrl, url) url = self.GetVerifiableVideoUrl(url) part.AppendMediaStream(url, q[1]) else: part.AppendMediaStream(url, q[1]) part.HttpHeaders.update(headers) if part.MediaStreams: item.complete = True Logger.Trace("Found mediaurl: %s", item) return item
def UpdateVideoItem(self, item): """ Accepts an item. It returns an updated item. Usually retrieves the MediaURL and the Thumb! It should return a completed item. """ Logger.Debug('Starting UpdateVideoItem for %s (%s)', item.name, self.channelName) # rtmpt://vrt.flash.streampower.be/een//2011/07/1000_110723_getipt_neefs_wiels_Website_EEN.flv # http://www.een.be/sites/een.be/modules/custom/vrt_video/player/player_4.3.swf # now the mediaurl is derived. First we try WMV data = UriHandler.Open(item.url, proxy=self.proxy) part = item.CreateNewEmptyMediaPart() if "mediazone.vrt.be" not in item.url: # Extract actual media data videoId = Regexer.DoRegex('data-video=[\'"]([^"\']+)[\'"]', data)[0] # if videoId.startswith("http"): # Logger.Info("Found direct stream. Not processing any further.") # part.AppendMediaStream(videoId, 0) # item.complete = True # return item url = "https://mediazone.vrt.be/api/v1/een/assets/%s" % (videoId, ) data = UriHandler.Open(url, proxy=self.proxy) json = JsonHelper(data) urls = json.GetValue("targetUrls") for urlInfo in urls: Logger.Trace(urlInfo) if urlInfo["type"].lower() != "hls": continue hlsUrl = urlInfo["url"] for s, b in M3u8.GetStreamsFromM3u8(hlsUrl, self.proxy): part.AppendMediaStream(s, b) # urls = Regexer.DoRegex(self.mediaUrlRegex, data) # Logger.Trace(urls) # part = item.CreateNewEmptyMediaPart() # for url in urls: # if not url[1] == "": # mediaurl = "%s//%s" % (url[0], url[1]) # the extra slash in the url causes the application name in the RTMP stream to be "een" instead of "een/2011" # else: # mediaurl = url[0] # # mediaurl = mediaurl.replace(" ", "%20") # # if "rtmp" in mediaurl: # mediaurl = self.GetVerifiableVideoUrl(mediaurl) # # In some cases the RTMPT does not work. Let's just try the RTMP first and then add the original if the RTMP version fails. # part.AppendMediaStream(mediaurl.replace("rtmpt://", "rtmp://"), 650) # elif "rtsp" in mediaurl: # part.AppendMediaStream(mediaurl, 600) # elif mediaurl.startswith("http") and "m3u8" in mediaurl: # # http://iphone.streampower.be/een_nogeo/_definst_/2013/08/1000_130830_placetobe_marjolein_Website_Een_M4V.m4v/playlist.m3u8 # mediaurl = mediaurl.rstrip() # for s, b in M3u8.GetStreamsFromM3u8(mediaurl, self.proxy): # part.AppendMediaStream(s, b) # else: # Logger.Warning("Media url was not recognised: %s", mediaurl) item.complete = True return item