From 146044505b845224c67c5316580a283f47bd91e8 Mon Sep 17 00:00:00 2001 From: k4yt3x Date: Mon, 6 May 2019 16:25:10 -0400 Subject: [PATCH] fixed issue #77 incorrect output video format --- bin/ffmpeg.py | 99 +++++++++++++++++++++++++++++++++++++++--------- bin/video2x.json | 32 +++++++++------- 2 files changed, 100 insertions(+), 31 deletions(-) diff --git a/bin/ffmpeg.py b/bin/ffmpeg.py index cace9423b1..9acf63d488 100644 --- a/bin/ffmpeg.py +++ b/bin/ffmpeg.py @@ -4,7 +4,7 @@ Name: FFMPEG Class Author: K4YT3X Date Created: Feb 24, 2018 -Last Modified: April 28, 2019 +Last Modified: May 4, 2019 Description: This class handles all FFMPEG related operations. @@ -77,12 +77,18 @@ def extract_frames(self, input_video, extracted_frames): extracted_frames {string} -- video output directory """ execute = [ - self.ffmpeg_binary, + self.ffmpeg_binary + ] + + execute.extend(self._read_configuration(phase='video_to_frames')) + + execute.extend([ '-i', input_video, f'{extracted_frames}\\extracted_%0d.{self.image_format}' - ] - self._execute(execute=execute, phase='video_to_frames') + ]) + + self._execute(execute) def convert_video(self, framerate, resolution, upscaled_frames): """Converts images into videos @@ -100,12 +106,30 @@ def convert_video(self, framerate, resolution, upscaled_frames): '-r', str(framerate), '-s', - resolution, + resolution + ] + + # read FFmpeg input options + execute.extend(self._read_configuration(phase='frames_to_video', section='input_options')) + + # append input frames path into command + execute.extend([ '-i', - f'{upscaled_frames}\\extracted_%d.{self.image_format}', + f'{upscaled_frames}\\extracted_%d.{self.image_format}' + ]) + + # read FFmpeg output options + execute.extend(self._read_configuration(phase='frames_to_video', section='output_options')) + + # read other options + execute.extend(self._read_configuration(phase='frames_to_video')) + + # specify output file location + execute.extend([ f'{upscaled_frames}\\no_audio.mp4' - ] - self._execute(execute=execute, phase='frames_to_video') + ]) + + self._execute(execute) def migrate_audio_tracks_subtitles(self, input_video, output_video, upscaled_frames): """ Migrates audio tracks and subtitles from input video to output video @@ -120,28 +144,69 @@ def migrate_audio_tracks_subtitles(self, input_video, output_video, upscaled_fra '-i', f'{upscaled_frames}\\no_audio.mp4', '-i', - input_video, - output_video + input_video ] - self._execute(execute=execute, phase='migrating_tracks') - def _execute(self, execute, phase): + execute.extend(self._read_configuration(phase='frames_to_video', section='output_options')) - for key in self.ffmpeg_settings[phase].keys(): + execute.extend([ + output_video + ]) - value = self.ffmpeg_settings[phase][key] + execute.extend(self._read_configuration(phase='migrating_tracks')) + + self._execute(execute) + + def _read_configuration(self, phase, section=None): + """ read configuration from JSON + + Read the configurations (arguments) from the JSON + configuration file and append them to the end of the + FFmpeg command. + + Arguments: + execute {list} -- list of arguments to be executed + phase {str} -- phase of operation + """ + + configuration = [] + + # if section is specified, read configurations or keys + # from only that section + if section: + source = self.ffmpeg_settings[phase][section].keys() + else: + source = self.ffmpeg_settings[phase].keys() + + for key in source: + + if section: + value = self.ffmpeg_settings[phase][section][key] + else: + value = self.ffmpeg_settings[phase][key] # null or None means that leave this option out (keep default) - if value is None or value is False: + if value is None or value is False or isinstance(value, list) or isinstance(value, dict): continue else: - execute.append(key) + configuration.append(key) # true means key is an option if value is True: continue - execute.append(str(value)) + configuration.append(str(value)) + + return configuration + + def _execute(self, execute): + """ execute command + Arguments: + execute {list} -- list of arguments to be executed + + Returns: + int -- execution return code + """ Avalon.debug_info(f'Executing: {execute}') return subprocess.run(execute, shell=True, check=True).returncode diff --git a/bin/video2x.json b/bin/video2x.json index 270d53665f..69e0a9ac1b 100644 --- a/bin/video2x.json +++ b/bin/video2x.json @@ -47,23 +47,27 @@ "-y": true }, "frames_to_video": { - "-qscale:v": null, - "-qscale:a": null, - "-f": "image2", - "-vcodec": "libx264", - "-crf": 17, - "-b:v": null, - "-pix_fmt": "yuv420p", - "-hwaccel": "auto", + "input_options":{ + "-qscale:v": null, + "-qscale:a": null, + "-f": "image2" + }, + "output_options":{ + "-vcodec": "libx264", + "-crf": 17, + "-b:v": null, + "-pix_fmt": "yuv420p" + }, "-y": true }, "migrating_tracks": { - "-map": "0:v:0?", - "-map": "1?", - "-c": "copy", - "-map": "-1:v?", - "-pix_fmt": "yuv420p", - "-hwaccel": "auto", + "output_options":{ + "-map": "0:v:0?", + "-map": "1?", + "-c": "copy", + "-map": "-1:v?", + "-pix_fmt": "yuv420p" + }, "-y": true } },