def get_palette( video_file_path, start=0, duration=2.5, ): in_file = ffmpeg.input(video_file_path, ss=start, t=duration) palette = in_file.filter("palettegen") ffmpeg.overwrite_output(palette.output('palette.png')).run() return
def say_over(message, base_path): output = tempfile.NamedTemporaryFile(suffix=".ogg", delete=False) with tempfile.NamedTemporaryFile() as temporary: subprocess.check_call( [espeak, "-v", "it", "-w", temporary.name, message]) speech = ffmpeg.input(temporary.name).filter('volume', 10) base = ffmpeg.input(base_path) merged_audio = ffmpeg.filter([base, speech], 'amix') ffmpeg.overwrite_output(merged_audio.output(output.name)).run() return output.name
def make_gif_from_video(video_file_path, start=0, duration=2.5, gif_name=None): gif_name = gif_name or drop_extension(video_file_path) gif_file_path = gif_name + ".gif" # get the file, and make the palette in_file = ffmpeg.input(video_file_path, ss=start, t=duration) palette = in_file.filter("palettegen") # scale and lower framerate: smaller = in_file.filter('scale', 480, -1).filter('fps', 12) # apply the palette to the video clip, and make into a gif output_stream = ffmpeg.filter([smaller, palette], "paletteuse").output(gif_file_path) ffmpeg.overwrite_output(output_stream).run() return
def download_video(url, file_out='video.mp4', audio=True, duration=5, input_kwargs={}, output_kwargs={}): """ Function to download video from 'url' 'file_out' can take on most extensions, just ... read the docs for ffmpeg Video will be recorded to 'file_out' ... for 'duration' seconds If 'audio' is True, audio will be recorded too Returns the current working directory + file_out """ local_dir = os.getcwd() path = local_dir + '\\' + file_out if not audio: output_kwargs.update({'an': None}) stream = ffmpeg.input(url, t=duration, **input_kwargs) stream = ffmpeg.output(stream, file_out, **output_kwargs) stream = ffmpeg.overwrite_output(stream) out, err = ffmpeg.run(stream, capture_stdout=True, capture_stderr=True) return path
def combine_videos(videos, scores): sorted_videos = sorted(Path(videos).iterdir()) sorted_videos = [ video for video in sorted_videos if "meta" not in str(video) ] indices = (get_iteration(v) for v in sorted_videos) inputs = [ffmpeg.input(str(v)) for v in sorted_videos] texted = [ ffmpeg.drawtext(v, text=f"{idx} - {score}", x='(w-tw)/2', y='(h-th)', fontcolor='[email protected]', box=1, boxcolor='[email protected]', fontfile='ttf/Hack-Bold.ttf') for idx, v, score in zip(indices, inputs, scores) ] #texted = [ffmpeg.drawtext(v, text=f"{idx} - {score}", x='(w-tw)/2', y='(h-th)', fontcolor='[email protected]', box=1, boxcolor='[email protected]', fontfile='ttf/Hack-Regular.ttf') for idx, v, score in zip(indices, inputs, scores)] joined = ffmpeg.concat(*texted) out_file = f"/tmp/{uuid.uuid1()}.mp4" out = ffmpeg.overwrite_output(ffmpeg.output(joined, out_file)) out.run() return out_file
def save_mp3_to_wav(file): """ Convert Flask mp3 file to wav and save Flask request.file is wrap request.file.stream And request.file.stream ia type: tempfile.SpooledTemporaryFile tempfile.SpooledTemporaryFile: Temporary file wrapper, specialized to switch from BytesIO \ or StringIO to a real file when it exceeds a certain size or when a fileno is needed. :param file: :return: """ f_path = 'upload_file.wav' stream = ffmpeg.input('pipe:0') stream = ffmpeg.output(stream, f_path, acodec='pcm_s16le', ac=1, ar='16k') # TODO, prompt and log when overwrite stream = ffmpeg.overwrite_output(stream) # call ffmpeg manually (i.e. p = subprocess.Popen(stream.compile(), stdin=subprocess.PIPE)), # use stdin as input in ffmpeg (use pipe:0 as the file name, see [this](https://ffmpeg.org/ffmpeg-protocols.html#pipe)) # stream.compile() Build command-line for invoking ffmpeg. # subprocess.Popen() Execute a child program in a new process p = subprocess.Popen(stream.compile(), stdin=subprocess.PIPE) CHUNK_SIZE = 1024 data = file.read(CHUNK_SIZE) while data: p.stdin.write(data) data = file.read(CHUNK_SIZE)
def main(): parser = argparse.ArgumentParser( "Split audio file by timestamps using ffmpeg") parser.add_argument('timestamps', metavar="timestamps.csv", help="CSV file formatted as <start>,<end>,<filename>") parser.add_argument('input', metavar="input.mp3", help="Input audio file") args = parser.parse_args() splits = [] with open(args.timestamps) as tsfile: tsreader = csv.reader(tsfile) for row in tsreader: splits.append( (ts_to_seconds(row[0]), ts_to_seconds(row[1]), row[2])) for i, tp in enumerate(splits): start, end, filename = tp print("========================================") print("Extracting %s (%d out of %d)" % (filename, i, len(splits))) print("========================================") print() # open a file, from `ss`, for duration `t` stream = ffmpeg.input(args.input, ss=start, t=(end - start)) # output to named file stream = ffmpeg.output(stream, filename) # this was to make trial and error easier stream = ffmpeg.overwrite_output(stream) # and actually run ffmpeg.run(stream) print("done")
def cut_ranges(filename, ranges): """ ranges are in seconds """ raise AssertionError('Deprecated! Look at concat_ranges!') input_vid = ffmpeg.input(filename) dir = f'{filename[:-4]}' if not os.path.exists(dir): os.makedirs(dir) count = 0 for r in ranges: start = int(r[0]) end = math.ceil(r[1]) out_filename = f'{dir}/out_{count}.mp4' print(f'{filename}: Trimming {out_filename} (of {len(ranges)}) from {start} to {end}') vid = ( input_vid .trim(start=start, end=end) .setpts('PTS-STARTPTS') ) aud = ( input_vid .filter_('atrim', start=start, end=end) .filter_('asetpts', 'PTS-STARTPTS') ) joined = ffmpeg.concat(vid, aud, v=1, a=1) output = ffmpeg.output(joined, out_filename) output = ffmpeg.overwrite_output(output) output.run(cmd=ffmpeg_cmd) count = count + 1
def ffmpeg_trim_audio_clip_atrim_encode(input_file: Path, stream_index: int, timestamp_start: int, timestamp_end: int, quality: Union[int, None], to_mono: bool, normalize_audio: bool, outpath: Path, format: str = None, capture_stdout: bool = False, silent: bool = True): r""" Take media file and export a trimmed audio file. :param stream_index: FFmpeg stream index. If input is not a container format, 0 should be used. :param capture_stdout: If true, returns stdout. Used in conjunction with outpath="pipe:" and format option. :param input_file: Path to video/audio file to clip from. :param timestamp_start: Start time in milliseconds. :param timestamp_end: End time in milliseconds. :param quality: If output extension is .mp3, this is the bitrate in kbps. Ignored otherwise. :param to_mono: If set, mixes all input channels to mono to save space :param normalize_audio: If set, attempts to normalize loudness of output audio. YMMV. :param outpath: Path to save to. :param format: Output format (e.g. mp3, flac, etc), required if extension of outpath is missing/not the intended format. Required if outpath is "pipe:" since there is no output extension to infer from. :param silent: If set, suppresses stderr. :return: FFmpeg stdout data if capture_stdout is set """ input_stream = ffmpeg.input(str(input_file)) input_stream = input_stream[str(stream_index)] input_stream = input_stream.filter("atrim", start=timestamp_start / 1000, end=timestamp_end / 1000).filter( "asetpts", "PTS-STARTPTS") if normalize_audio: input_stream = input_stream.filter("loudnorm", print_format="summary") kwargs = {} if outpath.suffix.lower() == ".mp3": if quality is not None: kwargs['audio_bitrate'] = f'{quality}k' else: kwargs['audio_bitrate'] = '320k' if to_mono: kwargs['ac'] = 1 # audio channels if format is not None: kwargs['format'] = format input_stream = ffmpeg.output(input_stream, str(outpath), **kwargs) input_stream = ffmpeg.overwrite_output(input_stream) args = input_stream.get_args() # logging.debug(f"ffmpeg_trim_audio_clip: args: {args}") stdout, stderr = ffmpeg.run(input_stream, capture_stdout=capture_stdout, capture_stderr=silent) return stdout
def crop_video( filename, xmin, xmax, ymin, ymax, out_name=None, speed='superfast', bit_rate='20000k'): if out_name is None: core, ext = os.path.splitext(filename) if ext == '.MP4': ext = '.mp4' out_name = core + '_crop' + ext width = xmax - xmin height = ymax - ymin stream = ffmpeg.input(filename) stream = ffmpeg.crop( stream, xmin, ymin, width, height) stream = ffmpeg.output( stream, out_name, preset=speed, video_bitrate=bit_rate) stream = ffmpeg.overwrite_output(stream) ffmpeg.run(stream, quiet=True)
def convert(file_name: str, convert_ext): tmp_path = os.getcwd() + "\\" + tmp_dir_path + "\\" + file_name convert_dir_path = "convert" if os.path.exists(convert_dir_path) is False: os.mkdir(convert_dir_path) convert_path = os.getcwd( ) + "\\" + convert_dir_path + "\\" + file_name.split( ".")[0] + "." + convert_ext if os.path.exists(log_dir_path) is False: os.mkdir(log_dir_path) log_path = os.getcwd() + "\\" + log_dir_path + "\\" + file_name.split( ".")[0] + ".txt" kwargs = {"progress": log_path} try: stream = ffmpeg.input(tmp_path) stream = ffmpeg.output(stream, convert_path, **kwargs) stream = ffmpeg.overwrite_output(stream) ffmpeg.run(stream) except Exception as e: print(e) finally: os.remove(tmp_path) return ""
def extract(source_path): wav_path = source_path + '.wav' stream = ffmpeg.input(source_path) stream = ffmpeg.output(stream, wav_path, acodec='pcm_s16le', ac=1) stream = ffmpeg.overwrite_output(stream) ffmpeg.run(stream, capture_stderr=True) wav, fr = _read_wave(wav_path) wav = wav[0] feat = dict() feat['sample_rate'] = fr feat['length'] = wav.size feat['time_ms'] = wav.size * 1000 // fr feat['db'] = _db(wav) feat['sound_sect'] = _sound_section(wav, fr) feat['power_spec'], feat['freq'], feat['pitch'] = _spectrum(wav, fr) nfilt = 16 high_freq = 8000 filter_type = 'mel' feat['fbank_spec'], feat['fbank_freq'] = _fbank(wav, sample_rate=fr, nfilt=nfilt, high_freq=high_freq, type=filter_type) feat['pitch_reaper'] = _pitch_reaper(wav_path) wav, fr = librosa.load(wav_path) feat['pitch_librosa'] = _pitch_librosa(wav, fr) os.remove(wav_path) return feat
def _save_video(path, array, fps=25, video_codec='libx264'): # Check the extension of the given file path = _check_extensions([path], extensions=['.mp4'])[0] # Get the informations from the array n, height, width, channels = array.shape # Initialize the process process = ffmpeg.input('pipe:', format='rawvideo', pix_fmt='rgb24', s='{}x{}'.format(width, height)) process = ffmpeg.output(process, path, pix_fmt='yuv420p', vcodec=video_codec, r=fps) process = ffmpeg.overwrite_output(process) process = ffmpeg.run_async(process, pipe_stdin=True) # Save all the frames for frame in array: process.stdin.write(frame.tobytes()) # Terminate the process process.stdin.close() process.wait()
def reencode(filepath, loglevel='panic'): """ Re-encode video as mp4, remove start offset and set bframes to 0 :param filepath: input video file :param loglevel: ffmpeg loglevel :return: """ try: import ffmpeg except ImportError: logger.error( 'Import Error! Cant import ffmpeg. ' 'Annotations operations will be limited. import manually and fix errors' ) raise if not os.path.isfile(filepath): raise IOError('File doesnt exists: {}'.format(filepath)) # re encode video without b frame and as mp4 basename, ext = os.path.splitext(filepath) output_filepath = os.path.join( basename, os.path.basename(filepath).replace(ext, '.mp4')) if not os.path.isdir(os.path.dirname(output_filepath)): os.makedirs(os.path.dirname(output_filepath)) try: stream = ffmpeg.input(filepath, **{ 'loglevel': loglevel }).output(output_filepath, **{ 'x264opts': 'bframes=0', 'f': 'mp4' }) ffmpeg.overwrite_output(stream).run() except Exception as e: logger.exception('ffmpeg error in disassemble:') raise output_probe = Videos.get_info(output_filepath) start_time = eval(output_probe['streams'][0]['start_time']) fps = eval(output_probe['streams'][0]['avg_frame_rate']) has_b_frames = output_probe['streams'][0]['has_b_frames'] start_frame = fps * start_time if start_time != 0: logger.warning('Video start_time is not 0!') if has_b_frames != 0: logger.warning('Video still has b frames!') return output_filepath
def convertToVideo(path): stream = ffmpeg.input(r'tweetimages/'+path+'/*.png', pattern_type='glob', framerate=0.33) #stream = ffmpeg.input(r'tweetimages/*.png', pattern_type='glob', framerate=1) #stream = ffmpeg.output(stream,'tweetimages/movie1.mp4') stream = ffmpeg.output(stream,'Videos/'+path+'.mp4',loglevel="quiet") stream = ffmpeg.overwrite_output(stream) ffmpeg.run(stream) shutil.rmtree('tweetimages/'+path)
def encode_frames(directory: str, output: str, framerate: int, pad_length: int): frames = ffmpeg.input(pjoin(directory, f"%0{pad_length}d.png"), **{"pattern_type": "sequence"}) frames = ffmpeg.filter(frames, "fps", fps=framerate) frames = ffmpeg.output(frames, output) frames = ffmpeg.overwrite_output(frames) ffmpeg.run(frames)
def ffmpeg_condense_audio(audiofile, sub_times, outfile=None): if outfile is None: outfile = "condensed.flac" # logging.info(f"saving condensed audio to {outfile}") # get samples in audio file audio_info = ffmpeg.probe(audiofile, cmd='ffprobe') sps = int( audio_info['streams'][0]['time_base'].split('/')[1]) # audio samples per second, inverse of sampling frequency # samples = audio_info['streams'][0]['duration_ts'] # total samples in audio track stream = ffmpeg.input(audiofile) clips = list() for time in sub_times: # times are in milliseconds start = int(time[0] * sps / 1000) # convert to sample index end = int(time[1] * sps / 1000) # use start_pts for sample/millisecond level precision clips.append(stream.audio.filter('atrim', start_pts=start, end_pts=end).filter('asetpts', 'PTS-STARTPTS')) combined = ffmpeg.concat(*clips, a=1, v=0) if os.path.splitext(outfile)[1] == ".mp3": combined = ffmpeg.output(combined, outfile, audio_bitrate='320k') # todo: make this user-settable else: combined = ffmpeg.output(combined, outfile) combined = ffmpeg.overwrite_output(combined) logging.debug(f"ffmpeg arguments: {' '.join(ffmpeg.get_args(combined))}") args = ffmpeg.get_args(combined) if len("ffmpeg " + " ".join(args)) > 32766 and os.name == 'nt': logging.warning("Arguments passed to ffmpeg exceeds 32767 characters while running on a Windows system. " "Will try using a temporary file to pass filter_complex arguments to ffmpeg.") idx = args.index("-filter_complex") + 1 complex_filter = str(args[idx]) # write complex_filter to a temporary file fp = tempfile.NamedTemporaryFile(delete=False) # don't delete b/c can't open file again when it's already open in windows, need to close first fp.write(complex_filter.encode(encoding="utf-8")) fp.close() args[idx] = fp.name args[idx - 1] = "-filter_complex_script" args = ["ffmpeg"] + args # ffmpeg.run(combined, quiet=logging.getLogger().getEffectiveLevel() >= logging.WARNING) pipe_stdin = False pipe_stdout = False pipe_stderr = False quiet = logging.getLogger().getEffectiveLevel() >= logging.WARNING stdin_stream = subprocess.PIPE if pipe_stdin else None stdout_stream = subprocess.PIPE if pipe_stdout or quiet else None stderr_stream = subprocess.PIPE if pipe_stderr or quiet else None process = subprocess.Popen( args, stdin=stdin_stream, stdout=stdout_stream, stderr=stderr_stream ) out, err = process.communicate(input) retcode = process.poll() if retcode: raise Error('ffmpeg', out, err)
def demo_extract_audio(): host = '172.31.23.124' stream = '2' stream = ffmpeg.input('rtsp://' + host + '/' + stream) stream = stream['a'] # 只抽出MPEG-4 AAC音频不转码 stream = ffmpeg.output(stream, 'out/rtsp_audio.mp4', strict='-2') # 直接覆盖同名文件不询问 stream = ffmpeg.overwrite_output(stream) stream.run(capture_stdout=True)
def generate_sequence(d): '''will expect correct folders and files''' d = os.path.abspath(d) console.rule(d, align='left') d_seq = os.path.join(d, 'sequences') console.print(d_seq) # stream = None # files = [d.path for d in os.scandir(d_seq) if d.is_file()] frames = [] for root, dirs, files in os.walk(d_seq): # files = [f for f in files if ('circle' in f or 'line' in f) ] files = [f for f in files if '.png' in f] files = [f for f in files if 'zoom' not in f] with open(f'{d}/output/sequence.lst', 'w') as lst: for f in sorted(files): png = os.path.join(d_seq, f) mp4 = f'{d}/output/{f}.mp4' frame = ffmpeg.input(png, r=1) frame = ffmpeg.output(frame, mp4) frame = ffmpeg.overwrite_output(frame) ffmpeg.run(frame) # frames.append(frame) lst.write(f'file {mp4}\n') # frames.append(ffmpeg.input(png, r=1)) # frames.append(ffmpeg.input(os.path.join(d_seq, f), frames=24)) f = os.path.splitext(f)[0] # num, *type = f.split('-') # print(int(num), *type) # out = ffmpeg.merge_outputs(*frames) # print(ffmpeg.get_args(out)) # out = ffmpeg.concat(*frames) # out = ffmpeg.input('output/sequence.lst', f='concat') # out = ffmpeg.input('output/sequence.lst') # out = ffmpeg.output(out, 'sequences3.mp4', unsafe=False) # files = [f.path for f in list(os.scandir('output')) if '.mp4' in f.path] # stream = '' # inputs = [] # for f in files: # inputs.append(ffmpeg.input(f)) # out = ffmpeg.output(*inputs, 'sequences3.mp4') # ffmpeg.run(out) proc = ['ffmpeg'] proc.append('-f') proc.append('concat') proc.append('-i') proc.append('output/sequence.lst') proc.append('-r') proc.append('60') proc.append('sequence4.mp4') subprocess.run(proc)
def videoConvert(inputFile, outputFile): stream = ffmpeg.input(inputFile, loglevel="error", stats="") stream = ffmpeg.output(stream, outputFile) stream = ffmpeg.overwrite_output(stream) print("Converting {}:".format(inputFile)) initial_time = time.time() ffmpeg.run(stream) overall = time.time() - initial_time print("Overall convert time", overall) return overall
def ffmpeg_export( p_indir ): # the real meat, this is where i struggle with ffmpeg-python and occasionally succeed des_w = int(entry_w.get()) des_h = int(entry_h.get()) if (des_w > sel_w) or (des_h > sel_h): messagebox.showerror( title="Error", message="Desired size is larger than source size!") return sel_ratio = sel_w / sel_h des_ratio = des_w / des_h # safe placeholder values for when src and output have the same ratio x_offset = 0 y_offset = 0 adj_w = sel_w adj_h = sel_h if (crop_h.get() == 1) and (sel_ratio != des_ratio): adj_w = des_ratio * sel_h # get the new width for the desired aspect ratio x_offset = (sel_w - adj_w) / 2 # centering math elif (crop_h.get() == 0) and (sel_ratio != des_ratio): adj_h = des_ratio * sel_w y_offset = (sel_h - adj_h) / 2 for x in files: x = p_indir + os.sep + x progress_ffmpeg.config(text='Rendering: ' + os.path.split(x)[1]) frame_ffmpeg.update() # ffmpeg complains if we try to output to the same file as our input # so we output to a different file and replace the input afterwards outdir = x + '~.png' if overwrite_og.get() == 0 and use_custom_outdir.get() == 0: newdir = os.path.dirname(str(x)) + '_' + \ str(des_w) + 'x' + str( des_h) # results in {old directory}_{width}x{height} in the old directory's parent dir outdir = newdir + os.sep + str(os.path.split(x)[1]) if not os.path.isdir(newdir): os.mkdir(newdir) elif use_custom_outdir.get() == 1: outdir = custom_outdir + os.sep + str(os.path.split(x)[1]) stream = ffmpeg.input(str(x), nostdin=None) stream = ffmpeg.crop(stream, x_offset, y_offset, adj_w, adj_h) stream = ffmpeg.filter( stream, "scale", des_w, des_h, flags="bilinear") # TODO: allow user to choose algorithm stream = ffmpeg.output( stream, outdir, hide_banner=None ) # TODO: find a way to stop making a new shell for each op stream = ffmpeg.overwrite_output(stream) ffmpeg.run_async(stream) if overwrite_og.get( ) == 1: # check again because overwriting when we're not supposed to is bad mkay os.remove(x) os.rename(x + '~.png', x) progress_ffmpeg.config(text='Rendering: Done!')
def _fix_framerate(self, vid_path, fr, overwrite): """ Fixes each video in the list of video paths to a certain frame rate. """ output_path = str(vid_path) if overwrite else str( vid_path.parent / f'{vid_path.stem}_fixed_{fr}.mp4') stream = ffmpeg.input(vid_path) stream = ffmpeg.output(stream, output_path, r=fr) stream = ffmpeg.overwrite_output(stream) out, err = ffmpeg.run(stream) return Path(output_path)
def convert_to_wav(tmp_path, dest_path): """Convert between any audio format supported by ffmpeg Args: tmp_path: string, input file path with some audio extension at the end (example: ./data/foo/name.mp3) dest_path: string, output path to which file will be converted to (example: ./data/bar/name.wav) """ stream = ffmpeg.input(tmp_path) stream = ffmpeg.output(stream, dest_path) stream = ffmpeg.overwrite_output(stream) ffmpeg.run(stream)
def save_video(fname, images, output_fps=30, vcodec='libx264', filters=''): assert isinstance(images, np.ndarray), "images should be np.array: NHWC" num_frames, height, width, channels = images.shape stream = ffmpeg.input('pipe:', format='rawvideo', pix_fmt='rgb24', s='{}x{}'.format(width, height)) stream = ffmpeg.filter(stream, 'setpts', '2*PTS') # 2*PTS is for slower playback stream = ffmpeg.output(stream, fname, pix_fmt='yuv420p', vcodec=vcodec, r=output_fps) stream = ffmpeg.overwrite_output(stream) process = ffmpeg.run_async(stream, pipe_stdin=True) for frame in tqdm(images, desc='writing video to %s' % fname): process.stdin.write(frame.astype(np.uint8).tobytes()) process.stdin.close() process.wait()
def convert_video(avi_file, source_file_path): source_file_dir = os.path.dirname(source_file_path) source_file_name = os.path.splitext(os.path.basename(source_file_path))[0] final_file_path = source_file_dir + "/" + source_file_name + ".mp4" stream = ffmpeg.input(avi_file) # stream = ffmpeg.output(stream, source_file_dir+"/"+source_file_name+".mp4", vcodec='libx264', metadata='s:v rotate="0"', vf="transpose=3", crf=23, acodec="copy") stream = ffmpeg.output(stream, final_file_path, vcodec='libx264', crf=23, acodec="copy") stream = ffmpeg.overwrite_output(stream) ffmpeg.run(stream) return final_file_path
def convert(self, scale_width): # self.message.reply_text('🔥 Testing video conversion 🔥') stream = ffmpeg.input('temp.' + self.ext) audio_stream = stream.audio if scale_width: stream = ffmpeg.filter(stream, 'scale', 640, -1) else: stream = ffmpeg.filter(stream, 'scale', -1, 640) out_stream = ffmpeg.concat(stream, audio_stream, v=1, a=1) output_filename = 'temp.converted.' + self.ext out_stream = ffmpeg.output(out_stream, output_filename) out_stream = ffmpeg.overwrite_output(out_stream) ffmpeg.run(out_stream) self.bot.send_video(chat_id=self.message.chat_id, video=open(output_filename, 'rb'), supports_streaming=True)
def output_segment_video(segment_video, segment_video_path): # if os.path.exists(segment_video_path): # os.rename(segment_video_path, segment_video_path + '.old') # segment_video_input_file = segment_video_path + '.old' # else: # segment_video_input_file = config.background_video segment_video = ffmpeg.output(segment_video, segment_video_path, preset='ultrafast', loglevel=config.ffmpeg['error_level'], threads=config.ffmpeg['threads']) segment_video = ffmpeg.overwrite_output(segment_video) ffmpeg.run(segment_video)
def disassemble(filepath, fps=None, loglevel='panic'): """ Disassemble video to images :param filepath: input video filepath :param fps: rate of disassemble. e.g if 1 frame per second fps is 1. if None all frames will be extracted :param loglevel: ffmpeg loglevel :return: """ import ffmpeg if not os.path.isfile(filepath): logger.exception('File doesnt exists') raise IOError basename, ext = os.path.splitext(filepath) # create folder for the frames if not os.path.exists(basename): os.makedirs(basename, exist_ok=True) # get video information video_props = Videos.get_info(filepath) if fps is None: fps = eval(video_props['streams'][0]['avg_frame_rate']) num_of_zeros = len(video_props['streams'][0]['nb_frames']) # format the output filename output_regex = os.path.join(basename, '%%0%dd.jpg' % num_of_zeros) try: stream = ffmpeg.input(filepath, **{ 'loglevel': loglevel }).output(output_regex, **{ 'start_number': '0', 'r': str(fps) }) ffmpeg.overwrite_output(stream).run() except Exception as e: logger.exception('ffmpeg error in disassemble:') raise return basename
def concat_ranges(filename, out_filename, ranges, config: VideoMontageConfig): """ ranges are in seconds """ assert os.path.isfile(filename) input_vid = ffmpeg.input(filename) total_duration = sum([x[1] - x[0] for x in ranges]) print(f'Processing {out_filename} ({len(ranges)} ranges -> {total_duration:.0f} seconds)') streams = [] for r in ranges: start = int(r[0]) end = math.floor(r[1]) vid = ( input_vid .trim(start=start, end=end) .setpts('PTS-STARTPTS') ) aud = ( input_vid['a:0'] .filter_('atrim', start=start, end=end) .filter_('asetpts', 'PTS-STARTPTS') ) if config.mix_mic_audio_track: mic = ( input_vid['a:1'] .filter_('atrim', start=start, end=end) .filter_('asetpts', 'PTS-STARTPTS') ) aud = ffmpeg.filter([aud, mic], 'amix', duration='shortest', weights=f'1 {config.mic_volume_multiplier}') streams.append(vid) streams.append(aud) joined = ffmpeg.concat(*streams, v=1, a=1) output = ffmpeg.output(joined, out_filename, vcodec='hevc_nvenc', video_bitrate=config.video_bitrate) output = output.global_args('-loglevel', 'error') output = ffmpeg.overwrite_output(output) start_time = time.time() custom_ffmpeg_run(output, ffmpeg_cmd) elapsed = time.time() - start_time print(f'Elapsed {elapsed:.2f} seconds\n')
def process_file(self, track: Track): """ Attempts to transcode the file in download/temp into the audio file """ temp_file = Path("download/temp") if not temp_file.is_file(): raise Exception("temp file doesn't exist") input_ffmpeg = ffmpeg.input("download/temp") input_audio = input_ffmpeg['a'] # We will not be referencing the video stream, only the main audio stream # Normalise loudness input_audio = ffmpeg.filter(input_audio, "loudnorm", I=-16, TP=-1.5, LRA=11) # https://superuser.com/questions/1362176/how-to-trim-silence-only-from-beginning-and-end-of-mp3-files-using-ffmpeg/1364824 # Trim silence from start input_audio = ffmpeg.filter(input_audio, "silenceremove", start_periods=1, start_duration=1, start_threshold="-60dB", detection="peak") # No idea what this does input_audio = ffmpeg.filter(input_audio, "aformat", "dblp") # Reverse the audio input_audio = ffmpeg.filter(input_audio, "areverse") # Trim silence from start (but this track is reversed now, so this is trimming from the end input_audio = ffmpeg.filter(input_audio, "silenceremove", start_periods=1, start_duration=1, start_threshold="-60dB", detection="peak") # No idea what this does input_audio = ffmpeg.filter(input_audio, "aformat", "dblp") # Reverse the audio input_audio = ffmpeg.filter(input_audio, "areverse") output_ffmpeg = ffmpeg.output(input_audio, filename=f"download/{track.info.source_id}.mp3") output_ffmpeg = ffmpeg.overwrite_output(output_ffmpeg) # overwrite if needed def run_ffmpeg(output): return ffmpeg.run(output, quiet=True) # Force monkey patching to run this in the background in this supposed background task... tpool.execute(run_ffmpeg, output_ffmpeg) try: os.remove("download/temp") except: raise Exception("failed to delete temp file")