def load_executable_paths_yaml() -> dict: """ Load the dandere2x_directories yaml file, but replace all the relative path definitions with absolute definitions. """ from os import path import logging from pathlib import Path import sys from dandere2x.dandere2xlib.utils.dandere2x_utils import get_operating_system logger = logging.getLogger() # For some reason, detecting if python is frozen or not isn't working on pyinstaller (on my machine, at least). # This will cycle through the two options, if we're running as a python script, or if we're running as an # executable, and return whatever one works. I wish the frozen thing worked on my system potential_main_paths = [os.path.dirname(os.path.abspath(sys.executable)), Path(path.abspath(sys.modules['__main__'].__file__)).parent] # This is acquired technical debt / my pyinstaller refuses to work by simply checking if it's frozen. for potential in potential_main_paths: # get location of dandere2x directories (will be in the same folder as main) configfile = "executable_paths.yaml" main_path = potential config_path = Path(path.join(main_path, "config_files")) directory_file = os.path.join(config_path, configfile) try: # load yaml with open(directory_file, "r") as read_file: config = yaml.safe_load(read_file) logger.info(f"Main path {potential} loaded {configfile} successfully. ") break except: logger.info(f"main_path option {potential} did not work, trying the next main_path option") # replace each relative path with it's absolute counter-part (if applicable) for key in config: # use system binaries if on linux for ffmpeg / ffprobe if key == "ffmpeg" and get_operating_system() == "linux": config[key] = "ffmpeg" continue if key == "ffprobe" and get_operating_system() == "linux": config[key] = "ffprobe" continue if get_operating_system() == "win32": """ Modifications needed to take place if we're not unix-based """ config[key] = config[key].replace("/", "\\") config[key] = config[key] + ".exe" if not os.path.isabs(config[key]): config[key] = os.path.join(main_path, config[key]) return config
def convert_gif_to_video(ffmpeg_dir: str, input_path: str, output_path: str, output_options=None) -> None: assert get_operating_system() != "win32" or os.path.exists(ffmpeg_dir), \ "%s does not exist" % ffmpeg_dir execute = [ ffmpeg_dir, "-i", input_path, ] options = get_options_from_section( output_options["ffmpeg"]['convert_video_to_gif']['output_options'], ffmpeg_command=True) for item in options: execute.append(item) execute.append(output_path) print(execute) process = subprocess.Popen(execute, stdout=open(os.devnull, 'w'), stderr=subprocess.PIPE, stdin=subprocess.PIPE, shell=False) stdout, stderr = process.communicate()
def get_aspect_ratio(ffprobe_dir, input_video): """ Gets input video information This method reads input video information using ffprobe in dictionary. Arguments: input_video {string} -- input video file path Returns: dictionary -- JSON text of input video information """ assert get_operating_system() != "win32" or os.path.exists( ffprobe_dir), "%s does not exist!" % ffprobe_dir # this execution command needs to be hard-coded # since video2x only strictly recignizes this one format execute = [ ffprobe_dir, '-v', 'panic', '-select_streams', 'v:0', '-show_entries', 'stream=display_aspect_ratio', '-of', 'csv=p=0', input_video ] return_bytes = subprocess.run(execute, check=True, stdout=subprocess.PIPE).stdout return_string = return_bytes.decode("utf-8") if "N/A" in return_string: return None return return_string
def get_video_info(ffprobe_dir, input_video): """ Gets input video information This method reads input video information using ffprobe in dictionary. Arguments: input_video {string} -- input video file path Returns: dictionary -- JSON text of input video information """ assert get_operating_system() != "win32" or os.path.exists( ffprobe_dir), "%s does not exist!" % ffprobe_dir # this execution command needs to be hard-coded # since video2x only strictly recignizes this one format execute = [ ffprobe_dir, '-v', 'panic', '-print_format', 'json', '-show_format', '-show_streams', '-i', input_video ] log = logging.getLogger() log.info("Loading video meta-data with ffprobe.. this might take a while.") log.info("Command: %s" % str(execute)) json_str = subprocess.run(execute, check=True, stdout=subprocess.PIPE).stdout return json.loads(json_str.decode('utf-8'))
def parse_gui_inputs(self): # f**k windows and it's file management system if get_operating_system() == 'win32': self.output_file = self.output_file.replace("/", "\\") self.input_file = self.input_file.replace("/", "\\") # Scale Factors if self.ui.scale_1_radio_button.isChecked(): self.scale_factor = 1 if self.ui.scale_2_radio_button.isChecked(): self.scale_factor = 2 if self.ui.scale_3_radio_button.isChecked(): self.scale_factor = 3 if self.ui.scale_4_radio_button.isChecked(): self.scale_factor = 4 # Noise factors if self.ui.noise_0_radio_button.isChecked(): self.noise_level = 0 if self.ui.noise_1_radio_button.isChecked(): self.noise_level = 1 if self.ui.noise_2_radio_button.isChecked(): self.noise_level = 2 if self.ui.noise_3_radio_button.isChecked(): self.noise_level = 3 # Dandere2x Settings self.image_quality = int(self.ui.image_quality_box.currentText()) self.block_size = int(self.ui.block_size_combo_box.currentText()) self.config_file = self.ui.config_select_box.currentText() print("config file: " + self.config_file) # Waifu2x Type if self.ui.waifu2x_type_combo_box.currentText() == 'Waifu2x-Caffe': self.waifu2x_type = 'caffe' if self.ui.waifu2x_type_combo_box.currentText() == 'Waifu2x-Vulkan': self.waifu2x_type = 'vulkan' if self.ui.waifu2x_type_combo_box.currentText() == 'RealSR': self.waifu2x_type = 'realsr_ncnn_vulkan' if self.ui.waifu2x_type_combo_box.currentText( ) == 'Waifu2x-Converter-Cpp': self.waifu2x_type = "converter_cpp"
def __init__(self): super().__init__() config_names = [] os.chdir(os.getcwd()) for file in glob.glob("*.yaml"): config_names.append(file) self.ui = Ui_Dandere2xGUI() self.ui.setupUi(self) _translate = QtCore.QCoreApplication.translate self.ui.config_select_box.setCurrentText( _translate("Dandere2xGUI", "Waifu2x-Caffe")) # load 'this folder' in a pyinstaller friendly way self.this_folder = os.getcwd() # Note: At the moment running d2x from venv on windows 10 is having issues with this # segment of code. I've left it commented for the time being since I'm unsure if pyinstaller # requires this part, but it may be removed all together once tested properly. # # if getattr(sys, 'frozen', False): # self.this_folder = os.path.dirname(sys.executable) + os.path.sep # elif __file__: # self.this_folder = os.path.dirname(__file__) + os.path.sep # lazy hack_around for linux build (im not sure why the previous statement doesnt work on venv linux) if get_operating_system() == "linux": self.this_folder = os.getcwd() self.input_file = '' self.output_file = '' self.config_file = '' self.scale_factor = None self.noise_level = None self.image_quality = None self.block_size = '' self.waifu2x_type = '' self.use_default_name = True # theres a bug with qt designer and '80' for default quality needs to be set elsewhere _translate = QtCore.QCoreApplication.translate self.ui.image_quality_box.setCurrentText( _translate("Dandere2xGUI", "98")) self.ui.block_size_combo_box.setCurrentText( _translate("Dandere2xGUI", "20")) self.ui.waifu2x_type_combo_box.setCurrentText( _translate("Dandere2xGUI", "Waifu2x-Vulkan")) # self.ui.video_icon.setPixmap(QtGui.QPixmap("assets\\aka.png")) self.config_buttons() self.refresh_scale_factor() self.show()
def __init__(self, context: Dandere2xServiceContext, controller: Dandere2xController): # implementation specific self.active_waifu2x_subprocess = None self.waifu2x_caffe_path = load_executable_paths_yaml()['waifu2x_caffe'] assert get_operating_system() != "win32" or os.path.exists(self.waifu2x_caffe_path), \ "%s does not exist!" % self.waifu2x_caffe_path super().__init__(context, controller) Thread.__init__(self, name="Waifu2x Thread")
def load_executable_paths_yaml() -> dict: """ Load the dandere2x_directories yaml file, but replace all the relative path definitions with absolute definitions. """ from os import path from pathlib import Path import sys from dandere2x.dandere2xlib.utils.dandere2x_utils import get_operating_system # get location of dandere2x directories (will be in the same folder as main) configfile = "executable_paths.yaml" main_path = Path(path.abspath(sys.modules['__main__'].__file__)).parent config_path = Path(path.join(main_path, "config_files")) directory_file = os.path.join(config_path, configfile) # load yaml with open(directory_file, "r") as read_file: config = yaml.safe_load(read_file) # replace each relative path with it's absolute counter-part (if applicable) for key in config: # use system binaries if on linux for ffmpeg / ffprobe if key == "ffmpeg" and get_operating_system() == "linux": config[key] = "ffmpeg" continue if key == "ffprobe" and get_operating_system() == "linux": config[key] = "ffprobe" continue if get_operating_system() == "win32": """ Modifications needed to take place if we're not unix-based """ config[key] = config[key].replace("/", "\\") config[key] = config[key] + ".exe" if not os.path.isabs(config[key]): config[key] = os.path.join(main_path, config[key]) return config
def is_file_video(ffprobe_dir: str, input_video: str): assert get_operating_system() != "win32" or os.path.exists( ffprobe_dir), "%s does not exist!" % ffprobe_dir execute = [ffprobe_dir, "-i", input_video, "-v", "quiet"] return_bytes = subprocess.run(execute, check=True, stdout=subprocess.PIPE).stdout if "Invalid data found when processing input" in return_bytes.decode( "utf-8"): return False return True
def get_frame_count(ffprobe_dir, input_video): assert get_operating_system() != "win32" or os.path.exists( ffprobe_dir), "%s does not exist!" % ffprobe_dir # this execution command needs to be hard-coded # since video2x only strictly recignizes this one format execute = [ ffprobe_dir, '-v', 'panic', '-count_frames', '-select_streams', 'v:0', '-show_entries', 'stream=nb_read_frames ', '-of', 'csv=p=0', input_video ] return_bytes = subprocess.run(execute, check=True, stdout=subprocess.PIPE).stdout return_string = return_bytes.decode("utf-8") return return_string
def get_frame_count_ffmpeg(ffmpeg_dir: str, input_video: str): assert get_operating_system() != "win32" or os.path.exists( ffmpeg_dir), "%s does not exist!" % ffmpeg_dir execute = [ ffmpeg_dir, "-vsync", str(1), "-i", input_video, "-c", "copy", "-f", "null", "-" ] process = subprocess.run(execute, capture_output=True) stdout_as_str = process.stderr.decode("utf-8") regex = re.compile("frame=.{0,3}[0-9]{1,10}") matched_regex = regex.findall(stdout_as_str) assert matched_regex matched_regex = matched_regex[0] frame_count = re.compile("\d{1,10}").findall(matched_regex)[0] return int(frame_count)
sys.stdout.write('\r') sys.stdout.write(intro_paragraph) time.sleep(1) print("\n") print( "-----------------------------------------------------------------------------------------------------------------------------") print( "This program will attempt to fix your video by manually completing the dandere2x process, what it should of done at 99%.") print( "I've been unable to replicate this bug on any of my window's versions (i've gone through 3 different versions of windows over the past year).") print("What we're going to do is manually try to migrate the audio tracks using what I know (I being the developer)") print("Be sure to be run this program as administrator by the way. ") print( "----------------------------------------------------------------------------------------------------------------------------") dandere2x_config_file = "dandere2x_%s.yaml" % get_operating_system() print(" > Attempting to read %s" % dandere2x_config_file) config = None try: with open(dandere2x_config_file, "r") as read_file: config = yaml.safe_load(read_file) print("File read!") except: print("Couldn't open %s, exiting" % dandere2x_config_file) exit(1) print(" > Attempting to load context / dandere2x with this file...") import logging