Exemplo n.º 1
0
    def wrstsegment(self, subdata):
        time = 0
        subs = []
        for i in self.kwargs["m3u8"].media_segment:
            itemurl = get_full_url(i["URI"], self.url)
            cont = self.http.get(itemurl)
            if "cmore" in self.url:
                cont.encoding = "utf-8"
            text = cont.text.split("\n")
            for t in text:  # is in text[1] for tv4play, but this should be more future proof
                if 'X-TIMESTAMP-MAP=MPEGTS' in t:
                    time = float(
                        re.search(r"X-TIMESTAMP-MAP=MPEGTS:(\d+)",
                                  t).group(1)) / 90000 - 10
            text = text[3:len(text) - 2]
            if len(text) > 1:
                itmes = []
                for n in text:
                    if n:
                        itmes.append(n)
                    else:
                        if len(subs) > 1 and itmes[1] == subs[-1][
                                1]:  # This will happen when  there is two sections in file
                            ha = strdate(subs[-1][0])
                            ha3 = strdate(itmes[0])
                            second = str2sec(ha3.group(2)) + time
                            subs[-1][0] = "{} --> {}".format(
                                ha.group(1), sec2str(second))
                            itmes = []
                        else:
                            ha = strdate(itmes[0])
                            first = str2sec(ha.group(1)) + time
                            second = str2sec(ha.group(2)) + time
                            itmes[0] = "{} --> {}".format(
                                sec2str(first), sec2str(second))
                            subs.append(itmes)
                            itmes = []
                if itmes:
                    if len(subs) > 0 and itmes[1] == subs[-1][1]:
                        ha = strdate(subs[-1][0])
                        ha3 = strdate(itmes[0])
                        second = str2sec(ha3.group(2)) + time
                        subs[-1][0] = "{} --> {}".format(
                            ha.group(1), sec2str(second))
                    else:
                        ha = strdate(itmes[0])
                        first = str2sec(ha.group(1)) + time
                        second = str2sec(ha.group(2)) + time
                        itmes[0] = "{} --> {}".format(sec2str(first),
                                                      sec2str(second))
                        subs.append(itmes)

        string = ""
        nr = 1
        for sub in subs:
            string += "{}\n{}\n\n".format(nr, '\n'.join(sub))
            nr += 1

        return string
Exemplo n.º 2
0
    def wrstsegment(self, subdata):
        time = 0
        subs = []
        for i in self.kwargs["m3u8"].media_segment:
            itemurl = get_full_url(i["URI"], self.url)
            cont = self.http.get(itemurl)
            if "cmore" in self.url:
                cont.encoding = "utf-8"
            text = cont.text.split("\n")
            for t in text:  # is in text[1] for tv4play, but this should be more future proof
                if "X-TIMESTAMP-MAP=MPEGTS" in t:
                    time = float(
                        re.search(r"X-TIMESTAMP-MAP=MPEGTS:(\d+)",
                                  t).group(1)) / 90000 - 10
            text = text[3:len(text) - 2]
            itmes = []
            if len(text) > 1:
                for n in text:
                    if n:  # don't get the empty lines.
                        itmes.append(n)

            several_items = False
            skip = False
            sub = []

            for x in range(len(itmes)):
                item = itmes[x]
                if strdate(item) and len(subs) > 0 and itmes[x +
                                                             1] == subs[-1][1]:
                    ha = strdate(subs[-1][0])
                    ha3 = strdate(item)
                    second = str2sec(ha3.group(2)) + time
                    subs[-1][0] = "{} --> {}".format(ha.group(1),
                                                     sec2str(second))
                    skip = True
                    continue
                has_date = strdate(item)
                if has_date:
                    if several_items:
                        subs.append(sub)
                        sub = []
                    skip = False
                    first = str2sec(has_date.group(1)) + time
                    second = str2sec(has_date.group(2)) + time
                    sub.append("{} --> {}".format(sec2str(first),
                                                  sec2str(second)))
                    several_items = True
                elif has_date is None and skip is False:
                    sub.append(item)

            if sub:
                subs.append(sub)
        string = ""
        nr = 1
        for sub in subs:
            string += "{}\n{}\n\n".format(nr, "\n".join(sub))
            nr += 1

        return string
Exemplo n.º 3
0
    def wrstsegment(self, subdata):
        time = 0
        subs = []
        for i in self.kwargs["m3u8"].media_segment:
            itemurl = get_full_url(i["URI"], self.url)
            cont = self.http.get(itemurl)
            if "cmore" in self.url:
                cont.encoding = "utf-8"
            text = cont.text.split("\n")
            for t in text:  # is in text[1] for tv4play, but this should be more future proof
                if 'X-TIMESTAMP-MAP=MPEGTS' in t:
                    time = float(re.search(r"X-TIMESTAMP-MAP=MPEGTS:(\d+)", t).group(1)) / 90000 - 10
            text = text[3:len(text) - 2]
            if len(text) > 1:
                itmes = []
                for n in text:
                    if n:
                        itmes.append(n)
                    else:
                        if len(subs) > 1 and len(itmes) < 2:  # Ignore empty lines in unexpected places
                            pass
                        elif len(subs) > 1 and itmes[1] == subs[-1][1]:  # This will happen when there are two sections in file
                            ha = strdate(subs[-1][0])
                            ha3 = strdate(itmes[0])
                            second = str2sec(ha3.group(2)) + time
                            subs[-1][0] = "{} --> {}".format(ha.group(1), sec2str(second))
                            itmes = []
                        else:
                            ha = strdate(itmes[0])
                            first = str2sec(ha.group(1)) + time
                            second = str2sec(ha.group(2)) + time
                            itmes[0] = "{} --> {}".format(sec2str(first), sec2str(second))
                            subs.append(itmes)
                            itmes = []
                if itmes:
                    if len(subs) > 0 and itmes[1] == subs[-1][1]:
                        ha = strdate(subs[-1][0])
                        ha3 = strdate(itmes[0])
                        second = str2sec(ha3.group(2)) + time
                        subs[-1][0] = "{} --> {}".format(ha.group(1), sec2str(second))
                    else:
                        ha = strdate(itmes[0])
                        first = str2sec(ha.group(1)) + time
                        second = str2sec(ha.group(2)) + time
                        itmes[0] = "{} --> {}".format(sec2str(first), sec2str(second))
                        subs.append(itmes)

        string = ""
        nr = 1
        for sub in subs:
            string += "{}\n{}\n\n".format(nr, '\n'.join(sub))
            nr += 1

        return string
Exemplo n.º 4
0
    def wrstsegment(self, subdata):
        time = 0
        subs = []
        for i in self.kwargs["m3u8"].media_segment:
            itemurl = get_full_url(i["URI"], self.url)
            cont = self.http.get(itemurl)
            if "cmore" in self.url:
                cont.encoding = "utf-8"
            text = cont.text.split("\n")
            for t in text:  # is in text[1] for tv4play, but this should be more future proof
                if 'X-TIMESTAMP-MAP=MPEGTS' in t:
                    time = float(re.search(r"X-TIMESTAMP-MAP=MPEGTS:(\d+)", t).group(1)) / 90000 - 10
            text = text[3:len(text) - 2]
            itmes = []
            if len(text) > 1:
                for n in text:
                    if n:  # don't get the empty lines.
                        itmes.append(n)

            several_items = False
            skip = False
            sub = []

            for x in range(len(itmes)):
                item = itmes[x]
                if strdate(item) and len(subs) > 0 and itmes[x + 1] == subs[-1][1]:
                    ha = strdate(subs[-1][0])
                    ha3 = strdate(item)
                    second = str2sec(ha3.group(2)) + time
                    subs[-1][0] = "{} --> {}".format(ha.group(1), sec2str(second))
                    skip = True
                    continue
                has_date = strdate(item)
                if has_date:
                    if several_items:
                        subs.append(sub)
                        sub = []
                    skip = False
                    first = str2sec(has_date.group(1)) + time
                    second = str2sec(has_date.group(2)) + time
                    sub.append("{} --> {}".format(sec2str(first), sec2str(second)))
                    several_items = True
                elif has_date is None and skip is False:
                    sub.append(item)

            if sub:
                subs.append(sub)
        string = ""
        nr = 1
        for sub in subs:
            string += "{}\n{}\n\n".format(nr, '\n'.join(sub))
            nr += 1

        return string
Exemplo n.º 5
0
 def test_get_full_url_1(self):
     for test in [
             # full http:// url as media segment in playlist
         {
             "srcurl": "INVALID",
             "segment": "http://example.com/",
             "expected": "http://example.com/"
         },
             # full https:// url as media segment in playlist
         {
             "srcurl": "INVALID",
             "segment": "https://example.com/",
             "expected": "https://example.com/"
         },
             # filename as media segment in playlist (http)
         {
             "srcurl": "http://example.com/",
             "segment": "foo.ts",
             "expected": "http://example.com/foo.ts"
         },
             # filename as media segment in playlist (https)
         {
             "srcurl": "https://example.com/",
             "segment": "foo.ts",
             "expected": "https://example.com/foo.ts"
         },
             # replacing srcurl file
         {
             "srcurl": "http://example.com/bar",
             "segment": "foo.ts",
             "expected": "http://example.com/foo.ts"
         },
             # with query parameters
         {
             "srcurl": "http://example.com/bar?baz=qux",
             "segment": "foo.ts",
             "expected": "http://example.com/foo.ts"
         },
             # with segment with slash
         {
             "srcurl": "http://example.com/bar",
             "segment": "/test",
             "expected": "http://example.com/test"
         },
     ]:
         assert get_full_url(test["segment"],
                             test["srcurl"]) == test["expected"]
Exemplo n.º 6
0
 def test_get_full_url_1(self):
     for test in [
         # full http:// url as media segment in playlist
         {
             'srcurl': 'INVALID',
             'segment': 'http://example.com/',
             'expected': 'http://example.com/'
         },
         # full https:// url as media segment in playlist
         {
             'srcurl': 'INVALID',
             'segment': 'https://example.com/',
             'expected': 'https://example.com/'
         },
         # filename as media segment in playlist (http)
         {
             'srcurl': 'http://example.com/',
             'segment': 'foo.ts',
             'expected': 'http://example.com/foo.ts'
         },
         # filename as media segment in playlist (https)
         {
             'srcurl': 'https://example.com/',
             'segment': 'foo.ts',
             'expected': 'https://example.com/foo.ts'
         },
         # replacing srcurl file
         {
             'srcurl': 'http://example.com/bar',
             'segment': 'foo.ts',
             'expected': 'http://example.com/foo.ts'
         },
         # with query parameters
         {
             'srcurl': 'http://example.com/bar?baz=qux',
             'segment': 'foo.ts',
             'expected': 'http://example.com/foo.ts'
         },
     ]:
         self.assertEqual(
             get_full_url(test['segment'], test['srcurl']),
             test['expected'])
Exemplo n.º 7
0
 def test_get_full_url_1(self):
     for test in [
             # full http:// url as media segment in playlist
         {
             'srcurl': 'INVALID',
             'segment': 'http://example.com/',
             'expected': 'http://example.com/'
         },
             # full https:// url as media segment in playlist
         {
             'srcurl': 'INVALID',
             'segment': 'https://example.com/',
             'expected': 'https://example.com/'
         },
             # filename as media segment in playlist (http)
         {
             'srcurl': 'http://example.com/',
             'segment': 'foo.ts',
             'expected': 'http://example.com/foo.ts'
         },
             # filename as media segment in playlist (https)
         {
             'srcurl': 'https://example.com/',
             'segment': 'foo.ts',
             'expected': 'https://example.com/foo.ts'
         },
             # replacing srcurl file
         {
             'srcurl': 'http://example.com/bar',
             'segment': 'foo.ts',
             'expected': 'http://example.com/foo.ts'
         },
             # with query parameters
         {
             'srcurl': 'http://example.com/bar?baz=qux',
             'segment': 'foo.ts',
             'expected': 'http://example.com/foo.ts'
         },
     ]:
         self.assertEqual(get_full_url(test['segment'], test['srcurl']),
                          test['expected'])
Exemplo n.º 8
0
def hlsparse(config, res, url, **kwargs):
    streams = {}

    if not res:
        return streams

    if res.status_code > 400:
        streams[0] = ServiceError("Can't read HLS playlist. {0}".format(
            res.status_code))
        return streams
    m3u8 = M3U8(res.text)

    keycookie = kwargs.pop("keycookie", None)
    authorization = kwargs.pop("authorization", None)
    httpobject = kwargs.pop("httpobject", None)
    output = kwargs.pop("output", None)

    media = {}
    subtitles = {}
    segments = None

    if m3u8.master_playlist:
        for i in m3u8.master_playlist:
            audio_url = None
            if i["TAG"] == "EXT-X-MEDIA":
                if "AUTOSELECT" in i and (i["AUTOSELECT"].upper() == "YES"):
                    if i["TYPE"] and i["TYPE"] != "SUBTITLES":
                        if "URI" in i:
                            if segments is None:
                                segments = True
                            if i["GROUP-ID"] not in media:
                                media[i["GROUP-ID"]] = []
                            media[i["GROUP-ID"]].append(i["URI"])
                        else:
                            segments = False
                if i["TYPE"] == "SUBTITLES":
                    if "URI" in i:
                        if i["GROUP-ID"] not in subtitles:
                            subtitles[i["GROUP-ID"]] = []
                        item = [i["URI"], i["LANGUAGE"]]
                        if item not in subtitles[i["GROUP-ID"]]:
                            subtitles[i["GROUP-ID"]].append(item)
                continue
            elif i["TAG"] == "EXT-X-STREAM-INF":
                bit_rate = float(i["BANDWIDTH"]) / 1000
                if "AUDIO" in i and (i["AUDIO"] in media):
                    audio_url = get_full_url(media[i["AUDIO"]][0], url)
                urls = get_full_url(i["URI"], url)
            else:
                continue  # Needs to be changed to utilise other tags.
            streams[int(bit_rate)] = HLS(copy.copy(config),
                                         urls,
                                         bit_rate,
                                         cookies=res.cookies,
                                         keycookie=keycookie,
                                         authorization=authorization,
                                         audio=audio_url,
                                         output=output,
                                         segments=bool(segments),
                                         kwargs=kwargs)

        if subtitles and httpobject:
            for sub in list(subtitles.keys()):
                for n in subtitles[sub]:
                    m3u8s = M3U8(
                        httpobject.request("get",
                                           get_full_url(n[0], url),
                                           cookies=res.cookies).text)
                    if "cmore" in url:
                        subtype = "wrstsegment"  # this have been seen in tv4play
                    else:
                        subtype = "wrst"
                    streams[int(random.randint(1, 40))] = subtitle(
                        copy.copy(config),
                        subtype,
                        get_full_url(m3u8s.media_segment[0]["URI"], url),
                        subfix=n[1],
                        output=copy.copy(output),
                        m3u8=m3u8s)

    elif m3u8.media_segment:
        config.set("segments", False)
        streams[0] = HLS(copy.copy(config),
                         url,
                         0,
                         cookies=res.cookies,
                         keycookie=keycookie,
                         authorization=authorization,
                         output=output,
                         segments=False)

    else:
        streams[0] = ServiceError("Can't find HLS playlist in m3u8 file.")

    return streams
Exemplo n.º 9
0
    def _download(self, url, file_name):
        cookies = self.kwargs.get("cookies", None)
        start_time = time.time()
        m3u8 = M3U8(self.http.request("get", url, cookies=cookies).text)
        key = None

        if m3u8.encrypted:
            from Crypto.Cipher import AES

        def random_iv():
            try:
                from Crypto import Random
                return Random.new().read(AES.block_size)
            except ImportError:
                return os.urandom(16)

        file_d = output(file_name[0], self.config, file_name[1])
        if file_d is None:
            return

        hls_time_stamp = self.kwargs.pop("hls_time_stamp", False)
        decryptor = None
        size_media = len(m3u8.media_segment)
        eta = ETA(size_media)
        total_duration = 0
        duration = 0
        max_duration = 0
        for index, i in enumerate(m3u8.media_segment):
            if "duration" in i["EXTINF"]:
                duration = i["EXTINF"]["duration"]
                max_duration = max(max_duration, duration)
                total_duration += duration
            item = get_full_url(i["URI"], url)

            if not self.config.get("silent"):
                if self.config.get("live"):
                    progressbar(
                        size_media, index + 1, ''.join([
                            'DU: ',
                            str(timedelta(seconds=int(total_duration)))
                        ]))
                else:
                    eta.increment()
                    progressbar(size_media, index + 1,
                                ''.join(['ETA: ', str(eta)]))

            data = self.http.request("get", item, cookies=cookies)
            if data.status_code == 404:
                break
            data = data.content
            if m3u8.encrypted:
                headers = {}
                if self.keycookie:
                    keycookies = self.keycookie
                else:
                    keycookies = cookies
                if self.authorization:
                    headers["authorization"] = self.authorization

                # Update key/decryptor
                if "EXT-X-KEY" in i:
                    keyurl = get_full_url(i["EXT-X-KEY"]["URI"], url)
                    key = self.http.request("get",
                                            keyurl,
                                            cookies=keycookies,
                                            headers=headers).content
                    iv = binascii.unhexlify(i["EXT-X-KEY"]["IV"][2:].zfill(
                        32)) if "IV" in i["EXT-X-KEY"] else random_iv()
                    decryptor = AES.new(key, AES.MODE_CBC, iv)

                if decryptor:
                    data = decryptor.decrypt(data)
                else:
                    raise ValueError(
                        "No decryptor found for encrypted hls steam.")

            file_d.write(data)

            if self.config.get(
                    "capture_time"
            ) > 0 and total_duration >= self.config.get("capture_time") * 60:
                break

            if (size_media == (index + 1)) and self.config.get("live"):
                sleep_int = (start_time + max_duration * 2) - time.time()
                if sleep_int > 0:
                    time.sleep(sleep_int)

                size_media_old = size_media
                while size_media_old == size_media:
                    start_time = time.time()

                    if hls_time_stamp:
                        end_time_stamp = (datetime.utcnow() - timedelta(
                            minutes=1, seconds=max_duration * 2)).replace(
                                microsecond=0)
                        start_time_stamp = end_time_stamp - timedelta(
                            minutes=1)

                        base_url = url.split(".m3u8")[0]
                        url = "{0}.m3u8?in={1}&out={2}?".format(
                            base_url, start_time_stamp.isoformat(),
                            end_time_stamp.isoformat())

                    new_m3u8 = M3U8(
                        self.http.request("get", url, cookies=cookies).text)
                    for n_m3u in new_m3u8.media_segment:
                        if not any(d["URI"] == n_m3u["URI"]
                                   for d in m3u8.media_segment):
                            m3u8.media_segment.append(n_m3u)

                    size_media = len(m3u8.media_segment)

                    if size_media_old == size_media:
                        time.sleep(max_duration)

        file_d.close()
        if not self.config.get("silent"):
            progress_stream.write('\n')
        self.finished = True
Exemplo n.º 10
0
def hlsparse(config, res, url, **kwargs):
    streams = {}

    if not res:
        return streams

    if res.status_code > 400:
        streams[0] = ServiceError("Can't read HLS playlist. {0}".format(res.status_code))
        return streams
    m3u8 = M3U8(res.text)

    keycookie = kwargs.pop("keycookie", None)
    authorization = kwargs.pop("authorization", None)
    httpobject = kwargs.pop("httpobject", None)
    output = kwargs.pop("output", None)

    media = {}
    subtitles = {}
    segments = None

    if m3u8.master_playlist:
        for i in m3u8.master_playlist:
            audio_url = None
            if i["TAG"] == "EXT-X-MEDIA":
                if "AUTOSELECT" in i and (i["AUTOSELECT"].upper() == "YES"):
                    if i["TYPE"] and i["TYPE"] != "SUBTITLES":
                        if "URI" in i:
                            if segments is None:
                                segments = True
                            if i["GROUP-ID"] not in media:
                                media[i["GROUP-ID"]] = []
                            media[i["GROUP-ID"]].append(i["URI"])
                        else:
                            segments = False
                if i["TYPE"] == "SUBTITLES":
                    if "URI" in i:
                        if i["GROUP-ID"] not in subtitles:
                            subtitles[i["GROUP-ID"]] = []
                        item = [i["URI"], i["LANGUAGE"]]
                        if item not in subtitles[i["GROUP-ID"]]:
                            subtitles[i["GROUP-ID"]].append(item)
                continue
            elif i["TAG"] == "EXT-X-STREAM-INF":
                bit_rate = float(i["BANDWIDTH"]) / 1000
                if "AUDIO" in i and (i["AUDIO"] in media):
                    audio_url = get_full_url(media[i["AUDIO"]][0], url)
                urls = get_full_url(i["URI"], url)
            else:
                continue  # Needs to be changed to utilise other tags.
            streams[int(bit_rate)] = HLS(copy.copy(config), urls, bit_rate,
                                         cookies=res.cookies, keycookie=keycookie, authorization=authorization,
                                         audio=audio_url, output=output, segments=bool(segments), kwargs=kwargs)

        if subtitles and httpobject:
            for sub in list(subtitles.keys()):
                for n in subtitles[sub]:
                    m3u8s = M3U8(httpobject.request("get", get_full_url(n[0], url), cookies=res.cookies).text)
                    if "cmore" in url:
                        subtype = "wrstsegment"  # this have been seen in tv4play
                    else:
                        subtype = "wrst"
                    streams[int(random.randint(1, 40))] = subtitle(copy.copy(config), subtype,
                                                                   get_full_url(m3u8s.media_segment[0]["URI"], url),
                                                                   subfix=n[1], output=copy.copy(output), m3u8=m3u8s)

    elif m3u8.media_segment:
        config.set("segments", False)
        streams[0] = HLS(copy.copy(config), url, 0, cookies=res.cookies, keycookie=keycookie, authorization=authorization,
                         output=output, segments=False)

    else:
        streams[0] = ServiceError("Can't find HLS playlist in m3u8 file.")

    return streams
Exemplo n.º 11
0
    def _download(self, url, file_name):
        cookies = self.kwargs.get("cookies", None)
        start_time = time.time()
        m3u8 = M3U8(self.http.request("get", url, cookies=cookies).text)
        key = None

        def random_iv():
            return os.urandom(16)
        file_d = output(file_name[0], self.config, file_name[1])
        if file_d is None:
            return

        hls_time_stamp = self.kwargs.pop("hls_time_stamp", False)
        decryptor = None
        size_media = len(m3u8.media_segment)
        eta = ETA(size_media)
        total_duration = 0
        duration = 0
        max_duration = 0
        for index, i in enumerate(m3u8.media_segment):
            if "duration" in i["EXTINF"]:
                duration = i["EXTINF"]["duration"]
                max_duration = max(max_duration, duration)
                total_duration += duration
            item = get_full_url(i["URI"], url)

            if not self.config.get("silent"):
                if self.config.get("live"):
                    progressbar(size_media, index + 1, ''.join(['DU: ', str(timedelta(seconds=int(total_duration)))]))
                else:
                    eta.increment()
                    progressbar(size_media, index + 1, ''.join(['ETA: ', str(eta)]))

            data = self.http.request("get", item, cookies=cookies)
            if data.status_code == 404:
                break
            data = data.content
            if m3u8.encrypted:
                headers = {}
                if self.keycookie:
                    keycookies = self.keycookie
                else:
                    keycookies = cookies
                if self.authorization:
                    headers["authorization"] = self.authorization

                # Update key/decryptor
                if "EXT-X-KEY" in i:
                    keyurl = get_full_url(i["EXT-X-KEY"]["URI"], url)
                    if keyurl and keyurl[:4] == "skd:":
                        raise HLSException(keyurl, "Can't decrypt beacuse of DRM")
                    key = self.http.request("get", keyurl, cookies=keycookies, headers=headers).content
                    iv = binascii.unhexlify(i["EXT-X-KEY"]["IV"][2:].zfill(32)) if "IV" in i["EXT-X-KEY"] else random_iv()
                    backend = default_backend()
                    cipher = Cipher(algorithms.AES(key), modes.CBC(iv), backend=backend)
                    decryptor = cipher.decryptor()

                if decryptor:
                    data = decryptor.update(data)
                else:
                    raise ValueError("No decryptor found for encrypted hls steam.")

            file_d.write(data)

            if self.config.get("capture_time") > 0 and total_duration >= self.config.get("capture_time") * 60:
                break

            if (size_media == (index + 1)) and self.config.get("live"):
                sleep_int = (start_time + max_duration * 2) - time.time()
                if sleep_int > 0:
                    time.sleep(sleep_int)

                size_media_old = size_media
                while size_media_old == size_media:
                    start_time = time.time()

                    if hls_time_stamp:
                        end_time_stamp = (datetime.utcnow() - timedelta(minutes=1,
                                                                        seconds=max_duration * 2)).replace(microsecond=0)
                        start_time_stamp = end_time_stamp - timedelta(minutes=1)

                        base_url = url.split(".m3u8")[0]
                        url = "{0}.m3u8?in={1}&out={2}?".format(base_url, start_time_stamp.isoformat(), end_time_stamp.isoformat())

                    new_m3u8 = M3U8(self.http.request("get", url, cookies=cookies).text)
                    for n_m3u in new_m3u8.media_segment:
                        if not any(d["URI"] == n_m3u["URI"] for d in m3u8.media_segment):
                            m3u8.media_segment.append(n_m3u)

                    size_media = len(m3u8.media_segment)

                    if size_media_old == size_media:
                        time.sleep(max_duration)

        file_d.close()
        if not self.config.get("silent"):
            progress_stream.write('\n')
        self.finished = True
Exemplo n.º 12
0
    def _download(self, url, file_name):
        cookies = self.kwargs.get("cookies", None)
        start_time = time.time()
        m3u8 = M3U8(self.http.request("get", url, cookies=cookies).text)
        key = None

        def random_iv():
            return os.urandom(16)

        file_d = output(file_name[0], self.config, file_name[1])
        if file_d is None:
            return

        if "EXT-X-MAP" in m3u8.media_segment[0]:
            entry = {
                "URI": get_full_url(m3u8.media_segment[0]["EXT-X-MAP"]["URI"],
                                    url),
                "EXTINF": {
                    "duration": 0
                }
            }
            if "EXT-X-KEY" in m3u8.media_segment[0]:
                entry["EXT-X-KEY"] = {
                    "URI": m3u8.media_segment[0]["EXT-X-KEY"]["URI"]
                }
            m3u8.media_segment.insert(0, entry)
        hls_time_stamp = self.kwargs.pop("hls_time_stamp", False)
        decryptor = None
        size_media = len(m3u8.media_segment)
        eta = ETA(size_media)
        total_duration = 0
        duration = 0
        max_duration = 0
        for index, i in enumerate(m3u8.media_segment):
            if "duration" in i["EXTINF"]:
                duration = i["EXTINF"]["duration"]
                max_duration = max(max_duration, duration)
                total_duration += duration
            item = get_full_url(i["URI"], url)

            if not self.config.get("silent"):
                if self.config.get("live"):
                    progressbar(
                        size_media, index + 1, "".join([
                            "DU: ",
                            str(timedelta(seconds=int(total_duration)))
                        ]))
                else:
                    eta.increment()
                    progressbar(size_media, index + 1,
                                "".join(["ETA: ", str(eta)]))

            data = self.http.request("get", item, cookies=cookies)
            if data.status_code == 404:
                break
            data = data.content

            if m3u8.encrypted:
                headers = {}
                if self.keycookie:
                    keycookies = self.keycookie
                else:
                    keycookies = cookies
                if self.authorization:
                    headers["authorization"] = self.authorization

                # Update key/decryptor
                if "EXT-X-KEY" in i:
                    keyurl = get_full_url(i["EXT-X-KEY"]["URI"], url)
                    if keyurl and keyurl[:4] == "skd:":
                        raise HLSException(keyurl,
                                           "Can't decrypt beacuse of DRM")
                    key = self.http.request("get",
                                            keyurl,
                                            cookies=keycookies,
                                            headers=headers).content
                    iv = binascii.unhexlify(i["EXT-X-KEY"]["IV"][2:].zfill(
                        32)) if "IV" in i["EXT-X-KEY"] else random_iv()
                    backend = default_backend()
                    cipher = Cipher(algorithms.AES(key),
                                    modes.CBC(iv),
                                    backend=backend)
                    decryptor = cipher.decryptor()

                # In some cases the playlist say its encrypted but the files is not.
                # This happen on svtplay 5.1ch stream where it started with ID3..
                # Adding the other ones is header for mpeg-ts files. third byte is 10 or 11..
                if data[:
                        3] != b"ID3" and data[:
                                              3] != b"\x47\x40\x11" and data[:3] != b"\x47\x40\x10" and data[
                                                  4:12] != b"ftypisom":
                    if decryptor:
                        data = decryptor.update(data)
                    else:
                        raise ValueError(
                            "No decryptor found for encrypted hls steam.")
            file_d.write(data)

            if self.config.get(
                    "capture_time"
            ) > 0 and total_duration >= self.config.get("capture_time") * 60:
                break

            if (size_media == (index + 1)) and self.config.get("live"):
                sleep_int = (start_time + max_duration * 2) - time.time()
                if sleep_int > 0:
                    time.sleep(sleep_int)

                size_media_old = size_media
                while size_media_old == size_media:
                    start_time = time.time()

                    if hls_time_stamp:
                        end_time_stamp = (datetime.utcnow() - timedelta(
                            minutes=1, seconds=max_duration * 2)).replace(
                                microsecond=0)
                        start_time_stamp = end_time_stamp - timedelta(
                            minutes=1)

                        base_url = url.split(".m3u8")[0]
                        url = f"{base_url}.m3u8?in={start_time_stamp.isoformat()}&out={end_time_stamp.isoformat()}?"

                    new_m3u8 = M3U8(
                        self.http.request("get", url, cookies=cookies).text)
                    for n_m3u in new_m3u8.media_segment:
                        if not any(d["URI"] == n_m3u["URI"]
                                   for d in m3u8.media_segment):
                            m3u8.media_segment.append(n_m3u)

                    size_media = len(m3u8.media_segment)

                    if size_media_old == size_media:
                        time.sleep(max_duration)

        file_d.close()
        if not self.config.get("silent"):
            progress_stream.write("\n")
        self.finished = True