def get_m3u8(self, quality: str) -> M3U8: """Gets the episode's M3U8 data. :param quality: The quality whose M3U8 data you need. All the available are "ld" (360p), "sd" (480p), "hd" (720p) and "fullhd" (1080p). :type quality: str :return: A M3U8 object, the data can be accessed by calling the ``data`` property on the object. :rtype: M3U8 """ if self.__m3u8: return self.__m3u8 else: try: headers = self.__generate_default_headers() aniwatch_episode = self.get_aniwatch_episode() self.toggle_mark_as_watched() self.spoof_download_sprites() uri = aniwatch_episode.stream.sources[ quality] # The uri to the M3U8 file. res = self.__network.get_with_user_session(uri, headers) self.__m3u8 = M3U8(res.text) return self.__m3u8 except: return Nonec
def make_feed_manifest(request, stream, feed): url = request.build_absolute_uri(stream.index_manifest_url) p = load_m3u8(url) m = M3U8() m.version = p.version m.target_duration = p.target_duration m.media_sequence = p.media_sequence for s in p.segments: if not m.program_date_time: m.program_date_time = s.current_program_date_time vtt_url = furl(basename(feed.webvtt_url)).set({"stream": stream.uuid}) if s.current_program_date_time: vtt_url.args.update({ "start": s.current_program_date_time.isoformat(), "end": (s.current_program_date_time + timedelta(seconds=s.duration)).isoformat(), "epoch": stream.started_at.isoformat(), }) v = Segment( base_uri=vtt_url.url, uri=vtt_url.url, duration=s.duration, discontinuity=s.discontinuity, program_date_time=s.current_program_date_time, ) m.add_segment(v) return m.dumps()
def make_master_manifest(request, stream): if stream.info: bandwidth = int(stream.info["bw_out"]) width = stream.info["meta"]["video"]["width"] height = stream.info["meta"]["video"]["height"] stream_info = { "bandwidth": bandwidth, "resolution": f"{width}x{height}", "codecs": "avc1.640028,mp4a.40.2", } else: stream_info = {"bandwidth": 1000} p = Playlist(basename(stream.index_manifest_url), stream_info, None, None) m = M3U8() m.add_playlist(p) for feed in stream.feeds.all(): media = Media( type="SUBTITLES", group_id="feeds", name=f"feed-{feed.uuid}", language="en", default="YES", autoselect="YES", uri=furl(feed.manifest_url).set({ "stream": stream.uuid }).url, ) p.media.append(media) m.add_media(media) return m.dumps()
def start(self): if self._run: self._files = None d = self._reload_playlist( M3U8(self.url, self._cookies, self.hls_headers)) d.addCallback(self._start_get_files) return d
def generate_vod_recording_playlist_m3u8(cls, client_uuid, recording_id, http_token): db_session = Database.create_session() try: vod_playlist_m3u8_object = M3U8() vod_playlist_m3u8_object.media_sequence = 0 vod_playlist_m3u8_object.version = '3' vod_playlist_m3u8_object.target_duration = 0 vod_playlist_m3u8_object.playlist_type = 'VOD' for segment_row in DatabaseAccess.query_segment_pickle( db_session, recording_id): segment = pickle.loads(segment_row.pickle) if segment.duration > vod_playlist_m3u8_object.target_duration: vod_playlist_m3u8_object.target_duration = math.ceil( segment.duration) vod_playlist_m3u8_object.add_segment(segment) return re.sub( r'(\.ts\?)(.*)', r'\1client_uuid={0}&http_token={1}&\2'.format( client_uuid, urllib.parse.quote(http_token) if http_token else ''), '{0}\n' '{1}'.format(vod_playlist_m3u8_object.dumps(), '#EXT-X-ENDLIST')) finally: db_session.close()
async def get_m3u8(self): if self.m3u8 is None: headers = {"referer": "https://kwik.cx"} m3u8_url = await self.get_m3u8_url() response = await self.__network__.get(m3u8_url, headers=headers) print(await response.text()) self.m3u8 = M3U8(await response.text()) return self.m3u8
def downM3u8Video(url, out_dir, out_name, process_num): out_path = os.path.join(out_dir, out_name) tmp_dir = os.path.join(out_dir, os.path.splitext(os.path.basename(out_name))[0]) if os.path.exists(out_path) and not os.path.exists(tmp_dir): # 该任务已完成下载 print('Input name is existed:%s!' % out_name) return m3u8_info = M3U8(url) ts_len = len(m3u8_info.ts_urls) print('ts length:%d' % ts_len) if ts_len > 0: if not os.path.exists(tmp_dir): os.makedirs(tmp_dir) process_list = [] per_process_num = int(ts_len / process_num) # 启用多进程下载视频 for i in range(process_num): id_start = i * per_process_num id_end = (i + 1) * per_process_num if i == process_num - 1: id_end = ts_len cur_process = multiprocessing.Process( target=downloadTsFiles, args=(m3u8_info.ts_urls[id_start:id_end], tmp_dir, i)) cur_process.start() # search_ip(ip_prefix, database, table_name, ip_start, ip_end, i) process_list.append(cur_process) for process_item in process_list: process_item.join() # 若有加密,尝试解密文件 if CRYPTO_ENABLE and m3u8_info.encrypt_method: print('encrypt method:%s' % m3u8_info.encrypt_method) print('key uri:%s' % m3u8_info.key_uri) key_str = getResponse(m3u8_info.key_uri) decryptFiles(m3u8_info.ts_urls, tmp_dir, m3u8_info.encrypt_method, key_str) print('Merging to one file:%s' % out_path) with open(out_path, 'wb') as f_out: for i, ts_url in enumerate(m3u8_info.ts_urls): tmp_file = os.path.join(tmp_dir, ts_url.rsplit('/', 1)[-1]) decrypt_file = os.path.join(tmp_dir, 'decrypt_' + ts_url.rsplit('/', 1)[-1]) dst_file = decrypt_file if CRYPTO_ENABLE and m3u8_info.encrypt_method is not None else tmp_file if not os.path.exists(dst_file): print('Some files fail to download or decrypt, try again!') return with open(dst_file, 'rb') as f: f_out.write(f.read()) if os.path.exists(tmp_dir): shutil.rmtree(tmp_dir)
def fetch_playlist(link, token=None): params = {'allow_source': 'true'} if token else {} params.update( {'token': token['token'], 'sig': token['sig']} if token else {} ) raw_playlist = Contents.utf8(link, params=params, onerror=lambda _: None) if raw_playlist is None: return M3U8(None) return m3u8.loads(raw_playlist)
def __init__(self, _outputFile: PathModel, _tempFolder: PathModel = None) -> None: if _tempFolder is None: _tempFolder = _outputFile.temp() os.chdir(_tempFolder.path) try: progress = int(re.findall("file tmp_(.*).mp4", open('temp.txt', 'r').readlines()[-3])[0])+1 except: progress = 0 key, M3U8s = M3U8.getAll(self) dec = Decrypt(key) l = len(M3U8s) id = Id(l, progress) try: for i in range(progress, l): file_name = 'tmp_%s.mp4' % id.add() print('Processing %d of %d' % (i+1, l)) url = M3U8s[i].url url = "http" + url.removeprefix("https") open(file_name, 'wb').write( dec.get(self.getFile(url))) open('temp.txt', 'a').write( "file %s\nduration %s\n\n" % (file_name, M3U8s[i].duration)) except: print("Errore nel download dei file\nRiprova in seguito") else: # size = 0 # st = os.stat_result. # free = st.f_bavail * st.f_frsize # for file_name in os.listdir(tempPath): # size += os.path.getsize(file_name) # # if free >= size: self._concatenateAll() # else: # self._concatenateProgress(l) os.chdir(_tempFolder.dir) shutil.move("%s\\output.mp4" % _tempFolder.name, _outputFile.path) shutil.rmtree(_tempFolder.path)
def vido_download(num, videolist): '''下载视频文件,cnwkw.cn 网站上的视频分为 '流畅-LD' '标清-SD' '高清-HD', param num, videolist: numberID and video links list ''' print("ResourceID: {0}".format(num)) for video in videolist: # similiar to dict # {'definition': '流畅', 'format': 'mp4', 'url': # 'http://video.cnwkw.cn/WeiKe/video/201506/0215/928c9efb778f4c598449401f984603ca-LD.mp4'} # {'definition': '高清', 'format': 'm3u8', 'url': # 'http://video.cnwkw.cn/WeiKe/video/201710/1008/d9557690d81e4287a6fc3d41e39e05cf-HD.m3u8'} filename = video['url'].split('/')[-1] # 解析内部文件名 #suffix = video['url'].split('-')[-1] # 解析文件名后缀,含分辨率 LD,SD,HD和文件格式 print("Definition: {0}, Format: {1}, Filename: {2}, ...".format( video['definition'], video['format'], filename)) # KEY: Copy a network object to a local file by using urllib.request.urlretrieve(URL, local_filename) # '高清' 视频(多为 m3u8 播放格式)下载, 可以借鉴 u3u8 module(from model.py) if video['format'].lower() == 'm3u8': url = video['url'] base_path = url.rsplit('/', 1)[0] request = urllib.request.Request( url, headers={'User-Agent': UserAgent().random}) response = urllib.request.urlopen(request) all_content = response.read() # return 'bytes-object' all_content = all_content.decode( 'utf-8') # return 'string' after decoding by 'utf-8' response.close() #all_content = requests.get(url, headers=header).text # replaced by Request/urlopen # 通过文本内容,调用m3u8模块中的类M3U8,和save_m3u过程 m3u = M3U8(all_content, base_path=base_path) m3u_filename = video_file(num, video['definition']) #print("M3U Fielname: {0}".format(m3u_filename)) save_m3u(m3u, m3u_filename) #download(num, video['definition'], video['url']) elif video['format'].lower() == 'mp4': mp4_filename = video_file(num, video['definition']) print('MP4 Filename: {0}'.format(mp4_filename)) #urllib.request.urlretrieve(video['url'], mp4_filename) #MP_dir + num+'-'+suffix) #'.'+video['format']) else: print("Unknown video format {0} in URL {1}".format( video['fromat'], video['url']))
def get_m3u8(self, quality: str): if self.__m3u8: return self.__m3u8 else: REFERER = self.__generate_referer() HEADERS = self.headers HEADERS.update({ 'REFERER': REFERER, 'ORIGIN': 'https://aniwatch.me' }) aniwatch_episode = self.get_aniwatch_episode() res = requests.get(aniwatch_episode.stream.sources[quality], headers=HEADERS, cookies=self.cookies) self.__m3u8 = M3U8(res.text) return self.__m3u8
def _get_playlist_url(self) -> str: log.debug(f'Retrieving playlist: {self.video_id} {self.quality}') self._variant_m3u8 = M3U8(self._variant_fetch()) try: return cast( str, next(playlist.uri for playlist in self._variant_m3u8.playlists if playlist.media[0].group_id == self.quality)) except StopIteration: qualities = [ playlist.media[0].group_id for playlist in self._variant_m3u8.playlists ] msg = f"Got '{self.quality}' while expected one of {qualities}" log.exception(msg) raise
def _playlist_updated(self, pl): if pl and pl.has_programs(): # if we got a program playlist, save it and start a program self._program_playlist = pl (program_url, _) = pl.get_program_playlist(self.program, self.bitrate) return self._reload_playlist( M3U8(program_url, self._cookies, self.hls_headers)) elif pl and pl.has_files(): # we got sequence playlist, start reloading it regularly, and get files self._file_playlist = pl if not self._files: self._files = pl.iter_files() if not pl.endlist(): reactor.callLater(pl.reload_delay(), self._reload_playlist, pl) if self._file_playlisted: self._file_playlisted.callback(pl) self._file_playlisted = None else: raise Exception('Playlist has no valid content.') return pl
KICKFLIP_USER_NAME = '' KICKFLIP_UUID = '' KICKFLIP_ACCESS_TOKEN = '' KICKFLIP_SECRET_ACCESS_TOKEN = '' # Amazon AWS_ACCESS_KEY = '' AWS_SECRET_ACCESS_KEY = '' s3 = None # Video settings VIDEO_BITRATE = '2000k' AUDIO_BITRATE = '128k' playlist = M3U8() #################### # AWS #################### def set_aws_keys(USERNAME, AWS_ACCESS_KEY_VAR, AWS_SECRET_ACCESS_KEY_VAR): global AWS_ACCESS_KEY global AWS_SECRET_ACCESS_KEY global KICKFLIP_USER_NAME AWS_ACCESS_KEY = AWS_ACCESS_KEY_VAR AWS_SECRET_ACCESS_KEY = AWS_SECRET_ACCESS_KEY_VAR KICKFLIP_USER_NAME = USERNAME
def update(self, use_old_url: bool = False) -> None: if not use_old_url: self._url = self._get_playlist_url() request = get_url(self.url) self._m3u8 = M3U8(request.text)
def start(self, agfid, device_name, temp_file_dir): params = { 'segment_list_file_abs_path': temp_file_dir + str(datetime.datetime.now())[:10] + '.m3u8', 'segment_afid_list_file_abs_path': temp_file_dir + str(datetime.datetime.now())[:10] + '_afid.m3u8', 'segement_time': 8, 'device_mount_point': '/dev/' + device_name } self.ffmpeg = FFmpeg(self.get_live_command(params)) live = None if agfid == "": res, err = self.afs.create_gfid() if err is not None: return err live = Live(res.agfid) err = self.ffmpeg.start() start = timer() now = datetime.datetime.now() live_time = now for line in self.ffmpeg.get_stdout(): line = line.decode() if self.ffmpeg.is_fail_to_find_video_device(line): err = "cannot find video device " + params['device_mount_point'] return err if self.ffmpeg.is_video_device_busy(line): err = "cannot connect to video device " + params[ 'device_mount_point'] + " since it is busy" return err if self.ffmpeg.is_creating_segment_ts(line): if is_m3u8_file_exists(params): m3u8 = M3U8(params['segment_list_file_abs_path']) afid_m3u8 = None if not is_afid_m3u8_file_exists(params): contents = m3u8.get_contents( m3u8.get_number_of_line() - 1) afid_m3u8 = M3U8( params['segment_afid_list_file_abs_path']) afid_m3u8.create_from_contents(contents) afid_m3u8.append_end("\n") afid_m3u8.append_end(live.cts_afid) else: contents = m3u8.get_contents( m3u8.get_number_of_line() - 1) afid_m3u8 = M3U8( params['segment_afid_list_file_abs_path']) afid_m3u8.append_end("\n") afid_m3u8.append_end(contents[-1]) afid_m3u8.append_end(live.cts_afid) live.set_afid_m3u8(afid_m3u8) live.set_m3u8(m3u8) res, err = self.afs.upload(live.get_afid_m3u8().abs_path) if err is not None: return err res, err = self.afs.set_gfid(live.get_agfid(), res.afid) if err is not None: return err live.num_of_ts = live.num_of_ts + 1 live_time += datetime.timedelta(0, params['segement_time']) cmd_out = "live_start=" + now.strftime( "%Y-%m-%d %H:%M:%S" ) + ";lastest_up_cdn=" + datetime.datetime.now().strftime( "%Y-%m-%d %H:%M:%S") + ";num_of_ts=" + str( live.num_of_ts) + ";live_time=" + live_time.strftime( "%Y-%m-%d %H:%M:%S") + ";agfid=" + live.agfid + ";" print(cmd_out, flush=True) logging.info(cmd_out) live.cts_abs_path = self.ffmpeg.get_file_name_current_segemnt_ts( line) if self.ffmpeg.is_creating_segment_list(line): if live.cts_abs_path != None: res = self.afs.upload(live.cts_abs_path) if err is not None: return err live.cts_afid = res.afid os.remove(live.cts_abs_path) return err
import csv import m3u8 from m3u8 import M3U8 # this could also be an absolute filename m3u8_obj = m3u8.load( 'http://tvdomel.com:8880/get.php?username=XXXX&password=YYYY&type=m3u&output=ts' ) #print m3u8_obj.segments outputTV = M3U8() outputAll = M3U8() orderTV = [] orderAll = [] configMap = {} segmentMap = {} with open('config.csv') as csvfile: readCSV = csv.reader(csvfile, delimiter=',') for row in readCSV: orderTV.append(row[4]) configMap[row[4]] = row for x in m3u8_obj.segments: if (".ts" in x.uri): if x.title not in orderTV: orderTV.append(x.title) orderAll.append(x.title) else: orderAll.append(x.title)