mirror of
https://github.com/k4yt3x/video2x.git
synced 2026-02-10 14:54:46 +08:00
Compare commits
17 Commits
4.0.0-beta
...
4.0.0-beta
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
14f7f34ee3 | ||
|
|
11ba334f16 | ||
|
|
c451b14bd7 | ||
|
|
80623a6bb7 | ||
|
|
a5dd87a72c | ||
|
|
9b20ef89c9 | ||
|
|
91efe2d684 | ||
|
|
0d9d5c4f43 | ||
|
|
e0e42b11c8 | ||
|
|
790bb54598 | ||
|
|
f2943802cb | ||
|
|
d12f2a3888 | ||
|
|
871d6386a8 | ||
|
|
589a68caf7 | ||
|
|
afacc48e1e | ||
|
|
4a3553607b | ||
|
|
988600a769 |
6
.gitignore
vendored
6
.gitignore
vendored
@@ -1,9 +1,3 @@
|
||||
# Runtime files
|
||||
upscaled/
|
||||
frames/
|
||||
waifu2x-caffe/
|
||||
testvid.mp4
|
||||
|
||||
# PyCharm
|
||||
.idea/
|
||||
|
||||
|
||||
@@ -12,12 +12,18 @@ To start a PowerShell session with execution policy bypass
|
||||
powershell –ExecutionPolicy Bypass
|
||||
#>
|
||||
|
||||
if ($args.count -ne 1){
|
||||
Write-Host -ForegroundColor White "Usage:`n .\build.ps1 VIDEO2X_VERSION"
|
||||
Exit
|
||||
}
|
||||
|
||||
# version number
|
||||
$SCRIPT_VERSION = "1.0.1"
|
||||
$VIDEO2X_VERSION = "4.0.0_beta2"
|
||||
$VIDEO2X_VERSION = $args[0]
|
||||
|
||||
Write-Host -ForegroundColor White "Video2X Building Script Version $($SCRIPT_VERSION)
|
||||
Starting to build Video2X release packages"
|
||||
Starting to build Video2X release packages
|
||||
Building Video2X release $($VIDEO2X_VERSION)"
|
||||
|
||||
# build Video2X CLI
|
||||
Write-Host -ForegroundColor White "`nBuilding Video2X CLI"
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"POT-Creation-Date: 2020-05-07 15:54-0400\n"
|
||||
"PO-Revision-Date: 2020-05-07 15:55-0400\n"
|
||||
"POT-Creation-Date: 2020-05-08 22:10-0400\n"
|
||||
"PO-Revision-Date: 2020-05-08 22:11-0400\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: \n"
|
||||
"Language: zh_CN\n"
|
||||
@@ -21,151 +21,163 @@ msgstr ""
|
||||
msgid "Upscaling Progress"
|
||||
msgstr "放大进度"
|
||||
|
||||
#: upscaler.py:104
|
||||
#: upscaler.py:105
|
||||
msgid "Specified or default cache directory is a file/link"
|
||||
msgstr "指定或默认的缓存目录是文件/链接"
|
||||
|
||||
#: upscaler.py:110
|
||||
#: upscaler.py:111
|
||||
msgid "Creating cache directory {}"
|
||||
msgstr "创建缓存目录 {}"
|
||||
|
||||
#: upscaler.py:113
|
||||
#: upscaler.py:114
|
||||
msgid "Unable to create {}"
|
||||
msgstr "无法创建 {}"
|
||||
|
||||
#: upscaler.py:118
|
||||
#: upscaler.py:119
|
||||
msgid "Extracted frames are being saved to: {}"
|
||||
msgstr "提取的帧将被保存到:{}"
|
||||
|
||||
#: upscaler.py:120
|
||||
#: upscaler.py:121
|
||||
msgid "Upscaled frames are being saved to: {}"
|
||||
msgstr "已放大的帧将被保存到:{}"
|
||||
|
||||
#: upscaler.py:130
|
||||
#: upscaler.py:131
|
||||
msgid "Cleaning up cache directory: {}"
|
||||
msgstr "清理缓存目录:{}"
|
||||
|
||||
#: upscaler.py:133
|
||||
#: upscaler.py:134
|
||||
msgid "Unable to delete: {}"
|
||||
msgstr "无法删除:{}"
|
||||
|
||||
#: upscaler.py:140 upscaler.py:151
|
||||
#: upscaler.py:140 upscaler.py:155 upscaler.py:166
|
||||
msgid "Input and output path type mismatch"
|
||||
msgstr "输入和输出路径类型不匹配"
|
||||
|
||||
#: upscaler.py:141
|
||||
msgid "Input is multiple files but output is not directory"
|
||||
msgstr "输入是多个文件,但输出不是目录"
|
||||
|
||||
#: upscaler.py:145
|
||||
msgid "Input path {} is neither a file nor a directory"
|
||||
msgstr "输入路径 {} 既不是文件也不是目录"
|
||||
|
||||
#: upscaler.py:149 upscaler.py:171
|
||||
msgid "Input directory and output directory cannot be the same"
|
||||
msgstr "输入目录和输出目录不能相同"
|
||||
|
||||
#: upscaler.py:156
|
||||
msgid "Input is single file but output is directory"
|
||||
msgstr "所选的输入路径是单个文件,但输出路径是目录"
|
||||
|
||||
#: upscaler.py:144
|
||||
#: upscaler.py:159
|
||||
msgid "No suffix found in output file path"
|
||||
msgstr "在输出文件路径中未找到后缀"
|
||||
|
||||
#: upscaler.py:145
|
||||
#: upscaler.py:160
|
||||
msgid "Suffix must be specified for FFmpeg"
|
||||
msgstr "必须为 FFmpeg 指定后缀"
|
||||
|
||||
#: upscaler.py:152
|
||||
#: upscaler.py:167
|
||||
msgid "Input is directory but output is existing single file"
|
||||
msgstr "输入是目录,但输出是现有的单个文件"
|
||||
|
||||
#: upscaler.py:157
|
||||
#: upscaler.py:176
|
||||
msgid "Input path is neither a file nor a directory"
|
||||
msgstr "输入路径既不是文件也不是目录"
|
||||
|
||||
#: upscaler.py:166
|
||||
#: upscaler.py:185
|
||||
msgid "FFmpeg or FFprobe cannot be found under the specified path"
|
||||
msgstr "在指定的路径下找不到 FFmpeg 或 FFprobe"
|
||||
|
||||
#: upscaler.py:167 upscaler.py:177
|
||||
#: upscaler.py:186 upscaler.py:196
|
||||
msgid "Please check the configuration file settings"
|
||||
msgstr "请检查配置文件设置"
|
||||
|
||||
#: upscaler.py:176
|
||||
#: upscaler.py:195
|
||||
msgid "Specified driver executable directory doesn't exist"
|
||||
msgstr "指定驱动的可执行文件不存在"
|
||||
|
||||
#: upscaler.py:203
|
||||
#: upscaler.py:222
|
||||
msgid "Failed to parse driver argument: {}"
|
||||
msgstr "解析驱动程序参数失败:{}"
|
||||
|
||||
#: upscaler.py:218
|
||||
#: upscaler.py:237
|
||||
msgid "Unrecognized driver: {}"
|
||||
msgstr "无法识别的驱动名称:{}"
|
||||
|
||||
#: upscaler.py:290
|
||||
#: upscaler.py:309
|
||||
msgid "Starting progress monitor"
|
||||
msgstr "启动进度监视器"
|
||||
|
||||
#: upscaler.py:295
|
||||
#: upscaler.py:314
|
||||
msgid "Starting upscaled image cleaner"
|
||||
msgstr "启动已放大图像清理程序"
|
||||
|
||||
#: upscaler.py:304 upscaler.py:321
|
||||
#: upscaler.py:323 upscaler.py:340
|
||||
msgid "Killing progress monitor"
|
||||
msgstr "终结进度监视器"
|
||||
|
||||
#: upscaler.py:307 upscaler.py:324
|
||||
#: upscaler.py:326 upscaler.py:343
|
||||
msgid "Killing upscaled image cleaner"
|
||||
msgstr "终结已放大图像清理程序"
|
||||
|
||||
#: upscaler.py:328
|
||||
#: upscaler.py:347
|
||||
msgid "Terminating all processes"
|
||||
msgstr "正在终止所有进程"
|
||||
|
||||
#: upscaler.py:335
|
||||
#: upscaler.py:354
|
||||
msgid "Main process waiting for subprocesses to exit"
|
||||
msgstr "主进程开始等待子进程结束"
|
||||
|
||||
#: upscaler.py:354 upscaler.py:358
|
||||
#: upscaler.py:373 upscaler.py:377
|
||||
msgid "Subprocess {} exited with code {}"
|
||||
msgstr "子进程 {} 结束,返回码 {}"
|
||||
|
||||
#: upscaler.py:364
|
||||
#: upscaler.py:383
|
||||
msgid "Stop signal received"
|
||||
msgstr "收到停止信号"
|
||||
|
||||
#: upscaler.py:369
|
||||
#: upscaler.py:388
|
||||
msgid "Subprocess execution ran into an error"
|
||||
msgstr "子进程执行遇到错误"
|
||||
|
||||
#: upscaler.py:395
|
||||
#: upscaler.py:430
|
||||
msgid "Upscaling single video file: {}"
|
||||
msgstr "放大单个视频文件:{}"
|
||||
|
||||
#: upscaler.py:414 upscaler.py:477
|
||||
#: upscaler.py:452 upscaler.py:515
|
||||
msgid "Starting to upscale extracted images"
|
||||
msgstr "开始对提取的帧进行放大"
|
||||
|
||||
#: upscaler.py:423 upscaler.py:479
|
||||
#: upscaler.py:461 upscaler.py:517
|
||||
msgid "Upscaling completed"
|
||||
msgstr "放大完成"
|
||||
|
||||
#: upscaler.py:432
|
||||
#: upscaler.py:470
|
||||
msgid "Reading video information"
|
||||
msgstr "读取视频信息"
|
||||
|
||||
#: upscaler.py:446
|
||||
#: upscaler.py:484
|
||||
msgid "Aborting: No video stream found"
|
||||
msgstr "程序中止:文件中未找到视频流"
|
||||
|
||||
#: upscaler.py:464
|
||||
#: upscaler.py:502
|
||||
msgid "Unsupported pixel format: {}"
|
||||
msgstr "不支持的像素格式:{}"
|
||||
|
||||
#: upscaler.py:467
|
||||
#: upscaler.py:505
|
||||
msgid "Framerate: {}"
|
||||
msgstr "帧率:{}"
|
||||
|
||||
#: upscaler.py:482
|
||||
#: upscaler.py:520
|
||||
msgid "Converting extracted frames into video"
|
||||
msgstr "将提取的帧转换为视频"
|
||||
|
||||
#: upscaler.py:487
|
||||
#: upscaler.py:525
|
||||
msgid "Conversion completed"
|
||||
msgstr "转换已完成"
|
||||
|
||||
#: upscaler.py:490
|
||||
#: upscaler.py:528
|
||||
msgid "Migrating audio tracks and subtitles to upscaled video"
|
||||
msgstr "将音轨和字幕迁移到放大后的视频"
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ class ProgressMonitor(threading.Thread):
|
||||
|
||||
def run(self):
|
||||
self.running = True
|
||||
|
||||
|
||||
# get number of extracted frames
|
||||
self.upscaler.total_frames = 0
|
||||
for directory in self.extracted_frames_directories:
|
||||
|
||||
142
src/upscaler.py
142
src/upscaler.py
@@ -4,7 +4,7 @@
|
||||
Name: Video2X Upscaler
|
||||
Author: K4YT3X
|
||||
Date Created: December 10, 2018
|
||||
Last Modified: May 7, 2020
|
||||
Last Modified: May 8, 2020
|
||||
|
||||
Description: This file contains the Upscaler class. Each
|
||||
instance of the Upscaler class is an upscaler on an image or
|
||||
@@ -30,9 +30,7 @@ import queue
|
||||
import re
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
import threading
|
||||
import time
|
||||
import traceback
|
||||
|
||||
@@ -71,8 +69,8 @@ class Upscaler:
|
||||
|
||||
def __init__(self, input_path, output_path, driver_settings, ffmpeg_settings):
|
||||
# mandatory arguments
|
||||
self.input_path = input_path
|
||||
self.output_path = output_path
|
||||
self.input = input_path
|
||||
self.output = output_path
|
||||
self.driver_settings = driver_settings
|
||||
self.ffmpeg_settings = ffmpeg_settings
|
||||
|
||||
@@ -87,9 +85,12 @@ class Upscaler:
|
||||
self.preserve_frames = False
|
||||
|
||||
# other internal members and signals
|
||||
self.stop_signal = False
|
||||
self.running = False
|
||||
self.total_frames_upscaled = 0
|
||||
self.total_frames = 0
|
||||
self.total_videos = 0
|
||||
self.total_processed = 0
|
||||
self.current_input_video = pathlib.Path()
|
||||
|
||||
def create_temp_directories(self):
|
||||
"""create temporary directories
|
||||
@@ -103,7 +104,7 @@ class Upscaler:
|
||||
if self.video2x_cache_directory.exists() and not self.video2x_cache_directory.is_dir():
|
||||
Avalon.error(_('Specified or default cache directory is a file/link'))
|
||||
raise FileExistsError('Specified or default cache directory is a file/link')
|
||||
|
||||
|
||||
# if cache directory doesn't exist, try creating it
|
||||
if not self.video2x_cache_directory.exists():
|
||||
try:
|
||||
@@ -134,29 +135,47 @@ class Upscaler:
|
||||
traceback.print_exc()
|
||||
|
||||
def _check_arguments(self):
|
||||
if isinstance(self.input, list):
|
||||
if self.output.exists() and not self.output.is_dir():
|
||||
Avalon.error(_('Input and output path type mismatch'))
|
||||
Avalon.error(_('Input is multiple files but output is not directory'))
|
||||
raise ArgumentError('input output path type mismatch')
|
||||
for input_path in self.input:
|
||||
if not input_path.is_file() and not input_path.is_dir():
|
||||
Avalon.error(_('Input path {} is neither a file nor a directory').format(input_path))
|
||||
raise FileNotFoundError(f'{input_path} is neither file nor directory')
|
||||
with contextlib.suppress(FileNotFoundError):
|
||||
if input_path.samefile(self.output):
|
||||
Avalon.error(_('Input directory and output directory cannot be the same'))
|
||||
raise FileExistsError('input directory and output directory are the same')
|
||||
|
||||
# if input is a file
|
||||
if self.input_path.is_file():
|
||||
if self.output_path.is_dir():
|
||||
elif self.input.is_file():
|
||||
if self.output.is_dir():
|
||||
Avalon.error(_('Input and output path type mismatch'))
|
||||
Avalon.error(_('Input is single file but output is directory'))
|
||||
raise ArgumentError('input output path type mismatch')
|
||||
if not re.search(r'.*\..*$', str(self.output_path)):
|
||||
if not re.search(r'.*\..*$', str(self.output)):
|
||||
Avalon.error(_('No suffix found in output file path'))
|
||||
Avalon.error(_('Suffix must be specified for FFmpeg'))
|
||||
raise ArgumentError('no output video suffix specified')
|
||||
|
||||
# if input is a directory
|
||||
elif self.input_path.is_dir():
|
||||
if self.output_path.is_file():
|
||||
elif self.input.is_dir():
|
||||
if self.output.is_file():
|
||||
Avalon.error(_('Input and output path type mismatch'))
|
||||
Avalon.error(_('Input is directory but output is existing single file'))
|
||||
raise ArgumentError('input output path type mismatch')
|
||||
with contextlib.suppress(FileNotFoundError):
|
||||
if self.input.samefile(self.output):
|
||||
Avalon.error(_('Input directory and output directory cannot be the same'))
|
||||
raise FileExistsError('input directory and output directory are the same')
|
||||
|
||||
# if input is neither
|
||||
else:
|
||||
Avalon.error(_('Input path is neither a file nor a directory'))
|
||||
raise FileNotFoundError(f'{self.input_path} is neither file nor directory')
|
||||
|
||||
raise FileNotFoundError(f'{self.input} is neither file nor directory')
|
||||
|
||||
# check Fmpeg settings
|
||||
ffmpeg_path = pathlib.Path(self.ffmpeg_settings['ffmpeg_path'])
|
||||
if not ((pathlib.Path(ffmpeg_path / 'ffmpeg.exe').is_file() and
|
||||
@@ -259,32 +278,32 @@ class Upscaler:
|
||||
# if the driver being used is waifu2x-caffe
|
||||
if self.driver == 'waifu2x_caffe':
|
||||
self.process_pool.append(driver.upscale(process_directory,
|
||||
self.upscaled_frames,
|
||||
self.scale_ratio,
|
||||
self.scale_width,
|
||||
self.scale_height,
|
||||
self.image_format,
|
||||
self.bit_depth))
|
||||
self.upscaled_frames,
|
||||
self.scale_ratio,
|
||||
self.scale_width,
|
||||
self.scale_height,
|
||||
self.image_format,
|
||||
self.bit_depth))
|
||||
|
||||
# if the driver being used is waifu2x-converter-cpp
|
||||
elif self.driver == 'waifu2x_converter_cpp':
|
||||
self.process_pool.append(driver.upscale(process_directory,
|
||||
self.upscaled_frames,
|
||||
self.scale_ratio,
|
||||
self.processes,
|
||||
self.image_format))
|
||||
self.upscaled_frames,
|
||||
self.scale_ratio,
|
||||
self.processes,
|
||||
self.image_format))
|
||||
|
||||
# if the driver being used is waifu2x-ncnn-vulkan
|
||||
elif self.driver == 'waifu2x_ncnn_vulkan':
|
||||
self.process_pool.append(driver.upscale(process_directory,
|
||||
self.upscaled_frames,
|
||||
self.scale_ratio))
|
||||
self.upscaled_frames,
|
||||
self.scale_ratio))
|
||||
|
||||
# if the driver being used is srmd_ncnn_vulkan
|
||||
elif self.driver == 'srmd_ncnn_vulkan':
|
||||
self.process_pool.append(driver.upscale(process_directory,
|
||||
self.upscaled_frames,
|
||||
self.scale_ratio))
|
||||
self.upscaled_frames,
|
||||
self.scale_ratio))
|
||||
|
||||
# start progress bar in a different thread
|
||||
Avalon.debug_info(_('Starting progress monitor'))
|
||||
@@ -305,7 +324,7 @@ class Upscaler:
|
||||
self.progress_monitor.stop()
|
||||
|
||||
Avalon.debug_info(_('Killing upscaled image cleaner'))
|
||||
self.image_cleaner.stop()
|
||||
self.image_cleaner.stop()
|
||||
raise e
|
||||
|
||||
# if the driver is waifu2x-converter-cpp
|
||||
@@ -337,9 +356,9 @@ class Upscaler:
|
||||
try:
|
||||
# while process pool not empty
|
||||
while self.process_pool:
|
||||
|
||||
|
||||
# if stop signal received, terminate all processes
|
||||
if self.stop_signal is True:
|
||||
if self.running is False:
|
||||
raise SystemExit
|
||||
|
||||
for process in self.process_pool:
|
||||
@@ -376,9 +395,9 @@ class Upscaler:
|
||||
This function controls the flow of video conversion
|
||||
and handles all necessary functions.
|
||||
"""
|
||||
|
||||
|
||||
# external stop signal when called in a thread
|
||||
self.stop_signal = False
|
||||
self.running = True
|
||||
|
||||
# define process pool to contain processes
|
||||
self.process_pool = []
|
||||
@@ -388,24 +407,43 @@ class Upscaler:
|
||||
self._check_arguments()
|
||||
|
||||
# define processing queue
|
||||
processing_queue = queue.Queue()
|
||||
self.processing_queue = queue.Queue()
|
||||
|
||||
# if input is a list of files
|
||||
if isinstance(self.input, list):
|
||||
# make output directory if it doesn't exist
|
||||
self.output.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
for input_path in self.input:
|
||||
|
||||
if input_path.is_file():
|
||||
output_video = self.output / input_path.name
|
||||
self.processing_queue.put((input_path.absolute(), output_video.absolute()))
|
||||
|
||||
elif input_path.is_dir():
|
||||
for input_video in [f for f in input_path.iterdir() if f.is_file()]:
|
||||
output_video = self.output / input_video.name
|
||||
self.processing_queue.put((input_video.absolute(), output_video.absolute()))
|
||||
|
||||
# if input specified is single file
|
||||
if self.input_path.is_file():
|
||||
Avalon.info(_('Upscaling single video file: {}').format(self.input_path))
|
||||
processing_queue.put((self.input_path.absolute(), self.output_path.absolute()))
|
||||
elif self.input.is_file():
|
||||
Avalon.info(_('Upscaling single video file: {}').format(self.input))
|
||||
self.processing_queue.put((self.input.absolute(), self.output.absolute()))
|
||||
|
||||
# if input specified is a directory
|
||||
elif self.input_path.is_dir():
|
||||
elif self.input.is_dir():
|
||||
|
||||
# make output directory if it doesn't exist
|
||||
self.output_path.mkdir(parents=True, exist_ok=True)
|
||||
for input_video in [f for f in self.input_path.iterdir() if f.is_file()]:
|
||||
output_video = self.output_path / input_video.name
|
||||
processing_queue.put((input_video.absolute(), output_video.absolute()))
|
||||
self.output.mkdir(parents=True, exist_ok=True)
|
||||
for input_video in [f for f in self.input.iterdir() if f.is_file()]:
|
||||
output_video = self.output / input_video.name
|
||||
self.processing_queue.put((input_video.absolute(), output_video.absolute()))
|
||||
|
||||
while not processing_queue.empty():
|
||||
input_video, output_video = processing_queue.get()
|
||||
# record video count for external calls
|
||||
self.total_videos = self.processing_queue.qsize()
|
||||
|
||||
while not self.processing_queue.empty():
|
||||
self.current_input_video, output_video = self.processing_queue.get()
|
||||
# drivers that have native support for video processing
|
||||
if self.driver == 'anime4kcpp':
|
||||
# append FFmpeg path to the end of PATH
|
||||
@@ -418,7 +456,7 @@ class Upscaler:
|
||||
driver = DriverWrapperMain(copy.deepcopy(self.driver_settings))
|
||||
|
||||
# run Anime4KCPP
|
||||
self.process_pool.append(driver.upscale(input_video, output_video, self.scale_ratio, self.processes))
|
||||
self.process_pool.append(driver.upscale(self.current_input_video, output_video, self.scale_ratio, self.processes))
|
||||
self._wait()
|
||||
Avalon.info(_('Upscaling completed'))
|
||||
|
||||
@@ -430,8 +468,8 @@ class Upscaler:
|
||||
fm = Ffmpeg(self.ffmpeg_settings, self.image_format)
|
||||
|
||||
Avalon.info(_('Reading video information'))
|
||||
video_info = fm.get_video_info(input_video)
|
||||
# analyze original video with ffprobe and retrieve framerate
|
||||
video_info = fm.get_video_info(self.current_input_video)
|
||||
# analyze original video with FFprobe and retrieve framerate
|
||||
# width, height = info['streams'][0]['width'], info['streams'][0]['height']
|
||||
|
||||
# find index of video stream
|
||||
@@ -447,7 +485,7 @@ class Upscaler:
|
||||
raise StreamNotFoundError('no video stream found')
|
||||
|
||||
# extract frames from video
|
||||
self.process_pool.append((fm.extract_frames(input_video, self.extracted_frames)))
|
||||
self.process_pool.append((fm.extract_frames(self.current_input_video, self.extracted_frames)))
|
||||
self._wait()
|
||||
|
||||
# get average frame rate of video stream
|
||||
@@ -488,7 +526,7 @@ class Upscaler:
|
||||
|
||||
# migrate audio tracks and subtitles
|
||||
Avalon.info(_('Migrating audio tracks and subtitles to upscaled video'))
|
||||
self.process_pool.append(fm.migrate_audio_tracks_subtitles(input_video, output_video, self.upscaled_frames))
|
||||
self.process_pool.append(fm.migrate_audio_tracks_subtitles(self.current_input_video, output_video, self.upscaled_frames))
|
||||
self._wait()
|
||||
|
||||
# destroy temp directories
|
||||
@@ -498,3 +536,9 @@ class Upscaler:
|
||||
with contextlib.suppress(ValueError):
|
||||
self.cleanup_temp_directories()
|
||||
raise e
|
||||
|
||||
# increment total number of videos processed
|
||||
self.total_processed += 1
|
||||
|
||||
# signal upscaling completion
|
||||
self.running = False
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Name: Video2X Configuration File
|
||||
# Creator: K4YT3X
|
||||
# Date Created: October 23, 2018
|
||||
# Last Modified: May 7, 2020
|
||||
# Last Modified: May 8, 2020
|
||||
# Items commented out are parameters handled by Video2x.
|
||||
waifu2x_caffe:
|
||||
path: '%LOCALAPPDATA%\video2x\waifu2x-caffe\waifu2x-caffe-cui'
|
||||
@@ -31,13 +31,13 @@ waifu2x_converter_cpp:
|
||||
#list-processor # dump processor list
|
||||
output-format: null # The format used when running in recursive/folder mode
|
||||
png-compression: 5 # Set PNG compression level (0-9), 9 = Max compression (slowest & smallest)
|
||||
image-quality: -1 # JPEG & WebP Compression quality (0-101, 0 being smallest size and lowest quality), use 101 for lossless WebP
|
||||
image-quality: -1 # JPEG & WebP Compression quality (-1-101, 0 being smallest size and lowest quality, -1 being default), use 101 for lossless WebP
|
||||
block-size: 0 # block size
|
||||
disable-gpu: false # disable GPU
|
||||
force-OpenCL: false # force to use OpenCL on Intel Platform
|
||||
processor: -1 # set target processor
|
||||
processor: -1 # set target processor (-1 uses default device)
|
||||
jobs: 0 # number of threads launching at the same time
|
||||
model-dir: null # path to custom model directory (don't append last / ) default: models_rgb
|
||||
model-dir: null # path to custom model directory (don't append last / ) default: models_rgb
|
||||
#scale-ratio: 2.0 # custom scale ratio
|
||||
noise-level: 1 # <0|1|2|3> noise reduction level
|
||||
mode: noise-scale # <noise|scale|noise-scale> image processing mode
|
||||
@@ -97,12 +97,16 @@ anime4kcpp:
|
||||
codec: mp4v # Specify the codec for encoding from mp4v(recommended in Windows), dxva(for Windows), avc1(H264, recommended in Linux), vp09(very slow), hevc(not support in Windowds), av01(not support in Windowds) (string [=mp4v])
|
||||
ffmpeg:
|
||||
ffmpeg_path: '%LOCALAPPDATA%\video2x\ffmpeg-latest-win64-static\bin'
|
||||
# step 1: extract all frames from original video
|
||||
# into temporary directory
|
||||
video_to_frames:
|
||||
output_options:
|
||||
'-qscale:v': null
|
||||
'-pix_fmt': rgba64be
|
||||
'-hwaccel': auto
|
||||
'-y': true
|
||||
# step 2: stitch all frames back into a video
|
||||
# with only a video track
|
||||
frames_to_video:
|
||||
input_options:
|
||||
'-qscale:v': null
|
||||
@@ -115,6 +119,8 @@ ffmpeg:
|
||||
'-pix_fmt': null
|
||||
'-hwaccel': auto
|
||||
'-y': true
|
||||
# step 3: migrate audio and subtitle tracks from original
|
||||
# video into the upscaled video
|
||||
migrating_tracks:
|
||||
output_options:
|
||||
'-map':
|
||||
@@ -125,6 +131,7 @@ ffmpeg:
|
||||
- '1:t?'
|
||||
'-c': copy
|
||||
'-pix_fmt': null
|
||||
'-metadata': 'comment=Upscaled by Video2X'
|
||||
'-hwaccel': auto
|
||||
'-y': true
|
||||
video2x:
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Creator: Video2X QT
|
||||
Creator: Video2X GUI
|
||||
Author: K4YT3X
|
||||
Date Created: May 5, 2020
|
||||
Last Modified: May 6, 2020
|
||||
Last Modified: May 8, 2020
|
||||
"""
|
||||
|
||||
# local imports
|
||||
@@ -14,7 +14,6 @@ from upscaler import Upscaler
|
||||
import contextlib
|
||||
import os
|
||||
import pathlib
|
||||
import re
|
||||
import sys
|
||||
import tempfile
|
||||
import time
|
||||
@@ -22,9 +21,10 @@ import traceback
|
||||
import yaml
|
||||
|
||||
# third-party imports
|
||||
from PyQt5 import QtWidgets, QtGui
|
||||
from PyQt5 import uic
|
||||
from PyQt5.QtCore import QObject, pyqtSlot, pyqtSignal, QRunnable, QThreadPool
|
||||
from PyQt5 import QtGui, uic
|
||||
from PyQt5.QtCore import *
|
||||
from PyQt5.QtWidgets import *
|
||||
# QObject, pyqtSlot, pyqtSignal, QRunnable, QThreadPool, QAbstractTableModel, Qt
|
||||
|
||||
VERSION = '2.0.0'
|
||||
|
||||
@@ -42,6 +42,7 @@ AVAILABLE_DRIVERS = {
|
||||
'Anime4KCPP': 'anime4kcpp'
|
||||
}
|
||||
|
||||
|
||||
def resource_path(relative_path: str) -> pathlib.Path:
|
||||
try:
|
||||
base_path = pathlib.Path(sys._MEIPASS)
|
||||
@@ -52,13 +53,14 @@ def resource_path(relative_path: str) -> pathlib.Path:
|
||||
|
||||
class WorkerSignals(QObject):
|
||||
progress = pyqtSignal(tuple)
|
||||
error = pyqtSignal(str)
|
||||
error = pyqtSignal(Exception)
|
||||
interrupted = pyqtSignal()
|
||||
finished = pyqtSignal()
|
||||
|
||||
class ProgressBarWorker(QRunnable):
|
||||
|
||||
class ProgressMonitorWorkder(QRunnable):
|
||||
def __init__(self, fn, *args, **kwargs):
|
||||
super(ProgressBarWorker, self).__init__()
|
||||
super(ProgressMonitorWorkder, self).__init__()
|
||||
self.fn = fn
|
||||
self.args = args
|
||||
self.kwargs = kwargs
|
||||
@@ -72,6 +74,7 @@ class ProgressBarWorker(QRunnable):
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
|
||||
class UpscalerWorker(QRunnable):
|
||||
|
||||
def __init__(self, fn, *args, **kwargs):
|
||||
@@ -91,144 +94,241 @@ class UpscalerWorker(QRunnable):
|
||||
self.fn(*self.args, **self.kwargs)
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
self.signals.interrupted.emit()
|
||||
except Exception:
|
||||
error_message = traceback.format_exc()
|
||||
print(error_message, file=sys.stderr)
|
||||
self.signals.error.emit(error_message)
|
||||
except Exception as e:
|
||||
traceback.print_exc()
|
||||
self.signals.error.emit(e)
|
||||
else:
|
||||
self.signals.finished.emit()
|
||||
|
||||
class Video2XMainWindow(QtWidgets.QMainWindow):
|
||||
|
||||
class InputTableModel(QAbstractTableModel):
|
||||
def __init__(self, data):
|
||||
super(InputTableModel, self).__init__()
|
||||
self._data = data
|
||||
|
||||
def data(self, index, role):
|
||||
if role == Qt.DisplayRole:
|
||||
|
||||
if index.column() == 0:
|
||||
return str(self._data[index.row()].absolute())
|
||||
else:
|
||||
if self._data[index.row()].is_file():
|
||||
return 'File'
|
||||
elif self._data[index.row()].is_dir():
|
||||
return 'Folder'
|
||||
else:
|
||||
return 'Unknown'
|
||||
|
||||
def rowCount(self, index):
|
||||
return len(self._data)
|
||||
|
||||
def columnCount(self, index):
|
||||
return 2
|
||||
|
||||
def removeRow(self, index):
|
||||
self._data.pop(index)
|
||||
|
||||
def headerData(self, section, orientation, role):
|
||||
# section is the index of the column/row.
|
||||
if role != Qt.DisplayRole:
|
||||
return None
|
||||
|
||||
horizontal_headers = ['File Path', 'Type']
|
||||
|
||||
# return the correspondign header
|
||||
if orientation == Qt.Horizontal:
|
||||
return horizontal_headers[section]
|
||||
|
||||
# simply return the line number
|
||||
if orientation == Qt.Vertical:
|
||||
return str(section)
|
||||
|
||||
|
||||
class Video2XMainWindow(QMainWindow):
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
uic.loadUi(str(resource_path('video2x_gui.ui')), self)
|
||||
|
||||
# create thread pool for upscaler workers
|
||||
self.threadpool = QThreadPool()
|
||||
|
||||
# set window title and icon
|
||||
self.video2x_icon_path = str(resource_path('images/video2x.png'))
|
||||
self.setWindowTitle(f'Video2X GUI {VERSION}')
|
||||
self.setWindowIcon(QtGui.QIcon(self.video2x_icon_path))
|
||||
|
||||
# menu bar
|
||||
self.action_exit = self.findChild(QtWidgets.QAction, 'actionExit')
|
||||
self.action_exit = self.findChild(QAction, 'actionExit')
|
||||
self.action_exit.triggered.connect(sys.exit)
|
||||
|
||||
self.action_about = self.findChild(QtWidgets.QAction, 'actionAbout')
|
||||
self.action_about.triggered.connect(lambda: self.show_message(LEGAL_INFO, custom_icon=QtGui.QPixmap(self.video2x_icon_path)))
|
||||
self.action_about = self.findChild(QAction, 'actionAbout')
|
||||
self.action_about.triggered.connect(self.show_about)
|
||||
|
||||
# main tab
|
||||
# select input file/folder
|
||||
self.input_line_edit = self.findChild(QtWidgets.QLineEdit, 'inputLineEdit')
|
||||
self.input_select_file_button = self.findChild(QtWidgets.QPushButton, 'inputSelectFileButton')
|
||||
self.input_select_file_button.clicked.connect(self.select_input_file)
|
||||
self.input_select_folder_button = self.findChild(QtWidgets.QPushButton, 'inputSelectFolderButton')
|
||||
self.input_select_folder_button.clicked.connect(self.select_input_folder)
|
||||
self.input_table_view = self.findChild(QTableView, 'inputTableView')
|
||||
self.input_table_view.dragEnterEvent = self.dragEnterEvent
|
||||
self.input_table_view.dropEvent = self.dropEvent
|
||||
|
||||
# initialize data in table
|
||||
self.input_table_data = []
|
||||
self.input_table_model = InputTableModel(self.input_table_data)
|
||||
self.input_table_view.setModel(self.input_table_model)
|
||||
# stretch file path and fill columns horizontally
|
||||
self.input_table_view.horizontalHeader().setSectionResizeMode(0, QHeaderView.Stretch)
|
||||
|
||||
# input table buttons
|
||||
self.input_select_file_button = self.findChild(QPushButton, 'inputSelectFileButton')
|
||||
self.input_select_file_button.clicked.connect(self.select_input_file)
|
||||
self.input_select_folder_button = self.findChild(QPushButton, 'inputSelectFolderButton')
|
||||
self.input_select_folder_button.clicked.connect(self.select_input_folder)
|
||||
self.input_delete_selected_button = self.findChild(QPushButton, 'inputDeleteSelectedButton')
|
||||
self.input_delete_selected_button.clicked.connect(self.input_table_delete_selected)
|
||||
self.input_clear_all_button = self.findChild(QPushButton, 'inputClearAllButton')
|
||||
self.input_clear_all_button.clicked.connect(self.input_table_clear_all)
|
||||
|
||||
# other paths selection
|
||||
# select output file/folder
|
||||
self.output_line_edit = self.findChild(QtWidgets.QLineEdit, 'outputLineEdit')
|
||||
self.output_select_file_button = self.findChild(QtWidgets.QPushButton, 'outputSelectFileButton')
|
||||
self.output_line_edit = self.findChild(QLineEdit, 'outputLineEdit')
|
||||
self.enable_line_edit_file_drop(self.output_line_edit)
|
||||
self.output_line_edit.setText(str((pathlib.Path().cwd() / 'output').absolute()))
|
||||
self.output_select_file_button = self.findChild(QPushButton, 'outputSelectFileButton')
|
||||
self.output_select_file_button.clicked.connect(self.select_output_file)
|
||||
self.output_select_folder_button = self.findChild(QtWidgets.QPushButton, 'outputSelectFolderButton')
|
||||
self.output_select_folder_button = self.findChild(QPushButton, 'outputSelectFolderButton')
|
||||
self.output_select_folder_button.clicked.connect(self.select_output_folder)
|
||||
|
||||
# config file
|
||||
self.config_line_edit = self.findChild(QtWidgets.QLineEdit, 'configLineEdit')
|
||||
self.config_line_edit = self.findChild(QLineEdit, 'configLineEdit')
|
||||
self.enable_line_edit_file_drop(self.config_line_edit)
|
||||
self.config_line_edit.setText(str((pathlib.Path(__file__).parent / 'video2x.yaml').absolute()))
|
||||
self.config_select_file_button = self.findChild(QtWidgets.QPushButton, 'configSelectButton')
|
||||
self.config_select_file_button = self.findChild(QPushButton, 'configSelectButton')
|
||||
self.config_select_file_button.clicked.connect(self.select_config_file)
|
||||
|
||||
# cache directory
|
||||
self.cache_line_edit = self.findChild(QtWidgets.QLineEdit, 'cacheLineEdit')
|
||||
self.cache_select_folder_button = self.findChild(QtWidgets.QPushButton, 'cacheSelectFolderButton')
|
||||
self.cache_line_edit = self.findChild(QLineEdit, 'cacheLineEdit')
|
||||
self.enable_line_edit_file_drop(self.cache_line_edit)
|
||||
self.cache_select_folder_button = self.findChild(QPushButton, 'cacheSelectFolderButton')
|
||||
self.cache_select_folder_button.clicked.connect(self.select_cache_folder)
|
||||
|
||||
# express settings
|
||||
self.driver_combo_box = self.findChild(QtWidgets.QComboBox, 'driverComboBox')
|
||||
self.driver_combo_box = self.findChild(QComboBox, 'driverComboBox')
|
||||
self.driver_combo_box.currentTextChanged.connect(self.update_gui_for_driver)
|
||||
self.processes_spin_box = self.findChild(QtWidgets.QSpinBox, 'processesSpinBox')
|
||||
self.scale_ratio_double_spin_box = self.findChild(QtWidgets.QDoubleSpinBox, 'scaleRatioDoubleSpinBox')
|
||||
self.preserve_frames_check_box = self.findChild(QtWidgets.QCheckBox, 'preserveFramesCheckBox')
|
||||
self.processes_spin_box = self.findChild(QSpinBox, 'processesSpinBox')
|
||||
self.scale_ratio_double_spin_box = self.findChild(QDoubleSpinBox, 'scaleRatioDoubleSpinBox')
|
||||
self.preserve_frames_check_box = self.findChild(QCheckBox, 'preserveFramesCheckBox')
|
||||
|
||||
# progress bar and start/stop controls
|
||||
self.progress_bar = self.findChild(QtWidgets.QProgressBar, 'progressBar')
|
||||
self.time_elapsed_label = self.findChild(QtWidgets.QLabel, 'timeElapsedLabel')
|
||||
self.time_remaining_label = self.findChild(QtWidgets.QLabel, 'timeRemainingLabel')
|
||||
self.rate_label = self.findChild(QtWidgets.QLabel, 'rateLabel')
|
||||
self.start_button = self.findChild(QtWidgets.QPushButton, 'startButton')
|
||||
# currently processing
|
||||
self.currently_processing_label = self.findChild(QLabel, 'currentlyProcessingLabel')
|
||||
self.current_progress_bar = self.findChild(QProgressBar, 'currentProgressBar')
|
||||
self.time_elapsed_label = self.findChild(QLabel, 'timeElapsedLabel')
|
||||
self.time_remaining_label = self.findChild(QLabel, 'timeRemainingLabel')
|
||||
self.rate_label = self.findChild(QLabel, 'rateLabel')
|
||||
self.frames_label = self.findChild(QLabel, 'framesLabel')
|
||||
|
||||
# overall progress
|
||||
self.overall_progress_bar = self.findChild(QProgressBar, 'overallProgressBar')
|
||||
self.overall_progress_label = self.findChild(QLabel, 'overallProgressLabel')
|
||||
self.start_button = self.findChild(QPushButton, 'startButton')
|
||||
self.start_button.clicked.connect(self.start)
|
||||
self.stop_button = self.findChild(QtWidgets.QPushButton, 'stopButton')
|
||||
self.stop_button = self.findChild(QPushButton, 'stopButton')
|
||||
self.stop_button.clicked.connect(self.stop)
|
||||
|
||||
# driver settings
|
||||
# waifu2x-caffe
|
||||
self.waifu2x_caffe_path_line_edit = self.findChild(QtWidgets.QLineEdit, 'waifu2xCaffePathLineEdit')
|
||||
self.waifu2x_caffe_path_select_button = self.findChild(QtWidgets.QPushButton, 'waifu2xCaffePathSelectButton')
|
||||
self.waifu2x_caffe_path_line_edit = self.findChild(QLineEdit, 'waifu2xCaffePathLineEdit')
|
||||
self.enable_line_edit_file_drop(self.waifu2x_caffe_path_line_edit)
|
||||
self.waifu2x_caffe_path_select_button = self.findChild(QPushButton, 'waifu2xCaffePathSelectButton')
|
||||
self.waifu2x_caffe_path_select_button.clicked.connect(lambda: self.select_driver_binary_path(self.waifu2x_caffe_path_line_edit))
|
||||
self.waifu2x_caffe_mode_combo_box = self.findChild(QtWidgets.QComboBox, 'waifu2xCaffeModeComboBox')
|
||||
self.waifu2x_caffe_noise_level_spin_box = self.findChild(QtWidgets.QSpinBox, 'waifu2xCaffeNoiseLevelSpinBox')
|
||||
self.waifu2x_caffe_process_combo_box = self.findChild(QtWidgets.QComboBox, 'waifu2xCaffeProcessComboBox')
|
||||
self.waifu2x_caffe_model_combobox = self.findChild(QtWidgets.QComboBox, 'waifu2xCaffeModelComboBox')
|
||||
self.waifu2x_caffe_crop_size_spin_box = self.findChild(QtWidgets.QSpinBox, 'waifu2xCaffeCropSizeSpinBox')
|
||||
self.waifu2x_caffe_output_quality_spin_box = self.findChild(QtWidgets.QSpinBox, 'waifu2xCaffeOutputQualitySpinBox')
|
||||
self.waifu2x_caffe_output_depth_spin_box = self.findChild(QtWidgets.QSpinBox, 'waifu2xCaffeOutputDepthSpinBox')
|
||||
self.waifu2x_caffe_batch_size_spin_box = self.findChild(QtWidgets.QSpinBox, 'waifu2xCaffeBatchSizeSpinBox')
|
||||
self.waifu2x_caffe_gpu_spin_box = self.findChild(QtWidgets.QSpinBox, 'waifu2xCaffeGpuSpinBox')
|
||||
self.waifu2x_caffe_tta_check_box = self.findChild(QtWidgets.QCheckBox, 'waifu2xCaffeTtaCheckBox')
|
||||
self.waifu2x_caffe_mode_combo_box = self.findChild(QComboBox, 'waifu2xCaffeModeComboBox')
|
||||
self.waifu2x_caffe_noise_level_spin_box = self.findChild(QSpinBox, 'waifu2xCaffeNoiseLevelSpinBox')
|
||||
self.waifu2x_caffe_process_combo_box = self.findChild(QComboBox, 'waifu2xCaffeProcessComboBox')
|
||||
self.waifu2x_caffe_model_combobox = self.findChild(QComboBox, 'waifu2xCaffeModelComboBox')
|
||||
self.waifu2x_caffe_crop_size_spin_box = self.findChild(QSpinBox, 'waifu2xCaffeCropSizeSpinBox')
|
||||
self.waifu2x_caffe_output_quality_spin_box = self.findChild(QSpinBox, 'waifu2xCaffeOutputQualitySpinBox')
|
||||
self.waifu2x_caffe_output_depth_spin_box = self.findChild(QSpinBox, 'waifu2xCaffeOutputDepthSpinBox')
|
||||
self.waifu2x_caffe_batch_size_spin_box = self.findChild(QSpinBox, 'waifu2xCaffeBatchSizeSpinBox')
|
||||
self.waifu2x_caffe_gpu_spin_box = self.findChild(QSpinBox, 'waifu2xCaffeGpuSpinBox')
|
||||
self.waifu2x_caffe_tta_check_box = self.findChild(QCheckBox, 'waifu2xCaffeTtaCheckBox')
|
||||
|
||||
# waifu2x-converter-cpp
|
||||
self.waifu2x_converter_cpp_path_line_edit = self.findChild(QtWidgets.QLineEdit, 'waifu2xConverterCppPathLineEdit')
|
||||
self.waifu2x_converter_cpp_path_edit_button = self.findChild(QtWidgets.QPushButton, 'waifu2xConverterCppPathSelectButton')
|
||||
self.waifu2x_converter_cpp_path_line_edit = self.findChild(QLineEdit, 'waifu2xConverterCppPathLineEdit')
|
||||
self.enable_line_edit_file_drop(self.waifu2x_converter_cpp_path_line_edit)
|
||||
self.waifu2x_converter_cpp_path_edit_button = self.findChild(QPushButton, 'waifu2xConverterCppPathSelectButton')
|
||||
self.waifu2x_converter_cpp_path_edit_button.clicked.connect(lambda: self.select_driver_binary_path(self.waifu2x_converter_cpp_path_line_edit))
|
||||
self.waifu2x_converter_cpp_png_compression_spin_box = self.findChild(QtWidgets.QSpinBox, 'waifu2xConverterCppPngCompressionSpinBox')
|
||||
self.waifu2x_converter_cpp_processor_spin_box = self.findChild(QtWidgets.QSpinBox, 'waifu2xConverterCppProcessorSpinBox')
|
||||
self.waifu2x_converter_cpp_model_combo_box = self.findChild(QtWidgets.QComboBox, 'waifu2xConverterCppModelComboBox')
|
||||
self.waifu2x_converter_cpp_mode_combo_box = self.findChild(QtWidgets.QComboBox, 'waifu2xConverterCppModeComboBox')
|
||||
self.waifu2x_converter_cpp_disable_gpu_check_box = self.findChild(QtWidgets.QCheckBox, 'disableGpuCheckBox')
|
||||
self.waifu2x_converter_cpp_tta_check_box = self.findChild(QtWidgets.QCheckBox, 'ttaCheckBox')
|
||||
self.waifu2x_converter_cpp_png_compression_spin_box = self.findChild(QSpinBox, 'waifu2xConverterCppPngCompressionSpinBox')
|
||||
self.waifu2x_converter_cpp_processor_spin_box = self.findChild(QSpinBox, 'waifu2xConverterCppProcessorSpinBox')
|
||||
self.waifu2x_converter_cpp_model_combo_box = self.findChild(QComboBox, 'waifu2xConverterCppModelComboBox')
|
||||
self.waifu2x_converter_cpp_mode_combo_box = self.findChild(QComboBox, 'waifu2xConverterCppModeComboBox')
|
||||
self.waifu2x_converter_cpp_disable_gpu_check_box = self.findChild(QCheckBox, 'disableGpuCheckBox')
|
||||
self.waifu2x_converter_cpp_tta_check_box = self.findChild(QCheckBox, 'ttaCheckBox')
|
||||
|
||||
# waifu2x-ncnn-vulkan
|
||||
self.waifu2x_ncnn_vulkan_path_line_edit = self.findChild(QtWidgets.QLineEdit, 'waifu2xNcnnVulkanPathLineEdit')
|
||||
self.waifu2x_ncnn_vulkan_path_select_button = self.findChild(QtWidgets.QPushButton, 'waifu2xNcnnVulkanPathSelectButton')
|
||||
self.waifu2x_ncnn_vulkan_path_line_edit = self.findChild(QLineEdit, 'waifu2xNcnnVulkanPathLineEdit')
|
||||
self.enable_line_edit_file_drop(self.waifu2x_ncnn_vulkan_path_line_edit)
|
||||
self.waifu2x_ncnn_vulkan_path_select_button = self.findChild(QPushButton, 'waifu2xNcnnVulkanPathSelectButton')
|
||||
self.waifu2x_ncnn_vulkan_path_select_button.clicked.connect(lambda: self.select_driver_binary_path(self.waifu2x_ncnn_vulkan_path_line_edit))
|
||||
self.waifu2x_ncnn_vulkan_noise_level_spin_box = self.findChild(QtWidgets.QSpinBox, 'waifu2xNcnnVulkanNoiseLevelSpinBox')
|
||||
self.waifu2x_ncnn_vulkan_tile_size_spin_box = self.findChild(QtWidgets.QSpinBox, 'waifu2xNcnnVulkanTileSizeSpinBox')
|
||||
self.waifu2x_ncnn_vulkan_model_combo_box = self.findChild(QtWidgets.QComboBox, 'waifu2xNcnnVulkanModelComboBox')
|
||||
self.waifu2x_ncnn_vulkan_gpu_id_spin_box = self.findChild(QtWidgets.QSpinBox, 'waifu2xNcnnVulkanGpuIdSpinBox')
|
||||
self.waifu2x_ncnn_vulkan_jobs_line_edit = self.findChild(QtWidgets.QLineEdit, 'waifu2xNcnnVulkanJobsLineEdit')
|
||||
self.waifu2x_ncnn_vulkan_tta_check_box = self.findChild(QtWidgets.QCheckBox, 'waifu2xNcnnVulkanTtaCheckBox')
|
||||
self.waifu2x_ncnn_vulkan_noise_level_spin_box = self.findChild(QSpinBox, 'waifu2xNcnnVulkanNoiseLevelSpinBox')
|
||||
self.waifu2x_ncnn_vulkan_tile_size_spin_box = self.findChild(QSpinBox, 'waifu2xNcnnVulkanTileSizeSpinBox')
|
||||
self.waifu2x_ncnn_vulkan_model_combo_box = self.findChild(QComboBox, 'waifu2xNcnnVulkanModelComboBox')
|
||||
self.waifu2x_ncnn_vulkan_gpu_id_spin_box = self.findChild(QSpinBox, 'waifu2xNcnnVulkanGpuIdSpinBox')
|
||||
self.waifu2x_ncnn_vulkan_jobs_line_edit = self.findChild(QLineEdit, 'waifu2xNcnnVulkanJobsLineEdit')
|
||||
self.waifu2x_ncnn_vulkan_tta_check_box = self.findChild(QCheckBox, 'waifu2xNcnnVulkanTtaCheckBox')
|
||||
|
||||
# srmd-ncnn-vulkan
|
||||
self.srmd_ncnn_vulkan_path_line_edit = self.findChild(QtWidgets.QLineEdit, 'srmdNcnnVulkanPathLineEdit')
|
||||
self.srmd_ncnn_vulkan_path_select_button = self.findChild(QtWidgets.QPushButton, 'srmdNcnnVulkanPathSelectButton')
|
||||
self.srmd_ncnn_vulkan_path_line_edit = self.findChild(QLineEdit, 'srmdNcnnVulkanPathLineEdit')
|
||||
self.enable_line_edit_file_drop(self.srmd_ncnn_vulkan_path_line_edit)
|
||||
self.srmd_ncnn_vulkan_path_select_button = self.findChild(QPushButton, 'srmdNcnnVulkanPathSelectButton')
|
||||
self.srmd_ncnn_vulkan_path_select_button.clicked.connect(lambda: self.select_driver_binary_path(self.srmd_ncnn_vulkan_path_line_edit))
|
||||
self.srmd_ncnn_vulkan_noise_level_spin_box = self.findChild(QtWidgets.QSpinBox, 'srmdNcnnVulkanNoiseLevelSpinBox')
|
||||
self.srmd_ncnn_vulkan_tile_size_spin_box = self.findChild(QtWidgets.QSpinBox, 'srmdNcnnVulkanTileSizeSpinBox')
|
||||
self.srmd_ncnn_vulkan_model_combo_box = self.findChild(QtWidgets.QComboBox, 'srmdNcnnVulkanModelComboBox')
|
||||
self.srmd_ncnn_vulkan_gpu_id_spin_box = self.findChild(QtWidgets.QSpinBox, 'srmdNcnnVulkanGpuIdSpinBox')
|
||||
self.srmd_ncnn_vulkan_jobs_line_edit = self.findChild(QtWidgets.QLineEdit, 'srmdNcnnVulkanJobsLineEdit')
|
||||
self.srmd_ncnn_vulkan_tta_check_box = self.findChild(QtWidgets.QCheckBox, 'srmdNcnnVulkanTtaCheckBox')
|
||||
self.srmd_ncnn_vulkan_noise_level_spin_box = self.findChild(QSpinBox, 'srmdNcnnVulkanNoiseLevelSpinBox')
|
||||
self.srmd_ncnn_vulkan_tile_size_spin_box = self.findChild(QSpinBox, 'srmdNcnnVulkanTileSizeSpinBox')
|
||||
self.srmd_ncnn_vulkan_model_combo_box = self.findChild(QComboBox, 'srmdNcnnVulkanModelComboBox')
|
||||
self.srmd_ncnn_vulkan_gpu_id_spin_box = self.findChild(QSpinBox, 'srmdNcnnVulkanGpuIdSpinBox')
|
||||
self.srmd_ncnn_vulkan_jobs_line_edit = self.findChild(QLineEdit, 'srmdNcnnVulkanJobsLineEdit')
|
||||
self.srmd_ncnn_vulkan_tta_check_box = self.findChild(QCheckBox, 'srmdNcnnVulkanTtaCheckBox')
|
||||
|
||||
# anime4k
|
||||
self.anime4kcpp_path_line_edit = self.findChild(QtWidgets.QLineEdit, 'anime4kCppPathLineEdit')
|
||||
self.anime4kcpp_path_select_button = self.findChild(QtWidgets.QPushButton, 'anime4kCppPathSelectButton')
|
||||
self.anime4kcpp_path_line_edit = self.findChild(QLineEdit, 'anime4kCppPathLineEdit')
|
||||
self.enable_line_edit_file_drop(self.anime4kcpp_path_line_edit)
|
||||
self.anime4kcpp_path_select_button = self.findChild(QPushButton, 'anime4kCppPathSelectButton')
|
||||
self.anime4kcpp_path_select_button.clicked.connect(lambda: self.select_driver_binary_path(self.anime4kcpp_path_line_edit))
|
||||
self.anime4kcpp_passes_spin_box = self.findChild(QtWidgets.QSpinBox, 'anime4kCppPassesSpinBox')
|
||||
self.anime4kcpp_push_color_count_spin_box = self.findChild(QtWidgets.QSpinBox, 'anime4kCppPushColorCountSpinBox')
|
||||
self.anime4kcpp_strength_color_spin_box = self.findChild(QtWidgets.QDoubleSpinBox, 'anime4kCppStrengthColorSpinBox')
|
||||
self.anime4kcpp_strength_gradient_spin_box = self.findChild(QtWidgets.QDoubleSpinBox, 'anime4kCppStrengthGradientSpinBox')
|
||||
self.anime4kcpp_threads_spin_box = self.findChild(QtWidgets.QSpinBox, 'anime4kCppThreadsSpinBox')
|
||||
self.anime4kcpp_pre_filters_spin_box = self.findChild(QtWidgets.QSpinBox, 'anime4kCppPreFiltersSpinBox')
|
||||
self.anime4kcpp_post_filters_spin_box = self.findChild(QtWidgets.QSpinBox, 'anime4kCppPostFiltersSpinBox')
|
||||
self.anime4kcpp_platform_id_spin_box = self.findChild(QtWidgets.QSpinBox, 'anime4kCppPlatformIdSpinBox')
|
||||
self.anime4kcpp_device_id_spin_box = self.findChild(QtWidgets.QSpinBox, 'anime4kCppDeviceIdSpinBox')
|
||||
self.anime4kcpp_codec_combo_box = self.findChild(QtWidgets.QComboBox, 'anime4kCppCodecComboBox')
|
||||
self.anime4kcpp_fast_mode_check_box = self.findChild(QtWidgets.QCheckBox, 'anime4kCppFastModeCheckBox')
|
||||
self.anime4kcpp_pre_processing_check_box = self.findChild(QtWidgets.QCheckBox, 'anime4kCppPreProcessingCheckBox')
|
||||
self.anime4kcpp_post_processing_check_box = self.findChild(QtWidgets.QCheckBox, 'anime4kCppPostProcessingCheckBox')
|
||||
self.anime4kcpp_gpu_mode_check_box = self.findChild(QtWidgets.QCheckBox, 'anime4kCppGpuModeCheckBox')
|
||||
self.anime4kcpp_passes_spin_box = self.findChild(QSpinBox, 'anime4kCppPassesSpinBox')
|
||||
self.anime4kcpp_push_color_count_spin_box = self.findChild(QSpinBox, 'anime4kCppPushColorCountSpinBox')
|
||||
self.anime4kcpp_strength_color_spin_box = self.findChild(QDoubleSpinBox, 'anime4kCppStrengthColorSpinBox')
|
||||
self.anime4kcpp_strength_gradient_spin_box = self.findChild(QDoubleSpinBox, 'anime4kCppStrengthGradientSpinBox')
|
||||
self.anime4kcpp_threads_spin_box = self.findChild(QSpinBox, 'anime4kCppThreadsSpinBox')
|
||||
self.anime4kcpp_pre_filters_spin_box = self.findChild(QSpinBox, 'anime4kCppPreFiltersSpinBox')
|
||||
self.anime4kcpp_post_filters_spin_box = self.findChild(QSpinBox, 'anime4kCppPostFiltersSpinBox')
|
||||
self.anime4kcpp_platform_id_spin_box = self.findChild(QSpinBox, 'anime4kCppPlatformIdSpinBox')
|
||||
self.anime4kcpp_device_id_spin_box = self.findChild(QSpinBox, 'anime4kCppDeviceIdSpinBox')
|
||||
self.anime4kcpp_codec_combo_box = self.findChild(QComboBox, 'anime4kCppCodecComboBox')
|
||||
self.anime4kcpp_fast_mode_check_box = self.findChild(QCheckBox, 'anime4kCppFastModeCheckBox')
|
||||
self.anime4kcpp_pre_processing_check_box = self.findChild(QCheckBox, 'anime4kCppPreProcessingCheckBox')
|
||||
self.anime4kcpp_post_processing_check_box = self.findChild(QCheckBox, 'anime4kCppPostProcessingCheckBox')
|
||||
self.anime4kcpp_gpu_mode_check_box = self.findChild(QCheckBox, 'anime4kCppGpuModeCheckBox')
|
||||
|
||||
# load configurations
|
||||
self.load_configurations()
|
||||
|
||||
def dragEnterEvent(self, event):
|
||||
if event.mimeData().hasUrls():
|
||||
event.accept()
|
||||
else:
|
||||
event.ignore()
|
||||
|
||||
def dropEvent(self, event):
|
||||
input_paths = [pathlib.Path(u.toLocalFile()) for u in event.mimeData().urls()]
|
||||
for path in input_paths:
|
||||
if (path.is_file() or path.is_dir()) and not self.input_table_path_exists(path):
|
||||
self.input_table_data.append(path)
|
||||
|
||||
self.update_input_table()
|
||||
self.update_output_path()
|
||||
|
||||
def enable_line_edit_file_drop(self, line_edit: QLineEdit):
|
||||
line_edit.dragEnterEvent = self.dragEnterEvent
|
||||
line_edit.dropEvent = lambda event: line_edit.setText(str(pathlib.Path(event.mimeData().urls()[0].toLocalFile()).absolute()))
|
||||
|
||||
@staticmethod
|
||||
def read_config(config_file: pathlib.Path) -> dict:
|
||||
""" read video2x configurations from config file
|
||||
@@ -250,7 +350,7 @@ class Video2XMainWindow(QtWidgets.QMainWindow):
|
||||
|
||||
# if file doesn't exist, return
|
||||
if not config_file_path.is_file():
|
||||
QtWidgets.QErrorMessage(self).showMessage('Video2X configuration file not found, please specify manually.')
|
||||
QErrorMessage(self).showMessage('Video2X configuration file not found, please specify manually.')
|
||||
return
|
||||
|
||||
# read configuration dict from config file
|
||||
@@ -328,7 +428,7 @@ class Video2XMainWindow(QtWidgets.QMainWindow):
|
||||
self.anime4kcpp_gpu_mode_check_box.setChecked(settings['GPUMode'])
|
||||
|
||||
def resolve_driver_settings(self):
|
||||
|
||||
|
||||
# waifu2x-caffe
|
||||
self.config['waifu2x_caffe']['path'] = os.path.expandvars(self.waifu2x_caffe_path_line_edit.text())
|
||||
self.config['waifu2x_caffe']['mode'] = self.waifu2x_caffe_mode_combo_box.currentText()
|
||||
@@ -340,7 +440,7 @@ class Video2XMainWindow(QtWidgets.QMainWindow):
|
||||
self.config['waifu2x_caffe']['output_depth'] = self.waifu2x_caffe_output_depth_spin_box.value()
|
||||
self.config['waifu2x_caffe']['batch_size'] = self.waifu2x_caffe_batch_size_spin_box.value()
|
||||
self.config['waifu2x_caffe']['gpu'] = self.waifu2x_caffe_gpu_spin_box.value()
|
||||
self.config['waifu2x_caffe']['tta'] = int(self.waifu2x_caffe_tta_check_box.checkState())
|
||||
self.config['waifu2x_caffe']['tta'] = int(self.waifu2x_caffe_tta_check_box.isChecked())
|
||||
|
||||
# waifu2x-converter-cpp
|
||||
self.config['waifu2x_converter_cpp']['path'] = os.path.expandvars(self.waifu2x_converter_cpp_path_line_edit.text())
|
||||
@@ -348,8 +448,8 @@ class Video2XMainWindow(QtWidgets.QMainWindow):
|
||||
self.config['waifu2x_converter_cpp']['processor'] = self.waifu2x_converter_cpp_processor_spin_box.value()
|
||||
self.config['waifu2x_converter_cpp']['model-dir'] = str((pathlib.Path(self.config['waifu2x_converter_cpp']['path']).parent / self.waifu2x_converter_cpp_model_combo_box.currentText()).absolute())
|
||||
self.config['waifu2x_converter_cpp']['mode'] = self.waifu2x_converter_cpp_mode_combo_box.currentText()
|
||||
self.config['waifu2x_converter_cpp']['disable-gpu'] = bool(self.waifu2x_converter_cpp_disable_gpu_check_box.checkState())
|
||||
self.config['waifu2x_converter_cpp']['tta'] = int(self.waifu2x_converter_cpp_tta_check_box.checkState())
|
||||
self.config['waifu2x_converter_cpp']['disable-gpu'] = bool(self.waifu2x_converter_cpp_disable_gpu_check_box.isChecked())
|
||||
self.config['waifu2x_converter_cpp']['tta'] = int(self.waifu2x_converter_cpp_tta_check_box.isChecked())
|
||||
|
||||
# waifu2x-ncnn-vulkan
|
||||
self.config['waifu2x_ncnn_vulkan']['path'] = os.path.expandvars(self.waifu2x_ncnn_vulkan_path_line_edit.text())
|
||||
@@ -358,7 +458,7 @@ class Video2XMainWindow(QtWidgets.QMainWindow):
|
||||
self.config['waifu2x_ncnn_vulkan']['m'] = str((pathlib.Path(self.config['waifu2x_ncnn_vulkan']['path']).parent / self.waifu2x_ncnn_vulkan_model_combo_box.currentText()).absolute())
|
||||
self.config['waifu2x_ncnn_vulkan']['g'] = self.waifu2x_ncnn_vulkan_gpu_id_spin_box.value()
|
||||
self.config['waifu2x_ncnn_vulkan']['j'] = self.waifu2x_ncnn_vulkan_jobs_line_edit.text()
|
||||
self.config['waifu2x_ncnn_vulkan']['x'] = self.waifu2x_ncnn_vulkan_tta_check_box.checkState()
|
||||
self.config['waifu2x_ncnn_vulkan']['x'] = self.waifu2x_ncnn_vulkan_tta_check_box.isChecked()
|
||||
|
||||
# srmd-ncnn-vulkan
|
||||
self.config['srmd_ncnn_vulkan']['path'] = os.path.expandvars(self.srmd_ncnn_vulkan_path_line_edit.text())
|
||||
@@ -367,7 +467,7 @@ class Video2XMainWindow(QtWidgets.QMainWindow):
|
||||
self.config['srmd_ncnn_vulkan']['m'] = str((pathlib.Path(self.config['srmd_ncnn_vulkan']['path']).parent / self.srmd_ncnn_vulkan_model_combo_box.currentText()).absolute())
|
||||
self.config['srmd_ncnn_vulkan']['g'] = self.srmd_ncnn_vulkan_gpu_id_spin_box.value()
|
||||
self.config['srmd_ncnn_vulkan']['j'] = self.srmd_ncnn_vulkan_jobs_line_edit.text()
|
||||
self.config['srmd_ncnn_vulkan']['x'] = self.srmd_ncnn_vulkan_tta_check_box.checkState()
|
||||
self.config['srmd_ncnn_vulkan']['x'] = self.srmd_ncnn_vulkan_tta_check_box.isChecked()
|
||||
|
||||
# anime4k
|
||||
self.config['anime4kcpp']['path'] = os.path.expandvars(self.anime4kcpp_path_line_edit.text())
|
||||
@@ -381,14 +481,14 @@ class Video2XMainWindow(QtWidgets.QMainWindow):
|
||||
self.config['anime4kcpp']['platformID'] = self.anime4kcpp_platform_id_spin_box.value()
|
||||
self.config['anime4kcpp']['deviceID'] = self.anime4kcpp_device_id_spin_box.value()
|
||||
self.config['anime4kcpp']['codec'] = self.anime4kcpp_codec_combo_box.currentText()
|
||||
self.config['anime4kcpp']['fastMode'] = bool(self.anime4kcpp_fast_mode_check_box.checkState())
|
||||
self.config['anime4kcpp']['preprocessing'] = bool(self.anime4kcpp_pre_processing_check_box.checkState())
|
||||
self.config['anime4kcpp']['postprocessing'] = bool(self.anime4kcpp_post_processing_check_box.checkState())
|
||||
self.config['anime4kcpp']['GPUMode'] = bool(self.anime4kcpp_gpu_mode_check_box.checkState())
|
||||
self.config['anime4kcpp']['fastMode'] = bool(self.anime4kcpp_fast_mode_check_box.isChecked())
|
||||
self.config['anime4kcpp']['preprocessing'] = bool(self.anime4kcpp_pre_processing_check_box.isChecked())
|
||||
self.config['anime4kcpp']['postprocessing'] = bool(self.anime4kcpp_post_processing_check_box.isChecked())
|
||||
self.config['anime4kcpp']['GPUMode'] = bool(self.anime4kcpp_gpu_mode_check_box.isChecked())
|
||||
|
||||
def update_gui_for_driver(self):
|
||||
current_driver = AVAILABLE_DRIVERS[self.driver_combo_box.currentText()]
|
||||
|
||||
|
||||
# update scale ratio constraints
|
||||
if current_driver in ['waifu2x_caffe', 'waifu2x_converter_cpp', 'anime4kcpp']:
|
||||
self.scale_ratio_double_spin_box.setMinimum(0.0)
|
||||
@@ -402,59 +502,93 @@ class Video2XMainWindow(QtWidgets.QMainWindow):
|
||||
self.scale_ratio_double_spin_box.setMinimum(2.0)
|
||||
self.scale_ratio_double_spin_box.setMaximum(4.0)
|
||||
self.scale_ratio_double_spin_box.setValue(2.0)
|
||||
|
||||
|
||||
# update preferred processes/threads count
|
||||
if current_driver == 'anime4kcpp':
|
||||
self.processes_spin_box.setValue(16)
|
||||
else:
|
||||
self.processes_spin_box.setValue(1)
|
||||
|
||||
|
||||
def update_input_table(self):
|
||||
# HACK: use insertRow, removeRow and signals
|
||||
del self.input_table_model
|
||||
self.input_table_model = InputTableModel(self.input_table_data)
|
||||
self.input_table_view.setModel(self.input_table_model)
|
||||
|
||||
def input_table_delete_selected(self):
|
||||
items_to_delete = []
|
||||
for index in [i.row() for i in self.input_table_view.selectedIndexes()]:
|
||||
items_to_delete.append(self.input_table_data[index])
|
||||
|
||||
for item in items_to_delete:
|
||||
self.input_table_data.remove(item)
|
||||
self.update_input_table()
|
||||
|
||||
def input_table_clear_all(self):
|
||||
self.input_table_data = []
|
||||
self.update_input_table()
|
||||
|
||||
def input_table_path_exists(self, input_path):
|
||||
for path in self.input_table_data:
|
||||
# not using Path.samefile since file may not exist
|
||||
if str(path.absolute()) == str(input_path.absolute()):
|
||||
return True
|
||||
return False
|
||||
|
||||
def select_file(self, *args, **kwargs) -> pathlib.Path:
|
||||
file_selected = QtWidgets.QFileDialog.getOpenFileName(self, *args, **kwargs)
|
||||
file_selected = QFileDialog.getOpenFileName(self, *args, **kwargs)
|
||||
if not isinstance(file_selected, tuple) or file_selected[0] == '':
|
||||
return None
|
||||
return pathlib.Path(file_selected[0])
|
||||
|
||||
def select_folder(self, *args, **kwargs) -> pathlib.Path:
|
||||
folder_selected = QtWidgets.QFileDialog.getExistingDirectory(self, *args, **kwargs)
|
||||
folder_selected = QFileDialog.getExistingDirectory(self, *args, **kwargs)
|
||||
if folder_selected == '':
|
||||
return None
|
||||
return pathlib.Path(folder_selected)
|
||||
|
||||
def select_input_file(self):
|
||||
|
||||
if (input_file := self.select_file('Select Input File')) is None:
|
||||
def update_output_path(self):
|
||||
# if there is more than one input
|
||||
if len(self.input_table_data) != 1:
|
||||
return
|
||||
self.input_line_edit.setText(str(input_file.absolute()))
|
||||
|
||||
# try to set an output file name automatically
|
||||
output_file = input_file.parent / f'{input_file.stem}_output.mp4'
|
||||
input_path = self.input_table_data[0]
|
||||
# give up if input path doesn't exist or isn't a file or a directory
|
||||
if not input_path.exists() or not (input_path.is_file() or input_path.is_dir()):
|
||||
return
|
||||
|
||||
output_file_id = 0
|
||||
while output_file.is_file() and output_file_id <= 10:
|
||||
output_file = input_file.parent / pathlib.Path(f'{input_file.stem}_output_{output_file_id}.mp4')
|
||||
output_file_id += 1
|
||||
if input_path.is_file():
|
||||
output_path = input_path.parent / f'{input_path.stem}_output.mp4'
|
||||
elif input_path.is_dir():
|
||||
output_path = input_path.parent / f'{input_path.stem}_output'
|
||||
|
||||
if not output_file.exists():
|
||||
self.output_line_edit.setText(str(output_file.absolute()))
|
||||
# try up to 1000 times
|
||||
output_path_id = 0
|
||||
while output_path.exists() and output_path_id <= 1000:
|
||||
if input_path.is_file():
|
||||
output_path = input_path.parent / pathlib.Path(f'{input_path.stem}_output_{output_path_id}.mp4')
|
||||
elif input_path.is_dir():
|
||||
output_path = input_path.parent / pathlib.Path(f'{input_path.stem}_output_{output_path_id}')
|
||||
output_path_id += 1
|
||||
|
||||
if not output_path.exists():
|
||||
self.output_line_edit.setText(str(output_path.absolute()))
|
||||
|
||||
def select_input_file(self):
|
||||
if ((input_file := self.select_file('Select Input File')) is None or
|
||||
self.input_table_path_exists(input_file)):
|
||||
return
|
||||
self.input_table_data.append(input_file)
|
||||
self.update_output_path()
|
||||
self.update_input_table()
|
||||
|
||||
def select_input_folder(self):
|
||||
|
||||
if (input_folder := self.select_folder('Select Input Folder')) is None:
|
||||
if ((input_folder := self.select_folder('Select Input Folder')) is None or
|
||||
self.input_table_path_exists(input_folder)):
|
||||
return
|
||||
|
||||
self.input_line_edit.setText(str(input_folder.absolute()))
|
||||
|
||||
# try to set an output file name automatically
|
||||
output_folder = input_folder.parent / f'{input_folder.stem}_output'
|
||||
|
||||
output_file_id = 0
|
||||
while output_folder.is_dir() and output_file_id <= 10:
|
||||
output_folder = input_folder.parent / pathlib.Path(f'{input_folder.stem}_output_{output_file_id}')
|
||||
output_file_id += 1
|
||||
|
||||
if not output_folder.exists():
|
||||
self.output_line_edit.setText(str(output_folder.absolute()))
|
||||
self.input_table_data.append(input_folder)
|
||||
self.update_output_path()
|
||||
self.update_input_table()
|
||||
|
||||
def select_output_file(self):
|
||||
if (output_file := self.select_file('Select Output File')) is None:
|
||||
@@ -476,58 +610,79 @@ class Video2XMainWindow(QtWidgets.QMainWindow):
|
||||
return
|
||||
self.config_line_edit.setText(str(config_file.absolute()))
|
||||
self.load_configurations()
|
||||
|
||||
|
||||
def select_driver_binary_path(self, driver_line_edit):
|
||||
if (driver_binary_path := self.select_file('Select Driver Binary File')) is None:
|
||||
return
|
||||
driver_line_edit.setText(str(driver_binary_path.absolute()))
|
||||
|
||||
def show_error(self, message: str):
|
||||
QtWidgets.QErrorMessage(self).showMessage(message.replace('\n', '<br>'))
|
||||
def show_about(self, message: str):
|
||||
message_box = QMessageBox(self)
|
||||
message_box.setWindowTitle('About Video2X')
|
||||
message_box.setIconPixmap(QtGui.QPixmap(self.video2x_icon_path).scaled(64, 64))
|
||||
message_box.setText(LEGAL_INFO)
|
||||
message_box.exec_()
|
||||
|
||||
def show_message(self, message: str, custom_icon=None):
|
||||
message_box = QtWidgets.QMessageBox()
|
||||
message_box.setWindowTitle('Message')
|
||||
if custom_icon:
|
||||
message_box.setIconPixmap(custom_icon.scaled(64, 64))
|
||||
else:
|
||||
message_box.setIcon(QtWidgets.QMessageBox.Information)
|
||||
def show_information(self, message: str):
|
||||
message_box = QMessageBox(self)
|
||||
message_box.setWindowTitle('Information')
|
||||
message_box.setIcon(QMessageBox.Information)
|
||||
message_box.setText(message)
|
||||
message_box.exec_()
|
||||
|
||||
def start_progress_bar(self, progress_callback):
|
||||
# wait for progress monitor to come online
|
||||
while 'progress_monitor' not in self.upscaler.__dict__:
|
||||
if self.upscaler.stop_signal:
|
||||
return
|
||||
time.sleep(0.1)
|
||||
def show_warning(self, message: str):
|
||||
message_box = QMessageBox(self)
|
||||
message_box.setWindowTitle('Warning')
|
||||
message_box.setIcon(QMessageBox.Warning)
|
||||
message_box.setText(message)
|
||||
message_box.exec_()
|
||||
|
||||
def show_error(self, exception: Exception):
|
||||
# QErrorMessage(self).showMessage(message.replace('\n', '<br>'))
|
||||
message_box = QMessageBox(self)
|
||||
message_box.setWindowTitle('Error')
|
||||
message_box.setIcon(QMessageBox.Critical)
|
||||
|
||||
error_message = '''Upscaler ran into an error:
|
||||
{}
|
||||
Check the console output for details.
|
||||
When reporting an error, please include console output.'''
|
||||
|
||||
try:
|
||||
message_box.setText(error_message.format(exception.args[0]))
|
||||
except (AttributeError, IndexError):
|
||||
message_box.setText(error_message.format(exception))
|
||||
|
||||
message_box.exec_()
|
||||
|
||||
def progress_monitor(self, progress_callback):
|
||||
|
||||
# initialize progress bar values
|
||||
upscale_begin_time = time.time()
|
||||
progress_callback.emit((0, 0, 0, upscale_begin_time))
|
||||
progress_callback.emit((upscale_begin_time, 0, 0, 0, 0, pathlib.Path()))
|
||||
|
||||
# keep querying upscaling process and feed information to callback signal
|
||||
while self.upscaler.progress_monitor.running:
|
||||
try:
|
||||
progress_percentage = int(100 * self.upscaler.total_frames_upscaled / self.upscaler.total_frames)
|
||||
except ZeroDivisionError:
|
||||
progress_percentage = 0
|
||||
while self.upscaler.running:
|
||||
|
||||
progress_callback.emit((progress_percentage,
|
||||
self.upscaler.total_frames_upscaled,
|
||||
self.upscaler.total_frames,
|
||||
upscale_begin_time))
|
||||
progress_callback.emit((upscale_begin_time,
|
||||
self.upscaler.total_frames_upscaled,
|
||||
self.upscaler.total_frames,
|
||||
self.upscaler.total_processed,
|
||||
self.upscaler.total_videos,
|
||||
self.upscaler.current_input_video))
|
||||
time.sleep(1)
|
||||
|
||||
# upscale process will stop at 99%
|
||||
# so it's set to 100 manually when all is done
|
||||
progress_callback.emit((100, 0, 0, upscale_begin_time))
|
||||
progress_callback.emit((upscale_begin_time, 0, 0, 0, 0, pathlib.Path()))
|
||||
|
||||
def set_progress(self, progress_information: tuple):
|
||||
progress_percentage = progress_information[0]
|
||||
upscale_begin_time = progress_information[0]
|
||||
total_frames_upscaled = progress_information[1]
|
||||
total_frames = progress_information[2]
|
||||
upscale_begin_time = progress_information[3]
|
||||
total_processed = progress_information[3]
|
||||
total_videos = progress_information[4]
|
||||
current_input_video = progress_information[5]
|
||||
|
||||
# calculate fields based on frames and time elapsed
|
||||
time_elapsed = time.time() - upscale_begin_time
|
||||
@@ -539,10 +694,29 @@ class Video2XMainWindow(QtWidgets.QMainWindow):
|
||||
time_remaining = 0.0
|
||||
|
||||
# set calculated values in GUI
|
||||
self.progress_bar.setValue(progress_percentage)
|
||||
self.current_progress_bar.setMaximum(total_frames)
|
||||
self.current_progress_bar.setValue(total_frames_upscaled)
|
||||
self.frames_label.setText('Frames: {}/{}'.format(total_frames_upscaled, total_frames))
|
||||
self.time_elapsed_label.setText('Time Elapsed: {}'.format(time.strftime("%H:%M:%S", time.gmtime(time_elapsed))))
|
||||
self.time_remaining_label.setText('Time Remaining: {}'.format(time.strftime("%H:%M:%S", time.gmtime(time_remaining))))
|
||||
self.rate_label.setText('Rate (FPS): {}'.format(round(rate, 2)))
|
||||
self.overall_progress_label.setText('Overall Progress: {}/{}'.format(total_processed, total_videos))
|
||||
self.overall_progress_bar.setMaximum(total_videos)
|
||||
self.overall_progress_bar.setValue(total_processed)
|
||||
self.currently_processing_label.setText('Currently Processing: {}'.format(str(current_input_video.name)))
|
||||
|
||||
def reset_progress_display(self):
|
||||
# reset progress display UI elements
|
||||
self.current_progress_bar.setMaximum(100)
|
||||
self.current_progress_bar.setValue(0)
|
||||
self.frames_label.setText('Frames: {}/{}'.format(0, 0))
|
||||
self.time_elapsed_label.setText('Time Elapsed: {}'.format(time.strftime("%H:%M:%S", time.gmtime(0))))
|
||||
self.time_remaining_label.setText('Time Remaining: {}'.format(time.strftime("%H:%M:%S", time.gmtime(0))))
|
||||
self.rate_label.setText('Rate (FPS): {}'.format(0.0))
|
||||
self.overall_progress_label.setText('Overall Progress: {}/{}'.format(0, 0))
|
||||
self.overall_progress_bar.setMaximum(100)
|
||||
self.overall_progress_bar.setValue(0)
|
||||
self.currently_processing_label.setText('Currently Processing:')
|
||||
|
||||
def start(self):
|
||||
|
||||
@@ -552,18 +726,20 @@ class Video2XMainWindow(QtWidgets.QMainWindow):
|
||||
self.begin_time = time.time()
|
||||
|
||||
# resolve input and output directories from GUI
|
||||
if self.input_line_edit.text().strip() == '':
|
||||
self.show_error('Input path not specified')
|
||||
if len(self.input_table_data) == 0:
|
||||
self.show_warning('Input path unspecified', standard_icon=QMessageBox.Warning)
|
||||
return
|
||||
if self.output_line_edit.text().strip() == '':
|
||||
self.show_error('Output path not specified')
|
||||
self.show_warning('Output path unspecified', standard_icon=QMessageBox.Warning)
|
||||
return
|
||||
|
||||
input_directory = pathlib.Path(os.path.expandvars(self.input_line_edit.text()))
|
||||
output_directory = pathlib.Path(os.path.expandvars(self.output_line_edit.text()))
|
||||
if len(self.input_table_data) == 1:
|
||||
input_directory = self.input_table_data[0]
|
||||
else:
|
||||
input_directory = self.input_table_data
|
||||
|
||||
# create thread pool for upscaler workers
|
||||
self.threadpool = QThreadPool()
|
||||
# resolve output directory
|
||||
output_directory = pathlib.Path(os.path.expandvars(self.output_line_edit.text()))
|
||||
|
||||
# load driver settings from GUI
|
||||
self.resolve_driver_settings()
|
||||
@@ -582,44 +758,52 @@ class Video2XMainWindow(QtWidgets.QMainWindow):
|
||||
self.upscaler.processes = self.processes_spin_box.value()
|
||||
self.upscaler.video2x_cache_directory = pathlib.Path(os.path.expandvars(self.cache_line_edit.text()))
|
||||
self.upscaler.image_format = self.config['video2x']['image_format'].lower()
|
||||
self.upscaler.preserve_frames = bool(self.preserve_frames_check_box.checkState())
|
||||
|
||||
# start progress bar
|
||||
if AVAILABLE_DRIVERS[self.driver_combo_box.currentText()] != 'anime4kcpp':
|
||||
progress_bar_worker = ProgressBarWorker(self.start_progress_bar)
|
||||
progress_bar_worker.signals.progress.connect(self.set_progress)
|
||||
self.threadpool.start(progress_bar_worker)
|
||||
self.upscaler.preserve_frames = bool(self.preserve_frames_check_box.isChecked())
|
||||
|
||||
# run upscaler
|
||||
worker = UpscalerWorker(self.upscaler.run)
|
||||
worker.signals.error.connect(self.upscale_errored)
|
||||
worker.signals.finished.connect(self.upscale_completed)
|
||||
worker.signals.interrupted.connect(self.upscale_interrupted)
|
||||
worker.signals.finished.connect(self.upscale_successful)
|
||||
self.threadpool.start(worker)
|
||||
|
||||
# start progress monitoring
|
||||
progress_bar_worker = ProgressMonitorWorkder(self.progress_monitor)
|
||||
progress_bar_worker.signals.progress.connect(self.set_progress)
|
||||
self.threadpool.start(progress_bar_worker)
|
||||
|
||||
self.start_button.setEnabled(False)
|
||||
self.stop_button.setEnabled(True)
|
||||
|
||||
except Exception:
|
||||
self.upscale_errored(traceback.format_exc())
|
||||
|
||||
def upscale_errored(self, error_message):
|
||||
self.show_error(f'Upscaler ran into an error:\n{error_message}')
|
||||
except Exception as e:
|
||||
traceback.print_exc()
|
||||
self.upscale_errored(e)
|
||||
|
||||
def upscale_completed(self):
|
||||
# if all threads have finished
|
||||
if self.threadpool.activeThreadCount() == 0:
|
||||
self.show_message('Program completed, taking {} seconds'.format(round((time.time() - self.begin_time), 5)))
|
||||
self.start_button.setEnabled(True)
|
||||
self.stop_button.setEnabled(False)
|
||||
|
||||
def upscale_interrupted(self):
|
||||
self.show_message('Upscale has been interrupted')
|
||||
def upscale_errored(self, exception: Exception):
|
||||
self.show_error(exception)
|
||||
self.threadpool.waitForDone(5)
|
||||
self.start_button.setEnabled(True)
|
||||
self.stop_button.setEnabled(False)
|
||||
self.reset_progress_display()
|
||||
|
||||
def upscale_interrupted(self):
|
||||
self.show_information('Upscale has been interrupted')
|
||||
self.threadpool.waitForDone(5)
|
||||
self.start_button.setEnabled(True)
|
||||
self.stop_button.setEnabled(False)
|
||||
self.reset_progress_display()
|
||||
|
||||
def upscale_successful(self):
|
||||
# if all threads have finished
|
||||
self.threadpool.waitForDone(5)
|
||||
self.show_information('Upscale finished successfully, taking {} seconds'.format(round((time.time() - self.begin_time), 5)))
|
||||
self.start_button.setEnabled(True)
|
||||
self.stop_button.setEnabled(False)
|
||||
self.reset_progress_display()
|
||||
|
||||
def stop(self):
|
||||
with contextlib.suppress(AttributeError):
|
||||
self.upscaler.stop_signal = True
|
||||
self.upscaler.running = False
|
||||
|
||||
def closeEvent(self, event):
|
||||
# try cleaning up temp directories
|
||||
@@ -629,7 +813,14 @@ class Video2XMainWindow(QtWidgets.QMainWindow):
|
||||
|
||||
# this file shouldn't be imported
|
||||
if __name__ == '__main__':
|
||||
app = QtWidgets.QApplication(sys.argv)
|
||||
window = Video2XMainWindow()
|
||||
window.show()
|
||||
app.exec_()
|
||||
try:
|
||||
app = QApplication(sys.argv)
|
||||
window = Video2XMainWindow()
|
||||
window.show()
|
||||
app.exec_()
|
||||
|
||||
# on GUI exception, print error message in console
|
||||
# and hold window open using input()
|
||||
except Exception:
|
||||
traceback.print_exc()
|
||||
input('Press enter to close')
|
||||
|
||||
190
src/video2x_gui.pyproject.user
Normal file
190
src/video2x_gui.pyproject.user
Normal file
@@ -0,0 +1,190 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE QtCreatorProject>
|
||||
<!-- Written by QtCreator 4.12.0, 2020-05-08T20:28:53. -->
|
||||
<qtcreator>
|
||||
<data>
|
||||
<variable>EnvironmentId</variable>
|
||||
<value type="QByteArray">{25c1e4a4-6b4a-4828-883b-6f32c3f7eba0}</value>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.ActiveTarget</variable>
|
||||
<value type="int">0</value>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.EditorSettings</variable>
|
||||
<valuemap type="QVariantMap">
|
||||
<value type="bool" key="EditorConfiguration.AutoIndent">true</value>
|
||||
<value type="bool" key="EditorConfiguration.AutoSpacesForTabs">false</value>
|
||||
<value type="bool" key="EditorConfiguration.CamelCaseNavigation">true</value>
|
||||
<valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.0">
|
||||
<value type="QString" key="language">Cpp</value>
|
||||
<valuemap type="QVariantMap" key="value">
|
||||
<value type="QByteArray" key="CurrentPreferences">CppGlobal</value>
|
||||
</valuemap>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.1">
|
||||
<value type="QString" key="language">QmlJS</value>
|
||||
<valuemap type="QVariantMap" key="value">
|
||||
<value type="QByteArray" key="CurrentPreferences">QmlJSGlobal</value>
|
||||
</valuemap>
|
||||
</valuemap>
|
||||
<value type="int" key="EditorConfiguration.CodeStyle.Count">2</value>
|
||||
<value type="QByteArray" key="EditorConfiguration.Codec">UTF-8</value>
|
||||
<value type="bool" key="EditorConfiguration.ConstrainTooltips">false</value>
|
||||
<value type="int" key="EditorConfiguration.IndentSize">4</value>
|
||||
<value type="bool" key="EditorConfiguration.KeyboardTooltips">false</value>
|
||||
<value type="int" key="EditorConfiguration.MarginColumn">80</value>
|
||||
<value type="bool" key="EditorConfiguration.MouseHiding">true</value>
|
||||
<value type="bool" key="EditorConfiguration.MouseNavigation">true</value>
|
||||
<value type="int" key="EditorConfiguration.PaddingMode">1</value>
|
||||
<value type="bool" key="EditorConfiguration.ScrollWheelZooming">true</value>
|
||||
<value type="bool" key="EditorConfiguration.ShowMargin">false</value>
|
||||
<value type="int" key="EditorConfiguration.SmartBackspaceBehavior">0</value>
|
||||
<value type="bool" key="EditorConfiguration.SmartSelectionChanging">true</value>
|
||||
<value type="bool" key="EditorConfiguration.SpacesForTabs">true</value>
|
||||
<value type="int" key="EditorConfiguration.TabKeyBehavior">0</value>
|
||||
<value type="int" key="EditorConfiguration.TabSize">8</value>
|
||||
<value type="bool" key="EditorConfiguration.UseGlobal">true</value>
|
||||
<value type="int" key="EditorConfiguration.Utf8BomBehavior">1</value>
|
||||
<value type="bool" key="EditorConfiguration.addFinalNewLine">true</value>
|
||||
<value type="bool" key="EditorConfiguration.cleanIndentation">true</value>
|
||||
<value type="bool" key="EditorConfiguration.cleanWhitespace">true</value>
|
||||
<value type="bool" key="EditorConfiguration.inEntireDocument">false</value>
|
||||
</valuemap>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.PluginSettings</variable>
|
||||
<valuemap type="QVariantMap">
|
||||
<valuelist type="QVariantList" key="ClangCodeModel.CustomCommandLineKey">
|
||||
<value type="QString">-fno-delayed-template-parsing</value>
|
||||
</valuelist>
|
||||
<value type="bool" key="ClangCodeModel.UseGlobalConfig">true</value>
|
||||
<value type="QString" key="ClangCodeModel.WarningConfigId">Builtin.Questionable</value>
|
||||
<valuemap type="QVariantMap" key="ClangTools">
|
||||
<value type="bool" key="ClangTools.BuildBeforeAnalysis">true</value>
|
||||
<value type="QString" key="ClangTools.DiagnosticConfig">Builtin.DefaultTidyAndClazy</value>
|
||||
<value type="int" key="ClangTools.ParallelJobs">8</value>
|
||||
<valuelist type="QVariantList" key="ClangTools.SelectedDirs"/>
|
||||
<valuelist type="QVariantList" key="ClangTools.SelectedFiles"/>
|
||||
<valuelist type="QVariantList" key="ClangTools.SuppressedDiagnostics"/>
|
||||
<value type="bool" key="ClangTools.UseGlobalSettings">true</value>
|
||||
</valuemap>
|
||||
</valuemap>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.Target.0</variable>
|
||||
<valuemap type="QVariantMap">
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Desktop (x86-windows-msvc2019-pe-64bit)</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Desktop (x86-windows-msvc2019-pe-64bit)</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">{5450e32e-f498-4c15-a0a5-7456f3375388}</value>
|
||||
<value type="int" key="ProjectExplorer.Target.ActiveBuildConfiguration">-1</value>
|
||||
<value type="int" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value>
|
||||
<value type="int" key="ProjectExplorer.Target.ActiveRunConfiguration">0</value>
|
||||
<value type="int" key="ProjectExplorer.Target.BuildConfigurationCount">0</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.0">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">0</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deploy</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Deploy</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.DeployConfiguration.CustomData"/>
|
||||
<value type="bool" key="ProjectExplorer.DeployConfiguration.CustomDataEnabled">false</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.DefaultDeployConfiguration</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.Target.DeployConfigurationCount">1</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.PluginSettings"/>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.0">
|
||||
<value type="QString" key="Analyzer.Perf.CallgraphMode">dwarf</value>
|
||||
<valuelist type="QVariantList" key="Analyzer.Perf.Events">
|
||||
<value type="QString">cpu-cycles</value>
|
||||
</valuelist>
|
||||
<valuelist type="QVariantList" key="Analyzer.Perf.ExtraArguments"/>
|
||||
<value type="int" key="Analyzer.Perf.Frequency">250</value>
|
||||
<valuelist type="QVariantList" key="Analyzer.Perf.RecordArguments">
|
||||
<value type="QString">-e</value>
|
||||
<value type="QString">cpu-cycles</value>
|
||||
<value type="QString">--call-graph</value>
|
||||
<value type="QString">dwarf,4096</value>
|
||||
<value type="QString">-F</value>
|
||||
<value type="QString">250</value>
|
||||
</valuelist>
|
||||
<value type="QString" key="Analyzer.Perf.SampleMode">-F</value>
|
||||
<value type="bool" key="Analyzer.Perf.Settings.UseGlobalSettings">true</value>
|
||||
<value type="int" key="Analyzer.Perf.StackSize">4096</value>
|
||||
<value type="bool" key="Analyzer.QmlProfiler.AggregateTraces">false</value>
|
||||
<value type="bool" key="Analyzer.QmlProfiler.FlushEnabled">false</value>
|
||||
<value type="uint" key="Analyzer.QmlProfiler.FlushInterval">1000</value>
|
||||
<value type="QString" key="Analyzer.QmlProfiler.LastTraceFile"></value>
|
||||
<value type="bool" key="Analyzer.QmlProfiler.Settings.UseGlobalSettings">true</value>
|
||||
<valuelist type="QVariantList" key="Analyzer.Valgrind.AddedSuppressionFiles"/>
|
||||
<value type="bool" key="Analyzer.Valgrind.Callgrind.CollectBusEvents">false</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.Callgrind.CollectSystime">false</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.Callgrind.EnableBranchSim">false</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.Callgrind.EnableCacheSim">false</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.Callgrind.EnableEventToolTips">true</value>
|
||||
<value type="double" key="Analyzer.Valgrind.Callgrind.MinimumCostRatio">0.01</value>
|
||||
<value type="double" key="Analyzer.Valgrind.Callgrind.VisualisationMinimumCostRatio">10</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.FilterExternalIssues">true</value>
|
||||
<value type="QString" key="Analyzer.Valgrind.KCachegrindExecutable">kcachegrind</value>
|
||||
<value type="int" key="Analyzer.Valgrind.LeakCheckOnFinish">1</value>
|
||||
<value type="int" key="Analyzer.Valgrind.NumCallers">25</value>
|
||||
<valuelist type="QVariantList" key="Analyzer.Valgrind.RemovedSuppressionFiles"/>
|
||||
<value type="int" key="Analyzer.Valgrind.SelfModifyingCodeDetection">1</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.Settings.UseGlobalSettings">true</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.ShowReachable">false</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.TrackOrigins">true</value>
|
||||
<value type="QString" key="Analyzer.Valgrind.ValgrindExecutable">valgrind</value>
|
||||
<valuelist type="QVariantList" key="Analyzer.Valgrind.VisibleErrorKinds">
|
||||
<value type="int">0</value>
|
||||
<value type="int">1</value>
|
||||
<value type="int">2</value>
|
||||
<value type="int">3</value>
|
||||
<value type="int">4</value>
|
||||
<value type="int">5</value>
|
||||
<value type="int">6</value>
|
||||
<value type="int">7</value>
|
||||
<value type="int">8</value>
|
||||
<value type="int">9</value>
|
||||
<value type="int">10</value>
|
||||
<value type="int">11</value>
|
||||
<value type="int">12</value>
|
||||
<value type="int">13</value>
|
||||
<value type="int">14</value>
|
||||
</valuelist>
|
||||
<value type="int" key="PE.EnvironmentAspect.Base">2</value>
|
||||
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">video2x_gui</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">PythonEditor.RunConfiguration.C:/Users/k4yt3x/Documents/Projects/video2x/src/video2x_gui.py</value>
|
||||
<value type="QString" key="ProjectExplorer.RunConfiguration.BuildKey">C:/Users/k4yt3x/Documents/Projects/video2x/src/video2x_gui.py</value>
|
||||
<value type="bool" key="PythonEditor.RunConfiguation.Buffered">false</value>
|
||||
<value type="QString" key="PythonEditor.RunConfiguation.Interpreter">{ffc39ed5-fbe0-4af8-8b16-9a60c393bdb8}</value>
|
||||
<value type="QString" key="PythonEditor.RunConfiguation.Script">C:\Users\k4yt3x\Documents\Projects\video2x\src\video2x_gui.py</value>
|
||||
<value type="QString" key="RunConfiguration.Arguments"></value>
|
||||
<value type="bool" key="RunConfiguration.Arguments.multi">false</value>
|
||||
<value type="QString" key="RunConfiguration.OverrideDebuggerStartup"></value>
|
||||
<value type="bool" key="RunConfiguration.UseCppDebugger">false</value>
|
||||
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
|
||||
<value type="bool" key="RunConfiguration.UseMultiProcess">false</value>
|
||||
<value type="bool" key="RunConfiguration.UseQmlDebugger">false</value>
|
||||
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
|
||||
<value type="QString" key="RunConfiguration.WorkingDirectory"></value>
|
||||
<value type="QString" key="RunConfiguration.WorkingDirectory.default"></value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.Target.RunConfigurationCount">1</value>
|
||||
</valuemap>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.TargetCount</variable>
|
||||
<value type="int">1</value>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.Updater.FileVersion</variable>
|
||||
<value type="int">22</value>
|
||||
</data>
|
||||
<data>
|
||||
<variable>Version</variable>
|
||||
<value type="int">22</value>
|
||||
</data>
|
||||
</qtcreator>
|
||||
@@ -1,19 +1,22 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>Video2xQt</class>
|
||||
<widget class="QMainWindow" name="Video2xQt">
|
||||
<class>Video2xGui</class>
|
||||
<widget class="QMainWindow" name="Video2xGui">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>691</width>
|
||||
<height>503</height>
|
||||
<width>718</width>
|
||||
<height>740</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Video2xQt</string>
|
||||
<property name="acceptDrops">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<widget class="QWidget" name="centralwidget">
|
||||
<property name="windowTitle">
|
||||
<string>Video2X GUI</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="centralWidget">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<property name="leftMargin">
|
||||
<number>5</number>
|
||||
@@ -38,154 +41,198 @@
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_8">
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="fileSelectionVerticalLayout">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="inputHorizontalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="inputLabel">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>63</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="lineWidth">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Input</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="margin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="inputLineEdit"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="inputSelectFileButton">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Select File</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="inputSelectFolderButton">
|
||||
<property name="text">
|
||||
<string>Select Folder</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="outputHorizontalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="outputLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>63</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Output</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="outputLineEdit"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="outputSelectFileButton">
|
||||
<property name="text">
|
||||
<string>Select File</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="outputSelectFolderButton">
|
||||
<property name="text">
|
||||
<string>Select Folder</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="configHorizontalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="configLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>63</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Config</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="configLineEdit"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="configSelectButton">
|
||||
<property name="text">
|
||||
<string>Select</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="cacheHorizontalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="cacheLabel">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>63</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Cache Folder</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="cacheLineEdit"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="cacheSelectFolderButton">
|
||||
<property name="text">
|
||||
<string>Select Folder</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
<widget class="QLabel" name="dragDropLabelTop">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>15</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>**Drag and drop file or folder anywhere in this window to select input file/folder.**</string>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::MarkdownText</enum>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="dragDropLabelBottom">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>15</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>**Drop item on a specific input box to set the value of that box.**</string>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::MarkdownText</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="inputSelectionGroupBox">
|
||||
<property name="title">
|
||||
<string>Input Selection</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_5">
|
||||
<item>
|
||||
<widget class="QTableView" name="inputTableView"/>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="inputButtonsHorizontalLayout">
|
||||
<item>
|
||||
<widget class="QPushButton" name="inputSelectFileButton">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Select File</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="inputSelectFolderButton">
|
||||
<property name="text">
|
||||
<string>Select Folder</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="inputDeleteSelectedButton">
|
||||
<property name="text">
|
||||
<string>Delete Selected</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="inputClearAllButton">
|
||||
<property name="text">
|
||||
<string>Clear All</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="otherPathsSelectionGroupBox">
|
||||
<property name="title">
|
||||
<string>Other Paths Selection</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_9">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="outputHorizontalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="outputLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>63</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Output</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="outputLineEdit"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="outputSelectFileButton">
|
||||
<property name="text">
|
||||
<string>Select File</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="outputSelectFolderButton">
|
||||
<property name="text">
|
||||
<string>Select Folder</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="configHorizontalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="configLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>63</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Config</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="configLineEdit"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="configSelectButton">
|
||||
<property name="text">
|
||||
<string>Select</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="cacheHorizontalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="cacheLabel">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>63</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Cache Folder</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="cacheLineEdit"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="cacheSelectFolderButton">
|
||||
<property name="text">
|
||||
<string>Select Folder</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="expressSettingsGroupBox">
|
||||
@@ -1229,72 +1276,184 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="controlsVerticalLayout">
|
||||
<item>
|
||||
<widget class="QProgressBar" name="progressBar">
|
||||
<property name="value">
|
||||
<number>0</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="timeControlsHorizontalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="timeElapsedLabel">
|
||||
<property name="acceptDrops">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Time Elapsed: 00:00:00</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="timeRemainingLabel">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Time Remaining: 00:00:00</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="rateLabel">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Rate (FPS): 0.0</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="startButton">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Start</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="stopButton">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Stop</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
<widget class="QGroupBox" name="currentVideoProcessingProgressGroupBox">
|
||||
<property name="title">
|
||||
<string>Current Video Processing Progress</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_11">
|
||||
<item>
|
||||
<widget class="QLabel" name="currentlyProcessingLabel">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Currently Processing:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QProgressBar" name="currentProgressBar">
|
||||
<property name="value">
|
||||
<number>0</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="currentlyProcessingInfoHorizontalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="timeElapsedLabel">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="acceptDrops">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Time Elapsed: 00:00:00</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="timeRemainingLabel">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Time Remaining: 00:00:00</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="rateLabel">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Rate (FPS): 0.0</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="framesLabel">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Frames: 0/0</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="overallVideoProcessingProgressGroupBox">
|
||||
<property name="title">
|
||||
<string>Overall Video Processing Progress</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_13">
|
||||
<item>
|
||||
<widget class="QProgressBar" name="overallProgressBar">
|
||||
<property name="value">
|
||||
<number>0</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="overallProcessingHorizontalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="overallProgressLabel">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Overall Progress: 0/0</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="startButton">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>130</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Start</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="stopButton">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>130</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Stop</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
@@ -1303,7 +1462,7 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>691</width>
|
||||
<width>718</width>
|
||||
<height>21</height>
|
||||
</rect>
|
||||
</property>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
Name: Video2X Setup Script
|
||||
Creator: K4YT3X
|
||||
Date Created: November 28, 2018
|
||||
Last Modified: May 7, 2020
|
||||
Last Modified: May 8, 2020
|
||||
|
||||
Editor: BrianPetkovsek
|
||||
Editor: SAT3LL
|
||||
@@ -261,7 +261,7 @@ class Video2xSetup:
|
||||
# configure only the specified drivers
|
||||
if self.driver == 'all':
|
||||
template_dict['waifu2x_caffe']['path'] = str(LOCALAPPDATA / 'video2x' / 'waifu2x-caffe' / 'waifu2x-caffe-cui')
|
||||
template_dict['waifu2x_converter_cpp']['path'] = str(LOCALAPPDATA / 'video2x' / 'waifu2x-converter-cpp')
|
||||
template_dict['waifu2x_converter_cpp']['path'] = str(LOCALAPPDATA / 'video2x' / 'waifu2x-converter-cpp' / 'waifu2x-converter-cpp')
|
||||
template_dict['waifu2x_ncnn_vulkan']['path'] = str(LOCALAPPDATA / 'video2x' / 'waifu2x-ncnn-vulkan' / 'waifu2x-ncnn-vulkan')
|
||||
template_dict['srmd_ncnn_vulkan']['path'] = str(LOCALAPPDATA / 'video2x' / 'srmd-ncnn-vulkan' / 'srmd-ncnn-vulkan')
|
||||
template_dict['anime4kcpp']['path'] = str(LOCALAPPDATA / 'video2x' / 'anime4kcpp' / 'CLI' / 'Anime4KCPP_CLI' / 'Anime4KCPP_CLI')
|
||||
|
||||
@@ -45,7 +45,7 @@ class WrapperMain:
|
||||
parser.add_argument('-z', '--zoomFactor', type=float, help='zoom factor for resizing')
|
||||
parser.add_argument('-t', '--threads', type=int, help='Threads count for video processing')
|
||||
parser.add_argument('-f', '--fastMode', action='store_true', help='Faster but maybe low quality')
|
||||
# parser.add_argument('-v', '--videoMode', action='store_true', help='Video process')
|
||||
parser.add_argument('-v', '--videoMode', action='store_true', help='Video process')
|
||||
parser.add_argument('-s', '--preview', action='store_true', help='Preview image')
|
||||
parser.add_argument('-b', '--preprocessing', action='store_true', help='Enable pre processing')
|
||||
parser.add_argument('-a', '--postprocessing', action='store_true', help='Enable post processing')
|
||||
@@ -73,7 +73,7 @@ class WrapperMain:
|
||||
self.driver_settings['output'] = output_file
|
||||
self.driver_settings['zoomFactor'] = zoom_factor
|
||||
self.driver_settings['threads'] = threads
|
||||
|
||||
|
||||
# Anime4KCPP will look for Anime4KCPPKernel.cl under the current working directory
|
||||
# change the CWD to its containing directory so it will find it
|
||||
if platform.system() == 'Windows':
|
||||
|
||||
@@ -45,7 +45,7 @@ class WrapperMain:
|
||||
parser.add_argument('-l', '--list-processor', action='store_true', help='dump processor list')
|
||||
parser.add_argument('-f', '--output-format', choices=['png', 'jpg'], help='The format used when running in recursive/folder mode\nSee --list-supported-formats for a list of supported formats/extensions.')
|
||||
parser.add_argument('-c', '--png-compression', type=int, choices=range(10), help='Set PNG compression level (0-9), 9 = Max compression (slowest & smallest)')
|
||||
parser.add_argument('-q', '--image-quality', type=int, choices=range(100), help='JPEG & WebP Compression quality (0-101, 0 being smallest size and lowest quality), use 101 for lossless WebP')
|
||||
parser.add_argument('-q', '--image-quality', type=int, choices=range(-1, 102), help='JPEG & WebP Compression quality (0-101, 0 being smallest size and lowest quality), use 101 for lossless WebP')
|
||||
parser.add_argument('--block-size', type=int, help='block size')
|
||||
parser.add_argument('--disable-gpu', action='store_true', help='disable GPU')
|
||||
parser.add_argument('--force-OpenCL', action='store_true', help='force to use OpenCL on Intel Platform')
|
||||
|
||||
Reference in New Issue
Block a user