Exemplo n.º 1
0
    def update_json_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

        """

        headers = {}
        if self.localIP:
            headers.update(self.localIP)

        data = UriHandler.open(item.url,
                               proxy=self.proxy,
                               additional_headers=headers)
        video_data = JsonHelper(data)
        stream_data = video_data.get_value("mediaAssetsOnDemand")
        if not stream_data:
            return item

        use_adaptive = AddonSettings.use_adaptive_stream_add_on()
        stream_data = stream_data[0]
        part = item.create_new_empty_media_part()
        if "hlsUrl" in stream_data:
            hls_url = stream_data["hlsUrl"]
            if use_adaptive:
                stream = part.append_media_stream(hls_url, 0)
                M3u8.set_input_stream_addon_input(stream,
                                                  self.proxy,
                                                  headers=headers)
                item.complete = True
            else:
                for s, b in M3u8.get_streams_from_m3u8(hls_url,
                                                       self.proxy,
                                                       headers=headers):
                    item.complete = True
                    part.append_media_stream(s, b)

        if "timedTextSubtitlesUrl" in stream_data and stream_data[
                "timedTextSubtitlesUrl"]:
            sub_url = stream_data["timedTextSubtitlesUrl"].replace(
                ".ttml", ".vtt")
            sub_url = HtmlEntityHelper.url_decode(sub_url)
            part.Subtitle = SubtitleHelper.download_subtitle(sub_url,
                                                             format="webvtt")
        return item
Exemplo n.º 2
0
    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
Exemplo n.º 3
0
    def __update_m3u8(self, url, part, headers, use_kodi_hls):
        """ Update a video that has M3u8 streams.

        :param str url:                 The URL for the stream.
        :param MediaItemPart part:      The new part that needs updating.
        :param dict[str,str] headers:   The URL headers to use.
        :param bool use_kodi_hls:       Should we use the InputStream Adaptive add-on?

        """
        # first see if there are streams in this file, else check the second location.
        for s, b in M3u8.get_streams_from_m3u8(url,
                                               self.proxy,
                                               headers=headers):
            if use_kodi_hls:
                strm = part.append_media_stream(url, 0)
                M3u8.set_input_stream_addon_input(strm, headers=headers)
                # Only the main M3u8 is needed
                break
            else:
                part.append_media_stream(s, b)

        if not part.MediaStreams and "manifest.m3u8" in url:
            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.get_streams_from_m3u8(url,
                                                   self.proxy,
                                                   headers=headers):
                if use_kodi_hls:
                    strm = part.append_media_stream(url, 0)
                    M3u8.set_input_stream_addon_input(strm, headers=headers)
                    # Only the main M3u8 is needed
                    break
                else:
                    part.append_media_stream(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")
            sub_url = url.rsplit("uri=")[-1]
            sub_url = HtmlEntityHelper.url_decode(sub_url)
            sub_data = UriHandler.open(sub_url, proxy=self.proxy)
            subs = [
                line for line in sub_data.split("\n")
                if line.startswith("http")
            ]
            if subs:
                part.Subtitle = SubtitleHelper.download_subtitle(
                    subs[0], format='webvtt', proxy=self.proxy)
        return
Exemplo n.º 4
0
    def __update_video_from_mpd(self, item, mpd_info,
                                use_adaptive_with_encryption):
        """ Updates an existing MediaItem with more data based on an MPD stream.

        :param dict[str,str] mpd_info:              Stream info retrieved from the stream json.
        :param bool use_adaptive_with_encryption:   Do we use the Adaptive InputStream add-on?
        :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("Updating streams using BrightCove data.")

        part = item.create_new_empty_media_part()
        mpd_manifest_url = "https:{0}".format(mpd_info["mediaLocator"])
        mpd_data = UriHandler.open(mpd_manifest_url, proxy=self.proxy)
        subtitles = Regexer.do_regex(r'<BaseURL>([^<]+\.vtt)</BaseURL>',
                                     mpd_data)

        if subtitles:
            Logger.debug("Found subtitle: %s", subtitles[0])
            subtitle = SubtitleHelper.download_subtitle(subtitles[0],
                                                        proxy=self.proxy,
                                                        format="webvtt")
            part.Subtitle = subtitle

        if use_adaptive_with_encryption:
            # We can use the adaptive add-on with encryption
            Logger.info("Using MPD InputStreamAddon")
            license_url = Regexer.do_regex('licenseUrl="([^"]+)"', mpd_data)[0]
            token = "Bearer {0}".format(mpd_info["playToken"])
            key_headers = {"Authorization": token}
            license_key = Mpd.get_license_key(license_url,
                                              key_headers=key_headers)

            stream = part.append_media_stream(mpd_manifest_url, 0)
            Mpd.set_input_stream_addon_input(stream,
                                             self.proxy,
                                             license_key=license_key)
            item.complete = True
        else:
            XbmcWrapper.show_dialog(
                LanguageHelper.get_localized_string(LanguageHelper.DrmTitle),
                LanguageHelper.get_localized_string(
                    LanguageHelper.WidevineLeiaRequired))

        return item
    def get_subtitle(stream_id, proxy=None):
        """ Downloads a subtitle for a POMS id.

        :param str stream_id:   The POMS id.
        :param ProxyInfo proxy: The proxy to use

        :return: The full patch of the cached SRT file.
        :rtype: str

        """

        sub_title_url = "http://tt888.omroep.nl/tt888/%s" % (stream_id, )
        return SubtitleHelper.download_subtitle(sub_title_url,
                                                stream_id + ".srt",
                                                format='srt',
                                                proxy=proxy)
    def update_video_item(self, item):  # NOSONAR
        """ 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)

        # we need to fetch the actual url as it might differ for single video items
        data, secure_url = UriHandler.header(item.url, proxy=self.proxy)

        # Get the MZID
        secure_url = secure_url.rstrip("/")
        secure_url = "%s.mssecurevideo.json" % (secure_url, )
        data = UriHandler.open(secure_url,
                               proxy=self.proxy,
                               additional_headers=item.HttpHeaders)
        secure_data = JsonHelper(data, logger=Logger.instance())
        mzid = secure_data.get_value(
            list(secure_data.json.keys())[0], "videoid")

        # region New URL retrieval with DRM protection
        # 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=vrtvideo"\
            .format(HtmlEntityHelper.url_encode(mzid), HtmlEntityHelper.url_encode(token))
        asset_data = UriHandler.open(asset_url,
                                     proxy=self.proxy,
                                     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)
        part = item.create_new_empty_media_part()
        srt = None

        # see if we prefer hls over dash
        hls_prio = 2 if self._get_setting("hls_over_dash", False) 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, 0)
                M3u8.set_input_stream_addon_input(stream, self.proxy)

            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, self.proxy)
                else:
                    m3u8_data = UriHandler.open(video_url, self.proxy)
                    for s, b, a in M3u8.get_streams_from_m3u8(
                            video_url,
                            self.proxy,
                            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,
                                            proxy=self.proxy)
                    if not srt:
                        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, self.proxy)
                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, self.proxy, license_key=encryption_key)

            if video_type.startswith("hls") and srt is None:
                srt = M3u8.get_subtitle(video_url, proxy=self.proxy)
                if srt:
                    srt = srt.replace(".m3u8", ".vtt")
                    part.Subtitle = SubtitleHelper.download_subtitle(
                        srt, format="webvtt")

            item.complete = True
        # endregion
        return item
Exemplo n.º 7
0
    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

        """

        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")

        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)
        return item
Exemplo n.º 8
0
 def GetSubtitle(streamId, proxy=None):
     subTitleUrl = "http://tt888.omroep.nl/tt888/%s" % (streamId, )
     return SubtitleHelper.DownloadSubtitle(subTitleUrl,
                                            streamId + ".srt",
                                            format='srt',
                                            proxy=proxy)
Exemplo n.º 9
0
    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
Exemplo n.º 10
0
    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)
        m3u8_url = stream_info.get_value("playbackItem", "manifestUrl")
        if m3u8_url is None:
            return item

        part = item.create_new_empty_media_part()

        if AddonSettings.use_adaptive_stream_add_on() and False:
            subtitle = M3u8.get_subtitle(m3u8_url, proxy=self.proxy)
            stream = part.append_media_stream(m3u8_url, 0)
            M3u8.set_input_stream_addon_input(stream, self.proxy)
            item.complete = True
        else:
            m3u8_data = UriHandler.open(m3u8_url,
                                        proxy=self.proxy,
                                        additional_headers=self.localIP)
            subtitle = M3u8.get_subtitle(m3u8_url,
                                         proxy=self.proxy,
                                         play_list_data=m3u8_data)
            for s, b, a in M3u8.get_streams_from_m3u8(m3u8_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
Exemplo n.º 11
0
    def update_video_for_mzid(self, item, mzid, live=False):  # NOSONAR
        """ Updates a video item based on the MZID

        :param MediaItem item: the parent item
        :param str mzid:       the MZID

        """

        # region New URL retrieval with DRM protection
        # 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=vrtvideo"\
            .format(HtmlEntityHelper.url_encode(mzid), HtmlEntityHelper.url_encode(token))
        asset_data = UriHandler.open(asset_url,
                                     proxy=self.proxy,
                                     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)
        part = item.create_new_empty_media_part()
        srt = None

        # see if we prefer hls over dash
        hls_prio = 2 if self._get_setting("hls_over_dash",
                                          'false') == 'true' 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, self.proxy)

            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, self.proxy)
                else:
                    m3u8_data = UriHandler.open(video_url, self.proxy)
                    for s, b, a in M3u8.get_streams_from_m3u8(
                            video_url,
                            self.proxy,
                            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,
                                            proxy=self.proxy)
                    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, self.proxy)
                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, self.proxy, license_key=encryption_key)

            if video_type.startswith("hls") and srt is None:
                srt = M3u8.get_subtitle(video_url, proxy=self.proxy)
                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
        # endregion
        return item
Exemplo n.º 12
0
    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)
        use_kodi_hls = AddonSettings.use_adaptive_stream_add_on(channel=self)

        # User-agent (and possible other headers), should be consistent over all
        # M3u8 requests (See #864)
        headers = {}
        if not use_kodi_hls:
            headers = {
                "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)",
            }
        if self.localIP:
            headers.update(self.localIP)

        data = UriHandler.open(item.url,
                               proxy=self.proxy,
                               additional_headers=headers or None)
        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.download_subtitle(
                    part.Subtitle, format="webvtt", proxy=self.proxy)
            else:
                part.Subtitle = SubtitleHelper.download_subtitle(
                    part.Subtitle, format="dcsubtitle", proxy=self.proxy)
        else:
            part = item.create_new_empty_media_part()

        for quality in ("high", 3500), ("hls", 2700), ("medium", 2100):
            url = json.get_value("streams", quality[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:
                self.__update_m3u8(url, part, headers, use_kodi_hls)

            elif url.startswith("rtmp"):
                self.__update_rtmp(url, part, quality)

            elif "[empty]" in url:
                Logger.debug(
                    "Found post-live url with '[empty]' in it. Ignoring this.")
                continue

            else:
                part.append_media_stream(url, quality[1])

        if not use_kodi_hls:
            part.HttpHeaders.update(headers)

        if part.MediaStreams:
            item.complete = True
        Logger.trace("Found mediaurl: %s", item)
        return item
Exemplo n.º 13
0
    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)
        url = item.url

        if self.localIP:
            item.HttpHeaders.update(self.localIP)

        if ".m3u8" not in item.url:
            data = UriHandler.Open(url, proxy=self.proxy, additionalHeaders=item.HttpHeaders)
            json = JsonHelper(data)
            url = json.GetValue("mediaUrl")
            if url is None:
                Logger.Warning("Could not find mediaUrl in %s", item.url)
                return
            f4mNeedle = "/manifest.f4m"
            if f4mNeedle in url:
                Logger.Info("Found F4m stream. Converting to M3u8.")
                url = url[:url.index(f4mNeedle)].replace("/z/", "/i/").replace("http:", "https:")
                url = "%s/master.m3u8" % (url, )

        # are there subs? They are added as URL parameter

        part = item.CreateNewEmptyMediaPart()
        subMatches = Regexer.DoRegex('https*%3a%2f%2.+master.m3u8', url)
        if subMatches:
            subUrl = HtmlEntityHelper.UrlDecode(subMatches[0])
            Logger.Info("Item has subtitles: %s", subUrl)
            subTitle = SubtitleHelper.DownloadSubtitle(subUrl, format="m3u8srt", proxy=self.proxy)
            if subTitle:
                part.Subtitle = subTitle

        for s, b in M3u8.GetStreamsFromM3u8(url, self.proxy, headers=item.HttpHeaders):
            item.complete = True
            # s = self.GetVerifiableVideoUrl(s)
            part.AppendMediaStream(s, b)
            if self.localIP:
                part.HttpHeaders.update(self.localIP)

        return item
Exemplo n.º 14
0
    def __update_embedded_video(self, item):
        """ Updates video items that are encrypted. This could be the default for Krypton!

        :param MediaItem item: The item to update.

        :return: An updated item.
        :rtype: MediaItem

        """

        data = UriHandler.open(item.url, proxy=self.proxy)
        start_needle = "var playerConfig ="
        start_data = data.index(start_needle) + len(start_needle)
        end_data = data.index("var talpaPlayer")
        data = data[start_data:end_data].strip().rstrip(";")

        json = JsonHelper(data)
        has_drm_only = True
        adaptive_available = AddonSettings.use_adaptive_stream_add_on(
            with_encryption=False, channel=self)
        adaptive_available_encrypted = AddonSettings.use_adaptive_stream_add_on(
            with_encryption=True, channel=self)

        for play_list_entry in json.get_value("playlist"):
            part = item.create_new_empty_media_part()
            for source in play_list_entry["sources"]:
                stream_type = source["type"]
                stream_url = source["file"]
                stream_drm = source.get("drm")

                if not stream_drm:
                    has_drm_only = False
                    if stream_type == "m3u8":
                        Logger.debug("Found non-encrypted M3u8 stream: %s",
                                     stream_url)
                        M3u8.update_part_with_m3u8_streams(part,
                                                           stream_url,
                                                           proxy=self.proxy,
                                                           channel=self)
                        item.complete = True
                    elif stream_type == "dash" and adaptive_available:
                        Logger.debug("Found non-encrypted Dash stream: %s",
                                     stream_url)
                        stream = part.append_media_stream(stream_url, 1)
                        Mpd.set_input_stream_addon_input(stream,
                                                         proxy=self.proxy)
                        item.complete = True
                    else:
                        Logger.debug("Unknown stream source: %s", source)

                else:
                    compatible_drm = "widevine"
                    if compatible_drm not in stream_drm or stream_type != "dash":
                        Logger.debug("Found encrypted %s stream: %s",
                                     stream_type, stream_url)
                        continue

                    Logger.debug("Found Widevine encrypted Dash stream: %s",
                                 stream_url)
                    license_url = stream_drm[compatible_drm]["url"]
                    pid = stream_drm[compatible_drm]["releasePid"]
                    encryption_json = '{"getRawWidevineLicense":' \
                                      '{"releasePid":"%s", "widevineChallenge":"b{SSM}"}' \
                                      '}' % (pid,)

                    headers = {
                        "Content-Type": "application/json",
                        "Origin": "https://embed.kijk.nl",
                        "Referer": stream_url
                    }

                    encryption_key = Mpd.get_license_key(
                        license_url,
                        key_type=None,
                        key_value=encryption_json,
                        key_headers=headers)

                    stream = part.append_media_stream(stream_url, 0)
                    Mpd.set_input_stream_addon_input(
                        stream, proxy=self.proxy, license_key=encryption_key)
                    item.complete = True

            subs = [
                s['file'] for s in play_list_entry.get("tracks", [])
                if s.get('kind') == "captions"
            ]
            if subs:
                subtitle = SubtitleHelper.download_subtitle(subs[0],
                                                            format="webvtt")
                part.Subtitle = subtitle

        if has_drm_only and not adaptive_available_encrypted:
            XbmcWrapper.show_dialog(
                LanguageHelper.get_localized_string(LanguageHelper.DrmTitle),
                LanguageHelper.get_localized_string(
                    LanguageHelper.WidevineLeiaRequired))
        return item