def trim_video(context: Context, output_file: str): # load context input_file = context.input_file trim_video_command = [ context.ffmpeg_dir, "-hwaccel", context.hwaccel, "-i", input_file ] trim_video_time = get_options_from_section( context.config_json["ffmpeg"]["trim_video"]["time"]) for element in trim_video_time: trim_video_command.append(element) trim_video_options = \ get_options_from_section(context.config_json["ffmpeg"]["trim_video"]["output_options"], ffmpeg_command=True) for element in trim_video_options: trim_video_command.append(element) trim_video_command.append(output_file) console_output = open(context.log_dir + "ffmpeg_trim_video_command.txt", "w") console_output.write(str(trim_video_command)) subprocess.call(trim_video_command, shell=True, stderr=console_output, stdout=console_output)
def __init__(self, context: Context): # load context self.frame_count = context.frame_count self.waifu2x_vulkan_dir = context.waifu2x_ncnn_vulkan_file_path self.waifu2x_vulkan_path = context.waifu2x_ncnn_vulkan_path self.differences_dir = context.differences_dir self.upscaled_dir = context.upscaled_dir self.noise_level = context.noise_level self.scale_factor = context.scale_factor self.workspace = context.workspace self.context = context self.waifu2x_vulkan_upscale_frame = [ self.waifu2x_vulkan_dir, "-i", "[input_file]", "-n", str(self.noise_level), "-s", str(self.scale_factor) ] waifu2x_vulkan_options = get_options_from_section( self.context.config_json["waifu2x_ncnn_vulkan"]["output_options"]) # add custom options to waifu2x_vulkan for element in waifu2x_vulkan_options: self.waifu2x_vulkan_upscale_frame.append(element) self.waifu2x_vulkan_upscale_frame.extend(["-o", "[output_file]"]) threading.Thread.__init__(self) logging.basicConfig(filename=self.workspace + 'waifu2x.log', level=logging.INFO)
def __init__(self, context: Context): self.frame_count = context.frame_count self.waifu2x_caffe_cui_dir = context.waifu2x_caffe_cui_dir self.differences_dir = context.differences_dir self.upscaled_dir = context.upscaled_dir self.noise_level = context.noise_level self.scale_factor = context.scale_factor self.workspace = context.workspace self.context = context # Create Caffe Command self.waifu2x_caffe_upscale_frame = [ self.waifu2x_caffe_cui_dir, "-i", "[input_file]", "-n", str(self.noise_level), "-s", str(self.scale_factor) ] waifu2x_caffe_options = get_options_from_section( context.config_json["waifu2x_caffe"]["output_options"]) for element in waifu2x_caffe_options: self.waifu2x_caffe_upscale_frame.append(element) self.waifu2x_caffe_upscale_frame.extend(["-o", "[output_file]"]) threading.Thread.__init__(self) logging.basicConfig(filename=self.workspace + 'waifu2x.log', level=logging.INFO)
def __init__(self, context: Context): # load context self.frame_count = context.frame_count self.waifu2x_converter_cpp_file_path = context.waifu2x_converter_cpp_file_path self.waifu2x_converter_cpp_path = context.waifu2x_converter_cpp_path self.residual_images_dir = context.residual_images_dir self.residual_upscaled_dir = context.residual_upscaled_dir self.noise_level = context.noise_level self.scale_factor = context.scale_factor self.workspace = context.workspace self.context = context self.waifu2x_conv_upscale_frame = [ self.waifu2x_converter_cpp_file_path, "-i", "[input_file]", "--noise-level", str(self.noise_level), "--scale-ratio", str(self.scale_factor) ] waifu2x_conv_options = get_options_from_section( self.context.config_json["waifu2x_converter"]["output_options"]) # add custom options to waifu2x_vulkan for element in waifu2x_conv_options: self.waifu2x_conv_upscale_frame.append(element) self.waifu2x_conv_upscale_frame.extend(["-o", "[output_file]"]) threading.Thread.__init__(self) logging.basicConfig(filename=self.workspace + 'waifu2x.log', level=logging.INFO)
def extract_frames(context: Context, input_file: str): input_frames_dir = context.input_frames_dir extension_type = context.extension_type output_file = input_frames_dir + "frame%01d" + extension_type logger = logging.getLogger(__name__) frame_rate = context.frame_rate extract_frames_command = [ context.ffmpeg_dir, "-hwaccel", context.hwaccel, "-i", input_file ] extract_frames_options = \ get_options_from_section(context.config_json["ffmpeg"]["video_to_frames"]['output_options'], ffmpeg_command=True) for element in extract_frames_options: extract_frames_command.append(element) extract_frames_command.append("-r") extract_frames_command.append(str(frame_rate)) extract_frames_command.extend([output_file]) logger.info("extracting frames") console_output = open( context.log_dir + "ffmpeg_extract_frames_console.txt", "w") console_output.write(str(extract_frames_command)) subprocess.call(extract_frames_command, shell=True, stderr=console_output, stdout=console_output)
def create_video_from_specific_frames(context: Context, file_prefix, output_file, start_number, frames_per_video): # load context logger = context.logger extension_type = context.extension_type input_files = file_prefix + "%d" + extension_type video_from_frames_command = [ context.ffmpeg_dir, "-start_number", str(start_number), "-hwaccel", context.hwaccel, "-framerate", str(context.frame_rate), "-i", input_files, "-vframes", str(frames_per_video), "-r", str(context.frame_rate) ] frame_to_video_option = get_options_from_section( context.config_json["ffmpeg"]["frames_to_video"]['output_options'], ffmpeg_command=True) for element in frame_to_video_option: video_from_frames_command.append(element) video_from_frames_command.extend([output_file]) logger.info("running ffmpeg command: " + str(video_from_frames_command)) console_output = open(context.log_dir + "video_from_frames_command.txt", "w") console_output.write(str(video_from_frames_command)) subprocess.call(video_from_frames_command, shell=True, stderr=console_output, stdout=console_output)
def concat_encoded_vids(context: Context, output_file: str): """ Concatonate a video using 2) in this stackoverflow post. https://stackoverflow.com/questions/7333232/how-to-concatenate-two-mp4-files-using-ffmpeg The 'list.txt' should already exist, as it's produced in realtime_encoding.py """ encoded_dir = context.encoded_dir text_file = encoded_dir + "list.txt" concat_videos_command = [ context.ffmpeg_dir, "-f", "concat", "-safe", "0", "-hwaccel", context.hwaccel, "-i", text_file ] concat_videos_option = \ get_options_from_section(context.config_json["ffmpeg"]["concat_videos"]['output_options'], ffmpeg_command=True) for element in concat_videos_option: concat_videos_command.append(element) concat_videos_command.extend([output_file]) console_output = open(context.log_dir + "ffmpeg_concat_videos_command.txt", "w") console_output.write((str(concat_videos_command))) subprocess.call(concat_videos_command, shell=False, stderr=console_output, stdout=console_output)
def migrate_tracks(context: Context, no_audio: str, file_dir: str, output_file: str): """ Add the audio tracks from the original video to the output video. """ migrate_tracks_command = [ context.ffmpeg_dir, "-i", no_audio, "-i", file_dir, "-map", "0:v:0?", "-map", "1?", "-c", "copy", "-map", "-1:v?" ] migrate_tracks_options = \ get_options_from_section(context.config_json["ffmpeg"]["migrating_tracks"]['output_options'], ffmpeg_command=True) for element in migrate_tracks_options: migrate_tracks_command.append(element) migrate_tracks_command.extend([str(output_file)]) console_output = open(context.log_dir + "migrate_tracks_command.txt", "w") console_output.write(str(migrate_tracks_command)) subprocess.call(migrate_tracks_command, shell=False, stderr=console_output, stdout=console_output)
def concat_encoded_vids(context: Context, output_file: str): text_file = context.workspace + "encoded\\list.txt" concat_videos_command = [ context.ffmpeg_dir, "-f", "concat", "-safe", "0", "-hwaccel", context.hwaccel, "-i", text_file ] concat_videos_option = \ get_options_from_section(context.config_json["ffmpeg"]["concat_videos"]['output_options'], ffmpeg_command=True) for element in concat_videos_option: concat_videos_command.append(element) concat_videos_command.extend([output_file]) console_output = open(context.log_dir + "ffmpeg_concat_videos_command.txt", "w") console_output.write((str(concat_videos_command))) subprocess.call(concat_videos_command, shell=True, stderr=console_output, stdout=console_output)
def __init__(self, config_json_unparsed: json): """ Create all the needed values that will be used in various parts of dandere2x. A lot of these values are derived from external files, such as the json, ffmpeg and ffprobe, or are joined from directories. Having all the variables here allows dandere2x the values needed to be global, but at the same time not really. """ self.this_folder = None # load 'this folder' in a pyinstaller friendly way if getattr(sys, 'frozen', False): self.this_folder = os.path.dirname(sys.executable) elif __file__: self.this_folder = os.path.dirname(__file__) self.this_folder = pathlib.Path(self.this_folder) # Parse the unparsed config into a parsed (../externals -> C:/this_folder/externals) self.config_json = absolutify_json(config_json_unparsed, str(self.this_folder.absolute()), absolutify_key="..") ################################ # setup all the directories.. # ################################ # side note - for vulkan and converter, we need to know the path of the file in order for it to run correctly, # hence why we have two variables for them self.waifu2x_converter_cpp_path = self.config_json[ 'waifu2x_converter']['waifu2x_converter_path'] self.waifu2x_converter_file_name = self.config_json[ 'waifu2x_converter']['waifu2x_converter_file_name'] self.waifu2x_converter_cpp_file_path = os.path.join( self.waifu2x_converter_cpp_path, self.waifu2x_converter_file_name) self.waifu2x_ncnn_vulkan_path = self.config_json[ 'waifu2x_ncnn_vulkan']['waifu2x_ncnn_vulkan_path'] self.waifu2x_ncnn_vulkan_file_name = self.config_json[ 'waifu2x_ncnn_vulkan']['waifu2x_ncnn_vulkan_file_name'] self.waifu2x_ncnn_vulkan_file_path = os.path.join( self.waifu2x_ncnn_vulkan_path, self.waifu2x_ncnn_vulkan_file_name) self.waifu2x_caffe_cui_dir = pathlib.Path( self.config_json['waifu2x_caffe']['waifu2x_caffe_path']) self.workspace = self.config_json['dandere2x']['developer_settings'][ 'workspace'] self.workspace_use_temp = self.config_json['dandere2x'][ 'developer_settings']['workspace_use_temp'] # if we're using a temporary workspace, assign workspace to be in the temp folder if self.workspace_use_temp: self.workspace = os.path.join(pathlib.Path(tempfile.gettempdir()), 'dandere2x') + os.path.sep # setup directories self.input_frames_dir = self.workspace + "inputs" + os.path.sep self.residual_images_dir = self.workspace + "residual_images" + os.path.sep self.residual_upscaled_dir = self.workspace + "residual_upscaled" + os.path.sep self.correction_data_dir = self.workspace + "correction_data" + os.path.sep self.merged_dir = self.workspace + "merged" + os.path.sep self.residual_data_dir = self.workspace + "residual_data" + os.path.sep self.pframe_data_dir = self.workspace + "pframe_data" + os.path.sep self.fade_data_dir = self.workspace + "fade_data" + os.path.sep self.debug_dir = self.workspace + "debug" + os.path.sep self.log_dir = self.workspace + "logs" + os.path.sep self.compressed_static_dir = self.workspace + "compressed_static" + os.path.sep self.compressed_moving_dir = self.workspace + "compressed_moving" + os.path.sep self.encoded_dir = self.workspace + "encoded" + os.path.sep self.temp_image_folder = self.workspace + "temp_image_folder" + os.path.sep # put all the directories that need to be created into a list for creation / deleting. self.directories = { self.workspace, self.input_frames_dir, self.correction_data_dir, self.residual_images_dir, self.residual_upscaled_dir, self.merged_dir, self.residual_data_dir, self.pframe_data_dir, self.debug_dir, self.log_dir, self.compressed_static_dir, self.compressed_moving_dir, self.fade_data_dir, self.encoded_dir, self.temp_image_folder } self.ffmpeg_dir = self.config_json['ffmpeg']['ffmpeg_path'] self.ffprobe_dir = self.config_json['ffmpeg']['ffprobe_path'] self.hwaccel = self.config_json['ffmpeg']['-hwaccel'] ################################ # Load Dandere2x User Settings # ################################ # User Settings self.block_size = self.config_json['dandere2x']['usersettings'][ 'block_size'] self.quality_minimum = self.config_json['dandere2x']['usersettings'][ 'quality_minimum'] self.waifu2x_type = self.config_json['dandere2x']['usersettings'][ 'waifu2x_type'] self.noise_level = self.config_json['dandere2x']['usersettings'][ 'denoise_level'] self.scale_factor = self.config_json['dandere2x']['usersettings'][ 'scale_factor'] self.input_file = self.config_json['dandere2x']['usersettings'][ 'input_file'] self.output_file = self.config_json['dandere2x']['usersettings'][ 'output_file'] # Developer Settings self.quality_moving_ratio = self.config_json['dandere2x'][ 'developer_settings']['quality_moving_ratio'] self.step_size = self.config_json['dandere2x']['developer_settings'][ 'step_size'] self.bleed = self.config_json['dandere2x']['developer_settings'][ 'bleed'] self.extension_type = self.config_json['dandere2x'][ 'developer_settings']['extension_type'] self.debug = self.config_json['dandere2x']['developer_settings'][ 'debug'] self.dandere2x_cpp_dir = self.config_json['dandere2x'][ 'developer_settings']['dandere2x_cpp_dir'] self.correction_block_size = 2 # Real Time Encoding self.realtime_encoding_enabled = self.config_json['dandere2x'][ 'developer_settings']['realtime_encoding'][ 'realtime_encoding_enabled'] self.realtime_encoding_delete_files = self.config_json['dandere2x'][ 'developer_settings']['realtime_encoding'][ 'realtime_encoding_delete_files'] self.realtime_encoding_seconds_per_video = \ self.config_json['dandere2x']['developer_settings']['realtime_encoding']['realtime_encoding_seconds_per_video'] ################################ # Video Settings # ################################ # find out if the user trimmed a video by checking the time part of the json. IF theres nothing there, # then the user didn't trim anything self.user_trim_video = False find_out_if_trim = get_options_from_section( self.config_json["ffmpeg"]["trim_video"]['time']) if find_out_if_trim: self.user_trim_video = True # load the needed video settings self.video_settings = VideoSettings(self.ffprobe_dir, self.input_file) self.frame_rate = math.ceil(self.video_settings.frame_rate) self.width = self.video_settings.width self.height = self.video_settings.height self.frame_count = 0
def __init__(self, config_json_unparsed: json): # load 'this folder' in a pyinstaller friendly way self.this_folder = None if getattr(sys, 'frozen', False): self.this_folder = os.path.dirname(sys.executable) elif __file__: self.this_folder = os.path.dirname(__file__) self.this_folder = pathlib.Path(self.this_folder) # We need the json to be absolute, meaning ".." --> this.folder # This allows Dandere2x to be somewhat portable on different systems self.config_json = absolutify_json(config_json_unparsed, str(self.this_folder.absolute()), absolutify_key="..") ################################ # setup all the directories.. # ################################ # side note - for vulkan and converter, we need to know the path of the file in order for it to run correctly, # hence why we have two variables for them self.waifu2x_converter_cpp_path = self.config_json['waifu2x_converter']['waifu2x_converter_path'] self.waifu2x_converter_cpp_dir = os.path.join(self.waifu2x_converter_cpp_path, "waifu2x-converter-cpp.exe") self.waifu2x_vulkan_path = self.config_json['waifu2x_ncnn_vulkan']['waifu2x_ncnn_vulkan_path'] self.waifu2x_vulkan_dir = os.path.join(self.waifu2x_vulkan_path, "waifu2x-ncnn-vulkan.exe") self.waifu2x_caffe_cui_dir = pathlib.Path(self.config_json['waifu2x_caffe']['waifu2x_caffe_path']) self.workspace = self.config_json['dandere2x']['developer_settings']['workspace'] self.workspace_use_temp = self.config_json['dandere2x']['developer_settings']['workspace_use_temp'] # if we're using a temporary workspace, assign workspace to be in the temp folder if self.workspace_use_temp: self.workspace = os.path.join(pathlib.Path(tempfile.gettempdir()), 'dandere2x') + "\\" # setup directories self.input_frames_dir = self.workspace + "inputs" + os.path.sep self.differences_dir = self.workspace + "differences" + os.path.sep self.upscaled_dir = self.workspace + "upscaled" + os.path.sep self.correction_data_dir = self.workspace + "correction_data" + os.path.sep self.merged_dir = self.workspace + "merged" + os.path.sep self.inversion_data_dir = self.workspace + "inversion_data" + os.path.sep self.pframe_data_dir = self.workspace + "pframe_data" + os.path.sep self.fade_data_dir = self.workspace + "fade_data" + os.path.sep self.debug_dir = self.workspace + "debug" + os.path.sep self.log_dir = self.workspace + "logs" + os.path.sep self.compressed_static_dir = self.workspace + "compressed_static" + os.path.sep self.compressed_moving_dir = self.workspace + "compressed_moving" + os.path.sep self.encoded_dir = self.workspace + "encoded" + os.path.sep self.temp_image_folder = self.workspace + "temp_image_folder" + os.path.sep self.ffmpeg_dir = self.config_json['ffmpeg']['ffmpeg_path'] self.ffprobe_dir = self.config_json['ffmpeg']['ffprobe_path'] self.hwaccel = self.config_json['ffmpeg']['-hwaccel'] ################################ # Load Dandere2x User Settings # ################################ # User Settings self.block_size = self.config_json['dandere2x']['usersettings']['block_size'] self.quality_minimum = self.config_json['dandere2x']['usersettings']['quality_minimum'] self.waifu2x_type = self.config_json['dandere2x']['usersettings']['waifu2x_type'] self.noise_level = self.config_json['dandere2x']['usersettings']['denoise_level'] self.scale_factor = self.config_json['dandere2x']['usersettings']['scale_factor'] self.input_file = self.config_json['dandere2x']['usersettings']['input_file'] self.output_file = self.config_json['dandere2x']['usersettings']['output_file'] # Developer Settings self.quality_moving_ratio = self.config_json['dandere2x']['developer_settings']['quality_moving_ratio'] self.step_size = self.config_json['dandere2x']['developer_settings']['step_size'] self.bleed = self.config_json['dandere2x']['developer_settings']['bleed'] self.extension_type = self.config_json['dandere2x']['developer_settings']['extension_type'] self.debug = self.config_json['dandere2x']['developer_settings']['debug'] self.dandere2x_cpp_dir = self.config_json['dandere2x']['developer_settings']['dandere2x_cpp_dir'] self.correction_block_size = 2 # Real Time Encoding self.realtime_encoding_enabled = self.config_json['dandere2x']['developer_settings']['realtime_encoding'][ 'realtime_encoding_enabled'] self.realtime_encoding_delete_files = self.config_json['dandere2x']['developer_settings']['realtime_encoding'][ 'realtime_encoding_delete_files'] self.realtime_encoding_seconds_per_video = \ self.config_json['dandere2x']['developer_settings']['realtime_encoding']['realtime_encoding_seconds_per_video'] ################################ # Video Settings # ################################ # find out if the user trimmed a video by checking the time part of the json. IF theres nothing there, # then the user didn't trim anything self.user_trim_video = False find_out_if_trim = get_options_from_section(self.config_json["ffmpeg"]["trim_video"]['time']) if find_out_if_trim: self.user_trim_video = True self.video_settings = VideoSettings(self.ffprobe_dir, self.input_file) self.frame_rate = math.ceil(self.video_settings.frame_rate) self.width = self.video_settings.width self.height = self.video_settings.height self.frame_count = 0