def get_stream_info(self, item, mzid, live=False, hls_over_dash=False): # NOSONAR """ Updates an item with Vualto stream data. :param MediaItem item: The Mediaitem to update :param str mzid: The MZ ID of the stream :param bool live: Indicator if the stream is live or not :param bool hls_over_dash: Should we prefer HLS over Dash? :return: An updated MediaItem :rtype: MediaItem """ # We need a player token token_data = UriHandler.open("https://media-services-public.vrt.be/" "vualto-video-aggregator-web/rest/external/v1/tokens", data="", additional_headers={"Content-Type": "application/json"}) token = JsonHelper(token_data).get_value("vrtPlayerToken") asset_url = "https://media-services-public.vrt.be/vualto-video-aggregator-web/rest/" \ "external/v1/videos/{0}?vrtPlayerToken={1}&client={2}" \ .format(mzid, HtmlEntityHelper.url_encode(token), self.client_id) asset_data = UriHandler.open(asset_url, no_cache=True) asset_data = JsonHelper(asset_data) drm_key = asset_data.get_value("drm") drm_protected = drm_key is not None adaptive_available = AddonSettings.use_adaptive_stream_add_on( with_encryption=drm_protected, channel=self.channel) part = item.create_new_empty_media_part() srt = None # see if we prefer hls over dash hls_prio = 2 if hls_over_dash else 0 for target_url in asset_data.get_value("targetUrls"): video_type = target_url["type"] video_url = target_url["url"] if video_type == "hls_aes" and drm_protected and adaptive_available: # no difference in encrypted or not. Logger.debug("Found HLS AES encrypted stream and a DRM key") stream = part.append_media_stream(video_url, hls_prio) M3u8.set_input_stream_addon_input(stream) elif video_type == "hls" and not drm_protected: # no difference in encrypted or not. if adaptive_available: Logger.debug("Found standard HLS stream and without DRM protection") stream = part.append_media_stream(video_url, hls_prio) M3u8.set_input_stream_addon_input(stream) else: m3u8_data = UriHandler.open(video_url) for s, b, a in M3u8.get_streams_from_m3u8(video_url, play_list_data=m3u8_data, map_audio=True): item.complete = True if a: audio_part = a.rsplit("-", 1)[-1] audio_part = "-%s" % (audio_part,) s = s.replace(".m3u8", audio_part) part.append_media_stream(s, b) srt = M3u8.get_subtitle(video_url, play_list_data=m3u8_data) if not srt or live: # If there is not SRT don't download it. If it a live stream with subs, # don't use it as it is not supported by Kodi continue srt = srt.replace(".m3u8", ".vtt") part.Subtitle = SubtitleHelper.download_subtitle(srt, format="webvtt") elif video_type == "mpeg_dash" and adaptive_available: if not drm_protected: Logger.debug("Found standard MPD stream and without DRM protection") stream = part.append_media_stream(video_url, 1) Mpd.set_input_stream_addon_input(stream) else: stream = part.append_media_stream(video_url, 1) encryption_json = '{{"token":"{0}","drm_info":[D{{SSM}}],"kid":"{{KID}}"}}' \ .format(drm_key) encryption_key = Mpd.get_license_key( key_url="https://widevine-proxy.drm.technology/proxy", key_type="D", key_value=encryption_json, key_headers={"Content-Type": "text/plain;charset=UTF-8"} ) Mpd.set_input_stream_addon_input(stream, license_key=encryption_key) if video_type.startswith("hls") and srt is None: srt = M3u8.get_subtitle(video_url) if not srt or live: # If there is not SRT don't download it. If it a live stream with subs, # don't use it as it is not supported by Kodi continue srt = srt.replace(".m3u8", ".vtt") part.Subtitle = SubtitleHelper.download_subtitle(srt, format="webvtt") item.complete = True return item
def update_video_item(self, item): """ Updates an existing MediaItem with more data. 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. :param MediaItem item: the original MediaItem that needs updating. :return: The original item with more data added to it's properties. :rtype: MediaItem """ Logger.debug('Starting update_video_item for %s (%s)', item.name, self.channelName) # noinspection PyStatementEffect """ C:\temp\rtmpdump-2.3>rtmpdump.exe -z -o test.flv -n "cp70051.edgefcs.net" -a "tv 4ondemand" -y "mp4:/mp4root/2010-06-02/pid2780626_1019976_T3MP48_.mp4?token=c3Rh cnRfdGltZT0yMDEwMDcyNjE2NDYyNiZlbmRfdGltZT0yMDEwMDcyNjE2NDgyNiZkaWdlc3Q9ZjFjN2U1 NTRiY2U5ODMxMDMwYWQxZWEwNzNhZmUxNjI=" -l 2 C:\temp\rtmpdump-2.3>rtmpdump.exe -z -o test.flv -r rtmpe://cp70051.edgefcs.net/ tv4ondemand/mp4root/2010-06-02/pid2780626_1019976_T3MP48_.mp4?token=c3RhcnRfdGlt ZT0yMDEwMDcyNjE2NDYyNiZlbmRfdGltZT0yMDEwMDcyNjE2NDgyNiZkaWdlc3Q9ZjFjN2U1NTRiY2U5 ODMxMDMwYWQxZWEwNzNhZmUxNjI= """ # retrieve the mediaurl data = UriHandler.open(item.url, proxy=self.proxy, additional_headers=self.localIP) stream_info = JsonHelper(data) stream_url = stream_info.get_value("playbackItem", "manifestUrl") if stream_url is None: return item if ".mpd" in stream_url: return self.__update_dash_video(item, stream_info) part = item.create_new_empty_media_part() if AddonSettings.use_adaptive_stream_add_on() and False: subtitle = M3u8.get_subtitle(stream_url, proxy=self.proxy) stream = part.append_media_stream(stream_url, 0) M3u8.set_input_stream_addon_input(stream, self.proxy) item.complete = True else: m3u8_data = UriHandler.open(stream_url, proxy=self.proxy, additional_headers=self.localIP) subtitle = M3u8.get_subtitle(stream_url, proxy=self.proxy, play_list_data=m3u8_data) for s, b, a in M3u8.get_streams_from_m3u8(stream_url, self.proxy, play_list_data=m3u8_data, map_audio=True): item.complete = True if not item.isLive and "-video" not in s: continue if a and "-audio" not in s: # remove any query parameters video_part = s.rsplit("?", 1)[0] video_part = video_part.rsplit("-", 1)[-1] video_part = "-%s" % (video_part, ) s = a.replace(".m3u8", video_part) part.append_media_stream(s, b) if subtitle: subtitle = subtitle.replace(".m3u8", ".webvtt") part.Subtitle = SubtitleHelper.download_subtitle(subtitle, format="m3u8srt", proxy=self.proxy) return item
def update_video_item(self, item): """ Updates an existing MediaItem with more data. 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. :param MediaItem item: the original MediaItem that needs updating. :return: The original item with more data added to it's properties. :rtype: MediaItem """ if item.metaData.get(self.__REQUIRES_LOGIN, False): logged_in = self.log_on() if not logged_in: XbmcWrapper.show_dialog(LanguageHelper.LoginErrorTitle, LanguageHelper.LoginErrorText) return item video_data = UriHandler.open(item.url, proxy=self.proxy, additional_headers=self.localIP) if not video_data: return item video_data = JsonHelper(video_data) video_info = video_data.get_value("data", "attributes") errors = video_data.get_value("errors") Logger.error("Error updating items: %s", errors) if errors: return item part = item.create_new_empty_media_part() m3u8url = video_info["streaming"]["hls"]["url"] m3u8data = UriHandler.open(m3u8url, self.proxy) if AddonSettings.use_adaptive_stream_add_on(): stream = part.append_media_stream(m3u8url, 0) item.complete = True M3u8.set_input_stream_addon_input(stream, self.proxy) else: # user agent for all sub m3u8 and ts requests needs to be the same 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)" for s, b, a in M3u8.get_streams_from_m3u8( m3u8url, self.proxy, append_query_string=False, map_audio=True, play_list_data=m3u8data): item.complete = True if a: audio_part = a.split("-prog_index.m3u8", 1)[0] audio_id = audio_part.rsplit("/", 1)[-1] s = s.replace("-prog_index.m3u8", "-{0}-prog_index.m3u8".format(audio_id)) part.append_media_stream(s, b) if self.language == "se": vtt_url = M3u8.get_subtitle(m3u8url, self.proxy, m3u8data, language="sv") elif self.language == "dk": vtt_url = M3u8.get_subtitle(m3u8url, self.proxy, m3u8data, language="da") else: vtt_url = M3u8.get_subtitle(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 vtt_url = vtt_url.replace("-prog_index.m3u8", "-0.vtt") part.Subtitle = SubtitleHelper.download_subtitle(vtt_url, format='srt', proxy=self.proxy) # if the user has premium, don't show any warnings if self.__has_premium: item.isPaid = False return item