def trim(input, output, start, stop, re_encode, show_ffmpeg_output, suppress_prompts): """removes unwanted content from the start and end of the input file""" if show_ffmpeg_output: autoscrub.suppress_ffmpeg_output(False) else: autoscrub.suppress_ffmpeg_output(True) # check executables exist check_ffmpeg() # check autoscrub version check_for_new_autoscrub_version() # convert input/output paths to absolute paths input = os.path.abspath(input) output = os.path.abspath(output) # check if output file exists and prompt if os.path.exists(output) and not suppress_prompts: click.confirm( '[autoscrub:warning] The specified output file [{output}] already exists. Do you want to overwrite?' .format(output=output), abort=True) if re_encode is None: re_encode = 'copy' autoscrub.trim(input, start, stop, output, True, re_encode)
def get_properties(input, show_ffmpeg_output): """Displays properties about the input file""" if show_ffmpeg_output: autoscrub.suppress_ffmpeg_output(False) else: autoscrub.suppress_ffmpeg_output(True) # check executables exist check_ffmpeg() # check autoscrub version check_for_new_autoscrub_version() # convert input/output paths to absolute paths input = os.path.abspath(input) # run ffprobe and extract data ffprobe_log = autoscrub.ffprobe(input) duration = autoscrub.findDuration(ffprobe_log) samplerate = autoscrub.findSampleRate(ffprobe_log) loudness = autoscrub.getLoudness(input) try: click.echo("[ffprobe] Duration: {:.3f}s".format(duration)) except Exception: click.echo("[ffprobe] Duration: unknown") try: click.echo("[ffprobe] Audio sample rate: {}Hz".format(samplerate)) except Exception: click.echo("[ffprobe] Audio sample rate: unknown") try: click.echo("[ffmpeg:ebur128] Loudness: {}LUFS".format(loudness['I'])) except Exception: click.echo("[ffmpeg:ebur128] Loudness: unknown")
def match_loudness(input, output, target_lufs, show_ffmpeg_output, suppress_prompts): """Adjusts the loudness of the input file""" if show_ffmpeg_output: autoscrub.suppress_ffmpeg_output(False) else: autoscrub.suppress_ffmpeg_output(True) # check executables exist check_ffmpeg() # check autoscrub version check_for_new_autoscrub_version() # convert input/output paths to absolute paths input = os.path.abspath(input) output = os.path.abspath(output) # check if output file exists and prompt if os.path.exists(output) and not suppress_prompts: click.confirm( '[autoscrub:warning] The specified output file [{output}] already exists. Do you want to overwrite?' .format(output=output), abort=True) autoscrub.matchLoudness(input, target_lufs, output, overwrite=True)
def make_filtergraph(input, speed, rescale, target_lufs, target_threshold, pan_audio, hasten_audio, silence_duration, delay, silent_volume, show_ffmpeg_output, suppress_prompts): """Generates a filter-graph file for use with ffmpeg. \b This command is useful if you want to manually edit the filter-graph file before processing your video.""" if show_ffmpeg_output: autoscrub.suppress_ffmpeg_output(False) else: autoscrub.suppress_ffmpeg_output(True) # check executables exist check_ffmpeg() # check autoscrub version check_for_new_autoscrub_version() # convert input/output paths to absolute paths input = os.path.abspath(input) # ensure that there will always be some part of a silent segment that experiences a speedup if not (2 * delay < silence_duration): click.echo( "[autoscrub:error] The value for delay must be less than half of the silence_duration specified" ) return # determine the path of the filter graph file based on the name of the input file folder, filename = os.path.split(input) filter_graph_path = os.path.join( folder, '.'.join(filename.split('.')[:-1]) + '.filter-graph') # check if output file exists and prompt if os.path.exists(filter_graph_path) and not suppress_prompts: click.confirm( '[autoscrub:warning] The specified filtergraph output file [{output}] already exists. Do you want to overwrite?' .format(output=filter_graph_path), abort=True) # adjust hasten_audio if 'trunc' if hasten_audio == 'trunc': hasten_audio = None create_filtergraph(input, filter_graph_path, speed, rescale, target_lufs, target_threshold, pan_audio, hasten_audio, silence_duration, delay, silent_volume, suppress_prompts)
def use_filtergraph(input, output, show_ffmpeg_output, suppress_prompts): """Processes a video file using the filter-graph file created by the autoscrub make-filtergraph command""" if show_ffmpeg_output: autoscrub.suppress_ffmpeg_output(False) else: autoscrub.suppress_ffmpeg_output(True) # check executables exist check_ffmpeg() # check autoscrub version check_for_new_autoscrub_version() # convert input/output paths to absolute paths input = os.path.abspath(input) output = os.path.abspath(output) # determine the path of the filter script file based on the name of the input file folder, filename = os.path.split(input) filter_graph_path = os.path.join( folder, '.'.join(filename.split('.')[:-1]) + '.filter-graph') if not os.path.exists(filter_graph_path): raise Exception( '[autoscrub:error] Could not find filter-graph file for the specified input video (if you are unsure of what a filter-graph file is, consider using "autoscrub autoprocess"). Ensure that {path} exists. This file can be generated by using "autoscrub make-filtergraph".' ) # check if output file exists and prompt if os.path.exists(output) and not suppress_prompts: click.confirm( '[autoscrub:warning] The specified output file [{output}] already exists. Do you want to overrite?' .format(output=output), abort=True) # Process the video file using ffmpeg and the filtergraph result = autoscrub.ffmpegComplexFilter(input, filter_graph_path, output, run_command=True, overwrite=True)
def get_silences(input, silence_duration, target_threshold, show_ffmpeg_output): """Displays a table of detected silent segments""" if show_ffmpeg_output: autoscrub.suppress_ffmpeg_output(False) else: autoscrub.suppress_ffmpeg_output(True) # check executables exist check_ffmpeg() # check autoscrub version check_for_new_autoscrub_version() # convert input/output paths to absolute paths input = os.path.abspath(input) # output a message before beginning click.echo("[autoscub:info] Scanning for silent segments...") silences = autoscrub.getSilences(input, target_threshold, silence_duration, save_silences=False) click.echo("#\tstart \tend \tduration") for i, silence in enumerate(silences): ti = autoscrub.seconds_to_hhmmssd(silence['silence_start']) tf = autoscrub.seconds_to_hhmmssd( silence['silence_end']) if 'silence_end' in silence else '' dt = autoscrub.seconds_to_hhmmssd( silence['silence_duration'] ) if 'silence_duration' in silence else '' click.echo("{num}\t{start}\t{end}\t{duration}".format(num=i, start=ti, end=tf, duration=dt))
output_movie = movie_audio_folder / "movie_audio.mp3" video = VideoFileClip(str(movie_file)) audio = video.audio audio.write_audiofile(str(output_movie)) audio.close() audio.close() # # Extract silence from audios movies = [m for m in os.listdir(movies_prep_path) if not m.startswith('.')] # m = movies[0] for m in movies: silences_file = movies_prep_path / f'{m}/audio/silences.csv' if not os.path.exists(silences_file): print(m) audiofile = movies_prep_path / f'{m}/audio/movie_audio.mp3' autoscrub.suppress_ffmpeg_output(True) results = autoscrub.getSilences('./{}'.format(audiofile), input_threshold_dB=-40.0, silence_duration=1.0, save_silences=False) df = pd.DataFrame(results) df.to_csv(silences_file, index=False)
def autoprocess(input, output, speed, rescale, target_lufs, target_threshold, pan_audio, hasten_audio, silence_duration, delay, silent_volume, show_ffmpeg_output, suppress_prompts, debug): """automatically process the input video and write to the specified output file""" if show_ffmpeg_output: autoscrub.suppress_ffmpeg_output(False) else: autoscrub.suppress_ffmpeg_output(True) # check executables exist check_ffmpeg() # check autoscrub version check_for_new_autoscrub_version() # convert input/output paths to absolute paths input = os.path.abspath(input) output = os.path.abspath(output) # ensure that there will always be some part of a silent segment that experiences a speedup if not (2 * delay < silence_duration): click.echo( "[autoscrub:error] The value for delay must be less than half of the silence_duration specified" ) return # check if output file exists and prompt if os.path.exists(output) and not suppress_prompts: click.confirm( '[autoscrub:warning] The specified output file [{output}] already exists. Do you want to overwrite it?' .format(output=output), abort=True) # adjust hasten_audio if 'trunc' if hasten_audio == 'trunc': hasten_audio = None # Make a temporary file for the filterscript handle, filter_graph_path = tempfile.mkstemp() # Python returns an open handle which we don't want, so close it os.close(handle) silences = create_filtergraph(input, filter_graph_path, speed, rescale, target_lufs, target_threshold, pan_audio, hasten_audio, silence_duration, delay, silent_volume, suppress_prompts) estimated_duration = autoscrub.getDuration(input) for silence in silences: if 'silence_duration' in silence: estimated_duration -= (silence['silence_duration'] - 2 * delay) * (1 - 1.0 / speed) click.echo("[autoscrub:info] autoscrubbing video") # commented out because it's a bit confusing and could be incorrectly interpretted as the estimated conversion time, not video duration # click.echo("Estimated duration of autoscrubbed video is {}".format(autoscrub.seconds_to_hhmmssd(estimated_duration))) nlc = NewLineCallback(estimated_duration) if not show_ffmpeg_output: callback = nlc.new_line_callback else: callback = None # Process the video file using ffmpeg and the filtergraph result = autoscrub.ffmpegComplexFilter(input, filter_graph_path, output, run_command=True, overwrite=True, stderr_callback=callback) start_time = callback.__self__.start_time if autoscrub.six.PY3 else callback.im_self.start_time seconds_taken = time.time() - start_time time_taken = autoscrub.seconds_to_hhmmssd(seconds_taken, decimal=False) click.echo( "[ffmpeg:filter_complex_script] Completed in {} ({:.1f}x speed) ". format(time_taken, estimated_duration / seconds_taken)) click.echo("[autoscrub:info] Done!") click.echo("[autoscrub:info] FFmpeg command run was: ") click.echo(" " + subprocess.list2cmdline(result)) # delete the filtergraph temporary file unless we are debugging if not debug: # delete the temporary file os.remove(filter_graph_path) else: click.echo( '[autoscrub:debug] The filter script is located at: {filter_graph_path}' .format(filter_graph_path=filter_graph_path))