def ffprobe_get_media_duration(file): print('Getting {} duration'.format(file)) params = [FFPROBE] params.extend(['-i', file]) params.extend(['-show_entries', 'format=duration']) params.extend(['-v', 'quiet']) params.extend(['-of', 'csv=p=0']) return subprocess.check_output( params, stdin=STDIN, stderr=subprocess.STDOUT ).decode().strip()
def ffmpeg_download_stream( files, title, ext, params={}, output_dir='.', stream=True, **kwargs ): """str, str->True WARNING: NOT THE SAME PARMS AS OTHER FUNCTIONS!!!!!! You can basicly download anything with this function but better leave it alone with """ # https://ffmpeg.org/ffmpeg.html#Main-options output = '{}.{}'.format(title, ext) if not (output_dir == '.'): output = '{}/{}'.format(output_dir, output) print( 'Downloading streaming content with FFmpeg, press q to stop ' 'recording...' ) if stream: ffmpeg_params = [FFMPEG] + ['-y', '-re', '-i'] else: ffmpeg_params = [FFMPEG] + ['-y', '-i'] ffmpeg_params.append(files) # not the same here!!!! if FFMPEG == 'avconv': # who cares? ffmpeg_params += ['-c', 'copy', output] elif kwargs.get('override'): pass else: ffmpeg_params += ['-c', 'copy', '-bsf:a', 'aac_adtstoasc'] if params is not None: if len(params) > 0: for k, v in params.items(): ffmpeg_params.append(k) ffmpeg_params.append(v) ffmpeg_params.append(output) print(' '.join(ffmpeg_params)) try: a = subprocess.Popen(ffmpeg_params, stdin=subprocess.PIPE) a.communicate() except KeyboardInterrupt: try: a.stdin.write('q'.encode('utf-8')) except Exception: pass return True
def ffmpeg_concat_av(files, output, ext): print('Merging video parts... ', end="", flush=True) params = [FFMPEG] + LOGLEVEL for file in files: if os.path.isfile(file): params.extend(['-i', file]) params.extend(['-c:v', 'copy']) if ext == 'mp4': params.extend(['-c:a', 'aac']) elif ext == 'webm': params.extend(['-c:a', 'vorbis']) params.extend(['-strict', 'experimental']) params.append(output) return subprocess.call(params, stdin=STDIN)
def ffmpeg_concat_audio_and_video(files, output, ext): print('Merging video and audio parts... ', end='', flush=True) if has_ffmpeg_installed: params = [FFMPEG] + LOGLEVEL params.extend(['-f', 'concat']) for file in files: if os.path.isfile(file): params.extend(['-i', file]) params.extend(['-c:v', 'copy']) params.extend(['-c:a', 'aac']) params.extend(['-strict', 'experimental']) params.append('{}.{}'.format(output, ext)) return subprocess.call(params, stdin=STDIN) else: raise EnvironmentError('No ffmpeg found')
def ffmpeg_concat_ts_to_mkv(files, output='output.mkv'): print('Merging video parts... ', end='', flush=True) params = [FFMPEG] + LOGLEVEL + ['-isync', '-y', '-i'] params.append('concat:') for file in files: if os.path.isfile(file): params[-1] += file + '|' params += ['-f', 'matroska', '-c', 'copy', output] try: if subprocess.call(params, stdin=STDIN) == 0: return True else: return False except Exception: return False
def ffmpeg_concat_flv_to_mp4(files, output='output.mp4'): print('Merging video parts... ', end='', flush=True) # Use concat demuxer on FFmpeg >= 1.1 if FFMPEG == 'ffmpeg' and ( FFMPEG_VERSION[0] >= 2 or ( FFMPEG_VERSION[0] == 1 and FFMPEG_VERSION[1] >= 1 ) ): concat_list = generate_concat_list(files, output) params = [FFMPEG] + LOGLEVEL + [ '-y', '-f', 'concat', '-safe', '-1', '-i', concat_list, '-c', 'copy', '-bsf:a', 'aac_adtstoasc', output ] subprocess.check_call(params, stdin=STDIN) os.remove(output + '.txt') return True for file in files: if os.path.isfile(file): params = [FFMPEG] + LOGLEVEL + ['-y', '-i'] params.append(file) params += [ '-map', '0', '-c', 'copy', '-f', 'mpegts', '-bsf:v', 'h264_mp4toannexb' ] params.append(file + '.ts') subprocess.call(params, stdin=STDIN) params = [FFMPEG] + LOGLEVEL + ['-y', '-i'] params.append('concat:') for file in files: f = file + '.ts' if os.path.isfile(f): params[-1] += f + '|' if FFMPEG == 'avconv': params += ['-c', 'copy', output] else: params += ['-c', 'copy', '-absf', 'aac_adtstoasc', output] if subprocess.call(params, stdin=STDIN) == 0: for file in files: os.remove(file + '.ts') return True else: raise
def get_usable_ffmpeg(cmd): try: p = subprocess.Popen( [cmd, '-version'], stdin=DEVNULL, stdout=subprocess.PIPE, stderr=subprocess.PIPE ) out, err = p.communicate() vers = str(out, 'utf-8').split('\n')[0].split() assert (vers[0] == 'ffmpeg' and vers[2][0] > '0') or \ (vers[0] == 'avconv') # set version to 1.0 for nightly build and print warning try: version = [int(i) for i in vers[2].split('.')] except Exception: print('It seems that your ffmpeg is a nightly build.') print('Please switch to the latest stable if merging failed.') version = [1, 0] return cmd, 'ffprobe', version except Exception: return None
def netease_lyric_download(self, song, output_dir, info_only, playlist_prefix='', **kwargs): if info_only or not kwargs.get('caption'): return data = json.loads( get_content('http://music.163.com/api/song/lyric/?' 'id={}&lv=-1&csrf_token='.format(song['id']), headers={'Referer': 'http://music.163.com/'})) title = '{}{}. {}'.format(playlist_prefix, song['position'], song['name']) filename = '{}.lrc'.format(get_filename(title)) print('Saving {} ...'.format(filename), end='', flush=True) with open(os.path.join(output_dir, filename), 'w', encoding='utf-8') as x: x.write(data['lrc']['lyric']) print('Done.')
def p_i(self, stream_id): if stream_id in self.streams: stream = self.streams[stream_id] else: stream = self.dash_streams[stream_id] maybe_print(" - title: %s" % self.title) print(" size: {} MiB ({} bytes)".format( round(stream['size'] / 1048576, 1), stream['size'])) print(" url: %s" % self.url) print()
def download(self, **kwargs): if 'json_output' in kwargs and kwargs['json_output']: json_output.output(self) elif 'info_only' in kwargs and kwargs['info_only']: if 'stream_id' in kwargs and kwargs['stream_id']: # Display the stream stream_id = kwargs['stream_id'] if 'index' not in kwargs: self.p(stream_id) else: self.p_i(stream_id) else: # Display all available streams if 'index' not in kwargs: self.p([]) else: stream_id = self.streams_sorted[0]['id'] \ if 'id' in self.streams_sorted[0] \ else self.streams_sorted[0]['itag'] self.p_i(stream_id) else: if 'stream_id' in kwargs and kwargs['stream_id']: # Download the stream stream_id = kwargs['stream_id'] else: # Download stream with the best quality stream_id = self.streams_sorted[0]['id'] \ if 'id' in self.streams_sorted[0] \ else self.streams_sorted[0]['itag'] if 'index' not in kwargs: self.p(stream_id) else: self.p_i(stream_id) if stream_id in self.streams: urls = self.streams[stream_id]['src'] ext = self.streams[stream_id]['container'] total_size = self.streams[stream_id]['size'] else: urls = self.dash_streams[stream_id]['src'] ext = self.dash_streams[stream_id]['container'] total_size = self.dash_streams[stream_id]['size'] if not urls: log.wtf('[Failed] Cannot extract video source.') if ext == 'm3u8': ffmpeg_kwargs = {} if 'iqiyi' in self.name: # ffmpeg_kwargs['override'] = True # ffmpeg_kwargs['params'] = { # '-c:a': 'copy', '-bsf:a': 'aac_adtstoasc' # } m3u8_urls = general_m3u8_extractor(urls[0]) # FIXME(iawia002): 如果要计算大小的话需要消耗太多时间 if len(m3u8_urls) <= 100: size = urls_size(m3u8_urls) else: size = float('inf') download_urls(m3u8_urls, self.title, 'mp4', size, **kwargs) else: download_url_ffmpeg(urls[0], self.title, 'mp4', output_dir=kwargs['output_dir'], merge=kwargs['merge'], stream=False, **ffmpeg_kwargs) else: headers = copy(config.FAKE_HEADERS) if self.ua is not None: headers['User-Agent'] = self.ua if self.referer is not None: headers['Referer'] = self.referer download_urls(urls, self.title, ext, total_size, headers=headers, output_dir=kwargs['output_dir'], merge=kwargs['merge'], av=stream_id in self.dash_streams) if 'caption' not in kwargs or not kwargs['caption']: print('Skipping captions or danmuku.') return for lang in self.caption_tracks: filename = '%s.%s.srt' % (get_filename(self.title), lang) print('Saving %s ... ' % filename, end="", flush=True) srt = self.caption_tracks[lang] with open(os.path.join(kwargs['output_dir'], filename), 'w', encoding='utf-8') as x: x.write(srt) print('Done.') if self.danmuku is not None and not dry_run: filename = '{}.cmt.xml'.format(get_filename(self.title)) print('Downloading {} ...\n'.format(filename)) with open(os.path.join(kwargs['output_dir'], filename), 'w', encoding='utf8') as fp: fp.write(self.danmuku) keep_obj = kwargs.get('keep_obj', False) if not keep_obj: self.__init__()
def p_playlist(self, stream_id=None): maybe_print("site: %s" % self.__class__.name) print("playlist: %s" % self.title) print("videos:")
def p(self, stream_id=None): maybe_print("site: %s" % self.__class__.name) maybe_print("title: %s" % self.title) if stream_id: # Print the stream print("stream:") self.p_stream(stream_id) elif stream_id is None: # Print stream with best quality print("stream: # Best quality") stream_id = self.streams_sorted[0]['id'] \ if 'id' in self.streams_sorted[0] \ else self.streams_sorted[0]['itag'] self.p_stream(stream_id) elif stream_id == []: print("streams: # Available quality and codecs") # Print DASH streams if self.dash_streams: print(" [ DASH ] %s" % ('_' * 36)) itags = sorted(self.dash_streams, key=lambda i: -self.dash_streams[i]['size']) for stream in itags: self.p_stream(stream) # Print all other available streams print(" [ DEFAULT ] %s" % ('_' * 33)) for stream in self.streams_sorted: self.p_stream(stream['id'] if 'id' in stream else stream['itag']) if self.audiolang: print("audio-languages:") for i in self.audiolang: print(" - lang: {}".format(i['lang'])) print(" download-url: {}\n".format(i['url']))
def p_stream(self, stream_id): if stream_id in self.streams: stream = self.streams[stream_id] else: stream = self.dash_streams[stream_id] if 'itag' in stream: print(" - itag: %s" % log.sprint(stream_id, log.NEGATIVE)) else: print(" - format: %s" % log.sprint(stream_id, log.NEGATIVE)) if 'container' in stream: print(" container: %s" % stream['container']) if 'video_profile' in stream: maybe_print(" video-profile: %s" % stream['video_profile']) if 'quality' in stream: print(" quality: %s" % stream['quality']) if 'size' in stream and stream['container'].lower() != 'm3u8': if stream['size'] != float('inf') and stream['size'] != 0: print(" size: {} MiB ({} bytes)".format( round(stream['size'] / 1048576, 1), stream['size'])) if 'm3u8_url' in stream: print(" m3u8_url: {}".format(stream['m3u8_url'])) if 'itag' in stream: print( " # download-with: %s" % log.sprint("lulu --itag=%s [URL]" % stream_id, log.UNDERLINE)) else: print(" # download-with: %s" % log.sprint( "lulu --format=%s [URL]" % stream_id, log.UNDERLINE)) print()
def download(self, **kwargs): if 'json_output' in kwargs and kwargs['json_output']: json_output.output(self) elif 'info_only' in kwargs and kwargs['info_only']: if 'stream_id' in kwargs and kwargs['stream_id']: # Display the stream stream_id = kwargs['stream_id'] if 'index' not in kwargs: self.p(stream_id) else: self.p_i(stream_id) else: # Display all available streams if 'index' not in kwargs: self.p([]) else: stream_id = self.streams_sorted[0]['id'] \ if 'id' in self.streams_sorted[0] \ else self.streams_sorted[0]['itag'] self.p_i(stream_id) else: if 'stream_id' in kwargs and kwargs['stream_id']: # Download the stream stream_id = kwargs['stream_id'] else: # Download stream with the best quality stream_id = self.streams_sorted[0]['id'] \ if 'id' in self.streams_sorted[0] \ else self.streams_sorted[0]['itag'] if 'index' not in kwargs: self.p(stream_id) else: self.p_i(stream_id) if stream_id in self.streams: urls = self.streams[stream_id]['src'] ext = self.streams[stream_id]['container'] total_size = self.streams[stream_id]['size'] else: urls = self.dash_streams[stream_id]['src'] ext = self.dash_streams[stream_id]['container'] total_size = self.dash_streams[stream_id]['size'] if ext == 'm3u8': ext = 'mp4' if not urls: log.wtf('[Failed] Cannot extract video source.') # For legacy main() headers = copy(config.FAKE_HEADERS) if self.ua is not None: headers['User-Agent'] = self.ua if self.referer is not None: headers['Referer'] = self.referer download_urls( urls, self.title, ext, total_size, headers=headers, output_dir=kwargs['output_dir'], merge=kwargs['merge'], av=stream_id in self.dash_streams ) if 'caption' not in kwargs or not kwargs['caption']: print('Skipping captions or danmuku.') return for lang in self.caption_tracks: filename = '%s.%s.srt' % (get_filename(self.title), lang) print('Saving %s ... ' % filename, end="", flush=True) srt = self.caption_tracks[lang] with open( os.path.join(kwargs['output_dir'], filename), 'w', encoding='utf-8' ) as x: x.write(srt) print('Done.') if self.danmuku is not None and not dry_run: filename = '{}.cmt.xml'.format(get_filename(self.title)) print('Downloading {} ...\n'.format(filename)) with open( os.path.join(kwargs['output_dir'], filename), 'w', encoding='utf8' ) as fp: fp.write(self.danmuku) # For main_dev() # download_urls( # urls, self.title, self.streams[stream_id]['container'], # self.streams[stream_id]['size'] # ) keep_obj = kwargs.get('keep_obj', False) if not keep_obj: self.__init__()
def download(self, **kwargs): """Override the original one Ugly ugly dirty hack """ if 'json_output' in kwargs and kwargs['json_output']: json_output.output(self) elif 'info_only' in kwargs and kwargs['info_only']: if 'stream_id' in kwargs and kwargs['stream_id']: # Display the stream stream_id = kwargs['stream_id'] if 'index' not in kwargs: self.p(stream_id) else: self.p_i(stream_id) else: # Display all available streams if 'index' not in kwargs: self.p([]) else: stream_id = self.streams_sorted[0]['id'] \ if 'id' in self.streams_sorted[0] \ else self.streams_sorted[0]['itag'] self.p_i(stream_id) else: if 'stream_id' in kwargs and kwargs['stream_id']: # Download the stream stream_id = kwargs['stream_id'] else: # Download stream with the best quality stream_id = self.streams_sorted[0]['id'] \ if 'id' in self.streams_sorted[0] \ else self.streams_sorted[0]['itag'] if 'index' not in kwargs: self.p(stream_id) else: self.p_i(stream_id) if stream_id in self.streams: urls = self.streams[stream_id]['src'] # ext = self.streams[stream_id]['container'] # total_size = self.streams[stream_id]['size'] else: urls = self.dash_streams[stream_id]['src'] # ext = self.dash_streams[stream_id]['container'] # total_size = self.dash_streams[stream_id]['size'] if not urls: log.wtf('[Failed] Cannot extract video source.') # Here's the change! download_url_ffmpeg(urls[0], self.title, 'mp4', output_dir=kwargs['output_dir'], merge=kwargs['merge'], stream=False) if not kwargs['caption']: print('Skipping captions.') return for lang in self.caption_tracks: filename = '{}.{}.srt'.format(get_filename(self.title), lang) print('Saving {} ... '.format(filename), end='', flush=True) srt = self.caption_tracks[lang] with open(os.path.join(kwargs['output_dir'], filename), 'w', encoding='utf-8') as x: x.write(srt) print('Done.')