added image and GIF upscale support

This commit is contained in:
k4yt3x
2020-05-11 20:24:18 -04:00
parent 5cf3271aad
commit e305d0188e
13 changed files with 401 additions and 231 deletions

View File

@@ -69,6 +69,10 @@ class WrapperMain:
self.driver_settings['zoomFactor'] = upscaler.scale_ratio
self.driver_settings['threads'] = upscaler.processes
# append FFmpeg path to the end of PATH
# Anime4KCPP will then use FFmpeg to migrate audio tracks
os.environ['PATH'] += f';{upscaler.ffmpeg_settings["ffmpeg_path"]}'
def upscale(self, input_file, output_file):
"""This is the core function for WAIFU2X class
@@ -90,14 +94,14 @@ class WrapperMain:
# list to be executed
# initialize the list with waifu2x binary path as the first element
execute = [self.driver_settings.pop('path')]
execute = [self.driver_settings['path']]
for key in self.driver_settings.keys():
value = self.driver_settings[key]
# null or None means that leave this option out (keep default)
if value is None or value is False:
if key == 'path' or value is None or value is False:
continue
else:
if len(key) == 1:

View File

@@ -12,6 +12,7 @@ Description: This class handles all FFmpeg related operations.
# built-in imports
import json
import pathlib
import shlex
import subprocess
# third-party imports
@@ -36,7 +37,7 @@ class Ffmpeg:
# video metadata
self.image_format = image_format
self.intermediate_file_name = pathlib.Path(self.ffmpeg_settings['intermediate_file_name'])
self.pixel_format = None
self.pixel_format = self.ffmpeg_settings['input_to_frames']['output_options']['-pix_fmt']
def get_pixel_formats(self):
""" Get a dictionary of supported pixel formats
@@ -49,8 +50,8 @@ class Ffmpeg:
"""
execute = [
self.ffmpeg_probe_binary,
'-v',
'quiet',
# '-v',
# 'quiet',
'-pix_fmts'
]
@@ -74,7 +75,7 @@ class Ffmpeg:
return pixel_formats
def get_video_info(self, input_video):
def probe_file_info(self, input_video):
""" Gets input video information
This method reads input video information
@@ -104,31 +105,25 @@ class Ffmpeg:
# turn elements into str
execute = [str(e) for e in execute]
Avalon.debug_info(f'Executing: {" ".join(execute)}')
Avalon.debug_info(f'Executing: {shlex.join(execute)}')
json_str = subprocess.run(execute, check=True, stdout=subprocess.PIPE).stdout
return json.loads(json_str.decode('utf-8'))
def extract_frames(self, input_video, extracted_frames):
"""Extract every frame from original videos
This method extracts every frame from input video using FFmpeg
Arguments:
input_video {string} -- input video path
extracted_frames {string} -- video output directory
def extract_frames(self, input_file, extracted_frames):
""" extract frames from video or GIF file
"""
execute = [
self.ffmpeg_binary
]
execute.extend(self._read_configuration(phase='video_to_frames'))
execute.extend(self._read_configuration(phase='input_to_frames'))
execute.extend([
'-i',
input_video
input_file
])
execute.extend(self._read_configuration(phase='video_to_frames', section='output_options'))
execute.extend(self._read_configuration(phase='input_to_frames', section='output_options'))
execute.extend([
extracted_frames / f'extracted_%0d.{self.image_format}'
@@ -136,7 +131,7 @@ class Ffmpeg:
return(self._execute(execute))
def assemble_video(self, framerate, resolution, upscaled_frames):
def assemble_video(self, framerate, upscaled_frames):
"""Converts images into videos
This method converts a set of images into a video
@@ -149,9 +144,9 @@ class Ffmpeg:
execute = [
self.ffmpeg_binary,
'-r',
str(framerate),
'-s',
resolution
str(framerate)
# '-s',
# resolution
]
# read other options
@@ -274,17 +269,9 @@ class Ffmpeg:
return configuration
def _execute(self, execute):
""" execute command
Arguments:
execute {list} -- list of arguments to be executed
Returns:
int -- execution return code
"""
# turn all list elements into string to avoid errors
execute = [str(e) for e in execute]
Avalon.debug_info(f'Executing: {execute}')
Avalon.debug_info(f'Executing: {shlex.join(execute)}')
return subprocess.Popen(execute)

70
src/wrappers/gifski.py Normal file
View File

@@ -0,0 +1,70 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Name: Gifski Wrapper
Creator: K4YT3X
Date Created: May 11, 2020
Last Modified: May 11, 2020
Description: High-level wrapper for Gifski.
"""
# built-in imports
import pathlib
import subprocess
# third-party imports
from avalon_framework import Avalon
class Gifski:
def __init__(self, gifski_settings):
self.gifski_settings = gifski_settings
def make_gif(self, upscaled_frames: pathlib.Path, output_path: pathlib.Path, framerate: float, image_format: str) -> subprocess.Popen:
execute = [
self.gifski_settings['gifski_path'],
'-o',
output_path,
'--fps',
int(round(framerate, 0))
]
# load configurations from config file
execute.extend(self._load_configuration())
# append frames location
execute.extend([upscaled_frames / f'extracted_*.{image_format}'])
return(self._execute(execute))
def _load_configuration(self):
configuration = []
for key in self.gifski_settings.keys():
value = self.gifski_settings[key]
# null or None means that leave this option out (keep default)
if key == 'gifski_path' or value is None or value is False:
continue
else:
if len(key) == 1:
configuration.append(f'-{key}')
else:
configuration.append(f'--{key}')
# true means key is an option
if value is not True:
configuration.append(str(value))
return configuration
def _execute(self, execute: list) -> subprocess.Popen:
# turn all list elements into string to avoid errors
execute = [str(e) for e in execute]
Avalon.debug_info(f'Executing: {execute}')
return subprocess.Popen(execute)

View File

@@ -77,14 +77,14 @@ class WrapperMain:
# list to be executed
# initialize the list with the binary path as the first element
execute = [self.driver_settings.pop('path')]
execute = [self.driver_settings['path']]
for key in self.driver_settings.keys():
value = self.driver_settings[key]
# null or None means that leave this option out (keep default)
if value is None or value is False:
if key == 'path' or value is None or value is False:
continue
else:
if len(key) == 1:

View File

@@ -56,8 +56,8 @@ class WrapperMain:
parser.add_argument('-m', '--mode', choices=['noise', 'scale', 'noise_scale', 'auto_scale'], help='image processing mode')
parser.add_argument('-e', '--output_extention', type=str, help='extention to output image file when output_path is (auto) or input_path is folder')
parser.add_argument('-l', '--input_extention_list', type=str, help='extention to input image file when input_path is folder')
parser.add_argument('-o', '--output', type=str, help=argparse.SUPPRESS) # help='path to output image file (when input_path is folder, output_path must be folder)')
parser.add_argument('-i', '--input_file', type=str, help=argparse.SUPPRESS) # help='(required) path to input image file')
parser.add_argument('-o', '--output_path', type=str, help=argparse.SUPPRESS) # help='path to output image file (when input_path is folder, output_path must be folder)')
parser.add_argument('-i', '--input_path', type=str, help=argparse.SUPPRESS) # help='(required) path to input image file')
return parser.parse_args(arguments)
def load_configurations(self, upscaler):
@@ -79,14 +79,14 @@ class WrapperMain:
# list to be executed
# initialize the list with waifu2x binary path as the first element
execute = [self.driver_settings.pop('path')]
execute = [self.driver_settings['path']]
for key in self.driver_settings.keys():
value = self.driver_settings[key]
# null or None means that leave this option out (keep default)
if value is None or value is False:
if key == 'path' or value is None or value is False:
continue
else:
if len(key) == 1:

View File

@@ -93,14 +93,14 @@ class WrapperMain:
# list to be executed
# initialize the list with waifu2x binary path as the first element
execute = [self.driver_settings.pop('path')]
execute = [self.driver_settings['path']]
for key in self.driver_settings.keys():
value = self.driver_settings[key]
# null or None means that leave this option out (keep default)
if value is None or value is False:
if key == 'path' or value is None or value is False:
continue
else:
if len(key) == 1:

View File

@@ -80,14 +80,14 @@ class WrapperMain:
# list to be executed
# initialize the list with waifu2x binary path as the first element
execute = [self.driver_settings.pop('path')]
execute = [self.driver_settings['path']]
for key in self.driver_settings.keys():
value = self.driver_settings[key]
# null or None means that leave this option out (keep default)
if value is None or value is False:
if key == 'path' or value is None or value is False:
continue
else:
if len(key) == 1: