mirror of
https://github.com/k4yt3x/video2x.git
synced 2026-02-15 17:54:49 +08:00
Compare commits
30 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 | ||
|
|
36aa3bf1d4 | ||
|
|
9dde3c66f1 | ||
|
|
e9c1c22788 | ||
|
|
134e8b7080 | ||
|
|
a295b4a54f | ||
|
|
c198082190 | ||
|
|
8f2dc43af3 | ||
|
|
b0ce8f3ff9 | ||
|
|
0b1f7b8422 | ||
|
|
def20650e2 | ||
|
|
7489376404 | ||
|
|
826279ce09 | ||
|
|
88d2cd9e14 |
6
.gitignore
vendored
6
.gitignore
vendored
@@ -1,9 +1,3 @@
|
|||||||
# Runtime files
|
|
||||||
upscaled/
|
|
||||||
frames/
|
|
||||||
waifu2x-caffe/
|
|
||||||
testvid.mp4
|
|
||||||
|
|
||||||
# PyCharm
|
# PyCharm
|
||||||
.idea/
|
.idea/
|
||||||
|
|
||||||
|
|||||||
14
README.md
14
README.md
@@ -72,6 +72,8 @@ Watch for the sharper edges in this screenshot around the shadows:
|
|||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
*Upscale Comparison Demonstration*
|
||||||
|
|
||||||
**You can also watch the YouTube video Demo: https://www.youtube.com/watch?v=PG94iPoeoZk**
|
**You can also watch the YouTube video Demo: https://www.youtube.com/watch?v=PG94iPoeoZk**
|
||||||
|
|
||||||
Clip is from trailer of animated movie "千と千尋の神隠し". Copyright belongs to "株式会社スタジオジブリ (STUDIO GHIBLI INC.)". Will delete immediately if use of clip is in violation of copyright.
|
Clip is from trailer of animated movie "千と千尋の神隠し". Copyright belongs to "株式会社スタジオジブリ (STUDIO GHIBLI INC.)". Will delete immediately if use of clip is in violation of copyright.
|
||||||
@@ -80,12 +82,20 @@ Clip is from trailer of animated movie "千と千尋の神隠し". Copyright bel
|
|||||||
|
|
||||||
### Video2X GUI
|
### Video2X GUI
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
*Video2X GUI Main Tab Screenshot*
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
*Video2X GUI Driver Settings Screenshot*
|
||||||
|
|
||||||
### Video2X CLI
|
### Video2X CLI
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
*Video2X CLI Screenshot*
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Documentations
|
## Documentations
|
||||||
@@ -158,6 +168,8 @@ If you can't find a video clip to begin with, or if you want to see a before-aft
|
|||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
*Sample Upscale Videos*
|
||||||
|
|
||||||
- [Sample Video Original (240P) 1.7MB](https://files.k4yt3x.com/Resources/Videos/sample_input.mp4)
|
- [Sample Video Original (240P) 1.7MB](https://files.k4yt3x.com/Resources/Videos/sample_input.mp4)
|
||||||
- [Sample Video Upscaled (1080P) 4.8MB](https://files.k4yt3x.com/Resources/Videos/sample_output.mp4)
|
- [Sample Video Upscaled (1080P) 4.8MB](https://files.k4yt3x.com/Resources/Videos/sample_output.mp4)
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
Name: Video2X Build Script
|
Name: Video2X Build Script
|
||||||
Creator: K4YT3X
|
Creator: K4YT3X
|
||||||
Date Created: May 6, 2020
|
Date Created: May 6, 2020
|
||||||
Last Modified: May 6, 2020
|
Last Modified: May 7, 2020
|
||||||
|
|
||||||
Description: A PowerShell script that will build Video2X
|
Description: A PowerShell script that will build Video2X
|
||||||
executable (PE) releases automatically using PyInstaller.
|
executable (PE) releases automatically using PyInstaller.
|
||||||
@@ -12,12 +12,18 @@ To start a PowerShell session with execution policy bypass
|
|||||||
powershell –ExecutionPolicy Bypass
|
powershell –ExecutionPolicy Bypass
|
||||||
#>
|
#>
|
||||||
|
|
||||||
|
if ($args.count -ne 1){
|
||||||
|
Write-Host -ForegroundColor White "Usage:`n .\build.ps1 VIDEO2X_VERSION"
|
||||||
|
Exit
|
||||||
|
}
|
||||||
|
|
||||||
# version number
|
# version number
|
||||||
$SCRIPT_VERSION = "1.0.0"
|
$SCRIPT_VERSION = "1.0.1"
|
||||||
$VIDEO2X_VERSION = "4.0.0"
|
$VIDEO2X_VERSION = $args[0]
|
||||||
|
|
||||||
Write-Host -ForegroundColor White "Video2X Building Script Version $($SCRIPT_VERSION)
|
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
|
# build Video2X CLI
|
||||||
Write-Host -ForegroundColor White "`nBuilding Video2X CLI"
|
Write-Host -ForegroundColor White "`nBuilding Video2X CLI"
|
||||||
@@ -46,33 +52,33 @@ pyinstaller --noconfirm --log-level=WARN `
|
|||||||
video2x_setup.py
|
video2x_setup.py
|
||||||
|
|
||||||
# remove old builds if found
|
# remove old builds if found
|
||||||
if (Test-Path "video2x-builds" -PathType any) {
|
if (Test-Path "$($VIDEO2X_VERSION)" -PathType any) {
|
||||||
Remove-Item -path "video2x-builds" -recurse
|
Remove-Item -path "$($VIDEO2X_VERSION)" -recurse
|
||||||
}
|
}
|
||||||
|
|
||||||
# create build directory
|
# create build directory
|
||||||
New-Item "video2x-builds" -ItemType Directory
|
New-Item "$($VIDEO2X_VERSION)" -ItemType Directory
|
||||||
|
|
||||||
# copy files into corresponding builds
|
# copy files into corresponding builds
|
||||||
# full edition
|
# full edition
|
||||||
Write-Host -ForegroundColor White "`nCreating full package"
|
Write-Host -ForegroundColor White "`nCreating full package"
|
||||||
New-Item "video2x-builds\video2x-$($VIDEO2X_VERSION)-win32-full" -ItemType Directory
|
New-Item "$($VIDEO2X_VERSION)\video2x-$($VIDEO2X_VERSION)-win32-full" -ItemType Directory
|
||||||
Copy-Item "dist\video2x.exe" -Destination "video2x-builds\video2x-$($VIDEO2X_VERSION)-win32-full\"
|
Copy-Item "dist\video2x.exe" -Destination "$($VIDEO2X_VERSION)\video2x-$($VIDEO2X_VERSION)-win32-full\"
|
||||||
Copy-Item "dist\video2x_gui.exe" -Destination "video2x-builds\video2x-$($VIDEO2X_VERSION)-win32-full\"
|
Copy-Item "dist\video2x_gui.exe" -Destination "$($VIDEO2X_VERSION)\video2x-$($VIDEO2X_VERSION)-win32-full\"
|
||||||
Copy-Item -Path "$env:LOCALAPPDATA\video2x" -Destination "video2x-builds\video2x-$($VIDEO2X_VERSION)-win32-full\dependencies" -Recurse
|
Copy-Item -Path "$env:LOCALAPPDATA\video2x" -Destination "$($VIDEO2X_VERSION)\video2x-$($VIDEO2X_VERSION)-win32-full\dependencies" -Recurse
|
||||||
|
|
||||||
# overwrite paths to relative paths
|
# overwrite paths to relative paths
|
||||||
(Get-Content "video2x.yaml").replace("C:\Users\K4YT3X\AppData\Local\video2x\", "dependencies\") | Set-Content "video2x.yaml.relative"
|
(Get-Content "video2x.yaml").replace("%LOCALAPPDATA%\video2x", "dependencies") | Set-Content "video2x.yaml.relative"
|
||||||
Move-Item "video2x.yaml.relative" -Destination "video2x-builds\video2x-$($VIDEO2X_VERSION)-win32-full\video2x.yaml"
|
Move-Item "video2x.yaml.relative" -Destination "$($VIDEO2X_VERSION)\video2x-$($VIDEO2X_VERSION)-win32-full\video2x.yaml"
|
||||||
|
|
||||||
# light edition
|
# light edition
|
||||||
Write-Host -ForegroundColor White "`nCreating light package"
|
Write-Host -ForegroundColor White "`nCreating light package"
|
||||||
New-Item "video2x-builds\video2x-$($VIDEO2X_VERSION)-win32-light" -ItemType Directory
|
New-Item "$($VIDEO2X_VERSION)\video2x-$($VIDEO2X_VERSION)-win32-light" -ItemType Directory
|
||||||
Copy-Item "dist\video2x.exe" -Destination "video2x-builds\video2x-$($VIDEO2X_VERSION)-win32-light\"
|
Copy-Item "dist\video2x.exe" -Destination "$($VIDEO2X_VERSION)\video2x-$($VIDEO2X_VERSION)-win32-light\"
|
||||||
Copy-Item "dist\video2x_gui.exe" -Destination "video2x-builds\video2x-$($VIDEO2X_VERSION)-win32-light\"
|
Copy-Item "dist\video2x_gui.exe" -Destination "$($VIDEO2X_VERSION)\video2x-$($VIDEO2X_VERSION)-win32-light\"
|
||||||
Copy-Item "dist\video2x_setup.exe" -Destination "video2x-builds\video2x-$($VIDEO2X_VERSION)-win32-light\"
|
Copy-Item "dist\video2x_setup.exe" -Destination "$($VIDEO2X_VERSION)\video2x-$($VIDEO2X_VERSION)-win32-light\"
|
||||||
Copy-Item "video2x.yaml" -Destination "video2x-builds\video2x-$($VIDEO2X_VERSION)-win32-light\"
|
Copy-Item "video2x.yaml" -Destination "$($VIDEO2X_VERSION)\video2x-$($VIDEO2X_VERSION)-win32-light\"
|
||||||
Copy-Item "requirements.txt" -Destination "video2x-builds\video2x-$($VIDEO2X_VERSION)-win32-light\"
|
Copy-Item "requirements.txt" -Destination "$($VIDEO2X_VERSION)\video2x-$($VIDEO2X_VERSION)-win32-light\"
|
||||||
|
|
||||||
# clean up temporary files
|
# clean up temporary files
|
||||||
Write-Host -ForegroundColor White "`nDeleting temporary files"
|
Write-Host -ForegroundColor White "`nDeleting temporary files"
|
||||||
|
|||||||
@@ -5,8 +5,8 @@
|
|||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: \n"
|
"Project-Id-Version: \n"
|
||||||
"POT-Creation-Date: 2020-05-04 19:14-0400\n"
|
"POT-Creation-Date: 2020-05-08 22:10-0400\n"
|
||||||
"PO-Revision-Date: 2020-05-04 19:16-0400\n"
|
"PO-Revision-Date: 2020-05-08 22:11-0400\n"
|
||||||
"Last-Translator: \n"
|
"Last-Translator: \n"
|
||||||
"Language-Team: \n"
|
"Language-Team: \n"
|
||||||
"Language: zh_CN\n"
|
"Language: zh_CN\n"
|
||||||
@@ -17,107 +17,167 @@ msgstr ""
|
|||||||
"X-Generator: Poedit 2.3\n"
|
"X-Generator: Poedit 2.3\n"
|
||||||
"Plural-Forms: nplurals=1; plural=0;\n"
|
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||||
|
|
||||||
#: upscaler.py:85
|
#: progress_monitor.py:42
|
||||||
msgid "Extracted frames are being saved to: {}"
|
|
||||||
msgstr "提取的帧将被保存到:{}"
|
|
||||||
|
|
||||||
#: upscaler.py:87
|
|
||||||
msgid "Upscaled frames are being saved to: {}"
|
|
||||||
msgstr "已放大的帧将被保存到:{}"
|
|
||||||
|
|
||||||
#: upscaler.py:97
|
|
||||||
msgid "Cleaning up cache directory: {}"
|
|
||||||
msgstr "清理缓存目录:{}"
|
|
||||||
|
|
||||||
#: upscaler.py:100
|
|
||||||
msgid "Unable to delete: {}"
|
|
||||||
msgstr "无法删除:{}"
|
|
||||||
|
|
||||||
#: upscaler.py:107
|
|
||||||
msgid "You must specify input video file/directory path"
|
|
||||||
msgstr "您必须指定输入视频文件/目录路径"
|
|
||||||
|
|
||||||
#: upscaler.py:110
|
|
||||||
msgid "You must specify output video file/directory path"
|
|
||||||
msgstr "您必须指定输出视频文件/目录路径"
|
|
||||||
|
|
||||||
#: upscaler.py:113
|
|
||||||
msgid "Selected driver accepts only scaling ratio"
|
|
||||||
msgstr "所选驱动程序仅接受缩放比率"
|
|
||||||
|
|
||||||
#: upscaler.py:116
|
|
||||||
msgid "Scaling ratio must be 1 or 2 for waifu2x_ncnn_vulkan"
|
|
||||||
msgstr "waifu2x_ncnn_vulkan 的缩放比必须为 1 或 2"
|
|
||||||
|
|
||||||
#: upscaler.py:119
|
|
||||||
msgid "Scaling ratio must be one of 2, 3 or 4 for srmd_ncnn_vulkan"
|
|
||||||
msgstr "srmd_ncnn_vulkan 的缩放比必须为 2、3 或 4"
|
|
||||||
|
|
||||||
#: upscaler.py:122
|
|
||||||
msgid "You can only specify either scaling ratio or output width and height"
|
|
||||||
msgstr "您只能指定缩放比或输出宽度和高度两者之一"
|
|
||||||
|
|
||||||
#: upscaler.py:125
|
|
||||||
msgid "You must specify both width and height"
|
|
||||||
msgstr "您必须同时指定宽度和高度"
|
|
||||||
|
|
||||||
#: upscaler.py:142
|
|
||||||
msgid "Upscaling Progress"
|
msgid "Upscaling Progress"
|
||||||
msgstr "放大进度"
|
msgstr "放大进度"
|
||||||
|
|
||||||
#: upscaler.py:179
|
#: upscaler.py:105
|
||||||
|
msgid "Specified or default cache directory is a file/link"
|
||||||
|
msgstr "指定或默认的缓存目录是文件/链接"
|
||||||
|
|
||||||
|
#: upscaler.py:111
|
||||||
|
msgid "Creating cache directory {}"
|
||||||
|
msgstr "创建缓存目录 {}"
|
||||||
|
|
||||||
|
#: upscaler.py:114
|
||||||
|
msgid "Unable to create {}"
|
||||||
|
msgstr "无法创建 {}"
|
||||||
|
|
||||||
|
#: upscaler.py:119
|
||||||
|
msgid "Extracted frames are being saved to: {}"
|
||||||
|
msgstr "提取的帧将被保存到:{}"
|
||||||
|
|
||||||
|
#: upscaler.py:121
|
||||||
|
msgid "Upscaled frames are being saved to: {}"
|
||||||
|
msgstr "已放大的帧将被保存到:{}"
|
||||||
|
|
||||||
|
#: upscaler.py:131
|
||||||
|
msgid "Cleaning up cache directory: {}"
|
||||||
|
msgstr "清理缓存目录:{}"
|
||||||
|
|
||||||
|
#: upscaler.py:134
|
||||||
|
msgid "Unable to delete: {}"
|
||||||
|
msgstr "无法删除:{}"
|
||||||
|
|
||||||
|
#: 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:159
|
||||||
|
msgid "No suffix found in output file path"
|
||||||
|
msgstr "在输出文件路径中未找到后缀"
|
||||||
|
|
||||||
|
#: upscaler.py:160
|
||||||
|
msgid "Suffix must be specified for FFmpeg"
|
||||||
|
msgstr "必须为 FFmpeg 指定后缀"
|
||||||
|
|
||||||
|
#: upscaler.py:167
|
||||||
|
msgid "Input is directory but output is existing single file"
|
||||||
|
msgstr "输入是目录,但输出是现有的单个文件"
|
||||||
|
|
||||||
|
#: upscaler.py:176
|
||||||
|
msgid "Input path is neither a file nor a directory"
|
||||||
|
msgstr "输入路径既不是文件也不是目录"
|
||||||
|
|
||||||
|
#: upscaler.py:185
|
||||||
|
msgid "FFmpeg or FFprobe cannot be found under the specified path"
|
||||||
|
msgstr "在指定的路径下找不到 FFmpeg 或 FFprobe"
|
||||||
|
|
||||||
|
#: upscaler.py:186 upscaler.py:196
|
||||||
|
msgid "Please check the configuration file settings"
|
||||||
|
msgstr "请检查配置文件设置"
|
||||||
|
|
||||||
|
#: upscaler.py:195
|
||||||
|
msgid "Specified driver executable directory doesn't exist"
|
||||||
|
msgstr "指定驱动的可执行文件不存在"
|
||||||
|
|
||||||
|
#: upscaler.py:222
|
||||||
|
msgid "Failed to parse driver argument: {}"
|
||||||
|
msgstr "解析驱动程序参数失败:{}"
|
||||||
|
|
||||||
|
#: upscaler.py:237
|
||||||
msgid "Unrecognized driver: {}"
|
msgid "Unrecognized driver: {}"
|
||||||
msgstr "无法识别的驱动名称:{}"
|
msgstr "无法识别的驱动名称:{}"
|
||||||
|
|
||||||
#: upscaler.py:258
|
#: upscaler.py:309
|
||||||
|
msgid "Starting progress monitor"
|
||||||
|
msgstr "启动进度监视器"
|
||||||
|
|
||||||
|
#: upscaler.py:314
|
||||||
msgid "Starting upscaled image cleaner"
|
msgid "Starting upscaled image cleaner"
|
||||||
msgstr "启动已放大图像清理程序"
|
msgstr "启动已放大图像清理程序"
|
||||||
|
|
||||||
#: upscaler.py:264
|
#: upscaler.py:323 upscaler.py:340
|
||||||
msgid "Main process waiting for subprocesses to exit"
|
msgid "Killing progress monitor"
|
||||||
msgstr "主进程开始等待子进程结束"
|
msgstr "终结进度监视器"
|
||||||
|
|
||||||
#: upscaler.py:266
|
#: upscaler.py:326 upscaler.py:343
|
||||||
msgid "Subprocess {} exited with code {}"
|
|
||||||
msgstr "子进程 {} 结束,返回码 {}"
|
|
||||||
|
|
||||||
#: upscaler.py:274 upscaler.py:287
|
|
||||||
msgid "Killing upscaled image cleaner"
|
msgid "Killing upscaled image cleaner"
|
||||||
msgstr "终结已放大图像清理程序"
|
msgstr "终结已放大图像清理程序"
|
||||||
|
|
||||||
#: upscaler.py:313 upscaler.py:368
|
#: upscaler.py:347
|
||||||
|
msgid "Terminating all processes"
|
||||||
|
msgstr "正在终止所有进程"
|
||||||
|
|
||||||
|
#: upscaler.py:354
|
||||||
|
msgid "Main process waiting for subprocesses to exit"
|
||||||
|
msgstr "主进程开始等待子进程结束"
|
||||||
|
|
||||||
|
#: upscaler.py:373 upscaler.py:377
|
||||||
|
msgid "Subprocess {} exited with code {}"
|
||||||
|
msgstr "子进程 {} 结束,返回码 {}"
|
||||||
|
|
||||||
|
#: upscaler.py:383
|
||||||
|
msgid "Stop signal received"
|
||||||
|
msgstr "收到停止信号"
|
||||||
|
|
||||||
|
#: upscaler.py:388
|
||||||
|
msgid "Subprocess execution ran into an error"
|
||||||
|
msgstr "子进程执行遇到错误"
|
||||||
|
|
||||||
|
#: upscaler.py:430
|
||||||
|
msgid "Upscaling single video file: {}"
|
||||||
|
msgstr "放大单个视频文件:{}"
|
||||||
|
|
||||||
|
#: upscaler.py:452 upscaler.py:515
|
||||||
msgid "Starting to upscale extracted images"
|
msgid "Starting to upscale extracted images"
|
||||||
msgstr "开始对提取的帧进行放大"
|
msgstr "开始对提取的帧进行放大"
|
||||||
|
|
||||||
#: upscaler.py:316 upscaler.py:370
|
#: upscaler.py:461 upscaler.py:517
|
||||||
msgid "Upscaling completed"
|
msgid "Upscaling completed"
|
||||||
msgstr "放大完成"
|
msgstr "放大完成"
|
||||||
|
|
||||||
#: upscaler.py:324
|
#: upscaler.py:470
|
||||||
msgid "Reading video information"
|
msgid "Reading video information"
|
||||||
msgstr "读取视频信息"
|
msgstr "读取视频信息"
|
||||||
|
|
||||||
#: upscaler.py:338
|
#: upscaler.py:484
|
||||||
msgid "Aborting: No video stream found"
|
msgid "Aborting: No video stream found"
|
||||||
msgstr "程序中止:文件中未找到视频流"
|
msgstr "程序中止:文件中未找到视频流"
|
||||||
|
|
||||||
#: upscaler.py:355
|
#: upscaler.py:502
|
||||||
msgid "Unsupported pixel format: {}"
|
msgid "Unsupported pixel format: {}"
|
||||||
msgstr "不支持的像素格式:{}"
|
msgstr "不支持的像素格式:{}"
|
||||||
|
|
||||||
#: upscaler.py:358
|
#: upscaler.py:505
|
||||||
msgid "Framerate: {}"
|
msgid "Framerate: {}"
|
||||||
msgstr "帧率:{}"
|
msgstr "帧率:{}"
|
||||||
|
|
||||||
#: upscaler.py:373
|
#: upscaler.py:520
|
||||||
msgid "Converting extracted frames into video"
|
msgid "Converting extracted frames into video"
|
||||||
msgstr "将提取的帧转换为视频"
|
msgstr "将提取的帧转换为视频"
|
||||||
|
|
||||||
#: upscaler.py:377
|
#: upscaler.py:525
|
||||||
msgid "Conversion completed"
|
msgid "Conversion completed"
|
||||||
msgstr "转换已完成"
|
msgstr "转换已完成"
|
||||||
|
|
||||||
#: upscaler.py:380
|
#: upscaler.py:528
|
||||||
msgid "Migrating audio tracks and subtitles to upscaled video"
|
msgid "Migrating audio tracks and subtitles to upscaled video"
|
||||||
msgstr "将音轨和字幕迁移到放大后的视频"
|
msgstr "将音轨和字幕迁移到放大后的视频"
|
||||||
|
|
||||||
@@ -187,58 +247,34 @@ msgstr "缩放比"
|
|||||||
msgid "This file cannot be imported"
|
msgid "This file cannot be imported"
|
||||||
msgstr "此文件无法被当作模块导入"
|
msgstr "此文件无法被当作模块导入"
|
||||||
|
|
||||||
#: video2x.py:193
|
|
||||||
msgid "Specified driver executable directory doesn't exist"
|
|
||||||
msgstr "指定驱动的可执行文件不存在"
|
|
||||||
|
|
||||||
#: video2x.py:194
|
|
||||||
msgid "Please check the configuration file settings"
|
|
||||||
msgstr "请检查配置文件设置"
|
|
||||||
|
|
||||||
#: video2x.py:211
|
|
||||||
msgid "Specified cache directory is a file/link"
|
|
||||||
msgstr "指定的缓存目录是文件/链接"
|
|
||||||
|
|
||||||
#: video2x.py:218
|
|
||||||
msgid "Creating cache directory {}"
|
|
||||||
msgstr "创建缓存目录 {}"
|
|
||||||
|
|
||||||
#: video2x.py:224
|
#: video2x.py:224
|
||||||
msgid "Unable to create {}"
|
|
||||||
msgstr "无法创建 {}"
|
|
||||||
|
|
||||||
#: video2x.py:237
|
|
||||||
msgid "Upscaling single video file: {}"
|
|
||||||
msgstr "放大单个视频文件:{}"
|
|
||||||
|
|
||||||
#: video2x.py:241
|
|
||||||
msgid "Input and output path type mismatch"
|
|
||||||
msgstr "输入和输出路径类型不匹配"
|
|
||||||
|
|
||||||
#: video2x.py:242
|
|
||||||
msgid "Input is single file but output is directory"
|
|
||||||
msgstr "所选的输入路径是单个文件,但输出路径是目录"
|
|
||||||
|
|
||||||
#: video2x.py:245
|
|
||||||
msgid "No suffix found in output file path"
|
|
||||||
msgstr "在输出文件路径中未找到后缀"
|
|
||||||
|
|
||||||
#: video2x.py:246
|
|
||||||
msgid "Suffix must be specified for FFmpeg"
|
|
||||||
msgstr "必须为 FFmpeg 指定后缀"
|
|
||||||
|
|
||||||
#: video2x.py:270
|
|
||||||
msgid "Upscaling videos in directory: {}"
|
|
||||||
msgstr "放大该文件夹中的所有视频:{}"
|
|
||||||
|
|
||||||
#: video2x.py:295
|
|
||||||
msgid "Input path is neither a file nor a directory"
|
|
||||||
msgstr "输入路径既不是文件也不是目录"
|
|
||||||
|
|
||||||
#: video2x.py:298
|
|
||||||
msgid "Program completed, taking {} seconds"
|
msgid "Program completed, taking {} seconds"
|
||||||
msgstr "程序执行完毕,总计花费 {} 秒"
|
msgstr "程序执行完毕,总计花费 {} 秒"
|
||||||
|
|
||||||
#: video2x.py:301
|
#: video2x.py:227
|
||||||
msgid "An exception has occurred"
|
msgid "An exception has occurred"
|
||||||
msgstr "发生了异常"
|
msgstr "发生了异常"
|
||||||
|
|
||||||
|
#~ msgid "You must specify input video file/directory path"
|
||||||
|
#~ msgstr "您必须指定输入视频文件/目录路径"
|
||||||
|
|
||||||
|
#~ msgid "You must specify output video file/directory path"
|
||||||
|
#~ msgstr "您必须指定输出视频文件/目录路径"
|
||||||
|
|
||||||
|
#~ msgid "Selected driver accepts only scaling ratio"
|
||||||
|
#~ msgstr "所选驱动程序仅接受缩放比率"
|
||||||
|
|
||||||
|
#~ msgid "Scaling ratio must be 1 or 2 for waifu2x_ncnn_vulkan"
|
||||||
|
#~ msgstr "waifu2x_ncnn_vulkan 的缩放比必须为 1 或 2"
|
||||||
|
|
||||||
|
#~ msgid "Scaling ratio must be one of 2, 3 or 4 for srmd_ncnn_vulkan"
|
||||||
|
#~ msgstr "srmd_ncnn_vulkan 的缩放比必须为 2、3 或 4"
|
||||||
|
|
||||||
|
#~ msgid "You can only specify either scaling ratio or output width and height"
|
||||||
|
#~ msgstr "您只能指定缩放比或输出宽度和高度两者之一"
|
||||||
|
|
||||||
|
#~ msgid "You must specify both width and height"
|
||||||
|
#~ msgstr "您必须同时指定宽度和高度"
|
||||||
|
|
||||||
|
#~ msgid "Upscaling videos in directory: {}"
|
||||||
|
#~ msgstr "放大该文件夹中的所有视频:{}"
|
||||||
|
|||||||
61
src/progress_monitor.py
Normal file
61
src/progress_monitor.py
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"""
|
||||||
|
Name: Video2X Upscale Progress Monitor
|
||||||
|
Author: BrianPetkovsek
|
||||||
|
Date Created: May 7, 2020
|
||||||
|
Last Modified: May 7, 2020
|
||||||
|
"""
|
||||||
|
|
||||||
|
# built-in imports
|
||||||
|
import contextlib
|
||||||
|
import threading
|
||||||
|
import time
|
||||||
|
|
||||||
|
# third-party imports
|
||||||
|
from tqdm import tqdm
|
||||||
|
|
||||||
|
|
||||||
|
class ProgressMonitor(threading.Thread):
|
||||||
|
""" progress monitor
|
||||||
|
|
||||||
|
This class provides progress monitoring functionalities
|
||||||
|
by keeping track of the amount of frames in the input
|
||||||
|
directory and the output directory. This is originally
|
||||||
|
suggested by @ArmandBernard.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, upscaler, extracted_frames_directories):
|
||||||
|
threading.Thread.__init__(self)
|
||||||
|
self.upscaler = upscaler
|
||||||
|
self.extracted_frames_directories = extracted_frames_directories
|
||||||
|
self.running = False
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
self.running = True
|
||||||
|
|
||||||
|
# get number of extracted frames
|
||||||
|
self.upscaler.total_frames = 0
|
||||||
|
for directory in self.extracted_frames_directories:
|
||||||
|
self.upscaler.total_frames += len([f for f in directory.iterdir() if str(f).lower().endswith(self.upscaler.image_format.lower())])
|
||||||
|
|
||||||
|
with tqdm(total=self.upscaler.total_frames, ascii=True, desc=_('Upscaling Progress')) as progress_bar:
|
||||||
|
# tqdm update method adds the value to the progress
|
||||||
|
# bar instead of setting the value. Therefore, a delta
|
||||||
|
# needs to be calculated.
|
||||||
|
previous_cycle_frames = 0
|
||||||
|
while self.running:
|
||||||
|
|
||||||
|
with contextlib.suppress(FileNotFoundError):
|
||||||
|
self.upscaler.total_frames_upscaled = len([f for f in self.upscaler.upscaled_frames.iterdir() if str(f).lower().endswith(self.upscaler.image_format.lower())])
|
||||||
|
|
||||||
|
# update progress bar
|
||||||
|
delta = self.upscaler.total_frames_upscaled - previous_cycle_frames
|
||||||
|
previous_cycle_frames = self.upscaler.total_frames_upscaled
|
||||||
|
progress_bar.update(delta)
|
||||||
|
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
|
def stop(self):
|
||||||
|
self.running = False
|
||||||
|
self.join()
|
||||||
499
src/upscaler.py
499
src/upscaler.py
@@ -4,7 +4,7 @@
|
|||||||
Name: Video2X Upscaler
|
Name: Video2X Upscaler
|
||||||
Author: K4YT3X
|
Author: K4YT3X
|
||||||
Date Created: December 10, 2018
|
Date Created: December 10, 2018
|
||||||
Last Modified: May 6, 2020
|
Last Modified: May 8, 2020
|
||||||
|
|
||||||
Description: This file contains the Upscaler class. Each
|
Description: This file contains the Upscaler class. Each
|
||||||
instance of the Upscaler class is an upscaler on an image or
|
instance of the Upscaler class is an upscaler on an image or
|
||||||
@@ -14,6 +14,7 @@ a folder.
|
|||||||
# local imports
|
# local imports
|
||||||
from exceptions import *
|
from exceptions import *
|
||||||
from image_cleaner import ImageCleaner
|
from image_cleaner import ImageCleaner
|
||||||
|
from progress_monitor import ProgressMonitor
|
||||||
from wrappers.ffmpeg import Ffmpeg
|
from wrappers.ffmpeg import Ffmpeg
|
||||||
|
|
||||||
# built-in imports
|
# built-in imports
|
||||||
@@ -25,17 +26,16 @@ import importlib
|
|||||||
import locale
|
import locale
|
||||||
import os
|
import os
|
||||||
import pathlib
|
import pathlib
|
||||||
|
import queue
|
||||||
import re
|
import re
|
||||||
import shutil
|
import shutil
|
||||||
import sys
|
import subprocess
|
||||||
import tempfile
|
import tempfile
|
||||||
import threading
|
|
||||||
import time
|
import time
|
||||||
import traceback
|
import traceback
|
||||||
|
|
||||||
# third-party imports
|
# third-party imports
|
||||||
from avalon_framework import Avalon
|
from avalon_framework import Avalon
|
||||||
from tqdm import tqdm
|
|
||||||
|
|
||||||
# internationalization constants
|
# internationalization constants
|
||||||
DOMAIN = 'video2x'
|
DOMAIN = 'video2x'
|
||||||
@@ -67,10 +67,10 @@ class Upscaler:
|
|||||||
ArgumentError -- if argument is not valid
|
ArgumentError -- if argument is not valid
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, input_video, output_video, driver_settings, ffmpeg_settings):
|
def __init__(self, input_path, output_path, driver_settings, ffmpeg_settings):
|
||||||
# mandatory arguments
|
# mandatory arguments
|
||||||
self.input_video = input_video
|
self.input = input_path
|
||||||
self.output_video = output_video
|
self.output = output_path
|
||||||
self.driver_settings = driver_settings
|
self.driver_settings = driver_settings
|
||||||
self.ffmpeg_settings = ffmpeg_settings
|
self.ffmpeg_settings = ffmpeg_settings
|
||||||
|
|
||||||
@@ -84,14 +84,36 @@ class Upscaler:
|
|||||||
self.image_format = 'png'
|
self.image_format = 'png'
|
||||||
self.preserve_frames = False
|
self.preserve_frames = False
|
||||||
|
|
||||||
|
# other internal members and signals
|
||||||
|
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):
|
def create_temp_directories(self):
|
||||||
"""create temporary directory
|
"""create temporary directories
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# create a new temp directory if the current one is not found
|
# if cache directory unspecified, use %TEMP%\video2x
|
||||||
if not self.video2x_cache_directory.exists():
|
if self.video2x_cache_directory is None:
|
||||||
self.video2x_cache_directory = pathlib.Path(tempfile.gettempdir()) / 'video2x'
|
self.video2x_cache_directory = pathlib.Path(tempfile.gettempdir()) / 'video2x'
|
||||||
|
|
||||||
|
# if specified cache path exists and isn't a directory
|
||||||
|
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:
|
||||||
|
Avalon.debug_info(_('Creating cache directory {}').format(self.video2x_cache_directory))
|
||||||
|
self.video2x_cache_directory.mkdir(parents=True, exist_ok=True)
|
||||||
|
except Exception as exception:
|
||||||
|
Avalon.error(_('Unable to create {}').format(self.video2x_cache_directory))
|
||||||
|
raise exception
|
||||||
|
|
||||||
# create temp directories for extracted frames and upscaled frames
|
# create temp directories for extracted frames and upscaled frames
|
||||||
self.extracted_frames = pathlib.Path(tempfile.mkdtemp(dir=self.video2x_cache_directory))
|
self.extracted_frames = pathlib.Path(tempfile.mkdtemp(dir=self.video2x_cache_directory))
|
||||||
Avalon.debug_info(_('Extracted frames are being saved to: {}').format(self.extracted_frames))
|
Avalon.debug_info(_('Extracted frames are being saved to: {}').format(self.extracted_frames))
|
||||||
@@ -113,65 +135,92 @@ class Upscaler:
|
|||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
|
|
||||||
def _check_arguments(self):
|
def _check_arguments(self):
|
||||||
# check if arguments are valid / all necessary argument
|
if isinstance(self.input, list):
|
||||||
# values are specified
|
if self.output.exists() and not self.output.is_dir():
|
||||||
if not self.input_video:
|
Avalon.error(_('Input and output path type mismatch'))
|
||||||
Avalon.error(_('You must specify input video file/directory path'))
|
Avalon.error(_('Input is multiple files but output is not directory'))
|
||||||
raise ArgumentError('input video path not specified')
|
raise ArgumentError('input output path type mismatch')
|
||||||
if not self.output_video:
|
for input_path in self.input:
|
||||||
Avalon.error(_('You must specify output video file/directory path'))
|
if not input_path.is_file() and not input_path.is_dir():
|
||||||
raise ArgumentError('output video path not specified')
|
Avalon.error(_('Input path {} is neither a file nor a directory').format(input_path))
|
||||||
if (self.driver in ['waifu2x_converter', 'waifu2x_ncnn_vulkan', 'anime4k']) and self.scale_width and self.scale_height:
|
raise FileNotFoundError(f'{input_path} is neither file nor directory')
|
||||||
Avalon.error(_('Selected driver accepts only scaling ratio'))
|
|
||||||
raise ArgumentError('selected driver supports only scaling ratio')
|
|
||||||
if self.driver == 'waifu2x_ncnn_vulkan' and self.scale_ratio is not None and (self.scale_ratio > 2 or not self.scale_ratio.is_integer()):
|
|
||||||
Avalon.error(_('Scaling ratio must be 1 or 2 for waifu2x_ncnn_vulkan'))
|
|
||||||
raise ArgumentError('scaling ratio must be 1 or 2 for waifu2x_ncnn_vulkan')
|
|
||||||
if self.driver == 'srmd_ncnn_vulkan' and self.scale_ratio is not None and (self.scale_ratio not in [2, 3, 4]):
|
|
||||||
Avalon.error(_('Scaling ratio must be one of 2, 3 or 4 for srmd_ncnn_vulkan'))
|
|
||||||
raise ArgumentError('scaling ratio must be one of 2, 3 or 4 for srmd_ncnn_vulkan')
|
|
||||||
if (self.scale_width or self.scale_height) and self.scale_ratio:
|
|
||||||
Avalon.error(_('You can only specify either scaling ratio or output width and height'))
|
|
||||||
raise ArgumentError('both scaling ration and width/height specified')
|
|
||||||
if (self.scale_width and not self.scale_height) or (not self.scale_width and self.scale_height):
|
|
||||||
Avalon.error(_('You must specify both width and height'))
|
|
||||||
raise ArgumentError('only one of width or height is specified')
|
|
||||||
|
|
||||||
def _progress_bar(self, extracted_frames_directories):
|
|
||||||
""" This method prints a progress bar
|
|
||||||
|
|
||||||
This method prints a progress bar by keeping track
|
|
||||||
of the amount of frames in the input directory
|
|
||||||
and the output directory. This is originally
|
|
||||||
suggested by @ArmandBernard.
|
|
||||||
"""
|
|
||||||
|
|
||||||
# get number of extracted frames
|
|
||||||
self.total_frames = 0
|
|
||||||
for directory in extracted_frames_directories:
|
|
||||||
self.total_frames += len([f for f in directory.iterdir() if str(f).lower().endswith(self.image_format.lower())])
|
|
||||||
|
|
||||||
with tqdm(total=self.total_frames, ascii=True, desc=_('Upscaling Progress')) as progress_bar:
|
|
||||||
|
|
||||||
# tqdm update method adds the value to the progress
|
|
||||||
# bar instead of setting the value. Therefore, a delta
|
|
||||||
# needs to be calculated.
|
|
||||||
previous_cycle_frames = 0
|
|
||||||
while not self.progress_bar_exit_signal:
|
|
||||||
|
|
||||||
with contextlib.suppress(FileNotFoundError):
|
with contextlib.suppress(FileNotFoundError):
|
||||||
self.total_frames_upscaled = len([f for f in self.upscaled_frames.iterdir() if str(f).lower().endswith(self.image_format.lower())])
|
if input_path.samefile(self.output):
|
||||||
delta = self.total_frames_upscaled - previous_cycle_frames
|
Avalon.error(_('Input directory and output directory cannot be the same'))
|
||||||
previous_cycle_frames = self.total_frames_upscaled
|
raise FileExistsError('input directory and output directory are the same')
|
||||||
|
|
||||||
# if upscaling is finished
|
# if input is a file
|
||||||
if self.total_frames_upscaled >= self.total_frames:
|
elif self.input.is_file():
|
||||||
return
|
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)):
|
||||||
|
Avalon.error(_('No suffix found in output file path'))
|
||||||
|
Avalon.error(_('Suffix must be specified for FFmpeg'))
|
||||||
|
raise ArgumentError('no output video suffix specified')
|
||||||
|
|
||||||
# adds the delta into the progress bar
|
# if input is a directory
|
||||||
progress_bar.update(delta)
|
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')
|
||||||
|
|
||||||
time.sleep(1)
|
# if input is neither
|
||||||
|
else:
|
||||||
|
Avalon.error(_('Input path is neither a file nor a 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
|
||||||
|
pathlib.Path(ffmpeg_path / 'ffprobe.exe').is_file()) or
|
||||||
|
(pathlib.Path(ffmpeg_path / 'ffmpeg').is_file() and
|
||||||
|
pathlib.Path(ffmpeg_path / 'ffprobe').is_file())):
|
||||||
|
Avalon.error(_('FFmpeg or FFprobe cannot be found under the specified path'))
|
||||||
|
Avalon.error(_('Please check the configuration file settings'))
|
||||||
|
raise FileNotFoundError(self.ffmpeg_settings['ffmpeg_path'])
|
||||||
|
|
||||||
|
# check if driver settings
|
||||||
|
driver_settings = copy.deepcopy(self.driver_settings)
|
||||||
|
driver_path = driver_settings.pop('path')
|
||||||
|
|
||||||
|
# check if driver path exists
|
||||||
|
if not (pathlib.Path(driver_path).is_file() or pathlib.Path(f'{driver_path}.exe').is_file()):
|
||||||
|
Avalon.error(_('Specified driver executable directory doesn\'t exist'))
|
||||||
|
Avalon.error(_('Please check the configuration file settings'))
|
||||||
|
raise FileNotFoundError(driver_path)
|
||||||
|
|
||||||
|
# parse driver arguments using driver's parser
|
||||||
|
# the parser will throw AttributeError if argument doesn't satisfy constraints
|
||||||
|
try:
|
||||||
|
driver_arguments = []
|
||||||
|
for key in driver_settings.keys():
|
||||||
|
|
||||||
|
value = driver_settings[key]
|
||||||
|
|
||||||
|
if value is None or value is False:
|
||||||
|
continue
|
||||||
|
|
||||||
|
else:
|
||||||
|
if len(key) == 1:
|
||||||
|
driver_arguments.append(f'-{key}')
|
||||||
|
else:
|
||||||
|
driver_arguments.append(f'--{key}')
|
||||||
|
# true means key is an option
|
||||||
|
if value is not True:
|
||||||
|
driver_arguments.append(str(value))
|
||||||
|
|
||||||
|
DriverWrapperMain = getattr(importlib.import_module(f'wrappers.{self.driver}'), 'WrapperMain')
|
||||||
|
DriverWrapperMain.parse_arguments(driver_arguments)
|
||||||
|
except AttributeError as e:
|
||||||
|
Avalon.error(_('Failed to parse driver argument: {}').format(e.args[0]))
|
||||||
|
raise e
|
||||||
|
|
||||||
def _upscale_frames(self):
|
def _upscale_frames(self):
|
||||||
""" Upscale video frames with waifu2x-caffe
|
""" Upscale video frames with waifu2x-caffe
|
||||||
@@ -183,16 +232,10 @@ class Upscaler:
|
|||||||
w2 {Waifu2x Object} -- initialized waifu2x object
|
w2 {Waifu2x Object} -- initialized waifu2x object
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# progress bar process exit signal
|
|
||||||
self.progress_bar_exit_signal = False
|
|
||||||
|
|
||||||
# initialize waifu2x driver
|
# initialize waifu2x driver
|
||||||
if self.driver not in AVAILABLE_DRIVERS:
|
if self.driver not in AVAILABLE_DRIVERS:
|
||||||
raise UnrecognizedDriverError(_('Unrecognized driver: {}').format(self.driver))
|
raise UnrecognizedDriverError(_('Unrecognized driver: {}').format(self.driver))
|
||||||
|
|
||||||
# create a container for all upscaler processes
|
|
||||||
upscaler_processes = []
|
|
||||||
|
|
||||||
# list all images in the extracted frames
|
# list all images in the extracted frames
|
||||||
frames = [(self.extracted_frames / f) for f in self.extracted_frames.iterdir() if f.is_file]
|
frames = [(self.extracted_frames / f) for f in self.extracted_frames.iterdir() if f.is_file]
|
||||||
|
|
||||||
@@ -234,73 +277,117 @@ class Upscaler:
|
|||||||
|
|
||||||
# if the driver being used is waifu2x-caffe
|
# if the driver being used is waifu2x-caffe
|
||||||
if self.driver == 'waifu2x_caffe':
|
if self.driver == 'waifu2x_caffe':
|
||||||
upscaler_processes.append(driver.upscale(process_directory,
|
self.process_pool.append(driver.upscale(process_directory,
|
||||||
self.upscaled_frames,
|
self.upscaled_frames,
|
||||||
self.scale_ratio,
|
self.scale_ratio,
|
||||||
self.scale_width,
|
self.scale_width,
|
||||||
self.scale_height,
|
self.scale_height,
|
||||||
self.image_format,
|
self.image_format,
|
||||||
self.bit_depth))
|
self.bit_depth))
|
||||||
|
|
||||||
# if the driver being used is waifu2x-converter-cpp
|
# if the driver being used is waifu2x-converter-cpp
|
||||||
elif self.driver == 'waifu2x_converter_cpp':
|
elif self.driver == 'waifu2x_converter_cpp':
|
||||||
upscaler_processes.append(driver.upscale(process_directory,
|
self.process_pool.append(driver.upscale(process_directory,
|
||||||
self.upscaled_frames,
|
self.upscaled_frames,
|
||||||
self.scale_ratio,
|
self.scale_ratio,
|
||||||
self.processes,
|
self.processes,
|
||||||
self.image_format))
|
self.image_format))
|
||||||
|
|
||||||
# if the driver being used is waifu2x-ncnn-vulkan
|
# if the driver being used is waifu2x-ncnn-vulkan
|
||||||
elif self.driver == 'waifu2x_ncnn_vulkan':
|
elif self.driver == 'waifu2x_ncnn_vulkan':
|
||||||
upscaler_processes.append(driver.upscale(process_directory,
|
self.process_pool.append(driver.upscale(process_directory,
|
||||||
self.upscaled_frames,
|
self.upscaled_frames,
|
||||||
self.scale_ratio))
|
self.scale_ratio))
|
||||||
|
|
||||||
# if the driver being used is srmd_ncnn_vulkan
|
# if the driver being used is srmd_ncnn_vulkan
|
||||||
elif self.driver == 'srmd_ncnn_vulkan':
|
elif self.driver == 'srmd_ncnn_vulkan':
|
||||||
upscaler_processes.append(driver.upscale(process_directory,
|
self.process_pool.append(driver.upscale(process_directory,
|
||||||
self.upscaled_frames,
|
self.upscaled_frames,
|
||||||
self.scale_ratio))
|
self.scale_ratio))
|
||||||
|
|
||||||
# start progress bar in a different thread
|
# start progress bar in a different thread
|
||||||
progress_bar = threading.Thread(target=self._progress_bar, args=(process_directories,))
|
Avalon.debug_info(_('Starting progress monitor'))
|
||||||
progress_bar.start()
|
self.progress_monitor = ProgressMonitor(self, process_directories)
|
||||||
|
self.progress_monitor.start()
|
||||||
|
|
||||||
# create the clearer and start it
|
# create the clearer and start it
|
||||||
Avalon.debug_info(_('Starting upscaled image cleaner'))
|
Avalon.debug_info(_('Starting upscaled image cleaner'))
|
||||||
image_cleaner = ImageCleaner(self.extracted_frames, self.upscaled_frames, len(upscaler_processes))
|
self.image_cleaner = ImageCleaner(self.extracted_frames, self.upscaled_frames, len(self.process_pool))
|
||||||
image_cleaner.start()
|
self.image_cleaner.start()
|
||||||
|
|
||||||
# wait for all process to exit
|
# wait for all process to exit
|
||||||
try:
|
try:
|
||||||
Avalon.debug_info(_('Main process waiting for subprocesses to exit'))
|
self._wait()
|
||||||
for process in upscaler_processes:
|
except (Exception, KeyboardInterrupt, SystemExit) as e:
|
||||||
Avalon.debug_info(_('Subprocess {} exited with code {}').format(process.pid, process.wait()))
|
# cleanup
|
||||||
except (KeyboardInterrupt, SystemExit):
|
Avalon.debug_info(_('Killing progress monitor'))
|
||||||
Avalon.warning('Exit signal received')
|
self.progress_monitor.stop()
|
||||||
Avalon.warning('Killing processes')
|
|
||||||
for process in upscaler_processes:
|
|
||||||
process.terminate()
|
|
||||||
|
|
||||||
# cleanup and exit with exit code 1
|
|
||||||
Avalon.debug_info(_('Killing upscaled image cleaner'))
|
Avalon.debug_info(_('Killing upscaled image cleaner'))
|
||||||
image_cleaner.stop()
|
self.image_cleaner.stop()
|
||||||
self.progress_bar_exit_signal = True
|
raise e
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
# if the driver is waifu2x-converter-cpp
|
# if the driver is waifu2x-converter-cpp
|
||||||
# images need to be renamed to be recognizable for FFmpeg
|
# images need to be renamed to be recognizable for FFmpeg
|
||||||
if self.driver == 'waifu2x_converter_cpp':
|
if self.driver == 'waifu2x_converter_cpp':
|
||||||
for image in [f for f in self.upscaled_frames.iterdir() if f.is_file()]:
|
for image in [f for f in self.upscaled_frames.iterdir() if f.is_file()]:
|
||||||
renamed = re.sub(f'_\\[.*\\]\\[x(\\d+(\\.\\d+)?)\\]\\.{self.image_format}', f'.{self.image_format}', str(image.name))
|
renamed = re.sub(f'_\\[.*\\]\\[x(\\d+(\\.\\d+)?)\\]\\.{self.image_format}',
|
||||||
|
f'.{self.image_format}',
|
||||||
|
str(image.name))
|
||||||
(self.upscaled_frames / image).rename(self.upscaled_frames / renamed)
|
(self.upscaled_frames / image).rename(self.upscaled_frames / renamed)
|
||||||
|
|
||||||
# upscaling done, kill the clearer
|
# upscaling done, kill helper threads
|
||||||
Avalon.debug_info(_('Killing upscaled image cleaner'))
|
Avalon.debug_info(_('Killing progress monitor'))
|
||||||
image_cleaner.stop()
|
self.progress_monitor.stop()
|
||||||
|
|
||||||
# pass exit signal to progress bar thread
|
Avalon.debug_info(_('Killing upscaled image cleaner'))
|
||||||
self.progress_bar_exit_signal = True
|
self.image_cleaner.stop()
|
||||||
|
|
||||||
|
def _terminate_subprocesses(self):
|
||||||
|
Avalon.warning(_('Terminating all processes'))
|
||||||
|
for process in self.process_pool:
|
||||||
|
process.terminate()
|
||||||
|
|
||||||
|
def _wait(self):
|
||||||
|
""" wait for subprocesses in process pool to complete
|
||||||
|
"""
|
||||||
|
Avalon.debug_info(_('Main process waiting for subprocesses to exit'))
|
||||||
|
|
||||||
|
try:
|
||||||
|
# while process pool not empty
|
||||||
|
while self.process_pool:
|
||||||
|
|
||||||
|
# if stop signal received, terminate all processes
|
||||||
|
if self.running is False:
|
||||||
|
raise SystemExit
|
||||||
|
|
||||||
|
for process in self.process_pool:
|
||||||
|
process_status = process.poll()
|
||||||
|
|
||||||
|
# if process finished
|
||||||
|
if process_status is None:
|
||||||
|
continue
|
||||||
|
|
||||||
|
# if return code is not 0
|
||||||
|
elif process_status != 0:
|
||||||
|
Avalon.error(_('Subprocess {} exited with code {}').format(process.pid, process_status))
|
||||||
|
raise subprocess.CalledProcessError(process_status, process.args)
|
||||||
|
|
||||||
|
else:
|
||||||
|
Avalon.debug_info(_('Subprocess {} exited with code {}').format(process.pid, process_status))
|
||||||
|
self.process_pool.remove(process)
|
||||||
|
|
||||||
|
time.sleep(0.1)
|
||||||
|
|
||||||
|
except (KeyboardInterrupt, SystemExit) as e:
|
||||||
|
Avalon.warning(_('Stop signal received'))
|
||||||
|
self._terminate_subprocesses()
|
||||||
|
raise e
|
||||||
|
|
||||||
|
except (Exception, subprocess.CalledProcessError) as e:
|
||||||
|
Avalon.error(_('Subprocess execution ran into an error'))
|
||||||
|
self._terminate_subprocesses()
|
||||||
|
raise e
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
""" Main controller for Video2X
|
""" Main controller for Video2X
|
||||||
@@ -309,93 +396,149 @@ class Upscaler:
|
|||||||
and handles all necessary functions.
|
and handles all necessary functions.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
# external stop signal when called in a thread
|
||||||
|
self.running = True
|
||||||
|
|
||||||
|
# define process pool to contain processes
|
||||||
|
self.process_pool = []
|
||||||
|
|
||||||
# parse arguments for waifu2x
|
# parse arguments for waifu2x
|
||||||
# check argument sanity
|
# check argument sanity
|
||||||
self._check_arguments()
|
self._check_arguments()
|
||||||
|
|
||||||
# convert paths to absolute paths
|
# define processing queue
|
||||||
self.input_video = self.input_video.absolute()
|
self.processing_queue = queue.Queue()
|
||||||
self.output_video = self.output_video.absolute()
|
|
||||||
|
|
||||||
# drivers that have native support for video processing
|
# if input is a list of files
|
||||||
if self.driver == 'anime4kcpp':
|
if isinstance(self.input, list):
|
||||||
# append FFmpeg path to the end of PATH
|
# make output directory if it doesn't exist
|
||||||
# Anime4KCPP will then use FFmpeg to migrate audio tracks
|
self.output.mkdir(parents=True, exist_ok=True)
|
||||||
os.environ['PATH'] += f';{self.ffmpeg_settings["ffmpeg_path"]}'
|
|
||||||
Avalon.info(_('Starting to upscale extracted images'))
|
|
||||||
|
|
||||||
# import and initialize Anime4KCPP wrapper
|
for input_path in self.input:
|
||||||
DriverWrapperMain = getattr(importlib.import_module('wrappers.anime4kcpp'), 'WrapperMain')
|
|
||||||
driver = DriverWrapperMain(copy.deepcopy(self.driver_settings))
|
|
||||||
|
|
||||||
# run Anime4KCPP
|
if input_path.is_file():
|
||||||
driver.upscale(self.input_video, self.output_video, self.scale_ratio, self.processes).wait()
|
output_video = self.output / input_path.name
|
||||||
Avalon.info(_('Upscaling completed'))
|
self.processing_queue.put((input_path.absolute(), output_video.absolute()))
|
||||||
|
|
||||||
else:
|
elif input_path.is_dir():
|
||||||
self.create_temp_directories()
|
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()))
|
||||||
|
|
||||||
# initialize objects for ffmpeg and waifu2x-caffe
|
# if input specified is single file
|
||||||
fm = Ffmpeg(self.ffmpeg_settings, self.image_format)
|
elif self.input.is_file():
|
||||||
|
Avalon.info(_('Upscaling single video file: {}').format(self.input))
|
||||||
|
self.processing_queue.put((self.input.absolute(), self.output.absolute()))
|
||||||
|
|
||||||
Avalon.info(_('Reading video information'))
|
# if input specified is a directory
|
||||||
video_info = fm.get_video_info(self.input_video)
|
elif self.input.is_dir():
|
||||||
# analyze original video with ffprobe and retrieve framerate
|
|
||||||
# width, height = info['streams'][0]['width'], info['streams'][0]['height']
|
|
||||||
|
|
||||||
# find index of video stream
|
# make output directory if it doesn't exist
|
||||||
video_stream_index = None
|
self.output.mkdir(parents=True, exist_ok=True)
|
||||||
for stream in video_info['streams']:
|
for input_video in [f for f in self.input.iterdir() if f.is_file()]:
|
||||||
if stream['codec_type'] == 'video':
|
output_video = self.output / input_video.name
|
||||||
video_stream_index = stream['index']
|
self.processing_queue.put((input_video.absolute(), output_video.absolute()))
|
||||||
break
|
|
||||||
|
|
||||||
# exit if no video stream found
|
# record video count for external calls
|
||||||
if video_stream_index is None:
|
self.total_videos = self.processing_queue.qsize()
|
||||||
Avalon.error(_('Aborting: No video stream found'))
|
|
||||||
raise StreamNotFoundError('no video stream found')
|
|
||||||
|
|
||||||
# extract frames from video
|
while not self.processing_queue.empty():
|
||||||
fm.extract_frames(self.input_video, self.extracted_frames)
|
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
|
||||||
|
# Anime4KCPP will then use FFmpeg to migrate audio tracks
|
||||||
|
os.environ['PATH'] += f';{self.ffmpeg_settings["ffmpeg_path"]}'
|
||||||
|
Avalon.info(_('Starting to upscale extracted images'))
|
||||||
|
|
||||||
# get average frame rate of video stream
|
# import and initialize Anime4KCPP wrapper
|
||||||
framerate = float(Fraction(video_info['streams'][video_stream_index]['avg_frame_rate']))
|
DriverWrapperMain = getattr(importlib.import_module('wrappers.anime4kcpp'), 'WrapperMain')
|
||||||
fm.pixel_format = video_info['streams'][video_stream_index]['pix_fmt']
|
driver = DriverWrapperMain(copy.deepcopy(self.driver_settings))
|
||||||
|
|
||||||
# get a dict of all pixel formats and corresponding bit depth
|
# run Anime4KCPP
|
||||||
pixel_formats = fm.get_pixel_formats()
|
self.process_pool.append(driver.upscale(self.current_input_video, output_video, self.scale_ratio, self.processes))
|
||||||
|
self._wait()
|
||||||
|
Avalon.info(_('Upscaling completed'))
|
||||||
|
|
||||||
# try getting pixel format's corresponding bti depth
|
else:
|
||||||
try:
|
try:
|
||||||
self.bit_depth = pixel_formats[fm.pixel_format]
|
self.create_temp_directories()
|
||||||
except KeyError:
|
|
||||||
Avalon.error(_('Unsupported pixel format: {}').format(fm.pixel_format))
|
|
||||||
raise UnsupportedPixelError(f'unsupported pixel format {fm.pixel_format}')
|
|
||||||
|
|
||||||
Avalon.info(_('Framerate: {}').format(framerate))
|
# initialize objects for ffmpeg and waifu2x-caffe
|
||||||
|
fm = Ffmpeg(self.ffmpeg_settings, self.image_format)
|
||||||
|
|
||||||
# width/height will be coded width/height x upscale factor
|
Avalon.info(_('Reading video information'))
|
||||||
if self.scale_ratio:
|
video_info = fm.get_video_info(self.current_input_video)
|
||||||
original_width = video_info['streams'][video_stream_index]['width']
|
# analyze original video with FFprobe and retrieve framerate
|
||||||
original_height = video_info['streams'][video_stream_index]['height']
|
# width, height = info['streams'][0]['width'], info['streams'][0]['height']
|
||||||
self.scale_width = int(self.scale_ratio * original_width)
|
|
||||||
self.scale_height = int(self.scale_ratio * original_height)
|
|
||||||
|
|
||||||
# upscale images one by one using waifu2x
|
# find index of video stream
|
||||||
Avalon.info(_('Starting to upscale extracted images'))
|
video_stream_index = None
|
||||||
self._upscale_frames()
|
for stream in video_info['streams']:
|
||||||
Avalon.info(_('Upscaling completed'))
|
if stream['codec_type'] == 'video':
|
||||||
|
video_stream_index = stream['index']
|
||||||
|
break
|
||||||
|
|
||||||
# frames to Video
|
# exit if no video stream found
|
||||||
Avalon.info(_('Converting extracted frames into video'))
|
if video_stream_index is None:
|
||||||
|
Avalon.error(_('Aborting: No video stream found'))
|
||||||
|
raise StreamNotFoundError('no video stream found')
|
||||||
|
|
||||||
# use user defined output size
|
# extract frames from video
|
||||||
fm.convert_video(framerate, f'{self.scale_width}x{self.scale_height}', self.upscaled_frames)
|
self.process_pool.append((fm.extract_frames(self.current_input_video, self.extracted_frames)))
|
||||||
Avalon.info(_('Conversion completed'))
|
self._wait()
|
||||||
|
|
||||||
# migrate audio tracks and subtitles
|
# get average frame rate of video stream
|
||||||
Avalon.info(_('Migrating audio tracks and subtitles to upscaled video'))
|
framerate = float(Fraction(video_info['streams'][video_stream_index]['avg_frame_rate']))
|
||||||
fm.migrate_audio_tracks_subtitles(self.input_video, self.output_video, self.upscaled_frames)
|
fm.pixel_format = video_info['streams'][video_stream_index]['pix_fmt']
|
||||||
|
|
||||||
# destroy temp directories
|
# get a dict of all pixel formats and corresponding bit depth
|
||||||
self.cleanup_temp_directories()
|
pixel_formats = fm.get_pixel_formats()
|
||||||
|
|
||||||
|
# try getting pixel format's corresponding bti depth
|
||||||
|
try:
|
||||||
|
self.bit_depth = pixel_formats[fm.pixel_format]
|
||||||
|
except KeyError:
|
||||||
|
Avalon.error(_('Unsupported pixel format: {}').format(fm.pixel_format))
|
||||||
|
raise UnsupportedPixelError(f'unsupported pixel format {fm.pixel_format}')
|
||||||
|
|
||||||
|
Avalon.info(_('Framerate: {}').format(framerate))
|
||||||
|
|
||||||
|
# width/height will be coded width/height x upscale factor
|
||||||
|
if self.scale_ratio:
|
||||||
|
original_width = video_info['streams'][video_stream_index]['width']
|
||||||
|
original_height = video_info['streams'][video_stream_index]['height']
|
||||||
|
self.scale_width = int(self.scale_ratio * original_width)
|
||||||
|
self.scale_height = int(self.scale_ratio * original_height)
|
||||||
|
|
||||||
|
# upscale images one by one using waifu2x
|
||||||
|
Avalon.info(_('Starting to upscale extracted images'))
|
||||||
|
self._upscale_frames()
|
||||||
|
Avalon.info(_('Upscaling completed'))
|
||||||
|
|
||||||
|
# frames to Video
|
||||||
|
Avalon.info(_('Converting extracted frames into video'))
|
||||||
|
|
||||||
|
# use user defined output size
|
||||||
|
self.process_pool.append(fm.convert_video(framerate, f'{self.scale_width}x{self.scale_height}', self.upscaled_frames))
|
||||||
|
self._wait()
|
||||||
|
Avalon.info(_('Conversion completed'))
|
||||||
|
|
||||||
|
# migrate audio tracks and subtitles
|
||||||
|
Avalon.info(_('Migrating audio tracks and subtitles to upscaled video'))
|
||||||
|
self.process_pool.append(fm.migrate_audio_tracks_subtitles(self.current_input_video, output_video, self.upscaled_frames))
|
||||||
|
self._wait()
|
||||||
|
|
||||||
|
# destroy temp directories
|
||||||
|
self.cleanup_temp_directories()
|
||||||
|
|
||||||
|
except (Exception, KeyboardInterrupt, SystemExit) as e:
|
||||||
|
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
|
||||||
|
|||||||
139
src/video2x.py
139
src/video2x.py
@@ -13,7 +13,7 @@ __ __ _ _ ___ __ __
|
|||||||
Name: Video2X Controller
|
Name: Video2X Controller
|
||||||
Creator: K4YT3X
|
Creator: K4YT3X
|
||||||
Date Created: Feb 24, 2018
|
Date Created: Feb 24, 2018
|
||||||
Last Modified: May 4, 2020
|
Last Modified: May 7, 2020
|
||||||
|
|
||||||
Editor: BrianPetkovsek
|
Editor: BrianPetkovsek
|
||||||
Last Modified: June 17, 2019
|
Last Modified: June 17, 2019
|
||||||
@@ -58,6 +58,7 @@ import contextlib
|
|||||||
import gettext
|
import gettext
|
||||||
import importlib
|
import importlib
|
||||||
import locale
|
import locale
|
||||||
|
import os
|
||||||
import pathlib
|
import pathlib
|
||||||
import re
|
import re
|
||||||
import shutil
|
import shutil
|
||||||
@@ -178,6 +179,16 @@ config = read_config(video2x_args.config)
|
|||||||
|
|
||||||
# load waifu2x configuration
|
# load waifu2x configuration
|
||||||
driver_settings = config[video2x_args.driver]
|
driver_settings = config[video2x_args.driver]
|
||||||
|
driver_settings['path'] = os.path.expandvars(driver_settings['path'])
|
||||||
|
|
||||||
|
# read FFmpeg configuration
|
||||||
|
ffmpeg_settings = config['ffmpeg']
|
||||||
|
ffmpeg_settings['ffmpeg_path'] = os.path.expandvars(ffmpeg_settings['ffmpeg_path'])
|
||||||
|
|
||||||
|
# load video2x settings
|
||||||
|
image_format = config['video2x']['image_format'].lower()
|
||||||
|
preserve_frames = config['video2x']['preserve_frames']
|
||||||
|
video2x_cache_directory = config['video2x']['video2x_cache_directory']
|
||||||
|
|
||||||
# overwrite driver_settings with driver_args
|
# overwrite driver_settings with driver_args
|
||||||
if driver_args is not None:
|
if driver_args is not None:
|
||||||
@@ -186,126 +197,32 @@ if driver_args is not None:
|
|||||||
if driver_args_dict[key] is not None:
|
if driver_args_dict[key] is not None:
|
||||||
driver_settings[key] = driver_args_dict[key]
|
driver_settings[key] = driver_args_dict[key]
|
||||||
|
|
||||||
# check if driver path exists
|
|
||||||
if not pathlib.Path(driver_settings['path']).exists():
|
|
||||||
if not pathlib.Path(f'{driver_settings["path"]}.exe').exists():
|
|
||||||
Avalon.error(_('Specified driver executable directory doesn\'t exist'))
|
|
||||||
Avalon.error(_('Please check the configuration file settings'))
|
|
||||||
raise FileNotFoundError(driver_settings['path'])
|
|
||||||
|
|
||||||
# read FFmpeg configuration
|
|
||||||
ffmpeg_settings = config['ffmpeg']
|
|
||||||
|
|
||||||
# load video2x settings
|
|
||||||
image_format = config['video2x']['image_format'].lower()
|
|
||||||
preserve_frames = config['video2x']['preserve_frames']
|
|
||||||
|
|
||||||
# load cache directory
|
|
||||||
if config['video2x']['video2x_cache_directory'] is not None:
|
|
||||||
video2x_cache_directory = pathlib.Path(config['video2x']['video2x_cache_directory'])
|
|
||||||
else:
|
|
||||||
video2x_cache_directory = pathlib.Path(tempfile.gettempdir()) / 'video2x'
|
|
||||||
|
|
||||||
if video2x_cache_directory.exists() and not video2x_cache_directory.is_dir():
|
|
||||||
Avalon.error(_('Specified cache directory is a file/link'))
|
|
||||||
raise FileExistsError('Specified cache directory is a file/link')
|
|
||||||
|
|
||||||
# if cache directory doesn't exist
|
|
||||||
# ask the user if it should be created
|
|
||||||
elif not video2x_cache_directory.exists():
|
|
||||||
try:
|
|
||||||
Avalon.debug_info(_('Creating cache directory {}').format(video2x_cache_directory))
|
|
||||||
video2x_cache_directory.mkdir(parents=True, exist_ok=True)
|
|
||||||
# there can be a number of exceptions here
|
|
||||||
# PermissionError, FileExistsError, etc.
|
|
||||||
# therefore, we put a catch-them-all here
|
|
||||||
except Exception as exception:
|
|
||||||
Avalon.error(_('Unable to create {}').format(video2x_cache_directory))
|
|
||||||
raise exception
|
|
||||||
|
|
||||||
|
|
||||||
# start execution
|
# start execution
|
||||||
try:
|
try:
|
||||||
# start timer
|
# start timer
|
||||||
begin_time = time.time()
|
begin_time = time.time()
|
||||||
|
|
||||||
# if input specified is a single file
|
# initialize upscaler object
|
||||||
if video2x_args.input.is_file():
|
upscaler = Upscaler(input_path=video2x_args.input,
|
||||||
|
output_path=video2x_args.output,
|
||||||
|
driver_settings=driver_settings,
|
||||||
|
ffmpeg_settings=ffmpeg_settings)
|
||||||
|
|
||||||
# upscale single video file
|
# set upscaler optional options
|
||||||
Avalon.info(_('Upscaling single video file: {}').format(video2x_args.input))
|
upscaler.driver = video2x_args.driver
|
||||||
|
upscaler.scale_width = video2x_args.width
|
||||||
|
upscaler.scale_height = video2x_args.height
|
||||||
|
upscaler.scale_ratio = video2x_args.ratio
|
||||||
|
upscaler.processes = video2x_args.processes
|
||||||
|
upscaler.video2x_cache_directory = video2x_cache_directory
|
||||||
|
upscaler.image_format = image_format
|
||||||
|
upscaler.preserve_frames = preserve_frames
|
||||||
|
|
||||||
# check for input output format mismatch
|
# run upscaler
|
||||||
if video2x_args.output.is_dir():
|
upscaler.run()
|
||||||
Avalon.error(_('Input and output path type mismatch'))
|
|
||||||
Avalon.error(_('Input is single file but output is directory'))
|
|
||||||
raise Exception('input output path type mismatch')
|
|
||||||
if not re.search(r'.*\..*$', str(video2x_args.output)):
|
|
||||||
Avalon.error(_('No suffix found in output file path'))
|
|
||||||
Avalon.error(_('Suffix must be specified for FFmpeg'))
|
|
||||||
raise Exception('No suffix specified')
|
|
||||||
|
|
||||||
upscaler = Upscaler(input_video=video2x_args.input,
|
|
||||||
output_video=video2x_args.output,
|
|
||||||
driver_settings=driver_settings,
|
|
||||||
ffmpeg_settings=ffmpeg_settings)
|
|
||||||
|
|
||||||
# set optional options
|
|
||||||
upscaler.driver = video2x_args.driver
|
|
||||||
upscaler.scale_width = video2x_args.width
|
|
||||||
upscaler.scale_height = video2x_args.height
|
|
||||||
upscaler.scale_ratio = video2x_args.ratio
|
|
||||||
upscaler.processes = video2x_args.processes
|
|
||||||
upscaler.video2x_cache_directory = video2x_cache_directory
|
|
||||||
upscaler.image_format = image_format
|
|
||||||
upscaler.preserve_frames = preserve_frames
|
|
||||||
|
|
||||||
# run upscaler
|
|
||||||
upscaler.run()
|
|
||||||
|
|
||||||
# if input specified is a directory
|
|
||||||
elif video2x_args.input.is_dir():
|
|
||||||
# upscale videos in a directory
|
|
||||||
Avalon.info(_('Upscaling videos in directory: {}').format(video2x_args.input))
|
|
||||||
|
|
||||||
# make output directory if it doesn't exist
|
|
||||||
video2x_args.output.mkdir(parents=True, exist_ok=True)
|
|
||||||
|
|
||||||
for input_video in [f for f in video2x_args.input.iterdir() if f.is_file()]:
|
|
||||||
output_video = video2x_args.output / input_video.name
|
|
||||||
upscaler = Upscaler(input_video=input_video,
|
|
||||||
output_video=output_video,
|
|
||||||
driver_settings=driver_settings,
|
|
||||||
ffmpeg_settings=ffmpeg_settings)
|
|
||||||
|
|
||||||
# set optional options
|
|
||||||
upscaler.driver = video2x_args.driver
|
|
||||||
upscaler.scale_width = video2x_args.width
|
|
||||||
upscaler.scale_height = video2x_args.height
|
|
||||||
upscaler.scale_ratio = video2x_args.ratio
|
|
||||||
upscaler.processes = video2x_args.processes
|
|
||||||
upscaler.video2x_cache_directory = video2x_cache_directory
|
|
||||||
upscaler.image_format = image_format
|
|
||||||
upscaler.preserve_frames = preserve_frames
|
|
||||||
|
|
||||||
# run upscaler
|
|
||||||
upscaler.run()
|
|
||||||
else:
|
|
||||||
Avalon.error(_('Input path is neither a file nor a directory'))
|
|
||||||
raise FileNotFoundError(f'{video2x_args.input} is neither file nor directory')
|
|
||||||
|
|
||||||
Avalon.info(_('Program completed, taking {} seconds').format(round((time.time() - begin_time), 5)))
|
Avalon.info(_('Program completed, taking {} seconds').format(round((time.time() - begin_time), 5)))
|
||||||
|
|
||||||
except Exception:
|
except Exception:
|
||||||
Avalon.error(_('An exception has occurred'))
|
Avalon.error(_('An exception has occurred'))
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
|
|
||||||
# try cleaning up temp directories
|
|
||||||
with contextlib.suppress(Exception):
|
|
||||||
upscaler.cleanup_temp_directories()
|
|
||||||
|
|
||||||
finally:
|
|
||||||
# remove Video2X cache directory
|
|
||||||
with contextlib.suppress(FileNotFoundError):
|
|
||||||
if not preserve_frames:
|
|
||||||
shutil.rmtree(video2x_cache_directory)
|
|
||||||
|
|||||||
124
src/video2x.yaml
124
src/video2x.yaml
@@ -1,53 +1,59 @@
|
|||||||
|
# Name: Video2X Configuration File
|
||||||
|
# Creator: K4YT3X
|
||||||
|
# Date Created: October 23, 2018
|
||||||
|
# Last Modified: May 8, 2020
|
||||||
|
# Items commented out are parameters handled by Video2x.
|
||||||
waifu2x_caffe:
|
waifu2x_caffe:
|
||||||
path: 'C:\Users\K4YT3X\AppData\Local\video2x\waifu2x-caffe\waifu2x-caffe-cui'
|
path: '%LOCALAPPDATA%\video2x\waifu2x-caffe\waifu2x-caffe-cui'
|
||||||
input_extention_list: null
|
tta: 0 # <0|1> 8x slower and slightly high quality
|
||||||
output_extention: null
|
gpu: 0 # gpu device no
|
||||||
mode: noise_scale
|
batch_size: 1 # input batch size
|
||||||
scale_ratio: null
|
crop_h: null # input image split size(height)
|
||||||
scale_width: null
|
crop_w: null # input image split size(width)
|
||||||
scale_height: null
|
crop_size: 128 # input image split size
|
||||||
noise_level: 3
|
output_depth: 8 # output image chaneel depth bit
|
||||||
process: gpu
|
output_quality: -1 # output image quality
|
||||||
crop_size: 128
|
process: gpu # <cpu|gpu|cudnn> process mode
|
||||||
output_quality: -1
|
model_dir: null # path to custom model directory (don't append last / )
|
||||||
output_depth: 8
|
#scale_height: null # custom scale height
|
||||||
batch_size: 1
|
#scale_width: null # custom scale width
|
||||||
gpu: 0
|
#scale_ratio: null # custom scale ratio
|
||||||
tta: 0
|
noise_level: 3 # <0|1|2|3> noise reduction level
|
||||||
input_path: null
|
mode: noise_scale # <noise|scale|noise_scale|auto_scale> image processing mode
|
||||||
output_path: null
|
output_extention: null # extention to output image file when output_path is (auto) or input_path is folder
|
||||||
model_dir: null
|
input_extention_list: null # extention to input image file when input_path is folder
|
||||||
crop_w: null
|
#output_path: null # path to output image file (when input_path is folder, output_path must be folder)
|
||||||
crop_h: null
|
#input_path: null # (required) path to input image file
|
||||||
waifu2x_converter_cpp:
|
waifu2x_converter_cpp:
|
||||||
path: 'C:\Users\K4YT3X\AppData\Local\video2x\waifu2x-converter-cpp\waifu2x-converter-cpp'
|
path: '%LOCALAPPDATA%\video2x\waifu2x-converter-cpp\waifu2x-converter-cpp'
|
||||||
# list-supported-formats: null
|
#list-supported-formats: null # dump currently supported format list
|
||||||
# list-opencv-formats: null
|
#list-opencv-formats: null # (deprecated. Use --list-supported-formats) dump opencv supported format list
|
||||||
# list-processor
|
#list-processor # dump processor list
|
||||||
output-format: progress_bar_exit_signal
|
output-format: null # The format used when running in recursive/folder mode
|
||||||
png-compression: 5
|
png-compression: 5 # Set PNG compression level (0-9), 9 = Max compression (slowest & smallest)
|
||||||
image-quality: -1
|
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: 0 # block size
|
||||||
disable-gpu: false
|
disable-gpu: false # disable GPU
|
||||||
force-OpenCL: false
|
force-OpenCL: false # force to use OpenCL on Intel Platform
|
||||||
processor: -1
|
processor: -1 # set target processor (-1 uses default device)
|
||||||
jobs: 0
|
jobs: 0 # number of threads launching at the same time
|
||||||
model-dir: null # models_rgb
|
model-dir: null # path to custom model directory (don't append last / ) default: models_rgb
|
||||||
scale-ratio: 2.0
|
#scale-ratio: 2.0 # custom scale ratio
|
||||||
noise-level: 1
|
noise-level: 1 # <0|1|2|3> noise reduction level
|
||||||
mode: noise-scale
|
mode: noise-scale # <noise|scale|noise-scale> image processing mode
|
||||||
log-level: 1
|
log-level: 1 # <0|1|2|3|4> Set log level
|
||||||
silent: null
|
silent: true # Enable silent mode. (same as --log-level 1)
|
||||||
tta: 0
|
tta: 0 # Enable Test-Time Augmentation mode. (0 or 1)
|
||||||
# generate-subdir: 0
|
#generate-subdir: 0 # Generate sub folder when recursive directory is enabled.
|
||||||
# recursive-directory: 0
|
#auto-naming: 0 # Add postfix to output name when output path is not specified.
|
||||||
output: null
|
#recursive-directory: 0 # Search recursively through directories to find more images to process.
|
||||||
input: null
|
#output: null # path to output image file or directory (you should use the full path)
|
||||||
|
#input: null # (required) path to input image file or directory (you should use the full path)
|
||||||
waifu2x_ncnn_vulkan:
|
waifu2x_ncnn_vulkan:
|
||||||
path: 'C:\Users\K4YT3X\AppData\Local\video2x\waifu2x-ncnn-vulkan\waifu2x-ncnn-vulkan'
|
path: '%LOCALAPPDATA%\video2x\waifu2x-ncnn-vulkan\waifu2x-ncnn-vulkan'
|
||||||
v: null # verbose output
|
v: null # verbose output
|
||||||
i: null # input-path: input image path (jpg/png) or directory
|
#i: null # input-path: input image path (jpg/png) or directory
|
||||||
o: null # output-path: output image path (png) or directory
|
#o: null # output-path: output image path (png) or directory
|
||||||
'n': 2 # noise-level: denoise level (-1/0/1/2/3, default=0)
|
'n': 2 # noise-level: denoise level (-1/0/1/2/3, default=0)
|
||||||
s: 2 # scale: upscale ratio (1/2, default=2)
|
s: 2 # scale: upscale ratio (1/2, default=2)
|
||||||
t: 400 # tile-size: tile size (>=32, default=400)
|
t: 400 # tile-size: tile size (>=32, default=400)
|
||||||
@@ -56,10 +62,10 @@ waifu2x_ncnn_vulkan:
|
|||||||
j: '1:2:2' # thread count for load/proc/save (default=1:2:2)
|
j: '1:2:2' # thread count for load/proc/save (default=1:2:2)
|
||||||
x: false # enable tta mode
|
x: false # enable tta mode
|
||||||
srmd_ncnn_vulkan:
|
srmd_ncnn_vulkan:
|
||||||
path: 'C:\Users\K4YT3X\AppData\Local\video2x\srmd-ncnn-vulkan\srmd-ncnn-vulkan'
|
path: '%LOCALAPPDATA%\video2x\srmd-ncnn-vulkan\srmd-ncnn-vulkan'
|
||||||
v: null # verbose output
|
v: null # verbose output
|
||||||
i: null # input-path: input image path (jpg/png) or directory
|
#i: null # input-path: input image path (jpg/png) or directory
|
||||||
o: null # output-path: output image path (png) or directory
|
#o: null # output-path: output image path (png) or directory
|
||||||
'n': 3 # noise-level: denoise level (-1/0/1/2/3/4/5/6/7/8/9/10, default=3)
|
'n': 3 # noise-level: denoise level (-1/0/1/2/3/4/5/6/7/8/9/10, default=3)
|
||||||
s: 2 # upscale ratio (2/3/4, default=2)
|
s: 2 # upscale ratio (2/3/4, default=2)
|
||||||
t: 400 # tile-size: tile size (>=32, default=400)
|
t: 400 # tile-size: tile size (>=32, default=400)
|
||||||
@@ -68,9 +74,9 @@ srmd_ncnn_vulkan:
|
|||||||
j: '1:2:2' # thread count for load/proc/save (default=1:2:2)
|
j: '1:2:2' # thread count for load/proc/save (default=1:2:2)
|
||||||
x: false # enable tta mode
|
x: false # enable tta mode
|
||||||
anime4kcpp:
|
anime4kcpp:
|
||||||
path: 'C:\Users\K4YT3X\AppData\Local\video2x\anime4kcpp\CLI\Anime4KCPP_CLI\Anime4KCPP_CLI'
|
path: '%LOCALAPPDATA%\video2x\anime4kcpp\CLI\Anime4KCPP_CLI\Anime4KCPP_CLI'
|
||||||
input: null # File for loading (string [=./pic/p1.png])
|
#input: null # File for loading (string [=./pic/p1.png])
|
||||||
output: null # File for outputting (string [=output.png])
|
#output: null # File for outputting (string [=output.png])
|
||||||
passes: 2 # Passes for processing (int [=2])
|
passes: 2 # Passes for processing (int [=2])
|
||||||
pushColorCount: 2 # Limit the number of color pushes (int [=2])
|
pushColorCount: 2 # Limit the number of color pushes (int [=2])
|
||||||
strengthColor: 0.3 # Strength for pushing color,range 0 to 1,higher for thinner (double [=0.3])
|
strengthColor: 0.3 # Strength for pushing color,range 0 to 1,higher for thinner (double [=0.3])
|
||||||
@@ -80,22 +86,27 @@ anime4kcpp:
|
|||||||
fastMode: false # Faster but maybe low quality
|
fastMode: false # Faster but maybe low quality
|
||||||
videoMode: true # Video process
|
videoMode: true # Video process
|
||||||
preview: null # Preview image
|
preview: null # Preview image
|
||||||
preProcessing: False # Enable pre processing
|
preprocessing: False # Enable pre processing
|
||||||
postProcessing: False # Enable post processing
|
postprocessing: False # Enable post processing
|
||||||
preFilters: 4 # Enhancement filter, only working when preProcessing is true,there are 5 options by binary:Median blur=0000001, Mean blur=0000010, CAS Sharpening=0000100, Gaussian blur weak=0001000, Gaussian blur=0010000, Bilateral filter=0100000, Bilateral filter faster=1000000, you can freely combine them, eg: Gaussian blur weak + Bilateral filter = 0001000 | 0100000 = 0101000 = 40(D) (unsigned int [=4])
|
preFilters: 4 # Enhancement filter, only working when preProcessing is true,there are 5 options by binary:Median blur=0000001, Mean blur=0000010, CAS Sharpening=0000100, Gaussian blur weak=0001000, Gaussian blur=0010000, Bilateral filter=0100000, Bilateral filter faster=1000000, you can freely combine them, eg: Gaussian blur weak + Bilateral filter = 0001000 | 0100000 = 0101000 = 40(D) (unsigned int [=4])
|
||||||
postFilters: 40 # Enhancement filter, only working when postProcessing is true,there are 5 options by binary:Median blur=0000001, Mean blur=0000010, CAS Sharpening=0000100, Gaussian blur weak=0001000, Gaussian blur=0010000, Bilateral filter=0100000, Bilateral filter faster=1000000, you can freely combine them, eg: Gaussian blur weak + Bilateral filter = 0001000 | 0100000 = 0101000 = 40(D), so you can put 40 to enable Gaussian blur weak and Bilateral filter, which also is what I recommend for image that < 1080P, 48 for image that >= 1080P, and for performance I recommend to use 72 for video that < 1080P, 80 for video that >=1080P (unsigned int [=40])
|
postFilters: 40 # Enhancement filter, only working when postProcessing is true,there are 5 options by binary:Median blur=0000001, Mean blur=0000010, CAS Sharpening=0000100, Gaussian blur weak=0001000, Gaussian blur=0010000, Bilateral filter=0100000, Bilateral filter faster=1000000, you can freely combine them, eg: Gaussian blur weak + Bilateral filter = 0001000 | 0100000 = 0101000 = 40(D), so you can put 40 to enable Gaussian blur weak and Bilateral filter, which also is what I recommend for image that < 1080P, 48 for image that >= 1080P, and for performance I recommend to use 72 for video that < 1080P, 80 for video that >=1080P (unsigned int [=40])
|
||||||
GPUMode: False # Enable GPU acceleration
|
GPUMode: False # Enable GPU acceleration
|
||||||
listGPUs: null # list GPUs
|
listGPUs: null # list GPUs
|
||||||
platformID: 0 # Specify the platform ID (unsigned int [=0])
|
platformID: 0 # Specify the platform ID (unsigned int [=0])
|
||||||
deviceID: 0 # Specify the device ID (unsigned int [=0])
|
deviceID: 0 # Specify the device ID (unsigned int [=0])
|
||||||
|
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:
|
||||||
ffmpeg_path: 'C:\Users\K4YT3X\AppData\Local\video2x\ffmpeg-latest-win64-static\bin'
|
ffmpeg_path: '%LOCALAPPDATA%\video2x\ffmpeg-latest-win64-static\bin'
|
||||||
|
# step 1: extract all frames from original video
|
||||||
|
# into temporary directory
|
||||||
video_to_frames:
|
video_to_frames:
|
||||||
output_options:
|
output_options:
|
||||||
'-qscale:v': null
|
'-qscale:v': null
|
||||||
'-pix_fmt': rgba64be
|
'-pix_fmt': rgba64be
|
||||||
'-hwaccel': auto
|
'-hwaccel': auto
|
||||||
'-y': true
|
'-y': true
|
||||||
|
# step 2: stitch all frames back into a video
|
||||||
|
# with only a video track
|
||||||
frames_to_video:
|
frames_to_video:
|
||||||
input_options:
|
input_options:
|
||||||
'-qscale:v': null
|
'-qscale:v': null
|
||||||
@@ -108,6 +119,8 @@ ffmpeg:
|
|||||||
'-pix_fmt': null
|
'-pix_fmt': null
|
||||||
'-hwaccel': auto
|
'-hwaccel': auto
|
||||||
'-y': true
|
'-y': true
|
||||||
|
# step 3: migrate audio and subtitle tracks from original
|
||||||
|
# video into the upscaled video
|
||||||
migrating_tracks:
|
migrating_tracks:
|
||||||
output_options:
|
output_options:
|
||||||
'-map':
|
'-map':
|
||||||
@@ -118,6 +131,7 @@ ffmpeg:
|
|||||||
- '1:t?'
|
- '1:t?'
|
||||||
'-c': copy
|
'-c': copy
|
||||||
'-pix_fmt': null
|
'-pix_fmt': null
|
||||||
|
'-metadata': 'comment=Upscaled by Video2X'
|
||||||
'-hwaccel': auto
|
'-hwaccel': auto
|
||||||
'-y': true
|
'-y': true
|
||||||
video2x:
|
video2x:
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
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"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<ui version="4.0">
|
<ui version="4.0">
|
||||||
<class>Video2xQt</class>
|
<class>Video2xGui</class>
|
||||||
<widget class="QMainWindow" name="Video2xQt">
|
<widget class="QMainWindow" name="Video2xGui">
|
||||||
<property name="geometry">
|
<property name="geometry">
|
||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>691</width>
|
<width>718</width>
|
||||||
<height>503</height>
|
<height>740</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="acceptDrops">
|
||||||
<string>Video2xQt</string>
|
<bool>true</bool>
|
||||||
</property>
|
</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">
|
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||||
<property name="leftMargin">
|
<property name="leftMargin">
|
||||||
<number>5</number>
|
<number>5</number>
|
||||||
@@ -38,154 +41,198 @@
|
|||||||
</attribute>
|
</attribute>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_8">
|
<layout class="QVBoxLayout" name="verticalLayout_8">
|
||||||
<item>
|
<item>
|
||||||
<layout class="QVBoxLayout" name="fileSelectionVerticalLayout">
|
<widget class="QLabel" name="dragDropLabelTop">
|
||||||
<item>
|
<property name="maximumSize">
|
||||||
<layout class="QHBoxLayout" name="inputHorizontalLayout">
|
<size>
|
||||||
<item>
|
<width>16777215</width>
|
||||||
<widget class="QLabel" name="inputLabel">
|
<height>15</height>
|
||||||
<property name="minimumSize">
|
</size>
|
||||||
<size>
|
</property>
|
||||||
<width>63</width>
|
<property name="frameShape">
|
||||||
<height>0</height>
|
<enum>QFrame::NoFrame</enum>
|
||||||
</size>
|
</property>
|
||||||
</property>
|
<property name="text">
|
||||||
<property name="lineWidth">
|
<string>**Drag and drop file or folder anywhere in this window to select input file/folder.**</string>
|
||||||
<number>1</number>
|
</property>
|
||||||
</property>
|
<property name="textFormat">
|
||||||
<property name="text">
|
<enum>Qt::MarkdownText</enum>
|
||||||
<string>Input</string>
|
</property>
|
||||||
</property>
|
<property name="wordWrap">
|
||||||
<property name="wordWrap">
|
<bool>false</bool>
|
||||||
<bool>false</bool>
|
</property>
|
||||||
</property>
|
</widget>
|
||||||
<property name="margin">
|
</item>
|
||||||
<number>0</number>
|
<item>
|
||||||
</property>
|
<widget class="QLabel" name="dragDropLabelBottom">
|
||||||
</widget>
|
<property name="maximumSize">
|
||||||
</item>
|
<size>
|
||||||
<item>
|
<width>16777215</width>
|
||||||
<widget class="QLineEdit" name="inputLineEdit"/>
|
<height>15</height>
|
||||||
</item>
|
</size>
|
||||||
<item>
|
</property>
|
||||||
<widget class="QPushButton" name="inputSelectFileButton">
|
<property name="text">
|
||||||
<property name="enabled">
|
<string>**Drop item on a specific input box to set the value of that box.**</string>
|
||||||
<bool>true</bool>
|
</property>
|
||||||
</property>
|
<property name="textFormat">
|
||||||
<property name="text">
|
<enum>Qt::MarkdownText</enum>
|
||||||
<string>Select File</string>
|
</property>
|
||||||
</property>
|
</widget>
|
||||||
</widget>
|
</item>
|
||||||
</item>
|
<item>
|
||||||
<item>
|
<widget class="QGroupBox" name="inputSelectionGroupBox">
|
||||||
<widget class="QPushButton" name="inputSelectFolderButton">
|
<property name="title">
|
||||||
<property name="text">
|
<string>Input Selection</string>
|
||||||
<string>Select Folder</string>
|
</property>
|
||||||
</property>
|
<layout class="QVBoxLayout" name="verticalLayout_5">
|
||||||
</widget>
|
<item>
|
||||||
</item>
|
<widget class="QTableView" name="inputTableView"/>
|
||||||
</layout>
|
</item>
|
||||||
</item>
|
<item>
|
||||||
<item>
|
<layout class="QHBoxLayout" name="inputButtonsHorizontalLayout">
|
||||||
<layout class="QHBoxLayout" name="outputHorizontalLayout">
|
<item>
|
||||||
<item>
|
<widget class="QPushButton" name="inputSelectFileButton">
|
||||||
<widget class="QLabel" name="outputLabel">
|
<property name="enabled">
|
||||||
<property name="sizePolicy">
|
<bool>true</bool>
|
||||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
</property>
|
||||||
<horstretch>0</horstretch>
|
<property name="text">
|
||||||
<verstretch>0</verstretch>
|
<string>Select File</string>
|
||||||
</sizepolicy>
|
</property>
|
||||||
</property>
|
</widget>
|
||||||
<property name="minimumSize">
|
</item>
|
||||||
<size>
|
<item>
|
||||||
<width>63</width>
|
<widget class="QPushButton" name="inputSelectFolderButton">
|
||||||
<height>0</height>
|
<property name="text">
|
||||||
</size>
|
<string>Select Folder</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
</widget>
|
||||||
<string>Output</string>
|
</item>
|
||||||
</property>
|
<item>
|
||||||
</widget>
|
<widget class="QPushButton" name="inputDeleteSelectedButton">
|
||||||
</item>
|
<property name="text">
|
||||||
<item>
|
<string>Delete Selected</string>
|
||||||
<widget class="QLineEdit" name="outputLineEdit"/>
|
</property>
|
||||||
</item>
|
</widget>
|
||||||
<item>
|
</item>
|
||||||
<widget class="QPushButton" name="outputSelectFileButton">
|
<item>
|
||||||
<property name="text">
|
<widget class="QPushButton" name="inputClearAllButton">
|
||||||
<string>Select File</string>
|
<property name="text">
|
||||||
</property>
|
<string>Clear All</string>
|
||||||
</widget>
|
</property>
|
||||||
</item>
|
</widget>
|
||||||
<item>
|
</item>
|
||||||
<widget class="QPushButton" name="outputSelectFolderButton">
|
</layout>
|
||||||
<property name="text">
|
</item>
|
||||||
<string>Select Folder</string>
|
</layout>
|
||||||
</property>
|
</widget>
|
||||||
</widget>
|
</item>
|
||||||
</item>
|
<item>
|
||||||
</layout>
|
<widget class="QGroupBox" name="otherPathsSelectionGroupBox">
|
||||||
</item>
|
<property name="title">
|
||||||
<item>
|
<string>Other Paths Selection</string>
|
||||||
<layout class="QHBoxLayout" name="configHorizontalLayout">
|
</property>
|
||||||
<item>
|
<layout class="QVBoxLayout" name="verticalLayout_9">
|
||||||
<widget class="QLabel" name="configLabel">
|
<item>
|
||||||
<property name="sizePolicy">
|
<layout class="QHBoxLayout" name="outputHorizontalLayout">
|
||||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
<item>
|
||||||
<horstretch>0</horstretch>
|
<widget class="QLabel" name="outputLabel">
|
||||||
<verstretch>0</verstretch>
|
<property name="sizePolicy">
|
||||||
</sizepolicy>
|
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||||
</property>
|
<horstretch>0</horstretch>
|
||||||
<property name="minimumSize">
|
<verstretch>0</verstretch>
|
||||||
<size>
|
</sizepolicy>
|
||||||
<width>63</width>
|
</property>
|
||||||
<height>0</height>
|
<property name="minimumSize">
|
||||||
</size>
|
<size>
|
||||||
</property>
|
<width>63</width>
|
||||||
<property name="text">
|
<height>0</height>
|
||||||
<string>Config</string>
|
</size>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
<property name="text">
|
||||||
</item>
|
<string>Output</string>
|
||||||
<item>
|
</property>
|
||||||
<widget class="QLineEdit" name="configLineEdit"/>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QPushButton" name="configSelectButton">
|
<widget class="QLineEdit" name="outputLineEdit"/>
|
||||||
<property name="text">
|
</item>
|
||||||
<string>Select</string>
|
<item>
|
||||||
</property>
|
<widget class="QPushButton" name="outputSelectFileButton">
|
||||||
</widget>
|
<property name="text">
|
||||||
</item>
|
<string>Select File</string>
|
||||||
</layout>
|
</property>
|
||||||
</item>
|
</widget>
|
||||||
<item>
|
</item>
|
||||||
<layout class="QHBoxLayout" name="cacheHorizontalLayout">
|
<item>
|
||||||
<item>
|
<widget class="QPushButton" name="outputSelectFolderButton">
|
||||||
<widget class="QLabel" name="cacheLabel">
|
<property name="text">
|
||||||
<property name="minimumSize">
|
<string>Select Folder</string>
|
||||||
<size>
|
</property>
|
||||||
<width>63</width>
|
</widget>
|
||||||
<height>0</height>
|
</item>
|
||||||
</size>
|
</layout>
|
||||||
</property>
|
</item>
|
||||||
<property name="text">
|
<item>
|
||||||
<string>Cache Folder</string>
|
<layout class="QHBoxLayout" name="configHorizontalLayout">
|
||||||
</property>
|
<item>
|
||||||
</widget>
|
<widget class="QLabel" name="configLabel">
|
||||||
</item>
|
<property name="sizePolicy">
|
||||||
<item>
|
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||||
<widget class="QLineEdit" name="cacheLineEdit"/>
|
<horstretch>0</horstretch>
|
||||||
</item>
|
<verstretch>0</verstretch>
|
||||||
<item>
|
</sizepolicy>
|
||||||
<widget class="QPushButton" name="cacheSelectFolderButton">
|
</property>
|
||||||
<property name="text">
|
<property name="minimumSize">
|
||||||
<string>Select Folder</string>
|
<size>
|
||||||
</property>
|
<width>63</width>
|
||||||
</widget>
|
<height>0</height>
|
||||||
</item>
|
</size>
|
||||||
</layout>
|
</property>
|
||||||
</item>
|
<property name="text">
|
||||||
</layout>
|
<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>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QGroupBox" name="expressSettingsGroupBox">
|
<widget class="QGroupBox" name="expressSettingsGroupBox">
|
||||||
@@ -1175,6 +1222,51 @@
|
|||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="7" column="1">
|
||||||
|
<layout class="QHBoxLayout" name="anime4kCppCodecHorizontalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="anime4kCppCodecLabel">
|
||||||
|
<property name="text">
|
||||||
|
<string>Codec</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QComboBox" name="anime4kCppCodecComboBox">
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>mp4v</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>dxva</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>avc1</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>vp09</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>hevc</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>av01</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</widget>
|
</widget>
|
||||||
@@ -1184,72 +1276,184 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<layout class="QVBoxLayout" name="controlsVerticalLayout">
|
<widget class="QGroupBox" name="currentVideoProcessingProgressGroupBox">
|
||||||
<item>
|
<property name="title">
|
||||||
<widget class="QProgressBar" name="progressBar">
|
<string>Current Video Processing Progress</string>
|
||||||
<property name="value">
|
</property>
|
||||||
<number>0</number>
|
<layout class="QVBoxLayout" name="verticalLayout_11">
|
||||||
</property>
|
<item>
|
||||||
</widget>
|
<widget class="QLabel" name="currentlyProcessingLabel">
|
||||||
</item>
|
<property name="minimumSize">
|
||||||
<item>
|
<size>
|
||||||
<layout class="QHBoxLayout" name="timeControlsHorizontalLayout">
|
<width>0</width>
|
||||||
<item>
|
<height>20</height>
|
||||||
<widget class="QLabel" name="timeElapsedLabel">
|
</size>
|
||||||
<property name="acceptDrops">
|
</property>
|
||||||
<bool>false</bool>
|
<property name="text">
|
||||||
</property>
|
<string>Currently Processing:</string>
|
||||||
<property name="frameShape">
|
</property>
|
||||||
<enum>QFrame::StyledPanel</enum>
|
</widget>
|
||||||
</property>
|
</item>
|
||||||
<property name="text">
|
<item>
|
||||||
<string>Time Elapsed: 00:00:00</string>
|
<widget class="QProgressBar" name="currentProgressBar">
|
||||||
</property>
|
<property name="value">
|
||||||
</widget>
|
<number>0</number>
|
||||||
</item>
|
</property>
|
||||||
<item>
|
</widget>
|
||||||
<widget class="QLabel" name="timeRemainingLabel">
|
</item>
|
||||||
<property name="frameShape">
|
<item>
|
||||||
<enum>QFrame::StyledPanel</enum>
|
<layout class="QHBoxLayout" name="currentlyProcessingInfoHorizontalLayout">
|
||||||
</property>
|
<item>
|
||||||
<property name="text">
|
<widget class="QLabel" name="timeElapsedLabel">
|
||||||
<string>Time Remaining: 00:00:00</string>
|
<property name="minimumSize">
|
||||||
</property>
|
<size>
|
||||||
</widget>
|
<width>0</width>
|
||||||
</item>
|
<height>20</height>
|
||||||
<item>
|
</size>
|
||||||
<widget class="QLabel" name="rateLabel">
|
</property>
|
||||||
<property name="frameShape">
|
<property name="acceptDrops">
|
||||||
<enum>QFrame::StyledPanel</enum>
|
<bool>false</bool>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="frameShape">
|
||||||
<string>Rate (FPS): 0.0</string>
|
<enum>QFrame::StyledPanel</enum>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
<property name="text">
|
||||||
</item>
|
<string>Time Elapsed: 00:00:00</string>
|
||||||
<item>
|
</property>
|
||||||
<widget class="QPushButton" name="startButton">
|
</widget>
|
||||||
<property name="enabled">
|
</item>
|
||||||
<bool>false</bool>
|
<item>
|
||||||
</property>
|
<widget class="QLabel" name="timeRemainingLabel">
|
||||||
<property name="text">
|
<property name="minimumSize">
|
||||||
<string>Start</string>
|
<size>
|
||||||
</property>
|
<width>0</width>
|
||||||
</widget>
|
<height>20</height>
|
||||||
</item>
|
</size>
|
||||||
<item>
|
</property>
|
||||||
<widget class="QPushButton" name="stopButton">
|
<property name="frameShape">
|
||||||
<property name="enabled">
|
<enum>QFrame::StyledPanel</enum>
|
||||||
<bool>false</bool>
|
</property>
|
||||||
</property>
|
<property name="text">
|
||||||
<property name="text">
|
<string>Time Remaining: 00:00:00</string>
|
||||||
<string>Stop</string>
|
</property>
|
||||||
</property>
|
</widget>
|
||||||
</widget>
|
</item>
|
||||||
</item>
|
<item>
|
||||||
</layout>
|
<widget class="QLabel" name="rateLabel">
|
||||||
</item>
|
<property name="minimumSize">
|
||||||
</layout>
|
<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>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
@@ -1258,7 +1462,7 @@
|
|||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>691</width>
|
<width>718</width>
|
||||||
<height>21</height>
|
<height>21</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
Name: Video2X Setup Script
|
Name: Video2X Setup Script
|
||||||
Creator: K4YT3X
|
Creator: K4YT3X
|
||||||
Date Created: November 28, 2018
|
Date Created: November 28, 2018
|
||||||
Last Modified: May 5, 2020
|
Last Modified: May 8, 2020
|
||||||
|
|
||||||
Editor: BrianPetkovsek
|
Editor: BrianPetkovsek
|
||||||
Editor: SAT3LL
|
Editor: SAT3LL
|
||||||
@@ -260,16 +260,19 @@ class Video2xSetup:
|
|||||||
|
|
||||||
# configure only the specified drivers
|
# configure only the specified drivers
|
||||||
if self.driver == 'all':
|
if self.driver == 'all':
|
||||||
template_dict['waifu2x_caffe']['path'] = str(LOCALAPPDATA / 'video2x' / 'waifu2x-caffe' / 'waifu2x-caffe-cui.exe')
|
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.exe')
|
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')
|
template_dict['anime4kcpp']['path'] = str(LOCALAPPDATA / 'video2x' / 'anime4kcpp' / 'CLI' / 'Anime4KCPP_CLI' / 'Anime4KCPP_CLI')
|
||||||
elif self.driver == 'waifu2x_caffe':
|
elif self.driver == 'waifu2x_caffe':
|
||||||
template_dict['waifu2x_caffe']['path'] = str(LOCALAPPDATA / 'video2x' / 'waifu2x-caffe' / 'waifu2x-caffe-cui.exe')
|
template_dict['waifu2x_caffe']['path'] = str(LOCALAPPDATA / 'video2x' / 'waifu2x-caffe' / 'waifu2x-caffe-cui')
|
||||||
elif self.driver == 'waifu2x_converter_cpp':
|
elif self.driver == 'waifu2x_converter_cpp':
|
||||||
template_dict['waifu2x_converter_cpp']['path'] = str(LOCALAPPDATA / 'video2x' / 'waifu2x-converter-cpp' / 'waifu2x-converter-cpp')
|
template_dict['waifu2x_converter_cpp']['path'] = str(LOCALAPPDATA / 'video2x' / 'waifu2x-converter-cpp' / 'waifu2x-converter-cpp')
|
||||||
elif self.driver == 'waifu2x_ncnn_vulkan':
|
elif self.driver == 'waifu2x_ncnn_vulkan':
|
||||||
template_dict['waifu2x_ncnn_vulkan']['path'] = str(LOCALAPPDATA / 'video2x' / 'waifu2x-ncnn-vulkan' / 'waifu2x-ncnn-vulkan.exe')
|
template_dict['waifu2x_ncnn_vulkan']['path'] = str(LOCALAPPDATA / 'video2x' / 'waifu2x-ncnn-vulkan' / 'waifu2x-ncnn-vulkan')
|
||||||
|
elif self.driver == 'srmd_ncnn_vulkan':
|
||||||
|
template_dict['srmd_ncnn_vulkan']['path'] = str(LOCALAPPDATA / 'video2x' / 'srmd-ncnn-vulkan' / 'srmd-ncnn-vulkan')
|
||||||
elif self.driver == 'anime4kcpp':
|
elif self.driver == 'anime4kcpp':
|
||||||
template_dict['anime4kcpp']['path'] = str(LOCALAPPDATA / 'video2x' / 'anime4kcpp' / 'CLI' / 'Anime4KCPP_CLI' / 'Anime4KCPP_CLI')
|
template_dict['anime4kcpp']['path'] = str(LOCALAPPDATA / 'video2x' / 'anime4kcpp' / 'CLI' / 'Anime4KCPP_CLI' / 'Anime4KCPP_CLI')
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
Name: Waifu2x Caffe Driver
|
Name: Waifu2x Caffe Driver
|
||||||
Author: K4YT3X
|
Author: K4YT3X
|
||||||
Date Created: May 3, 2020
|
Date Created: May 3, 2020
|
||||||
Last Modified: May 4, 2020
|
Last Modified: May 7, 2020
|
||||||
|
|
||||||
Description: This class is a high-level wrapper
|
Description: This class is a high-level wrapper
|
||||||
for waifu2x-caffe.
|
for waifu2x-caffe.
|
||||||
@@ -13,6 +13,8 @@ for waifu2x-caffe.
|
|||||||
# built-in imports
|
# built-in imports
|
||||||
import argparse
|
import argparse
|
||||||
import os
|
import os
|
||||||
|
import pathlib
|
||||||
|
import platform
|
||||||
import shlex
|
import shlex
|
||||||
import subprocess
|
import subprocess
|
||||||
import threading
|
import threading
|
||||||
@@ -32,6 +34,7 @@ class WrapperMain:
|
|||||||
@staticmethod
|
@staticmethod
|
||||||
def parse_arguments(arguments):
|
def parse_arguments(arguments):
|
||||||
parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter, add_help=False)
|
parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter, add_help=False)
|
||||||
|
parser.error = lambda message: (_ for _ in ()).throw(AttributeError(message))
|
||||||
parser.add_argument('--help', action='help', help='show this help message and exit')
|
parser.add_argument('--help', action='help', help='show this help message and exit')
|
||||||
# parser.add_argument('-i', '--input', type=pathlib.Path, help='File for loading')
|
# parser.add_argument('-i', '--input', type=pathlib.Path, help='File for loading')
|
||||||
# parser.add_argument('-o', '--output', type=pathlib.Path, help='File for outputting')
|
# parser.add_argument('-o', '--output', type=pathlib.Path, help='File for outputting')
|
||||||
@@ -42,16 +45,17 @@ class WrapperMain:
|
|||||||
parser.add_argument('-z', '--zoomFactor', type=float, help='zoom factor for resizing')
|
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('-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('-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('-s', '--preview', action='store_true', help='Preview image')
|
||||||
parser.add_argument('-b', '--preProcessing', action='store_true', help='Enable pre processing')
|
parser.add_argument('-b', '--preprocessing', action='store_true', help='Enable pre processing')
|
||||||
parser.add_argument('-a', '--postProcessing', action='store_true', help='Enable post processing')
|
parser.add_argument('-a', '--postprocessing', action='store_true', help='Enable post processing')
|
||||||
parser.add_argument('-r', '--preFilters', type=int, help='Enhancement filter, only working when preProcessing is true,there are 5 options by binary:Median blur=0000001, Mean blur=0000010, CAS Sharpening=0000100, Gaussian blur weak=0001000, Gaussian blur=0010000, Bilateral filter=0100000, Bilateral filter faster=1000000, you can freely combine them, eg: Gaussian blur weak + Bilateral filter = 0001000 | 0100000 = 0101000 = 40(D)')
|
parser.add_argument('-r', '--preFilters', type=int, help='Enhancement filter, only working when preProcessing is true,there are 5 options by binary:Median blur=0000001, Mean blur=0000010, CAS Sharpening=0000100, Gaussian blur weak=0001000, Gaussian blur=0010000, Bilateral filter=0100000, Bilateral filter faster=1000000, you can freely combine them, eg: Gaussian blur weak + Bilateral filter = 0001000 | 0100000 = 0101000 = 40(D)')
|
||||||
parser.add_argument('-e', '--postFilters', type=int, help='Enhancement filter, only working when postProcessing is true,there are 5 options by binary:Median blur=0000001, Mean blur=0000010, CAS Sharpening=0000100, Gaussian blur weak=0001000, Gaussian blur=0010000, Bilateral filter=0100000, Bilateral filter faster=1000000, you can freely combine them, eg: Gaussian blur weak + Bilateral filter = 0001000 | 0100000 = 0101000 = 40(D), so you can put 40 to enable Gaussian blur weak and Bilateral filter, which also is what I recommend for image that < 1080P, 48 for image that >= 1080P, and for performance I recommend to use 72 for video that < 1080P, 80 for video that >=1080P')
|
parser.add_argument('-e', '--postFilters', type=int, help='Enhancement filter, only working when postProcessing is true,there are 5 options by binary:Median blur=0000001, Mean blur=0000010, CAS Sharpening=0000100, Gaussian blur weak=0001000, Gaussian blur=0010000, Bilateral filter=0100000, Bilateral filter faster=1000000, you can freely combine them, eg: Gaussian blur weak + Bilateral filter = 0001000 | 0100000 = 0101000 = 40(D), so you can put 40 to enable Gaussian blur weak and Bilateral filter, which also is what I recommend for image that < 1080P, 48 for image that >= 1080P, and for performance I recommend to use 72 for video that < 1080P, 80 for video that >=1080P')
|
||||||
parser.add_argument('-q', '--GPUMode', action='store_true', help='Enable GPU acceleration')
|
parser.add_argument('-q', '--GPUMode', action='store_true', help='Enable GPU acceleration')
|
||||||
parser.add_argument('-l', '--listGPUs', action='store_true', help='list GPUs')
|
parser.add_argument('-l', '--listGPUs', action='store_true', help='list GPUs')
|
||||||
parser.add_argument('-h', '--platformID', type=int, help='Specify the platform ID')
|
parser.add_argument('-h', '--platformID', type=int, help='Specify the platform ID')
|
||||||
parser.add_argument('-d', '--deviceID', type=int, help='Specify the device ID')
|
parser.add_argument('-d', '--deviceID', type=int, help='Specify the device ID')
|
||||||
|
parser.add_argument('-C', '--codec', type=str, help='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])')
|
||||||
return parser.parse_args(arguments)
|
return parser.parse_args(arguments)
|
||||||
|
|
||||||
def upscale(self, input_file, output_file, zoom_factor, threads):
|
def upscale(self, input_file, output_file, zoom_factor, threads):
|
||||||
@@ -70,6 +74,11 @@ class WrapperMain:
|
|||||||
self.driver_settings['zoomFactor'] = zoom_factor
|
self.driver_settings['zoomFactor'] = zoom_factor
|
||||||
self.driver_settings['threads'] = threads
|
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':
|
||||||
|
os.chdir(pathlib.Path(self.driver_settings['path']).parent)
|
||||||
|
|
||||||
# list to be executed
|
# list to be executed
|
||||||
# initialize the list with waifu2x binary path as the first element
|
# initialize the list with waifu2x binary path as the first element
|
||||||
execute = [self.driver_settings.pop('path')]
|
execute = [self.driver_settings.pop('path')]
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
Name: Video2X FFmpeg Controller
|
Name: Video2X FFmpeg Controller
|
||||||
Author: K4YT3X
|
Author: K4YT3X
|
||||||
Date Created: Feb 24, 2018
|
Date Created: Feb 24, 2018
|
||||||
Last Modified: November 15, 2019
|
Last Modified: May 7, 2020
|
||||||
|
|
||||||
Description: This class handles all FFmpeg related operations.
|
Description: This class handles all FFmpeg related operations.
|
||||||
"""
|
"""
|
||||||
@@ -131,7 +131,7 @@ class Ffmpeg:
|
|||||||
extracted_frames / f'extracted_%0d.{self.image_format}'
|
extracted_frames / f'extracted_%0d.{self.image_format}'
|
||||||
])
|
])
|
||||||
|
|
||||||
self._execute(execute)
|
return(self._execute(execute))
|
||||||
|
|
||||||
def convert_video(self, framerate, resolution, upscaled_frames):
|
def convert_video(self, framerate, resolution, upscaled_frames):
|
||||||
"""Converts images into videos
|
"""Converts images into videos
|
||||||
@@ -180,7 +180,7 @@ class Ffmpeg:
|
|||||||
upscaled_frames / 'no_audio.mp4'
|
upscaled_frames / 'no_audio.mp4'
|
||||||
])
|
])
|
||||||
|
|
||||||
self._execute(execute)
|
return(self._execute(execute))
|
||||||
|
|
||||||
def migrate_audio_tracks_subtitles(self, input_video, output_video, upscaled_frames):
|
def migrate_audio_tracks_subtitles(self, input_video, output_video, upscaled_frames):
|
||||||
""" Migrates audio tracks and subtitles from input video to output video
|
""" Migrates audio tracks and subtitles from input video to output video
|
||||||
@@ -209,7 +209,7 @@ class Ffmpeg:
|
|||||||
output_video
|
output_video
|
||||||
])
|
])
|
||||||
|
|
||||||
self._execute(execute)
|
return(self._execute(execute))
|
||||||
|
|
||||||
def _read_configuration(self, phase, section=None):
|
def _read_configuration(self, phase, section=None):
|
||||||
""" read configuration from JSON
|
""" read configuration from JSON
|
||||||
@@ -284,4 +284,4 @@ class Ffmpeg:
|
|||||||
|
|
||||||
Avalon.debug_info(f'Executing: {execute}')
|
Avalon.debug_info(f'Executing: {execute}')
|
||||||
|
|
||||||
return subprocess.run(execute, check=True).returncode
|
return subprocess.Popen(execute)
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
Name: SRMD NCNN Vulkan Driver
|
Name: SRMD NCNN Vulkan Driver
|
||||||
Creator: K4YT3X
|
Creator: K4YT3X
|
||||||
Date Created: April 26, 2020
|
Date Created: April 26, 2020
|
||||||
Last Modified: May 5, 2020
|
Last Modified: May 7, 2020
|
||||||
|
|
||||||
Description: This class is a high-level wrapper
|
Description: This class is a high-level wrapper
|
||||||
for srmd_ncnn_vulkan.
|
for srmd_ncnn_vulkan.
|
||||||
@@ -39,6 +39,7 @@ class WrapperMain:
|
|||||||
@staticmethod
|
@staticmethod
|
||||||
def parse_arguments(arguments):
|
def parse_arguments(arguments):
|
||||||
parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter, add_help=False)
|
parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter, add_help=False)
|
||||||
|
parser.error = lambda message: (_ for _ in ()).throw(AttributeError(message))
|
||||||
parser.add_argument('--help', action='help', help='show this help message and exit')
|
parser.add_argument('--help', action='help', help='show this help message and exit')
|
||||||
parser.add_argument('-v', action='store_true', help='verbose output')
|
parser.add_argument('-v', action='store_true', help='verbose output')
|
||||||
# parser.add_argument('-i', type=pathlib.Path, help='input image path (jpg/png) or directory')
|
# parser.add_argument('-i', type=pathlib.Path, help='input image path (jpg/png) or directory')
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
Name: Waifu2x Caffe Driver
|
Name: Waifu2x Caffe Driver
|
||||||
Author: K4YT3X
|
Author: K4YT3X
|
||||||
Date Created: Feb 24, 2018
|
Date Created: Feb 24, 2018
|
||||||
Last Modified: May 4, 2020
|
Last Modified: May 7, 2020
|
||||||
|
|
||||||
Description: This class is a high-level wrapper
|
Description: This class is a high-level wrapper
|
||||||
for waifu2x-caffe.
|
for waifu2x-caffe.
|
||||||
@@ -37,6 +37,7 @@ class WrapperMain:
|
|||||||
@staticmethod
|
@staticmethod
|
||||||
def parse_arguments(arguments):
|
def parse_arguments(arguments):
|
||||||
parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter, add_help=False)
|
parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter, add_help=False)
|
||||||
|
parser.error = lambda message: (_ for _ in ()).throw(AttributeError(message))
|
||||||
parser.add_argument('--help', action='help', help='show this help message and exit')
|
parser.add_argument('--help', action='help', help='show this help message and exit')
|
||||||
parser.add_argument('-t', '--tta', type=int, choices=range(2), help='8x slower and slightly high quality')
|
parser.add_argument('-t', '--tta', type=int, choices=range(2), help='8x slower and slightly high quality')
|
||||||
parser.add_argument('--gpu', type=int, help='gpu device no')
|
parser.add_argument('--gpu', type=int, help='gpu device no')
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
Name: Waifu2x Converter CPP Driver
|
Name: Waifu2x Converter CPP Driver
|
||||||
Author: K4YT3X
|
Author: K4YT3X
|
||||||
Date Created: February 8, 2019
|
Date Created: February 8, 2019
|
||||||
Last Modified: May 4, 2020
|
Last Modified: May 7, 2020
|
||||||
|
|
||||||
Description: This class is a high-level wrapper
|
Description: This class is a high-level wrapper
|
||||||
for waifu2x-converter-cpp.
|
for waifu2x-converter-cpp.
|
||||||
@@ -38,13 +38,14 @@ class WrapperMain:
|
|||||||
@staticmethod
|
@staticmethod
|
||||||
def parse_arguments(arguments):
|
def parse_arguments(arguments):
|
||||||
parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter, add_help=False)
|
parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter, add_help=False)
|
||||||
|
parser.error = lambda message: (_ for _ in ()).throw(AttributeError(message))
|
||||||
parser.add_argument('--help', action='help', help='show this help message and exit')
|
parser.add_argument('--help', action='help', help='show this help message and exit')
|
||||||
parser.add_argument('--list-supported-formats', action='store_true', help='dump currently supported format list')
|
parser.add_argument('--list-supported-formats', action='store_true', help='dump currently supported format list')
|
||||||
parser.add_argument('--list-opencv-formats', action='store_true', help='(deprecated. Use --list-supported-formats) dump opencv supported format list')
|
parser.add_argument('--list-opencv-formats', action='store_true', help='(deprecated. Use --list-supported-formats) dump opencv supported format list')
|
||||||
parser.add_argument('-l', '--list-processor', action='store_true', help='dump processor list')
|
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('-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('-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('--block-size', type=int, help='block size')
|
||||||
parser.add_argument('--disable-gpu', action='store_true', help='disable GPU')
|
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')
|
parser.add_argument('--force-OpenCL', action='store_true', help='force to use OpenCL on Intel Platform')
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
Name: Waifu2x NCNN Vulkan Driver
|
Name: Waifu2x NCNN Vulkan Driver
|
||||||
Creator: SAT3LL
|
Creator: SAT3LL
|
||||||
Date Created: June 26, 2019
|
Date Created: June 26, 2019
|
||||||
Last Modified: May 5, 2020
|
Last Modified: May 7, 2020
|
||||||
|
|
||||||
Editor: K4YT3X
|
Editor: K4YT3X
|
||||||
Last Modified: February 22, 2020
|
Last Modified: February 22, 2020
|
||||||
@@ -42,6 +42,7 @@ class WrapperMain:
|
|||||||
@staticmethod
|
@staticmethod
|
||||||
def parse_arguments(arguments):
|
def parse_arguments(arguments):
|
||||||
parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter, add_help=False)
|
parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter, add_help=False)
|
||||||
|
parser.error = lambda message: (_ for _ in ()).throw(AttributeError(message))
|
||||||
parser.add_argument('--help', action='help', help='show this help message and exit')
|
parser.add_argument('--help', action='help', help='show this help message and exit')
|
||||||
parser.add_argument('-v', action='store_true', help='verbose output')
|
parser.add_argument('-v', action='store_true', help='verbose output')
|
||||||
# parser.add_argument('-i', type=pathlib.Path, help='input image path (jpg/png) or directory')
|
# parser.add_argument('-i', type=pathlib.Path, help='input image path (jpg/png) or directory')
|
||||||
|
|||||||
Reference in New Issue
Block a user