# overwrite driver_settings with driver_args if driver_args is not None: driver_args_dict = vars(driver_args) for key in driver_args_dict: if driver_args_dict[key] is not None: driver_settings[key] = driver_args_dict[key] # start execution try: # start timer begin_time = time.time() # initialize upscaler object upscaler = Upscaler(input_path=video2x_args.input, output_path=video2x_args.output, driver_settings=driver_settings, ffmpeg_settings=ffmpeg_settings, gifski_settings=gifski_settings) # set upscaler optional options upscaler.driver = video2x_args.driver upscaler.scale_ratio = video2x_args.ratio upscaler.processes = video2x_args.processes upscaler.video2x_cache_directory = video2x_cache_directory upscaler.image_format = image_format upscaler.preserve_frames = preserve_frames # run upscaler upscaler.run() Avalon.info(
def load(self): debug_prefix = "[Dandere2x.load]" # Create Utils self.utils = Utils() # Set the log file, here's why loglevel 0 isn't literally 0 self.utils.clean_set_log() self.utils.log(colors["phases"], 3, debug_prefix, "# # [Load phase] # #") self.utils.log(color, 3, debug_prefix, "Created Utils()") # Check a few things and make sure the settings are compatible self.utils.log(color, 3, debug_prefix, "Creating FailSafe()") self.failsafe = FailSafe(self.utils) # Communication between files, static self.utils.log(color, 3, debug_prefix, "Creating Context()") self.context = Context(self.utils, self.config, self.failsafe) # Communication between files, depends on runtime self.utils.log(color, 3, debug_prefix, "Creating Controller()") self.controller = Controller(self.utils, self.context) # Let Utils access Controller self.utils.log(color, 3, debug_prefix, "Giving Utils, Controller") self.utils.set_controller(self.controller) # Let Utils access Context self.utils.log(color, 3, debug_prefix, "Giving Utils, Context") self.utils.set_context(self.context) # Stats self.utils.log(color, 3, debug_prefix, "Creating Dandere2xStats()") self.stats = Dandere2xStats(self.context, self.utils, self.controller) # Deals with Video related stuff self.utils.log(color, 3, debug_prefix, "Creating Video()") self.video = Video(self.context, self.utils, self.controller) # Deals with images, mostly numpy wrapper and special functions like block substitution self.utils.log(color, 3, debug_prefix, "Creating Frame()") self.frame = Frame # Our upscale wrapper, on which the default is upscaler self.utils.log(color, 3, debug_prefix, "Creating Upscaler()") self.upscaler = Upscaler(self.context, self.utils, self.controller, self.frame) # Math utils, specific cases for Dandere2x self.utils.log(color, 3, debug_prefix, "Creating Dandere2xMath()") self.d2xmath = Dandere2xMath(self.context, self.utils) # Dandere2x C++ wrapper self.utils.log(color, 3, debug_prefix, "Creating Dandere2xCPPWraper()") self.d2xcpp = Dandere2xCPPWraper(self.context, self.utils, self.controller, self.video, self.stats) # "Layers" of processing before the actual upscale from upscaler self.utils.log(color, 3, debug_prefix, "Creating Processing()") self.processing = Processing(self.context, self.utils, self.controller, self.frame, self.video, self.upscaler) # On where everything is controlled and starts self.utils.log(color, 3, debug_prefix, "Creating Core()") self.core = Core(self.context, self.utils, self.controller, self.upscaler, self.d2xcpp, self.processing, self.stats, self.video) # Vapoursynth wrapper self.utils.log(color, 3, debug_prefix, "Creating VapourSynthWrapper()") self.vapoursynth_wrapper = VapourSynthWrapper(self.context, self.utils, self.controller)
# start execution try: # start timer begin_time = time.time() # initialize upscaler object upscaler = Upscaler( # required parameters input_path=video2x_args.input, output_path=video2x_args.output, driver_settings=driver_settings, ffmpeg_settings=ffmpeg_settings, gifski_settings=gifski_settings, # optional parameters driver=video2x_args.driver, scale_ratio=video2x_args.ratio, scale_width=video2x_args.width, scale_height=video2x_args.height, processes=video2x_args.processes, video2x_cache_directory=video2x_cache_directory, extracted_frame_format=extracted_frame_format, output_file_name_format_string=output_file_name_format_string, image_output_extension=image_output_extension, video_output_extension=video_output_extension, preserve_frames=preserve_frames, ) # run upscaler upscaler.run() Avalon.info( _("Program completed, taking {} seconds").format(
if args.input.is_file(): # upscale single video file Avalon.info(f'Upscaling single video file: {args.input}') # check for input output format mismatch if args.output.is_dir(): Avalon.error('Input and output path type mismatch') Avalon.error('Input is single file but output is directory') raise Exception('input output path type mismatch') if not re.search(r'.*\..*$', str(args.output)): Avalon.error('No suffix found in output file path') Avalon.error('Suffix must be specified for FFmpeg') raise Exception('No suffix specified') upscaler = Upscaler(input_video=args.input, output_video=args.output, method=args.method, waifu2x_settings=waifu2x_settings, ffmpeg_settings=ffmpeg_settings) # set optional options upscaler.waifu2x_driver = args.driver upscaler.scale_width = args.width upscaler.scale_height = args.height upscaler.scale_ratio = args.ratio upscaler.model_dir = args.model_dir upscaler.threads = args.threads upscaler.video2x_cache_directory = video2x_cache_directory upscaler.image_format = image_format upscaler.preserve_frames = preserve_frames # run upscaler upscaler.create_temp_directories() upscaler.run()
class Dandere2x(): def __init__(self, config): self.config = config #os.system("sh release/compile_d2xcpp_linux.sh") #os.system("sh dandere2x_cpp_tremx/linux_cross_compile_windows.sh") #exit() # This function loads up the "core" variables and objects def load(self): debug_prefix = "[Dandere2x.load]" # Create Utils self.utils = Utils() # Set the log file, here's why loglevel 0 isn't literally 0 self.utils.clean_set_log() self.utils.log(colors["phases"], 3, debug_prefix, "# # [Load phase] # #") self.utils.log(color, 3, debug_prefix, "Created Utils()") # Check a few things and make sure the settings are compatible self.utils.log(color, 3, debug_prefix, "Creating FailSafe()") self.failsafe = FailSafe(self.utils) # Communication between files, static self.utils.log(color, 3, debug_prefix, "Creating Context()") self.context = Context(self.utils, self.config, self.failsafe) # Communication between files, depends on runtime self.utils.log(color, 3, debug_prefix, "Creating Controller()") self.controller = Controller(self.utils, self.context) # Let Utils access Controller self.utils.log(color, 3, debug_prefix, "Giving Utils, Controller") self.utils.set_controller(self.controller) # Let Utils access Context self.utils.log(color, 3, debug_prefix, "Giving Utils, Context") self.utils.set_context(self.context) # Stats self.utils.log(color, 3, debug_prefix, "Creating Dandere2xStats()") self.stats = Dandere2xStats(self.context, self.utils, self.controller) # Deals with Video related stuff self.utils.log(color, 3, debug_prefix, "Creating Video()") self.video = Video(self.context, self.utils, self.controller) # Deals with images, mostly numpy wrapper and special functions like block substitution self.utils.log(color, 3, debug_prefix, "Creating Frame()") self.frame = Frame # Our upscale wrapper, on which the default is upscaler self.utils.log(color, 3, debug_prefix, "Creating Upscaler()") self.upscaler = Upscaler(self.context, self.utils, self.controller, self.frame) # Math utils, specific cases for Dandere2x self.utils.log(color, 3, debug_prefix, "Creating Dandere2xMath()") self.d2xmath = Dandere2xMath(self.context, self.utils) # Dandere2x C++ wrapper self.utils.log(color, 3, debug_prefix, "Creating Dandere2xCPPWraper()") self.d2xcpp = Dandere2xCPPWraper(self.context, self.utils, self.controller, self.video, self.stats) # "Layers" of processing before the actual upscale from upscaler self.utils.log(color, 3, debug_prefix, "Creating Processing()") self.processing = Processing(self.context, self.utils, self.controller, self.frame, self.video, self.upscaler) # On where everything is controlled and starts self.utils.log(color, 3, debug_prefix, "Creating Core()") self.core = Core(self.context, self.utils, self.controller, self.upscaler, self.d2xcpp, self.processing, self.stats, self.video) # Vapoursynth wrapper self.utils.log(color, 3, debug_prefix, "Creating VapourSynthWrapper()") self.vapoursynth_wrapper = VapourSynthWrapper(self.context, self.utils, self.controller) # This function mainly configures things before upscaling and verifies stuff, # sees if it's a resume session, etc def setup(self): debug_prefix = "[Dandere2x.setup]" self.utils.log(colors["phases"], 3, debug_prefix, "# # [Setup phase] # #") # Make session folder self.utils.log(color, 3, debug_prefix, "Creating sessions directory if it doesn't exist [%s]" % self.context.sessions_folder) self.utils.mkdir_dne(self.context.sessions_folder) # Verify upscaler, get the binary self.utils.log(color, 3, debug_prefix, "Verifying upscaler") self.upscaler.verify() self.utils.log(color, 3, debug_prefix, "Generating run command from upscaler") self.upscaler.generate_run_command() # Warn the user and log mindisk mode if self.context.mindisk: self.utils.log(color, 2, debug_prefix, "[MINDISK] [WARNING] MINDISK MODE [ON]") else: self.utils.log(color, 2, debug_prefix, "[MINDISK] [WARNING] MINDISK MODE [OFF]") # Check if context_vars file exist and is set to be resume # If force argument is set, force not resume session if self.context.force: self.utils.log(colors["hard_warning"], 0, debug_prefix, "FORCE MODE ENABLED, FORCING RESUME=FALSE") # Set resume and force to false as both aren't true anymore self.context.resume = False self.context.force = False else: self.utils.log(color, 1, debug_prefix, "Checking if is Resume session") self.context.resume = self.utils.check_resume() # NOT RESUME SESSION, delete previous session, load up and check directories if not self.context.resume: # Log and reset session directory self.utils.log(colors["li_red"], 0, debug_prefix, "NOT RESUME SESSION, deleting session [%s]" % self.context.session_name) self.utils.rmdir(self.context.session) # Check dirs self.utils.log(color, 3, debug_prefix, "Checking directories") self.utils.check_dirs() # Reset files self.utils.log(color, 3, debug_prefix, "Reseting files") self.utils.reset_files() # Debugging, show static files self.utils.log(color, 3, debug_prefix, "Showing static files") self.utils.show_static_files() # Get video info self.utils.log(color, 3, debug_prefix, "Getting video info") self.video.get_video_info() self.utils.log(color, 3, debug_prefix, "Showing video info") self.video.show_info() # Values that should be setted up automatically self.d2xmath.set_block_size() # Save vars of context so we can resume it later self.utils.log(color, 3, debug_prefix, "Saving Context vars to file") self.context.save_vars() # Apply pre vapoursynth filter if self.context.use_vapoursynth: # Apply pre filter self.vapoursynth_wrapper.apply_filter( self.context.vapoursynth_pre, self.context.input_file, self.context.vapoursynth_processing ) # As we applied pre filter, our input video is now the processed one by vapoursynth self.context.input_file = self.context.vapoursynth_processing # # As something like a transpose can modify the video resolution we get the new info # Get video info self.utils.log(color, 3, debug_prefix, "Getting new video info [Vapoursynth can modify resolution]") self.video.get_video_info() self.utils.log(color, 3, debug_prefix, "Showing new video info") self.video.show_info() # IS RESUME SESSION, basically load instructions from the context saved vars else: self.utils.log(colors["li_red"], debug_prefix, 0, "IS RESUME SESSION") # Delete previous residuals / upscaled as they can cause some trouble self.utils.log(color, 1, debug_prefix, "[FAILSAFE] DELETING RESIDUAL, UPSCALE DIR AND PLUGINS INPUT FILE") self.utils.rmdir(self.context.residual) self.utils.rmdir(self.context.upscaled) # We just deleted two dirs, so gotta make sure they exist self.utils.log(color, 1, debug_prefix, "[FAILSAFE] REGENERATING DIRS") self.utils.check_dirs() # Load previous stopped session from the context self.utils.log(color, 1, debug_prefix, "Loading Context vars from context_vars file") self.context.load_vars_from_file(self.context.context_vars) # Get the last frame we piped to the last partial video as the starting frame of the next partial self.video.save_last_frame_of_video_ffmpeg(self.utils.get_last_partial_video_path(), self.context.resume_video_frame) # Create the encoding FFmpeg pipe self.video.ffmpeg.pipe_one_time(self.utils.get_partial_video_path()) # Here's the core logic for Dandere2x def run(self): debug_prefix = "[Dandere2x.run]" # Generate the command to run Dandere2x C++ self.d2xcpp.generate_run_command() # Only run Dandere2x C++ if self.context.only_run_dandere2x_cpp: self.context.mindisk = False self.d2xcpp.generate_run_command() self.utils.log(color, 0, debug_prefix, "WRITE ONLY DEBUG VIDEO SET TO TRUE, CALLING CPP AND QUITTING") self.context.last_processing_frame = 0 self.d2xcpp.run() self.controller.exit() return 0 # As now we get into the run part of Dandere2x, we don't really want to log # within the "global" log on the root folder so we move the logfile to session/log.log self.utils.move_log_file(self.context.logfile) self.utils.log(colors["phases"], 3, debug_prefix, "# # [Run phase] # #") # Start core Dandere2x, ie, start the threads self.core.start() # Set resume to True as we just started Dandere2x # It's not a good idea to stop an session early on, can yield blank videos and will not be merged properly at the end self.context.resume = True # Show the user we're still alive while True: # If controller stops or upscale is finished, break if self.controller.stop: break if self.controller.upscale_finished: break if not self.context.show_stats: self.utils.log(color, 1, debug_prefix, "Total upscale time: %s" % self.context.total_upscale_time) self.context.total_upscale_time += 1 time.sleep(1) # # When we exit the while loop before either we finished or we stopped # If we finished if self.controller.upscale_finished: # How many partials videos there is on the session partial directory? partials = len(os.listdir(self.context.partial)) # 1? Just copy it to the upscaled video if partials == 1: self.utils.rename(self.context.partial + "0.mkv", self.context.upscaled_video) # More than 1? Concatenate all of them elif partials > 1: # If we have two or more partials video self.video.ffmpeg.concat_video_folder_reencode(self.context.partial, self.context.upscaled_video) # Delete the partial dir self.utils.rmdir(self.context.partial) # None? oops, error else: self.utils.log(color, 0, debug_prefix, "[ERROR] No partials were found in [%s]" % self.context.partial) sys.exit(-1) # We still gotta add the audio to the upscaled file or / and post filters we might be interested into # Apply post vapoursynth filter as the upscale finished if self.context.use_vapoursynth: self.utils.log(color, 1, debug_prefix, "APPLYING POST VAPOURSYNTH FILTER") if self.context.use_vapoursynth: self.vapoursynth_wrapper.apply_filter( self.context.vapoursynth_pos, self.context.upscaled_video, self.context.vapoursynth_processing ) # Make the processed one the new upscaled self.utils.delete_file(self.context.upscaled_video) self.utils.rename(self.context.vapoursynth_processing, self.context.upscaled_video) # Migrate audio tracks from the original video to the new one self.video.ffmpeg.copy_videoA_audioB_to_other_videoC( self.context.upscaled_video, self.context.input_file, self.context.joined_audio ) # Delete old only upscaled video as migrated tracks self.utils.delete_file(self.context.upscaled_video) self.utils.rename(self.context.joined_audio, self.context.output_file) self.utils.log(color, 1, debug_prefix, "Total upscale time: %s" % self.context.total_upscale_time) # Move the logfile to the root folder as we're gonna delete the session folder self.utils.log(color, 1, debug_prefix, "Moving session log to root Dandere2x folder and Removing session folder [%s]" % self.context.session) self.utils.rename(self.context.logfile, self.context.logfile_last_session) # For removing the dir we gotta have a writable log file self.utils.logfile = self.context.logfile_last_session # Remove session folder as we finished everything self.utils.rmdir(self.context.session) # Happy upscaled video :) else: # Save progress for later resuming self.context.save_vars() self.utils.log(color, 0, debug_prefix, "Exiting Dandere2x.run")
# if input specified is a single file if os.path.isfile(args.input): """ Upscale single video file """ Avalon.info('Upscaling single video file: {}'.format(args.input)) # check for input output format mismatch if os.path.isdir(args.output): Avalon.error('Input and output path type mismatch') Avalon.error('Input is single file but output is folder') raise Exception('input output path type mismatch') if not re.search('.*\..*$', args.output): Avalon.error('No suffix found in output file path') Avalon.error('Suffix must be specified for FFmpeg') raise Exception('No suffix specified') upscaler = Upscaler(input_video=args.input, output_video=args.output, method=args.method, waifu2x_settings=waifu2x_settings, ffmpeg_settings=ffmpeg_settings) # set optional options upscaler.waifu2x_driver = args.driver upscaler.scale_width = args.width upscaler.scale_height = args.height upscaler.scale_ratio = args.ratio upscaler.model_dir = args.model_dir upscaler.threads = args.threads upscaler.video2x_cache_folder = video2x_cache_folder upscaler.image_format = image_format upscaler.preserve_frames = preserve_frames # run upscaler- upscaler.run() upscaler.cleanup()
exit(1) # start execution try: # start timer begin_time = time.time() if os.path.isfile(args.input): """ Upscale single video file """ Avalon.info('Upscaling single video file: {}'.format(args.input)) upscaler = Upscaler(input_video=args.input, output_video=args.output, method=args.method, waifu2x_settings=waifu2x_settings, ffmpeg_settings=ffmpeg_settings, waifu2x_driver=args.driver, scale_width=args.width, scale_height=args.height, scale_ratio=args.ratio, model_dir=args.model_dir, threads=args.threads, video2x_cache_folder=video2x_cache_folder) upscaler.run() upscaler.cleanup() elif os.path.isdir(args.input): """ Upscale videos in a folder/directory """ Avalon.info('Upscaling videos in folder/directory: {}'.format( args.input)) for input_video in [ f for f in os.listdir(args.input) if os.path.isfile(os.path.join(args.input, f)) ]:
class Video2xGui(): def __init__(self): self.running = False # create main window self.main_window = Tk() self.main_window.title(f'Video2X GUI {VERSION}') self.main_frame = Frame() self.main_frame.pack(fill=BOTH, expand=True) # add menu bar self.menu_bar = Menu(self.main_frame) # file menu self.file_menu = Menu(self.menu_bar, tearoff=0) self.file_menu.add_command(label='Exit', command=self.main_frame.quit) self.menu_bar.add_cascade(label='File', menu=self.file_menu) # help menu self.help_menu = Menu(self.menu_bar, tearoff=0) self.help_menu.add_command(label='About', command=self._display_help) self.menu_bar.add_cascade(label='Help', menu=self.help_menu) self.main_window.config(menu=self.menu_bar) # file frame self.file_frame = Frame(self.main_frame) self.file_frame.pack(fill=X, padx=5, pady=5, expand=True) # input file self.input_file = StringVar() label_text = StringVar() label_text.set('Input File') Label(self.file_frame, textvariable=label_text, relief=RIDGE, width=10).grid(row=0, column=0, padx=5, pady=5, sticky=W) Entry(self.file_frame, textvariable=self.input_file, width=60).grid(row=0, column=1, padx=5, pady=5, sticky=W) Button(self.file_frame, text='Select', command=self._select_input).grid(row=0, column=2, padx=5, pady=5, sticky=W) # output file self.output_file = StringVar() label_text = StringVar() label_text.set('Output File') Label(self.file_frame, textvariable=label_text, relief=RIDGE, width=10).grid(row=1, column=0, padx=5, pady=5, sticky=W) Entry(self.file_frame, textvariable=self.output_file, width=60).grid(row=1, column=1, padx=5, pady=5, sticky=W) Button(self.file_frame, text='Select', command=self._select_output).grid(row=1, column=2, padx=5, pady=5, sticky=W) # options self.options_frame = Frame() # self.options_left.pack(fill=X, padx=5, pady=5, expand=True) self.options_frame.pack(fill=X, padx=5, pady=5, expand=True) self.options_left = Frame(self.options_frame) # self.options_left.pack(fill=X, padx=5, pady=5, expand=True) self.options_left.grid(row=0, column=0, padx=5, pady=5, sticky=N) # width self.width = IntVar() # self.width.set(1920) Label(self.options_left, text='Width', relief=RIDGE, width=15).grid(row=0, column=0, padx=2, pady=3) width_field = Entry(self.options_left, textvariable=self.width) width_field.grid(row=0, column=1, padx=2, pady=3, sticky=W) # height self.height = IntVar() # self.height.set(1080) Label(self.options_left, text='Height', relief=RIDGE, width=15).grid(row=1, column=0, padx=2, pady=3) height_field = Entry(self.options_left, textvariable=self.height) height_field.grid(row=1, column=1, padx=2, pady=3, sticky=W) # scale ratio self.scale_ratio = DoubleVar() # self.scale_ratio.set(2.0) Label(self.options_left, text='Scale Ratio', relief=RIDGE, width=15).grid(row=2, column=0, padx=2, pady=3) scale_ratio_field = Entry(self.options_left, textvariable=self.scale_ratio) scale_ratio_field.grid(row=2, column=1, padx=2, pady=3, sticky=W) # image format self.image_format = StringVar(self.options_left) self.image_format.set('PNG') Label(self.options_left, text='Image Format', relief=RIDGE, width=15).grid(row=3, column=0, padx=2, pady=3) image_format_menu = OptionMenu(self.options_left, self.image_format, *IMAGE_FORMATS) image_format_menu.grid(row=3, column=1, padx=2, pady=3, sticky=W) # options self.options_right = Frame(self.options_frame) # self.options_left.pack(fill=X, padx=5, pady=5, expand=True) self.options_right.grid(row=0, column=1, padx=5, pady=5, sticky=N) # threads self.threads = IntVar() self.threads.set(1) Label(self.options_right, text='Threads', relief=RIDGE, width=15).grid(row=0, column=0, padx=2, pady=3) threads_field = Entry(self.options_right, textvariable=self.threads) threads_field.grid(row=0, column=1, padx=2, pady=3, sticky=W) # method self.method = StringVar(self.options_left) self.method.set('GPU') Label(self.options_right, text='Method', relief=RIDGE, width=15).grid(row=1, column=0, padx=2, pady=3) method_menu = OptionMenu(self.options_right, self.method, *AVAILABLE_METHODS) method_menu.grid(row=1, column=1, padx=2, pady=3, sticky=W) # driver self.driver = StringVar(self.options_left) self.driver.set('Waifu2X Caffe') Label(self.options_right, text='Driver', relief=RIDGE, width=15).grid(row=2, column=0, padx=2, pady=3) driver_menu = OptionMenu(self.options_right, self.driver, *AVAILABLE_DRIVERS) driver_menu.grid(row=2, column=1, padx=2, pady=3, sticky=W) # preserve frames self.preserve_frames = BooleanVar(self.options_left) self.preserve_frames.set(True) Label(self.options_right, text='Preserve Frames', relief=RIDGE, width=15).grid(row=3, column=0, padx=2, pady=3) preserve_frames_menu = OptionMenu(self.options_right, self.preserve_frames, *{True, False}) preserve_frames_menu.grid(row=3, column=1, padx=2, pady=3, sticky=W) # progress bar self.progress_bar_frame = Frame() self.progress_bar_frame.pack(fill=X, padx=5, pady=5, expand=True) self.progress_bar = ttk.Progressbar(self.progress_bar_frame, orient='horizontal', length=100, mode='determinate') self.progress_bar.pack(fill=X) # start button frame self.start_frame = Frame() self.start_frame.pack(fill=X, padx=5, pady=5, expand=True) # start button self.start_button_text = StringVar() self.start_button_text.set('Start') Button(self.start_frame, textvariable=self.start_button_text, command=self._launch_upscaling, width=20).pack(side=RIGHT) self.main_frame.mainloop() def _display_help(self): messagebox.showinfo('About', LEGAL_INFO) def _launch_upscaling(self): # prevent launching multiple instances if self.running: messagebox.showerror('Error', 'Video2X is already running') return # arguments sanity check if self.input_file.get() == '': messagebox.showerror( 'Error', 'You must specify input video file/directory path') return if self.output_file.get() == '': messagebox.showerror( 'Error', 'You must specify output video file/directory path') return if (self.driver.get() in [ 'Waifu2X Converter CPP', 'Waifu2x NCNN Vulkan', 'Anime4K' ]) and self.width.get() and self.height.get(): messagebox.showerror( 'Error', f'Selected driver \"{self.driver.get()}\" accepts only scaling ratio' ) return if self.driver.get() == 'waifu2x_ncnn_vulkan' and ( self.scale_ratio.get() > 2 or not self.scale_ratio.get().is_integer()): messagebox.showerror( 'Error', 'Scaling ratio must be 1 or 2 for waifu2x_ncnn_vulkan') return if (self.width.get() or self.height.get()) and self.scale_ratio.get(): messagebox.showerror( 'Error', 'You can only specify either scaling ratio or output width and height' ) return if (self.width.get() and not self.height.get()) or (not self.width.get() and self.height.get()): messagebox.showerror('Error', 'You must specify both width and height') return if (not self.width.get() or not self.height.get()) and not self.scale_ratio.get(): messagebox.showerror( 'Error', 'You must specify either output dimensions or scaling ratio') return upscale = threading.Thread(target=self._upscale) upscale.start() self.running = True self.start_button_text.set('Running') def _upscale(self): # start timer begin_time = time.time() # read configuration file config = read_config('video2x.json') config = absolutify_paths(config) input_file = pathlib.Path(self.input_file.get()) output_file = pathlib.Path(self.output_file.get()) driver = AVAILABLE_DRIVERS[self.driver.get()] if driver == 'waifu2x_caffe': waifu2x_settings = config['waifu2x_caffe'] if not pathlib.Path( waifu2x_settings['waifu2x_caffe_path']).is_file(): messagebox.showerror( 'Error', 'Specified waifu2x-caffe directory doesn\'t exist\nPlease check the configuration file settings' ) raise FileNotFoundError(waifu2x_settings['waifu2x_caffe_path']) elif driver == 'waifu2x_converter': waifu2x_settings = config['waifu2x_converter'] if not pathlib.Path( waifu2x_settings['waifu2x_converter_path']).is_dir(): messagebox.showerror( 'Error', 'Specified waifu2x-converter-cpp directory doesn\'t exist\nPlease check the configuration file settings' ) raise FileNotFoundError( waifu2x_settings['waifu2x_converter_path']) elif driver == 'waifu2x_ncnn_vulkan': waifu2x_settings = config['waifu2x_ncnn_vulkan'] if not pathlib.Path( waifu2x_settings['waifu2x_ncnn_vulkan_path']).is_file(): messagebox.showerror( 'Error', 'Specified waifu2x_ncnn_vulkan directory doesn\'t exist\nPlease check the configuration file settings' ) raise FileNotFoundError( waifu2x_settings['waifu2x_ncnn_vulkan_path']) elif driver == 'anime4k': waifu2x_settings = config['anime4k'] if not pathlib.Path(waifu2x_settings['anime4k_path']).is_file(): messagebox.showerror( 'Error', 'Specified Anime4K directory doesn\'t exist\nPlease check the configuration file settings' ) raise FileNotFoundError(waifu2x_settings['anime4k_path']) # read FFmpeg configuration ffmpeg_settings = config['ffmpeg'] # load video2x settings image_format = config['video2x']['image_format'].lower() preserve_frames = config['video2x']['preserve_frames'] # load cache directory if isinstance(config['video2x']['video2x_cache_directory'], str): video2x_cache_directory = pathlib.Path( config['video2x']['video2x_cache_directory']) else: video2x_cache_directory = pathlib.Path( tempfile.gettempdir()) / 'video2x' if video2x_cache_directory.exists( ) and not video2x_cache_directory.is_dir(): messagebox.showerror('Error', 'Specified cache directory is a file/link') raise FileExistsError('Specified cache directory is a file/link') elif not video2x_cache_directory.exists(): # try creating the cache directory if messagebox.askyesno( 'Question', f'Specified cache directory {video2x_cache_directory} does not exist\nCreate directory?' ): try: video2x_cache_directory.mkdir(parents=True, exist_ok=True) # there can be a number of exceptions here # PermissionError, FileExistsError, etc. # therefore, we put a catch-them-all here except Exception as e: messagebox.showerror( 'Error', f'Unable to create {video2x_cache_directory}\nAborting...' ) raise e else: raise FileNotFoundError('Could not create cache directory') # load more settings from gui width = self.width.get() height = self.height.get() scale_ratio = self.scale_ratio.get() image_format = self.image_format.get() threads = self.threads.get() method = AVAILABLE_METHODS[self.method.get()] preserve_frames = self.preserve_frames.get() self.upscaler = Upscaler(input_video=input_file, output_video=output_file, method=method, waifu2x_settings=waifu2x_settings, ffmpeg_settings=ffmpeg_settings) # set optional options self.upscaler.waifu2x_driver = driver self.upscaler.scale_width = width self.upscaler.scale_height = height self.upscaler.scale_ratio = scale_ratio self.upscaler.model_dir = None self.upscaler.threads = threads self.upscaler.video2x_cache_directory = video2x_cache_directory self.upscaler.image_format = image_format self.upscaler.preserve_frames = preserve_frames # run upscaler self.upscaler.create_temp_directories() # start progress bar progress_bar = threading.Thread(target=self._progress_bar) progress_bar.start() # start upscaling self.upscaler.run() self.upscaler.cleanup_temp_directories() # show message when upscaling completes messagebox.showinfo( 'Info', f'Upscaling Completed\nTime Taken: {round((time.time() - begin_time), 5)} seconds' ) self.progress_bar['value'] = 100 self.running = False self.start_button_text.set('Start') def _progress_bar(self): """ This method prints a progress bar This method prints a progress bar by keeping track of the amount of frames in the input directory and the output directory. This is originally suggested by @ArmandBernard. """ # initialize variables early self.upscaler.progress_bar_exit_signal = False self.upscaler.total_frames_upscaled = 0 self.upscaler.total_frames = 1 # initialize progress bar values self.progress_bar['value'] = 0 while not self.upscaler.progress_bar_exit_signal: self.progress_bar['value'] = int( 100 * self.upscaler.total_frames_upscaled / self.upscaler.total_frames) time.sleep(1) def _select_input(self): self.input_file.set(askopenfilename(title='Select Input File')) # try to set an output file name automatically output_file = pathlib.Path(f'{self.input_file.get()}_output.mp4') output_file_id = 0 while output_file.is_file() and output_file_id <= 10: output_file = pathlib.Path( f'{self.input_file.get()}_output_{output_file_id}.mp4') output_file_id += 1 if not output_file.exists(): self.output_file.set(str(output_file)) def _select_output(self): self.output_file.set(asksaveasfilename(title='Select Output File'))
def _upscale(self): # start timer begin_time = time.time() # read configuration file config = read_config('video2x.json') config = absolutify_paths(config) input_file = pathlib.Path(self.input_file.get()) output_file = pathlib.Path(self.output_file.get()) driver = AVAILABLE_DRIVERS[self.driver.get()] if driver == 'waifu2x_caffe': waifu2x_settings = config['waifu2x_caffe'] if not pathlib.Path( waifu2x_settings['waifu2x_caffe_path']).is_file(): messagebox.showerror( 'Error', 'Specified waifu2x-caffe directory doesn\'t exist\nPlease check the configuration file settings' ) raise FileNotFoundError(waifu2x_settings['waifu2x_caffe_path']) elif driver == 'waifu2x_converter': waifu2x_settings = config['waifu2x_converter'] if not pathlib.Path( waifu2x_settings['waifu2x_converter_path']).is_dir(): messagebox.showerror( 'Error', 'Specified waifu2x-converter-cpp directory doesn\'t exist\nPlease check the configuration file settings' ) raise FileNotFoundError( waifu2x_settings['waifu2x_converter_path']) elif driver == 'waifu2x_ncnn_vulkan': waifu2x_settings = config['waifu2x_ncnn_vulkan'] if not pathlib.Path( waifu2x_settings['waifu2x_ncnn_vulkan_path']).is_file(): messagebox.showerror( 'Error', 'Specified waifu2x_ncnn_vulkan directory doesn\'t exist\nPlease check the configuration file settings' ) raise FileNotFoundError( waifu2x_settings['waifu2x_ncnn_vulkan_path']) elif driver == 'anime4k': waifu2x_settings = config['anime4k'] if not pathlib.Path(waifu2x_settings['anime4k_path']).is_file(): messagebox.showerror( 'Error', 'Specified Anime4K directory doesn\'t exist\nPlease check the configuration file settings' ) raise FileNotFoundError(waifu2x_settings['anime4k_path']) # read FFmpeg configuration ffmpeg_settings = config['ffmpeg'] # load video2x settings image_format = config['video2x']['image_format'].lower() preserve_frames = config['video2x']['preserve_frames'] # load cache directory if isinstance(config['video2x']['video2x_cache_directory'], str): video2x_cache_directory = pathlib.Path( config['video2x']['video2x_cache_directory']) else: video2x_cache_directory = pathlib.Path( tempfile.gettempdir()) / 'video2x' if video2x_cache_directory.exists( ) and not video2x_cache_directory.is_dir(): messagebox.showerror('Error', 'Specified cache directory is a file/link') raise FileExistsError('Specified cache directory is a file/link') elif not video2x_cache_directory.exists(): # try creating the cache directory if messagebox.askyesno( 'Question', f'Specified cache directory {video2x_cache_directory} does not exist\nCreate directory?' ): try: video2x_cache_directory.mkdir(parents=True, exist_ok=True) # there can be a number of exceptions here # PermissionError, FileExistsError, etc. # therefore, we put a catch-them-all here except Exception as e: messagebox.showerror( 'Error', f'Unable to create {video2x_cache_directory}\nAborting...' ) raise e else: raise FileNotFoundError('Could not create cache directory') # load more settings from gui width = self.width.get() height = self.height.get() scale_ratio = self.scale_ratio.get() image_format = self.image_format.get() threads = self.threads.get() method = AVAILABLE_METHODS[self.method.get()] preserve_frames = self.preserve_frames.get() self.upscaler = Upscaler(input_video=input_file, output_video=output_file, method=method, waifu2x_settings=waifu2x_settings, ffmpeg_settings=ffmpeg_settings) # set optional options self.upscaler.waifu2x_driver = driver self.upscaler.scale_width = width self.upscaler.scale_height = height self.upscaler.scale_ratio = scale_ratio self.upscaler.model_dir = None self.upscaler.threads = threads self.upscaler.video2x_cache_directory = video2x_cache_directory self.upscaler.image_format = image_format self.upscaler.preserve_frames = preserve_frames # run upscaler self.upscaler.create_temp_directories() # start progress bar progress_bar = threading.Thread(target=self._progress_bar) progress_bar.start() # start upscaling self.upscaler.run() self.upscaler.cleanup_temp_directories() # show message when upscaling completes messagebox.showinfo( 'Info', f'Upscaling Completed\nTime Taken: {round((time.time() - begin_time), 5)} seconds' ) self.progress_bar['value'] = 100 self.running = False self.start_button_text.set('Start')
# Start execution try: # Start timer begin_time = time.time() if os.path.isfile(args.input): """ Upscale single video file """ Avalon.info('Upscaling single video file: {}'.format(args.input)) upscaler = Upscaler(input_video=args.input, output_video=args.output, method=args.method, waifu2x_path=waifu2x_path, ffmpeg_path=ffmpeg_path, waifu2x_driver=args.driver, ffmpeg_arguments=ffmpeg_arguments, ffmpeg_hwaccel=ffmpeg_hwaccel, output_width=args.width, output_height=args.height, ratio=args.ratio, model_type=args.model_type, threads=args.threads, extracted_frames=extracted_frames, upscaled_frames=upscaled_frames) upscaler.run() elif os.path.isdir(args.input): """ Upscale videos in a folder/directory """ Avalon.info('Upscaling videos in folder: {}'.format(args.input)) for input_video in [ f for f in os.listdir(args.input) if os.path.isfile(os.path.join(args.input, f)) ]:
# Start execution try: # Start timer begin_time = time.time() if os.path.isfile(args.input): """ Upscale single video file """ Avalon.info('Upscaling single video file: {}'.format(args.input)) upscaler = Upscaler(input_video=args.input, output_video=args.output, method=args.method, waifu2x_path=waifu2x_path, ffmpeg_path=ffmpeg_path, waifu2x_driver=args.driver, ffmpeg_arguments=ffmpeg_arguments, ffmpeg_hwaccel=ffmpeg_hwaccel, output_width=args.width, output_height=args.height, ratio=args.ratio, model_type=args.model_type, threads=args.threads, video2x_cache_folder=video2x_cache_folder) upscaler.run() upscaler.cleanup() elif os.path.isdir(args.input): """ Upscale videos in a folder/directory """ Avalon.info('Upscaling videos in folder/directory: {}'.format( args.input)) for input_video in [ f for f in os.listdir(args.input) if os.path.isfile(os.path.join(args.input, f))
# upscale single video file Avalon.info( _('Upscaling single video file: {}').format(video2x_args.input)) # check for input output format mismatch if video2x_args.output.is_dir(): Avalon.error(_('Input and output path type mismatch')) Avalon.error(_('Input is single file but output is directory')) raise Exception('input output path type mismatch') if not re.search(r'.*\..*$', str(video2x_args.output)): Avalon.error(_('No suffix found in output file path')) Avalon.error(_('Suffix must be specified for FFmpeg')) raise Exception('No suffix specified') upscaler = Upscaler(input_video=video2x_args.input, output_video=video2x_args.output, driver_settings=driver_settings, ffmpeg_settings=ffmpeg_settings) # set optional options upscaler.driver = video2x_args.driver upscaler.scale_width = video2x_args.width upscaler.scale_height = video2x_args.height upscaler.scale_ratio = video2x_args.ratio upscaler.processes = video2x_args.processes upscaler.video2x_cache_directory = video2x_cache_directory upscaler.image_format = image_format upscaler.preserve_frames = preserve_frames # run upscaler upscaler.run()