mirror of
https://github.com/k4yt3x/video2x.git
synced 2026-02-23 07:14:46 +08:00
added image and GIF upscale support
This commit is contained in:
@@ -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:
|
||||
|
||||
@@ -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
70
src/wrappers/gifski.py
Normal 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)
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user