570 Commits

Author SHA1 Message Date
k4yt3x
1b67f373d1 removed UESR nobody as it breaks permissions 2022-04-01 06:51:27 +00:00
k4yt3x
7215ee1921 fixed release pipeline ref quoting 2022-04-01 06:27:15 +00:00
k4yt3x
65c0d32a51 updated the Dockerfiles and the pipeline for 5.0.0-beta5 2022-04-01 06:23:46 +00:00
k4yt3x
268460fd17 added pynput as dependency; fixed hotkey in headless env; disabled FFmpeg stdin 2022-03-21 21:46:08 +00:00
k4yt3x
d72ecb332a fixed variable name error 2022-03-21 03:43:48 +00:00
k4yt3x
8ba56e58c2 added pause function 2022-03-21 03:28:19 +00:00
k4yt3x
fa485b6cdd restricted Vulkan ICD files in Dockerfile 2022-03-21 00:21:00 +00:00
k4yt3x
625b340f3d added RealCUGAN 2022-03-19 17:45:03 +00:00
k4yt3x
fa3bd38217 fixed minor flake8 formatting issues 2022-03-18 23:14:20 +00:00
k4yt3x
0fca5c8e9a added cuda drivers to cuda Dockerfile; updated slim Dockerfile for current version 2022-03-18 23:10:40 +00:00
k4yt3x
237f6336ec sorted encoder input and updated vsync to cft from 1 2022-03-05 21:30:01 +00:00
k4yt3x
083af60c6f sorted imports using isort 2022-03-01 21:11:50 +00:00
k4yt3x
f7756886e7 changed progress bar color 2022-02-28 17:33:16 +00:00
k4yt3x
6e72df66fc added colored threat id for interp 2022-02-28 06:56:16 +00:00
k4yt3x
2bfcb13976 fixed fail to exit upon ^C 2022-02-28 06:49:41 +00:00
k4yt3x
49e0375eee updated PDM dependencies 2022-02-28 06:45:56 +00:00
k4yt3x
4459f4d3be redirected subprocess outputs into Rich console 2022-02-28 01:54:52 +00:00
k4yt3x
c0fe81bd2e improved main function return handling 2022-02-27 06:21:46 +00:00
k4yt3x
8cb64d3b70 install rife directly from PyPI; changed setuptools to pdm 2022-02-27 02:39:48 +00:00
k4yt3x
0b154a715c changed builder from setuptools to pdm 2022-02-27 02:38:56 +00:00
k4yt3x
05031b2b5a fixed GHA release workflow hook 2022-02-19 04:59:45 +00:00
k4yt3x
2510c8fa28 bumped script versions to beta4 2022-02-19 03:21:47 +00:00
k4yt3x
f17d75539c fixed dockerfile label syntax 2022-02-19 01:49:23 +00:00
k4yt3x
82512ef10c updated CI to build multiple versions of containers 2022-02-17 05:43:12 +00:00
k4yt3x
ad479e53b8 renamed Dockerfiles for CI 2022-02-17 05:42:48 +00:00
k4yt3x
a356bfeaff fixed workflow container image name 2022-02-17 05:08:22 +00:00
k4yt3x
dee8e23485 changed get tag command 2022-02-17 04:59:24 +00:00
k4yt3x
1fa0821057 changed container build pipeline to release 2022-02-17 04:36:26 +00:00
k4yt3x
b5ecffba81 added container build workflow 2022-02-17 04:22:27 +00:00
k4yt3x
672c9b8652 bumped version to 5.0.0-beta4 2022-02-17 03:52:04 +00:00
k4yt3x
9f73e75f17 added audio, subtitles, data, and attachments copying 2022-02-17 03:51:55 +00:00
k4yt3x
ef1a8f3e41 added extra args for run scripts 2022-02-17 03:50:38 +00:00
k4yt3x
04f409ef80 updated discussion group heading 2022-02-17 02:01:06 +00:00
k4yt3x
51c8693dce fixed legeal info print 2022-02-16 03:02:26 +00:00
k4yt3x
bb572e2468 fixed argparse help bug 2022-02-16 02:56:35 +00:00
k4yt3x
c07fafc0e9 bumped version to 5.0.0-beta3 2022-02-15 07:02:53 +00:00
k4yt3x
595b179d3c updated Library link 2022-02-15 05:49:24 +00:00
k4yt3x
c865d494a1 updated run source script paths 2022-02-15 02:30:22 +00:00
k4yt3x
f4acb2188d renamed container run scripts 2022-02-15 00:59:40 +00:00
k4yt3x
01d4006c75 changed -d to -a 2022-02-15 00:55:54 +00:00
k4yt3x
a7f0f34751 terminology change: driver -> algorithm 2022-02-15 00:54:17 +00:00
k4yt3x
b6b1bf9f0e added two container debugging scripts 2022-02-15 00:52:28 +00:00
k4yt3x
5d7a53a2fc added Python and shell examples 2022-02-15 00:52:21 +00:00
k4yt3x
b32e0ec132 updated containers documentation path 2022-02-15 00:06:56 +00:00
k4yt3x
6378a36d91 remove encoded images from memory to prevent exhaustion 2022-02-13 03:47:27 +00:00
k4yt3x
0d0fd70a24 redirected STDOUT and STDERR to prevent output from breaking the progress bar 2022-02-12 23:51:30 +00:00
K4YT3X
7c0e9c45d8 Merge pull request #598 from mayiflex/master
Update README.md
2022-02-12 20:24:07 +00:00
k4yt3x
7b60041529 replaced tqdm with rich.progress; enhanced error handling 2022-02-12 09:08:28 +00:00
k4yt3x
6ffd6282e0 removed tqdm files from project 2022-02-12 09:08:05 +00:00
mayiflex
c37e7f0d72 Update README.md
Fixed hyperlink to the Collab Notebook with instructions
2022-02-12 09:58:54 +01:00
k4yt3x
ca1e593874 let setup read version from init 2022-02-12 06:45:59 +00:00
k4yt3x
bfb0f339e2 fixed log format issue 2022-02-12 06:45:33 +00:00
k4yt3x
3690337092 fixed FFmpeg memory exhaustion issue by limiting the queue size 2022-02-12 05:14:00 +00:00
k4yt3x
6c129a1c7a fixed a typo in release link 2022-02-11 22:28:50 +00:00
k4yt3x
2b539c15f7 updated setup licensing and classification info 2022-02-11 22:28:34 +00:00
k4yt3x
53456cd442 updated gitignore 2022-02-11 06:59:44 +00:00
k4yt3x
e1f4cdd71d updated licensing info in source files 2022-02-11 06:55:07 +00:00
k4yt3x
ab6d2e3c9e reorganized README sections and docs 2022-02-11 01:33:04 +00:00
k4yt3x
f69c95a608 completed the Telegram group's description 2022-02-10 03:50:50 +00:00
k4yt3x
c103e45076 updated release information 2022-02-10 03:47:31 +00:00
k4yt3x
240d722fda updated the Dockerfiles to use full URL 2022-02-10 03:26:01 +00:00
k4yt3x
14f3cd1e16 removed Docker badge since we no longer use Docker Hub 2022-02-08 07:02:49 +00:00
k4yt3x
f4cc178dcd removed outdated CodeQL workflow 2022-02-08 07:02:34 +00:00
k4yt3x
ad825bd2ba removed git checkout from CodeQL workflow 2022-02-08 06:53:45 +00:00
k4yt3x
151733c8f8 updated README and legal/licensing info 2022-02-08 06:49:57 +00:00
K4YT3X
544a7081ed Merge pull request #593 from k4yt3x/5.0.0-beta
5.0.0 beta
2022-02-08 05:30:28 +00:00
k4yt3x
4b3bde1615 updated license to AGPL 3.0 2022-02-08 05:21:55 +00:00
k4yt3x
b38cef2de2 removed outdated issue templates 2022-02-08 05:21:36 +00:00
k4yt3x
b27da8a61a updated funding info 2022-02-08 05:21:13 +00:00
k4yt3x
5e4170b0b7 fixed CI pipeline build stage 2022-02-08 05:06:26 +00:00
k4yt3x
b3539d4aa8 removed Gifski wrapper which is no longer being used 2022-02-08 05:01:20 +00:00
k4yt3x
d09efc4748 rewritten the CI pipeline for 5.0.0 2022-02-07 01:07:04 +00:00
k4yt3x
dc532ff184 updated video2x package information 2022-02-04 22:01:45 +00:00
k4yt3x
1fbb2f22f3 removed files for Jenkins website 2022-02-04 21:46:21 +00:00
k4yt3x
339815f74c added the CUDA-based Dockerfile as default 2022-02-04 21:00:38 +00:00
k4yt3x
fa6dc88faa updated metadata in the Alpine Dockerfile 2022-02-04 21:00:23 +00:00
k4yt3x
ce344caa72 renamed the Alpine-based Dockerfile 2022-02-04 20:56:58 +00:00
k4yt3x
d8aed8065b added OpenCV file open check 2022-02-02 15:20:03 +00:00
k4yt3x
6b83734382 added new requirements items 2022-02-02 15:19:14 +00:00
k4yt3x
2b52d4aa45 changed Rife dependency path 2022-02-02 15:18:32 +00:00
k4yt3x
a515886ad8 updated the setup.cfg to include new dependencies 2022-02-02 15:17:46 +00:00
k4yt3x
a7629db518 rewritten the Dockerfile for 5.0.0 2022-02-02 15:17:27 +00:00
K4YT3X
ba336e9c75 renamed SRMD and RealSR classes per Python conventions 2021-08-17 14:43:49 +00:00
K4YT3X
736771b1c8 added *-ncnn-vulkan dependencies into requirements.txt 2021-08-17 14:41:59 +00:00
K4YT3X
f9f736bec1 removed add_help=False and redundant numpy import 2021-08-17 14:40:31 +00:00
K4YT3X
535681f3cd renamed RIFE to Rife per Python conventions 2021-08-17 14:39:50 +00:00
K4YT3X
f283a12a0b fixed another upscaler diff threshold calculation error 2021-07-06 02:19:38 +00:00
K4YT3X
ac80de9399 fixed upscaler diff threshold bug 2021-07-06 01:27:32 +00:00
K4YT3X
7eabac2175 committing changes for 5.0.0-beta 2021-07-06 00:56:56 +00:00
K4YT3X
e870399af1 moved src to video2x for PyPI 2021-07-06 00:56:12 +00:00
K4YT3X
37d567f208 Merge pull request #480 from Presc/master
Update README.md
2021-03-14 04:17:13 +00:00
K4YT3X
7b9e811c99 Updated Bad Apple demo links with 120FPS versions' links 2021-03-14 04:16:32 +00:00
Prescot
0d97a11015 Update README.md
Updated old bad apple demo link to new updated version.
2021-03-13 14:20:18 +00:00
K4YT3X
079a2aa64b Merge pull request #471 from PeterDaveHello/fix-docker-build
Fix sources.list path in Dockerfile, cc #470
2021-02-24 16:57:20 +00:00
Peter Dave Hello
9cdddd2e41 Fix sources.list path in Dockerfile, cc #470 2021-02-25 00:30:40 +08:00
K4YT3X
26d82e1582 Merge pull request #470 from PeterDaveHello/fix-docker-build
Fix Docker image build by using Ubuntu old-release apt repository
2021-02-23 21:45:12 +00:00
Peter Dave Hello
c4e73cfbc7 Fix Docker image build by using Ubuntu old-release apt repository
Ubuntu 19.10 is EOL, but due to Nvidia library compatibility issue, the
base image of the Dockerfile wasn't upgraded to newer Ubuntu yet, and a
standard apt repository site won't be reachable in this case, which
makes the Docker image not able to be built. Before the base image
upgrade, a workaround to use old-releases apt repository can make the
image be able to be built again.
2021-02-23 20:13:37 +08:00
K4YT3X
2fffeeadf1 Merge pull request #453 from FrostyTheDumDum/master
Update README.md
2021-01-29 18:01:10 +00:00
Frosty!
25155b3029 Update README.md 2021-01-29 16:37:54 +05:30
K4YT3X
26795c5561 fixed issue #427 2021-01-23 17:01:38 -05:00
K4YT3X
5543382d03 fixed issue 443 2021-01-23 16:48:29 -05:00
K4YT3X
dc51b8b04c attempting to fix #442 2021-01-23 16:33:40 -05:00
K4YT3X
cde02be32b updated license dates 2021-01-23 16:33:19 -05:00
K4YT3X
9213e3e13a set default fallback locale for gettext 2021-01-07 00:35:58 -05:00
K4YT3X
b41f1f7e6c corrected ncnn Vulkan drivers' names 2021-01-07 00:34:18 -05:00
K4YT3X
7201c036d5 Merge branch 'master' of github.com:k4yt3x/video2x 2020-12-29 01:25:27 -05:00
K4YT3X
da532d8e13 renamed image file names and added workflow diagrams 2020-12-29 01:25:17 -05:00
K4YT3X
f97ed080e1 updated Video2X banner files 2020-12-20 21:32:10 -05:00
K4YT3X
d67f55c824 updated Video2X banner to be compatible with GitHub's new dark theme 2020-12-21 02:31:40 +00:00
K4YT3X
095d40b688 Merge pull request #434 from k4yt3x/black
Formatted code with Black and updated README
2020-12-21 01:58:19 +00:00
K4YT3X
bd6690fed1 updated Patreon badge 2020-12-20 20:56:49 -05:00
K4YT3X
bfda833bcf formatted code with black 2020-12-19 18:11:11 -05:00
K4YT3X
09345703e6 fixed video2x ubuntu setup script paths 2020-12-15 13:05:16 -05:00
K4YT3X
64e4a41710 Merge pull request #424 from fire0shadow/anime4kcpp-import-fix
Add 'import sys' to anime4kcpp.py wrapper
2020-12-15 17:59:28 +00:00
K4YT3X
f7b8b2520a sorted imports and updated file metadata 2020-12-15 17:58:45 +00:00
K4YT3X
fad793b18e formatted build script 2020-12-15 12:56:28 -05:00
K4YT3X
d09d05ae9b fixed video2x_gui name 2020-12-15 12:55:58 -05:00
Fireshadow
89ca3b09d9 Add 'import sys' to anime4kcpp.py wrapper 2020-12-14 23:26:16 +07:00
K4YT3X
4694c557ec added a none option for -tune to address #401 2020-12-13 17:13:03 -05:00
K4YT3X
33d96bcd4e added Discord server description 2020-12-13 16:55:37 -05:00
K4YT3X
eee43def3b redirected subprocess.Popen streams to system stdout and stderr 2020-12-13 16:53:55 -05:00
K4YT3X
f4be9cc596 BiLogger now inherits io.TextIOWrapper and has a fileno attribute 2020-12-13 16:52:58 -05:00
K4YT3X
cc89b0aac5 formatted setup script with black 2020-12-13 16:39:49 -05:00
K4YT3X
9e8e95803f setup script 2.4.1: fixed Gifski setup issues and enhanced garbage cleaning 2020-12-13 16:39:13 -05:00
K4YT3X
df0861ff5c Merge pull request #411 from konqiDAM/master
fix: windows installer fixed, now uses "zipball_url" for gifski
2020-11-18 20:24:54 +00:00
K4YT3X
706aeab03f updated setup script metadata 2020-11-18 20:24:17 +00:00
konqi
f850ca80f1 fix: windows installer fixed, now uses "zipball_url" for gifski 2020-11-18 20:56:56 +01:00
K4YT3X
608bf1a2ec added a link for @Felixkruemel 's name 2020-10-26 18:24:43 -04:00
K4YT3X
b1f7290c20 update Google Colab descriptions 2020-10-26 18:22:52 -04:00
K4YT3X
65d445c293 upscaler 4.4.1: use mimetypes to re-check python-magic's results 2020-10-26 18:14:49 -04:00
K4YT3X
43dbb134b6 Merge pull request #389 from jitsuCM/arr_fix
Quick fix for special case no-upscale 1.0 upscale
2020-10-26 22:09:04 +00:00
K4YT3X
84b0684d64 apply the smallest scaling ratio available instead of 1 2020-10-26 21:53:03 +00:00
K4YT3X
29b4153b63 Merge pull request #384 from Felixkruemel/master
Added Google Colab to readme
2020-10-26 21:47:43 +00:00
K4YT3X
3f1821f1ac Merge pull request #373 from donicrosby/master
Fixed issue where if hwaccel value in config is overwritten with auto
2020-10-26 21:47:16 +00:00
K4YT3X
4f8bb1be1c setup script 2.4.0: updated FFmpeg download URL and unpacking method 2020-10-26 13:13:54 -04:00
jitsuCM
c2f1e43656 Quick fix for special case no-upscale 1.0 upscale 2020-10-22 09:21:53 +02:00
Felixkruemel
914d5cdf87 fixed blank line 2020-10-13 19:27:36 +02:00
Felixkruemel
de77c90dd1 Updated Readme.md with Google Colab integration 2020-10-13 19:26:53 +02:00
donicrosby
458ce82644 Merge branch 'master' of https://github.com/k4yt3x/video2x into master 2020-09-29 17:18:37 -04:00
donicrosby
1d145a8690 Fixed issue where if hwaccel value is set to anything other auto it would be overwritten 2020-09-29 00:51:32 -04:00
K4YT3X
b37acfa31d setup script 2.3.0: changed FFmpeg build provider from zeranoe to gyan.dev 2020-09-28 20:31:22 -04:00
K4YT3X
a0522311e2 made custom intermediate frame format available for waifu2x/srmd/realsr 2020-09-21 15:14:00 -04:00
K4YT3X
7de9cc699a Merge pull request #363 from medram/waifu2x_ncnn_vulkan_args_update
Fixed supporting jpg format for waifu2x_ncnn_vulkan by updating its arguments.
2020-09-21 19:06:42 +00:00
medram
685648957f Update waifu2x_ncnn_vulkan arguments to the latest version! 2020-09-20 21:34:20 +01:00
K4YT3X
c2260ca709 updated wordings and translations 2020-09-14 14:25:17 -04:00
K4YT3X
776475265e added generate POT file script 2020-09-13 17:10:03 -04:00
K4YT3X
21928f9eb4 commented controlled parameters for waifu2x-caffe and Gifski 2020-09-13 17:09:24 -04:00
K4YT3X
211f024e49 removed useless Gifski width/height elements in GUI 2020-09-13 17:08:34 -04:00
K4YT3X
bfdb051705 fixed global scaling variable errors and Gifski output resolution issues 2020-09-13 17:05:36 -04:00
K4YT3X
d824cd6516 added description for log file saving scheme 2020-09-13 16:43:44 -04:00
K4YT3X
b4f46ad31e enhanced logging and error reporting system 2020-09-13 16:38:44 -04:00
K4YT3X
a8d7f7ecf2 redesigned upscaler to use pillow's Lanczos filter for downscaling; bug fixes 2020-09-13 14:34:52 -04:00
K4YT3X
2b84e497b5 added pillow into requirements 2020-09-13 14:34:17 -04:00
K4YT3X
9b408a6e62 renamed labels 2020-09-13 14:33:46 -04:00
K4YT3X
ecf94490a7 fixed working directory and timing errors 2020-09-13 14:33:35 -04:00
K4YT3X
881183ed0a removed image resizing function which is no longer needed 2020-09-13 14:33:12 -04:00
K4YT3X
9389511d2d fixed bulk processing file output issues 2020-09-13 12:42:55 -04:00
K4YT3X
16389fc8a6 changed frame preview layout 2020-09-13 12:42:36 -04:00
K4YT3X
c7013b2576 redesigned upscaler class to make arbitrary scaling available for images 2020-09-13 11:07:39 -04:00
K4YT3X
a82fcc778e fixed waifu2x-caffe upscale by resolution errors and optimized upscaler code 2020-09-12 19:34:48 -04:00
K4YT3X
6dbdf93ca4 eliminated unnecessary variable upscale_begin_time 2020-09-12 17:40:17 -04:00
K4YT3X
64eb03ac08 calculate width/height automatically if the value is 0 2020-09-10 16:38:11 -04:00
K4YT3X
227cf54a47 removed all use of the walrus operator for better backwards compatibility 2020-09-10 16:19:07 -04:00
K4YT3X
107d31e5dc removed the use of shlex.join for better backwards compatibility 2020-09-10 16:15:05 -04:00
K4YT3X
04562dcaa1 allow only one of width an height to be specified 2020-09-10 13:14:36 -04:00
K4YT3X
7059852586 added arbitrary upscaling ratio/resolution support 2020-09-09 13:07:42 -04:00
K4YT3X
8b7e9f959b fixed Docker Anime4KCPP path 2020-09-04 22:04:04 -04:00
K4YT3X
19bd05149d updated Anime4KCPP build script for the latest Anime4KCPP 2020-09-04 21:48:13 -04:00
K4YT3X
a3706a1a17 fixed aria2c download directory 2020-09-04 16:56:00 -04:00
K4YT3X
5a7c464dea added Anime4KCPP into Ubuntu setup script 2020-09-04 12:26:34 -04:00
K4YT3X
6c1b49b5ed GUI 2.7.3: fixed waifu2x-caffe output quality option 2020-09-04 02:06:24 -04:00
K4YT3X
59860dcfc3 added missing source command in Docker script 2020-09-02 14:00:47 -04:00
K4YT3X
b38ce2c56d fixed gifski build issue by downloading the newest cargo directly 2020-09-02 13:54:58 -04:00
K4YT3X
68e6331672 updated GUI for the newest version of Anime4kCPP 2020-09-01 03:48:00 -04:00
K4YT3X
188a44ce38 updated Anime4KCPP driver arguments 2020-08-20 04:50:19 -04:00
K4YT3X
5621eb306a changed default extracted frames pixel format from rgba64be to rgb24 2020-08-18 06:07:46 -04:00
K4YT3X
07a6356836 Created CodeQL workflow for code security scanning 2020-08-10 22:47:53 +00:00
K4YT3X
ef4269bbcd fixed ubuntu setup script embedded script path inconsistency 2020-07-25 19:56:25 -04:00
K4YT3X
898d45e4b5 opening log file with UTF-8 encoding to avoid compatibility problems 2020-07-17 14:48:57 -04:00
k4yt3x
01493068e1 added scroll area in GUI for low-resolution displays 2020-07-01 21:02:40 -04:00
k4yt3x
e44264bb6b added output file name format string 2020-06-30 10:41:31 -04:00
K4YT3X
06355441ea using gcc/g++ 8 to provide CC/CXX for cmake via environment variable instead of linking 2020-06-13 10:53:12 -04:00
K4YT3X
9b9da1ba5a updated Docker tag version 2020-06-13 09:47:35 -04:00
K4YT3X
78fa5e8c07 removed duplicating ca-certificates package 2020-06-13 08:25:21 -04:00
K4YT3X
b2d7415a2c fixed Docker build CA error 2020-06-13 08:07:59 -04:00
K4YT3X
75d342f145 updated Docker usages in README 2020-06-13 07:51:23 -04:00
K4YT3X
fae08dfb11 fixed waifu2x-caffe pathlib not found 2020-06-13 06:47:03 -04:00
K4YT3X
a0745e2196 made all drivers change cwd to binary's parent directory to resolve fnf issues 2020-06-13 06:26:27 -04:00
K4YT3X
986619165f bind mounting host to Docker 2020-06-13 06:13:12 -04:00
K4YT3X
78b0420e07 fixing waifu2x-converter-cpp issues 2020-06-13 06:12:52 -04:00
K4YT3X
1eba4f2187 patching waifu2x-converter-cpp libw2xc.so not found issue 2020-06-13 05:09:10 -04:00
k4yt3x
6e1315f2ed updated issue templates 2020-06-11 02:00:35 -04:00
k4yt3x
29a776d049 added file descriptions for src folder 2020-06-09 08:53:17 -04:00
k4yt3x
da4bfe9827 updated disable logging switch name in README 2020-06-08 05:10:09 -04:00
k4yt3x
00c391b46c disabled purging to avoid accidental uninstallation of wanted packages 2020-06-08 03:56:19 -04:00
k4yt3x
f5eb6514e1 moved upscaler optional parameters into function definition 2020-06-08 02:36:44 -04:00
k4yt3x
3f6a3addaa updated gitignore for QtCreator files 2020-06-08 02:07:27 -04:00
k4yt3x
8f2113ab0a removed useless QtCreator file 2020-06-08 02:06:38 -04:00
k4yt3x
60cf792c23 added disable logging check box 2020-06-07 23:59:00 -04:00
k4yt3x
7e87dac15e made output extensions in batch processing customizable 2020-06-07 23:36:09 -04:00
k4yt3x
0b15fb7bd2 renamed image_format to extracted_frame_format 2020-06-07 23:35:17 -04:00
k4yt3x
765db2512b remove libvulkan1 from garbage deletion 2020-06-07 19:39:54 -04:00
k4yt3x
e14fbea67b fixing issue #289 2020-06-07 15:43:30 -04:00
k4yt3x
491f80d2d2 updated Anime4KCPP 2.0 CNN Mode support 2020-06-07 15:27:15 -04:00
K4YT3X
2f4953e6c7 updated Dockerfile for ubuntu setup script changes 2020-06-05 16:11:43 -04:00
K4YT3X
3f36cb8b43 fixing waifu2x-caffe compile issues 2020-06-05 09:12:46 -04:00
K4YT3X
3e57e206c6 added config updating Python script 2020-06-05 08:56:37 -04:00
K4YT3X
da0e47528c changed file mode for script files 2020-06-05 08:41:17 -04:00
K4YT3X
f6aac30f96 added ubuntu setup script 2020-06-05 08:40:32 -04:00
K4YT3X
7d00189f2f added Actions download login notice 2020-06-05 07:54:05 -04:00
K4YT3X
751150fe64 ignoring all python-magic errors 2020-06-05 07:14:03 -04:00
K4YT3X
eb2b62b056 removed a redundant line 2020-06-05 07:13:44 -04:00
K4YT3X
cc1b0b5464 changed file mode 2020-06-05 02:10:24 -04:00
k4yt3x
fe7ded7e53 pointing download links to the latest releases 2020-06-05 01:52:38 -04:00
k4yt3x
5f2ad35d41 fixing issue #287 2020-06-05 01:09:57 -04:00
k4yt3x
d688ca490e bumped last edited date and added comments 2020-06-04 22:13:30 -04:00
k4yt3x
708c983c1e added log file 2020-06-04 22:10:19 -04:00
K4YT3X
9b91016d98 Merge pull request #286 from ImportTaste/requirements
Adjustments to return to a single requirements.txt
2020-06-05 00:33:01 +00:00
ImportTaste
b024581906 Adjustments to return to a single requirements.txt 2020-06-04 19:25:31 -05:00
k4yt3x
8fd3292cd6 use mimetypes when python-magic binaries are not found 2020-06-04 18:46:29 -04:00
k4yt3x
e646825c57 moved apt-key statement to resolve stdout error 2020-05-31 04:00:45 -04:00
k4yt3x
fdf326108f fixing libcudnn7-dev source 2020-05-30 22:43:49 -04:00
k4yt3x
e26561c56a removing unused packages from Dockerfile and fixed a typo 2020-05-30 20:02:04 -04:00
k4yt3x
9d7c3963c3 removed some unused packages 2020-05-30 20:01:24 -04:00
k4yt3x
ce5d4051e5 setup script 2.2.1: updated regex for new waifu2x/srmd/realsr NCNN Vulkan 2020-05-30 16:11:05 -04:00
k4yt3x
9f6f1eee5b added more comments in the config file 2020-05-29 21:18:07 -04:00
k4yt3x
6ae7491652 added RealSR into descriptions and credits 2020-05-29 21:15:36 -04:00
k4yt3x
d35472fbfb added links to specials thanks usernames 2020-05-29 18:14:54 -04:00
k4yt3x
7166afdc0e updated file information and maintainer labels, added comments, changed ENTRYPOINT 2020-05-29 18:14:32 -04:00
k4yt3x
d3db4e8cf1 updated build script requirements file name 2020-05-29 16:24:22 -04:00
k4yt3x
f887dfe3a7 fixed a dash with the wrong encoding 2020-05-29 16:20:11 -04:00
k4yt3x
a41df138bf updated setup script for RealSR NCNN Vulkan and changed requirement files 2020-05-29 16:02:06 -04:00
k4yt3x
41833f4068 fixed Anime4KCPP multi-processing mishandling issue 2020-05-29 15:30:16 -04:00
K4YT3X
c0955ae7e4 updated file modes for Linux 2020-05-28 10:52:38 -04:00
K4YT3X
682aeb82ff updated GitHub Actions config for requirements file changes 2020-05-28 10:24:24 -04:00
K4YT3X
21407c831c separated Linux requirements from Windows requirements 2020-05-28 10:23:54 -04:00
k4yt3x
7e34bf7516 updated Patreon badge 2020-05-27 19:17:05 -04:00
k4yt3x
4c5ca73e38 added RealSR NCNN Vulkan support 2020-05-26 06:35:53 -04:00
k4yt3x
387a233daf added Docker cloud build status badge 2020-05-25 05:29:28 -04:00
k4yt3x
781eb6686f added Docker usage section, added @lhanjian to special thanks for writing the Dockerfile 2020-05-24 23:36:10 -04:00
k4yt3x
c73edd9001 fixed docker submodule issues, formatted Dockerfile 2020-05-24 23:09:22 -04:00
k4yt3x
deb742ee8d added a short description for each of the drivers 2020-05-24 14:26:32 -04:00
k4yt3x
5ef6eb7e8e added Dockerfile written by @lhanjian 2020-05-24 13:24:28 -04:00
k4yt3x
6c5e079a1c added a list of supported drivers into README since it is useful info 2020-05-23 10:19:18 -04:00
k4yt3x
1e384596ee Updated special thanks section 2020-05-23 09:40:17 -04:00
k4yt3x
4680647f1f removed the insignificant master version number badge 2020-05-23 09:05:31 -04:00
k4yt3x
4015db5bcf CLI 4.0.1: require input and output to be specified if help is not specified 2020-05-23 08:59:57 -04:00
k4yt3x
082c6d44fa GUI 2.4.0: added H264/265 tune option 2020-05-23 08:59:39 -04:00
k4yt3x
de841a4636 removed bold exception string to avoid formatting bugs 2020-05-23 07:41:01 -04:00
k4yt3x
40711a2711 updated translations for upscaler 4.1.1 2020-05-22 17:56:31 -04:00
k4yt3x
0c63768165 Upscaler 4.1.1: fixed python-magic detection issues, added more debug output 2020-05-22 17:56:22 -04:00
k4yt3x
ac2d447391 GUI 2.3.1: added shortcut keys 2020-05-22 17:55:55 -04:00
k4yt3x
b03747dbde updated translations after fixing typo 2020-05-22 16:30:02 -04:00
k4yt3x
89740f01dc using mimetypes as a backup mime detection method, fixed typo 2020-05-22 16:29:51 -04:00
k4yt3x
676e70f088 updated drivers tooltips 2020-05-17 16:15:38 -04:00
k4yt3x
f57b5e9d04 bumped GUI version number 2020-05-17 16:15:26 -04:00
k4yt3x
f48e23a890 ignore FileNotFoundError while clearing cache 2020-05-17 15:50:05 -04:00
k4yt3x
826b4e9829 renamed stream copy checkbox 2020-05-17 15:48:21 -04:00
k4yt3x
c56be51e21 updated output path generation logic, organized lines 2020-05-17 15:48:06 -04:00
k4yt3x
d2b3175ccd changed default output codec to yuv420p for wider compatibility, added frame interpolation comment 2020-05-17 15:47:33 -04:00
k4yt3x
a98d1c7277 added stopping confirmation 2020-05-17 10:51:17 -04:00
k4yt3x
e107ddc96e updated translations 2020-05-17 10:13:43 -04:00
k4yt3x
289f5441eb added FFmpeg frame interpolation option 2020-05-17 09:57:07 -04:00
k4yt3x
179bd6afc8 updated GUI 2.1.0 screenshot 2020-05-16 08:01:11 -04:00
k4yt3x
5af49012c8 upscaler 4.1.0: removed Anime4KCPP workaround to enable support for GIF and progress bar 2020-05-16 07:12:25 -04:00
k4yt3x
192c6ef38b setup script 2.1.0: added uninstallation option, other minor enhancements 2020-05-16 07:04:44 -04:00
k4yt3x
0b67ec879d updated Jekyll site settings 2020-05-16 06:32:49 -04:00
k4yt3x
288f21f7ce updated Jekyll config 2020-05-16 06:21:30 -04:00
k4yt3x
60af2a2782 updated mirror site information 2020-05-16 05:40:44 -04:00
k4yt3x
53aa27409e fixing Jekyll theme plugin 2020-05-16 04:00:26 -04:00
k4yt3x
ab22fb2359 changing GitHub Pages theme attempt 2 2020-05-16 03:54:07 -04:00
k4yt3x
fc18307b22 changing GitHub Pages theme 2020-05-16 03:36:58 -04:00
k4yt3x
04d598a525 CLI and GUI now displays upscaler version 2020-05-15 21:28:22 -04:00
k4yt3x
748f1e5799 updated run from source code URL 2020-05-15 21:15:03 -04:00
k4yt3x
c384bb91c4 added checkbox to ensure width and height are divisible by 2 2020-05-14 22:34:27 -04:00
k4yt3x
0882f44e1f added Gifski settings, added config filter for ffmpeg 2020-05-14 20:17:10 -04:00
k4yt3x
99abb4f6df 2.1.0: added FFmpeg Settings tab 2020-05-14 19:56:06 -04:00
k4yt3x
54f8f19c7e added input_options import for every phase 2020-05-14 19:55:52 -04:00
k4yt3x
c1c96815cf adjusted FFmpeg options and added comments 2020-05-14 19:55:25 -04:00
k4yt3x
98a7fbf9cb fixed FFmpeg configuration key 2020-05-13 02:43:22 -04:00
k4yt3x
f2ba6033b7 added locale into pyinstaller packages 2020-05-13 02:42:56 -04:00
k4yt3x
f92d1a41a2 moved FFprobe general options before input and output options 2020-05-12 21:23:26 -04:00
k4yt3x
1b6c4b8c49 renamed FFmpeg phase names to match FFmpeg wrapper function names 2020-05-12 21:11:30 -04:00
k4yt3x
9b4ee89aee added FFmpeg Settings tab and Tools tab and FFprobe tool 2020-05-12 20:31:58 -04:00
k4yt3x
0953fc52a1 made image format optional 2020-05-12 20:31:39 -04:00
k4yt3x
759a3c7c96 updated FFmpeg parameters, moved debug info 2020-05-12 20:30:59 -04:00
k4yt3x
786ccaa610 upon stream migration fails, move intermediate file instead of copy 2020-05-12 19:27:37 -04:00
k4yt3x
0c3c136458 fixing issue #249 by @GitGerby 2020-05-12 19:25:39 -04:00
k4yt3x
1be2c1ead7 fixed pyinstaller 7z unpacking issues, replaced pyunpack with patoolib 2020-05-12 06:31:18 -04:00
k4yt3x
180bfcab20 added 7z files for pyinstaller 2020-05-12 06:30:49 -04:00
k4yt3x
0cc67857f7 changed setup script pyunpack to patoolib 2020-05-12 05:50:08 -04:00
k4yt3x
e07848f4bf updated GUI and CLI screenshots 2020-05-12 04:47:00 -04:00
k4yt3x
379d699c0d added patool hidden import for setup script 2020-05-12 04:39:24 -04:00
k4yt3x
e6702d4486 removed "recent change" as this info will be available in releases 2020-05-12 04:31:22 -04:00
k4yt3x
8f5edb720e updated translations 2020-05-12 04:30:04 -04:00
k4yt3x
b27e9b1fa5 added line breaks before image captions 2020-05-12 04:18:20 -04:00
k4yt3x
0b72236d95 added nightly build information, updated some other fields 2020-05-12 04:15:02 -04:00
k4yt3x
fdb813d6d6 moved build.yml to nightly.yml 2020-05-12 03:42:48 -04:00
k4yt3x
417dfc5deb changed nightly build workflow name 2020-05-12 03:42:13 -04:00
k4yt3x
12673f1c37 added pywin32 to fix build issues, renamed artifacts 2020-05-12 03:31:34 -04:00
k4yt3x
f7d8d551b3 corrected nightly build path 2020-05-12 03:23:17 -04:00
k4yt3x
9cbb213e55 added artifact collecting and uploading 2020-05-12 03:16:28 -04:00
k4yt3x
181e5c94e6 fixed path error for requirements.txt 2020-05-12 02:43:44 -04:00
k4yt3x
37547d1233 changed workflow default working directory 2020-05-12 02:40:55 -04:00
k4yt3x
8368cb1f49 replaced workflow forward slash with grave accent 2020-05-12 02:29:44 -04:00
k4yt3x
9643c96ed7 updated workflow to eliminate unix shell syntax 2020-05-12 02:26:07 -04:00
K4YT3X
1c5bf1604f Create build.yml 2020-05-12 06:18:24 +00:00
k4yt3x
23cfba86f8 updated GIF and image upscale examples 2020-05-11 22:41:06 -04:00
k4yt3x
0ef0d6e161 updated banner and social preview PSD file 2020-05-11 22:02:47 -04:00
k4yt3x
4e43ff9086 fixed Anime4KCPP attribute issue 2020-05-11 21:01:09 -04:00
k4yt3x
a93d18eb09 updated logo and banner 2020-05-11 21:00:55 -04:00
k4yt3x
e305d0188e added image and GIF upscale support 2020-05-11 20:24:18 -04:00
k4yt3x
5cf3271aad added Bad Apple!! to demo videos 2020-05-11 16:24:09 -04:00
k4yt3x
bcbead4d96 updated CLI usages 2020-05-11 06:57:16 -04:00
k4yt3x
a3d0465e44 updated GUI screenshot 2020-05-11 05:32:39 -04:00
k4yt3x
995fdec5c8 updated sample video URLs 2020-05-11 05:18:00 -04:00
k4yt3x
5c3ea51ccb updated demo video links 2020-05-11 05:13:06 -04:00
k4yt3x
a24b321088 updated translations 2020-05-11 04:41:05 -04:00
k4yt3x
a83249c670 fixed waifu2x-caffe pixel format check typo 2020-05-11 04:38:33 -04:00
k4yt3x
ab2f982a84 fixed waifu2x-caffe parsing error 2020-05-11 04:33:38 -04:00
k4yt3x
91401977da added frame preview, redesigned driver instance initiation and argument parsing 2020-05-11 04:17:21 -04:00
k4yt3x
99971bceb1 adjusted GUI dimensions 2020-05-10 00:59:16 -04:00
k4yt3x
0c6de8af16 re-added CLI usages 2020-05-09 23:31:34 -04:00
k4yt3x
4def30f516 added prerequisites in README 2020-05-09 23:22:36 -04:00
k4yt3x
8d553ac575 added a link for download builds 2020-05-09 23:14:24 -04:00
k4yt3x
e1a1cf578b moved badges below the icon 2020-05-09 23:13:12 -04:00
k4yt3x
4015617152 updated README for recent code updates 2020-05-09 23:12:37 -04:00
k4yt3x
648bf4fd3d added video2x banner files 2020-05-09 23:12:20 -04:00
k4yt3x
e3ed08ff40 updated logo files 2020-05-09 22:20:40 -04:00
k4yt3x
90f807655a better about and error dialog 2020-05-09 20:27:04 -04:00
k4yt3x
ab77d62c71 updated config file comments 2020-05-09 20:13:08 -04:00
k4yt3x
a64fabae87 added more GUI options for waifu2x-converter-cpp 2020-05-09 20:10:12 -04:00
k4yt3x
26558c6159 changed some wording in upscaler 2020-05-09 19:40:18 -04:00
k4yt3x
4fbbb20258 updated zh_CN translation files 2020-05-09 19:40:07 -04:00
k4yt3x
4659a9a9f5 changed gitignore to include translation files 2020-05-09 19:39:51 -04:00
k4yt3x
4c48af4fa4 output intermediate video-only file if stream migration fails 2020-05-09 19:30:24 -04:00
k4yt3x
4a6f90a1f0 fixing temp directory loading problem attempt 2 2020-05-09 05:49:59 -04:00
k4yt3x
2d9c5fe751 fixed custom cache path loading issues 2020-05-09 05:39:40 -04:00
k4yt3x
bef3861d3c fixed some spelling errors in waifu2x-caffe 2020-05-09 05:39:19 -04:00
k4yt3x
bcb54b6d2c yielding multithreading control to srmd/waifu2x-ncnn-vulkan, fixing FFmpeg framerate detection 2020-05-09 04:54:28 -04:00
k4yt3x
e82a26d44f deleted some unused imports 2020-05-09 02:23:21 -04:00
k4yt3x
14f7f34ee3 build script displays v2x version when building 2020-05-09 01:11:03 -04:00
k4yt3x
11ba334f16 added more comments and ffmpeg Video2X signature 2020-05-09 01:01:12 -04:00
k4yt3x
c451b14bd7 fixed waifu2x-converter-cpp path error 2020-05-09 00:54:57 -04:00
k4yt3x
80623a6bb7 fixed waifu2x-converter-cpp constraints 2020-05-09 00:47:12 -04:00
k4yt3x
a5dd87a72c updated build script to read version from args 2020-05-08 22:35:10 -04:00
k4yt3x
9b20ef89c9 fixed Anime4KCPP execution issues 2020-05-08 22:34:53 -04:00
k4yt3x
91efe2d684 updated zh_CN translation 2020-05-08 22:12:33 -04:00
k4yt3x
0d9d5c4f43 fixed progress monitor error, enhanced GUI error display 2020-05-08 22:12:24 -04:00
k4yt3x
e0e42b11c8 update qtcreator file 2020-05-08 20:29:08 -04:00
k4yt3x
790bb54598 redesigned UI progress display 2020-05-08 20:28:46 -04:00
k4yt3x
f2943802cb upgraded input QLineEdit to QTableView 2020-05-08 17:37:16 -04:00
k4yt3x
d12f2a3888 deleted blank lines 2020-05-08 17:32:36 -04:00
k4yt3x
871d6386a8 added file drag and drop to GUI 2020-05-07 21:11:33 -04:00
k4yt3x
589a68caf7 removed some obsolete items from gitignore 2020-05-07 19:59:04 -04:00
k4yt3x
afacc48e1e added qtcreator project file 2020-05-07 19:58:51 -04:00
k4yt3x
4a3553607b deleted some empty lines with indentations in the project 2020-05-07 19:55:33 -04:00
k4yt3x
988600a769 fixed checkbox return value type error 2020-05-07 19:50:40 -04:00
k4yt3x
36aa3bf1d4 GUI resolve driver paths into absolute paths 2020-05-07 16:31:05 -04:00
k4yt3x
9dde3c66f1 build script 1.0.1: building into directory with name of version 2020-05-07 16:30:36 -04:00
k4yt3x
e9c1c22788 better exception handling, soft task interruption, GUI stop button, GUI folder processing, better argument checks 2020-05-07 15:58:22 -04:00
k4yt3x
134e8b7080 uncommented some keys unmanaged by v2x 2020-05-07 10:03:42 -04:00
k4yt3x
a295b4a54f finished adding comments for all drivers 2020-05-07 09:58:25 -04:00
k4yt3x
c198082190 updated new Anime4KCPP parameters 2020-05-07 09:38:13 -04:00
k4yt3x
8f2dc43af3 updated UI for newest Anime4KCPP 2020-05-07 09:33:37 -04:00
k4yt3x
b0ce8f3ff9 added environment variable expansion support, updated for newest Anime4KCPP 2020-05-07 09:33:12 -04:00
k4yt3x
0b1f7b8422 replaced absolute paths with environment variables, updated for newest Anime4KCPP 2020-05-07 09:32:51 -04:00
k4yt3x
def20650e2 added environment variable expansion support 2020-05-07 09:32:15 -04:00
k4yt3x
7489376404 fixed srmd-ncnn-vulkan path not added issue in the setup script 2020-05-07 09:02:42 -04:00
k4yt3x
826279ce09 fixing image captions 2020-05-06 20:48:19 -04:00
k4yt3x
88d2cd9e14 updated README screenshots and added image captions 2020-05-06 20:40:35 -04:00
k4yt3x
31728ff625 added PowerShell automatic build script 2020-05-06 20:20:51 -04:00
k4yt3x
3168737fd4 added time elapsed, time remaining and speed rate 2020-05-06 20:20:38 -04:00
k4yt3x
5fbc195740 unified config path case 2020-05-06 20:19:49 -04:00
K4YT3X
40d0d79141 added a patreon badge 2020-05-06 20:03:49 +00:00
k4yt3x
37a0966bad added binary path loading and error dialog system 2020-05-06 15:36:55 -04:00
k4yt3x
baf4c5815f added pyqt5 into requirements 2020-05-06 14:30:59 -04:00
k4yt3x
d25a478e64 added automatic constraint update upon driver selection 2020-05-06 14:27:21 -04:00
K4YT3X
ba723c6216 enable sponsorships 2020-05-06 17:46:35 +00:00
k4yt3x
11ea8a7a21 added config descriptions for some drivers 2020-05-06 13:24:32 -04:00
k4yt3x
3bce37416b GUI 2.0 design and basic functionalities finished 2020-05-06 13:24:10 -04:00
k4yt3x
e3cfe13b5c fixed some bugs in GUI 2020-05-06 11:01:14 -04:00
k4yt3x
81d8ce78cb updated default values 2020-05-06 10:40:04 -04:00
k4yt3x
89fa91c8c5 updated GUI UI file for new settings 2020-05-06 10:39:47 -04:00
k4yt3x
c8dbb90f5b added waifu2x-caffe and waifu2x-converter-cpp settings to GUI 2020-05-06 10:39:34 -04:00
k4yt3x
685120011b added Waifu2x-Extension-GUI into the related projects section 2020-05-06 04:57:43 -04:00
k4yt3x
82da40327b updated Video2X GUI screenshot 2020-05-06 04:48:04 -04:00
k4yt3x
9b4fb3258a video2x GUI 2.0.0: completely redesigned and rewritten with PyQt5 2020-05-06 04:45:48 -04:00
k4yt3x
f00a10aa91 added image files and project files 2020-05-06 04:44:36 -04:00
k4yt3x
93e8f36ffb fixed a typo 2020-05-06 00:12:49 -04:00
k4yt3x
f10e59099c deprecated JSON config file 2020-05-06 00:12:31 -04:00
k4yt3x
82715ade18 addressed srmd-ncnn-vulkan and waifu2x-ncnn-vulkan model path issues 2020-05-05 02:49:10 -04:00
K4YT3X
63de63e594 added master branch version badge 2020-05-05 06:29:03 +00:00
K4YT3X
8daeb862a4 updated README terminal screenshot 2020-05-05 06:26:39 +00:00
k4yt3x
be0d1f1d08 added some badges 2020-05-05 02:22:37 -04:00
k4yt3x
ec1327b5d8 updated README for version 4.0.0 2020-05-05 01:51:24 -04:00
k4yt3x
5b3e5604cc fixed srmd-ncnn-vulkan binary path issue 2020-05-05 01:12:12 -04:00
k4yt3x
a2fc71d6c5 fixed Anime4KCPP upscaling bug 2020-05-05 01:11:50 -04:00
k4yt3x
ab684bcd48 updated default Anime4KCPP path 2020-05-05 01:11:37 -04:00
k4yt3x
d26b406813 setup script 1.8.0: added Anime4KCPP setup support 2020-05-05 01:11:26 -04:00
k4yt3x
133b837b15 added language zh_CN 2020-05-04 20:25:43 -04:00
k4yt3x
9aebc77883 removing default values for model directories for multi-platform support 2020-05-04 20:25:32 -04:00
k4yt3x
b8472f155a added internationalization support 2020-05-04 20:25:12 -04:00
k4yt3x
19e6d241d5 fixing driver argument TypeError 2020-05-04 17:19:48 -04:00
k4yt3x
89860f22cb 4.0.0 new argument parsing mechanism and project structure 2020-05-04 17:12:41 -04:00
k4yt3x
88299d404a removed anime4k support and added Anime4KCPP support; cleaned up the program 2020-05-03 19:20:23 -04:00
k4yt3x
0f1639ed62 adding Anime4KCPP support 2020-05-03 19:19:19 -04:00
k4yt3x
3b6462d1da removing support for Anime4K (Java) 2020-05-03 19:19:00 -04:00
k4yt3x
43a2078330 moving wrappers into a sub-directory 2020-05-03 19:18:39 -04:00
k4yt3x
b1e844dcad updated README for setup script 1.7.0 2020-04-26 20:12:42 -04:00
k4yt3x
becce32d3e setup script 1.7.0: added support for srmd-ncnn-vulkan 2020-04-26 20:12:06 -04:00
k4yt3x
d2ddf32527 updated README for 3.2.0 2020-04-26 20:04:37 -04:00
k4yt3x
7224c53997 3.2.0 added SRMD NCNN Vulkan support 2020-04-26 20:01:37 -04:00
k4yt3x
2ed9bd4da6 updated configuration files for SRMD NCNN Vulkan 2020-04-26 20:00:01 -04:00
k4yt3x
38c52cdfd2 updated JSON config file to match YAML 2020-04-26 19:40:21 -04:00
k4yt3x
80579d3fa9 updated absolutify paths function 2020-04-26 13:40:22 -04:00
k4yt3x
47f94dfd6c updated Anime4K ZIP file download URL 2020-04-24 00:22:39 -04:00
k4yt3x
c470dde5da fixing issue #220 2020-04-04 06:24:40 -04:00
k4yt3x
c532ac3c88 updated file modification dates and editor information 2020-03-23 09:05:24 -04:00
K4YT3X
f50ceecd62 Merge pull request #214 from 28598519a/master
Fix k4yt3x#211 bug
2020-03-23 08:55:16 -04:00
劃破黑夜
2ba0e951f9 Fix k4yt3x#211 bug 2020-03-17 22:01:56 +08:00
k4yt3x
5753ea8f52 updated readme for version 3.1.0 2020-02-26 22:31:51 -05:00
k4yt3x
09db8bedd0 3.1.0 switched to multi-processing and added KeyboardInterrupt support 2020-02-26 05:28:48 -05:00
k4yt3x
6a100b1526 removed multi-threading in favor of muti-processing 2020-02-26 05:27:57 -05:00
k4yt3x
a2150a8dbc fixing progress bar error due to string case mismatch 2020-02-22 02:31:39 -05:00
k4yt3x
78ded08ed5 changed default number of threads to 1 2020-02-21 23:16:22 -05:00
k4yt3x
5db2cfd2a3 added anime4k instructions 2020-01-12 03:32:25 -05:00
k4yt3x
652b9f34bd fixing #180 bug2 attempt 2 2020-01-04 17:03:16 -05:00
k4yt3x
f3c50ea728 fixing #180 bug2 2020-01-04 16:59:51 -05:00
k4yt3x
880087241d updated waifu2x-ncnn-vulkan path key for new config structure 2020-01-04 16:56:08 -05:00
k4yt3x
067e17290a 1.6.1 changed driver paths to 3.0.0 config style 2020-01-04 16:49:13 -05:00
k4yt3x
fc675e7899 updated copyright date 2020-01-04 16:48:37 -05:00
K4YT3X
2d81270e44 Set theme jekyll-theme-slate 2019-12-22 06:00:02 +00:00
K4YT3X
3ace2447c2 Create CNAME 2019-12-22 05:48:39 +00:00
K4YT3X
30b0e2c7bf Delete CNAME 2019-12-22 05:48:25 +00:00
k4yt3x
d54fea0310 enables available memory warning for Linux platform 2019-12-19 23:03:58 -05:00
k4yt3x
332055a4e5 fixed temp directory cleaning problem on exit 2019-12-11 22:20:01 -05:00
k4yt3x
19e17b1a8f updated platform information 2019-12-11 21:59:38 -05:00
k4yt3x
9e745fb747 video2x_gui 1.1.3: fixed driver path key name 2019-12-11 21:59:20 -05:00
K4YT3X
fd5edead7e Merge pull request #171 from YOUSIKI/master
Check platform correctly
2019-11-30 19:56:08 +00:00
YOUSIKI
aa7c0b3f12 Check platform correctly
Continue if running on win32.
Exit if running on other platforms.
2019-11-30 22:56:34 +08:00
k4yt3x
65cc4c6afb Merge branch '3.0.0' 2019-11-26 04:14:13 -05:00
k4yt3x
bd2da021bd updated README for 3.0.0 2019-11-26 04:12:04 -05:00
k4yt3x
7e888db7b2 formatted YAML file 2019-11-26 04:10:01 -05:00
k4yt3x
7726a86e35 added platform check, made PermissionError more obvious 2019-11-26 04:03:03 -05:00
K4YT3X
a0595136ab Create CNAME 2019-11-18 06:43:00 +00:00
K4YT3X
5c93a5a73b Delete CNAME 2019-11-18 06:42:54 +00:00
K4YT3X
7b9b87fa9b Create CNAME 2019-11-17 05:41:13 +00:00
k4yt3x
cb255da65c added missing sys library import 2019-11-16 02:54:25 -05:00
k4yt3x
d503325a62 changed YAML load to FullLoader to make it WIndows-compatible 2019-11-16 02:52:33 -05:00
k4yt3x
954233c238 changed default config path from JSON to YAML 2019-11-16 01:51:01 -05:00
k4yt3x
95416f68a8 make the GUI script YAML-compatible 2019-11-16 01:50:41 -05:00
k4yt3x
dce778b3bf 1.1.2 fixed repeated output file extensions 2019-11-15 22:40:48 -05:00
k4yt3x
c537dd726c changed YAML loader to Windows compatible FullLoader 2019-11-15 22:40:19 -05:00
k4yt3x
b1918a4a8a fixed pixel_formats print bug and subprocess execution bug 2019-11-15 02:39:27 -05:00
k4yt3x
7ae9618785 updated file modification date 2019-11-15 02:38:39 -05:00
k4yt3x
eb3d29103c fixed anime4k path key 2019-11-15 02:38:11 -05:00
k4yt3x
a188f6ebda 1.6.0 added support for YAML, better exception handling 2019-11-15 02:04:12 -05:00
k4yt3x
fd67dfca11 docstring modifications, added JDK warning 2019-11-15 02:03:44 -05:00
k4yt3x
b1f29f1098 fixed NCNN Vulkan driver argument error 2019-11-15 01:09:55 -05:00
k4yt3x
fe7c0c840d fixed type error for waifu2x-ncnn-vulkan argument 2019-10-24 21:33:05 -04:00
k4yt3x
dc2410d4da renaming variables, using YAML to replace JSON 2019-10-19 21:53:12 -04:00
k4yt3x
91ac512d57 remove .exe extension for Linux compatibility 2019-10-19 21:52:31 -04:00
k4yt3x
732288f075 renamed waifu2x_settings to driver_settings 2019-10-19 21:52:11 -04:00
k4yt3x
e812c228c3 updated file permissions 2019-10-19 21:51:18 -04:00
k4yt3x
9841fa9577 converted JSON config into YAML 2019-10-19 21:45:44 -04:00
k4yt3x
5391f59847 renamed bin to src since python isn't binary 2019-10-19 21:40:00 -04:00
k4yt3x
6180ccd9b2 fixing folder upscaling function 2019-08-29 16:03:15 -04:00
k4yt3x
e10315f89e using contextlib instead of try-catch 2019-08-25 23:03:37 -04:00
k4yt3x
6521e071ce enhanced logo-printing 2019-08-25 23:03:18 -04:00
k4yt3x
a685e91b14 removed unused dependencies 2019-08-25 23:02:59 -04:00
k4yt3x
9d72bad314 temporary fix for Anime4K download 2019-08-20 22:40:26 -04:00
k4yt3x
2b63b5f0a6 added total time display 2019-08-17 23:28:37 -04:00
k4yt3x
9c84228c17 added screenshot for video2x gui 2019-08-17 23:19:47 -04:00
k4yt3x
f9bb191336 fixed gui compatibility with anime4k, added constraints for a4k 2019-08-17 18:16:47 -04:00
K4YT3X
7a3af366f8 Merge pull request #137 from k4yt3x/2.10.0-anime4k
2.10.0 anime4k
2019-08-16 15:49:33 +00:00
k4yt3x
d4223f93ec fixed a4k not installed bug 2019-08-16 02:53:07 -04:00
k4yt3x
c5c764a91f GUI 1.1.1: Added support for Anime4K 2019-08-16 02:49:38 -04:00
k4yt3x
ba6472c9fc exe build is out of beta 2019-08-16 02:49:22 -04:00
k4yt3x
dc1244580f updated README for 2.10.0 2019-08-16 00:46:43 -04:00
k4yt3x
0347d05127 setup script 1.5.0: added support for Anime4K 2019-08-16 00:36:45 -04:00
k4yt3x
45f5bf91e6 updated anime4k path 2019-08-16 00:36:22 -04:00
k4yt3x
5e78beabcf added thread dialog for anime4k 2019-08-16 00:19:36 -04:00
k4yt3x
6c5b7ea17f moved constants into one single place 2019-08-15 23:57:24 -04:00
k4yt3x
d9610abae0 fixed thread-unsafe printing 2019-08-15 23:56:55 -04:00
k4yt3x
47471352ba 2.10.0 added anime4k support 2019-08-15 23:34:24 -04:00
k4yt3x
969cfe5c0d fixing issue #134 2019-08-11 23:57:10 -04:00
k4yt3x
e12db41213 updated bug report template for newest version of v2x 2019-08-07 23:07:55 -04:00
k4yt3x
7a69d58e28 placed version number into window title 2019-08-07 22:56:41 -04:00
k4yt3x
ad6308d385 relocated docstrings 2019-08-07 22:54:39 -04:00
k4yt3x
8c3a85ac42 GUI 1.1.0 added basic menu bar and better output file naming check 2019-08-07 22:54:33 -04:00
k4yt3x
db603062e9 updated main file date 2019-08-03 23:15:36 -04:00
k4yt3x
807276fcc3 fixing converter frame filename issues 2019-08-03 23:15:19 -04:00
k4yt3x
9be46f7d62 fixing support for waifu2x_ncnn_vulkan 2019-08-03 23:15:03 -04:00
k4yt3x
f42a8ab71f fixed waifu2x-ncnn-vulkan argument errors 2019-08-03 21:29:13 -04:00
k4yt3x
e3b2624977 fixed the issue where subprocess tries to execute pathlib.Path 2019-08-03 19:45:22 -04:00
k4yt3x
685d894bef Merge remote-tracking branch 'origin/master' 2019-07-30 01:28:43 -04:00
k4yt3x
b0167e9f08 Setup Script 1.4.0: fixed ncnn setup error, fixed JSON error 2019-07-30 01:28:29 -04:00
K4YT3X
74767743bd Merge pull request #130 from k4yt3x/video2x_gui
added alpha version of video2x gui
2019-07-30 05:12:08 +00:00
k4yt3x
ece345e531 added alpha version of video2x gui 2019-07-28 03:09:40 -04:00
k4yt3x
47e787c80c added more exceptions for better error handling 2019-07-27 17:52:31 -04:00
k4yt3x
4639555626 added a missing new line 2019-07-27 17:52:18 -04:00
k4yt3x
d423fa1b6e updated code contributors list 2019-07-27 17:38:52 -04:00
K4YT3X
734cf7bb0e Merge pull request #129 from k4yt3x/2.9.0
2.9.0
2019-07-27 21:34:35 +00:00
k4yt3x
77ad212b01 updated README for 2.9.0 2019-07-27 17:33:35 -04:00
k4yt3x
a27bdb4b63 changed file handling method from os to pathlib 2019-07-27 17:29:33 -04:00
k4yt3x
89dfd21f97 removed f_string support for legacy versions of Python 2019-07-27 13:39:40 -04:00
k4yt3x
5151be4122 fixing issue #94 2019-07-26 14:22:49 -04:00
K4YT3X
f8d3fa5c25 Merge pull request #122 from sat3ll/waifu2x_vk_update
update waifu2x_ncnn_vulkan wrapper
2019-07-13 05:07:47 +00:00
sat3ll
61abcc6a3a When batch upscaling (new behavior), for sub 8G VRAM gpus, the recommended value is 200. 2019-07-13 01:08:31 +01:00
sat3ll
40a4d3a602 update waifu2x_ncnn_vulkan wrapper for directory as input
add workaround for the double file extension
2019-07-12 23:12:08 +01:00
K4YT3X
9429b04528 Merge pull request #121 from sat3ll/w2x-vulkan-update
update waifu2x_ncnn_vulkan to new options
2019-07-10 02:51:15 +00:00
k4yt3x
55c2f7abfb extracting frames into rgba64be format 2019-07-09 22:48:29 -04:00
k4yt3x
c7c83d35ed updated README for 2.8.1 2019-07-09 20:48:54 -04:00
k4yt3x
ca90c5be02 2.8.1 added automatic pixel format and color depth detection 2019-07-09 20:47:55 -04:00
sat3ll
5a2b387b9d deduplicate code 2019-07-10 01:36:26 +01:00
sat3ll
eda5d70773 update waifu2x_ncnn_vulkan to new options 2019-07-10 01:30:50 +01:00
k4yt3x
8b845e35b3 matching JSON indentation 2019-06-29 13:49:34 -04:00
k4yt3x
e3b7110ff5 added vulkan reference link 2019-06-25 23:59:51 -04:00
k4yt3x
cefa2c4f30 updated README for 2.8.0 2019-06-25 23:48:41 -04:00
k4yt3x
4d9c0866ce 2.8.0 added support for waifu2x-ncnn-vulkan 2019-06-25 23:48:22 -04:00
K4YT3X
25fca78eb4 Merge pull request #112 from sat3ll/waifu2x-ncnn-vk
Add support for waifu2x-ncnn-vulkan engine
2019-06-26 03:40:34 +00:00
k4yt3x
4a0ffae6c8 updated key order for w2x ncnn 2019-06-25 23:39:53 -04:00
k4yt3x
f94f99eb1c sorted imports, updated dates 2019-06-25 23:36:03 -04:00
k4yt3x
a9586bf508 updated version to 1.3.0, using shutil.rmtree instead of os.rmdir 2019-06-25 23:35:42 -04:00
k4yt3x
5f69a44bf7 changed some wording 2019-06-25 23:35:17 -04:00
k4yt3x
1ee76c0224 removed redundant code block 2019-06-25 23:34:57 -04:00
sat3ll
0b99ac33a6 change waifu2x-ncnn-vulkan to underscores
agglomerate waifu2x choices to a list
2019-06-26 00:50:29 +01:00
sat3ll
4e3565b3ac Add support for waifu2x-ncnn-vulkan engine 2019-06-26 00:25:27 +01:00
K4YT3X
b40aee0cd7 Merge pull request #107 from BrianPetkovsek/Fix-encoding-problem
Fixed encoding problem
2019-06-18 14:28:20 +00:00
Brian Petkovsek
5b27cf26e1 Merge pull request #3 from BrianPetkovsek/master
remove uninstall not needed
2019-06-17 22:38:50 -04:00
BrianPetkovsek
8fe6fd4009 Fix encoding problem 2019-06-17 22:37:04 -04:00
BrianPetkovsek
d4d485e132 Revert "Added uninstall function to setup"
This reverts commit d25857a178.
2019-06-17 22:34:45 -04:00
BrianPetkovsek
53f5192896 Revert "Fix encoding problem"
This reverts commit 81af7b1c1b.
2019-06-17 22:33:27 -04:00
Brian Petkovsek
e6d865a80d Merge pull request #2 from BrianPetkovsek/master
Added uninstall function to setup
2019-06-17 12:06:43 -04:00
BrianPetkovsek
d25857a178 Added uninstall function to setup 2019-06-17 12:05:06 -04:00
BrianPetkovsek
81af7b1c1b Fix encoding problem 2019-06-16 17:32:41 -04:00
K4YT3X
81b8e45b6f Merge pull request #104 from BrianPetkovsek/master
make video2x backwards compatible
2019-06-15 14:44:32 -04:00
K4YT3X
e003cbc568 Merge branch 'master' into master 2019-06-15 14:42:56 -04:00
k4yt3x
f96b95563e code style adjustments 2019-06-15 14:35:22 -04:00
K4YT3X
76144b589a Merge pull request #103 from sat3ll/wip_1
use os.path.join
2019-06-15 14:26:28 -04:00
sat3ll
15d2dbb07a use os.path.join 2019-06-15 12:32:36 +01:00
BrianPetkovsek
9d5ad2f70c make video2x backwards compatible
adds future-fstrings package
transforms the source to .format() format on runtime
2019-06-14 21:43:18 -04:00
BrianPetkovsek
b5da9ebbf7 make setup backwards compatible
change the f'' to ''.format()
2019-06-14 21:37:38 -04:00
BrianPetkovsek
a1e1d98929 Make pip_install function more flexible
sys.executable gets the python.exe used to run the script
-r allows pip to use requirements.txt
2019-06-14 21:11:31 -04:00
BrianPetkovsek
fafd5fadd3 Merge remote-tracking branch 'upstream/master' 2019-06-14 20:54:04 -04:00
k4yt3x
1280a791ec fixing issue #102 2019-06-14 01:15:13 -04:00
k4yt3x
8e85d6a6d3 fixed threading bugs found by @Aidolii 2019-06-13 23:49:18 -04:00
k4yt3x
8b0f82e95e 2.7.2 fixed threading bugs found by @Aidolii 2019-06-13 23:49:10 -04:00
k4yt3x
a6666c3c3b added version option 2019-06-13 23:42:43 -04:00
BrianPetkovsek
585164a508 Merge remote-tracking branch 'upstream/master' 2019-06-12 18:06:08 -04:00
k4yt3x
6b3e1b9768 fixing video to frames ffmpeg config parsing order error 2019-06-09 21:31:13 -04:00
k4yt3x
0f4daa12d2 fixing a bug found by @CardinalPanda 2019-06-05 12:18:51 -04:00
k4yt3x
4cf83dc565 fixing progress bar bug found by @CardinalPanda 2019-05-25 23:20:31 -04:00
k4yt3x
146044505b fixed issue #77 incorrect output video format 2019-05-06 16:25:10 -04:00
k4yt3x
a7d41cafdf changed default number of threads to 1 2019-04-30 03:53:40 -04:00
k4yt3x
875572c75a corrected repo links and step by step instruction description 2019-04-29 00:11:30 -04:00
k4yt3x
c7353c4bf2 unified all "folder/directory" into "directory" to end this mess 2019-04-29 00:06:54 -04:00
k4yt3x
0af68bb39c added description for Q&A page 2019-04-29 00:05:56 -04:00
k4yt3x
19cb823591 all string formatting switched to f-string 2019-04-22 01:26:36 -04:00
k4yt3x
6c1a714a1e updated README for 2.7.1 2019-04-18 14:57:30 -04:00
k4yt3x
837aca371e fixed temp folders bug 2019-04-18 14:56:30 -04:00
k4yt3x
6538abd6e5 corrected a typo 2019-04-11 14:56:51 -04:00
k4yt3x
a57465e866 added input and output file type mismatch check 2019-04-11 14:53:46 -04:00
k4yt3x
405c4b6636 fixed error reading video resolution 2019-04-02 16:23:59 -04:00
k4yt3x
3d46e1a822 changed default crf value to visually lossless, added video bitrate limit option 2019-04-01 16:02:26 -04:00
k4yt3x
7b501f2c67 added video2x builds information 2019-03-31 03:58:09 -04:00
k4yt3x
98e2cbdb04 1.2.1 added support for exe packaging 2019-03-31 03:46:15 -04:00
k4yt3x
25156077f2 added function to absolutify paths set in config file for better exe support 2019-03-31 03:23:08 -04:00
Brian Petkovsek
b984977227 Merge pull request #1 from K4YT3X/master
Pull latest updates
2019-03-25 02:14:50 -04:00
47 changed files with 5371 additions and 1668 deletions

12
.github/FUNDING.yml vendored Normal file
View File

@@ -0,0 +1,12 @@
# These are supported funding model platforms
github: k4yt3x
patreon: k4yt3x
open_collective: # Replace with a single Open Collective username
ko_fi: # Replace with a single Ko-fi username
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username
otechie: # Replace with a single Otechie username
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']

View File

@@ -1,31 +0,0 @@
---
name: Bug report
about: Use this template if you believe you've encountered a bug.
title: ''
labels: bug
assignees: K4YT3X
---
## Environment Information
|Module|Version|
|-|-|
|`video2x`||
|`ffmpeg`||
|`waifu2x-caffe`||
|`waifu2x-converter-cpp`||
## Symptom
Briefly describe what's going on.
## Screenshots or Error Messages
Please paste screenshots or error messages here.
Include as much details as you can, as this greatly helps debugging the problem.
Please paste your error message in the code block down below:
```
```

View File

@@ -1,16 +0,0 @@
---
name: Feature request
about: Request a new feature to be added
title: ''
labels: enhancement
assignees: K4YT3X
---
## Description
Briefly describe the feature you want to be added into `video2x`.
## Sources
Paste links to descriptions of related documentations, websites and etc. here.

41
.github/workflows/ci.yml vendored Normal file
View File

@@ -0,0 +1,41 @@
name: CI
on:
push:
branches:
- master
- dev/*
pull_request: {}
workflow_dispatch: {}
jobs:
ubuntu:
runs-on: ubuntu-latest
env:
DEBIAN_FRONTEND: noninteractive
steps:
- name: Checkout repository
uses: actions/checkout@v2
with:
submodules: recursive
- name: Setup Python
uses: actions/setup-python@v2
with:
python-version: 3.8
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y --no-install-recommends \
python3-opencv python3-pil python3-tqdm python3-dev \
libvulkan-dev glslang-dev glslang-tools swig
pip install wheel
- name: Build wheels
run: |
pip wheel -w /tmp/wheels \
rife-ncnn-vulkan-python@git+https://github.com/media2x/rife-ncnn-vulkan-python.git .
- name: Package artifacts
run: |
tar cJvf /tmp/video2x-nightly-wheels.txz /tmp/wheels/*
- name: Upload artifacts
uses: actions/upload-artifact@v2
with:
name: video2x-nightly-wheels
path: /tmp/video2x-nightly-wheels.txz

78
.github/workflows/release.yml vendored Normal file
View File

@@ -0,0 +1,78 @@
name: Release
on:
push:
tags:
- "*"
jobs:
setup:
if: github.event.base_ref == 'refs/heads/master'
name: Setup
runs-on: ubuntu-latest
outputs:
tag: ${{ steps.get_tag.outputs.tag }}
steps:
- name: Get tag
id: get_tag
run: echo ::set-output name=tag::${GITHUB_REF/refs\/tags\//}
create-release:
name: Create release
needs:
- setup
runs-on: ubuntu-latest
outputs:
upload_url: ${{ steps.create_release.outputs.upload_url }}
steps:
- name: Create release
id: create_release
uses: actions/create-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ needs.setup.outputs.tag }}
release_name: Video2X ${{ needs.setup.outputs.tag }}
draft: true
prerelease: false
container:
name: Build and upload container
needs:
- setup
- create-release
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v2
- uses: mr-smithers-excellent/docker-build-push@v5
name: Build & push the Docker image
with:
registry: ghcr.io
username: ${{ secrets.GHCR_USER }}
password: ${{ secrets.GHCR_TOKEN }}
dockerfile: Dockerfile
image: video2x
tags: latest, ${{ needs.setup.outputs.tag }}
container-variants:
name: Build and upload variants of the container
needs:
- setup
- create-release
strategy:
matrix:
version:
- slim-alpine
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v2
- uses: mr-smithers-excellent/docker-build-push@v5
name: Build & push the Docker image
with:
registry: ghcr.io
username: ${{ secrets.GHCR_USER }}
password: ${{ secrets.GHCR_TOKEN }}
dockerfile: Dockerfile.${{ matrix.version }}
image: video2x
tags: ${{ needs.setup.outputs.tag }}-${{ matrix.version }}

26
.gitignore vendored
View File

@@ -1,11 +1,17 @@
# Runtime files
upscaled/
frames/
waifu2x-caffe/
testvid.mp4
# PDM
.pdm.toml
__pypackages__/
# PyCharm
.idea/
# test videos
*.mp4
*.mkv
*.mov
*.avi
*.flv
*.webm
# vim session file
Session.vim
# Byte-compiled / optimized / DLL files
__pycache__/
@@ -57,8 +63,8 @@ coverage.xml
.pytest_cache/
# Translations
*.mo
*.pot
#*.mo
#*.pot
# Django stuff:
*.log
@@ -110,4 +116,4 @@ venv.bak/
/site
# mypy
.mypy_cache/
.mypy_cache/

42
Dockerfile Normal file
View File

@@ -0,0 +1,42 @@
# Name: Video2X Dockerfile
# Creator: K4YT3X
# Date Created: February 3, 2022
# Last Modified: March 28, 2022
# stage 1: build the python components into wheels
FROM docker.io/nvidia/vulkan:1.2.133-450 AS builder
ENV DEBIAN_FRONTEND=noninteractive
COPY . /video2x
WORKDIR /video2x
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
python3.8 python3-pip python3-opencv python3-pil \
python3.8-dev libvulkan-dev glslang-dev glslang-tools \
build-essential swig \
&& pip wheel -w /wheels wheel pdm-pep517 .
# stage 2: install wheels into the final image
FROM docker.io/nvidia/vulkan:1.2.133-450
LABEL maintainer="K4YT3X <i@k4yt3x.com>" \
org.opencontainers.image.source="https://github.com/k4yt3x/video2x" \
org.opencontainers.image.description="A lossless video/GIF/image upscaler"
ENV DEBIAN_FRONTEND=noninteractive
ENV VK_ICD_FILENAMES=/usr/share/vulkan/icd.d/nvidia_icd.json\
:/usr/share/vulkan/icd.d/radeon_icd.x86_64.json\
:/usr/share/vulkan/icd.d/intel_icd.x86_64.json
COPY --from=builder /var/lib/apt/lists* /var/lib/apt/lists/
COPY --from=builder /wheels /wheels
COPY . /video2x
WORKDIR /video2x
RUN apt-get install -y --no-install-recommends \
python3-pip python3.8-dev \
python3-opencv python3-pil \
mesa-vulkan-drivers cuda-drivers ffmpeg \
&& pip install --no-cache-dir --no-index -f /wheels . \
&& apt-get clean \
&& rm -rf /wheels /video2x /var/lib/apt/lists/*
WORKDIR /host
ENTRYPOINT ["/usr/bin/python3.8", "-m", "video2x"]

34
Dockerfile.slim-alpine Normal file
View File

@@ -0,0 +1,34 @@
# Name: Video2X Dockerfile (Slim Alpine)
# Creator: K4YT3X
# Date Created: February 1, 2022
# Last Modified: March 18, 2022
# stage: build python components into heels
FROM docker.io/library/python:3.10.4-alpine3.15 AS builder
COPY . /video2x
WORKDIR /video2x
RUN apk add --no-cache \
cmake g++ gcc git ninja swig linux-headers \
ffmpeg-dev glslang-dev jpeg-dev vulkan-loader-dev zlib-dev \
&& pip install -U pip \
&& CMAKE_ARGS="-DWITH_FFMPEG=YES" pip wheel -w /wheels opencv-python \
&& pip wheel -w /wheels wheel pdm-pep517 .
# stage 2: install wheels into final image
FROM docker.io/library/python:3.10.4-alpine3.15
LABEL maintainer="K4YT3X <i@k4yt3x.com>" \
org.opencontainers.image.source="https://github.com/k4yt3x/video2x" \
org.opencontainers.image.description="A lossless video/GIF/image upscaler"
COPY --from=builder /wheels /wheels
COPY . /video2x
WORKDIR /video2x
RUN apk add --no-cache --virtual .run-deps \
ffmpeg libgomp libjpeg-turbo libstdc++ \
vulkan-loader mesa-vulkan-ati \
&& pip install --no-cache-dir -U pip \
&& pip install --no-cache-dir --no-index -f /wheels . \
&& rm -rf /wheels /video2x
WORKDIR /host
ENTRYPOINT ["/usr/local/bin/python", "-m", "video2x"]

147
LICENSE
View File

@@ -1,23 +1,21 @@
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
GNU AFFERO GENERAL PUBLIC LICENSE
Version 3, 19 November 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The GNU Affero General Public License is a free, copyleft license for
software and other kinds of works, specifically designed to ensure
cooperation with the community in the case of network server software.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
our General Public Licenses are intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too.
software for all its users.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
@@ -26,44 +24,34 @@ them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
Developers that use our General Public Licenses protect your rights
with two steps: (1) assert copyright on the software, and (2) offer
you this License which gives you legal permission to copy, distribute
and/or modify the software.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
A secondary benefit of defending all users' freedom is that
improvements made in alternate versions of the program, if they
receive widespread use, become available for other developers to
incorporate. Many developers of free software are heartened and
encouraged by the resulting cooperation. However, in the case of
software used on network servers, this result may fail to come about.
The GNU General Public License permits making a modified version and
letting the public access it on a server without ever releasing its
source code to the public.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
The GNU Affero General Public License is designed specifically to
ensure that, in such cases, the modified source code becomes available
to the community. It requires the operator of a network server to
provide the source code of the modified version running there to the
users of that server. Therefore, public use of a modified version, on
a publicly accessible server, gives the public access to the source
code of the modified version.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
An older license, called the Affero General Public License and
published by Affero, was designed to accomplish similar goals. This is
a different license, not a version of the Affero GPL, but Affero has
released a new version of the Affero GPL which permits relicensing under
this license.
The precise terms and conditions for copying, distribution and
modification follow.
@@ -72,7 +60,7 @@ modification follow.
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"This License" refers to version 3 of the GNU Affero General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
@@ -549,35 +537,45 @@ to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
13. Remote Network Interaction; Use with the GNU General Public License.
Notwithstanding any other provision of this License, if you modify the
Program, your modified version must prominently offer all users
interacting with it remotely through a computer network (if your version
supports such interaction) an opportunity to receive the Corresponding
Source of your version by providing access to the Corresponding Source
from a network server at no charge, through some standard or customary
means of facilitating copying of software. This Corresponding Source
shall include the Corresponding Source for any work covered by version 3
of the GNU General Public License that is incorporated pursuant to the
following paragraph.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
under version 3 of the GNU General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
but the work with which it is combined will remain governed by version
3 of the GNU General Public License.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
the GNU Affero General Public License from time to time. Such new versions
will be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU General
Program specifies that a certain numbered version of the GNU Affero General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
GNU Affero General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
versions of the GNU Affero General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
@@ -635,40 +633,29 @@ the "copyright" line and a pointer to where the full notice is found.
Copyright (C) <year> <name of author>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
GNU Affero General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
<program> Copyright (C) <year> <name of author>
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".
If your software can interact with users remotely through a computer
network, you should also make sure that it provides a way for users to
get its source. For example, if your program is a web application, its
interface could display a "Source" link that leads users to an archive
of the code. There are many ways you could offer source, and different
solutions will be better for different programs; see section 13 for the
specific requirements.
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<http://www.gnu.org/licenses/>.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
For more information on this, and how to apply and follow the GNU AGPL, see
<https://www.gnu.org/licenses/>.

43
NOTICE Normal file
View File

@@ -0,0 +1,43 @@
Video2X
Copyright (c) 2018-2022 K4YT3X and contributors.
This product depends on FFmpeg, which is available under
the GNU Lesser General Public License 2.1. The source code can be found at
https://www.gnu.org/licenses/agpl-3.0.txt.
This product depends on waifu2x-ncnn-vulkan, which is available under
the MIT License. The source code can be found at
https://github.com/nihui/waifu2x-ncnn-vulkan.
This product depends on srmd-ncnn-vulkan, which is available under
the MIT License. The source code can be found at
https://github.com/nihui/srmd-ncnn-vulkan.
This product depends on realsr-ncnn-vulkan, which is available under
the MIT License. The source code can be found at
https://github.com/nihui/realsr-ncnn-vulkan.
This product depends on rife-ncnn-vulkan, which is available under
the MIT License. The source code can be found at
https://github.com/nihui/rife-ncnn-vulkan.
This product depends on ffmpeg-python, which is available under
the Apache License Version 2.0. The source code can be found at
https://github.com/kkroening/ffmpeg-python.
This product depends on Loguru, which is available under
the MIT License. The source code can be found at
https://github.com/Delgan/loguru.
This product depends on opencv-python, which is available under
the MIT License. The source code can be found at
https://github.com/opencv/opencv-python.
This product depends on Pillow, which is available under
the Historical Permission Notice and Disclaimer. The source code
can be found at
https://github.com/python-pillow/Pillow.
This product depends on Rich, which is available under
the MIT License. The source code can be found at
https://github.com/Textualize/rich.

278
README.md
View File

@@ -1,224 +1,124 @@
# Video2X Lossless Video Enlarger
<p align="center">
<img src="https://user-images.githubusercontent.com/21986859/102733190-872a7880-4334-11eb-8e9e-0ca747f130b1.png"/>
</br>
<img src="https://img.shields.io/github/v/release/k4yt3x/video2x?style=flat-square"/>
<img src="https://img.shields.io/github/workflow/status/k4yt3x/video2x/CI?label=CI&style=flat-square"/>
<img src="https://img.shields.io/github/downloads/k4yt3x/video2x/total?style=flat-square"/>
<img src="https://img.shields.io/github/license/k4yt3x/video2x?style=flat-square"/>
<img src="https://img.shields.io/badge/dynamic/json?color=%23e85b46&label=Patreon&query=data.attributes.patron_count&suffix=%20patrons&url=https%3A%2F%2Fwww.patreon.com%2Fapi%2Fcampaigns%2F4507807&style=flat-square"/>
</p>
### Official Discussion Group (Telegram): https://t.me/video2x
## [💬 Telegram Discussion Group](https://t.me/video2x)
## Prerequisites
Join our Telegram discussion group to ask any questions you have about Video2X, chat directly with the developers, or discuss about upscaling technologies and the future of Video2X in general.
Component names that are **bolded** are mandatory.
## [🪟 Download Windows Releases](https://github.com/k4yt3x/video2x/releases/tag/4.8.1)
Component names that are *italicized* can be automatically downloaded and configured with the `video2x_setup.py` script.
The latest Windows update is built based on version 4.8.1. GUI is not available for 5.0.0 yet, but is already under development. Go to the [GUI](https://github.com/k4yt3x/video2x/wiki/GUI) page to see the basic usages of the GUI. Try the [mirror](https://files.k4yt3x.com/Projects/Video2X/latest) if you can't download releases directly from GitHub.
1. Operating System: Windows
1. AMD GPU / Nvidia GPU
1. AMD GPU driver / Nvidia GPU driver / Nvidia CUDNN
1. [***FFMPEG***](https://ffmpeg.zeranoe.com/builds/)
1. [***waifu2x-caffe***](https://github.com/lltcggie/waifu2x-caffe/releases) / [***waifu2x-converter-cpp***](https://github.com/DeadSix27/waifu2x-converter-cpp/releases)
## [📔 Google Colab](https://colab.research.google.com/drive/1gWEwcA9y57EsxwOjmLNmNMXPsafw0kGo)
## Recent Changes
You can use Video2X on [Google Colab](https://colab.research.google.com/) **for free** if you don't have a powerful GPU of your own. You can borrow a powerful GPU (Tesla K80, T4, P4, or P100) on Google's server for free for a maximum of 12 hours per session. **Please use the free resource fairly** and do not create sessions back-to-back and run upscaling 24/7. This might result in you getting banned. You can get [Colab Pro/Pro+](https://colab.research.google.com/signup/pricing) if you'd like to use better GPUs and get longer runtimes. Usage instructions are embedded in the [Colab Notebook](https://colab.research.google.com/drive/1gWEwcA9y57EsxwOjmLNmNMXPsafw0kGo).
### 2.7.0 (March 30, 2019)
## [🌙 Download Nightly Releases](https://github.com/k4yt3x/video2x/actions/workflows/ci.yml)
- Added support for different extracted image formats.
- Redesigned FFMPEG wrapper, FFMPEG settings are now customizable in the `video2x.json` config file.
- Other minor enhancements and adjustments (e.g. argument -> method variable)
Nightly releases are automatically created by the GitHub Actions CI/CD pipelines. They usually contain more experimental features and bug fixes. However, they are much less stable to the stable releases. **You must log in to GitHub to download CI build artifacts.**
### Setup Script 1.2.0 (March 26, 2019)
## [📦 Container Image](https://github.com/k4yt3x/video2x/pkgs/container/video2x)
- `video2x_setup.py` script can now automatically download and configure `waifu2x-converter-cpp`.
- replaced old progress indicator with progress bar.
Video2X container images are available on the GitHub Container Registry for easy deployment on Linux and macOS. If you already have Docker/Podman installed, only one command is needed to start upscaling a video. For more information on how to use Video2X's Docker image, please refer to the [documentations](https://github.com/K4YT3X/video2x/wiki/Container).
### 2.6.3 (March 24, 2019)
## [📖 Documentations](https://github.com/k4yt3x/video2x/wiki)
- Added image cleaner by @BrianPetkovsek which removes upscaled frames.
- Fixed some PEP8 issues.
- Exceptions in waifu2x are now caught, and script will now stop on waifu2x error instead of keep going on to FFMPEG.
Video2X's documentations are hosted on this repository's [Wiki page](https://github.com/k4yt3x/video2x/wiki). It includes comprehensive explanations for how to use the [GUI](https://github.com/k4yt3x/video2x/wiki/GUI), the [CLI](https://github.com/k4yt3x/video2x/wiki/CLI), the [container image](https://github.com/K4YT3X/video2x/wiki/Container), the [library](https://github.com/k4yt3x/video2x/wiki/Library), and more. The Wiki is open to edits by the community, so you, yes you, can also correct errors or add new contents to the documentations.
## Description
## Introduction
Video2X is an automation software based on waifu2x image enlarging engine. It extracts frames from a video, enlarge it by a number of times without losing any details or quality, keeping lines smooth and edges sharp.
Video2X is a video/GIF/image upscaling and frame interpolation software written in Python. It can use these following state-of-the-art algorithms to increase the resolution and frame rate of your video/GIF/image. More information about the algorithms that it supports can be found in [the documentations](https://github.com/k4yt3x/video2x/wiki/Algorithms).
For short: **Video2X enlarges your video without losing details**
### Video Upscaling
Watch for the sharper edges in this screenshot around the shadows:
![Spirited Away Demo](https://user-images.githubusercontent.com/21986859/49412428-65083280-f73a-11e8-8237-bb34158a545e.png)\
_Upscale demo: Spirited Away's movie trailer_
![preview](https://user-images.githubusercontent.com/21986859/49412428-65083280-f73a-11e8-8237-bb34158a545e.png)
- **Spirited Away**: [YouTube](https://youtu.be/mGEfasQl2Zo) | [Bilibili](https://www.bilibili.com/video/BV1V5411471i/)
- 360P to 4K
- The [original video](https://www.youtube.com/watch?v=ByXuk9QqQkk)'s copyright belongs to 株式会社スタジオジブリ
- **Bad Apple!!**: [YouTube](https://youtu.be/A81rW_FI3cw) | [Bilibili](https://www.bilibili.com/video/BV16K411K7ue)
- 384P to 4K 120FPS
- The [original video](https://www.nicovideo.jp/watch/sm8628149)'s copyright belongs to あにら
- **The Pet Girl of Sakurasou**: [YouTube](https://youtu.be/M0vDI1HH2_Y) | [Bilibili](https://www.bilibili.com/video/BV14k4y167KP/)
- 240P to 1080P 60FPS
- The original video's copyright belongs to ASCII Media Works
**You can also watch the YouTube video Demo: https://www.youtube.com/watch?v=PG94iPoeoZk**
### GIF Upscaling
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.
![catfru](https://user-images.githubusercontent.com/21986859/81631069-96d4fc80-93f6-11ea-92fb-33d6545055e7.gif)
![catfru4x](https://user-images.githubusercontent.com/21986859/81631070-976d9300-93f6-11ea-9137-072a3b386110.gif)\
_Catfru scaled up to 4x its original size using waifu2x [(original image)](https://gfycat.com/craftyeasygoingankole-capoo-bug-cat)_
## Screenshot
### Image Upscaling
![screenshot](https://user-images.githubusercontent.com/21986859/40265170-39c0caae-5b01-11e8-8371-8b6c24769639.png)
![Jill Comparison](https://user-images.githubusercontent.com/21986859/81631903-79a12d80-93f8-11ea-9c3c-f340240cf08c.png)\
_Image 8x upscaling demo ([original image](https://72915.tumblr.com/post/173793265673) by [nananicu](https://twitter.com/nananicu))_
---
### Standard Test Clip
## Documentations
The following clip can be used to test if your setup works properly. This is also the standard clip used for running performance benchmarks.
### [Video2X Wiki](https://github.com/K4YT3X/video2x/wiki)
- [Standard Test Clip (240P)](https://files.k4yt3x.com/Resources/Videos/standard-test.mp4) 4.54 MiB
- [waifu2x Upscaled Sample (1080P)](https://files.k4yt3x.com/Resources/Videos/standard-waifu2x.mp4) 4.54 MiB
- [Original Ground Truth (1080P)](https://files.k4yt3x.com/Resources/Videos/standard-original.mp4) 22.2 MiB
You can find all detailed user-facing and developer-facing documentations in the [Video2X Wiki](https://github.com/K4YT3X/video2x/wiki). It covers everything from step-by-step instructions for beginners, to the code structure of this program for advanced users and developers. If this README page doesn't answer all your questions, the wiki page is where you should head to.
### [Step-By-Step Tutorial](https://github.com/K4YT3X/video2x/wiki/Step-By-Step-Tutorial) (Nvidia GPUs)
For those who want a detailed walk-through of how to use `Video2X`, you can head to the [Step-By-Step Tutorial](https://github.com/K4YT3X/video2x/wiki/Step-By-Step-Tutorial) wiki page. It includes almost every step you need to perform in order to enlarge your first video.
### [Waifu2X Drivers](https://github.com/K4YT3X/video2x/wiki/Waifu2X-Drivers)
Go to the [Waifu2X Drivers](https://github.com/K4YT3X/video2x/wiki/Waifu2X-Drivers) wiki page if you want to see a detailed description on the different types of `waifu2x` drivers implemented by `Video2X`. This wiki page contains detailed difference between different drivers, and how to download and set each of them up for `Video2X`.
---
## Quick Start
### Prerequisites
- **Python 3**
Download: https://www.python.org/downloads/windows/
- **FFMPEG Windows Build**
Download: https://ffmpeg.org/download.html
- **waifu2x-caffe** (for Nvidia CUDA/CUDNN)
Download: https://github.com/lltcggie/waifu2x-caffe/releases
- **waifu2x-converter-cpp** (required for AMD, OpenCL and OpenGL processing)
Download: https://github.com/DeadSix27/waifu2x-converter-cpp/releases
### Installing Dependencies
First, clone the video2x repository.
```shell
git clone https://github.com/K4YT3X/video2x.git
cd video2x/bin
```
Then you may run the `video2x_setup.py` script to install and configure the dependencies automatically. This script is designed and tested on Windows 10.
This script will install the newest version of `ffmpeg`, either or both of `waifu2x-caffe` and `waifu2x-converter-cpp` to `%LOCALAPPDATA%\\video2x` and all required python libraries.
```shell
python video2x_setup.py
```
Alternatively, you can also install the dependencies manually. Please refer to the prerequisites section to see what's needed.
Then you'll need to install python dependencies before start using video2x. Install simply by executing the following command.
```shell
pip install -r requirements.txt
```
**Note that all command line arguments/options overwrite configuration file settings.**
### Sample Videos
If you can't find a video clip to begin with, or if you want to see a before-after comparison, we have prepared some sample clips for you. The quick start guide down below will also be based on the name of the sample clips.
![sample_video](https://user-images.githubusercontent.com/21986859/52905766-d5512b00-3236-11e9-9aea-077636539679.png)
- [Sample Video Original (240P) 1.7MB](https://files.flexio.org/Resources/Videos/sample_input.mp4)
- [Sample Video Upscaled (1080P) 4.8MB](https://files.flexio.org/Resources/Videos/sample_output.mp4)
Clip is from anime "さくら荘のペットな彼女". Copyright belongs to "株式会社アニプレックス (Aniplex Inc.)". Will delete immediately if use of clip is in violation of copyright.
### Nvidia CUDA (waifu2x-caffe)
Enlarge the video to 1920x1080 using CUDA. You may also use the `-r/--ratio` option.
```shell
python video2x.py -i sample_input.mp4 -o sample_output.mp4 -m gpu --width=1920 --height=1080
```
### Nvidia CNDNN
Enlarge the video to 1920x1080 using CUDNN. You may also use the `-r/--ratio` option.
```shell
python video2x.py -i sample_input.mp4 -o sample_output.mp4 -m cudnn --width=1920 --height=1080
```
### AMD or Nvidia (waifu2x-converter-cpp OpenCL)
Enlarge the video by 2 times using OpenCL. Note that `waifu2x-converter-cpp` doesn't support width and height. You'll also have to explicitly specify that the driver to be used is `waifu2x_converter`.
```shell
python video2x.py -i sample_input.mp4 -o sample_output.mp4 -m gpu -r 2 -d waifu2x_converter
```
### CPU
Enlarge the video to 1920x1080 using the CPU. You may also use the `-r/--ratio` option. This is potentially much slower than using a GPU. The configuration file for this method is similar to the previous methods.
```shell
python video2x.py -i sample_input.mp4 -o sample_output.mp4 -m cpu --width=1920 --height=1080
```
---
# Full Usage
## General Options
### -h, --help
show this help message and exit
## File Options
### -i INPUT, --input INPUT
Source video file/directory (default: None)
### -o OUTPUT, --output OUTPUT
Output video file/directory (default: None)
## Upscaling Options
### -m {cpu,gpu,cudnn}, --method {cpu,gpu,cudnn}
Upscaling method (default: gpu)
### -d {waifu2x_caffe,waifu2x_converter}, --driver {waifu2x_caffe,waifu2x_converter}
Waifu2x driver (default: waifu2x_caffe)
### -y MODEL_DIR, --model_dir MODEL_DIR
Folder containing model JSON files
### -t THREADS, --threads THREADS
Number of threads to use for upscaling (default: 5)
### -c CONFIG, --config CONFIG
Video2X config file location (default: video2x\bin\video2x.json)
### -b, --batch
Enable batch mode (select all default values to questions)
## Scaling Options
### --width WIDTH
Output video width
### --height HEIGHT
Output video height
### -r RATIO, --ratio RATIO
Scaling ratio
---
The original clip came from the anime "さくら荘のペットな彼女."\
Copyright of this clip belongs to 株式会社アニプレックス.
## License
Licensed under the GNU General Public License Version 3 (GNU GPL v3)
https://www.gnu.org/licenses/gpl-3.0.txt
This project is licensed under the [GNU Affero General Public License Version 3 (GNU AGPL v3)](https://www.gnu.org/licenses/agpl-3.0.txt)\
Copyright (c) 2018-2022 K4YT3X and contributors.
![GPLv3 Icon](https://www.gnu.org/graphics/gplv3-127x51.png)
![AGPLv3](https://www.gnu.org/graphics/agplv3-155x51.png)
(C) 2018-2019 K4YT3X
This project includes or depends on these following projects:
## Credits
| Project | License |
| ------------------------------------------------------------------- | --------------- |
| [FFmpeg](https://www.ffmpeg.org/) | LGPLv2.1, GPLv2 |
| [waifu2x-ncnn-vulkan](https://github.com/nihui/waifu2x-ncnn-vulkan) | MIT License |
| [srmd-ncnn-vulkan](https://github.com/nihui/srmd-ncnn-vulkan) | MIT License |
| [realsr-ncnn-vulkan](https://github.com/nihui/realsr-ncnn-vulkan) | MIT License |
| [rife-ncnn-vulkan](https://github.com/nihui/rife-ncnn-vulkan) | MIT License |
| [ffmpeg-python](https://github.com/kkroening/ffmpeg-python) | Apache-2.0 |
| [Loguru](https://github.com/Delgan/loguru) | MIT License |
| [opencv-python](https://github.com/opencv/opencv-python) | MIT License |
| [Pillow](https://github.com/python-pillow/Pillow) | HPND License |
| [Rich](https://github.com/Textualize/rich) | MIT License |
This project relies on the following software and projects.
Legacy versions of this project includes or depends on these following projects:
- [FFMPEG]('https://www.ffmpeg.org/')
- [waifu2x-caffe](https://github.com/lltcggie/waifu2x-caffe)
- [waifu2x-converter-cpp](https://github.com/DeadSix27/waifu2x-converter-cpp)
| Project | License |
| --------------------------------------------------------------------------- | -------------------- |
| [waifu2x-caffe](https://github.com/lltcggie/waifu2x-caffe) | MIT License |
| [waifu2x-converter-cpp](https://github.com/DeadSix27/waifu2x-converter-cpp) | MIT License |
| [Anime4K](https://github.com/bloc97/Anime4K) | MIT License |
| [Anime4KCPP](https://github.com/TianZerL/Anime4KCPP) | MIT License |
| [Gifski](https://github.com/ImageOptim/gifski) | AGPLv3 |
| [tqdm](https://github.com/tqdm/tqdm) | MPLv2.0, MIT License |
## Related Resources
More licensing information can be found in the [NOTICES](NOTICES) file.
- [Dandere2x](https://github.com/CardinalPanda/dandere2x): `Dandere2x` is a lossy video upscaler also built around `waifu2x`, but with video compression techniques to shorten the time needed to process a video.
## Special Thanks
Appreciations given to the following personnel who have contributed significantly to the project.
- [@BrianPetkovsek](https://github.com/BrianPetkovsek)
- [@sat3ll](https://github.com/sat3ll)
- [@ddouglas87](https://github.com/ddouglas87)
- [@lhanjian](https://github.com/lhanjian)
- [@ArchieMeng](https://github.com/archiemeng)
## Similar Projects
- [Dandere2x](https://github.com/CardinalPanda/dandere2x): A lossy video upscaler also built around `waifu2x`, but with video compression techniques to shorten the time needed to process a video.
- [Waifu2x-Extension-GUI](https://github.com/AaronFeng753/Waifu2x-Extension-GUI): A similar project that focuses more and only on building a better graphical user interface. It is built using C++ and Qt5, and currently only supports the Windows platform.

View File

@@ -1,13 +0,0 @@
#!/usr/bin/env python3
# -*- code:utf-8 -*-
"""
Name: Video2X Exceptions
Dev: K4YT3X
Date Created: December 13, 2018
Last Modified: March 19, 2019
"""
class ArgumentError(Exception):
def __init__(self, message):
super().__init__(message)

View File

@@ -1,147 +0,0 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Name: FFMPEG Class
Author: K4YT3X
Date Created: Feb 24, 2018
Last Modified: March 30, 2019
Description: This class handles all FFMPEG related
operations.
"""
from avalon_framework import Avalon
import json
import subprocess
class Ffmpeg:
"""This class communicates with ffmpeg
This class deals with ffmpeg. It handles extracitng
frames, stripping audio, converting images into videos
and inserting audio tracks to videos.
"""
def __init__(self, ffmpeg_settings, image_format):
self.ffmpeg_settings = ffmpeg_settings
self.ffmpeg_path = self.ffmpeg_settings['ffmpeg_path']
# add a forward slash to directory if not present
# otherwise there will be a format error
if self.ffmpeg_path[-1] != '/' and self.ffmpeg_path[-1] != '\\':
self.ffmpeg_path = '{}\\'.format(self.ffmpeg_path)
self.ffmpeg_binary = '{}ffmpeg.exe'.format(self.ffmpeg_path)
self.ffmpeg_probe_binary = '{}ffprobe.exe'.format(self.ffmpeg_path)
self.image_format = image_format
def get_video_info(self, input_video):
""" Gets input video information
This method reads input video information
using ffprobe in dictionary.
Arguments:
input_video {string} -- input video file path
Returns:
dictionary -- JSON text of input video information
"""
# this execution command needs to be hard-coded
# since video2x only strictly recignizes this one format
execute = [
self.ffmpeg_probe_binary,
'-v',
'quiet',
'-print_format',
'json',
'-show_format',
'-show_streams',
'-i',
'{}'.format(input_video)
]
Avalon.debug_info('Executing: {}'.format(' '.join(execute)))
json_str = subprocess.run(execute, check=True, stdout=subprocess.PIPE).stdout
return json.loads(json_str.decode('utf-8'))
def extract_frames(self, input_video, extracted_frames):
"""Extract every frame from original videos
This method extracts every frame from videoin
using ffmpeg
Arguments:
input_video {string} -- input video path
extracted_frames {string} -- video output folder
"""
execute = [
self.ffmpeg_binary,
'-i',
input_video,
'{}\\extracted_%0d.{}'.format(extracted_frames, self.image_format)
]
self._execute(execute=execute, phase='video_to_frames')
def convert_video(self, framerate, resolution, upscaled_frames):
"""Converts images into videos
This method converts a set of images into a
video.
Arguments:
framerate {float} -- target video framerate
resolution {string} -- target video resolution
upscaled_frames {string} -- source images folder
"""
execute = [
self.ffmpeg_binary,
'-r',
str(framerate),
'-s',
resolution,
'-i',
'{}\\extracted_%d.{}'.format(upscaled_frames, self.image_format),
'{}\\no_audio.mp4'.format(upscaled_frames)
]
self._execute(execute=execute, phase='frames_to_video')
def migrate_audio_tracks_subtitles(self, input_video, output_video, upscaled_frames):
""" Migrates audio tracks and subtitles from input video to output video
Arguments:
input_video {string} -- input video file path
output_video {string} -- output video file path
upscaled_frames {string} -- directory containing upscaled frames
"""
execute = [
self.ffmpeg_binary,
'-i',
'{}\\no_audio.mp4'.format(upscaled_frames),
'-i',
input_video,
output_video
]
self._execute(execute=execute, phase='migrating_tracks')
def _execute(self, execute, phase):
for key in self.ffmpeg_settings[phase].keys():
value = self.ffmpeg_settings[phase][key]
# null or None means that leave this option out (keep default)
if value is None or value is False:
continue
else:
execute.append(key)
# true means key is an option
if value is True:
continue
execute.append(str(value))
Avalon.debug_info('Executing: {}'.format(execute))
return subprocess.run(execute, shell=True, check=True).returncode

View File

@@ -1,76 +0,0 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Name: Video2X Image Cleaner
Author: BrianPetkovsek
Author: K4YT3X
Date Created: March 24, 2019
Last Modified: March 24, 2019
Description: This class is to remove the extracted frames
that have already been upscaled.
"""
import os
import threading
import time
class ImageCleaner(threading.Thread):
""" Video2X Image Cleaner
This class creates an object that keeps track of extracted
frames that has already been upscaled and are not needed
anymore. It then deletes them to save disk space.
Extends:
threading.Thread
"""
def __init__(self, input_folder, output_folder, num_threads):
threading.Thread.__init__(self)
self.input_folder = input_folder
self.output_folder = output_folder
self.num_threads = num_threads
self.running = False
def run(self):
""" Run image cleaner
"""
self.running = True
while self.running:
self.remove_upscaled_frames()
time.sleep(1)
def stop(self):
""" Stop the image cleaner
"""
self.running = False
self.join()
def remove_upscaled_frames(self):
""" remove frames that have already been upscaled
This method compares the files in the extracted frames
folder with the upscaled frames folder, and removes
the frames that has already been upscaled.
"""
# list all images in the extracted frames
output_frames = [f for f in os.listdir(self.output_folder) if os.path.isfile(os.path.join(self.output_folder, f))]
# compare and remove frames downscaled images that finished being upscaled
# within each thread's extracted frames folder
for i in range(self.num_threads):
dir_path = os.path.join(self.input_folder, str(i))
# for each file within all the folders
for f in os.listdir(dir_path):
file_path = os.path.join(dir_path, f)
# if file also exists in the output folder, then the file
# has already been processed, thus not needed anymore
if os.path.isfile(file_path) and f in output_frames:
os.remove(file_path)
output_frames.remove(f)

View File

@@ -1,6 +0,0 @@
avalon_framework
colorama
GPUtil
psutil
requests
tqdm

View File

@@ -1,305 +0,0 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Name: Video2X Upscaler
Author: K4YT3X
Date Created: December 10, 2018
Last Modified: March 30, 2019
Licensed under the GNU General Public License Version 3 (GNU GPL v3),
available at: https://www.gnu.org/licenses/gpl-3.0.txt
(C) 2018-2019 K4YT3X
"""
from avalon_framework import Avalon
from exceptions import *
from ffmpeg import Ffmpeg
from fractions import Fraction
from image_cleaner import ImageCleaner
from tqdm import tqdm
from waifu2x_caffe import Waifu2xCaffe
from waifu2x_converter import Waifu2xConverter
import os
import re
import shutil
import tempfile
import threading
import time
class Upscaler:
""" An instance of this class is a upscaler that will
upscale all images in the given folder.
Raises:
Exception -- all exceptions
ArgumentError -- if argument is not valid
"""
def __init__(self, input_video, output_video, method, waifu2x_settings, ffmpeg_settings):
# mandatory arguments
self.input_video = input_video
self.output_video = output_video
self.method = method
self.waifu2x_settings = waifu2x_settings
self.ffmpeg_settings = ffmpeg_settings
# optional arguments
self.waifu2x_driver = 'waifu2x_caffe'
self.scale_width = None
self.scale_height = None
self.scale_ratio = None
self.model_dir = None
self.threads = 5
self.video2x_cache_folder = '{}\\video2x'.format(tempfile.gettempdir())
self.image_format = 'png'
self.preserve_frames = False
# create temporary folder/directories
self.extracted_frames = tempfile.mkdtemp(dir=self.video2x_cache_folder)
Avalon.debug_info('Extracted frames are being saved to: {}'.format(self.extracted_frames))
self.upscaled_frames = tempfile.mkdtemp(dir=self.video2x_cache_folder)
Avalon.debug_info('Upscaled frames are being saved to: {}'.format(self.upscaled_frames))
def cleanup(self):
# delete temp directories when done
# avalon framework cannot be used if python is shutting down
# therefore, plain print is used
if not self.preserve_frames:
for directory in [self.extracted_frames, self.upscaled_frames]:
try:
print('Cleaning up cache directory: {}'.format(directory))
shutil.rmtree(directory)
except (OSError, FileNotFoundError):
pass
def _check_arguments(self):
# check if arguments are valid / all necessary argument
# values are specified
if not self.input_video:
raise ArgumentError('You need to specify the video to process')
elif (not self.scale_width or not self.scale_height) and not self.scale_ratio:
raise ArgumentError('You must specify output video width and height or upscale factor')
elif not self.output_video:
raise ArgumentError('You need to specify the output video name')
elif not self.method:
raise ArgumentError('You need to specify the enlarging processing unit')
def _progress_bar(self, extracted_frames_folders):
""" This method prints a progress bar
This method prints a progress bar by keeping track
of the amount of frames in the input directory/folder
and the output directory/folder. This is originally
suggested by @ArmandBernard.
"""
# get number of extracted frames
total_frames = 0
for folder in extracted_frames_folders:
total_frames += len([f for f in os.listdir(folder) if f[-4:] == '.png'])
with tqdm(total=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:
try:
total_frames_upscaled = len([f for f in os.listdir(self.upscaled_frames) if f[-4:] == '.png'])
delta = total_frames_upscaled - previous_cycle_frames
previous_cycle_frames = total_frames_upscaled
# if upscaling is finished
if total_frames_upscaled >= total_frames:
return
# adds the detla into the progress bar
progress_bar.update(delta)
except FileNotFoundError:
pass
time.sleep(1)
def _upscale_frames(self, w2):
""" Upscale video frames with waifu2x-caffe
This function upscales all the frames extracted
by ffmpeg using the waifu2x-caffe binary.
Arguments:
w2 {Waifu2x Object} -- initialized waifu2x object
"""
# progress bar thread exit signal
self.progress_bar_exit_signal = False
# create a container for exceptions in threads
# if this thread is not empty, then an exception has occured
self.upscaler_exceptions = []
# it's easier to do multi-threading with waifu2x_converter
# the number of threads can be passed directly to waifu2x_converter
if self.waifu2x_driver == 'waifu2x_converter':
progress_bar = threading.Thread(target=self._progress_bar, args=([self.extracted_frames],))
progress_bar.start()
w2.upscale(self.extracted_frames, self.upscaled_frames, self.scale_ratio, self.threads, self.image_format, self.upscaler_exceptions)
for image in [f for f in os.listdir(self.upscaled_frames) if os.path.isfile(os.path.join(self.upscaled_frames, f))]:
renamed = re.sub('_\[.*-.*\]\[x(\d+(\.\d+)?)\]\.{}'.format(self.image_format), '.{}'.format(self.image_format), image)
shutil.move('{}\\{}'.format(self.upscaled_frames, image), '{}\\{}'.format(self.upscaled_frames, renamed))
self.progress_bar_exit_signal = True
progress_bar.join()
return
# create a container for all upscaler threads
upscaler_threads = []
# list all images in the extracted frames
frames = [os.path.join(self.extracted_frames, f) for f in os.listdir(self.extracted_frames) if os.path.isfile(os.path.join(self.extracted_frames, f))]
# if we have less images than threads,
# create only the threads necessary
if len(frames) < self.threads:
self.threads = len(frames)
# create a folder for each thread and append folder
# name into a list
thread_pool = []
thread_folders = []
for thread_id in range(self.threads):
thread_folder = '{}\\{}'.format(self.extracted_frames, str(thread_id))
thread_folders.append(thread_folder)
# delete old folders and create new folders
if os.path.isdir(thread_folder):
shutil.rmtree(thread_folder)
os.mkdir(thread_folder)
# append folder path into list
thread_pool.append((thread_folder, thread_id))
# evenly distribute images into each folder
# until there is none left in the folder
for image in frames:
# move image
shutil.move(image, thread_pool[0][0])
# rotate list
thread_pool = thread_pool[-1:] + thread_pool[:-1]
# create threads and start them
for thread_info in thread_pool:
# create thread
if self.scale_ratio:
thread = threading.Thread(target=w2.upscale, args=(thread_info[0], self.upscaled_frames, self.scale_ratio, False, False, self.image_format, self.upscaler_exceptions))
else:
thread = threading.Thread(target=w2.upscale, args=(thread_info[0], self.upscaled_frames, False, self.scale_width, self.scale_height, self.image_format, self.upscaler_exceptions))
thread.name = thread_info[1]
# add threads into the pool
upscaler_threads.append(thread)
# start progress bar in a different thread
progress_bar = threading.Thread(target=self._progress_bar, args=(thread_folders,))
progress_bar.start()
# create the clearer and start it
Avalon.debug_info('Starting upscaled image cleaner')
image_cleaner = ImageCleaner(self.extracted_frames, self.upscaled_frames, len(upscaler_threads))
image_cleaner.start()
# start all threads
for thread in upscaler_threads:
thread.start()
# wait for threads to finish
for thread in upscaler_threads:
thread.join()
# upscaling done, kill the clearer
Avalon.debug_info('Killing upscaled image cleaner')
image_cleaner.stop()
self.progress_bar_exit_signal = True
if len(self.upscaler_exceptions) != 0:
raise(self.upscaler_exceptions[0])
def run(self):
"""Main controller for Video2X
This function controls the flow of video conversion
and handles all necessary functions.
"""
# parse arguments for waifu2x
# check argument sanity
self._check_arguments()
# convert paths to absolute paths
self.input_video = os.path.abspath(self.input_video)
self.output_video = os.path.abspath(self.output_video)
# initialize objects for ffmpeg and waifu2x-caffe
fm = Ffmpeg(self.ffmpeg_settings, self.image_format)
# initialize waifu2x driver
if self.waifu2x_driver == 'waifu2x_caffe':
w2 = Waifu2xCaffe(self.waifu2x_settings, self.method, self.model_dir)
elif self.waifu2x_driver == 'waifu2x_converter':
w2 = Waifu2xConverter(self.waifu2x_settings, self.model_dir)
else:
raise Exception('Unrecognized waifu2x driver: {}'.format(self.waifu2x_driver))
# extract frames from video
fm.extract_frames(self.input_video, self.extracted_frames)
Avalon.info('Reading video information')
video_info = fm.get_video_info(self.input_video)
# analyze original video with ffprobe and retrieve framerate
# width, height = info['streams'][0]['width'], info['streams'][0]['height']
# find index of video stream
video_stream_index = None
for stream in video_info['streams']:
if stream['codec_type'] == 'video':
video_stream_index = stream['index']
break
# exit if no video stream found
if video_stream_index is None:
Avalon.error('Aborting: No video stream found')
exit(1)
# get average frame rate of video stream
framerate = float(Fraction(video_info['streams'][video_stream_index]['avg_frame_rate']))
Avalon.info('Framerate: {}'.format(framerate))
# width/height will be coded width/height x upscale factor
if self.scale_ratio:
coded_width = video_info['streams'][video_stream_index]['coded_width']
coded_height = video_info['streams'][video_stream_index]['coded_height']
self.scale_width = int(self.scale_ratio * coded_width)
self.scale_height = int(self.scale_ratio * coded_height)
# upscale images one by one using waifu2x
Avalon.info('Starting to upscale extracted images')
self._upscale_frames(w2)
Avalon.info('Upscaling completed')
# frames to Video
Avalon.info('Converting extracted frames into video')
# use user defined output size
fm.convert_video(framerate, '{}x{}'.format(self.scale_width, self.scale_height), self.upscaled_frames)
Avalon.info('Conversion completed')
# migrate audio tracks and subtitles
Avalon.info('Migrating audio tracks and subtitles to upscaled video')
fm.migrate_audio_tracks_subtitles(self.input_video, self.output_video, self.upscaled_frames)

View File

@@ -1,73 +0,0 @@
{
"waifu2x_caffe": {
"waifu2x_caffe_path": "C:\\Users\\K4YT3X\\AppData\\Local\\video2x\\waifu2x-caffe\\waifu2x-caffe-cui.exe",
"input_extention_list": null,
"output_extention": null,
"mode": "noise_scale",
"scale_ratio": null,
"scale_width": null,
"scale_height": null,
"noise_level": 3,
"process": "gpu",
"crop_size": 128,
"output_quality": -1,
"output_depth": 8,
"batch_size": 1,
"gpu": 0,
"tta": 0,
"input_path": null,
"output_path": null,
"model_dir": null,
"crop_w": null,
"crop_h": null
},
"waifu2x_converter": {
"waifu2x_converter_path": "C:\\Users\\K4YT3X\\AppData\\Local\\video2x\\waifu2x-converter-cpp",
"output-format": null,
"png-compression": null,
"image-quality": null,
"block-size": null,
"disable-gpu": null,
"force-OpenCL": null,
"processor": null,
"jobs": null,
"model-dir": null,
"scale-ratio": null,
"noise-level": 3,
"mode": "noise-scale",
"silent": true,
"output": null,
"input": null
},
"ffmpeg": {
"ffmpeg_path": "C:\\Users\\K4YT3X\\AppData\\Local\\video2x\\ffmpeg-latest-win64-static\\bin",
"video_to_frames": {
"-qscale:v": null,
"-hwaccel": "auto",
"-y": true
},
"frames_to_video": {
"-qscale:v": null,
"-qscale:a": null,
"-f": "image2",
"-vcodec": "libx264",
"-crf": 25,
"-pix_fmt": "yuv420p",
"-hwaccel": "auto",
"-y": true
},
"migrating_tracks": {
"-map": "0:v:0?",
"-map": "1?",
"-c": "copy",
"-map": "-1:v?",
"-hwaccel": "auto",
"-y": true
}
},
"video2x": {
"video2x_cache_folder": null,
"image_format": "png",
"preserve_frames": false
}
}

View File

@@ -1,307 +0,0 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
__ __ _ _ ___ __ __
\ \ / / (_) | | |__ \ \ \ / /
\ \ / / _ __| | ___ ___ ) | \ V /
\ \/ / | | / _` | / _ \ / _ \ / / > <
\ / | | | (_| | | __/ | (_) | / /_ / . \
\/ |_| \__,_| \___| \___/ |____| /_/ \_\
Name: Video2X Controller
Author: K4YT3X
Date Created: Feb 24, 2018
Last Modified: March 30, 2019
Licensed under the GNU General Public License Version 3 (GNU GPL v3),
available at: https://www.gnu.org/licenses/gpl-3.0.txt
(C) 2018-2019 K4YT3X
Video2X is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Video2X is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
Description: Video2X is an automation software based on waifu2x image
enlarging engine. It extracts frames from a video, enlarge it by a
number of times without losing any details or quality, keeping lines
smooth and edges sharp.
"""
from avalon_framework import Avalon
from upscaler import Upscaler
import argparse
import GPUtil
import json
import os
import psutil
import shutil
import sys
import tempfile
import time
import traceback
VERSION = '2.7.0'
# each thread might take up to 2.5 GB during initialization.
# (system memory, not to be confused with GPU memory)
SYS_MEM_PER_THREAD = 2.5
GPU_MEM_PER_THREAD = 3.5
def process_arguments():
"""Processes CLI arguments
This function parses all arguments
This allows users to customize options
for the output video.
"""
parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter)
# video options
file_options = parser.add_argument_group('File Options')
file_options.add_argument('-i', '--input', help='Source video file/directory', action='store', required=True)
file_options.add_argument('-o', '--output', help='Output video file/directory', action='store', required=True)
# upscaler options
upscaler_options = parser.add_argument_group('Upscaler Options')
upscaler_options.add_argument('-m', '--method', help='Upscaling method', action='store', default='gpu', choices=['cpu', 'gpu', 'cudnn'], required=True)
upscaler_options.add_argument('-d', '--driver', help='Waifu2x driver', action='store', default='waifu2x_caffe', choices=['waifu2x_caffe', 'waifu2x_converter'])
upscaler_options.add_argument('-y', '--model_dir', help='Folder containing model JSON files', action='store')
upscaler_options.add_argument('-t', '--threads', help='Number of threads to use for upscaling', action='store', type=int, default=5)
upscaler_options.add_argument('-c', '--config', help='Video2X config file location', action='store', default='{}\\video2x.json'.format(os.path.dirname(os.path.abspath(sys.argv[0]))))
upscaler_options.add_argument('-b', '--batch', help='Enable batch mode (select all default values to questions)', action='store_true')
# scaling options
scaling_options = parser.add_argument_group('Scaling Options')
scaling_options.add_argument('--width', help='Output video width', action='store', type=int)
scaling_options.add_argument('--height', help='Output video height', action='store', type=int)
scaling_options.add_argument('-r', '--ratio', help='Scaling ratio', action='store', type=float)
# parse arguments
return parser.parse_args()
def print_logo():
print('__ __ _ _ ___ __ __')
print('\\ \\ / / (_) | | |__ \\ \\ \\ / /')
print(' \\ \\ / / _ __| | ___ ___ ) | \\ V /')
print(' \\ \\/ / | | / _` | / _ \\ / _ \\ / / > <')
print(' \\ / | | | (_| | | __/ | (_) | / /_ / . \\')
print(' \\/ |_| \\__,_| \\___| \\___/ |____| /_/ \\_\\')
print('\n Video2X Video Enlarger')
spaces = ((44 - len("Version {}".format(VERSION))) // 2) * " "
print('{}\n{} Version {}\n{}'.format(Avalon.FM.BD, spaces, VERSION, Avalon.FM.RST))
def check_memory():
""" Check usable system memory
Warn the user if insufficient memory is available for
the number of threads that the user have chosen.
"""
memory_status = []
# get system available memory
system_memory_available = psutil.virtual_memory().available / (1024 ** 3)
memory_status.append(('system', system_memory_available))
# check if Nvidia-smi is available
# GPUtil requires nvidia-smi.exe to interact with GPU
if args.method == 'gpu' or args.method == 'cudnn':
if not os.path.isfile('C:\\Program Files\\NVIDIA Corporation\\NVSMI\\nvidia-smi.exe'):
# Nvidia System Management Interface not available
Avalon.warning('Nvidia-smi not available, skipping available memory check')
Avalon.warning('If you experience error \"cudaSuccess out of memory\", try reducing number of threads you\'re using')
else:
try:
# "0" is GPU ID. Both waifu2x drivers use the first GPU available, therefore only 0 makes sense
gpu_memory_available = (GPUtil.getGPUs()[0].memoryTotal - GPUtil.getGPUs()[0].memoryUsed) / 1024
memory_status.append(('GPU', gpu_memory_available))
except ValueError:
pass
# go though each checkable memory type and check availability
for memory_type, memory_available in memory_status:
if memory_type == 'system':
mem_per_thread = SYS_MEM_PER_THREAD
else:
mem_per_thread = GPU_MEM_PER_THREAD
# if user doesn't even have enough memory to run even one thread
if memory_available < mem_per_thread:
Avalon.warning('You might have insufficient amount of {} memory available to run this program ({} GB)'.format(memory_type, memory_available))
Avalon.warning('Proceed with caution')
if args.threads > 1:
if Avalon.ask('Reduce number of threads to avoid crashing?', default=True, batch=args.batch):
args.threads = 1
# if memory available is less than needed, warn the user
elif memory_available < (mem_per_thread * args.threads):
Avalon.warning('Each waifu2x-caffe thread will require up to 2.5 GB of system memory')
Avalon.warning('You demanded {} threads to be created, but you only have {} GB {} memory available'.format(args.threads, round(memory_available, 4), memory_type))
Avalon.warning('{} GB of {} memory is recommended for {} threads'.format(mem_per_thread * args.threads, memory_type, args.threads))
Avalon.warning('With your current amount of {} memory available, {} threads is recommended'.format(memory_type, int(memory_available // mem_per_thread)))
# ask the user if he / she wants to change to the recommended
# number of threads
if Avalon.ask('Change to the recommended value?', default=True, batch=args.batch):
args.threads = int(memory_available // mem_per_thread)
else:
Avalon.warning('Proceed with caution')
def read_config(config_file):
""" Reads configuration file
Returns a dictionary read by JSON.
"""
with open(config_file, 'r') as raw_config:
config = json.load(raw_config)
return config
# /////////////////// Execution /////////////////// #
# this is not a library
if __name__ != '__main__':
Avalon.error('This file cannot be imported')
raise ImportError('{} cannot be imported'.format(__file__))
print_logo()
# process CLI arguments
args = process_arguments()
# arguments sanity check
if args.driver == 'waifu2x_converter' and args.width and args.height:
Avalon.error('Waifu2x Converter CPP accepts only scaling ratio')
exit(1)
if (args.width or args.height) and args.ratio:
Avalon.error('You can only specify either scaling ratio or output width and height')
exit(1)
if (args.width and not args.height) or (not args.width and args.height):
Avalon.error('You must specify both width and height')
exit(1)
# check available memory
check_memory()
# read configurations from JSON
config = read_config(args.config)
# load waifu2x configuration
if args.driver == 'waifu2x_caffe':
waifu2x_settings = config['waifu2x_caffe']
if not os.path.isfile(waifu2x_settings['waifu2x_caffe_path']):
Avalon.error('Specified waifu2x-caffe directory doesn\'t exist')
Avalon.error('Please check the configuration file settings')
raise FileNotFoundError(waifu2x_settings['waifu2x_caffe_path'])
elif args.driver == 'waifu2x_converter':
waifu2x_settings = config['waifu2x_converter']
if not os.path.isdir(waifu2x_settings['waifu2x_converter_path']):
Avalon.error('Specified waifu2x-conver-cpp directory doesn\'t exist')
Avalon.error('Please check the configuration file settings')
raise FileNotFoundError(waifu2x_settings['waifu2x_converter_path'])
# check if waifu2x path is valid
# read FFMPEG configuration
ffmpeg_settings = config['ffmpeg']
# load video2x settings
video2x_cache_folder = config['video2x']['video2x_cache_folder']
image_format = config['video2x']['image_format'].lower()
preserve_frames = config['video2x']['preserve_frames']
# create temp directories if they don't exist
if not video2x_cache_folder:
video2x_cache_folder = '{}\\video2x'.format(tempfile.gettempdir())
if video2x_cache_folder and not os.path.isdir(video2x_cache_folder):
if not os.path.isfile(video2x_cache_folder) and not os.path.islink(video2x_cache_folder):
Avalon.warning('Specified cache folder/directory {} does not exist'.format(video2x_cache_folder))
if Avalon.ask('Create folder/directory?', default=True, batch=args.batch):
if os.mkdir(video2x_cache_folder) is None:
Avalon.info('{} created'.format(video2x_cache_folder))
else:
Avalon.error('Unable to create {}'.format(video2x_cache_folder))
Avalon.error('Aborting...')
exit(1)
else:
Avalon.error('Specified cache folder/directory is a file/link')
Avalon.error('Unable to continue, exiting...')
exit(1)
# start execution
try:
# start timer
begin_time = time.time()
if os.path.isfile(args.input):
""" Upscale single video file """
Avalon.info('Upscaling single video file: {}'.format(args.input))
upscaler = Upscaler(input_video=args.input, output_video=args.output, method=args.method, waifu2x_settings=waifu2x_settings, ffmpeg_settings=ffmpeg_settings)
# set optional options
upscaler.waifu2x_driver = args.driver
upscaler.scale_width = args.width
upscaler.scale_height = args.height
upscaler.scale_ratio = args.ratio
upscaler.model_dir = args.model_dir
upscaler.threads = args.threads
upscaler.video2x_cache_folder = video2x_cache_folder
upscaler.image_format = image_format
upscaler.preserve_frames = preserve_frames
# run upscaler-
upscaler.run()
upscaler.cleanup()
elif os.path.isdir(args.input):
""" Upscale videos in a folder/directory """
Avalon.info('Upscaling videos in folder/directory: {}'.format(args.input))
for input_video in [f for f in os.listdir(args.input) if os.path.isfile(os.path.join(args.input, f))]:
output_video = '{}\\{}'.format(args.output, input_video)
upscaler = Upscaler(input_video=os.path.join(args.input, input_video), output_video=output_video, method=args.method, waifu2x_settings=waifu2x_settings, ffmpeg_settings=ffmpeg_settings)
# set optional options
upscaler.waifu2x_driver = args.driver
upscaler.scale_width = args.width
upscaler.scale_height = args.height
upscaler.scale_ratio = args.ratio
upscaler.model_dir = args.model_dir
upscaler.threads = args.threads
upscaler.video2x_cache_folder = video2x_cache_folder
upscaler.image_format = image_format
upscaler.preserve_frames = preserve_frames
# run upscaler
upscaler.run()
upscaler.cleanup()
else:
Avalon.error('Input path is neither a file nor a folder/directory')
raise FileNotFoundError('{} is neither file nor folder/directory'.format(args.input))
Avalon.info('Program completed, taking {} seconds'.format(round((time.time() - begin_time), 5)))
except Exception:
Avalon.error('An exception has occurred')
traceback.print_exc()
Avalon.warning('If you experience error \"cudaSuccess out of memory\", try reducing number of threads you\'re using')
finally:
# remove Video2X Cache folder
try:
if not preserve_frames:
shutil.rmtree(video2x_cache_folder)
except FileNotFoundError:
pass

View File

@@ -1,223 +0,0 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Name: Video2X Setup Script
Author: K4YT3X
Date Created: November 28, 2018
Last Modified: March 26, 2019
Licensed under the GNU General Public License Version 3 (GNU GPL v3),
available at: https://www.gnu.org/licenses/gpl-3.0.txt
(C) 2018-2019 K4YT3X
Description: This script helps installing all dependencies of video2x
and generates a configuration for it.
Installation Details:
- ffmpeg: %LOCALAPPDATA%\\video2x\\ffmpeg
- waifu2x-caffe: %LOCALAPPDATA%\\video2x\\waifu2x-caffe
"""
import argparse
import json
import os
import subprocess
import tempfile
import traceback
import zipfile
# Requests doesn't come with windows, therefore
# it will be installed as a dependency and imported
# later in the script.
# import requests
VERSION = '1.2.0'
def process_arguments():
"""Processes CLI arguments
"""
parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter)
# video options
general_options = parser.add_argument_group('General Options')
general_options.add_argument('-d', '--driver', help='driver to download and configure', action='store', choices=['all', 'waifu2x_caffe', 'waifu2x_converter'], default='all')
# parse arguments
return parser.parse_args()
class Video2xSetup:
""" Install dependencies for video2x video enlarger
This library is meant to be executed as a stand-alone
script. All files will be installed under %LOCALAPPDATA%\\video2x.
"""
def __init__(self, driver):
self.driver = driver
self.trash = []
def run(self):
print('\nInstalling Python libraries')
self._install_python_requirements()
print('\nInstalling FFMPEG')
self._install_ffmpeg()
if self.driver == 'all':
self._install_waifu2x_caffe()
self._install_waifu2x_converter_cpp()
elif self.driver == 'waifu2x_caffe':
self._install_waifu2x_caffe()
elif self.driver == 'waifu2x_converter':
self._install_waifu2x_converter_cpp()
print('\nGenerating Video2X configuration file')
self._generate_config()
print('\nCleaning up temporary files')
self._cleanup()
def _install_python_requirements(self):
""" Read requirements.txt and return its content
"""
with open('requirements.txt', 'r') as req:
for line in req:
package = line.split('==')[0]
pip_install(package)
def _cleanup(self):
""" Cleanup all the temp files downloaded
"""
for file in self.trash:
try:
print('Deleting: {}'.format(file))
os.remove(file)
except FileNotFoundError:
pass
def _install_ffmpeg(self):
""" Install FFMPEG
"""
latest_release = 'https://ffmpeg.zeranoe.com/builds/win64/static/ffmpeg-latest-win64-static.zip'
ffmpeg_zip = download(latest_release, tempfile.gettempdir())
self.trash.append(ffmpeg_zip)
with zipfile.ZipFile(ffmpeg_zip) as zipf:
zipf.extractall('{}\\video2x'.format(os.getenv('localappdata')))
def _install_waifu2x_caffe(self):
""" Install waifu2x_caffe
"""
print('\nInstalling waifu2x-caffe')
import requests
# Get latest release of waifu2x-caffe via GitHub API
latest_release = json.loads(requests.get('https://api.github.com/repos/lltcggie/waifu2x-caffe/releases/latest').content)
for a in latest_release['assets']:
if 'waifu2x-caffe.zip' in a['browser_download_url']:
waifu2x_caffe_zip = download(a['browser_download_url'], tempfile.gettempdir())
self.trash.append(waifu2x_caffe_zip)
with zipfile.ZipFile(waifu2x_caffe_zip) as zipf:
zipf.extractall('{}\\video2x'.format(os.getenv('localappdata')))
def _install_waifu2x_converter_cpp(self):
""" Install waifu2x_caffe
"""
print('\nInstalling waifu2x-converter-cpp')
import re
import requests
# Get latest release of waifu2x-caffe via GitHub API
latest_release = json.loads(requests.get('https://api.github.com/repos/DeadSix27/waifu2x-converter-cpp/releases/latest').content)
for a in latest_release['assets']:
if re.search(r'waifu2x-DeadSix27-win64_v[0-9]*\.zip', a['browser_download_url']):
waifu2x_converter_cpp_zip = download(a['browser_download_url'], tempfile.gettempdir())
self.trash.append(waifu2x_converter_cpp_zip)
with zipfile.ZipFile(waifu2x_converter_cpp_zip) as zipf:
zipf.extractall('{}\\video2x\\waifu2x-converter-cpp'.format(os.getenv('localappdata')))
def _generate_config(self):
""" Generate video2x config
"""
# Open current video2x.json file as template
with open('video2x.json', 'r') as template:
template_dict = json.load(template)
template.close()
# configure only the specified drivers
if self.driver == 'all':
template_dict['waifu2x_caffe']['waifu2x_caffe_path'] = '{}\\video2x\\waifu2x-caffe\\waifu2x-caffe-cui.exe'.format(os.getenv('localappdata'))
template_dict['waifu2x_converter']['waifu2x_converter_path'] = '{}\\video2x\\waifu2x-converter-cpp'.format(os.getenv('localappdata'))
elif self.driver == 'waifu2x_caffe':
template_dict['waifu2x_caffe']['waifu2x_caffe_path'] = '{}\\video2x\\waifu2x-caffe\\waifu2x-caffe-cui.exe'.format(os.getenv('localappdata'))
elif self.driver == 'waifu2x_converter':
template_dict['waifu2x_converter']['waifu2x_converter_path'] = '{}\\video2x\\waifu2x-converter-cpp'.format(os.getenv('localappdata'))
template_dict['ffmpeg']['ffmpeg_path'] = '{}\\video2x\\ffmpeg-latest-win64-static\\bin'.format(os.getenv('localappdata'))
template_dict['ffmpeg']['ffmpeg_hwaccel'] = 'auto'
template_dict['ffmpeg']['extra_arguments'] = []
template_dict['video2x']['video2x_cache_folder'] = False
template_dict['video2x']['preserve_frames'] = False
# Write configuration into file
with open('video2x.json', 'w') as config:
json.dump(template_dict, config, indent=2)
config.close()
def download(url, save_path, chunk_size=4096):
""" Download file to local with requests library
"""
from tqdm import tqdm
import requests
output_file = '{}\\{}'.format(save_path, url.split('/')[-1])
print('Downloading: {}'.format(url))
print('Chunk size: {}'.format(chunk_size))
print('Saving to: {}'.format(output_file))
stream = requests.get(url, stream=True)
total_size = int(stream.headers['content-length'])
# Write content into file
with open(output_file, 'wb') as output:
with tqdm(total=total_size, ascii=True) as progress_bar:
for chunk in stream.iter_content(chunk_size=chunk_size):
if chunk:
output.write(chunk)
progress_bar.update(len(chunk))
return output_file
def pip_install(package):
""" Install python package via python pip module
pip.main() is not available after pip 9.0.1, thus
pip module is not used in this case.
"""
return subprocess.run(['python', '-m', 'pip', 'install', '-U', package]).returncode
if __name__ == "__main__":
try:
args = process_arguments()
print('Video2x Setup Script')
print('Version: {}'.format(VERSION))
setup = Video2xSetup(args.driver)
setup.run()
print('\n Script finished successfully')
except Exception:
traceback.print_exc()
print('An error has occurred')
print('Video2X Automatic Setup has failed')
exit(1)

View File

@@ -1,93 +0,0 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Name: Waifu2x Caffe Driver
Author: K4YT3X
Date Created: Feb 24, 2018
Last Modified: March 30, 2019
Description: This class is a high-level wrapper
for waifu2x-caffe.
"""
from avalon_framework import Avalon
import subprocess
import threading
class Waifu2xCaffe:
"""This class communicates with waifu2x cui engine
An object will be created for this class, containing information
about the binary address and the processing method. When being called
by the main program, other detailed information will be passed to
the upscale function.
"""
def __init__(self, waifu2x_settings, process, model_dir):
self.waifu2x_settings = waifu2x_settings
self.waifu2x_settings['process'] = process
self.waifu2x_settings['model_dir'] = model_dir
# arguments passed through command line overwrites config file values
self.process = process
self.model_dir = model_dir
self.print_lock = threading.Lock()
def upscale(self, input_folder, output_folder, scale_ratio, scale_width, scale_height, image_format, upscaler_exceptions):
"""This is the core function for WAIFU2X class
Arguments:
input_folder {string} -- source folder path
output_folder {string} -- output folder path
width {int} -- output video width
height {int} -- output video height
"""
try:
# overwrite config file settings
self.waifu2x_settings['input_path'] = input_folder
self.waifu2x_settings['output_path'] = output_folder
if scale_ratio:
self.waifu2x_settings['scale_ratio'] = scale_ratio
elif scale_width and scale_height:
self.waifu2x_settings['scale_width'] = scale_width
self.waifu2x_settings['scale_height'] = scale_height
self.waifu2x_settings['output_extention'] = image_format
# print thread start message
self.print_lock.acquire()
Avalon.debug_info('[upscaler] Thread {} started'.format(threading.current_thread().name))
self.print_lock.release()
# list to be executed
execute = []
execute.append(self.waifu2x_settings['waifu2x_caffe_path'])
for key in self.waifu2x_settings.keys():
value = self.waifu2x_settings[key]
# is executable key or null or None means that leave this option out (keep default)
if key == 'waifu2x_caffe_path' or value is None or value is False:
continue
else:
if len(key) == 1:
execute.append('-{}'.format(key))
else:
execute.append('--{}'.format(key))
execute.append(str(value))
Avalon.debug_info('Executing: {}'.format(execute))
completed_command = subprocess.run(execute, check=True)
# print thread exiting message
self.print_lock.acquire()
Avalon.debug_info('[upscaler] Thread {} exiting'.format(threading.current_thread().name))
self.print_lock.release()
# return command execution return code
return completed_command.returncode
except Exception as e:
upscaler_exceptions.append(e)

View File

@@ -1,99 +0,0 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Name: Waifu2x Converter CPP Driver
Author: K4YT3X
Date Created: February 8, 2019
Last Modified: March 30, 2019
Description: This class is a high-level wrapper
for waifu2x-converter-cpp.
"""
from avalon_framework import Avalon
import subprocess
import threading
class Waifu2xConverter:
"""This class communicates with waifu2x cui engine
An object will be created for this class, containing information
about the binary address and the processing method. When being called
by the main program, other detailed information will be passed to
the upscale function.
"""
def __init__(self, waifu2x_settings, model_dir):
self.waifu2x_settings = waifu2x_settings
self.waifu2x_settings['model_dir'] = model_dir
self.print_lock = threading.Lock()
def upscale(self, input_folder, output_folder, scale_ratio, jobs, image_format, upscaler_exceptions):
""" Waifu2x Converter Driver Upscaler
This method executes the upscaling of extracted frames.
Arguments:
input_folder {string} -- source folder path
output_folder {string} -- output folder path
scale_ratio {int} -- frames' scale ratio
threads {int} -- number of threads
"""
try:
# overwrite config file settings
self.waifu2x_settings['input'] = input_folder
self.waifu2x_settings['output'] = output_folder
# temporary fix for https://github.com/DeadSix27/waifu2x-converter-cpp/issues/109
"""
self.waifu2x_settings['i'] = input_folder
self.waifu2x_settings['o'] = output_folder
self.waifu2x_settings['input'] = None
self.waifu2x_settings['output'] = None
"""
self.waifu2x_settings['scale-ratio'] = scale_ratio
self.waifu2x_settings['jobs'] = jobs
self.waifu2x_settings['output-format'] = image_format
# models_rgb must be specified manually for waifu2x-converter-cpp
# if it's not specified in the arguments, create automatically
if self.waifu2x_settings['model-dir'] is None:
self.waifu2x_settings['model-dir'] = '{}\\models_rgb'.format(self.waifu2x_settings['waifu2x_converter_path'])
# print thread start message
self.print_lock.acquire()
Avalon.debug_info('[upscaler] Thread {} started'.format(threading.current_thread().name))
self.print_lock.release()
# list to be executed
execute = []
for key in self.waifu2x_settings.keys():
value = self.waifu2x_settings[key]
# the key doesn't need to be passed in this case
if key == 'waifu2x_converter_path':
execute.append('{}\\waifu2x-converter-cpp.exe'.format(str(value)))
# null or None means that leave this option out (keep default)
elif value is None or value is False:
continue
else:
if len(key) == 1:
execute.append('-{}'.format(key))
else:
execute.append('--{}'.format(key))
# true means key is an option
if value is True:
continue
execute.append(str(value))
Avalon.debug_info('Executing: {}'.format(execute))
return subprocess.run(execute, check=True).returncode
except Exception as e:
upscaler_exceptions.append(e)

View File

@@ -0,0 +1,10 @@
#!/bin/sh
set -euxo pipefail
sudo podman run \
-it --rm --gpus all -v /dev/dri:/dev/dri \
-v $PWD/data:/host \
ghcr.io/k4yt3x/video2x:5.0.0-beta4-cuda \
-i input.mp4 -o output.mp4 \
interpolate

View File

@@ -0,0 +1,11 @@
#!/bin/sh
set -euxo pipefail
sudo podman run \
-it --rm --gpus all -v /dev/dri:/dev/dri \
-v $PWD/data:/host \
ghcr.io/k4yt3x/video2x:5.0.0-beta4-cuda \
-i input.mp4 -o output.mp4 \
-p5 upscale \
-h 720 -a waifu2x -n3

View File

@@ -0,0 +1,21 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# built-in imports
import pathlib
# import video2x
from video2x import Video2X
# create video2x object
video2x = Video2X()
# run upscale
video2x.interpolate(
pathlib.Path("input.mp4"), # input video path
pathlib.Path("output.mp4"), # another
3, # processes: number of parallel processors
10, # threshold: adjacent frames with > n% diff won't be processed (100 == process all)
"rife", # algorithm: the algorithm to use to process the video
)

24
examples/run_upscale_waifu2x.py Executable file
View File

@@ -0,0 +1,24 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# built-in imports
import pathlib
# import video2x
from video2x import Video2X
# create video2x object
video2x = Video2X()
# run upscale
video2x.upscale(
pathlib.Path("input.mp4"), # input video path
pathlib.Path("output.mp4"), # another
None, # width: width of output, None == auto
720, # height: height of output, None == auto
3, # noise: noise level, algorithm-dependent
5, # processes: number of parallel processors
0, # threshold: adjacent frames with < n% diff won't be processed (0 == process all)
"waifu2x", # algorithm: the algorithm to use to process the video
)

30
licenses/LICENSE-Pillow Normal file
View File

@@ -0,0 +1,30 @@
The Python Imaging Library (PIL) is
Copyright © 1997-2011 by Secret Labs AB
Copyright © 1995-2011 by Fredrik Lundh
Pillow is the friendly PIL fork. It is
Copyright © 2010-2022 by Alex Clark and contributors
Like PIL, Pillow is licensed under the open source HPND License:
By obtaining, using, and/or copying this software and/or its associated
documentation, you agree that you have read, understood, and will comply
with the following terms and conditions:
Permission to use, copy, modify, and distribute this software and its
associated documentation for any purpose and without fee is hereby granted,
provided that the above copyright notice appears in all copies, and that
both that copyright notice and this permission notice appear in supporting
documentation, and that the name of Secret Labs AB or the author not be
used in advertising or publicity pertaining to distribution of the software
without specific, written prior permission.
SECRET LABS AB AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
IN NO EVENT SHALL SECRET LABS AB OR THE AUTHOR BE LIABLE FOR ANY SPECIAL,
INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.

View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) Olli-Pekka Heinisuo
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2019 nihui
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

1743
licenses/LICENSE-rich Normal file

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2019 nihui
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2019 nihui
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2019 nihui
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

661
licenses/agpl-3.0.txt Normal file
View File

@@ -0,0 +1,661 @@
GNU AFFERO GENERAL PUBLIC LICENSE
Version 3, 19 November 2007
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU Affero General Public License is a free, copyleft license for
software and other kinds of works, specifically designed to ensure
cooperation with the community in the case of network server software.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
our General Public Licenses are intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
Developers that use our General Public Licenses protect your rights
with two steps: (1) assert copyright on the software, and (2) offer
you this License which gives you legal permission to copy, distribute
and/or modify the software.
A secondary benefit of defending all users' freedom is that
improvements made in alternate versions of the program, if they
receive widespread use, become available for other developers to
incorporate. Many developers of free software are heartened and
encouraged by the resulting cooperation. However, in the case of
software used on network servers, this result may fail to come about.
The GNU General Public License permits making a modified version and
letting the public access it on a server without ever releasing its
source code to the public.
The GNU Affero General Public License is designed specifically to
ensure that, in such cases, the modified source code becomes available
to the community. It requires the operator of a network server to
provide the source code of the modified version running there to the
users of that server. Therefore, public use of a modified version, on
a publicly accessible server, gives the public access to the source
code of the modified version.
An older license, called the Affero General Public License and
published by Affero, was designed to accomplish similar goals. This is
a different license, not a version of the Affero GPL, but Affero has
released a new version of the Affero GPL which permits relicensing under
this license.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU Affero General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Remote Network Interaction; Use with the GNU General Public License.
Notwithstanding any other provision of this License, if you modify the
Program, your modified version must prominently offer all users
interacting with it remotely through a computer network (if your version
supports such interaction) an opportunity to receive the Corresponding
Source of your version by providing access to the Corresponding Source
from a network server at no charge, through some standard or customary
means of facilitating copying of software. This Corresponding Source
shall include the Corresponding Source for any work covered by version 3
of the GNU General Public License that is incorporated pursuant to the
following paragraph.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the work with which it is combined will remain governed by version
3 of the GNU General Public License.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU Affero General Public License from time to time. Such new versions
will be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU Affero General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU Affero General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU Affero General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If your software can interact with users remotely through a computer
network, you should also make sure that it provides a way for users to
get its source. For example, if your program is a web application, its
interface could display a "Source" link that leads users to an archive
of the code. There are many ways you could offer source, and different
solutions will be better for different programs; see section 13 for the
specific requirements.
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU AGPL, see
<https://www.gnu.org/licenses/>.

201
licenses/apache-2.0.txt Normal file
View File

@@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright 2017 Karl Kroening
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

21
licenses/mit.txt Normal file
View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2017
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

533
pdm.lock generated Normal file
View File

@@ -0,0 +1,533 @@
[[package]]
name = "cmake"
version = "3.22.3"
summary = "CMake is an open-source, cross-platform family of tools designed to build, test and package software"
[[package]]
name = "cmake-build-extension"
version = "0.5.0"
requires_python = ">=3.6"
summary = "Setuptools extension to build and package CMake projects."
dependencies = [
"GitPython",
"cmake",
"ninja",
"setuptools-scm",
]
[[package]]
name = "colorama"
version = "0.4.4"
requires_python = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
summary = "Cross-platform colored terminal text."
[[package]]
name = "commonmark"
version = "0.9.1"
summary = "Python parser for the CommonMark Markdown spec"
[[package]]
name = "evdev"
version = "1.4.0"
summary = "Bindings to the Linux input handling subsystem"
[[package]]
name = "ffmpeg-python"
version = "0.2.0"
summary = "Python bindings for FFmpeg - with complex filtering support"
dependencies = [
"future",
]
[[package]]
name = "future"
version = "0.18.2"
requires_python = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*"
summary = "Clean single-source support for Python 3 and 2"
[[package]]
name = "gitdb"
version = "4.0.9"
requires_python = ">=3.6"
summary = "Git Object Database"
dependencies = [
"smmap<6,>=3.0.1",
]
[[package]]
name = "gitpython"
version = "3.1.27"
requires_python = ">=3.7"
summary = "GitPython is a python library used to interact with Git repositories"
dependencies = [
"gitdb<5,>=4.0.1",
"typing-extensions>=3.7.4.3; python_version < \"3.8\"",
]
[[package]]
name = "loguru"
version = "0.6.0"
requires_python = ">=3.5"
summary = "Python logging made (stupidly) simple"
dependencies = [
"colorama>=0.3.4; sys_platform == \"win32\"",
"win32-setctime>=1.0.0; sys_platform == \"win32\"",
]
[[package]]
name = "ninja"
version = "1.10.2.3"
summary = "Ninja is a small build system with a focus on speed"
[[package]]
name = "numpy"
version = "1.22.3"
requires_python = ">=3.8"
summary = "NumPy is the fundamental package for array computing with Python."
[[package]]
name = "opencv-python"
version = "4.5.5.64"
requires_python = ">=3.6"
summary = "Wrapper package for OpenCV python bindings."
dependencies = [
"numpy>=1.14.5; python_version >= \"3.7\"",
"numpy>=1.17.3; python_version >= \"3.8\"",
"numpy>=1.19.3; python_version >= \"3.6\" and platform_system == \"Linux\" and platform_machine == \"aarch64\"",
"numpy>=1.19.3; python_version >= \"3.9\"",
"numpy>=1.21.2; python_version >= \"3.10\"",
"numpy>=1.21.2; python_version >= \"3.6\" and platform_system == \"Darwin\" and platform_machine == \"arm64\"",
]
[[package]]
name = "packaging"
version = "21.3"
requires_python = ">=3.6"
summary = "Core utilities for Python packages"
dependencies = [
"pyparsing!=3.0.5,>=2.0.2",
]
[[package]]
name = "pillow"
version = "9.0.1"
requires_python = ">=3.7"
summary = "Python Imaging Library (Fork)"
[[package]]
name = "pygments"
version = "2.11.2"
requires_python = ">=3.5"
summary = "Pygments is a syntax highlighting package written in Python."
[[package]]
name = "pynput"
version = "1.7.6"
summary = "Monitor and control user input devices"
dependencies = [
"evdev>=1.3; \"linux\" in sys_platform",
"pyobjc-framework-ApplicationServices>=8.0; sys_platform == \"darwin\"",
"pyobjc-framework-Quartz>=8.0; sys_platform == \"darwin\"",
"python-xlib>=0.17; \"linux\" in sys_platform",
"six",
]
[[package]]
name = "pyobjc-core"
version = "8.4.1"
requires_python = ">=3.6"
summary = "Python<->ObjC Interoperability Module"
[[package]]
name = "pyobjc-framework-applicationservices"
version = "8.4.1"
requires_python = ">=3.6"
summary = "Wrappers for the framework ApplicationServices on macOS"
dependencies = [
"pyobjc-core>=8.4.1",
"pyobjc-framework-Cocoa>=8.4.1",
"pyobjc-framework-Quartz>=8.4.1",
]
[[package]]
name = "pyobjc-framework-cocoa"
version = "8.4.1"
requires_python = ">=3.6"
summary = "Wrappers for the Cocoa frameworks on macOS"
dependencies = [
"pyobjc-core>=8.4.1",
]
[[package]]
name = "pyobjc-framework-quartz"
version = "8.4.1"
requires_python = ">=3.6"
summary = "Wrappers for the Quartz frameworks on macOS"
dependencies = [
"pyobjc-core>=8.4.1",
"pyobjc-framework-Cocoa>=8.4.1",
]
[[package]]
name = "pyparsing"
version = "3.0.7"
requires_python = ">=3.6"
summary = "Python parsing module"
[[package]]
name = "python-xlib"
version = "0.31"
summary = "Python X Library"
dependencies = [
"six>=1.10.0",
]
[[package]]
name = "realcugan-ncnn-vulkan-python"
version = "1.0.0"
requires_python = ">=3.6"
summary = "A Python FFI of nihui/realcugan-ncnn-vulkan achieved with SWIG"
dependencies = [
"pillow",
]
[[package]]
name = "realsr-ncnn-vulkan-python"
version = "1.0.4"
requires_python = ">=3.6"
summary = "A Python FFI of nihui/realsr-ncnn-vulkan achieved with SWIG"
dependencies = [
"pillow",
]
[[package]]
name = "rich"
version = "12.0.0"
requires_python = ">=3.6.2,<4.0.0"
summary = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal"
dependencies = [
"commonmark<0.10.0,>=0.9.0",
"pygments<3.0.0,>=2.6.0",
"typing-extensions<5.0,>=3.7.4; python_version < \"3.8\"",
]
[[package]]
name = "rife-ncnn-vulkan-python"
version = "1.1.2.post3"
requires_python = ">=3.6"
summary = "A Python FFI of nihui/rife-ncnn-vulkan achieved with SWIG"
dependencies = [
"pillow",
]
[[package]]
name = "setuptools"
version = "60.10.0"
requires_python = ">=3.7"
summary = "Easily download, build, install, upgrade, and uninstall Python packages"
[[package]]
name = "setuptools-scm"
version = "6.4.2"
requires_python = ">=3.6"
summary = "the blessed package to manage your versions by scm tags"
dependencies = [
"packaging>=20.0",
"setuptools",
"tomli>=1.0.0",
]
[[package]]
name = "six"
version = "1.16.0"
requires_python = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*"
summary = "Python 2 and 3 compatibility utilities"
[[package]]
name = "smmap"
version = "5.0.0"
requires_python = ">=3.6"
summary = "A pure Python implementation of a sliding window memory map manager"
[[package]]
name = "srmd-ncnn-vulkan-python"
version = "1.0.2"
requires_python = ">=3.6"
summary = "A Python FFI of nihui/srmd-ncnn-vulkan achieved with SWIG"
dependencies = [
"pillow",
]
[[package]]
name = "tomli"
version = "2.0.1"
requires_python = ">=3.7"
summary = "A lil' TOML parser"
[[package]]
name = "typing-extensions"
version = "4.1.1"
requires_python = ">=3.6"
summary = "Backported and Experimental Type Hints for Python 3.6+"
[[package]]
name = "waifu2x-ncnn-vulkan-python"
version = "1.0.1"
requires_python = ">=3.6"
summary = "A Python FFI of nihui/waifu2x-ncnn-vulkan achieved with SWIG"
dependencies = [
"cmake",
"cmake-build-extension",
"pillow",
]
[[package]]
name = "win32-setctime"
version = "1.1.0"
requires_python = ">=3.5"
summary = "A small Python utility to set file creation time on Windows"
[metadata]
lock_version = "3.1"
content_hash = "sha256:f72fb9417f87c737f6a94710af1039611dc2d723d056e2479172fc6b695cab7c"
[metadata.files]
"cmake 3.22.3" = [
{file = "cmake-3.22.3-py2.py3-none-macosx_10_10_universal2.macosx_10_10_x86_64.macosx_11_0_arm64.macosx_11_0_universal2.whl", hash = "sha256:d387e4062541094d302c80b3beed08cfa4f2ef98454d04f34fd1071c595152d8"},
{file = "cmake-3.22.3-py2.py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9ff1a89c264a6645d5d222f73efe83ea47abc96d77ae96e3e4eb4580f6f396fc"},
{file = "cmake-3.22.3-py2.py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3adc8532f5029931e82c9ae6a07b5d866b216b422cedc72074155c80db6e27d7"},
{file = "cmake-3.22.3-py2.py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c46f0573b0455a234c397fff2f3679e18925eb3da32069cc41f1aab7cd968260"},
{file = "cmake-3.22.3-py2.py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:86c68b283223375ff942bce5b9f2b286fa5ac94b02f848e52fcec2369a407b22"},
{file = "cmake-3.22.3-py2.py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:452e53346d52241fbebdb9487e88786221c92d4abfa59fb002dc928ada69399c"},
{file = "cmake-3.22.3-py2.py3-none-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:fb5fbcb8b45c9f9823a1bffffe8eab673e463b8d36b258856035725e04baf446"},
{file = "cmake-3.22.3-py2.py3-none-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:e615d29c2c26faf7e3876c47bafbab0eefe29683e01bec3a14736e9694bdff73"},
{file = "cmake-3.22.3-py2.py3-none-musllinux_1_1_aarch64.whl", hash = "sha256:1d6096da730d2d0c8352926b647d0d340fc2ea3a6497dd13cff1c999d68d9d7b"},
{file = "cmake-3.22.3-py2.py3-none-musllinux_1_1_i686.whl", hash = "sha256:d3be0f5256bfe76c81d2db30216c937a7f7cefd251fb63c1cb30c5e0a896bbad"},
{file = "cmake-3.22.3-py2.py3-none-musllinux_1_1_ppc64le.whl", hash = "sha256:d73961a801ea9e2fdda9afa3b9fc84539e368ecec30de1ef54045abfabce4ece"},
{file = "cmake-3.22.3-py2.py3-none-musllinux_1_1_s390x.whl", hash = "sha256:45e89f6ff37283ecff912c7fe65dc4bc6dfe2fb78b7747b95272dd7423a3847f"},
{file = "cmake-3.22.3-py2.py3-none-musllinux_1_1_x86_64.whl", hash = "sha256:c776ad422f7ce3866497f132af4ba7240cb81d554ee5eb801fd5e2d8c7cd67d6"},
{file = "cmake-3.22.3-py2.py3-none-win32.whl", hash = "sha256:8d32168fb3153313408befc7b8b5593130bad7d5fe0b8df764bb723b8c710bfc"},
{file = "cmake-3.22.3-py2.py3-none-win_amd64.whl", hash = "sha256:d8db320fb36560fcf2ca66481009bc1d1f8ed45fd756ce91e4dee97026a0e3a4"},
{file = "cmake-3.22.3.tar.gz", hash = "sha256:6e1d1991775915dac047af851f2feec7eb35ab4b4610d3e7fd94d93bce8faf58"},
]
"cmake-build-extension 0.5.0" = [
{file = "cmake_build_extension-0.5.0-py3-none-any.whl", hash = "sha256:b11b8c140ef0a7595576c8a8f807dbae30924e78f92cdecd5be8060087a84e88"},
{file = "cmake-build-extension-0.5.0.tar.gz", hash = "sha256:75a8e866544976e213aad31799f6a9b68a5135cf37cc41af29c1706446d56155"},
]
"colorama 0.4.4" = [
{file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"},
{file = "colorama-0.4.4.tar.gz", hash = "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b"},
]
"commonmark 0.9.1" = [
{file = "commonmark-0.9.1-py2.py3-none-any.whl", hash = "sha256:da2f38c92590f83de410ba1a3cbceafbc74fee9def35f9251ba9a971d6d66fd9"},
{file = "commonmark-0.9.1.tar.gz", hash = "sha256:452f9dc859be7f06631ddcb328b6919c67984aca654e5fefb3914d54691aed60"},
]
"evdev 1.4.0" = [
{file = "evdev-1.4.0.tar.gz", hash = "sha256:8782740eb1a86b187334c07feb5127d3faa0b236e113206dfe3ae8f77fb1aaf1"},
]
"ffmpeg-python 0.2.0" = [
{file = "ffmpeg_python-0.2.0-py3-none-any.whl", hash = "sha256:ac441a0404e053f8b6a1113a77c0f452f1cfc62f6344a769475ffdc0f56c23c5"},
{file = "ffmpeg-python-0.2.0.tar.gz", hash = "sha256:65225db34627c578ef0e11c8b1eb528bb35e024752f6f10b78c011f6f64c4127"},
]
"future 0.18.2" = [
{file = "future-0.18.2.tar.gz", hash = "sha256:b1bead90b70cf6ec3f0710ae53a525360fa360d306a86583adc6bf83a4db537d"},
]
"gitdb 4.0.9" = [
{file = "gitdb-4.0.9-py3-none-any.whl", hash = "sha256:8033ad4e853066ba6ca92050b9df2f89301b8fc8bf7e9324d412a63f8bf1a8fd"},
{file = "gitdb-4.0.9.tar.gz", hash = "sha256:bac2fd45c0a1c9cf619e63a90d62bdc63892ef92387424b855792a6cabe789aa"},
]
"gitpython 3.1.27" = [
{file = "GitPython-3.1.27-py3-none-any.whl", hash = "sha256:5b68b000463593e05ff2b261acff0ff0972df8ab1b70d3cdbd41b546c8b8fc3d"},
{file = "GitPython-3.1.27.tar.gz", hash = "sha256:1c885ce809e8ba2d88a29befeb385fcea06338d3640712b59ca623c220bb5704"},
]
"loguru 0.6.0" = [
{file = "loguru-0.6.0-py3-none-any.whl", hash = "sha256:4e2414d534a2ab57573365b3e6d0234dfb1d84b68b7f3b948e6fb743860a77c3"},
{file = "loguru-0.6.0.tar.gz", hash = "sha256:066bd06758d0a513e9836fd9c6b5a75bfb3fd36841f4b996bc60b547a309d41c"},
]
"ninja 1.10.2.3" = [
{file = "ninja-1.10.2.3-py2.py3-none-macosx_10_9_universal2.macosx_10_9_x86_64.macosx_11_0_arm64.macosx_11_0_universal2.whl", hash = "sha256:d5e0275d28997a750a4f445c00bdd357b35cc334c13cdff13edf30e544704fbd"},
{file = "ninja-1.10.2.3-py2.py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5ea785bf6a15727040835256577239fa3cf5da0d60e618c307aa5efc31a1f0ce"},
{file = "ninja-1.10.2.3-py2.py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:29570a18d697fc84d361e7e6330f0021f34603ae0fcb0ef67ae781e9814aae8d"},
{file = "ninja-1.10.2.3-py2.py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:21a1d84d4c7df5881bfd86c25cce4cf7af44ba2b8b255c57bc1c434ec30a2dfc"},
{file = "ninja-1.10.2.3-py2.py3-none-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9ca8dbece144366d5f575ffc657af03eb11c58251268405bc8519d11cf42f113"},
{file = "ninja-1.10.2.3-py2.py3-none-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:279836285975e3519392c93c26e75755e8a8a7fafec9f4ecbb0293119ee0f9c6"},
{file = "ninja-1.10.2.3-py2.py3-none-musllinux_1_1_aarch64.whl", hash = "sha256:cc8b31b5509a2129e4d12a35fc21238c157038022560aaf22e49ef0a77039086"},
{file = "ninja-1.10.2.3-py2.py3-none-musllinux_1_1_i686.whl", hash = "sha256:688167841b088b6802e006f911d911ffa925e078c73e8ef2f88286107d3204f8"},
{file = "ninja-1.10.2.3-py2.py3-none-musllinux_1_1_ppc64le.whl", hash = "sha256:840a0b042d43a8552c4004966e18271ec726e5996578f28345d9ce78e225b67e"},
{file = "ninja-1.10.2.3-py2.py3-none-musllinux_1_1_s390x.whl", hash = "sha256:84be6f9ec49f635dc40d4b871319a49fa49b8d55f1d9eae7cd50d8e57ddf7a85"},
{file = "ninja-1.10.2.3-py2.py3-none-musllinux_1_1_x86_64.whl", hash = "sha256:6bd76a025f26b9ae507cf8b2b01bb25bb0031df54ed685d85fc559c411c86cf4"},
{file = "ninja-1.10.2.3-py2.py3-none-win32.whl", hash = "sha256:740d61fefb4ca13573704ee8fe89b973d40b8dc2a51aaa4e9e68367233743bb6"},
{file = "ninja-1.10.2.3-py2.py3-none-win_amd64.whl", hash = "sha256:0560eea57199e41e86ac2c1af0108b63ae77c3ca4d05a9425a750e908135935a"},
{file = "ninja-1.10.2.3.tar.gz", hash = "sha256:e1b86ad50d4e681a7dbdff05fc23bb52cb773edb90bc428efba33fa027738408"},
]
"numpy 1.22.3" = [
{file = "numpy-1.22.3-cp310-cp310-macosx_10_14_x86_64.whl", hash = "sha256:92bfa69cfbdf7dfc3040978ad09a48091143cffb778ec3b03fa170c494118d75"},
{file = "numpy-1.22.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8251ed96f38b47b4295b1ae51631de7ffa8260b5b087808ef09a39a9d66c97ab"},
{file = "numpy-1.22.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:48a3aecd3b997bf452a2dedb11f4e79bc5bfd21a1d4cc760e703c31d57c84b3e"},
{file = "numpy-1.22.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a3bae1a2ed00e90b3ba5f7bd0a7c7999b55d609e0c54ceb2b076a25e345fa9f4"},
{file = "numpy-1.22.3-cp310-cp310-win32.whl", hash = "sha256:f950f8845b480cffe522913d35567e29dd381b0dc7e4ce6a4a9f9156417d2430"},
{file = "numpy-1.22.3-cp310-cp310-win_amd64.whl", hash = "sha256:08d9b008d0156c70dc392bb3ab3abb6e7a711383c3247b410b39962263576cd4"},
{file = "numpy-1.22.3-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:201b4d0552831f7250a08d3b38de0d989d6f6e4658b709a02a73c524ccc6ffce"},
{file = "numpy-1.22.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:f8c1f39caad2c896bc0018f699882b345b2a63708008be29b1f355ebf6f933fe"},
{file = "numpy-1.22.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:568dfd16224abddafb1cbcce2ff14f522abe037268514dd7e42c6776a1c3f8e5"},
{file = "numpy-1.22.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ca688e1b9b95d80250bca34b11a05e389b1420d00e87a0d12dc45f131f704a1"},
{file = "numpy-1.22.3-cp38-cp38-win32.whl", hash = "sha256:e7927a589df200c5e23c57970bafbd0cd322459aa7b1ff73b7c2e84d6e3eae62"},
{file = "numpy-1.22.3-cp38-cp38-win_amd64.whl", hash = "sha256:07a8c89a04997625236c5ecb7afe35a02af3896c8aa01890a849913a2309c676"},
{file = "numpy-1.22.3-cp39-cp39-macosx_10_14_x86_64.whl", hash = "sha256:2c10a93606e0b4b95c9b04b77dc349b398fdfbda382d2a39ba5a822f669a0123"},
{file = "numpy-1.22.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:fade0d4f4d292b6f39951b6836d7a3c7ef5b2347f3c420cd9820a1d90d794802"},
{file = "numpy-1.22.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5bfb1bb598e8229c2d5d48db1860bcf4311337864ea3efdbe1171fb0c5da515d"},
{file = "numpy-1.22.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:97098b95aa4e418529099c26558eeb8486e66bd1e53a6b606d684d0c3616b168"},
{file = "numpy-1.22.3-cp39-cp39-win32.whl", hash = "sha256:fdf3c08bce27132395d3c3ba1503cac12e17282358cb4bddc25cc46b0aca07aa"},
{file = "numpy-1.22.3-cp39-cp39-win_amd64.whl", hash = "sha256:639b54cdf6aa4f82fe37ebf70401bbb74b8508fddcf4797f9fe59615b8c5813a"},
{file = "numpy-1.22.3-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c34ea7e9d13a70bf2ab64a2532fe149a9aced424cd05a2c4ba662fd989e3e45f"},
{file = "numpy-1.22.3.zip", hash = "sha256:dbc7601a3b7472d559dc7b933b18b4b66f9aa7452c120e87dfb33d02008c8a18"},
]
"opencv-python 4.5.5.64" = [
{file = "opencv_python-4.5.5.64-cp36-abi3-macosx_10_15_x86_64.whl", hash = "sha256:a512a0c59b6fec0fac3844b2f47d6ecb1a9d18d235e6c5491ce8dbbe0663eae8"},
{file = "opencv_python-4.5.5.64-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ca6138b6903910e384067d001763d40f97656875487381aed32993b076f44375"},
{file = "opencv_python-4.5.5.64-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b293ced62f4360d9f11cf72ae7e9df95320ff7bf5b834d87546f844e838c0c35"},
{file = "opencv_python-4.5.5.64-cp36-abi3-win32.whl", hash = "sha256:6247e584813c00c3b9ed69a795da40d2c153dc923d0182e957e1c2f00a554ac2"},
{file = "opencv_python-4.5.5.64-cp36-abi3-win_amd64.whl", hash = "sha256:408d5332550287aa797fd06bef47b2dfed163c6787668cc82ef9123a9484b56a"},
{file = "opencv_python-4.5.5.64-cp37-abi3-macosx_11_0_arm64.whl", hash = "sha256:7787bb017ae93d5f9bb1b817ac8e13e45dd193743cb648498fcab21d00cf20a3"},
{file = "opencv-python-4.5.5.64.tar.gz", hash = "sha256:f65de0446a330c3b773cd04ba10345d8ce1b15dcac3f49770204e37602d0b3f7"},
]
"packaging 21.3" = [
{file = "packaging-21.3-py3-none-any.whl", hash = "sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522"},
{file = "packaging-21.3.tar.gz", hash = "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb"},
]
"pillow 9.0.1" = [
{file = "Pillow-9.0.1-1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a5d24e1d674dd9d72c66ad3ea9131322819ff86250b30dc5821cbafcfa0b96b4"},
{file = "Pillow-9.0.1-1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:2632d0f846b7c7600edf53c48f8f9f1e13e62f66a6dbc15191029d950bfed976"},
{file = "Pillow-9.0.1-1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b9618823bd237c0d2575283f2939655f54d51b4527ec3972907a927acbcc5bfc"},
{file = "Pillow-9.0.1-cp310-cp310-macosx_10_10_universal2.whl", hash = "sha256:9bfdb82cdfeccec50aad441afc332faf8606dfa5e8efd18a6692b5d6e79f00fd"},
{file = "Pillow-9.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5100b45a4638e3c00e4d2320d3193bdabb2d75e79793af7c3eb139e4f569f16f"},
{file = "Pillow-9.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:528a2a692c65dd5cafc130de286030af251d2ee0483a5bf50c9348aefe834e8a"},
{file = "Pillow-9.0.1-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0f29d831e2151e0b7b39981756d201f7108d3d215896212ffe2e992d06bfe049"},
{file = "Pillow-9.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:855c583f268edde09474b081e3ddcd5cf3b20c12f26e0d434e1386cc5d318e7a"},
{file = "Pillow-9.0.1-cp310-cp310-win32.whl", hash = "sha256:d9d7942b624b04b895cb95af03a23407f17646815495ce4547f0e60e0b06f58e"},
{file = "Pillow-9.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:81c4b81611e3a3cb30e59b0cf05b888c675f97e3adb2c8672c3154047980726b"},
{file = "Pillow-9.0.1-cp37-cp37m-macosx_10_10_x86_64.whl", hash = "sha256:413ce0bbf9fc6278b2d63309dfeefe452835e1c78398efb431bab0672fe9274e"},
{file = "Pillow-9.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:80fe64a6deb6fcfdf7b8386f2cf216d329be6f2781f7d90304351811fb591360"},
{file = "Pillow-9.0.1-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cef9c85ccbe9bee00909758936ea841ef12035296c748aaceee535969e27d31b"},
{file = "Pillow-9.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1d19397351f73a88904ad1aee421e800fe4bbcd1aeee6435fb62d0a05ccd1030"},
{file = "Pillow-9.0.1-cp37-cp37m-win32.whl", hash = "sha256:d21237d0cd37acded35154e29aec853e945950321dd2ffd1a7d86fe686814669"},
{file = "Pillow-9.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:ede5af4a2702444a832a800b8eb7f0a7a1c0eed55b644642e049c98d589e5092"},
{file = "Pillow-9.0.1-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:b5b3f092fe345c03bca1e0b687dfbb39364b21ebb8ba90e3fa707374b7915204"},
{file = "Pillow-9.0.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:335ace1a22325395c4ea88e00ba3dc89ca029bd66bd5a3c382d53e44f0ccd77e"},
{file = "Pillow-9.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:db6d9fac65bd08cea7f3540b899977c6dee9edad959fa4eaf305940d9cbd861c"},
{file = "Pillow-9.0.1-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f154d173286a5d1863637a7dcd8c3437bb557520b01bddb0be0258dcb72696b5"},
{file = "Pillow-9.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:14d4b1341ac07ae07eb2cc682f459bec932a380c3b122f5540432d8977e64eae"},
{file = "Pillow-9.0.1-cp38-cp38-win32.whl", hash = "sha256:effb7749713d5317478bb3acb3f81d9d7c7f86726d41c1facca068a04cf5bb4c"},
{file = "Pillow-9.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:7f7609a718b177bf171ac93cea9fd2ddc0e03e84d8fa4e887bdfc39671d46b00"},
{file = "Pillow-9.0.1-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:80ca33961ced9c63358056bd08403ff866512038883e74f3a4bf88ad3eb66838"},
{file = "Pillow-9.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1c3c33ac69cf059bbb9d1a71eeaba76781b450bc307e2291f8a4764d779a6b28"},
{file = "Pillow-9.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:12875d118f21cf35604176872447cdb57b07126750a33748bac15e77f90f1f9c"},
{file = "Pillow-9.0.1-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:514ceac913076feefbeaf89771fd6febde78b0c4c1b23aaeab082c41c694e81b"},
{file = "Pillow-9.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d3c5c79ab7dfce6d88f1ba639b77e77a17ea33a01b07b99840d6ed08031cb2a7"},
{file = "Pillow-9.0.1-cp39-cp39-win32.whl", hash = "sha256:718856856ba31f14f13ba885ff13874be7fefc53984d2832458f12c38205f7f7"},
{file = "Pillow-9.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:f25ed6e28ddf50de7e7ea99d7a976d6a9c415f03adcaac9c41ff6ff41b6d86ac"},
{file = "Pillow-9.0.1-pp37-pypy37_pp73-macosx_10_10_x86_64.whl", hash = "sha256:011233e0c42a4a7836498e98c1acf5e744c96a67dd5032a6f666cc1fb97eab97"},
{file = "Pillow-9.0.1-pp37-pypy37_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:253e8a302a96df6927310a9d44e6103055e8fb96a6822f8b7f514bb7ef77de56"},
{file = "Pillow-9.0.1-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6295f6763749b89c994fcb6d8a7f7ce03c3992e695f89f00b741b4580b199b7e"},
{file = "Pillow-9.0.1-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:a9f44cd7e162ac6191491d7249cceb02b8116b0f7e847ee33f739d7cb1ea1f70"},
{file = "Pillow-9.0.1.tar.gz", hash = "sha256:6c8bc8238a7dfdaf7a75f5ec5a663f4173f8c367e5a39f87e720495e1eed75fa"},
]
"pygments 2.11.2" = [
{file = "Pygments-2.11.2-py3-none-any.whl", hash = "sha256:44238f1b60a76d78fc8ca0528ee429702aae011c265fe6a8dd8b63049ae41c65"},
{file = "Pygments-2.11.2.tar.gz", hash = "sha256:4e426f72023d88d03b2fa258de560726ce890ff3b630f88c21cbb8b2503b8c6a"},
]
"pynput 1.7.6" = [
{file = "pynput-1.7.6-py2.py3-none-any.whl", hash = "sha256:19861b2a0c430d646489852f89500e0c9332e295f2c020e7c2775e7046aa2e2f"},
{file = "pynput-1.7.6.tar.gz", hash = "sha256:3a5726546da54116b687785d38b1db56997ce1d28e53e8d22fc656d8b92e533c"},
]
"pyobjc-core 8.4.1" = [
{file = "pyobjc_core-8.4.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:9a89cac910fbd64728fe7ec0c7a3a7cf20959bc1d7e2f41db4d7800556e47745"},
{file = "pyobjc_core-8.4.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:2cf1d4348cb99fcba04fa38199a46e35263b2fe7bb66e6dfbd4f19bc2602998d"},
{file = "pyobjc_core-8.4.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:a130324b25c0f5f4cfe30b6a28b8e70865d6e1eee158caababb603906ef431d2"},
{file = "pyobjc_core-8.4.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:c31195d1a8f00da99abf79643f902d09c709dbbe9c9b6feb6b585303c57d720c"},
{file = "pyobjc_core-8.4.1-cp38-cp38-macosx_11_0_universal2.whl", hash = "sha256:e7fd2aefb53a96a8f688c8bb36c6ebd5446250a7251bfa6b688a045e05afc60b"},
{file = "pyobjc_core-8.4.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:b3191173ce268e23c84d84f036fc94c3a8749a6726fc7fe73baf27dbac14f7d0"},
{file = "pyobjc-core-8.4.1.tar.gz", hash = "sha256:df98669e957adb33566d9ef46773a5ac876a81afe8849c282d6a80448e35dd74"},
]
"pyobjc-framework-applicationservices 8.4.1" = [
{file = "pyobjc_framework_ApplicationServices-8.4.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:362d178c624a617fc60c3a35397550193d82da9a59272b215cf1dc6fb68c011c"},
{file = "pyobjc_framework_ApplicationServices-8.4.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:41f0f6be6d343f91de92cab053be4a983e3936b364ca267a94c6e06bc34ff7fe"},
{file = "pyobjc_framework_ApplicationServices-8.4.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:73287b758a70a037b6e74a60036f4adb1677407dfeaddee94102074d92539e6e"},
{file = "pyobjc_framework_ApplicationServices-8.4.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:287b541b66c5c931a11dde90d7be69ddd2e5c3624c2e980e679f5242ec3ee0da"},
{file = "pyobjc_framework_ApplicationServices-8.4.1-cp38-cp38-macosx_11_0_universal2.whl", hash = "sha256:780fbe2e3b02237f79e2f5780094dd95b7308ecdb265c062b78a507b9564eb4d"},
{file = "pyobjc_framework_ApplicationServices-8.4.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:092c4835e73e5dab1f3c498511b28b2e96503671fc7c1bc25f732c5e687b7214"},
{file = "pyobjc-framework-ApplicationServices-8.4.1.tar.gz", hash = "sha256:b058466266412d2bf24b0303785c91538961367f26db616bf2f9f45c498a83a3"},
]
"pyobjc-framework-cocoa 8.4.1" = [
{file = "pyobjc_framework_Cocoa-8.4.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:cfbe038a0108ae1b45f8f7067af70af5811b8352d2dc3d86a7bcb4484ff5d56e"},
{file = "pyobjc_framework_Cocoa-8.4.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:118225562064d991bafb41d0913899d6b3d723984d1888cb7181e4dba63b22c2"},
{file = "pyobjc_framework_Cocoa-8.4.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:d117a1eb24fd317e9f63792ac6a8703ed899de5d42e8a861c7bf885625668c31"},
{file = "pyobjc_framework_Cocoa-8.4.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:3af8577acbd6b980d3b9270ec99bc0164f66ef8397351a72fcdee527f23c1a34"},
{file = "pyobjc_framework_Cocoa-8.4.1-cp38-cp38-macosx_11_0_universal2.whl", hash = "sha256:91fdc964acb4dee4d37ae81fb603d48397739dbbfcc1eadbe0cdafaa8144b6e6"},
{file = "pyobjc_framework_Cocoa-8.4.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:197dd28668e786b55d7d4139afd85c285f780564ebbccc166e84a24be31de34f"},
{file = "pyobjc-framework-Cocoa-8.4.1.tar.gz", hash = "sha256:dc596bac0f5d424f67944e95b2d0d7c94a07c4166359d7b4a4d4ae4f8e112822"},
]
"pyobjc-framework-quartz 8.4.1" = [
{file = "pyobjc_framework_Quartz-8.4.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a82d9eab3b2a6fca46602465f731815026d06e4fd0ba65b5b5211f1a0472b861"},
{file = "pyobjc_framework_Quartz-8.4.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:1bd0a506385141b81330464b6e2537a7056cdca56deb98222b6926a04f72a3e6"},
{file = "pyobjc_framework_Quartz-8.4.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:64cc616386b7a387dce53d3adb8c12a8461c2720861ab36aeeb53768cd0ba7e4"},
{file = "pyobjc_framework_Quartz-8.4.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:a2dff998c4d1286998390f58a3131b99bdc9dbf5c3d881562b33f168098bbe2e"},
{file = "pyobjc_framework_Quartz-8.4.1-cp38-cp38-macosx_11_0_universal2.whl", hash = "sha256:a98c58e1b265d5b413f5ecc6ec186b9e305fb6e37909d8b4b97fd681176f5f1c"},
{file = "pyobjc_framework_Quartz-8.4.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:39f55426ef883cbe12a53969f90886f71e2a94513c98cf3730efdf404cdc5c83"},
{file = "pyobjc-framework-Quartz-8.4.1.tar.gz", hash = "sha256:f8acebf0b526f0687e79ea6946e8f2528ced4ef02d0ed3fbf7116124b2749e52"},
]
"pyparsing 3.0.7" = [
{file = "pyparsing-3.0.7-py3-none-any.whl", hash = "sha256:a6c06a88f252e6c322f65faf8f418b16213b51bdfaece0524c1c1bc30c63c484"},
{file = "pyparsing-3.0.7.tar.gz", hash = "sha256:18ee9022775d270c55187733956460083db60b37d0d0fb357445f3094eed3eea"},
]
"python-xlib 0.31" = [
{file = "python_xlib-0.31-py2.py3-none-any.whl", hash = "sha256:1ec6ce0de73d9e6592ead666779a5732b384e5b8fb1f1886bd0a81cafa477759"},
{file = "python-xlib-0.31.tar.gz", hash = "sha256:74d83a081f532bc07f6d7afcd6416ec38403d68f68b9b9dc9e1f28fbf2d799e9"},
]
"realcugan-ncnn-vulkan-python 1.0.0" = [
{file = "realcugan-ncnn-vulkan-python-1.0.0.tar.gz", hash = "sha256:f72764ffe0a0c53b13cdbe1ae328ff9b0eb5582b9d5d15a0ca0c0ac254d17410"},
]
"realsr-ncnn-vulkan-python 1.0.4" = [
{file = "realsr-ncnn-vulkan-python-1.0.4.tar.gz", hash = "sha256:bbfd9fc067cfea6ab28e8074f1d6aadcc7f927f166d90fab9dcc46380b7ef02d"},
]
"rich 12.0.0" = [
{file = "rich-12.0.0-py3-none-any.whl", hash = "sha256:fdcd2f8d416e152bcf35c659987038d1ae5a7bd336e821ca7551858a4c7e38a9"},
{file = "rich-12.0.0.tar.gz", hash = "sha256:14bfd0507edc633e021b02c45cbf7ca22e33b513817627b8de3412f047a3e798"},
]
"rife-ncnn-vulkan-python 1.1.2.post3" = [
{file = "rife-ncnn-vulkan-python-1.1.2.post3.tar.gz", hash = "sha256:df66d1f83bc6beacac33b0e384ee352b45fa39931b9e1ff8247b396d4d7a486d"},
]
"setuptools 60.10.0" = [
{file = "setuptools-60.10.0-py3-none-any.whl", hash = "sha256:782ef48d58982ddb49920c11a0c5c9c0b02e7d7d1c2ad0aa44e1a1e133051c96"},
{file = "setuptools-60.10.0.tar.gz", hash = "sha256:6599055eeb23bfef457d5605d33a4d68804266e6cb430b0fb12417c5efeae36c"},
]
"setuptools-scm 6.4.2" = [
{file = "setuptools_scm-6.4.2-py3-none-any.whl", hash = "sha256:acea13255093849de7ccb11af9e1fb8bde7067783450cee9ef7a93139bddf6d4"},
{file = "setuptools_scm-6.4.2.tar.gz", hash = "sha256:6833ac65c6ed9711a4d5d2266f8024cfa07c533a0e55f4c12f6eff280a5a9e30"},
]
"six 1.16.0" = [
{file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"},
{file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"},
]
"smmap 5.0.0" = [
{file = "smmap-5.0.0-py3-none-any.whl", hash = "sha256:2aba19d6a040e78d8b09de5c57e96207b09ed71d8e55ce0959eeee6c8e190d94"},
{file = "smmap-5.0.0.tar.gz", hash = "sha256:c840e62059cd3be204b0c9c9f74be2c09d5648eddd4580d9314c3ecde0b30936"},
]
"srmd-ncnn-vulkan-python 1.0.2" = [
{file = "srmd-ncnn-vulkan-python-1.0.2.tar.gz", hash = "sha256:3c7f71cbba2b6310c4b14c2b11dae7737582ac004893f8c9cc3f7c305c7bbe49"},
]
"tomli 2.0.1" = [
{file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"},
{file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"},
]
"typing-extensions 4.1.1" = [
{file = "typing_extensions-4.1.1-py3-none-any.whl", hash = "sha256:21c85e0fe4b9a155d0799430b0ad741cdce7e359660ccbd8b530613e8df88ce2"},
{file = "typing_extensions-4.1.1.tar.gz", hash = "sha256:1a9462dcc3347a79b1f1c0271fbe79e844580bb598bafa1ed208b94da3cdcd42"},
]
"waifu2x-ncnn-vulkan-python 1.0.1" = [
{file = "waifu2x-ncnn-vulkan-python-1.0.1.tar.gz", hash = "sha256:18dbdd00141fc427a5ef8996f0a0197f1d6f3086a7c60bb88934e1d2a3004801"},
]
"win32-setctime 1.1.0" = [
{file = "win32_setctime-1.1.0-py3-none-any.whl", hash = "sha256:231db239e959c2fe7eb1d7dc129f11172354f98361c4fa2d6d2d7e278baa8aad"},
{file = "win32_setctime-1.1.0.tar.gz", hash = "sha256:15cf5750465118d6929ae4de4eb46e8edae9a5634350c01ba582df868e932cb2"},
]

56
pyproject.toml Normal file
View File

@@ -0,0 +1,56 @@
[project]
name = "video2x"
description = "A video/image upscaling and frame interpolation framework"
readme = "README.md"
requires-python = ">=3.7"
license = { text = "AGPL-3.0-or-later" }
keywords = [
"super-resolution",
"upscaling",
"neural-network",
"machine-learning",
]
authors = [{ name = "K4YT3X", email = "i@k4yt3x.com" }]
classifiers = [
"Environment :: Console",
"Operating System :: OS Independent",
"Programming Language :: Python",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.6",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Topic :: Multimedia :: Video",
"Topic :: Scientific/Engineering :: Image Processing",
]
dependencies = [
"ffmpeg-python>=0.2.0",
"loguru>=0.6.0",
"opencv-python>=4.5.5.64",
"pillow>=9.0.1",
"rich>=12.0.0",
"waifu2x-ncnn-vulkan-python>=1.0.2rc3",
"srmd-ncnn-vulkan-python>=1.0.2",
"realsr-ncnn-vulkan-python>=1.0.4",
"rife-ncnn-vulkan-python>=1.1.2.post3",
"realcugan-ncnn-vulkan-python>=1.0.0",
"pynput>=1.7.6",
]
dynamic = ["version"]
[project.urls]
homepage = "https://github.com/k4yt3x/video2x/"
documentation = "https://github.com/k4yt3x/video2x/wiki"
repository = "https://github.com/k4yt3x/video2x.git"
changelog = "https://github.com/k4yt3x/video2x/releases"
[project.scripts]
video2x = "video2x:main"
[tool.pdm]
version = { from = "video2x/__init__.py" }
[build-system]
requires = ["pdm-pep517"]
build-backend = "pdm.pep517.api"

View File

@@ -0,0 +1,19 @@
#!/bin/sh
# mount the current (video2x repo root) directory into a container
# with drivers installed so the code can be debugged in the container
# this one launches an interactive shell instead of Python
set -euo pipefail
sudo podman run -it --rm \
--gpus all -v /dev/dri:/dev/dri \
-v $PWD:/host \
-m 15g \
--cpus 0.9 \
-v $HOME/projects/media2x/video2x:/video2x \
-e PYTHONPATH=/video2x \
-e PYTHONDONTWRITEBYTECODE=1 \
--entrypoint=/bin/bash \
ghcr.io/k4yt3x/video2x:5.0.0-beta4-cuda
# alias upscale='python3 -m video2x -i /host/input-large.mp4 -o /host/output-large.mp4 -p3 upscale -h 1440 -d waifu2x -n3'

View File

@@ -0,0 +1,19 @@
#!/bin/sh
# mount the current (video2x repo root) directory into a container
# with drivers installed so the code can be debugged in the container
set -euo pipefail
sudo podman run -it --rm \
--gpus all -v /dev/dri:/dev/dri \
-v $PWD:/host \
-m 15g \
--cpus 0.9 \
-v $HOME/projects/media2x/video2x:/video2x \
-e PYTHONPATH=/video2x \
-e PYTHONDONTWRITEBYTECODE=1 \
ghcr.io/k4yt3x/video2x:5.0.0-beta4-cuda \
-i data/input.mp4 -o data/output.mp4 \
-p3 \
upscale \
-h 1440 -a waifu2x -n3

31
video2x/__init__.py Executable file
View File

@@ -0,0 +1,31 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Copyright (C) 2018-2022 K4YT3X and contributors.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
Name: Package Init
Author: K4YT3X
Date Created: July 3, 2021
Last Modified: February 16, 2022
"""
# version assignment has to precede imports to
# prevent setup.cfg from producing import errors
__version__ = "5.0.0-beta5"
from .interpolator import Interpolator
from .upscaler import Upscaler
from .video2x import Video2X

30
video2x/__main__.py Executable file
View File

@@ -0,0 +1,30 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Copyright (C) 2018-2022 K4YT3X and contributors.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
Name: Package Main
Author: K4YT3X
Date Created: July 3, 2021
Last Modified: February 26, 2022
"""
import sys
from .video2x import main
if __name__ == "__main__":
sys.exit(main())

198
video2x/decoder.py Executable file
View File

@@ -0,0 +1,198 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Copyright (C) 2018-2022 K4YT3X and contributors.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
Name: Video Decoder
Author: K4YT3X
Date Created: June 17, 2021
Last Modified: March 21, 2022
"""
import contextlib
import multiprocessing
import os
import pathlib
import queue
import signal
import subprocess
import threading
import time
from multiprocessing.sharedctypes import Synchronized
import ffmpeg
from loguru import logger
from PIL import Image
from .pipe_printer import PipePrinter
# map Loguru log levels to FFmpeg log levels
LOGURU_FFMPEG_LOGLEVELS = {
"trace": "trace",
"debug": "debug",
"info": "info",
"success": "info",
"warning": "warning",
"error": "error",
"critical": "fatal",
}
class VideoDecoder(threading.Thread):
def __init__(
self,
input_path: pathlib.Path,
input_width: int,
input_height: int,
frame_rate: float,
processing_queue: multiprocessing.Queue,
processing_settings: tuple,
pause: Synchronized,
ignore_max_image_pixels=True,
) -> None:
threading.Thread.__init__(self)
self.running = False
self.input_path = input_path
self.input_width = input_width
self.input_height = input_height
self.processing_queue = processing_queue
self.processing_settings = processing_settings
self.pause = pause
# this disables the "possible DDoS" warning
if ignore_max_image_pixels:
Image.MAX_IMAGE_PIXELS = None
self.exception = None
self.decoder = subprocess.Popen(
ffmpeg.compile(
ffmpeg.input(input_path, r=frame_rate)["v"]
.output("pipe:1", format="rawvideo", pix_fmt="rgb24", vsync="cfr")
.global_args("-hide_banner")
.global_args("-nostats")
.global_args("-nostdin")
.global_args(
"-loglevel",
LOGURU_FFMPEG_LOGLEVELS.get(
os.environ.get("LOGURU_LEVEL", "INFO").lower()
),
),
overwrite_output=True,
),
env={"AV_LOG_FORCE_COLOR": "TRUE"},
stdin=subprocess.DEVNULL,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
)
# start the PIPE printer to start printing FFmpeg logs
self.pipe_printer = PipePrinter(self.decoder.stderr)
self.pipe_printer.start()
def run(self) -> None:
self.running = True
# the index of the frame
frame_index = 0
# create placeholder for previous frame
# used in interpolate mode
previous_image = None
# continue running until an exception occurs
# or all frames have been decoded
while self.running:
# pause if pause flag is set
if self.pause.value is True:
time.sleep(0.1)
continue
try:
buffer = self.decoder.stdout.read(
3 * self.input_width * self.input_height
)
# source depleted (decoding finished)
# after the last frame has been decoded
# read will return nothing
if len(buffer) == 0:
self.stop()
continue
# convert raw bytes into image object
image = Image.frombytes(
"RGB", (self.input_width, self.input_height), buffer
)
# keep checking if the running flag is set to False
# while waiting to put the next image into the queue
while self.running:
with contextlib.suppress(queue.Full):
self.processing_queue.put(
(
frame_index,
(previous_image, image),
self.processing_settings,
),
timeout=0.1,
)
break
previous_image = image
frame_index += 1
# most likely "not enough image data"
except ValueError as e:
self.exception = e
# ignore queue closed
if "is closed" not in str(e):
logger.exception(e)
break
# send exceptions into the client connection pipe
except Exception as e:
self.exception = e
logger.exception(e)
break
else:
logger.debug("Decoding queue depleted")
# flush the remaining data in STDOUT and STDERR
self.decoder.stdout.flush()
self.decoder.stderr.flush()
# send SIGINT (2) to FFmpeg
# this instructs it to finalize and exit
self.decoder.send_signal(signal.SIGINT)
# close PIPEs to prevent process from getting stuck
self.decoder.stdout.close()
self.decoder.stderr.close()
# wait for process to exit
self.decoder.wait()
# wait for PIPE printer to exit
self.pipe_printer.stop()
self.pipe_printer.join()
logger.info("Decoder thread exiting")
return super().run()
def stop(self) -> None:
self.running = False

198
video2x/encoder.py Executable file
View File

@@ -0,0 +1,198 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Copyright (C) 2018-2022 K4YT3X and contributors.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
Name: Video Encoder
Author: K4YT3X
Date Created: June 17, 2021
Last Modified: March 20, 2022
"""
import os
import pathlib
import signal
import subprocess
import threading
import time
from multiprocessing.managers import ListProxy
from multiprocessing.sharedctypes import Synchronized
import ffmpeg
from loguru import logger
from .pipe_printer import PipePrinter
# map Loguru log levels to FFmpeg log levels
LOGURU_FFMPEG_LOGLEVELS = {
"trace": "trace",
"debug": "debug",
"info": "info",
"success": "info",
"warning": "warning",
"error": "error",
"critical": "fatal",
}
class VideoEncoder(threading.Thread):
def __init__(
self,
input_path: pathlib.Path,
frame_rate: float,
output_path: pathlib.Path,
output_width: int,
output_height: int,
total_frames: int,
processed_frames: ListProxy,
processed: Synchronized,
pause: Synchronized,
copy_audio: bool = True,
copy_subtitle: bool = True,
copy_data: bool = False,
copy_attachments: bool = False,
) -> None:
threading.Thread.__init__(self)
self.running = False
self.input_path = input_path
self.output_path = output_path
self.total_frames = total_frames
self.processed_frames = processed_frames
self.processed = processed
self.pause = pause
# stores exceptions if the thread exits with errors
self.exception = None
# create FFmpeg input for the original input video
self.original = ffmpeg.input(input_path)
# define frames as input
frames = ffmpeg.input(
"pipe:0",
format="rawvideo",
pix_fmt="rgb24",
vsync="cfr",
s=f"{output_width}x{output_height}",
r=frame_rate,
)
# copy additional streams from original file
# https://ffmpeg.org/ffmpeg.html#Stream-specifiers-1
additional_streams = [
# self.original["1:v?"],
self.original["a?"] if copy_audio is True else None,
self.original["s?"] if copy_subtitle is True else None,
self.original["d?"] if copy_data is True else None,
self.original["t?"] if copy_attachments is True else None,
]
# run FFmpeg and produce final output
self.encoder = subprocess.Popen(
ffmpeg.compile(
ffmpeg.output(
frames,
*[s for s in additional_streams if s is not None],
str(self.output_path),
vcodec="libx264",
vsync="cfr",
pix_fmt="yuv420p",
crf=17,
preset="veryslow",
# acodec="libfdk_aac",
# cutoff=20000,
r=frame_rate,
map_metadata=1,
metadata="comment=Processed with Video2X",
)
.global_args("-hide_banner")
.global_args("-nostats")
.global_args(
"-loglevel",
LOGURU_FFMPEG_LOGLEVELS.get(
os.environ.get("LOGURU_LEVEL", "INFO").lower()
),
),
overwrite_output=True,
),
env={"AV_LOG_FORCE_COLOR": "TRUE"},
stdin=subprocess.PIPE,
stderr=subprocess.PIPE,
)
# start the PIPE printer to start printing FFmpeg logs
self.pipe_printer = PipePrinter(self.encoder.stderr)
self.pipe_printer.start()
def run(self) -> None:
self.running = True
frame_index = 0
while self.running and frame_index < self.total_frames:
# pause if pause flag is set
if self.pause.value is True:
time.sleep(0.1)
continue
try:
image = self.processed_frames[frame_index]
if image is None:
time.sleep(0.1)
continue
# send the image to FFmpeg for encoding
self.encoder.stdin.write(image.tobytes())
# remove the image from memory
self.processed_frames[frame_index] = None
with self.processed.get_lock():
self.processed.value += 1
frame_index += 1
# send exceptions into the client connection pipe
except Exception as e:
self.exception = e
logger.exception(e)
break
else:
logger.debug("Encoding queue depleted")
# flush the remaining data in STDIN and STDERR
self.encoder.stdin.flush()
self.encoder.stderr.flush()
# send SIGINT (2) to FFmpeg
# this instructs it to finalize and exit
self.encoder.send_signal(signal.SIGINT)
# close PIPEs to prevent process from getting stuck
self.encoder.stdin.close()
self.encoder.stderr.close()
# wait for process to exit
self.encoder.wait()
# wait for PIPE printer to exit
self.pipe_printer.stop()
self.pipe_printer.join()
logger.info("Encoder thread exiting")
return super().run()
def stop(self) -> None:
self.running = False

125
video2x/interpolator.py Executable file
View File

@@ -0,0 +1,125 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Copyright (C) 2018-2022 K4YT3X and contributors.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
Name: Interpolator
Author: K4YT3X
Date Created: May 27, 2021
Last Modified: March 20, 2022
"""
import multiprocessing
import queue
import signal
import time
from multiprocessing.managers import ListProxy
from multiprocessing.sharedctypes import Synchronized
from loguru import logger
from PIL import ImageChops, ImageStat
from rife_ncnn_vulkan_python.rife_ncnn_vulkan import Rife
ALGORITHM_CLASSES = {"rife": Rife}
class Interpolator(multiprocessing.Process):
def __init__(
self,
processing_queue: multiprocessing.Queue,
processed_frames: ListProxy,
pause: Synchronized,
) -> None:
multiprocessing.Process.__init__(self)
self.running = False
self.processing_queue = processing_queue
self.processed_frames = processed_frames
self.pause = pause
signal.signal(signal.SIGTERM, self._stop)
def run(self) -> None:
self.running = True
logger.opt(colors=True).info(
f"Interpolator process <blue>{self.name}</blue> initiating"
)
processor_objects = {}
while self.running:
try:
# pause if pause flag is set
if self.pause.value is True:
time.sleep(0.1)
continue
try:
# get new job from queue
(
frame_index,
(image0, image1),
(difference_threshold, algorithm),
) = self.processing_queue.get(False)
except queue.Empty:
time.sleep(0.1)
continue
# if image0 is None, image1 is the first frame
# skip this round
if image0 is None:
continue
difference = ImageChops.difference(image0, image1)
difference_stat = ImageStat.Stat(difference)
difference_ratio = (
sum(difference_stat.mean) / (len(difference_stat.mean) * 255) * 100
)
# if the difference is lower than threshold
# process the interpolation
if difference_ratio < difference_threshold:
# select a processor object with the required settings
# create a new object if none are available
processor_object = processor_objects.get(algorithm)
if processor_object is None:
processor_object = ALGORITHM_CLASSES[algorithm](0)
processor_objects[algorithm] = processor_object
interpolated_image = processor_object.process(image0, image1)
# if the difference is greater than threshold
# there's a change in camera angle, ignore
else:
interpolated_image = image0
if frame_index == 1:
self.processed_frames[0] = image0
self.processed_frames[frame_index * 2 - 1] = interpolated_image
self.processed_frames[frame_index * 2] = image1
# send exceptions into the client connection pipe
except (SystemExit, KeyboardInterrupt):
break
except Exception as e:
logger.exception(e)
break
logger.opt(colors=True).info(
f"Interpolator process <blue>{self.name}</blue> terminating"
)
return super().run()
def _stop(self, _signal_number, _frame) -> None:
self.running = False

63
video2x/pipe_printer.py Executable file
View File

@@ -0,0 +1,63 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Copyright (C) 2018-2022 K4YT3X and contributors.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
Name: PIPE Printer
Author: K4YT3X
Date Created: February 27, 2022
Last Modified: February 28, 2022
"""
import os
import sys
import threading
import time
from typing import IO
class PipePrinter(threading.Thread):
def __init__(self, stderr: IO[bytes]) -> None:
threading.Thread.__init__(self)
self.stderr = stderr
self.running = False
# set read mode to non-blocking
os.set_blocking(self.stderr.fileno(), False)
def _print_output(self) -> None:
output = self.stderr.read()
if output is not None and len(output) != 0:
print(output.decode(), file=sys.stderr)
def run(self) -> None:
self.running = True
# keep printing contents in the PIPE
while self.running:
time.sleep(0.5)
try:
self._print_output()
# pipe closed
except ValueError:
break
return super().run()
def stop(self) -> None:
self.running = False

207
video2x/upscaler.py Executable file
View File

@@ -0,0 +1,207 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Copyright (C) 2018-2022 K4YT3X and contributors.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
Name: Upscaler
Author: K4YT3X
Date Created: May 27, 2021
Last Modified: March 20, 2022
"""
import math
import multiprocessing
import queue
import signal
import time
from multiprocessing.managers import ListProxy
from multiprocessing.sharedctypes import Synchronized
from loguru import logger
from PIL import Image, ImageChops, ImageStat
from realcugan_ncnn_vulkan_python import Realcugan
from realsr_ncnn_vulkan_python import Realsr
from srmd_ncnn_vulkan_python import Srmd
from waifu2x_ncnn_vulkan_python import Waifu2x
# fixed scaling ratios supported by the algorithms
# that only support certain fixed scale ratios
ALGORITHM_FIXED_SCALING_RATIOS = {
"waifu2x": [1, 2],
"srmd": [2, 3, 4],
"realsr": [4],
"realcugan": [1, 2, 3, 4],
}
ALGORITHM_CLASSES = {
"waifu2x": Waifu2x,
"srmd": Srmd,
"realsr": Realsr,
"realcugan": Realcugan,
}
class Upscaler(multiprocessing.Process):
def __init__(
self,
processing_queue: multiprocessing.Queue,
processed_frames: ListProxy,
pause: Synchronized,
) -> None:
multiprocessing.Process.__init__(self)
self.running = False
self.processing_queue = processing_queue
self.processed_frames = processed_frames
self.pause = pause
signal.signal(signal.SIGTERM, self._stop)
def run(self) -> None:
self.running = True
logger.opt(colors=True).info(
f"Upscaler process <blue>{self.name}</blue> initiating"
)
processor_objects = {}
while self.running:
try:
# pause if pause flag is set
if self.pause.value is True:
time.sleep(0.1)
continue
try:
# get new job from queue
(
frame_index,
(image0, image1),
(
output_width,
output_height,
noise,
difference_threshold,
algorithm,
),
) = self.processing_queue.get(False)
# destructure settings
except queue.Empty:
time.sleep(0.1)
continue
difference_ratio = 0
if image0 is not None:
difference = ImageChops.difference(image0, image1)
difference_stat = ImageStat.Stat(difference)
difference_ratio = (
sum(difference_stat.mean)
/ (len(difference_stat.mean) * 255)
* 100
)
# if the difference is lower than threshold
# skip this frame
if difference_ratio < difference_threshold:
# make sure the previous frame has been processed
if frame_index > 0:
while self.processed_frames[frame_index - 1] is None:
time.sleep(0.1)
# make the current image the same as the previous result
self.processed_frames[frame_index] = self.processed_frames[
frame_index - 1
]
# if the difference is greater than threshold
# process this frame
else:
width, height = image1.size
# calculate required minimum scale ratio
output_scale = max(output_width / width, output_height / height)
# select the optimal algorithm scaling ratio to use
supported_scaling_ratios = sorted(
ALGORITHM_FIXED_SCALING_RATIOS[algorithm]
)
remaining_scaling_ratio = math.ceil(output_scale)
scaling_jobs = []
# if the scaling ratio is 1.0
# apply the smallest scaling ratio available
if remaining_scaling_ratio == 1:
scaling_jobs.append(supported_scaling_ratios[0])
else:
while remaining_scaling_ratio > 1:
for ratio in supported_scaling_ratios:
if ratio >= remaining_scaling_ratio:
scaling_jobs.append(ratio)
remaining_scaling_ratio /= ratio
break
else:
found = False
for i in supported_scaling_ratios:
for j in supported_scaling_ratios:
if i * j >= remaining_scaling_ratio:
scaling_jobs.extend([i, j])
remaining_scaling_ratio /= i * j
found = True
break
if found is True:
break
if found is False:
scaling_jobs.append(supported_scaling_ratios[-1])
remaining_scaling_ratio /= supported_scaling_ratios[
-1
]
for job in scaling_jobs:
# select a processor object with the required settings
# create a new object if none are available
processor_object = processor_objects.get((algorithm, job))
if processor_object is None:
processor_object = ALGORITHM_CLASSES[algorithm](
noise=noise, scale=job
)
processor_objects[(algorithm, job)] = processor_object
# process the image with the selected algorithm
image1 = processor_object.process(image1)
# downscale the image to the desired output size and
# save the image to disk
image1 = image1.resize((output_width, output_height), Image.LANCZOS)
self.processed_frames[frame_index] = image1
# send exceptions into the client connection pipe
except (SystemExit, KeyboardInterrupt):
break
except Exception as e:
logger.exception(e)
break
logger.opt(colors=True).info(
f"Upscaler process <blue>{self.name}</blue> terminating"
)
return super().run()
def _stop(self, _signal_number, _frame) -> None:
self.running = False

643
video2x/video2x.py Executable file
View File

@@ -0,0 +1,643 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
r"""
Copyright (C) 2018-2022 K4YT3X and contributors.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
__ __ _ _ ___ __ __
\ \ / / (_) | | |__ \ \ \ / /
\ \ / / _ __| | ___ ___ ) | \ V /
\ \/ / | | / _` | / _ \ / _ \ / / > <
\ / | | | (_| | | __/ | (_) | / /_ / . \
\/ |_| \__,_| \___| \___/ |____| /_/ \_\
Name: Video2X
Creator: K4YT3X
Date Created: February 24, 2018
Last Modified: March 21, 2022
Editor: BrianPetkovsek
Last Modified: June 17, 2019
Editor: SAT3LL
Last Modified: June 25, 2019
Editor: 28598519a
Last Modified: March 23, 2020
"""
import argparse
import ctypes
import math
import multiprocessing
import os
import pathlib
import signal
import sys
import time
import cv2
import ffmpeg
from loguru import logger
from rich import print
from rich.console import Console
from rich.file_proxy import FileProxy
from rich.progress import (
BarColumn,
Progress,
ProgressColumn,
Task,
TimeElapsedColumn,
TimeRemainingColumn,
)
from rich.text import Text
from . import __version__
from .decoder import VideoDecoder
from .encoder import VideoEncoder
from .interpolator import Interpolator
from .upscaler import Upscaler
# for desktop environments only
# if pynput can be loaded, enable global pause hotkey support
try:
import pynput
except ImportError:
ENABLE_HOTKEY = False
else:
ENABLE_HOTKEY = True
LEGAL_INFO = """Video2X\t\t{}
Author:\t\tK4YT3X
License:\tGNU AGPL v3
Github Page:\thttps://github.com/k4yt3x/video2x
Contact:\ti@k4yt3x.com""".format(
__version__
)
# algorithms available for upscaling tasks
UPSCALING_ALGORITHMS = [
"waifu2x",
"srmd",
"realsr",
"realcugan",
]
# algorithms available for frame interpolation tasks
INTERPOLATION_ALGORITHMS = ["rife"]
# progress bar labels for different modes
MODE_LABELS = {"upscale": "Upscaling", "interpolate": "Interpolating"}
# format string for Loguru loggers
LOGURU_FORMAT = (
"<green>{time:HH:mm:ss.SSSSSS!UTC}</green> | "
"<level>{level: <8}</level> | "
"<level>{message}</level>"
)
class ProcessingSpeedColumn(ProgressColumn):
"""Custom progress bar column that displays the processing speed"""
def render(self, task: Task) -> Text:
speed = task.finished_speed or task.speed
return Text(
f"{round(speed, 2) if isinstance(speed, float) else '?'} FPS",
style="progress.data.speed",
)
class Video2X:
"""
Video2X class
provides two vital functions:
- upscale: perform upscaling on a file
- interpolate: perform motion interpolation on a file
"""
def __init__(self) -> None:
self.version = __version__
def _get_video_info(self, path: pathlib.Path) -> tuple:
"""
get video file information with FFmpeg
:param path pathlib.Path: video file path
:raises RuntimeError: raised when video stream isn't found
"""
# probe video file info
logger.info("Reading input video information")
for stream in ffmpeg.probe(path)["streams"]:
if stream["codec_type"] == "video":
video_info = stream
break
else:
raise RuntimeError("unable to find video stream")
# get total number of frames to be processed
capture = cv2.VideoCapture(str(path))
# check if file is opened successfully
if not capture.isOpened():
raise RuntimeError("OpenCV has failed to open the input file")
total_frames = int(capture.get(cv2.CAP_PROP_FRAME_COUNT))
frame_rate = capture.get(cv2.CAP_PROP_FPS)
return video_info["width"], video_info["height"], total_frames, frame_rate
def _toggle_pause(self, _signal_number: int = -1, _frame=None):
# print console messages and update the progress bar's status
if self.pause.value is False:
self.progress.update(self.task, description=self.description + " (paused)")
self.progress.stop_task(self.task)
logger.warning("Processing paused, press Ctrl+Alt+V again to resume")
elif self.pause.value is True:
self.progress.update(self.task, description=self.description)
logger.warning("Resuming processing")
self.progress.start_task(self.task)
# invert the value of the pause flag
with self.pause.get_lock():
self.pause.value = not self.pause.value
def _run(
self,
input_path: pathlib.Path,
width: int,
height: int,
total_frames: int,
frame_rate: float,
output_path: pathlib.Path,
output_width: int,
output_height: int,
Processor: object,
mode: str,
processes: int,
processing_settings: tuple,
) -> None:
# record original STDOUT and STDERR for restoration
original_stdout = sys.stdout
original_stderr = sys.stderr
# create console for rich's Live display
console = Console()
# redirect STDOUT and STDERR to console
sys.stdout = FileProxy(console, sys.stdout)
sys.stderr = FileProxy(console, sys.stderr)
# re-add Loguru to point to the new STDERR
logger.remove()
logger.add(sys.stderr, colorize=True, format=LOGURU_FORMAT)
# initialize values
self.processor_processes = []
self.processing_queue = multiprocessing.Queue(maxsize=processes * 10)
processed_frames = multiprocessing.Manager().list([None] * total_frames)
self.processed = multiprocessing.Value("I", 0)
self.pause = multiprocessing.Value(ctypes.c_bool, False)
# set up and start decoder thread
logger.info("Starting video decoder")
self.decoder = VideoDecoder(
input_path,
width,
height,
frame_rate,
self.processing_queue,
processing_settings,
self.pause,
)
self.decoder.start()
# set up and start encoder thread
logger.info("Starting video encoder")
self.encoder = VideoEncoder(
input_path,
frame_rate * 2 if mode == "interpolate" else frame_rate,
output_path,
output_width,
output_height,
total_frames,
processed_frames,
self.processed,
self.pause,
)
self.encoder.start()
# create processor processes
for process_name in range(processes):
process = Processor(self.processing_queue, processed_frames, self.pause)
process.name = str(process_name)
process.daemon = True
process.start()
self.processor_processes.append(process)
# create progress bar
self.progress = Progress(
"[progress.description]{task.description}",
BarColumn(complete_style="blue", finished_style="green"),
"[progress.percentage]{task.percentage:>3.0f}%",
"[color(240)]({task.completed}/{task.total})",
ProcessingSpeedColumn(),
TimeElapsedColumn(),
"<",
TimeRemainingColumn(),
console=console,
speed_estimate_period=300.0,
disable=True,
)
self.description = f"[cyan]{MODE_LABELS.get(mode, 'Unknown')}"
self.task = self.progress.add_task(self.description, total=total_frames)
# allow sending SIGUSR1 to pause/resume processing
signal.signal(signal.SIGUSR1, self._toggle_pause)
# enable global pause hotkey if it's supported
if ENABLE_HOTKEY is True:
# create global pause hotkey
pause_hotkey = pynput.keyboard.HotKey(
pynput.keyboard.HotKey.parse("<ctrl>+<alt>+v"), self._toggle_pause
)
# create global keyboard input listener
keyboard_listener = pynput.keyboard.Listener(
on_press=(
lambda key: pause_hotkey.press(keyboard_listener.canonical(key))
),
on_release=(
lambda key: pause_hotkey.release(keyboard_listener.canonical(key))
),
)
# start monitoring global key presses
keyboard_listener.start()
# a temporary variable that stores the exception
exception = []
try:
# wait for jobs in queue to deplete
while self.processed.value < total_frames - 1:
time.sleep(1)
# check processor health
for process in self.processor_processes:
if not process.is_alive():
raise Exception("process died unexpectedly")
# check decoder health
if not self.decoder.is_alive() and self.decoder.exception is not None:
raise Exception("decoder died unexpectedly")
# check encoder health
if not self.encoder.is_alive() and self.encoder.exception is not None:
raise Exception("encoder died unexpectedly")
# show progress bar when upscale starts
if self.progress.disable is True and self.processed.value > 0:
self.progress.disable = False
self.progress.start()
# update progress
if self.pause.value is False:
self.progress.update(self.task, completed=self.processed.value)
self.progress.update(self.task, completed=total_frames)
self.progress.stop()
logger.info("Processing has completed")
# if SIGTERM is received or ^C is pressed
# TODO: pause and continue here
except (SystemExit, KeyboardInterrupt) as e:
self.progress.stop()
logger.warning("Exit signal received, exiting gracefully")
logger.warning("Press ^C again to force terminate")
exception.append(e)
except Exception as e:
self.progress.stop()
logger.exception(e)
exception.append(e)
finally:
# stop keyboard listener
if ENABLE_HOTKEY is True:
keyboard_listener.stop()
keyboard_listener.join()
# stop progress display
self.progress.stop()
# stop processor processes
logger.info("Stopping processor processes")
for process in self.processor_processes:
process.terminate()
# wait for processes to finish
for process in self.processor_processes:
process.join()
# stop encoder and decoder
logger.info("Stopping decoder and encoder threads")
self.decoder.stop()
self.encoder.stop()
self.decoder.join()
self.encoder.join()
# mark processing queue as closed
self.processing_queue.close()
# raise the error if there is any
if len(exception) > 0:
raise exception[0]
# restore original STDOUT and STDERR
sys.stdout = original_stdout
sys.stderr = original_stderr
# re-add Loguru to point to the restored STDERR
logger.remove()
logger.add(sys.stderr, colorize=True, format=LOGURU_FORMAT)
def upscale(
self,
input_path: pathlib.Path,
output_path: pathlib.Path,
output_width: int,
output_height: int,
noise: int,
processes: int,
threshold: float,
algorithm: str,
) -> None:
# get basic video information
width, height, total_frames, frame_rate = self._get_video_info(input_path)
# automatically calculate output width and height if only one is given
if output_width == 0 or output_width is None:
output_width = output_height / height * width
elif output_height == 0 or output_height is None:
output_height = output_width / width * height
# sanitize output width and height to be divisible by 2
output_width = int(math.ceil(output_width / 2.0) * 2)
output_height = int(math.ceil(output_height / 2.0) * 2)
# start processing
self._run(
input_path,
width,
height,
total_frames,
frame_rate,
output_path,
output_width,
output_height,
Upscaler,
"upscale",
processes,
(
output_width,
output_height,
noise,
threshold,
algorithm,
),
)
def interpolate(
self,
input_path: pathlib.Path,
output_path: pathlib.Path,
processes: int,
threshold: float,
algorithm: str,
) -> None:
# get video basic information
width, height, original_frames, frame_rate = self._get_video_info(input_path)
# calculate the number of total output frames
total_frames = original_frames * 2 - 1
# start processing
self._run(
input_path,
width,
height,
total_frames,
frame_rate,
output_path,
width,
height,
Interpolator,
"interpolate",
processes,
(threshold, algorithm),
)
def parse_arguments() -> argparse.Namespace:
"""
parse command line arguments
:rtype argparse.Namespace: command parsing results
"""
parser = argparse.ArgumentParser(
prog="video2x",
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
)
parser.add_argument(
"--version", help="show version information and exit", action="store_true"
)
parser.add_argument(
"-i",
"--input",
type=pathlib.Path,
help="input file/directory path",
required=True,
)
parser.add_argument(
"-o",
"--output",
type=pathlib.Path,
help="output file/directory path",
required=True,
)
parser.add_argument(
"-p", "--processes", type=int, help="number of processes to launch", default=1
)
parser.add_argument(
"-l",
"--loglevel",
choices=["trace", "debug", "info", "success", "warning", "error", "critical"],
default="info",
)
# upscaler arguments
action = parser.add_subparsers(
help="action to perform", dest="action", required=True
)
upscale = action.add_parser(
"upscale",
help="upscale a file",
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
add_help=False,
)
upscale.add_argument(
"--help", action="help", help="show this help message and exit"
)
upscale.add_argument("-w", "--width", type=int, help="output width")
upscale.add_argument("-h", "--height", type=int, help="output height")
upscale.add_argument("-n", "--noise", type=int, help="denoise level", default=3)
upscale.add_argument(
"-a",
"--algorithm",
choices=UPSCALING_ALGORITHMS,
help="algorithm to use for upscaling",
default=UPSCALING_ALGORITHMS[0],
)
upscale.add_argument(
"-t",
"--threshold",
type=float,
help=(
"skip if the percent difference between two adjacent frames is below this"
" value; set to 0 to process all frames"
),
default=0,
)
# interpolator arguments
interpolate = action.add_parser(
"interpolate",
help="interpolate frames for file",
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
add_help=False,
)
interpolate.add_argument(
"--help", action="help", help="show this help message and exit"
)
interpolate.add_argument(
"-a",
"--algorithm",
choices=UPSCALING_ALGORITHMS,
help="algorithm to use for upscaling",
default=INTERPOLATION_ALGORITHMS[0],
)
interpolate.add_argument(
"-t",
"--threshold",
type=float,
help=(
"skip if the percent difference between two adjacent frames exceeds this"
" value; set to 100 to interpolate all frames"
),
default=10,
)
return parser.parse_args()
def main() -> int:
"""
command line entrypoint for direct CLI invocation
:rtype int: 0 if completed successfully, else other int
"""
try:
# display version and lawful informaition
if "--version" in sys.argv:
print(LEGAL_INFO)
return 0
# parse command line arguments
args = parse_arguments()
# check input/output file paths
if not args.input.exists():
logger.critical(f"Cannot find input file: {args.input}")
return 1
elif not args.input.is_file():
logger.critical("Input path is not a file")
return 1
# set logger level
if os.environ.get("LOGURU_LEVEL") is None:
os.environ["LOGURU_LEVEL"] = args.loglevel.upper()
# remove default handler
logger.remove()
# add new sink with custom handler
logger.add(sys.stderr, colorize=True, format=LOGURU_FORMAT)
# print package version and copyright notice
logger.opt(colors=True).info(f"<magenta>Video2X {__version__}</magenta>")
logger.opt(colors=True).info(
"<magenta>Copyright (C) 2018-2022 K4YT3X and contributors.</magenta>"
)
# initialize video2x object
video2x = Video2X()
if args.action == "upscale":
video2x.upscale(
args.input,
args.output,
args.width,
args.height,
args.noise,
args.processes,
args.threshold,
args.algorithm,
)
elif args.action == "interpolate":
video2x.interpolate(
args.input,
args.output,
args.processes,
args.threshold,
args.algorithm,
)
# don't print the traceback for manual terminations
except KeyboardInterrupt:
return 2
except Exception as e:
logger.exception(e)
return 1
# if no exceptions were produced
else:
logger.success("Processing completed successfully")
return 0