def _pre_process(self): """ Creates self.child_request.input_file file by re-encoding self._service_request.input_file. Without this re-encode, dandere2x isn't guaranteed to function correctly. """ # Checks to see the video needs to be resized in order to conform to the block size. Applies the "DAR" # ffmpeg filter to 'pipe_video' in 'output_options.yaml' if the video was resized. resized_output_options = Dandere2xServiceInterface._check_and_fix_resolution( input_file=self._service_request.input_file, block_size=self._service_request.block_size, output_options_original=self._service_request.output_options) ffprobe_path = load_executable_paths_yaml()['ffprobe'] ffmpeg_path = load_executable_paths_yaml()['ffmpeg'] # Re-encode the sent service_request into the child's input file, so that the child_request will operate on # "pre_processed.mkv", rather than self._service_request.input_file, which may not be a valid video file to # operate on. re_encode_video(ffmpeg_dir=ffmpeg_path, ffprobe_dir=ffprobe_path, output_options=resized_output_options, input_file=self._service_request.input_file, output_file=self.child_request.input_file) self.dandere2x_service = Dandere2xServiceThread( service_request=self.child_request)
def _check_and_fix_resolution(input_file: str, block_size: int, output_options_original: dict) -> dict: """ Returns a dictionary containing the output settings, taking into consideration if the video needs to be resized, and if it does, changes the pipe_video commands to include dar. """ from dandere2x.dandere2xlib.utils.yaml_utils import load_executable_paths_yaml from dandere2x.dandere2xlib.wrappers.ffmpeg.ffmpeg import append_resize_filter_to_pre_process, \ append_dar_filter_to_pipe_process from dandere2x.dandere2xlib.wrappers.ffmpeg.videosettings import VideoSettings import copy def valid_input_resolution(width: int, height: int, block_size: int): return width % block_size == 0 and height % block_size == 0 new_output_options = copy.copy(output_options_original) # get meta-data from the video to do pre-processing ffprobe_path = load_executable_paths_yaml()['ffprobe'] ffmpeg_path = load_executable_paths_yaml()['ffmpeg'] video_settings = VideoSettings(ffprobe_path, ffmpeg_path, input_file) width, height = video_settings.width, video_settings.height if not valid_input_resolution( width=width, height=height, block_size=block_size): print("appending resize filter") append_resize_filter_to_pre_process(output_options=new_output_options, width=width, height=height, block_size=block_size) append_dar_filter_to_pipe_process(output_options=new_output_options, width=width, height=height) return new_output_options
def _pre_process(self): ffprobe_path = load_executable_paths_yaml()['ffprobe'] ffmpeg_path = load_executable_paths_yaml()['ffmpeg'] # Attempt to split the video up into N=3 distinct parts. divide_and_reencode_video( ffmpeg_path=ffmpeg_path, ffprobe_path=ffprobe_path, input_video=self._service_request.input_file, output_options=self._service_request.output_options, divide=3, output_dir=self._service_request.workspace) # Find all the split video files ffmpeg produced in the folder. divided_re_encoded_videos = glob.glob( os.path.join(self._service_request.workspace, "*.mkv")) # Create unique child_requests for each unique video, with the video being the input. for x in range(0, len(divided_re_encoded_videos)): child_request = copy.deepcopy(self._service_request) child_request.input_file = os.path.join( divided_re_encoded_videos[x]) child_request.output_file = os.path.join( self._service_request.workspace, "non_migrated%d.mkv" % x) child_request.workspace = os.path.join( self._service_request.workspace, "subworkspace%d" % x) self._divided_videos_upscaled.append(child_request.output_file) self._child_threads.append(Dandere2xServiceThread(child_request))
def _setup_pipe(self) -> None: self.log.info("Setting up pipe Called") # load variables.. output_no_sound = self.output_no_sound frame_rate = str(self.context.frame_rate) output_no_sound = output_no_sound ffmpeg_dir = load_executable_paths_yaml()['ffmpeg'] dar = self.context.video_settings.dar # constructing the pipe command... ffmpeg_pipe_command = [ffmpeg_dir, "-r", frame_rate] options = get_options_from_section( self.context.service_request.output_options["ffmpeg"]["pipe_video"] ['output_options'], ffmpeg_command=True) for item in options: ffmpeg_pipe_command.append(item) ffmpeg_pipe_command.append("-r") ffmpeg_pipe_command.append(frame_rate) ffmpeg_pipe_command.append(output_no_sound) # Starting the Pipe Command console_output = open( self.context.console_output_dir + "pipe_output.txt", "w") console_output.write(str(ffmpeg_pipe_command)) self.log.info("ffmpeg_pipe_command %s" % str(ffmpeg_pipe_command)) self.ffmpeg_pipe_subprocess = subprocess.Popen(ffmpeg_pipe_command, stdin=subprocess.PIPE, stdout=console_output)
def __init__(self, extracted_frames_dir: str, noised_frames_dir: str, frame_count): super().__init__() self.extracted_frames_dir = extracted_frames_dir self.noised_frames_dir = noised_frames_dir self.ffmpeg_path = load_executable_paths_yaml()['ffmpeg'] self.frame_count = frame_count
def _on_completion(self): """ Finishes the video up by migrating the audio tracks from the child's output file with the original input file. """ ffmpeg_path = load_executable_paths_yaml()['ffmpeg'] migrate_tracks_contextless( ffmpeg_dir=ffmpeg_path, no_audio=self.child_request.output_file, file_dir=self._service_request.input_file, output_file=self._service_request.output_file)
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 __init__(self, input_video: str, extracted_frames_dir: str, compressed_frames_dir: str, compressed_quality: int, block_size: int, output_options_original: dict): ffprobe_path = load_executable_paths_yaml()['ffprobe'] ffmpeg_path = load_executable_paths_yaml()['ffmpeg'] self.input_video = input_video self.extracted_frames_dir = extracted_frames_dir self.compressed_frames_dir = compressed_frames_dir self.compressed_quality = compressed_quality width, height = get_width_height(ffprobe_dir=ffprobe_path, input_video=input_video) self.cap = VideoFrameExtractor(Path(ffmpeg_path), Path(input_video), width, height, block_size, output_options_original) self.ffmpeg_path = load_executable_paths_yaml()['ffmpeg'] self.count = 1
def __init__(self, service_request: Dandere2xServiceRequest): """ Uses multiple Dandere2xServiceThread to upscale a given file. It does this by attempting to split the video up into equal parts, then migrating each upscaled-split video into one complete video file. """ super().__init__(service_request=copy.deepcopy(service_request)) assert is_file_video(ffprobe_dir=load_executable_paths_yaml()['ffprobe'], input_video=self._service_request.input_file),\ "%s is not a video file!" % self._service_request.input_file self._child_threads: List[Dandere2xServiceThread] = [] self._divided_videos_upscaled: List[str] = []
def _setup_pipe(self) -> None: self.log.info("Setting up pipe Called") # load variables.. output_no_sound = self.output_no_sound frame_rate = str(self.context.frame_rate) output_no_sound = output_no_sound ffmpeg_dir = load_executable_paths_yaml()['ffmpeg'] dar = self.context.video_settings.dar # constructing the pipe command... ffmpeg_pipe_command = [ffmpeg_dir] # walrus operator go brrrr if (hw_accel := self.context.service_request.output_options["ffmpeg"]["pipe_video"]["-hwaccel"]) is not None: ffmpeg_pipe_command.append("-hwaccel") ffmpeg_pipe_command.append(hw_accel)
def __init__(self, input_video: str, extracted_frames_dir: str, compressed_frames_dir: str, compressed_quality: int): self.input_video = input_video self.extracted_frames_dir = extracted_frames_dir self.compressed_frames_dir = compressed_frames_dir self.compressed_quality = compressed_quality self.cap = cv2.VideoCapture(self.input_video) self.ffmpeg_path = load_executable_paths_yaml()['ffmpeg'] self.count = 1
def __init__(self, context: Dandere2xServiceContext, controller: Dandere2xController): threading.Thread.__init__(self, name="Dandere2xCpp") self.context = context self.controller = controller self.dandere2x_cpp_subprocess = None self.log = logging.getLogger() dandere2x_cpp_dir = load_executable_paths_yaml()['dandere2x_cpp'] self.exec_command = [ dandere2x_cpp_dir, self.context.service_request.workspace, str(self.context.frame_count), str(self.context.service_request.block_size), str(self.context.step_size), "r", str(1), ".jpg" ]
def _on_completion(self): """ Converts all self._divided_videos_upscaled into one big video, then migrates the original audio into this service request's output file. """ ffmpeg_path = load_executable_paths_yaml()['ffmpeg'] no_audio = os.path.join(self._service_request.workspace, "noaudio.mkv") concat_n_videos(ffmpeg_dir=ffmpeg_path, temp_file_dir=self._service_request.workspace, console_output_dir=self._service_request.workspace, list_of_files=self._divided_videos_upscaled, output_file=no_audio) migrate_tracks_contextless( ffmpeg_dir=ffmpeg_path, no_audio=no_audio, file_dir=self._service_request.input_file, output_file=self._service_request.output_file)
def __init__(self, context: Dandere2xServiceContext, controller: Dandere2xController): threading.Thread.__init__(self, name="Dandere2xCpp") self.context = context self.controller = controller self.dandere2x_cpp_subprocess = None self.log = logging.getLogger() dandere2x_cpp_dir = load_executable_paths_yaml()['dandere2x_cpp'] self.exec_command = [ dandere2x_cpp_dir, self.context.service_request.workspace, str(self.context.frame_count), str(self.context.service_request.block_size), self.context.dandere2x_cpp_block_matching_arg, self.context.dandere2x_cpp_evaluator_arg, str(self.context.service_request.quality_minimum), str(self.context.bleed) ]
def __init__(self, service_request: Dandere2xServiceRequest): """ Uses a single Dandere2xServiceThread object to upscale a video file. Args: service_request: Dandere2xServiceRequest object. """ super().__init__(service_request=copy.deepcopy(service_request)) assert is_file_video(ffprobe_dir=load_executable_paths_yaml()['ffprobe'], input_video=self._service_request.input_file),\ "%s is not a video file!" % self._service_request.input_file self.child_request = copy.deepcopy(service_request) self.child_request.input_file = os.path.join(service_request.workspace, "pre_processed.mkv") self.child_request.output_file = os.path.join( service_request.workspace, "non_migrated.mkv") self.child_request.workspace = os.path.join(service_request.workspace, "subworkspace") self.dandere2x_service = None
from dandere2x.dandere2xlib.utils.yaml_utils import load_executable_paths_yaml from dandere2x.dandere2xlib.wrappers.ffmpeg.ffmpeg import apply_noise_to_image ffmpeg_path = load_executable_paths_yaml()['ffmpeg'] import time start = time.time() apply_noise_to_image( ffmpeg_dir=ffmpeg_path, input_image=r"C:\Users\Tyler\Desktop\3.3\workspace\ffmpeg_test\output1.jpg", output_file= r"C:\Users\Tyler\Desktop\3.3\workspace\ffmpeg_test\output_noise_python.jpg" ) end = time.time() print(end - start)
def __init__(self, service_request: Dandere2xServiceRequest): """ Creates struct-like object that serves as a set of constants and directories dandere2x will use. Once this is instantiated, it's to be treated as 'effectively final' meaning that none of the variables will change after they're declared. Most dandere2x-core functions will require a Dandere2xServiceContext object in order for it to run. Args: service_request: A service_request, which may be produced by the program or the user. """ self.service_request = service_request # Directories and Paths self.input_frames_dir = os.path.join(service_request.workspace, "inputs") + os.path.sep self.noised_input_frames_dir = os.path.join( service_request.workspace, "noised_inputs") + os.path.sep self.residual_images_dir = os.path.join( service_request.workspace, "residual_images") + os.path.sep self.residual_upscaled_dir = os.path.join( service_request.workspace, "residual_upscaled") + os.path.sep self.residual_data_dir = os.path.join(service_request.workspace, "residual_data") + os.path.sep self.pframe_data_dir = os.path.join(service_request.workspace, "pframe_data") + os.path.sep self.merged_dir = os.path.join(service_request.workspace, "merged") + os.path.sep self.fade_data_dir = os.path.join(service_request.workspace, "fade_data") + os.path.sep self.debug_dir = os.path.join(service_request.workspace, "debug") + os.path.sep self.console_output_dir = os.path.join(service_request.workspace, "console_output") + os.path.sep self.compressed_static_dir = os.path.join( service_request.workspace, "compressed_static") + os.path.sep self.encoded_dir = os.path.join(service_request.workspace, "encoded") + os.path.sep self.temp_image_folder = os.path.join( service_request.workspace, "temp_image_folder") + os.path.sep self.log_dir = os.path.join(service_request.workspace, "log_dir") + os.path.sep self.directories = { self.input_frames_dir, self.noised_input_frames_dir, self.residual_images_dir, self.residual_upscaled_dir, self.merged_dir, self.residual_data_dir, self.pframe_data_dir, self.debug_dir, self.console_output_dir, self.compressed_static_dir, self.fade_data_dir, self.encoded_dir, self.temp_image_folder, self.log_dir } ffprobe_path = load_executable_paths_yaml()['ffprobe'] ffmpeg_path = load_executable_paths_yaml()['ffmpeg'] video_settings = VideoSettings( ffprobe_dir=ffprobe_path, ffmpeg_dir=ffmpeg_path, video_file=self.service_request.input_file) self.video_settings = video_settings self.width, self.height = video_settings.width, video_settings.height self.frame_count = video_settings.frame_count self.frame_rate = video_settings.frame_rate # todo static-ish settings < add to a yaml somewhere > self.bleed = self.service_request.output_options["dandere2x"]["bleed"] self.temp_image = self.temp_image_folder + "tempimage.jpg" self.debug = False self.step_size = 4 self.max_frames_ahead = 100 # Dandere2xCPP self.dandere2x_cpp_block_matching_arg = self.service_request.output_options[ "dandere2x_cpp"]["block_matching_arg"] self.dandere2x_cpp_evaluator_arg = self.service_request.output_options[ "dandere2x_cpp"]["evaluator_arg"]