def downloadThread(self, v): #Logger.log('thread starting bps=%d\n'% v.bps) dirname = self.out_dir + '/' + str(v.bps) + '/' try: os.makedirs(dirname) except OSError as e: if (e.errno != errno.EEXIST): raise e out_playlist = m3u8.Playlist(dirname + '/index.m3u8') in_playlist = m3u8.parse(v.absolute_url) seq = in_playlist.media_sequence while True: e = in_playlist.getEntry(seq) if (not e): if (not in_playlist.endlist): time.sleep(1) in_playlist = m3u8.parse(v.absolute_url) if (in_playlist.media_sequence > seq): Logger.log('sequence discontinuity: %d -> %d\n' % seq, in_playlist.media_sequence) seq = in_playlist.media_sequence e = in_playlist.getEntry(seq) if (not e): Logger.log('empty playlist\n') continue else: continue else: #Logger.log('reached endlist\n') break Logger.log(e.absolute_url + '\n') try: r = requests.get(e.absolute_url) except requests.exceptions.RequestException as ex: time.sleep(1) Logger.log('exception on ' + e.absolute_url + ' ' + ex) continue if (r.status_code/100 != 2): Logger.log('error %d on %s\n', r.status_code, e.absolute_url) continue tsname = str(seq) + '.ts' with open(dirname + '/' + tsname, 'wb') as fd: for chunk in r.iter_content(128 * 1024): fd.write(chunk) e.url = tsname out_playlist.append_entry(e) out_playlist.save() seq += 1 #Logger.log('download endlist\n') out_playlist.endlist = True out_playlist.save() self.queue.put(Extractor.MESSAGE_THREAD_DONE)
def test_should_parse_variant_playlist_with_bandwidth_as_float(): data = m3u8.parse(playlists.VARIANT_PLAYLIST_WITH_BANDWIDTH_FLOAT) playlists_list = list(data['playlists']) assert 1280000 == playlists_list[0]['stream_info']['bandwidth'] assert 2560000 == playlists_list[1]['stream_info']['bandwidth'] assert 7680000 == playlists_list[2]['stream_info']['bandwidth'] assert 65000 == playlists_list[3]['stream_info']['bandwidth']
def test_should_parse_playlist_using_byteranges(): data = m3u8.parse(playlists.PLAYLIST_USING_BYTERANGES) assert False == data['is_i_frames_only'] assert 10 == data['segments'][0]['duration'] assert '76242@0' == data['segments'][0]['byterange'] assert 'segment.ts' == data['segments'][0]['uri']
def select_quailty(guid = common.args.url): video_url = VIDEO % guid sbitrate = int(addon.getSetting('quality')) * 1024 closedcaption = None video_url2 = None video_data = connection.getURL(video_url) video_menu = simplejson.loads(video_data)['items'] video_item = video_menu[0] bitrates = [] if addon.getSetting('preffered_stream_type') == 'RTMP': for video in video_item['videos']['flash'].itervalues(): try: bitrate = video['bitrate'] bitrates.append((bitrate,bitrate)) except: pass else: ipad_url = video_item['videos']['iphone']['url'] video_data2 = connection.getURL(ipad_url + '?format=json') video_url3 = simplejson.loads(video_data2)['url'] video_data3 = connection.getURL(video_url3) video_url4 = m3u8.parse(video_data3) uri = None for video_index in video_url4.get('playlists'): try: codecs = video_index.get('stream_info')['codecs'] except: codecs = '' if codecs != 'mp4a.40.5': bitrate = int(video_index.get('stream_info')['bandwidth']) bitrates.append((int(bitrate) / 1024 , bitrate)) return bitrates
def test_should_parse_iframe_playlist(): data = m3u8.parse(playlists.IFRAME_PLAYLIST) assert True == data['is_i_frames_only'] assert 4.12 == data['segments'][0]['duration'] assert '9400@376' == data['segments'][0]['byterange'] assert 'segment1.ts' == data['segments'][0]['uri']
def test_should_parse_scte35_from_playlist(): data = m3u8.parse(playlists.CUE_OUT_ELEMENTAL_PLAYLIST) assert not data['segments'][2]['cue_out'] assert data['segments'][3]['scte35'] assert data['segments'][3]['cue_out'] assert '/DAlAAAAAAAAAP/wFAUAAAABf+//wpiQkv4ARKogAAEBAQAAQ6sodg==' == data['segments'][4]['scte35'] assert '50' == data['segments'][4]['scte35_duration']
def test_should_parse_sliding_window_playlist_from_string(): data = m3u8.parse(playlists.SLIDING_WINDOW_PLAYLIST) assert 8 == data['targetduration'] assert 2680 == data['media_sequence'] assert ['https://priv.example.com/fileSequence2680.ts', 'https://priv.example.com/fileSequence2681.ts', 'https://priv.example.com/fileSequence2682.ts'] == [c['uri'] for c in data['segments']] assert [8, 8, 8] == [c['duration'] for c in data['segments']]
def m3u_bitrates(m3u_url): bitrates = [] video_data2 = connection.getURL(m3u_url, savecookie = True) video_url5 = m3u8.parse(video_data2) for video_index in video_url5.get('playlists'): bitrate = int(video_index.get('stream_info')['bandwidth']) bitrates.append((int(bitrate) / 1024, bitrate)) return bitrates
def test_should_parse_envivio_cue_playlist(): data = m3u8.parse(playlists.CUE_OUT_ENVIVIO_PLAYLIST) assert data['segments'][3]['scte35'] assert data['segments'][3]['cue_out'] assert '/DAlAAAENOOQAP/wFAUBAABrf+//N25XDf4B9p/gAAEBAQAAxKni9A==' == data['segments'][3]['scte35'] assert '366' == data['segments'][3]['scte35_duration'] assert data['segments'][4]['cue_out'] assert '/DAlAAAENOOQAP/wFAUBAABrf+//N25XDf4B9p/gAAEBAQAAxKni9A==' == data['segments'][4]['scte35'] assert '/DAlAAAENOOQAP/wFAUBAABrf+//N25XDf4B9p/gAAEBAQAAxKni9A==' == data['segments'][5]['scte35']
def test_should_handle_key_method_none_and_no_uri_attr(): data = m3u8.parse(playlists.PLAYLIST_WITH_MULTIPLE_KEYS_UNENCRYPTED_AND_ENCRYPTED_NONE_AND_NO_URI_ATTR) assert 'key' not in data['segments'][0] assert 'key' not in data['segments'][1] third_segment_key = data['segments'][2]['key'] assert "/hls-key/key.bin" == third_segment_key['uri'] assert "AES-128" == third_segment_key['method'] assert "0X10ef8f758ca555115584bb5b3c687f52" == third_segment_key['iv'] assert "NONE" == data['segments'][6]['key']['method']
def test_should_add_key_attribute_to_segment_from_playlist(): data = m3u8.parse(playlists.PLAYLIST_WITH_ENCRIPTED_SEGMENTS_AND_IV_WITH_MULTIPLE_KEYS) first_segment_key = data['segments'][0]['key'] assert "/hls-key/key.bin" == first_segment_key['uri'] assert "AES-128" == first_segment_key['method'] assert "0X10ef8f758ca555115584bb5b3c687f52" == first_segment_key['iv'] last_segment_key = data['segments'][-1]['key'] assert "/hls-key/key2.bin" == last_segment_key['uri'] assert "AES-128" == last_segment_key['method'] assert "0Xcafe8f758ca555115584bb5b3c687f52" == last_segment_key['iv']
def test_should_parse_playlist_with_encripted_segments_from_string(): data = m3u8.parse(playlists.PLAYLIST_WITH_ENCRIPTED_SEGMENTS) assert 7794 == data['media_sequence'] assert 15 == data['targetduration'] assert 'AES-128' == data['key']['method'] assert 'https://priv.example.com/key.php?r=52' == data['key']['uri'] assert ['http://media.example.com/fileSequence52-1.ts', 'http://media.example.com/fileSequence52-2.ts', 'http://media.example.com/fileSequence52-3.ts'] == [c['uri'] for c in data['segments']] assert [15, 15, 15] == [c['duration'] for c in data['segments']]
def process_m3u(m3u_url, qbitrate = None): key_url = None sbitrate = int(addon.getSetting('quality')) * 1024 lbitrate = -1 hbitrate = -1 video_data2 = connection.getURL(m3u_url, savecookie = True) video_url5 = m3u8.parse(video_data2) for video_index in video_url5.get('playlists'): bitrate = int(video_index.get('stream_info')['bandwidth']) try: codecs = video_index.get('stream_info')['codecs'] except: codecs = '' if qbitrate is None: if (bitrate < lbitrate or lbitrate == -1): lbitrate = bitrate lplaypath_url = video_index.get('uri') if (bitrate > hbitrate and bitrate <= sbitrate): hbitrate = bitrate playpath_url = video_index.get('uri') elif bitrate == qbitrate: playpath_url = video_index.get('uri') if playpath_url is None: playpath_url = lplaypath_url if not common.use_proxy() and int(addon.getSetting('connectiontype')) == 0: player._localHTTPServer = False return playpath_url else: m3u_data = connection.getURL(playpath_url, loadcookie = True) try: key_url = re.compile('URI="(.*?)"').findall(m3u_data)[0] key_data = connection.getURL(key_url, loadcookie = True) key_file = open(ustvpaths.KEYFILE % '0', 'wb') key_file.write(key_data) key_file.close() except: pass video_url5 = re.compile('(http:.*?)\n').findall(m3u_data) if int(addon.getSetting('connectiontype')) > 0: proxy_config = common.proxyConfig() for i, video_item in enumerate(video_url5): newurl = base64.b64encode(video_item) newurl = urllib.quote_plus(newurl) m3u_data = m3u_data.replace(video_item, 'http://127.0.0.1:12345/proxy/' + newurl + '/' + proxy_config) filestring = 'XBMC.RunScript(' + os.path.join(ustvpaths.LIBPATH,'proxy.py') + ', 12345)' xbmc.executebuiltin(filestring) time.sleep(20) if key_url is not None: m3u_data = m3u_data.replace(key_url, 'http://127.0.0.1:12345/play0.key') playfile = open(ustvpaths.PLAYFILE, 'w') playfile.write(m3u_data) playfile.close() return ustvpaths.PLAYFILE
def test_should_parse_variant_playlist_with_average_bandwidth(): data = m3u8.parse(playlists.VARIANT_PLAYLIST_WITH_AVERAGE_BANDWIDTH) playlists_list = list(data['playlists']) assert 1280000 == playlists_list[0]['stream_info']['bandwidth'] assert 1252345 == playlists_list[0]['stream_info']['average_bandwidth'] assert 2560000 == playlists_list[1]['stream_info']['bandwidth'] assert 2466570 == playlists_list[1]['stream_info']['average_bandwidth'] assert 7680000 == playlists_list[2]['stream_info']['bandwidth'] assert 7560423 == playlists_list[2]['stream_info']['average_bandwidth'] assert 65000 == playlists_list[3]['stream_info']['bandwidth'] assert 63005 == playlists_list[3]['stream_info']['average_bandwidth']
def list_qualities(video_url = common.args.url): bitrates = [] video_data = connection.getURL(video_url + '&manifest=m3u') video_tree = BeautifulSoup(video_data, 'html.parser') video_url2 = video_tree.find('video', src = True)['src'] video_data2 = connection.getURL(video_url2, savecookie = True) video_url3 = m3u8.parse(video_data2) for video_index in video_url3.get('playlists'): bitrate = int(video_index.get('stream_info')['bandwidth']) if bitrate > 100000: bitrates.append((bitrate / 1000, bitrate)) return bitrates
def run(self): variants = [] try: os.makedirs(self.out_dir) except OSError as e: if (e.errno != errno.EEXIST): raise e out_playlist = m3u8.Playlist(self.out_dir + '/index.m3u8') in_playlist = m3u8.parse(sys.argv[1]) for v in in_playlist.variants: variants.append(v) if (len(variants) == 0): v = m3u8.Variant(sys.argv[1], 0) variants.append(v) Logger.log('type \'q[enter]\' to terminate\n') for v in variants: v2 = copy.copy(v) v2.url = str(v2.bps) + '/index.m3u8' Logger.log('variant: ' + v.absolute_url + '\n') out_playlist.append_variant(v2) out_playlist.save() thread_count = 0 for v in variants: t = DebuggableThread(target = self.downloadThread, args = (v,)) t.daemon = True t.start() thread_count += 1 t = DebuggableThread(target = self.keyboardThread) t.daemon = True t.start() while (True): try: #we need a timeout so that Ctrl-C is caught m = self.queue.get(timeout=0.1) except Queue.Empty: continue if (m == Extractor.MESSAGE_QUIT): self.done() elif (m == Extractor.MESSAGE_THREAD_DONE): thread_count -= 1 #Logger.log('%d threads remaining\n'%thread_count) if (thread_count == 0): self.done()
def test_simple_playlist_with_custom_tags(): def get_movie(line, data, lineno): custom_tag = line.split(':') if len(custom_tag) == 2: data['movie'] = custom_tag[1].strip() data = m3u8.parse(playlists.SIMPLE_PLAYLIST_WITH_CUSTOM_TAGS, strict=False, custom_tags_parser=get_movie) assert data['movie'] == 'million dollar baby' assert 5220 == data['targetduration'] assert 0 == data['media_sequence'] assert ['http://media.example.com/entire.ts'] == [c['uri'] for c in data['segments']] assert [5220] == [c['duration'] for c in data['segments']]
def list_qualities(video_url=common.args.url): bitrates = [] video_data = connection.getURL(video_url + "&manifest=m3u") video_tree = BeautifulSoup(video_data, "html.parser") video_url2 = video_tree.find("video", src=True)["src"] video_data2 = connection.getURL(video_url2, savecookie=True) video_url3 = m3u8.parse(video_data2) for video_index in video_url3.get("playlists"): bitrate = int(video_index.get("stream_info")["bandwidth"]) if bitrate > 100000: bitrates.append((bitrate / 1000, bitrate)) return bitrates
def test_should_add_non_key_for_multiple_keys_unencrypted_and_encrypted(): data = m3u8.parse(playlists.PLAYLIST_WITH_MULTIPLE_KEYS_UNENCRYPTED_AND_ENCRYPTED) # First two segments have no Key, so it's not in the dictionary assert 'key' not in data['segments'][0] assert 'key' not in data['segments'][1] third_segment_key = data['segments'][2]['key'] assert "/hls-key/key.bin" == third_segment_key['uri'] assert "AES-128" == third_segment_key['method'] assert "0X10ef8f758ca555115584bb5b3c687f52" == third_segment_key['iv'] last_segment_key = data['segments'][-1]['key'] assert "/hls-key/key2.bin" == last_segment_key['uri'] assert "AES-128" == last_segment_key['method'] assert "0Xcafe8f758ca555115584bb5b3c687f52" == last_segment_key['iv']
def list_qualities(SITE, BRANDID, PARTNERID): video_id, video_type = common.args.url.split('#') bitrates = [] video_auth = get_authorization(BRANDID, video_id, video_type) if video_auth is False: video_url = VIDEOLIST % BRANDID + '001/-1/-1/-1/' + video_id + '/-1/-1' video_data = connection.getURL(video_url) try: video_data2 = simplejson.loads(video_data)['videos']['video'] video_format = video_data2['assets']['asset'][0]['@format'] except: try: video_data2 = simplejson.loads(video_data)['videos']['video'] video_format = video_data2['assets']['asset']['@format'] #video_closedcaption = video_data2['closedcaption']['@enabled'] except: video_format = 'MOV' #video_closedcaption = 'false' video_id = video_id.replace('VDKA','') if video_format == 'MP4': video_url = PLAYLISTMP4 % (PARTNERID, PARTNERID) + video_id video_data = connection.getURL(video_url) video_url2 = m3u8.parse(video_data) for video_index in video_url2.get('playlists'): bitrate = int(video_index.get('stream_info')['bandwidth']) bitrate.append((bitrate / 1000, bitrate)) elif video_format == 'MOV': video_url = PLAYLISTMOV % (PARTNERID, PARTNERID) + video_id video_data = connection.getURL(video_url) video_tree = BeautifulSoup(video_data, 'html.parser') base_url = video_tree('baseurl')[0].string video_url2 = video_tree.findAll('media') for video_index in video_url2: bitrate = int(video_index['bitrate']) bitrates.append((bitrate, bitrate)) else: video_url = VIDEOLIST % BRANDID + '002/-1/-1/-1/' + video_id + '/-1/-1' video_data = connection.getURL(video_url) video_data2 = simplejson.loads(video_data)['videos']['video'] video_closedcaption = video_data2['closedcaption']['@enabled'] try: video_url2 = video_data2['assets']['asset']['$'] + video_auth except: video_url2 = video_data2['assets']['asset'][1]['$'] + video_auth video_data3 = connection.getURL(video_url2.replace('m3u8','json')) video_url3 = simplejson.loads(video_data3) for video_keys in BITRATETABLE.iterkeys(): bitrate = int(video_keys) bitrates.append((bitrate, bitrate)) return bitrates
def select_quailty(guid = common.args.url): video_url = VIDEO % guid #hbitrate = -1 #lbitrate = -1 sbitrate = int(addon.getSetting('quality')) * 1024 closedcaption = None video_url2 = None #finalurl = '' video_data = connection.getURL(video_url) video_menu = simplejson.loads(video_data)['items'] video_item = video_menu[0] #try: # closedcaption = video_item['captions']['sami']['url'] #except: # pass # if (addon.getSetting('enablesubtitles') == 'true') and (closedcaption is not None) and (closedcaption != ''): # convert_subtitles(closedcaption.replace(' ', '+')) bitrates = [] if addon.getSetting('preffered_stream_type') == 'RTMP': for video in video_item['videos']['flash'].itervalues(): try: bitrate = video['bitrate'] # if bitrate < lbitrate or lbitrate == -1: # lbitrate = bitrate # luri = video['url'] # if bitrate > hbitrate and bitrate <= sbitrate: # hbitrate = bitrate # uri = video['url'] # print video bitrates.append((bitrate,bitrate)) except: pass #print uri,luri else: ipad_url = video_item['videos']['iphone']['url'] video_data2 = connection.getURL(ipad_url + '?format=json') video_url3 = simplejson.loads(video_data2)['url'] video_data3 = connection.getURL(video_url3) video_url4 = m3u8.parse(video_data3) uri = None for video_index in video_url4.get('playlists'): try: codecs = video_index.get('stream_info')['codecs'] except: codecs = '' if codecs != 'mp4a.40.5': bitrate = int(video_index.get('stream_info')['bandwidth']) bitrates.append((int(bitrate) / 1024 , bitrate)) return bitrates
def test_should_parse_variant_playlist(): data = m3u8.parse(playlists.VARIANT_PLAYLIST) playlists_list = list(data['playlists']) assert True == data['is_variant'] assert 4 == len(playlists_list) assert 'http://example.com/low.m3u8' == playlists_list[0]['uri'] assert '1' == playlists_list[0]['stream_info']['program_id'] assert '1280000' == playlists_list[0]['stream_info']['bandwidth'] assert 'http://example.com/audio-only.m3u8' == playlists_list[-1]['uri'] assert '1' == playlists_list[-1]['stream_info']['program_id'] assert '65000' == playlists_list[-1]['stream_info']['bandwidth'] assert 'mp4a.40.5,avc1.42801e' == playlists_list[-1]['stream_info']['codecs']
def list_qualities(): video_url = common.args.url bitrates = [] sig = sign_url(video_url) smil_url = re.compile('(.+)\?').findall(video_url)[0] + '?switch=hls&assetTypes=medium_video_s3&mbr=true&metafile=true&sig=' + sig video_data = connection.getURL(smil_url) smil_tree = BeautifulSoup(video_data, 'html.parser') video_url2 = smil_tree.video['src'] m3u_master_data = connection.getURL(video_url2) m3u_master = m3u8.parse(m3u_master_data) for video_index in m3u_master.get('playlists'): bitrate = int(video_index.get('stream_info')['bandwidth']) display = int(bitrate) / 1024 bitrates.append((display, bitrate)) return bitrates
def list_qualities2(API, video_url = common.args.url): video_bitrates = [] video_data = connection.getURL(API + 'playlists/%s/videos.json' % video_url) video_tree = simplejson.loads(video_data) video_mgid = video_tree['playlist']['videos'][0]['video']['mgid'] video_data2 = connection.getURL(VIDEOURLAPI % video_mgid) video_tree2 = BeautifulSoup(video_data2, 'html.parser') video_menu = video_tree2.find('src').string m3u8_url = None m3u8_master_data = connection.getURL(video_menu, savecookie = True) m3u8_master = m3u8.parse(m3u8_master_data) for video_index in m3u8_master.get('playlists'): video_bitrate = int(video_index.get('stream_info')['bandwidth']) bitrate_display = int(video_bitrate) / 1024 video_bitrates.append((bitrate_display, video_bitrate)) return video_bitrates
def list_qualities(): exception = False video_url = common.args.url bitrates = [] video_data = connection.getURL(video_url) video_tree = BeautifulSoup(video_data, 'html.parser') try: video_rtmp = video_tree.meta['base'] except: video_rtmp = None if 'link.theplatform.com' not in video_url: video_tree = BeautifulSoup(video_data, 'html.parser') player_url = 'http:' + video_tree.find('div', class_ = 'video-player-wrapper').iframe['src'] player_data = connection.getURL(player_url) player_tree = BeautifulSoup(player_data, 'html.parser') video_url = player_tree.find('link', type = "application/smil+xml")['href'] video_url = video_url + '&format=SMIL' video_data = connection.getURL(video_url) if video_rtmp is not None: for video_index in video_rtmp: bitrate = int(video_index['system-bitrate']) display = int(bitrate) bitrates.append((display, bitrate)) else: video_data = connection.getURL(video_url + '&manifest=m3u') video_tree = BeautifulSoup(video_data, 'html.parser') if video_tree.find('param', attrs = {'name' : 'isException', 'value' : 'true'}) is None: video_url2 = video_tree.seq.find_all('video')[0] video_url3 = video_url2['src'] video_data2 = connection.getURL(video_url3) video_url4 = m3u8.parse(video_data2) for video_index in video_url4.get('playlists'): bitrate = int(video_index.get('stream_info')['bandwidth']) try: codecs = video_index.get('stream_info')['codecs'] except: codecs = '' display = int(bitrate) / 1024 bitrates.append((display, bitrate)) else: exception = True if not exception: return bitrates else: common.show_exception(video_tree.ref['title'], video_tree.ref['abstract'])
def play_video(video_url = common.args.url): hbitrate = -1 sbitrate = int(addon.getSetting('quality')) * 1024 closedcaption = None video_data = connection.getURL(video_url) video_tree = BeautifulSoup(video_data, 'html.parser') video_rtmp = video_tree.meta if video_rtmp is not None: base_url = video_rtmp['base'] video_url2 = video_tree.switch.find_all('video') for video_index in video_url2: bitrate = int(video_index['system-bitrate']) if bitrate > hbitrate and bitrate <= sbitrate: hbitrate = bitrate playpath_url = video_index['src'] if '.mp4' in playpath_url: playpath_url = 'mp4:'+ playpath_url else: playpath_url = playpath_url.replace('.flv','') finalurl = base_url +' playpath=' + playpath_url + ' swfurl=' + SWFURL + ' swfvfy=true' else: video_data = connection.getURL(video_url + '&manifest=m3u') video_tree = BeautifulSoup(video_data, 'html.parser') try: closedcaption = video_tree.textstream['src'] except: pass if (addon.getSetting('enablesubtitles') == 'true') and (closedcaption is not None): convert_subtitles(closedcaption)# video_url2 = video_tree.seq.find_all('video')[0] video_url3 = video_url2['src'] video_url4 = video_url3.split('/')[-1] video_data2 = connection.getURL(video_url3) video_url5 = m3u8.parse(video_data2) for video_index in video_url5.get('playlists'): bitrate = int(video_index.get('stream_info')['bandwidth']) if bitrate > hbitrate and bitrate <= sbitrate: hbitrate = bitrate finalurl = video_url3.replace(video_url4, video_index.get('uri')) xbmcplugin.setResolvedUrl(pluginHandle, True, xbmcgui.ListItem(path = finalurl)) if (addon.getSetting('enablesubtitles') == 'true') and (closedcaption is not None): while not xbmc.Player().isPlaying(): xbmc.sleep(100) xbmc.Player().setSubtitles(ustvpaths.SUBTITLE)
def test_should_parse_variant_playlist_with_alt_iframe_playlists_layout(): data = m3u8.parse(playlists.VARIANT_PLAYLIST_WITH_ALT_IFRAME_PLAYLISTS_LAYOUT) iframe_playlists = list(data['iframe_playlists']) assert True == data['is_variant'] assert 4 == len(iframe_playlists) assert '1' == iframe_playlists[0]['iframe_stream_info']['program_id'] assert '151288' == iframe_playlists[0]['iframe_stream_info']['bandwidth'] assert '624x352' == iframe_playlists[0]['iframe_stream_info']['resolution'] assert 'avc1.4d001f' == iframe_playlists[0]['iframe_stream_info']['codecs'] assert 'video-800k-iframes.m3u8' == iframe_playlists[0]['uri'] assert '38775' == iframe_playlists[-1]['iframe_stream_info']['bandwidth'] assert 'avc1.4d001f' == ( iframe_playlists[-1]['iframe_stream_info']['codecs'] ) assert 'video-150k-iframes.m3u8' == iframe_playlists[-1]['uri']
def play_video(SITE): video_url = common.args.url try: qbitrate = common.args.quality except: qbitrate = None hbitrate = -1 lbitrate = -1 sbitrate = int(addon.getSetting('quality')) video_data = connection.getURL(video_url) smil_url = re.compile('video_auth_playlist_url = "(.*)"').findall(video_data)[0] smil_data = connection.getURL(smil_url + '&manifest=m3u') video_tree2 = BeautifulSoup(smil_data, 'html.parser') video_url3 = video_tree2.video['src'] video_data3 = connection.getURL(video_url3) video_url4 = m3u8.parse(video_data3) video_url5 = None for video_index in video_url4.get('playlists'): bitrate = int(video_index.get('stream_info')['bandwidth']) if qbitrate is None: try: codecs = video_index.get('stream_info')['codecs'] except: codecs = '' if (bitrate < lbitrate or lbitrate == -1) and 'mp4a.40.2' != codecs: lbitrate = bitrate lvideo_url5 = video_index.get('uri') if bitrate > hbitrate and bitrate <= (sbitrate * 1000) and codecs != 'mp4a.40.2': hbitrate = bitrate video_url5 = video_index.get('uri') elif bitrate == qbitrate: video_url5 = video_index.get('uri') if video_url5 is None: video_url5 = lvideo_url5 finalurl = video_url5 item = xbmcgui.ListItem(path = finalurl) if qbitrate is not None: item.setThumbnailImage(common.args.thumb) item.setInfo('Video', { 'title' : common.args.name, 'season' : common.args.season_number, 'episode' : common.args.episode_number, 'TVShowTitle' : common.args.show_title }) xbmcplugin.setResolvedUrl(pluginHandle, True, item)
def list_qualities(): video_url = common.args.url bitrates = [] sig = sign_url(video_url) smil_url = ( re.compile("(.+)\?").findall(video_url)[0] + "?switch=hls&assetTypes=medium_video_s3&mbr=true&metafile=true&sig=" + sig ) video_data = connection.getURL(smil_url) smil_tree = BeautifulSoup(video_data, "html.parser") video_url2 = smil_tree.video["src"] m3u_master_data = connection.getURL(video_url2) m3u_master = m3u8.parse(m3u_master_data) for video_index in m3u_master.get("playlists"): bitrate = int(video_index.get("stream_info")["bandwidth"]) display = int(bitrate) / 1024 bitrates.append((display, bitrate)) return bitrates
def list_qualities(SITE): video_url = common.args.url bitrates = [] video_data = connection.getURL(video_url) smil_url = re.compile("window.video_auth_playlist_url = '(.*)'").findall(video_data)[0] smil_data = connection.getURL(smil_url + '&manifest=m3u') video_tree2 = BeautifulSoup(smil_data, 'html.parser') video_url3 = video_tree2.video['src'] video_data3 = connection.getURL(video_url3) video_url4 = m3u8.parse(video_data3) for video_index in video_url4.get('playlists'): try: codecs = video_index.get('stream_info')['codecs'] except: codecs = '' if codecs != 'mp4a.40.2': bitrate = int(video_index.get('stream_info')['bandwidth']) display = int(bitrate) / 1000 bitrates.append((display, bitrate)) return bitrates
def test_should_parse_start_with_negative_time_offset(): data = m3u8.parse(playlists.SIMPLE_PLAYLIST_WITH_START_NEGATIVE_OFFSET) assert data['start']['time_offset'] == -2.0 assert not hasattr(data['start'], 'precise')
def play_video(SITE, EPISODE, HLSPATH=None): localhttpserver = False try: qbitrate = common.args.quality except: qbitrate = None stack_url = '' for v, video_id in enumerate(common.args.url.split(',')): if 'http' not in video_id: video_url = EPISODE % video_id else: video_url = video_id hbitrate = -1 sbitrate = int(getSetting('quality')) closedcaption = None video_data = connection.getURL(video_url) video_tree = BeautifulSoup(video_data, 'html.parser') hbitrate = -1 lbitrate = -1 file_url = None if video_tree.find('file', text=re.compile('mp4:')) is not None: hasRTMP = False else: hasRTMP = True if (getSetting('preffered_stream_type') == 'RTMP' and int(getSetting('connectiontype')) == 0) or hasRTMP: if qbitrate is None: video_menu = video_tree.find_all('file') for video_index in video_menu: try: try: play_mode = video_index['play_mode'] except: play_mode = '' if play_mode != 'window': bitrate = int(video_index['bitrate']) if bitrate < lbitrate or lbitrate == -1: lbitrate = bitrate, sbitrate lfile_url = video_index.string if bitrate > hbitrate and bitrate <= sbitrate: hbitrate = bitrate file_url = video_index.string except: pass if file_url is None: file_url = lfile_url else: file_url = video_tree.find('file', attrs={ 'bitrate': qbitrate }).string if 'mp4:' in file_url: filename = file_url[1:len(file_url) - 4] serverDetails = video_tree.find('akamai') server = serverDetails.find('src').string.split('://')[1] tokentype = serverDetails.find('authtokentype').string window = serverDetails.find('window').string aifp = serverDetails.find('aifp').string auth = getAUTH(aifp, window, tokentype, video_id, filename.replace('mp4:', ''), SITE) rtmp = 'rtmpe://' + server + '?' + auth + ' playpath=' + filename + ' swfurl=' + SWFURL + ' swfvfy=true' segurl = rtmp elif 'http' not in file_url: segurl = BASE + file_url else: segurl = file_url else: video = video_tree.find('file', bitrate='androidtablet').string video_url = HLSBASE % HLSPATH + video[1:] m3u8_data = connection.getURL(video_url) m3u8 = m3u8.parse(m3u8_data) uri = None for video_index in m3u8.get('playlists'): if int(video_index.get('stream_info')['bandwidth']) > 64000: bitrate = int( video_index.get('stream_info')['bandwidth']) / 1024 if bitrate < lbitrate or lbitrate == -1: lbitrate = bitrate lplaypath_url = video_index.get('uri') if bitrate > hbitrate and bitrate <= sbitrate: hbitrate = bitrate playpath_url = video_index.get('uri') if playpath_url is None: playpath_url = lplaypath_url master = video_url.split('/')[-1] segurl = video_url.replace(master, playpath_url) if int(getSetting('connectiontype')) > 0: localhttpserver = True play_data = connection.getURL(segurl) relative_urls = re.compile('(.*ts)\n').findall(play_data) relative_k_urls = re.compile('"(.*key)"').findall(play_data) proxy_config = common.proxyConfig() for i, video_item in enumerate(relative_urls): absolueurl = video_url.replace(master, video_item) newurl = base64.b64encode(absolueurl) newurl = urllib.quote_plus(newurl) newurl = newurl + '/' + proxy_config newurl = 'http://127.0.0.1:12345/proxy/' + newurl play_data = play_data.replace(video_item, newurl) for i, video_item in enumerate(relative_k_urls): absolueurl = video_url.replace(master, video_item) key_data = connection.getURL(absolueurl) key_file = open( ustvpaths.KEYFILE % (str(v) + '-' + str(i)), 'wb') key_file.write(key_data) key_file.close() play_data = play_data.replace( video_item, 'http://127.0.0.1:12345/play%s.key' % (str(v) + '-' + str(i))) file_name = ustvpaths.PLAYFILE.replace('.m3u8', str(v) + '.m3u8') playfile = open(file_name, 'w') playfile.write(play_data) playfile.close() segurl = 'http://127.0.0.1:12345/' + file_name.split('\\')[-1] stack_url += segurl.replace(',', ',,') + ' , ' if ', ' in stack_url: stack_url = 'stack://' + stack_url finalurl = stack_url[:-3] if localhttpserver: filestring = 'XBMC.RunScript(' + os.path.join(ustvpaths.LIBPATH, 'proxy.py') + ', 12345)' xbmc.executebuiltin(filestring) time.sleep(20) item = xbmcgui.ListItem(path=finalurl) try: item.setThumbnailImage(common.args.thumb) except: pass try: item.setInfo( 'Video', { 'title': common.args.name, 'season': common.args.season_number, 'episode': common.args.episode_number, 'TVShowTitle': common.args.show_title }) except: pass xbmcplugin.setResolvedUrl(pluginHandle, True, item) if localhttpserver: while player.is_active: player.sleep(250)
def test_should_parse_variant_playlist_with_hdcp_level(): data = m3u8.parse(playlists.VARIANT_PLAYLIST_WITH_HDCP_LEVEL) playlists_list = list(data['playlists']) assert 'NONE' == playlists_list[0]['stream_info']['hdcp_level'] assert 'TYPE-0' == playlists_list[1]['stream_info']['hdcp_level'] assert 'TYPE-1' == playlists_list[2]['stream_info']['hdcp_level']
def test_master_playlist_with_unrounded_frame_rate(): data = m3u8.parse(playlists.VARIANT_PLAYLIST_WITH_ROUNDABLE_FRAME_RATE) playlists_list = list(data['playlists']) assert 12.54321 == playlists_list[0]['stream_info']['frame_rate']
def test_delta_playlist_daterange_skipping(): data = m3u8.parse(playlists.DELTA_UPDATE_SKIP_DATERANGES_PLAYLIST) assert data['skip']['recently_removed_dateranges'] == "1" assert data['server_control']['can_skip_dateranges'] == "YES"
def test_parse_simple_playlist_messy(): data = m3u8.parse(playlists.SIMPLE_PLAYLIST_MESSY) assert 5220 == data['targetduration'] assert 0 == data['media_sequence'] assert ['http://media.example.com/entire.ts'] == [c['uri'] for c in data['segments']] assert [5220] == [c['duration'] for c in data['segments']]
def test_should_parse_segment_map_uri(): data = m3u8.parse(playlists.MAP_URI_PLAYLIST) assert data['segment_map']['uri'] == "fileSequence0.mp4"
def test_parse_simple_playlist_messy_strict(): with pytest.raises(ParseError) as catch: m3u8.parse(playlists.SIMPLE_PLAYLIST_MESSY, strict=True) assert str(catch.value) == 'Syntax error in manifest on line 5: JUNK'
def test_should_parse_program_date_time_from_playlist(): data = m3u8.parse(playlists.SIMPLE_PLAYLIST_WITH_PROGRAM_DATE_TIME) assert arrow.get('2014-08-13T13:36:33+00:00').datetime == data['program_date_time']
def test_should_parse_VERSION(): data = m3u8.parse(playlists.PLAYLIST_WITH_ENCRIPTED_SEGMENTS_AND_IV) assert '2' == data['version']
def test_should_parse_ALLOW_CACHE(): data = m3u8.parse(playlists.PLAYLIST_WITH_ENCRIPTED_SEGMENTS_AND_IV) assert 'no' == data['allow_cache']
def play_video(): try: qbitrate = common.args.quality except: qbitrate = None closedcaption = None video_url = common.args.url sig = sign_url(video_url) smil_url = re.compile('(.+)\?').findall( video_url )[0] + '?switch=hls&assetTypes=medium_video_s3&mbr=true&metafile=true&sig=' + sig smil_data = connection.getURL(smil_url) smil_tree = BeautifulSoup(smil_data, 'html.parser') video_url2 = smil_tree.video['src'] try: closedcaption = smil_tree.textstream['src'] except: pass m3u_master_data = connection.getURL(video_url2, savecookie=True) m3u_master = m3u8.parse(m3u_master_data) hbitrate = -1 sbitrate = int(addon.getSetting('quality')) * 1024 for video_index in m3u_master.get('playlists'): bitrate = int(video_index.get('stream_info')['bandwidth']) if qbitrate is None: if bitrate > hbitrate and bitrate <= sbitrate: hbitrate = bitrate m3u8_url = video_index.get('uri') elif bitrate == qbitrate: m3u8_url = video_index.get('uri') m3u_data = connection.getURL(m3u8_url, loadcookie=True) key_url = re.compile('URI="(.*?)"').findall(m3u_data)[0] key_data = connection.getURL(key_url, loadcookie=True) key_file = open(ustvpaths.KEYFILE % '0', 'wb') key_file.write(key_data) key_file.close() video_url5 = re.compile('(http:.*?)\n').findall(m3u_data) for i, video_item in enumerate(video_url5): newurl = base64.b64encode(video_item) newurl = urllib.quote_plus(newurl) m3u_data = m3u_data.replace( video_item, 'http://127.0.0.1:12345/0/foxstation/' + newurl) localhttpserver = True filestring = 'XBMC.RunScript(' + os.path.join(ustvpaths.LIBPATH, 'proxy.py') + ', 12345)' xbmc.executebuiltin(filestring) time.sleep(20) m3u_data = m3u_data.replace(key_url, 'http://127.0.0.1:12345/play0.key') playfile = open(ustvpaths.PLAYFILE, 'w') playfile.write(m3u_data) playfile.close() finalurl = ustvpaths.PLAYFILE if (addon.getSetting('enablesubtitles') == 'true') and (closedcaption is not None): convert_subtitles(closedcaption) item = xbmcgui.ListItem(path=finalurl) try: item.setThumbnailImage(common.args.thumb) except: pass try: item.setInfo( 'Video', { 'title': common.args.name, 'season': common.args.season_number, 'episode': common.args.episode_number, 'TVShowTitle': common.args.show_title }) except: pass xbmcplugin.setResolvedUrl(pluginHandle, True, item) if ((addon.getSetting('enablesubtitles') == 'true') and (closedcaption is not None)) or localhttpserver is True: while not xbmc.Player().isPlaying(): xbmc.sleep(100) if (addon.getSetting('enablesubtitles') == 'true') and (closedcaption is not None): xbmc.Player().setSubtitles(ustvpaths.SUBTITLE) if localhttpserver is True: while xbmc.Player().isPlaying(): xbmc.sleep(1000) connection.getURL('http://localhost:12345/stop', connectiontype=0)
def test_simple_playlist_with_discontinuity_sequence(): data = m3u8.parse(playlists.SIMPLE_PLAYLIST_WITH_DISCONTINUITY_SEQUENCE) assert data['discontinuity_sequence'] == 123
def test_should_parse_comma_in_title(): data = m3u8.parse(playlists.SIMPLE_PLAYLIST_TITLE_COMMA) assert ['Title with a comma, end' ] == [c['title'] for c in data['segments']]
def test_should_parse_simple_playlist_from_string_with_different_linebreaks(): data = m3u8.parse(playlists.SIMPLE_PLAYLIST.replace('\n', '\r\n')) assert 5220 == data['targetduration'] assert ['http://media.example.com/entire.ts'] == [c['uri'] for c in data['segments']] assert [5220] == [c['duration'] for c in data['segments']]
def test_should_parse_start_with_precise(): data = m3u8.parse(playlists.SIMPLE_PLAYLIST_WITH_START_PRECISE) assert data['start']['time_offset'] == 10.5 assert data['start']['precise'] == 'YES'
def test_should_parse_no_duration_cue_playlist(): data = m3u8.parse(playlists.CUE_OUT_NO_DURATION_PLAYLIST) assert data['segments'][0]['cue_out_start'] assert data['segments'][2]['cue_in']
def test_should_load_playlist_with_iv_from_string(): data = m3u8.parse(playlists.PLAYLIST_WITH_ENCRIPTED_SEGMENTS_AND_IV) assert "/hls-key/key.bin" == data['key']['uri'] assert "AES-128" == data['key']['method'] assert "0X10ef8f758ca555115584bb5b3c687f52" == data['key']['iv']
def test_commaless_extinf(): data = m3u8.parse(playlists.SIMPLE_PLAYLIST_COMMALESS_EXTINF) assert 5220 == data['targetduration'] assert 0 == data['media_sequence'] assert ['http://media.example.com/entire.ts'] == [c['uri'] for c in data['segments']] assert [5220] == [c['duration'] for c in data['segments']]
def test_should_parse_simple_playlist_from_string(): data = m3u8.parse(playlists.SIMPLE_PLAYLIST) assert 5220 == data['targetduration'] assert ['http://media.example.com/entire.ts'] == [c['uri'] for c in data['segments']] assert [5220] == [c['duration'] for c in data['segments']]
def play_video(SITE, BRANDID, PARTNERID): try: qbitrate = common.args.quality except: qbitrate = None video_id, video_type = common.args.url.split('#') hbitrate = -1 lbitrate = -1 sbitrate = int(addon.getSetting('quality')) localhttpserver = False video_auth = get_authorization(BRANDID, video_id, video_type) if video_auth is False: video_url = VIDEOLIST % BRANDID + '001/-1/-1/-1/' + video_id + '/-1/-1' video_data = connection.getURL(video_url) try: video_data2 = simplejson.loads(video_data)['videos']['video'] video_format = video_data2['assets']['asset'][0]['@format'] video_closedcaption = video_data2['closedcaption']['@enabled'] except: try: video_data2 = simplejson.loads(video_data)['videos']['video'] video_format = video_data2['assets']['asset']['@format'] video_closedcaption = video_data2['closedcaption']['@enabled'] except: video_format = 'MOV' video_closedcaption = 'false' video_id = video_id.replace('VDKA', '') if video_format == 'MP4': video_url = PLAYLISTMP4 % (PARTNERID, PARTNERID) + video_id video_data = connection.getURL(video_url) video_url2 = m3u8.parse(video_data) for video_index in video_url2.get('playlists'): bitrate = int(video_index.get('stream_info')['bandwidth']) if qbitrate is not None: if bitrate > hbitrate and bitrate <= (sbitrate * 1000): hbitrate = bitrate playpath_url = video_index.get('uri') else: if bitrate == qbitrate: playpath_url = video_index.get('uri') finalurl = playpath_url elif video_format == 'MOV': player._localHTTPServer = False playpath_url = None video_url = PLAYLISTMOV % (PARTNERID, PARTNERID) + video_id video_data = connection.getURL(video_url) video_tree = BeautifulSoup(video_data, 'html.parser') base_url = video_tree('baseurl')[0].string video_url2 = video_tree.findAll('media') if qbitrate is None: for video_index in video_url2: bitrate = int(video_index['bitrate']) if bitrate < lbitrate or lbitrate == -1: lbitrate = bitrate lplaypath_url = video_index['url'] if bitrate > hbitrate and bitrate <= sbitrate: hbitrate = bitrate playpath_url = video_index['url'] else: playpath_url = video_tree.find('media', bitrate=qbitrate)['url'] if playpath_url is None: playpath_url = lplaypath_url finalurl = base_url + ' playpath=' + playpath_url + ' swfUrl=' + SWFURL + ' swfVfy=true' else: video_url = VIDEOLIST % BRANDID + '002/-1/-1/-1/' + video_id + '/-1/-1' video_data = connection.getURL(video_url) video_data2 = simplejson.loads(video_data)['videos']['video'] video_closedcaption = video_data2['closedcaption']['@enabled'] try: video_url2 = video_data2['assets']['asset']['$'] + video_auth except: video_url2 = video_data2['assets']['asset'][1]['$'] + video_auth video_data3 = connection.getURL(video_url2.replace('m3u8', 'json')) video_url3 = simplejson.loads(video_data3) for video_keys in BITRATETABLE.iterkeys(): bitrate = int(video_keys) if qbitrate is None: if bitrate > hbitrate and bitrate <= sbitrate: hbitrate = bitrate video_url4 = video_url3['url'].replace( '__ray__', BITRATETABLE[video_keys]) else: if qbitrate == bitrate: video_url4 = video_url3['url'].replace( '__ray__', BITRATETABLE[video_keys]) video_url4 = video_url4.replace('https', 'http').replace('json', 'm3u8') video_data4 = re.sub(r"\#EXT-X-DISCONTINUITY\n", "", connection.getURL(video_url4)) key_url = re.compile('URI="(.*?)"').findall(video_data4)[0] key_data = connection.getURL(key_url) key_file = open(ustvpaths.KEYFILE % '0', 'wb') key_file.write(key_data) key_file.close() localhttpserver = True filestring = 'XBMC.RunScript(' + os.path.join(ustvpaths.LIBPATH, 'proxy.py') + ', 12345)' xbmc.executebuiltin(filestring) time.sleep(20) video_data4 = video_data4.replace(key_url, 'http://127.0.0.1:12345/play0.key') playfile = open(ustvpaths.PLAYFILE, 'w') playfile.write(video_data4) playfile.close() finalurl = ustvpaths.PLAYFILE if (video_closedcaption == 'true') and (addon.getSetting('enablesubtitles') == 'true'): try: closedcaption = CLOSEDCAPTIONHOST + video_data2['closedcaption'][ 'src']['$'].split('.com')[1] convert_subtitles(closedcaption) player._subtitles_Enabled = True except: video_closedcaption = 'false' item = xbmcgui.ListItem(path=finalurl) try: item.setThumbnailImage(common.args.thumb) except: pass try: item.setInfo( 'Video', { 'title': common.args.name, 'season': common.args.season_number, 'episode': common.args.episode_number, 'TVShowTitle': common.args.show_title }) except: pass xbmcplugin.setResolvedUrl(pluginHandle, True, item) while player.is_active: player.sleep(250)
def test_should_parse_unquoted_title_from_playlist(): data = m3u8.parse(playlists.SIMPLE_PLAYLIST_WITH_UNQUOTED_TITLE) assert 1 == len(data['segments']) assert 5220 == data['segments'][0]['duration'] assert "A sample unquoted title" == data['segments'][0]['title'] assert "http://media.example.com/entire.ts" == data['segments'][0]['uri']
def test_negative_media_sequence(): data = m3u8.parse(playlists.PLAYLIST_WITH_NEGATIVE_MEDIA_SEQUENCE) assert data['media_sequence'] == -2680
def test_should_parse_non_integer_duration_from_playlist_string(): data = m3u8.parse(playlists.PLAYLIST_WITH_NON_INTEGER_DURATION) assert 5220.5 == data['targetduration'] assert [5220.5] == [c['duration'] for c in data['segments']]
def test_should_parse_multiple_map_attributes(): data = m3u8.parse(playlists.MULTIPLE_MAP_URI_PLAYLIST) assert data['segments'][0]['init_section']['uri'] == 'init1.mp4' assert data['segments'][1]['init_section']['uri'] == 'init1.mp4' assert data['segments'][2]['init_section']['uri'] == 'init3.mp4'
def test_should_parse_endlist_playlist(): data = m3u8.parse(playlists.SIMPLE_PLAYLIST) assert True == data['is_endlist'] data = m3u8.parse(playlists.SLIDING_WINDOW_PLAYLIST) assert False == data['is_endlist']
def test_should_parse_variant_playlist_with_video_range(): data = m3u8.parse(playlists.VARIANT_PLAYLIST_WITH_VIDEO_RANGE) playlists_list = list(data['playlists']) assert 'SDR' == playlists_list[0]['stream_info']['video_range'] assert 'PQ' == playlists_list[1]['stream_info']['video_range']
def test_commaless_extinf_strict(): with pytest.raises(ParseError) as e: m3u8.parse(playlists.SIMPLE_PLAYLIST_COMMALESS_EXTINF, strict=True) assert str(e.value) == 'Syntax error in manifest on line 3: #EXTINF:5220'
def test_should_parse_session_data(): data = m3u8.parse(playlists.SESSION_DATA_PLAYLIST) assert data['session_data'][0]['data_id'] == 'com.example.value' assert data['session_data'][0]['value'] == 'example' assert data['session_data'][0]['language'] == 'en'
def test_should_parse_segment_map_uri_with_byterange(): data = m3u8.parse(playlists.MAP_URI_PLAYLIST_WITH_BYTERANGE) assert data['segment_map']['uri'] == "main.mp4"