diff --git a/FFMpeg.py b/FFMpeg.py index 7cac365..27bcebc 100644 --- a/FFMpeg.py +++ b/FFMpeg.py @@ -57,13 +57,13 @@ def ffprobe_run(input_file: str, execu=ffprob, de_bug=False) -> dict: '-analyzeduration', '100000000', '-probesize', '50000000', '-v', 'fatal', # XXX quiet, panic, fatal, error, warning, info, verbose, de_bug, trace + '-show_programs', + '-show_format', + '-show_streams', + '-show_error', + '-show_data', + '-show_private_data', '-of','json', # XXX default, csv, xml, flat, ini - '-show_programs', - '-show_format', - '-show_streams', - '-show_error', - '-show_data', - '-show_private_data', ] try: out = SP.run(cmd, stdout=SP.PIPE, check=True) @@ -338,7 +338,6 @@ def parse_frmat(input_file: str, mta_dta: Dict[str, any], de_bug: bool) -> Tuple if datax_streams: ff_datat, d_skip = parse_extrd(datax_streams, de_bug) - # ff_com.extend(ff_datat) d_skip = True # XXX: Avoid reencode skip_it = skip_it and d_skip if de_bug : print (f"\nSkip={skip_it}, Dskip = {d_skip}\n" ) @@ -400,12 +399,11 @@ def add_subtl_from_file(input_file: str, de_bug: bool) -> tuple[list, bool]: return [], True ##>>============-------------------< End >------------------==============<<## -# Define a helper function to select the appropriate encoder and options def get_encoder_options(codec_name, src_pix_fmt, bit_rate, use_hw_accel=False): msj = sys._getframe().f_code.co_name - # Determine if the source is 10-bit is_10bit = src_pix_fmt.endswith("10le") - # Set base values + + # Quality presets target_quality='as_is' quality_presets = { 'low': {'bitrate': (bit_rate // (1024 * 3 )), 'quality': 26}, @@ -414,17 +412,22 @@ def get_encoder_options(codec_name, src_pix_fmt, bit_rate, use_hw_accel=False): 'high': {'bitrate': (bit_rate // (1024 * 0.75)), 'quality': 20}, 'higher': {'bitrate': (bit_rate // (1024 * 0.5 )), 'quality': 18}, } + +# print (f"Cod:{codec_name} Pix: {src_pix_fmt} Btr: {bit_rate // 1024} HWA: {use_hw_accel} ") preset = quality_presets[target_quality] base_target_bitrate = int(preset['bitrate']) global_quality = preset['quality'] - # Adjust for 10-bit content + + # Adjust for 10-bit content if is_10bit: target_bitrate = str(int(base_target_bitrate * 1.25)) + 'k' else: target_bitrate = str(base_target_bitrate) + 'k' - # Calculate max_bitrate and bufsize + + # Calculate max_bitrate and bufsize max_bitrate = str(int(int(target_bitrate.rstrip('k')) * 1.5)) + 'k' bufsize = str(int(int(max_bitrate.rstrip('k')) * 2)) + 'k' + if use_hw_accel: # print(f" {msj} HW accelerated") hw_pix_fmt = "p010le" if is_10bit else "nv12" @@ -458,7 +461,6 @@ def get_encoder_options(codec_name, src_pix_fmt, bit_rate, use_hw_accel=False): ] ##>>============-------------------< End >------------------==============<<## - @perf_monitor def parse_video(strm_in, de_bug=False, use_hw_accel=True ): ''' Parse and extract data from video streams ''' diff --git a/My_Utils.py b/My_Utils.py index 1d267b2..0a887fd 100644 --- a/My_Utils.py +++ b/My_Utils.py @@ -77,7 +77,7 @@ def perf_monitor(func): if not debug: # If running in optimized mode, return the original function return func - + @wraps(func) def wrapper(*args, **kwargs): calling_function = sys._getframe().f_back.f_code.co_name if sys._getframe().f_back is not None else "Top Level" @@ -286,10 +286,10 @@ def __exit__(self, exc_type, exc_value, traceback): class Spinner: def __init__(self, spin_text="|/-o+\\", indent=0): - self.spinner_count = 0 - self.spin_text = spin_text - self.spin_length = len(spin_text) - self.prefix = " " * indent # Indentation string + self.spinner_count = 0 + self.spin_text = spin_text + self.spin_length = len(spin_text) + self.prefix = " " * indent # Indentation string self.last_message_length = 0 # To keep track of the length of the last printed message self.cursor_hidden = False @@ -298,11 +298,13 @@ def hide_cursor(self): sys.stderr.write("\033[?25l") # Hide cursor sys.stderr.flush() self.cursor_hidden = True + def show_cursor(self): if self.cursor_hidden: sys.stderr.write("\033[?25h") # Show cursor sys.stderr.flush() self.cursor_hidden = False + def print_spin(self, extra: str = "") -> None: """ Prints a spinner in the console to indicate progress. @@ -310,25 +312,40 @@ def print_spin(self, extra: str = "") -> None: Args: extra (str): Additional text to display after the spinner. """ + # Hide the cursor self.hide_cursor() + + # Get terminal width terminal_width = shutil.get_terminal_size().columns + spin_char = self.spin_text[self.spinner_count % self.spin_length] message = f"\r{self.prefix}| {spin_char} | {extra}" + + # Truncate the message if it's too long for the terminal if len(message) > terminal_width: message = message[:terminal_width - 1] # Truncate to fit the terminal width + + # Calculate the number of spaces needed to clear the previous message clear_spaces = max(self.last_message_length - len(message), 0) + + # Print the spinner and the extra text, followed by enough spaces to clear any leftover characters sys.stderr.write(f"{message}{' ' * clear_spaces}") sys.stderr.flush() + + # Update the length of the last message self.last_message_length = len(message) + self.spinner_count += 1 def stop(self): """ Stops the spinner and shows the cursor. """ + # Show the cursor self.show_cursor() sys.stderr.write("\n") # Move to the next line after stopping sys.stderr.flush() + ''' # Example usage: if __name__ == "__main__": @@ -448,33 +465,42 @@ def hm_sz(numb: Union[str, int, float], type: str = "B") -> str: ##==============------------------- End -------------------==============## def hm_time(timez: float) -> str: - '''Print time as years, months, weeks, days, hours, min, sec''' - units = { - 'year': 31536000, - 'month': 2592000, - 'week': 604800, - 'day': 86400, - 'hour': 3600, - 'min': 60, - 'sec': 1, - } - - if timez < 0.0: + """Converts time in seconds to a human-readable format.""" + + units = [ + ('year', 31536000), + ('month', 2592000), + ('week', 604800), + ('day', 86400), + ('hour', 3600), + ('minute', 60), + ('second', 1) + ] + + # Handle edge cases + if timez < 0: return "Error: time cannot be negative." - elif timez == 0.0: + if timez == 0: return "Zero time." - elif timez < 0.001: + if timez < 0.001: return f"{timez * 1000:.3f} ms" - elif timez < 60: - return f"{timez:>5.3f} sec{'s' if timez != 1 else ''}" + if timez < 60: + return f"{timez:.3f} second{'s' if timez != 1 else ''}" + + result = [] + + # Convert time into larger units + for unit, seconds_in_unit in units: + value = int(timez // seconds_in_unit) + if value > 0: + result.append(f"{value} {unit}{'s' if value > 1 else ''}") + timez %= seconds_in_unit + + # Join the result with 'and' for the last unit + if len(result) > 1: + return ", ".join(result[:-1]) + " and " + result[-1] else: - frmt = [] - for unit, unit_of_time in units.items(): - value = timez // unit_of_time - if value != 0: - frmt.append(f"{int(value)} {unit}{'s' if value > 1 else ''}") - timez %= unit_of_time - return ", ".join(frmt[:-1]) + " and " + frmt[-1] if len(frmt) > 1 else frmt[0] if frmt else "0 sec" + return result[0] ##>>============-------------------< End >------------------==============<<## @@ -502,7 +528,7 @@ def copy_move(src: str, dst: str, keep_original: bool = False, verbose: bool = F return True try: - (action, transfer_func) = ("_Copied", shutil.copy2) if keep_original else ("_Moved", shutil.move) + (action, transfer_func) = ("_Copy", shutil.copy2) if keep_original else ("_Move", shutil.move) transfer_func(src, dst) if verbose: print(f"{action}: {src}\nTo : {dst}") diff --git a/Trans_code.py b/Trans_code.py index af9cd5c..b0926b3 100644 --- a/Trans_code.py +++ b/Trans_code.py @@ -290,6 +290,7 @@ def process_files(executor=None): handle_result(result) except Exception as e: print(f"Error processing future for file {f_path}: {e}") + spinner.stop() # Ensure the spinner stops def handle_result(result): if result: