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 AddPageItems(self, data): """ Adds page items to the main listing @param data: the Parsed Data @return: a tuple of data and items """ Logger.Info("Performing Pre-Processing") items = [] json = JsonHelper(data) totalResults = json.GetValue("totalResults") fromValue = json.GetValue("from") sizeValue = json.GetValue("size") if fromValue + sizeValue < totalResults: morePages = LanguageHelper.GetLocalizedString( LanguageHelper.MorePages) url = self.parentItem.url.split('?')[0] url = "%s?size=%s&from=%s&sort=Nieuwste" % (url, sizeValue, fromValue + sizeValue) Logger.Debug("Adding next-page item from %s to %s", fromValue + sizeValue, fromValue + sizeValue + sizeValue) nextPage = mediaitem.MediaItem(morePages, url) nextPage.icon = self.parentItem.icon nextPage.fanart = self.parentItem.fanart nextPage.thumb = self.parentItem.thumb nextPage.dontGroup = True items.append(nextPage) Logger.Debug("Pre-Processing finished") return json, items
def UpdateVideoApiItem(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") subtitles = json.GetValue("subtitleReferences") Logger.Trace(videos) return self.__UpdateItemFromVideoReferences(item, videos, subtitles)
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") if stream is None: stream = json.GetValue("mzsource", "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 UpdateVideoItem(self, item): 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) part = item.CreateNewEmptyMediaPart() part.Subtitle = NpoStream.GetSubtitle(json.GetValue("mid"), proxy=self.proxy) for stream in json.GetValue("videoStreams"): if not stream["url"].startswith("odi"): part.AppendMediaStream(stream["url"], stream["bitrate"] / 1000) item.complete = True if item.HasMediaItemParts(): return item for s, b in NpoStream.GetStreamsFromNpo(None, json.GetValue("mid"), proxy=self.proxy): item.complete = True part.AppendMediaStream(s, b) 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) metaData = UriHandler.Open(item.url, proxy=self.proxy, referer=self.baseUrl) meta = JsonHelper(metaData) streamParts = meta.GetValue("feed", "items") for streamPart in streamParts: streamUrl = streamPart["group"]["content"] # streamUrl = streamUrl.replace("{device}", "ipad") streamUrl = streamUrl.replace("{device}", "html5") streamUrl = "%s&format=json" % (streamUrl, ) streamData = UriHandler.Open(streamUrl, proxy=self.proxy) stream = JsonHelper(streamData) # subUrls = stream.GetValue("package", "video", "item", 0, "transcript", 0, "typographic") part = item.CreateNewEmptyMediaPart() # m3u8Url = stream.GetValue("package", "video", "item", 0, "rendition", 0, "src") # for s, b in M3u8.GetStreamsFromM3u8(m3u8Url, self.proxy): # item.complete = True # part.AppendMediaStream(s, b) rtmpDatas = stream.GetValue("package", "video", "item", 0, "rendition") for rtmpData in rtmpDatas: rtmpUrl = rtmpData["src"] rtmpUrl = rtmpUrl.replace("rtmpe://", "rtmp://") bitrate = rtmpData["bitrate"] part.AppendMediaStream(rtmpUrl, bitrate) item.complete = True Logger.Trace("Media url: %s", item) 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 ListSomeVideos(self, data): """ If there was a Lastest section in the data return those video files """ items = [] if not self.__showSomeVideosInListing: return data, items jsonData = JsonHelper(data) sections = jsonData.GetValue("relatedVideoContent", "relatedVideosAccordion") sections = filter(lambda s: s['type'] not in self.__excludedTabs, sections) Logger.Debug("Found %s folders/tabs", len(sections)) if len(sections) == 1: # we should exclude that tab from the folders list and show the videos here self.__listedRelatedTab = sections[0]["type"] # otherwise the default "RELATED_VIDEO_TABS_LATEST" is used Logger.Debug("Excluded tab '%s' which will be show as videos", self.__listedRelatedTab) for section in sections: if not section["type"] == self.__listedRelatedTab: continue for videoData in section['videos']: items.append(self.CreateJsonItem(videoData)) return data, items
def LoadChannelData(self, data): """ Adds the channel items to the listing. @param data: The data to use. Returns a list of MediaItems that were retrieved. """ items = [] # data = UriHandler.Open("https://www.svtplay.se/api/channel_page", proxy=self.proxy, noCache=True) now = datetime.datetime.now() try: serverTime = UriHandler.Open("https://www.svtplay.se/api/server_time", proxy=self.proxy, noCache=True) serverTimeJson = JsonHelper(serverTime) serverTime = serverTimeJson.GetValue("time") except: Logger.Error("Error determining server time", exc_info=True) serverTime = "%04d-%02d-%02dT%02d:%02d:%02d" % (now.year, now.month, now.day, now.hour, now.minute, now.second) data = UriHandler.Open( "https://www.svtplay.se/api/channel_page?now=%s" % (serverTime, ), proxy=self.proxy) return data, items
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 GetScheduleData(self, data): """Performs pre-process actions for data processing Arguments: data : string - the retrieve data that was loaded for the current item and URL. Returns: A tuple of the data and a list of MediaItems that were generated. Accepts an data from the ProcessFolderList method, BEFORE the items are processed. Allows setting of parameters (like title etc) for the channel. Inside this method the <data> could be changed and additional items can be created. The return values should always be instantiated in at least ("", []). """ Logger.Info("Performing Pre-Processing") items = [] json = JsonHelper(data) self.scheduleData = json.GetValue("schedules") Logger.Debug("Pre-Processing finished") return data, items
def UpdateVideoItem(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) # sources part = item.CreateNewEmptyMediaPart() # high, web, mobile, url mediaSources = mediaInfo.json.get("sources", {}) for quality in mediaSources: url = mediaSources[quality] if quality == "high": bitrate = 2000 elif quality == "web": bitrate = 800 elif quality == "mobile": bitrate = 400 else: bitrate = 0 part.AppendMediaStream(url, bitrate) # geoLocRestriction item.isGeoLocked = not mediaInfo.GetValue("geoLocRestriction", fallback="world") == "world" item.complete = True return item
def UpdateVideoEpgItemJson(self, item): data = UriHandler.Open(item.url, proxy=self.proxy, additionalHeaders=self.httpHeaders) jsonData = JsonHelper(data) videoId = jsonData.GetValue("response", "videos", 0, "id") return self.__UpdateVideoItem(item, videoId)
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 the item """ data = UriHandler.Open(item.url, proxy=self.proxy) baseEncode = Regexer.DoRegex(self.mediaUrlRegex, data)[-1] jsonData = EncodingHelper().DecodeBase64(baseEncode) json = JsonHelper(jsonData, logger=Logger.Instance()) Logger.Trace(json) # "flv": "http://media.dumpert.nl/flv/e2a926ff_10307954_804223649588516_151552487_n.mp4.flv", # "tablet": "http://media.dumpert.nl/tablet/e2a926ff_10307954_804223649588516_151552487_n.mp4.mp4", # "mobile": "http://media.dumpert.nl/mobile/e2a926ff_10307954_804223649588516_151552487_n.mp4.mp4", item.MediaItemParts = [] part = item.CreateNewEmptyMediaPart() streams = json.GetValue() for key in streams: if key == "flv": part.AppendMediaStream(streams[key], 1000) elif key == "tablet": part.AppendMediaStream(streams[key], 800) elif key == "mobile": part.AppendMediaStream(streams[key], 450) else: Logger.Debug("Key '%s' was not used", key) item.complete = True Logger.Trace("VideoItem updated: %s", item) 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): """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 FromJson(path, version="x.x.x.x"): channelInfos = [] # Logger.Trace("Using JSON reader for %s", path) jsonFile = open(path) jsonData = jsonFile.read() jsonFile.close() json = JsonHelper(jsonData, logger=Logger.Instance()) channels = json.GetValue("channels") if "settings" in json.json: settings = json.GetValue("settings") else: settings = [] Logger.Debug("Found %s channels and %s settings in %s", len(channels), len(settings), path) for channel in channels: channelInfo = ChannelInfo(channel["guid"], channel["name"], channel["description"], channel["icon"], channel["category"], path, # none required items channel.get("channelcode", None), channel.get("sortorder", 255), channel.get("language", None), eval(channel.get("compatible", "Environments.All")), channel.get("fanart", None)) channelInfo.firstTimeMessage = channel.get("message", None) # Disable spoofing for the moment # channelInfo.localIPSupported = channel.get("localIPSupported", False) channelInfo.settings = settings channelInfo.version = version # validate a bit if channelInfo.channelCode == "None": raise Exception("'None' as channelCode") if channelInfo.language == "None": raise Exception("'None' as language") channelInfos.append(channelInfo) return channelInfos
def SelectVideoSection(self, data): """Performs pre-process actions for data processing Arguments: data : string - the retrieve data that was loaded for the current item and URL. Returns: A tuple of the data and a list of MediaItems that were generated. Accepts an data from the ProcessFolderList method, BEFORE the items are processed. Allows setting of parameters (like title etc) for the channel. Inside this method the <data> could be changed and additional items can be created. The return values should always be instantiated in at least ("", []). """ Logger.Info("Performing Pre-Processing") items = [] endOfSection = data.rfind('<div class="grid-4">') if endOfSection > 0: data = data[:endOfSection] # find the first main video jsonData = Regexer.DoRegex(self.mediaUrlRegex, data) if not jsonData: Logger.Debug("No show data found as JSON") return data, items Logger.Trace(jsonData[0]) json = JsonHelper(jsonData[0]) title = json.GetValue("title") url = json.GetValue("source", "hls") item = mediaitem.MediaItem(title, url) item.type = 'video' item.description = json.GetValue("description", fallback=None) item.thumb = json.GetValue("image", fallback=self.noImage) item.fanart = self.parentItem.fanart item.complete = False items.append(item) Logger.Debug("Pre-Processing finished") return data, items
def ParseMainList(self, returnData=False): """Parses the mainlist of the channel and returns a list of MediaItems This method creates a list of MediaItems that represent all the different programs that are available in the online source. The list is used to fill the ProgWindow. Keyword parameters: returnData : [opt] boolean - If set to true, it will return the retrieved data as well Returns a list of MediaItems that were retrieved. """ items = [] if len(self.mainListItems) > 1: if returnData: return self.mainListItems, "" else: return self.mainListItems data = UriHandler.Open(self.mainListUri, proxy=self.proxy, additionalHeaders=self.httpHeaders) Logger.Trace("Retrieved %s chars as mainlist data", len(data)) # first process folder items. watch = stopwatch.StopWatch('Mainlist', Logger.Instance()) episodeItems = [] if not self.episodeItemRegex == "" and self.episodeItemRegex is not None: Logger.Trace("Using Regexer for episodes") episodeItems = Regexer.DoRegex(self.episodeItemRegex, data) watch.Lap("Mainlist Regex complete") elif self.episodeItemJson is not None: Logger.Trace("Using JsonHelper for episodes") json = JsonHelper(data, Logger.Instance()) episodeItems = json.GetValue(*self.episodeItemJson) watch.Lap("Mainlist Json complete") Logger.Debug('Starting CreateEpisodeItem for %s items', len(episodeItems)) for episodeItem in episodeItems: Logger.Trace('Starting CreateEpisodeItem for %s', self.channelName) tmpItem = self.CreateEpisodeItem(episodeItem) # catch the return of None if tmpItem: items.append(tmpItem) # Filter out the duplicates using the HASH power of a set items = list(set(items)) watch.Lap("MediaItem creation complete") self.mainListItems = items if returnData: return items, data else: return items
def AddCategories(self, data): """ Add categories to the main listing @param data: the Parsed Data @return: a tuple of data and items """ Logger.Info("Performing Pre-Processing") items = [] cat = mediaitem.MediaItem( "\b.: Categorieën :.", "http://m.schooltv.nl/api/v1/categorieen.json?size=100") cat.thumb = self.noImage cat.icon = self.icon cat.fanart = self.fanart cat.complete = True cat.dontGroup = True items.append(cat) tips = mediaitem.MediaItem( "\b.: Tips :.", "http://m.schooltv.nl/api/v1/programmas/tips.json?size=100") tips.thumb = self.noImage tips.icon = self.icon tips.fanart = self.fanart tips.complete = True tips.dontGroup = True items.append(tips) data = JsonHelper(data) ages = mediaitem.MediaItem("\b.: Leeftijden :.", "") ages.thumb = self.noImage ages.icon = self.icon ages.fanart = self.fanart ages.complete = True ages.dontGroup = True for age in ("0-4", "5-6", "7-8", "9-12", "13-15", "16-18"): ageItem = mediaitem.MediaItem( "%s Jaar" % (age, ), "http://m.schooltv.nl/api/v1/leeftijdscategorieen/%s/afleveringen.json?" "size=%s&sort=Nieuwste" % (age, self.__PageSize)) ageItem.thumb = self.noImage ageItem.icon = self.icon ageItem.fanart = self.fanart ageItem.complete = True ageItem.dontGroup = True ages.items.append(ageItem) # We should list programs instead of videos, so just prefill them here. for program in data.GetValue(): if age in program['ageGroups']: ageItem.items.append(self.CreateEpisodeItem(program)) items.append(ages) Logger.Debug("Pre-Processing finished") return data, items
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) data = UriHandler.Open(item.url, proxy=self.proxy) javascriptUrls = Regexer.DoRegex( '<script type="text/javascript" src="(http://l1.bbvms.com/p/standaard/c/\d+.js)">', data) dataUrl = None for javascriptUrl in javascriptUrls: dataUrl = javascriptUrl if not dataUrl: return item data = UriHandler.Open(dataUrl, proxy=self.proxy) jsonData = Regexer.DoRegex( 'clipData\W*:([\w\W]{0,10000}?\}),"playerWidth', data) Logger.Trace(jsonData) json = JsonHelper(jsonData[0], logger=Logger.Instance()) Logger.Trace(json) streams = json.GetValue("assets") item.MediaItemParts = [] part = item.CreateNewEmptyMediaPart() for stream in streams: url = stream.get("src", None) if "://" not in url: url = "http://static.l1.nl/bbw%s" % (url, ) bitrate = stream.get("bandwidth", None) if url: part.AppendMediaStream(url, bitrate) if not item.thumb and json.GetValue("thumbnails"): url = json.GetValue("thumbnails")[0].get("src", None) if url and "http:/" not in url: url = "%s%s" % (self.baseUrl, url) item.thumb = url item.complete = True 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 AddLiveChannelAndFetchAllData(self, data): data, items = self.AddLiveChannel(data) # The current issue with this is that the API is providing only the videos and not # the full episodes. json = JsonHelper(data) jsonItems = json.GetValue("response", "items") count = json.GetValue("response", "total") for i in range(100, count, 100): url = "%s&from=%s" % (self.mainListUri, i) Logger.Debug("Retrieving more items from: %s", url) moreData = UriHandler.Open(url, proxy=self.proxy) moreJson = JsonHelper(moreData) moreItems = moreJson.GetValue("response", "items") if moreItems: jsonItems += moreItems return json, items
def UpdateVideoHtmlItem(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. """ data = UriHandler.Open(item.url, proxy=self.proxy) # Logger.Trace(data) data = self.ExtractJsonData(data)[0] json = JsonHelper(data, logger=Logger.Instance()) # check for direct streams: streams = json.GetValue("videoTitlePage", "video", "videoReferences") subtitles = json.GetValue("videoTitlePage", "video", "subtitles") if streams: Logger.Info("Found stream information within HTML data") return self.__UpdateItemFromVideoReferences(item, streams, subtitles) videoId = json.GetValue("videoPage", "video", "id") # in case that did not work, try the old version. if not videoId: videoId = json.GetValue("videoPage", "video", "programVersionId") if videoId: # item.url = "https://www.svt.se/videoplayer-api/video/%s" % (videoId, ) item.url = "https://api.svt.se/videoplayer-api/video/%s" % (videoId, ) return self.UpdateVideoApiItem(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) 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 AddVideoPageItemsJson(self, data): items = [] json = JsonHelper(data) currentOffset = json.GetValue("request", "offset") or 0 itemsOnThisPage = len(json.GetValue("response", "items") or []) totalItems = json.GetValue("response", "total") if totalItems > currentOffset + itemsOnThisPage: # add next page items newOffset = currentOffset + itemsOnThisPage seriesId = json.GetValue("request", "parentSeriesOID")[0] url = "https://vod.medialaan.io/api/1.0/list?app_id=%s&parentSeriesOID=%s&offset=%s" % (self.__app, seriesId, newOffset) more = LanguageHelper.GetLocalizedString(LanguageHelper.MorePages) item = MediaItem(more, url) item.thumb = self.noImage item.icon = self.icon item.fanart = self.parentItem.fanart item.complete = True items.append(item) return json, items
def __FetchActualStream(idaData, proxy): actualStreamJson = JsonHelper(idaData, Logger.Instance()) m3u8Url = actualStreamJson.GetValue('stream') Logger.Debug("Fetching redirected stream for: %s", m3u8Url) # now we have the m3u8 URL, but it will do a HTML 302 redirect (headData, m3u8Url) = UriHandler.Header(m3u8Url, proxy=proxy) # : @UnusedVariables Logger.Debug("Found redirected stream: %s", m3u8Url) return m3u8Url
def MergeSeasonData(self, data): items = [] jsonData = JsonHelper(data) seasonFolders = jsonData.GetValue("context", "dispatcher", "stores", "ContentPageProgramStore", "format", "videos") for season in seasonFolders: for video in seasonFolders[season]['program']: items.append(self.CreateJsonVideoItem(video)) return data, items
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