Example #1
0
def test_add_part_to_segment():
    obj = Segment(uri='fileSequence271.ts', duration=4.00008)

    obj.add_part(PartialSegment(None, 'filePart271.0.ts', 0.33334))

    result = obj.dumps(None)
    expected = '#EXT-X-PART:DURATION=0.33334,URI="filePart271.0.ts"'

    assert expected in result
Example #2
0
def test_segment_str_method():
    segment = Segment('entire.ts', 'http://1.2/', duration=1)

    expected = '#EXTINF:1,\nentire.ts'
    result = str(segment).strip()

    assert result == expected
Example #3
0
def test_dumps_segment_with_key():
    ("Segment.dumps should render a X-KEY if present but `last_segment` is None")

    key = {
        'method': 'AES-128',
        'uri': 'http://foo.bar/key.aes',
        'iv': 1234,
    }

    segment = Segment(
        uri='http://foo.bar/video1.ts',
        duration=2,
        base_uri='http://foo.bar',
        key=key,
    )

    rendered = segment.dumps()
    assert 'X-KEY' in rendered, 'X-KEY not present in {0}'.format(rendered)
Example #4
0
def test_add_segment_to_playlist():
    obj = m3u8.M3U8()

    obj.add_segment(
        Segment(
            'entire.ts',
            'http://1.2/',
            duration=1
        )
    )
Example #5
0
def test_dumps_segment_with_key():
    ("Segment.dumps should render a X-KEY if present but `last_segment` is None"
     )

    key = {
        'method': 'AES-128',
        'uri': 'http://foo.bar/key.aes',
        'iv': 1234,
    }

    segment = Segment(
        uri='http://foo.bar/video1.ts',
        duration=2,
        base_uri='http://foo.bar',
        key=key,
    )

    rendered = segment.dumps()
    assert 'X-KEY' in rendered, 'X-KEY not present in {0}'.format(rendered)
Example #6
0
    async def video(self, url, media_dir, title, playurl):
        """
        :param url: hls 视频流文件
        :param media_dir: 下载保存目录
        :param title:  视频标题
        :param playurl: ts文件地址
        :return:
        """
        resp = await self.client.get(url, headers=self.header)

        media = loads(resp.text)
        # 拼接ts文件列表
        playlist = [
            "{playurl}{uri}".format(playurl=playurl, uri=uri)
            for uri in media.segments.uri
        ]

        n = 0
        new_segments = []
        semaphore = asyncio.BoundedSemaphore(20)
        tasks = []
        # get ts file list
        # async with self.client.parallel() as parallel:
        for url in playlist:
            ts_file = os.path.join(media_dir, title,
                                   'm_{num}.ts'.format(num=n))
            ts_path = os.path.join(title, 'm_{num}.ts'.format(num=n))
            media.data['segments'][n]['uri'] = ts_path
            new_segments.append(media.data.get('segments')[n])
            tasks.append(
                asyncio.ensure_future(
                    self.fetch_single_ts_file(url, ts_file, semaphore)))

            n += 1

        results = await asyncio.gather(*tasks)
        for download_result in results:
            if not download_result.success:
                logger.exception("url: {} download failed, reason: {}".format(
                    download_result.data_url, download_result.reason))
        # change m3u8 data
        media.data['segments'] = new_segments
        # 修改m3u8文件信息
        segments = SegmentList([
            Segment(base_uri=None,
                    keyobject=find_key(segment.get('key', {}), media.keys),
                    **segment) for segment in media.data.get('segments', [])
        ])
        media.segments = segments

        # save m3u8 file
        m3u8_file = os.path.join(media_dir, '{title}.m3u8'.format(title=title))
        if not os.path.exists(m3u8_file):
            with open(m3u8_file, 'w', encoding='utf8') as f:
                f.write(media.dumps())
Example #7
0
    def download_video(self, download_dir, resource, nocache=False):
        resource_dir = os.path.join(download_dir, resource['id'])
        os.makedirs(resource_dir, exist_ok=True)

        url = resource['video_hls'].replace('\\', '')
        self.session.headers.update({
            'Referer':
            'https://pc-shop.xiaoe-tech.com/{appid}/video_details?id={resourceid}'
            .format(appid=self.appid, resourceid=resource['id'])
        })
        media = m3u8.loads(self.session.get(url).text)
        url_prefix, segments, changed, complete = url.split(
            'v.f230')[0], SegmentList(), False, True

        print('Total: {} part'.format(len(media.data['segments'])))
        for index, segment in enumerate(media.data['segments']):
            ts_file = os.path.join(resource_dir, 'v_{}.ts'.format(index))
            if not nocache and os.path.exists(ts_file):
                print('Already Downloaded: {title} {file}'.format(
                    title=resource['title'], file=ts_file))
            else:
                url = url_prefix + segment.get('uri')
                res = self.session.get(url)
                if res.status_code == 200:
                    with open(ts_file + '.tmp', 'wb') as ts:
                        ts.write(res.content)
                    os.rename(ts_file + '.tmp', ts_file)
                    changed = True
                    print('Download Successful: {title} {file}'.format(
                        title=resource['title'], file=ts_file))
                else:
                    print('Download Failed: {title} {file}'.format(
                        title=resource['title'], file=ts_file))
                    complete = False
            segment['uri'] = 'v_{}.ts'.format(index)
            segments.append(
                Segment(base_uri=None,
                        keyobject=find_key(segment.get('key', {}), media.keys),
                        **segment))

        m3u8_file = os.path.join(resource_dir, 'video.m3u8')
        if changed or not os.path.exists(m3u8_file):
            media.segments = segments
            with open(m3u8_file, 'w', encoding='utf8') as f:
                f.write(media.dumps())
        metadata = {'title': resource['title'], 'complete': complete}
        with open(os.path.join(download_dir, resource['id'], 'metadata'),
                  'w') as f:
            json.dump(metadata, f)
        return
Example #8
0
    def video(self, url, media_dir, title, playurl):
        '''
        :param url: hls 视频流文件
        :param media_dir: 下载保存目录
        :param title:  视频标题
        :param playurl: ts文件地址
        :return:
        '''
        resp = self.session.get(url, headers=self.header)

        media = loads(resp.text)
        # 拼接ts文件列表
        playlist = ["{playurl}{uri}".format(playurl=playurl, uri=uri) for uri in media.segments.uri]

        n = 0
        new_segments = []
        # get ts file list
        for url in playlist:
            ts_file = os.path.join(media_dir, title, 'm_{num}.ts'.format(num=n))
            ts_path = os.path.join(title, 'm_{num}.ts'.format(num=n))
            media.data['segments'][n]['uri'] = ts_path
            new_segments.append(media.data.get('segments')[n])
            # 下载ts文件
            resp = self.session.get(url, headers=self.header, cookies=self.cookie)
            if resp.status_code != 200:
                print('Error: {title} {tsfile}'.format(title=title, tsfile=ts_file))

            # 如果文件不存在或者本地文件大小于接口返回大小不一致则保存ts文件
            if not os.path.exists(ts_file) or os.stat(ts_file).st_size != resp.headers['content-length']:
                with open(ts_file, 'wb') as ts:
                    ts.write(resp.content)

            n += 1

        # change m3u8 data
        media.data['segments'] = new_segments
        # 修改m3u8文件信息
        segments = SegmentList(
            [Segment(base_uri=None, keyobject=find_key(segment.get('key', {}), media.keys), **segment)
             for segment in
             media.data.get('segments', [])])
        media.segments = segments

        # save m3u8 file
        m3u8_file = os.path.join(media_dir, '{title}.m3u8'.format(title=title))
        if not os.path.exists(m3u8_file):
            with open(m3u8_file, 'wb', encoding='utf8') as f:
                f.write(media.dumps())
Example #9
0
def test_should_correctly_update_base_path_if_its_blank():
    segment = Segment('entire.ts', 'http://1.2/')
    assert not segment.base_path
    segment.base_path = "base_path"
    assert "http://1.2/base_path/entire.ts" == segment.absolute_uri
Example #10
0
def test_should_correctly_update_base_path_if_its_blank():
    segment = Segment('entire.ts', 'http://1.2/')
    assert not segment.base_path
    segment.base_path = "base_path"
    assert "http://1.2/base_path/entire.ts" == segment.absolute_uri
Example #11
0
def test_base_path_should_just_return_uri_if_absolute():
    segment = Segment('http://1.2/entire.ts', '')
    assert 'http://1.2/entire.ts' == segment.absolute_uri