mirror of
https://github.com/k4yt3x/video2x.git
synced 2026-02-06 20:44:56 +08:00
Compare commits
35 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d3db4e8cf1 | ||
|
|
f887dfe3a7 | ||
|
|
a41df138bf | ||
|
|
41833f4068 | ||
|
|
c0955ae7e4 | ||
|
|
682aeb82ff | ||
|
|
21407c831c | ||
|
|
7e34bf7516 | ||
|
|
4c5ca73e38 | ||
|
|
387a233daf | ||
|
|
781eb6686f | ||
|
|
c73edd9001 | ||
|
|
deb742ee8d | ||
|
|
5ef6eb7e8e | ||
|
|
6c5e079a1c | ||
|
|
1e384596ee | ||
|
|
4680647f1f | ||
|
|
4015db5bcf | ||
|
|
082c6d44fa | ||
|
|
de841a4636 | ||
|
|
40711a2711 | ||
|
|
0c63768165 | ||
|
|
ac2d447391 | ||
|
|
b03747dbde | ||
|
|
89740f01dc | ||
|
|
676e70f088 | ||
|
|
f57b5e9d04 | ||
|
|
f48e23a890 | ||
|
|
826b4e9829 | ||
|
|
c56be51e21 | ||
|
|
d2b3175ccd | ||
|
|
a98d1c7277 | ||
|
|
e107ddc96e | ||
|
|
289f5441eb | ||
|
|
179bd6afc8 |
4
.github/workflows/nightly.yml
vendored
4
.github/workflows/nightly.yml
vendored
@@ -1,7 +1,7 @@
|
||||
# Name: Video2X Nightly Build
|
||||
# Creator: K4YT3X
|
||||
# Date Created: May 12, 2020
|
||||
# Last Modified: May 13, 2020
|
||||
# Last Modified: May 28, 2020
|
||||
|
||||
name: Video2X Nightly Build
|
||||
|
||||
@@ -27,7 +27,7 @@ jobs:
|
||||
run: |
|
||||
python -m pip install -U pip
|
||||
pip install -U pyinstaller pywin32
|
||||
pip install -U -r requirements.txt
|
||||
pip install -U -r requirements-windows.txt
|
||||
- name: Build Video2X CLI
|
||||
run: |
|
||||
pyinstaller --noconfirm --log-level=WARN `
|
||||
|
||||
186
Dockerfile
Normal file
186
Dockerfile
Normal file
@@ -0,0 +1,186 @@
|
||||
FROM ubuntu:19.10
|
||||
#FROM nvidia/cuda:10.1-cudnn7-devel-ubuntu18.04
|
||||
MAINTAINER Danielle Douglas <ddouglas87@gmail.com>
|
||||
MAINTAINER Lhanjian <lhjay1@foxmail.com>
|
||||
MAINTAINER K4YT3X <k4yt3x@k4yt3x.com>
|
||||
|
||||
# Don't ask questions during image setup.
|
||||
ENV DEBIAN_FRONTEND noninteractive
|
||||
ENV NASM_VERSION 2.14
|
||||
ENV NVCODEC_VERSION 8.2.15.6
|
||||
ENV PKG_CONFIG_PATH /usr/local/lib/pkgconfig
|
||||
ENV FFMPEG_VERSION 4.1.2
|
||||
|
||||
# Install apt-fast, because we got gigs to download.
|
||||
RUN apt-get update && apt-get install -y apt-utils &&\
|
||||
apt-get install -y --no-install-recommends software-properties-common &&\
|
||||
add-apt-repository ppa:apt-fast/stable &&\
|
||||
add-apt-repository -y ppa:graphics-drivers/ppa &&\
|
||||
apt-get install -y --no-install-recommends apt-fast && apt-fast update
|
||||
|
||||
|
||||
## Install Video2X ##
|
||||
|
||||
# Dependencies
|
||||
RUN apt-fast install -y --no-install-recommends git-core python3-pip python3-setuptools python3-wheel python3-psutil ffmpeg gcc g++ \
|
||||
libc6-dev python3-dev libmagic-dev libmagic1 python3.8 nvidia-driver-440 nvidia-cuda-toolkit gnupg2 curl ca-certificates pkg-config \
|
||||
autoconf libx264-dev libx265-dev libnuma-dev libvpx-dev libfdk-aac-dev libmp3lame-dev libopus-dev libass-dev libfreetype6-dev libgnutls28-dev \
|
||||
libsdl2-dev libtool libva-dev libvdpau-dev libvorbis-dev libxcb1-dev libxcb-shm0-dev libxcb-xfixes0-dev texinfo wget yasm zlib1g-dev \
|
||||
libass-dev libfreetype6-dev libsdl2-dev p11-kit libva-dev libvdpau-dev libvorbis-dev libxcb1-dev libxcb-shm0-dev libxcb-xfixes0-dev \
|
||||
pkg-config texinfo wget zlib1g-dev libchromaprint-dev frei0r-plugins-dev gnutls-dev ladspa-sdk libcaca-dev libcdio-paranoia-dev libcodec2-dev \
|
||||
libfontconfig1-dev libfreetype6-dev libfribidi-dev libgme-dev libgsm1-dev libjack-dev libmodplug-dev libmp3lame-dev libopencore-amrnb-dev \
|
||||
libopencore-amrwb-dev libopenjp2-7-dev libopenmpt-dev libopus-dev libpulse-dev librsvg2-dev librubberband-dev librtmp-dev libshine-dev \
|
||||
libsmbclient-dev libsnappy-dev libsoxr-dev libspeex-dev libssh-dev libtesseract-dev libtheora-dev libtwolame-dev libv4l-dev libvo-amrwbenc-dev \
|
||||
libvorbis-dev libvpx-dev libwavpack-dev libwebp-dev libx264-dev libx265-dev libxvidcore-dev libxml2-dev libzmq3-dev libzvbi-dev liblilv-dev \
|
||||
libopenal-dev opencl-dev libjack-dev libbluray-dev libfdk-aac-dev libmysofa-dev
|
||||
|
||||
RUN curl -vfsSLO https://www.nasm.us/pub/nasm/releasebuilds/$NASM_VERSION/nasm-$NASM_VERSION.tar.bz2 \
|
||||
&& tar -xjf nasm-$NASM_VERSION.tar.bz2 \
|
||||
&& cd nasm-$NASM_VERSION \
|
||||
&& ./autogen.sh \
|
||||
&& ./configure \
|
||||
&& make -j$(nproc) \
|
||||
&& make install
|
||||
|
||||
RUN git clone --recurse-submodules -b n$NVCODEC_VERSION --depth 1 https://git.videolan.org/git/ffmpeg/nv-codec-headers \
|
||||
&& cd nv-codec-headers \
|
||||
&& make install
|
||||
|
||||
RUN curl -vfsSLO https://ffmpeg.org/releases/ffmpeg-$FFMPEG_VERSION.tar.bz2 \
|
||||
&& tar -xjf ffmpeg-$FFMPEG_VERSION.tar.bz2 \
|
||||
&& cd ffmpeg-$FFMPEG_VERSION \
|
||||
&& ./configure --enable-cuda-sdk --enable-cuvid --enable-nonfree --enable-libnpp --enable-nvenc \
|
||||
--enable-gpl --enable-version3 \
|
||||
--enable-small --enable-avisynth --enable-chromaprint \
|
||||
--enable-frei0r --enable-gmp --enable-gnutls --enable-ladspa \
|
||||
--enable-libass --enable-libcaca --enable-libcdio \
|
||||
--enable-libcodec2 --enable-libfontconfig --enable-libfreetype \
|
||||
--enable-libfribidi --enable-libgme --enable-libgsm --enable-libjack \
|
||||
--enable-libmodplug --enable-libmp3lame --enable-libopencore-amrnb \
|
||||
--enable-libopencore-amrwb --enable-libopencore-amrwb \
|
||||
--enable-libopenjpeg --enable-libopenmpt --enable-libopus --enable-libpulse \
|
||||
--enable-librsvg --enable-librubberband --enable-librtmp --enable-libshine \
|
||||
--enable-libsnappy --enable-libsoxr --enable-libspeex \
|
||||
--enable-libssh --enable-libtesseract --enable-libtheora \
|
||||
--enable-libtwolame --enable-libv4l2 --enable-libvo-amrwbenc \
|
||||
--enable-libvorbis --enable-libvpx --enable-libwavpack --enable-libwebp \
|
||||
--enable-libx264 --enable-libx265 --enable-libxvid --enable-libxml2 \
|
||||
--enable-libzmq --enable-libzvbi --enable-lv2 \
|
||||
--enable-libmysofa \
|
||||
--enable-openal --enable-opencl --enable-opengl --enable-libdrm \
|
||||
--enable-libfdk-aac --enable-libbluray \
|
||||
&& make -j$(nproc) \
|
||||
&& make install
|
||||
|
||||
# Install Nvidia Driver
|
||||
|
||||
RUN curl -fsSL https://developer.download.nvidia.com/compute/cuda/repos/ubuntu1804/x86_64/7fa2af80.pub | apt-key add -
|
||||
|
||||
RUN echo "deb https://developer.download.nvidia.com/compute/machine-learning/repos/ubuntu1804/x86_64 /" > /etc/apt/sources.list.d/nvidia-ml.list
|
||||
|
||||
# Install Video2X
|
||||
RUN update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.7 1 && update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.8 2
|
||||
RUN cd / && python3.8 -m pip install --upgrade pip &&\
|
||||
git clone --recurse-submodules --progress https://github.com/k4yt3x/video2x.git --depth=1 &&\
|
||||
python3.8 -m pip install avalon_framework colorama python-magic patool psutil pyqt5 pyunpack pyyaml requests tqdm
|
||||
|
||||
# eg: docker build -t video2x . --build-arg driver=waifu2x_ncnn_vulkan
|
||||
ARG driver=all
|
||||
|
||||
# Check if driver exists.
|
||||
SHELL ["/bin/bash", "-c"]
|
||||
RUN drivers=(all waifu2x_caffe waifu2x_converter waifu2x_ncnn_vulkan) &&\
|
||||
case ${drivers[@]} in (*${driver,,}*) true ;; (*)\
|
||||
echo "ERROR: Unrecognized driver." >&2 &&\
|
||||
printf "%s " "Choices are: ${drivers[@]}" >&2 | printf "\n" >&2 &&\
|
||||
exit 1 ;;\
|
||||
esac
|
||||
|
||||
RUN if [ "$driver" = "all" ] || [ "$driver" = "waifu2x_caffe" ] ; then \
|
||||
# nagadomi/caffe prerequisites
|
||||
apt-fast update &&\
|
||||
apt-fast install -y --no-install-recommends build-essential cmake libboost-system-dev libboost-thread-dev libboost-filesystem-dev libboost-chrono-dev libboost-date-time-dev libboost-atomic-dev libboost-python-dev libprotobuf-dev protobuf-compiler libhdf5-dev liblmdb-dev libleveldb-dev libsnappy-dev libopencv-dev libatlas-base-dev python-numpy libgflags-dev libgoogle-glog-dev &&\
|
||||
# nagadomi/waifu2x-caffee-ubuntu prerequisites
|
||||
apt-fast install -y --no-install-recommends libboost-iostreams-dev;\
|
||||
fi
|
||||
# build waifu2x-caffe && install caffe
|
||||
RUN if [ "$driver" = "all" ] || [ "$driver" = "waifu2x_caffe" ] ; then \
|
||||
git clone --recurse-submodules --depth=1 --progress --recurse-submodules https://github.com/nagadomi/waifu2x-caffe-ubuntu.git &&\
|
||||
cd waifu2x-caffe-ubuntu &&\
|
||||
git clone --recurse-submodules --progress --depth=1 https://github.com/nagadomi/caffe.git;\
|
||||
fi
|
||||
|
||||
RUN if [ "$driver" = "all" ] || [ "$driver" = "waifu2x_caffe" ] ; then \
|
||||
apt-fast install --no-install-recommends -y gcc-8 libcudnn7 libcudnn7-dev &&\
|
||||
apt-get remove -y gcc g++ &&\
|
||||
ln -s /usr/bin/gcc-8 /usr/bin/gcc && ln -s /usr/bin/g++-8 /usr/bin/g++ &&\
|
||||
cd /waifu2x-caffe-ubuntu &&\
|
||||
mkdir build &&\
|
||||
cd build &&\
|
||||
cmake .. -DCMAKE_INSTALL_PREFIX=/usr &&\
|
||||
make -j$(nproc) install;\
|
||||
fi
|
||||
|
||||
RUN if [ "$driver" = "all" ] || [ "$driver" = "waifu2x_caffe" ] ; then \
|
||||
# install waifu2x-caffe
|
||||
cd /waifu2x-caffe-ubuntu/build &&\
|
||||
cp waifu2x-caffe ../bin/ &&\
|
||||
mv ../bin tempname &&\
|
||||
mv tempname /video2x/ &&\
|
||||
mv /video2x/tempname /video2x/waifu2x-caffe &&\
|
||||
rm -rf ../waifu2x-caffe-ubuntu ;\
|
||||
fi
|
||||
|
||||
RUN if [ "$driver" = "all" ] || [ "$driver" = "waifu2x_ncnn_vulkan" ] ; then \
|
||||
apt-fast install -y --no-install-recommends software-properties-common build-essential cmake libvulkan-dev glslang-tools libprotobuf-dev protobuf-compiler &&\
|
||||
git clone --recurse-submodules --depth=1 --progress https://github.com/Tencent/ncnn.git &&\
|
||||
cd ncnn &&\
|
||||
mkdir -p build &&\
|
||||
cd build &&\
|
||||
cmake -DCMAKE_INSTALL_PREFIX=/usr -DNCNN_VULKAN=ON .. &&\
|
||||
make -j$(nproc) install &&\
|
||||
rm -rf ../../ncnn &&\
|
||||
cd / &&\
|
||||
# Compile waifu2x-ncnn-vulkan
|
||||
git clone --recurse-submodules --depth=1 --progress https://github.com/nihui/waifu2x-ncnn-vulkan.git &&\
|
||||
cd waifu2x-ncnn-vulkan &&\
|
||||
mkdir -p build &&\
|
||||
cd build &&\
|
||||
cmake ../src &&\
|
||||
make -j$(nproc) &&\
|
||||
# Incall waifu2x-ncnn-vulkan
|
||||
cd /waifu2x-ncnn-vulkan &&\
|
||||
mkdir waifu2x-ncnn-vulkan &&\
|
||||
mv models/models-cunet waifu2x-ncnn-vulkan/ &&\
|
||||
mv build/waifu2x-ncnn-vulkan waifu2x-ncnn-vulkan/ &&\
|
||||
mv waifu2x-ncnn-vulkan /video2x/ &&\
|
||||
rm -rf ../waifu2x-ncnn-vulkan ;\
|
||||
fi
|
||||
|
||||
RUN if [ "$driver" = "all" ] || [ "$driver" = "waifu2x_converter" ] ;\
|
||||
then \
|
||||
# Prerequisits for waifu2x-converter-cpp
|
||||
apt-fast install -y --no-install-recommends build-essential cmake libopencv-dev ocl-icd-opencl-dev &&\
|
||||
# Compile & Install
|
||||
git clone --recurse-submodules --depth=1 --progress https://github.com/DeadSix27/waifu2x-converter-cpp &&\
|
||||
cd waifu2x-converter-cpp &&\
|
||||
mkdir build &&\
|
||||
cd build &&\
|
||||
cmake .. &&\
|
||||
make -j$(nproc) &&\
|
||||
#ldconfig &&\
|
||||
cp -r ../models_rgb ./&&\
|
||||
cd / ;\
|
||||
fi
|
||||
|
||||
# Go!
|
||||
#COPY entrypoint.sh /
|
||||
#ENTRYPOINT ["/entrypoint.sh"]
|
||||
|
||||
WORKDIR /host
|
||||
ENTRYPOINT ["/bin/bash"]
|
||||
|
||||
ENV NVIDIA_DRIVER_CAPABILITIES all
|
||||
# Docker image can ask questions now, if needed.
|
||||
ENV DEBIAN_FRONTEND teletype
|
||||
|
||||
26
README.md
26
README.md
@@ -2,13 +2,13 @@
|
||||
<img src="https://user-images.githubusercontent.com/21986859/81626588-ae5ab800-93eb-11ea-918f-ebe98c2de40a.png"/>
|
||||
</p>
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||
<img alt="Become a Patron!" src="https://c5.patreon.com/external/logo/become_a_patron_button@2x.png" href="https://www.patreon.com/bePatron?u=34970782" height=20>
|
||||

|
||||
|
||||
<!--# Video2X Lossless Video Enlarger-->
|
||||
|
||||
@@ -35,6 +35,14 @@ To download the latest nightly build, go to the [GitHub Actions](https://github.
|
||||
|
||||
Video2X is a video/GIF/image upscaling software based on Waifu2X, Anime4K and SRMD written in Python 3. It upscales videos, GIFs and images, restoring details from low-resolution inputs. Video2X also accepts GIF input to video output and video input to GIF output.
|
||||
|
||||
Currently, Video2X supports the following drivers (implementations of algorithms).
|
||||
|
||||
- **Waifu2X Caffe**: Caffe implementation of waifu2x
|
||||
- **Waifu2X Converter CPP**: CPP implementation of waifu2x based on OpenCL and OpenCV
|
||||
- **Waifu2X NCNN Vulkan**: NCNN implementation of waifu2x based on Vulkan API
|
||||
- **SRMD NCNN Vulkan**: NCNN implementation of SRMD based on Vulkan API
|
||||
- **Anime4KCPP**: CPP implementation of Anime4K
|
||||
|
||||
### Video Upscaling
|
||||
|
||||
\
|
||||
@@ -86,7 +94,7 @@ The list is sorted from new to old.
|
||||
|
||||
### Video2X GUI
|
||||
|
||||
\
|
||||
\
|
||||
*Video2X GUI Screenshot*
|
||||
|
||||
### Video2X CLI
|
||||
@@ -171,6 +179,14 @@ To see a help page for driver-specific settings, use `-d` to select the driver a
|
||||
python video2x.py -d waifu2x_caffe -- --help
|
||||
```
|
||||
|
||||
### Running Video2X (Docker)
|
||||
|
||||
Video2X can be deployed via Docker.
|
||||
|
||||
```shell
|
||||
docker pull k4yt3x/video2x
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Documentations
|
||||
@@ -268,10 +284,12 @@ This project relies on the following software and projects.
|
||||
|
||||
## Special Thanks
|
||||
|
||||
Appreciations given to the following code contributors:
|
||||
Appreciations given to the following personnel who have contributed significantly to the project (specifically the technical perspective).
|
||||
|
||||
- @BrianPetkovsek
|
||||
- @SAT3LL
|
||||
- @ddouglas87
|
||||
- @lhanjian
|
||||
|
||||
## Related Projects
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ executable (PE) releases automatically using PyInstaller.
|
||||
This script is currently only tuned for K4YT3X's environment.
|
||||
|
||||
To start a PowerShell session with execution policy bypass
|
||||
powershell –ExecutionPolicy Bypass
|
||||
powershell -ExecutionPolicy Bypass
|
||||
#>
|
||||
|
||||
if ($args.count -ne 1){
|
||||
@@ -82,7 +82,7 @@ Copy-Item "dist\video2x.exe" -Destination "$($VIDEO2X_VERSION)\video2x-$($VIDEO2
|
||||
Copy-Item "dist\video2x_gui.exe" -Destination "$($VIDEO2X_VERSION)\video2x-$($VIDEO2X_VERSION)-win32-light\"
|
||||
Copy-Item "dist\video2x_setup.exe" -Destination "$($VIDEO2X_VERSION)\video2x-$($VIDEO2X_VERSION)-win32-light\"
|
||||
Copy-Item "video2x.yaml" -Destination "$($VIDEO2X_VERSION)\video2x-$($VIDEO2X_VERSION)-win32-light\"
|
||||
Copy-Item "requirements.txt" -Destination "$($VIDEO2X_VERSION)\video2x-$($VIDEO2X_VERSION)-win32-light\"
|
||||
Copy-Item "requirements-windows.txt" -Destination "$($VIDEO2X_VERSION)\video2x-$($VIDEO2X_VERSION)-win32-light\"
|
||||
|
||||
# clean up temporary files
|
||||
Write-Host -ForegroundColor White "`nDeleting temporary files"
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -5,8 +5,8 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"POT-Creation-Date: 2020-05-12 04:27-0400\n"
|
||||
"PO-Revision-Date: 2020-05-12 04:29-0400\n"
|
||||
"POT-Creation-Date: 2020-05-22 17:51-0400\n"
|
||||
"PO-Revision-Date: 2020-05-22 17:54-0400\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: \n"
|
||||
"Language: zh_CN\n"
|
||||
@@ -21,276 +21,304 @@ msgstr ""
|
||||
msgid "Upscaling Progress"
|
||||
msgstr "放大进度"
|
||||
|
||||
#: upscaler.py:106
|
||||
#: upscaler.py:110
|
||||
msgid "Specified or default cache directory is a file/link"
|
||||
msgstr "指定或默认的缓存目录是文件/链接"
|
||||
|
||||
#: upscaler.py:112
|
||||
#: upscaler.py:116
|
||||
msgid "Creating cache directory {}"
|
||||
msgstr "创建缓存目录 {}"
|
||||
|
||||
#: upscaler.py:115
|
||||
#: upscaler.py:119
|
||||
msgid "Unable to create {}"
|
||||
msgstr "无法创建 {}"
|
||||
|
||||
#: upscaler.py:120
|
||||
#: upscaler.py:124
|
||||
msgid "Extracted frames are being saved to: {}"
|
||||
msgstr "提取的帧将被保存到:{}"
|
||||
|
||||
#: upscaler.py:122
|
||||
#: upscaler.py:126
|
||||
msgid "Upscaled frames are being saved to: {}"
|
||||
msgstr "已放大的帧将被保存到:{}"
|
||||
|
||||
#: upscaler.py:132
|
||||
#: upscaler.py:136
|
||||
msgid "Cleaning up cache directory: {}"
|
||||
msgstr "清理缓存目录:{}"
|
||||
|
||||
#: upscaler.py:135
|
||||
#: upscaler.py:141
|
||||
msgid "Unable to delete: {}"
|
||||
msgstr "无法删除:{}"
|
||||
|
||||
#: upscaler.py:141 upscaler.py:156 upscaler.py:167
|
||||
#: upscaler.py:147 upscaler.py:162 upscaler.py:173
|
||||
msgid "Input and output path type mismatch"
|
||||
msgstr "输入和输出路径类型不匹配"
|
||||
|
||||
#: upscaler.py:142
|
||||
#: upscaler.py:148
|
||||
msgid "Input is multiple files but output is not directory"
|
||||
msgstr "输入是多个文件,但输出不是目录"
|
||||
|
||||
#: upscaler.py:146
|
||||
#: upscaler.py:152
|
||||
msgid "Input path {} is neither a file nor a directory"
|
||||
msgstr "输入路径 {} 既不是文件也不是目录"
|
||||
|
||||
#: upscaler.py:150 upscaler.py:172
|
||||
#: upscaler.py:156 upscaler.py:178
|
||||
msgid "Input directory and output directory cannot be the same"
|
||||
msgstr "输入目录和输出目录不能相同"
|
||||
|
||||
#: upscaler.py:157
|
||||
#: upscaler.py:163
|
||||
msgid "Input is single file but output is directory"
|
||||
msgstr "所选的输入路径是单个文件,但输出路径是目录"
|
||||
|
||||
#: upscaler.py:160
|
||||
#: upscaler.py:166
|
||||
msgid "No suffix found in output file path"
|
||||
msgstr "在输出文件路径中未找到后缀"
|
||||
|
||||
#: upscaler.py:161
|
||||
#: upscaler.py:167
|
||||
msgid "Suffix must be specified"
|
||||
msgstr "必须指定文件后缀"
|
||||
|
||||
#: upscaler.py:168
|
||||
#: upscaler.py:174
|
||||
msgid "Input is directory but output is existing single file"
|
||||
msgstr "输入是目录,但输出是现有的单个文件"
|
||||
|
||||
#: upscaler.py:177
|
||||
#: upscaler.py:183
|
||||
msgid "Input path is neither a file nor a directory"
|
||||
msgstr "输入路径既不是文件也不是目录"
|
||||
|
||||
#: upscaler.py:186
|
||||
#: upscaler.py:192
|
||||
msgid "FFmpeg or FFprobe cannot be found under the specified path"
|
||||
msgstr "在指定的路径下找不到 FFmpeg 或 FFprobe"
|
||||
|
||||
#: upscaler.py:187 upscaler.py:197
|
||||
#: upscaler.py:193 upscaler.py:203
|
||||
msgid "Please check the configuration file settings"
|
||||
msgstr "请检查配置文件设置"
|
||||
|
||||
#: upscaler.py:196
|
||||
#: upscaler.py:202
|
||||
msgid "Specified driver executable directory doesn't exist"
|
||||
msgstr "指定驱动的可执行文件不存在"
|
||||
|
||||
#: upscaler.py:223
|
||||
#: upscaler.py:229
|
||||
msgid "Failed to parse driver argument: {}"
|
||||
msgstr "解析驱动程序参数失败:{}"
|
||||
|
||||
#: upscaler.py:248
|
||||
msgid "Anime4KCPP doesn't yet support GIF processing"
|
||||
msgstr "Anime4KCPP 尚不支持GIF处理"
|
||||
|
||||
#: upscaler.py:263
|
||||
#: upscaler.py:261
|
||||
msgid "Unrecognized driver: {}"
|
||||
msgstr "无法识别的驱动名称:{}"
|
||||
|
||||
#: upscaler.py:303
|
||||
#: upscaler.py:301
|
||||
msgid "Starting progress monitor"
|
||||
msgstr "启动进度监视器"
|
||||
|
||||
#: upscaler.py:308
|
||||
#: upscaler.py:306
|
||||
msgid "Starting upscaled image cleaner"
|
||||
msgstr "启动已放大图像清理程序"
|
||||
|
||||
#: upscaler.py:317 upscaler.py:334
|
||||
#: upscaler.py:315 upscaler.py:332
|
||||
msgid "Killing progress monitor"
|
||||
msgstr "终结进度监视器"
|
||||
|
||||
#: upscaler.py:320 upscaler.py:337
|
||||
#: upscaler.py:318 upscaler.py:335
|
||||
msgid "Killing upscaled image cleaner"
|
||||
msgstr "终结已放大图像清理程序"
|
||||
|
||||
#: upscaler.py:341
|
||||
#: upscaler.py:339
|
||||
msgid "Terminating all processes"
|
||||
msgstr "正在终止所有进程"
|
||||
|
||||
#: upscaler.py:348
|
||||
#: upscaler.py:346
|
||||
msgid "Main process waiting for subprocesses to exit"
|
||||
msgstr "主进程开始等待子进程结束"
|
||||
|
||||
#: upscaler.py:367 upscaler.py:371
|
||||
#: upscaler.py:365 upscaler.py:369
|
||||
msgid "Subprocess {} exited with code {}"
|
||||
msgstr "子进程 {} 结束,返回码 {}"
|
||||
|
||||
#: upscaler.py:377
|
||||
#: upscaler.py:375
|
||||
msgid "Stop signal received"
|
||||
msgstr "收到停止信号"
|
||||
|
||||
#: upscaler.py:382
|
||||
#: upscaler.py:380
|
||||
msgid "Subprocess execution ran into an error"
|
||||
msgstr "子进程执行遇到错误"
|
||||
|
||||
#: upscaler.py:430
|
||||
msgid "Upscaling single file: {}"
|
||||
msgstr "放大单个文件:{}"
|
||||
#: upscaler.py:410
|
||||
msgid "Loading files into processing queue"
|
||||
msgstr "正在将文件添加到处理队列中"
|
||||
|
||||
#: upscaler.py:466
|
||||
#: upscaler.py:415
|
||||
msgid "Loading files from multiple paths"
|
||||
msgstr "正在从多个路径中导入文件"
|
||||
|
||||
#: upscaler.py:416 upscaler.py:435 upscaler.py:442
|
||||
msgid "Input path(s): {}"
|
||||
msgstr "输入路径:{}"
|
||||
|
||||
#: upscaler.py:434
|
||||
msgid "Loading single file"
|
||||
msgstr "正在导入单个文件"
|
||||
|
||||
#: upscaler.py:441
|
||||
msgid "Loading files from directory"
|
||||
msgstr "正在从文件夹中导入文件"
|
||||
|
||||
#: upscaler.py:455
|
||||
msgid "Loaded files into processing queue"
|
||||
msgstr "文件已添加到处理队列"
|
||||
|
||||
#: upscaler.py:458
|
||||
msgid "Input file: {}"
|
||||
msgstr "输入文件:{}"
|
||||
|
||||
#: upscaler.py:485
|
||||
msgid "Starting to upscale image"
|
||||
msgstr "开始放大图像"
|
||||
|
||||
#: upscaler.py:469 upscaler.py:487 upscaler.py:545
|
||||
#: upscaler.py:488 upscaler.py:550
|
||||
msgid "Upscaling completed"
|
||||
msgstr "放大完成"
|
||||
|
||||
#: upscaler.py:482
|
||||
msgid "Starting to upscale video with Anime4KCPP"
|
||||
msgstr "开始用 Anime4KCPP 放大视频"
|
||||
|
||||
#: upscaler.py:496
|
||||
#: upscaler.py:502
|
||||
msgid "Reading video information"
|
||||
msgstr "读取视频信息"
|
||||
|
||||
#: upscaler.py:510
|
||||
#: upscaler.py:516
|
||||
msgid "Aborting: No video stream found"
|
||||
msgstr "程序中止:文件中未找到视频流"
|
||||
|
||||
#: upscaler.py:531
|
||||
msgid "Unsupported pixel format: {}"
|
||||
msgstr "不支持的像素格式:{}"
|
||||
|
||||
#: upscaler.py:534
|
||||
#: upscaler.py:521
|
||||
msgid "Framerate: {}"
|
||||
msgstr "帧率:{}"
|
||||
|
||||
#: upscaler.py:543
|
||||
#: upscaler.py:538
|
||||
msgid "Unsupported pixel format: {}"
|
||||
msgstr "不支持的像素格式:{}"
|
||||
|
||||
#: upscaler.py:548
|
||||
msgid "Starting to upscale extracted frames"
|
||||
msgstr "开始对提取的帧进行放大"
|
||||
|
||||
#: upscaler.py:550
|
||||
msgid "File {} ({}) neither an image of a video"
|
||||
#: upscaler.py:555
|
||||
msgid "File {} ({}) neither an image nor a video"
|
||||
msgstr "文件 {} ({}) 既不是图片也不是视频"
|
||||
|
||||
#: upscaler.py:551
|
||||
#: upscaler.py:556
|
||||
msgid "Skipping this file"
|
||||
msgstr "将跳过此文件"
|
||||
|
||||
#: upscaler.py:561
|
||||
#: upscaler.py:566
|
||||
msgid "Converting extracted frames into GIF image"
|
||||
msgstr "正在将提取的帧转换为 GIF"
|
||||
|
||||
#: upscaler.py:565 upscaler.py:574
|
||||
#: upscaler.py:570 upscaler.py:579
|
||||
msgid "Conversion completed"
|
||||
msgstr "转换已完成"
|
||||
|
||||
#: upscaler.py:570
|
||||
#: upscaler.py:575
|
||||
msgid "Converting extracted frames into video"
|
||||
msgstr "正在将提取的帧转换为视频"
|
||||
|
||||
#: upscaler.py:578
|
||||
#: upscaler.py:583
|
||||
msgid "Migrating audio, subtitles and other streams to upscaled video"
|
||||
msgstr "正在将音频、字幕和其他流迁移到放大后的视频"
|
||||
|
||||
#: upscaler.py:587
|
||||
#: upscaler.py:593
|
||||
msgid "Failed to migrate streams"
|
||||
msgstr "迁移流失败"
|
||||
|
||||
#: upscaler.py:588
|
||||
#: upscaler.py:594
|
||||
msgid "Trying to output video without additional streams"
|
||||
msgstr "正在尝试输出不含其他流的视频"
|
||||
|
||||
#: upscaler.py:599
|
||||
msgid "Output video file exists, aborting"
|
||||
msgstr "输出目标文件已存在,取消输出"
|
||||
#: upscaler.py:610
|
||||
msgid "Output video file exists"
|
||||
msgstr "输出目标文件已存在"
|
||||
|
||||
#: upscaler.py:603
|
||||
#: upscaler.py:614
|
||||
msgid "Created temporary directory to contain file"
|
||||
msgstr "为文件创建了临时目录"
|
||||
|
||||
#: upscaler.py:617
|
||||
msgid "Writing intermediate file to: {}"
|
||||
msgstr "正在将中间视频文件写入至:{}"
|
||||
|
||||
#: video2x.py:84
|
||||
#: video2x.py:85
|
||||
msgid ""
|
||||
"Video2X Version: {}\n"
|
||||
"Video2X CLI Version: {}\n"
|
||||
"Upscaler Version: {}\n"
|
||||
"Author: K4YT3X\n"
|
||||
"License: GNU GPL v3\n"
|
||||
"Github Page: https://github.com/k4yt3x/video2x\n"
|
||||
"Contact: k4yt3x@k4yt3x.com"
|
||||
msgstr ""
|
||||
"Video2X 版本: {}\n"
|
||||
"放大组件版本:{}\n"
|
||||
"作者: K4YT3X\n"
|
||||
"开源许可: GNU GPL v3\n"
|
||||
"GitHub 主页:https://github.com/k4yt3x/video2x\n"
|
||||
"联系方式:k4yt3x@k4yt3x.com"
|
||||
|
||||
#: video2x.py:106
|
||||
#: video2x.py:108
|
||||
msgid "Video2X Options"
|
||||
msgstr "Video2X 选项"
|
||||
|
||||
#: video2x.py:107
|
||||
#: video2x.py:109
|
||||
msgid "show this help message and exit"
|
||||
msgstr "显示此帮助消息并退出"
|
||||
|
||||
#: video2x.py:108
|
||||
#: video2x.py:110
|
||||
msgid "source video file/directory"
|
||||
msgstr "源视频文件/目录"
|
||||
|
||||
#: video2x.py:109
|
||||
#: video2x.py:111
|
||||
msgid "output video file/directory"
|
||||
msgstr "输出视频文件/目录"
|
||||
|
||||
#: video2x.py:110
|
||||
#: video2x.py:112
|
||||
msgid "video2x config file path"
|
||||
msgstr "video2x 配置文件路径"
|
||||
|
||||
#: video2x.py:112
|
||||
#: video2x.py:114
|
||||
msgid "display version, lawful information and exit"
|
||||
msgstr "显示版本和法律信息并退出"
|
||||
|
||||
#: video2x.py:115
|
||||
#: video2x.py:117
|
||||
msgid "Upscaling Options"
|
||||
msgstr "视频放大选项"
|
||||
|
||||
#: video2x.py:116
|
||||
#: video2x.py:118
|
||||
msgid "upscaling driver"
|
||||
msgstr "视频放大驱动"
|
||||
|
||||
#: video2x.py:117
|
||||
#: video2x.py:119
|
||||
msgid "scaling ratio"
|
||||
msgstr "缩放比"
|
||||
|
||||
#: video2x.py:118
|
||||
#: video2x.py:120
|
||||
msgid "number of processes to use for upscaling"
|
||||
msgstr "并发进程数"
|
||||
|
||||
#: video2x.py:119
|
||||
#: video2x.py:121
|
||||
msgid "preserve extracted and upscaled frames"
|
||||
msgstr "保留提取的和放大的帧"
|
||||
|
||||
#: video2x.py:159
|
||||
#: video2x.py:161
|
||||
msgid "This file cannot be imported"
|
||||
msgstr "此文件无法被当作模块导入"
|
||||
|
||||
#: video2x.py:234
|
||||
#: video2x.py:236
|
||||
msgid "Program completed, taking {} seconds"
|
||||
msgstr "程序执行完毕,总计花费 {} 秒"
|
||||
|
||||
#: video2x.py:237
|
||||
#: video2x.py:239
|
||||
msgid "An exception has occurred"
|
||||
msgstr "发生了异常"
|
||||
|
||||
#~ msgid "Anime4KCPP doesn't yet support GIF processing"
|
||||
#~ msgstr "Anime4KCPP 尚不支持GIF处理"
|
||||
|
||||
#~ msgid "Starting to upscale video with Anime4KCPP"
|
||||
#~ msgstr "开始用 Anime4KCPP 放大视频"
|
||||
|
||||
#~ msgid "output video width"
|
||||
#~ msgstr "输出视频宽度"
|
||||
|
||||
@@ -317,6 +345,3 @@ msgstr "发生了异常"
|
||||
|
||||
#~ msgid "You must specify both width and height"
|
||||
#~ msgstr "您必须同时指定宽度和高度"
|
||||
|
||||
#~ msgid "Upscaling videos in directory: {}"
|
||||
#~ msgstr "放大该文件夹中的所有视频:{}"
|
||||
|
||||
0
src/progress_monitor.py
Normal file → Executable file
0
src/progress_monitor.py
Normal file → Executable file
10
src/requirements-linux.txt
Normal file
10
src/requirements-linux.txt
Normal file
@@ -0,0 +1,10 @@
|
||||
avalon_framework
|
||||
colorama
|
||||
patool
|
||||
psutil
|
||||
pyqt5
|
||||
python-magic
|
||||
pyunpack
|
||||
pyyaml
|
||||
requests
|
||||
tqdm
|
||||
@@ -4,7 +4,7 @@
|
||||
Name: Video2X Upscaler
|
||||
Author: K4YT3X
|
||||
Date Created: December 10, 2018
|
||||
Last Modified: May 16, 2020
|
||||
Last Modified: May 29, 2020
|
||||
|
||||
Description: This file contains the Upscaler class. Each
|
||||
instance of the Upscaler class is an upscaler on an image or
|
||||
@@ -25,6 +25,7 @@ import copy
|
||||
import gettext
|
||||
import importlib
|
||||
import locale
|
||||
import mimetypes
|
||||
import pathlib
|
||||
import queue
|
||||
import re
|
||||
@@ -49,7 +50,7 @@ language.install()
|
||||
_ = language.gettext
|
||||
|
||||
# version information
|
||||
UPSCALER_VERSION = '4.1.0'
|
||||
UPSCALER_VERSION = '4.2.0'
|
||||
|
||||
# these names are consistent for
|
||||
# - driver selection in command line
|
||||
@@ -59,6 +60,7 @@ AVAILABLE_DRIVERS = ['waifu2x_caffe',
|
||||
'waifu2x_converter_cpp',
|
||||
'waifu2x_ncnn_vulkan',
|
||||
'srmd_ncnn_vulkan',
|
||||
'realsr_ncnn_vulkan',
|
||||
'anime4kcpp']
|
||||
|
||||
|
||||
@@ -134,7 +136,9 @@ class Upscaler:
|
||||
# therefore, plain print is used
|
||||
print(_('Cleaning up cache directory: {}').format(directory))
|
||||
shutil.rmtree(directory)
|
||||
except (OSError, FileNotFoundError):
|
||||
except FileNotFoundError:
|
||||
pass
|
||||
except OSError:
|
||||
print(_('Unable to delete: {}').format(directory))
|
||||
traceback.print_exc()
|
||||
|
||||
@@ -278,7 +282,7 @@ class Upscaler:
|
||||
process_directory.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
# waifu2x-converter-cpp will perform multi-threading within its own process
|
||||
if self.driver in ['waifu2x_converter_cpp', 'waifu2x_ncnn_vulkan', 'srmd_ncnn_vulkan']:
|
||||
if self.driver in ['waifu2x_converter_cpp', 'waifu2x_ncnn_vulkan', 'srmd_ncnn_vulkan', 'realsr_ncnn_vulkan', 'anime4kcpp']:
|
||||
process_directories = [self.extracted_frames]
|
||||
|
||||
else:
|
||||
@@ -404,8 +408,14 @@ class Upscaler:
|
||||
# define processing queue
|
||||
self.processing_queue = queue.Queue()
|
||||
|
||||
Avalon.info(_('Loading files into processing queue'))
|
||||
|
||||
# if input is a list of files
|
||||
if isinstance(self.input, list):
|
||||
|
||||
Avalon.info(_('Loading files from multiple paths'))
|
||||
Avalon.debug_info(_('Input path(s): {}').format(self.input))
|
||||
|
||||
# make output directory if it doesn't exist
|
||||
self.output.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
@@ -422,12 +432,15 @@ class Upscaler:
|
||||
|
||||
# if input specified is single file
|
||||
elif self.input.is_file():
|
||||
Avalon.info(_('Upscaling single file: {}').format(self.input))
|
||||
Avalon.info(_('Loading single file'))
|
||||
Avalon.debug_info(_('Input path(s): {}').format(self.input))
|
||||
self.processing_queue.put((self.input.absolute(), self.output.absolute()))
|
||||
|
||||
# if input specified is a directory
|
||||
elif self.input.is_dir():
|
||||
|
||||
Avalon.info(_('Loading files from directory'))
|
||||
Avalon.debug_info(_('Input path(s): {}').format(self.input))
|
||||
# make output directory if it doesn't exist
|
||||
self.output.mkdir(parents=True, exist_ok=True)
|
||||
for input_path in [f for f in self.input.iterdir() if f.is_file()]:
|
||||
@@ -440,6 +453,11 @@ class Upscaler:
|
||||
# record file count for external calls
|
||||
self.total_files = self.processing_queue.qsize()
|
||||
|
||||
Avalon.info(_('Loaded files into processing queue'))
|
||||
# print all files in queue for debugging
|
||||
for job in self.processing_queue.queue:
|
||||
Avalon.debug_info(_('Input file: {}').format(job[0].absolute()))
|
||||
|
||||
try:
|
||||
while not self.processing_queue.empty():
|
||||
|
||||
@@ -455,6 +473,13 @@ class Upscaler:
|
||||
input_file_type = input_file_mime_type.split('/')[0]
|
||||
input_file_subtype = input_file_mime_type.split('/')[1]
|
||||
|
||||
# in case python-magic fails to detect file type
|
||||
# try guessing file mime type with mimetypes
|
||||
if input_file_type not in ['image', 'video']:
|
||||
input_file_mime_type = mimetypes.guess_type(self.current_input_file.name)[0]
|
||||
input_file_type = input_file_mime_type.split('/')[0]
|
||||
input_file_subtype = input_file_mime_type.split('/')[1]
|
||||
|
||||
# start handling input
|
||||
# if input file is a static image
|
||||
if input_file_type == 'image' and input_file_subtype != 'gif':
|
||||
@@ -528,7 +553,7 @@ class Upscaler:
|
||||
# if file is none of: image, image/gif, video
|
||||
# skip to the next task
|
||||
else:
|
||||
Avalon.error(_('File {} ({}) neither an image of a video').format(self.current_input_file, input_file_mime_type))
|
||||
Avalon.error(_('File {} ({}) neither an image nor a video').format(self.current_input_file, input_file_mime_type))
|
||||
Avalon.warning(_('Skipping this file'))
|
||||
self.processing_queue.task_done()
|
||||
self.total_processed += 1
|
||||
|
||||
179
src/video2x.pot
179
src/video2x.pot
@@ -5,7 +5,7 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"POT-Creation-Date: 2020-05-12 04:27-0400\n"
|
||||
"POT-Creation-Date: 2020-05-22 17:51-0400\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
@@ -19,268 +19,289 @@ msgstr ""
|
||||
msgid "Upscaling Progress"
|
||||
msgstr ""
|
||||
|
||||
#: upscaler.py:106
|
||||
#: upscaler.py:110
|
||||
msgid "Specified or default cache directory is a file/link"
|
||||
msgstr ""
|
||||
|
||||
#: upscaler.py:112
|
||||
#: upscaler.py:116
|
||||
msgid "Creating cache directory {}"
|
||||
msgstr ""
|
||||
|
||||
#: upscaler.py:115
|
||||
#: upscaler.py:119
|
||||
msgid "Unable to create {}"
|
||||
msgstr ""
|
||||
|
||||
#: upscaler.py:120
|
||||
#: upscaler.py:124
|
||||
msgid "Extracted frames are being saved to: {}"
|
||||
msgstr ""
|
||||
|
||||
#: upscaler.py:122
|
||||
#: upscaler.py:126
|
||||
msgid "Upscaled frames are being saved to: {}"
|
||||
msgstr ""
|
||||
|
||||
#: upscaler.py:132
|
||||
#: upscaler.py:136
|
||||
msgid "Cleaning up cache directory: {}"
|
||||
msgstr ""
|
||||
|
||||
#: upscaler.py:135
|
||||
#: upscaler.py:141
|
||||
msgid "Unable to delete: {}"
|
||||
msgstr ""
|
||||
|
||||
#: upscaler.py:141 upscaler.py:156 upscaler.py:167
|
||||
#: upscaler.py:147 upscaler.py:162 upscaler.py:173
|
||||
msgid "Input and output path type mismatch"
|
||||
msgstr ""
|
||||
|
||||
#: upscaler.py:142
|
||||
#: upscaler.py:148
|
||||
msgid "Input is multiple files but output is not directory"
|
||||
msgstr ""
|
||||
|
||||
#: upscaler.py:146
|
||||
#: upscaler.py:152
|
||||
msgid "Input path {} is neither a file nor a directory"
|
||||
msgstr ""
|
||||
|
||||
#: upscaler.py:150 upscaler.py:172
|
||||
#: upscaler.py:156 upscaler.py:178
|
||||
msgid "Input directory and output directory cannot be the same"
|
||||
msgstr ""
|
||||
|
||||
#: upscaler.py:157
|
||||
#: upscaler.py:163
|
||||
msgid "Input is single file but output is directory"
|
||||
msgstr ""
|
||||
|
||||
#: upscaler.py:160
|
||||
#: upscaler.py:166
|
||||
msgid "No suffix found in output file path"
|
||||
msgstr ""
|
||||
|
||||
#: upscaler.py:161
|
||||
#: upscaler.py:167
|
||||
msgid "Suffix must be specified"
|
||||
msgstr ""
|
||||
|
||||
#: upscaler.py:168
|
||||
#: upscaler.py:174
|
||||
msgid "Input is directory but output is existing single file"
|
||||
msgstr ""
|
||||
|
||||
#: upscaler.py:177
|
||||
#: upscaler.py:183
|
||||
msgid "Input path is neither a file nor a directory"
|
||||
msgstr ""
|
||||
|
||||
#: upscaler.py:186
|
||||
#: upscaler.py:192
|
||||
msgid "FFmpeg or FFprobe cannot be found under the specified path"
|
||||
msgstr ""
|
||||
|
||||
#: upscaler.py:187 upscaler.py:197
|
||||
#: upscaler.py:193 upscaler.py:203
|
||||
msgid "Please check the configuration file settings"
|
||||
msgstr ""
|
||||
|
||||
#: upscaler.py:196
|
||||
#: upscaler.py:202
|
||||
msgid "Specified driver executable directory doesn't exist"
|
||||
msgstr ""
|
||||
|
||||
#: upscaler.py:223
|
||||
#: upscaler.py:229
|
||||
msgid "Failed to parse driver argument: {}"
|
||||
msgstr ""
|
||||
|
||||
#: upscaler.py:248
|
||||
msgid "Anime4KCPP doesn't yet support GIF processing"
|
||||
msgstr ""
|
||||
|
||||
#: upscaler.py:263
|
||||
#: upscaler.py:261
|
||||
msgid "Unrecognized driver: {}"
|
||||
msgstr ""
|
||||
|
||||
#: upscaler.py:303
|
||||
#: upscaler.py:301
|
||||
msgid "Starting progress monitor"
|
||||
msgstr ""
|
||||
|
||||
#: upscaler.py:308
|
||||
#: upscaler.py:306
|
||||
msgid "Starting upscaled image cleaner"
|
||||
msgstr ""
|
||||
|
||||
#: upscaler.py:317 upscaler.py:334
|
||||
#: upscaler.py:315 upscaler.py:332
|
||||
msgid "Killing progress monitor"
|
||||
msgstr ""
|
||||
|
||||
#: upscaler.py:320 upscaler.py:337
|
||||
#: upscaler.py:318 upscaler.py:335
|
||||
msgid "Killing upscaled image cleaner"
|
||||
msgstr ""
|
||||
|
||||
#: upscaler.py:341
|
||||
#: upscaler.py:339
|
||||
msgid "Terminating all processes"
|
||||
msgstr ""
|
||||
|
||||
#: upscaler.py:348
|
||||
#: upscaler.py:346
|
||||
msgid "Main process waiting for subprocesses to exit"
|
||||
msgstr ""
|
||||
|
||||
#: upscaler.py:367 upscaler.py:371
|
||||
#: upscaler.py:365 upscaler.py:369
|
||||
msgid "Subprocess {} exited with code {}"
|
||||
msgstr ""
|
||||
|
||||
#: upscaler.py:377
|
||||
#: upscaler.py:375
|
||||
msgid "Stop signal received"
|
||||
msgstr ""
|
||||
|
||||
#: upscaler.py:382
|
||||
#: upscaler.py:380
|
||||
msgid "Subprocess execution ran into an error"
|
||||
msgstr ""
|
||||
|
||||
#: upscaler.py:430
|
||||
msgid "Upscaling single file: {}"
|
||||
#: upscaler.py:410
|
||||
msgid "Loading files into processing queue"
|
||||
msgstr ""
|
||||
|
||||
#: upscaler.py:466
|
||||
#: upscaler.py:415
|
||||
msgid "Loading files from multiple paths"
|
||||
msgstr ""
|
||||
|
||||
#: upscaler.py:416 upscaler.py:435 upscaler.py:442
|
||||
msgid "Input path(s): {}"
|
||||
msgstr ""
|
||||
|
||||
#: upscaler.py:434
|
||||
msgid "Loading single file"
|
||||
msgstr ""
|
||||
|
||||
#: upscaler.py:441
|
||||
msgid "Loading files from directory"
|
||||
msgstr ""
|
||||
|
||||
#: upscaler.py:455
|
||||
msgid "Loaded files into processing queue"
|
||||
msgstr ""
|
||||
|
||||
#: upscaler.py:458
|
||||
msgid "Input file: {}"
|
||||
msgstr ""
|
||||
|
||||
#: upscaler.py:485
|
||||
msgid "Starting to upscale image"
|
||||
msgstr ""
|
||||
|
||||
#: upscaler.py:469 upscaler.py:487 upscaler.py:545
|
||||
#: upscaler.py:488 upscaler.py:550
|
||||
msgid "Upscaling completed"
|
||||
msgstr ""
|
||||
|
||||
#: upscaler.py:482
|
||||
msgid "Starting to upscale video with Anime4KCPP"
|
||||
msgstr ""
|
||||
|
||||
#: upscaler.py:496
|
||||
#: upscaler.py:502
|
||||
msgid "Reading video information"
|
||||
msgstr ""
|
||||
|
||||
#: upscaler.py:510
|
||||
#: upscaler.py:516
|
||||
msgid "Aborting: No video stream found"
|
||||
msgstr ""
|
||||
|
||||
#: upscaler.py:531
|
||||
msgid "Unsupported pixel format: {}"
|
||||
msgstr ""
|
||||
|
||||
#: upscaler.py:534
|
||||
#: upscaler.py:521
|
||||
msgid "Framerate: {}"
|
||||
msgstr ""
|
||||
|
||||
#: upscaler.py:543
|
||||
#: upscaler.py:538
|
||||
msgid "Unsupported pixel format: {}"
|
||||
msgstr ""
|
||||
|
||||
#: upscaler.py:548
|
||||
msgid "Starting to upscale extracted frames"
|
||||
msgstr ""
|
||||
|
||||
#: upscaler.py:550
|
||||
msgid "File {} ({}) neither an image of a video"
|
||||
#: upscaler.py:555
|
||||
msgid "File {} ({}) neither an image nor a video"
|
||||
msgstr ""
|
||||
|
||||
#: upscaler.py:551
|
||||
#: upscaler.py:556
|
||||
msgid "Skipping this file"
|
||||
msgstr ""
|
||||
|
||||
#: upscaler.py:561
|
||||
#: upscaler.py:566
|
||||
msgid "Converting extracted frames into GIF image"
|
||||
msgstr ""
|
||||
|
||||
#: upscaler.py:565 upscaler.py:574
|
||||
#: upscaler.py:570 upscaler.py:579
|
||||
msgid "Conversion completed"
|
||||
msgstr ""
|
||||
|
||||
#: upscaler.py:570
|
||||
#: upscaler.py:575
|
||||
msgid "Converting extracted frames into video"
|
||||
msgstr ""
|
||||
|
||||
#: upscaler.py:578
|
||||
#: upscaler.py:583
|
||||
msgid "Migrating audio, subtitles and other streams to upscaled video"
|
||||
msgstr ""
|
||||
|
||||
#: upscaler.py:587
|
||||
#: upscaler.py:593
|
||||
msgid "Failed to migrate streams"
|
||||
msgstr ""
|
||||
|
||||
#: upscaler.py:588
|
||||
#: upscaler.py:594
|
||||
msgid "Trying to output video without additional streams"
|
||||
msgstr ""
|
||||
|
||||
#: upscaler.py:599
|
||||
msgid "Output video file exists, aborting"
|
||||
#: upscaler.py:610
|
||||
msgid "Output video file exists"
|
||||
msgstr ""
|
||||
|
||||
#: upscaler.py:603
|
||||
#: upscaler.py:614
|
||||
msgid "Created temporary directory to contain file"
|
||||
msgstr ""
|
||||
|
||||
#: upscaler.py:617
|
||||
msgid "Writing intermediate file to: {}"
|
||||
msgstr ""
|
||||
|
||||
#: video2x.py:84
|
||||
#: video2x.py:85
|
||||
msgid ""
|
||||
"Video2X Version: {}\n"
|
||||
"Video2X CLI Version: {}\n"
|
||||
"Upscaler Version: {}\n"
|
||||
"Author: K4YT3X\n"
|
||||
"License: GNU GPL v3\n"
|
||||
"Github Page: https://github.com/k4yt3x/video2x\n"
|
||||
"Contact: k4yt3x@k4yt3x.com"
|
||||
msgstr ""
|
||||
|
||||
#: video2x.py:106
|
||||
#: video2x.py:108
|
||||
msgid "Video2X Options"
|
||||
msgstr ""
|
||||
|
||||
#: video2x.py:107
|
||||
#: video2x.py:109
|
||||
msgid "show this help message and exit"
|
||||
msgstr ""
|
||||
|
||||
#: video2x.py:108
|
||||
#: video2x.py:110
|
||||
msgid "source video file/directory"
|
||||
msgstr ""
|
||||
|
||||
#: video2x.py:109
|
||||
#: video2x.py:111
|
||||
msgid "output video file/directory"
|
||||
msgstr ""
|
||||
|
||||
#: video2x.py:110
|
||||
#: video2x.py:112
|
||||
msgid "video2x config file path"
|
||||
msgstr ""
|
||||
|
||||
#: video2x.py:112
|
||||
#: video2x.py:114
|
||||
msgid "display version, lawful information and exit"
|
||||
msgstr ""
|
||||
|
||||
#: video2x.py:115
|
||||
#: video2x.py:117
|
||||
msgid "Upscaling Options"
|
||||
msgstr ""
|
||||
|
||||
#: video2x.py:116
|
||||
#: video2x.py:118
|
||||
msgid "upscaling driver"
|
||||
msgstr ""
|
||||
|
||||
#: video2x.py:117
|
||||
#: video2x.py:119
|
||||
msgid "scaling ratio"
|
||||
msgstr ""
|
||||
|
||||
#: video2x.py:118
|
||||
#: video2x.py:120
|
||||
msgid "number of processes to use for upscaling"
|
||||
msgstr ""
|
||||
|
||||
#: video2x.py:119
|
||||
#: video2x.py:121
|
||||
msgid "preserve extracted and upscaled frames"
|
||||
msgstr ""
|
||||
|
||||
#: video2x.py:159
|
||||
#: video2x.py:161
|
||||
msgid "This file cannot be imported"
|
||||
msgstr ""
|
||||
|
||||
#: video2x.py:234
|
||||
#: video2x.py:236
|
||||
msgid "Program completed, taking {} seconds"
|
||||
msgstr ""
|
||||
|
||||
#: video2x.py:237
|
||||
#: video2x.py:239
|
||||
msgid "An exception has occurred"
|
||||
msgstr ""
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ __ __ _ _ ___ __ __
|
||||
Name: Video2X Controller
|
||||
Creator: K4YT3X
|
||||
Date Created: Feb 24, 2018
|
||||
Last Modified: May 15, 2020
|
||||
Last Modified: May 23, 2020
|
||||
|
||||
Editor: BrianPetkovsek
|
||||
Last Modified: June 17, 2019
|
||||
@@ -80,7 +80,7 @@ language.install()
|
||||
_ = language.gettext
|
||||
|
||||
|
||||
CLI_VERSION = '4.0.0'
|
||||
CLI_VERSION = '4.0.1'
|
||||
|
||||
LEGAL_INFO = _('''Video2X CLI Version: {}
|
||||
Upscaler Version: {}
|
||||
@@ -107,8 +107,15 @@ def parse_arguments():
|
||||
# video options
|
||||
video2x_options = parser.add_argument_group(_('Video2X Options'))
|
||||
video2x_options.add_argument('-h', '--help', action='help', help=_('show this help message and exit'))
|
||||
video2x_options.add_argument('-i', '--input', type=pathlib.Path, help=_('source video file/directory'))
|
||||
video2x_options.add_argument('-o', '--output', type=pathlib.Path, help=_('output video file/directory'))
|
||||
|
||||
# if help is in arguments list
|
||||
# do not require input and output path to be specified
|
||||
require_input_output = True
|
||||
if '-h' in sys.argv or '--help' in sys.argv:
|
||||
require_input_output = False
|
||||
video2x_options.add_argument('-i', '--input', type=pathlib.Path, help=_('source video file/directory'), required=require_input_output)
|
||||
video2x_options.add_argument('-o', '--output', type=pathlib.Path, help=_('output video file/directory'), required=require_input_output)
|
||||
|
||||
video2x_options.add_argument('-c', '--config', type=pathlib.Path, help=_('video2x config file path'), action='store',
|
||||
default=pathlib.Path(__file__).parent.absolute() / 'video2x.yaml')
|
||||
video2x_options.add_argument('-v', '--version', help=_('display version, lawful information and exit'), action='store_true')
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Name: Video2X Configuration File
|
||||
# Creator: K4YT3X
|
||||
# Date Created: October 23, 2018
|
||||
# Last Modified: May 14, 2020
|
||||
# Last Modified: May 26, 2020
|
||||
# Values here are the default values. Change the value here to
|
||||
# save the default value permanently.
|
||||
# Items commented out are parameters irrelevant to this context
|
||||
@@ -76,6 +76,17 @@ srmd_ncnn_vulkan:
|
||||
g: 0 # gpu device to use (default=0)
|
||||
j: '1:2:2' # thread count for load/proc/save (default=1:2:2)
|
||||
x: false # enable tta mode
|
||||
realsr_ncnn_vulkan:
|
||||
path: '%LOCALAPPDATA%\video2x\realsr-ncnn-vulkan\realsr-ncnn-vulkan'
|
||||
v: null # verbose output
|
||||
#i: null # input-path: input image path (jpg/png) or directory
|
||||
#o: null # output-path: output image path (png) or directory
|
||||
s: 4 # upscale ratio (4, default=4)
|
||||
t: 0 # tile size (>=32/0=auto, default=0)
|
||||
m: null # realsr model path (default=models-DF2K)
|
||||
g: 0 # gpu device to use (default=0)
|
||||
j: '1:2:2' # thread count for load/proc/save (default=1:2:2)
|
||||
x: false # enable tta mode
|
||||
anime4kcpp:
|
||||
path: '%LOCALAPPDATA%\video2x\anime4kcpp\CLI\Anime4KCPP_CLI\Anime4KCPP_CLI'
|
||||
#input: null # File for loading (string [=./pic/p1.png])
|
||||
@@ -119,10 +130,11 @@ ffmpeg:
|
||||
'-f': image2 # force image2 format
|
||||
output_options:
|
||||
'-vcodec': libx264 # video codec
|
||||
'-pix_fmt': 'yuv444p10le' # overwrite default pixel format
|
||||
'-pix_fmt': 'yuv420p' # overwrite default pixel format
|
||||
'-crf': 17 # H.264 Constant Rate Factor
|
||||
'-b:v': null # target average bitrate
|
||||
'-vf': 'pad=ceil(iw/2)*2:ceil(ih/2)*2' # ensure output is divisible by 2, recommended for libx264
|
||||
'-tune': 'animation' # encoding tuning film/animation/grain/stillimage/fastdecode/zerolatency/psnr/ssim
|
||||
# Step 3: Streams Migration
|
||||
# migrate audio and subtitle streams from original
|
||||
# video into the upscaled video
|
||||
@@ -138,6 +150,7 @@ ffmpeg:
|
||||
- '1:d?' # copy data streams
|
||||
- '1:t?' # copy fonts
|
||||
'-c': copy # copy codec for all streams
|
||||
# '-vf': 'minterpolate=''fps=60''' # minterpolate frame interpolation
|
||||
'-map_metadata': 0 # copy known metadata tags
|
||||
# '-movflags': 'use_metadata_tags' # copy custom/arbitrary metadata tags
|
||||
'-pix_fmt': null
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
Creator: Video2X GUI
|
||||
Author: K4YT3X
|
||||
Date Created: May 5, 2020
|
||||
Last Modified: May 15, 2020
|
||||
Last Modified: May 26, 2020
|
||||
"""
|
||||
|
||||
# local imports
|
||||
@@ -15,6 +15,7 @@ from wrappers.ffmpeg import Ffmpeg
|
||||
# built-in imports
|
||||
import contextlib
|
||||
import json
|
||||
import mimetypes
|
||||
import os
|
||||
import pathlib
|
||||
import sys
|
||||
@@ -25,13 +26,13 @@ import urllib
|
||||
import yaml
|
||||
|
||||
# third-party imports
|
||||
from PyQt5 import QtGui, uic
|
||||
from PyQt5 import uic
|
||||
from PyQt5.QtCore import *
|
||||
from PyQt5.QtGui import *
|
||||
from PyQt5.QtWidgets import *
|
||||
import magic
|
||||
# QObject, pyqtSlot, pyqtSignal, QRunnable, QThreadPool, QAbstractTableModel, Qt
|
||||
|
||||
GUI_VERSION = '2.1.0'
|
||||
GUI_VERSION = '2.5.0'
|
||||
|
||||
LEGAL_INFO = f'''Video2X GUI Version: {GUI_VERSION}\\
|
||||
Upscaler Version: {UPSCALER_VERSION}\\
|
||||
@@ -45,6 +46,7 @@ AVAILABLE_DRIVERS = {
|
||||
'Waifu2X Converter CPP': 'waifu2x_converter_cpp',
|
||||
'Waifu2X NCNN Vulkan': 'waifu2x_ncnn_vulkan',
|
||||
'SRMD NCNN Vulkan': 'srmd_ncnn_vulkan',
|
||||
'RealSR NCNN Vulkan': 'realsr_ncnn_vulkan',
|
||||
'Anime4KCPP': 'anime4kcpp'
|
||||
}
|
||||
|
||||
@@ -132,6 +134,14 @@ class InputTableModel(QAbstractTableModel):
|
||||
input_file_mime_type = magic.from_file(str(file_path.absolute()), mime=True)
|
||||
input_file_type = input_file_mime_type.split('/')[0]
|
||||
input_file_subtype = input_file_mime_type.split('/')[1]
|
||||
|
||||
# in case python-magic fails to detect file type
|
||||
# try guessing file mime type with mimetypes
|
||||
if input_file_type not in ['image', 'video']:
|
||||
input_file_mime_type = mimetypes.guess_type(file_path.name)[0]
|
||||
input_file_type = input_file_mime_type.split('/')[0]
|
||||
input_file_subtype = input_file_mime_type.split('/')[1]
|
||||
|
||||
if input_file_type == 'image':
|
||||
if input_file_subtype == 'gif':
|
||||
return 'GIF'
|
||||
@@ -183,11 +193,22 @@ class Video2XMainWindow(QMainWindow):
|
||||
# set window title and icon
|
||||
self.video2x_icon_path = str(resource_path('images/video2x.png'))
|
||||
self.setWindowTitle(f'Video2X GUI {GUI_VERSION}')
|
||||
self.setWindowIcon(QtGui.QIcon(self.video2x_icon_path))
|
||||
self.setWindowIcon(QIcon(self.video2x_icon_path))
|
||||
|
||||
# register shortcut keys
|
||||
QShortcut(QKeySequence(Qt.CTRL + Qt.Key_W), self, self.close)
|
||||
QShortcut(QKeySequence(Qt.CTRL + Qt.Key_Q), self, self.close)
|
||||
QShortcut(QKeySequence(Qt.CTRL + Qt.Key_I), self, self.select_input_file)
|
||||
QShortcut(QKeySequence(Qt.CTRL + Qt.Key_O), self, self.select_output_file)
|
||||
QShortcut(QKeySequence(Qt.CTRL + Qt.SHIFT + Qt.Key_I), self, self.select_input_folder)
|
||||
QShortcut(QKeySequence(Qt.CTRL + Qt.SHIFT + Qt.Key_O), self, self.select_output_folder)
|
||||
|
||||
# menu bar
|
||||
self.action_exit = self.findChild(QAction, 'actionExit')
|
||||
self.action_exit.triggered.connect(sys.exit)
|
||||
self.action_exit.triggered.connect(self.close)
|
||||
|
||||
self.action_shortcuts = self.findChild(QAction, 'actionShortcuts')
|
||||
self.action_shortcuts.triggered.connect(self.show_shortcuts)
|
||||
|
||||
self.action_about = self.findChild(QAction, 'actionAbout')
|
||||
self.action_about.triggered.connect(self.show_about)
|
||||
@@ -326,6 +347,17 @@ class Video2XMainWindow(QMainWindow):
|
||||
self.srmd_ncnn_vulkan_jobs_line_edit = self.findChild(QLineEdit, 'srmdNcnnVulkanJobsLineEdit')
|
||||
self.srmd_ncnn_vulkan_tta_check_box = self.findChild(QCheckBox, 'srmdNcnnVulkanTtaCheckBox')
|
||||
|
||||
# realsr-ncnn-vulkan
|
||||
self.realsr_ncnn_vulkan_path_line_edit = self.findChild(QLineEdit, 'realsrNcnnVulkanPathLineEdit')
|
||||
self.enable_line_edit_file_drop(self.realsr_ncnn_vulkan_path_line_edit)
|
||||
self.realsr_ncnn_vulkan_path_select_button = self.findChild(QPushButton, 'realsrNcnnVulkanPathSelectButton')
|
||||
self.realsr_ncnn_vulkan_path_select_button.clicked.connect(lambda: self.select_driver_binary_path(self.realsr_ncnn_vulkan_path_line_edit))
|
||||
self.realsr_ncnn_vulkan_tile_size_spin_box = self.findChild(QSpinBox, 'realsrNcnnVulkanTileSizeSpinBox')
|
||||
self.realsr_ncnn_vulkan_model_combo_box = self.findChild(QComboBox, 'realsrNcnnVulkanModelComboBox')
|
||||
self.realsr_ncnn_vulkan_gpu_id_spin_box = self.findChild(QSpinBox, 'realsrNcnnVulkanGpuIdSpinBox')
|
||||
self.realsr_ncnn_vulkan_jobs_line_edit = self.findChild(QLineEdit, 'realsrNcnnVulkanJobsLineEdit')
|
||||
self.realsr_ncnn_vulkan_tta_check_box = self.findChild(QCheckBox, 'realsrNcnnVulkanTtaCheckBox')
|
||||
|
||||
# anime4k
|
||||
self.anime4kcpp_path_line_edit = self.findChild(QLineEdit, 'anime4kCppPathLineEdit')
|
||||
self.enable_line_edit_file_drop(self.anime4kcpp_path_line_edit)
|
||||
@@ -363,6 +395,7 @@ class Video2XMainWindow(QMainWindow):
|
||||
self.ffmpeg_assemble_video_output_options_video_codec_line_edit = self.findChild(QLineEdit, 'ffmpegAssembleVideoOutputOptionsVideoCodecLineEdit')
|
||||
self.ffmpeg_assemble_video_output_options_pixel_format_line_edit = self.findChild(QLineEdit, 'ffmpegAssembleVideoOutputOptionsPixelFormatLineEdit')
|
||||
self.ffmpeg_assemble_video_output_options_crf_spin_box = self.findChild(QSpinBox, 'ffmpegAssembleVideoOutputOptionsCrfSpinBox')
|
||||
self.ffmpeg_assemble_video_output_options_tune_combo_box = self.findChild(QComboBox, 'ffmpegAssembleVideoOutputOptionsTuneComboBox')
|
||||
self.ffmpeg_assemble_video_output_options_bitrate_line_edit = self.findChild(QLineEdit, 'ffmpegAssembleVideoOutputOptionsBitrateLineEdit')
|
||||
self.ffmpeg_assemble_video_output_options_ensure_divisible_check_box = self.findChild(QCheckBox, 'ffmpegAssembleVideoOutputOptionsEnsureDivisibleCheckBox')
|
||||
self.ffmpeg_assemble_video_hardware_acceleration_check_box = self.findChild(QCheckBox, 'ffmpegAssembleVideoHardwareAccelerationCheckBox')
|
||||
@@ -374,9 +407,12 @@ class Video2XMainWindow(QMainWindow):
|
||||
self.ffmpeg_migrate_streams_output_options_mapping_data_check_box_check_box = self.findChild(QCheckBox, 'ffmpegMigrateStreamsOutputOptionsMappingDataCheckBox')
|
||||
self.ffmpeg_migrate_streams_output_options_mapping_font_check_box_check_box = self.findChild(QCheckBox, 'ffmpegMigrateStreamsOutputOptionsMappingFontCheckBox')
|
||||
self.ffmpeg_migrate_streams_output_options_pixel_format_line_edit = self.findChild(QLineEdit, 'ffmpegMigrateStreamsOutputOptionsPixelFormatLineEdit')
|
||||
self.ffmpeg_migrate_streams_output_options_copy_codec_check_box = self.findChild(QCheckBox, 'ffmpegMigrateStreamsOutputOptionsCopyCodecCheckBox')
|
||||
self.ffmpeg_migrate_streams_output_options_copy_known_metadata_tags_check_box = self.findChild(QCheckBox, 'ffmpegMigrateStreamsOutputOptionsOtherCopyKnownMetadataTagsCheckBox')
|
||||
self.ffmpeg_migrate_streams_output_options_copy_arbitrary_metadata_tags_check_box = self.findChild(QCheckBox, 'ffmpegMigrateStreamsOutputOptionsOtherCopyArbitraryMetadataTagsCheckBox')
|
||||
self.ffmpeg_migrate_streams_output_options_frame_interpolation_spin_box = self.findChild(QSpinBox, 'ffmpegMigrateStreamsOutputOptionsFrameInterpolationSpinBox')
|
||||
self.ffmpeg_migrate_streams_output_options_frame_interpolation_spin_box.valueChanged.connect(self.mutually_exclude_frame_interpolation_stream_copy)
|
||||
self.ffmpeg_migrate_streams_output_options_frame_interpolation_spin_box.textChanged.connect(self.mutually_exclude_frame_interpolation_stream_copy)
|
||||
self.ffmpeg_migrate_streams_output_options_copy_streams_check_box = self.findChild(QCheckBox, 'ffmpegMigrateStreamsOutputOptionsCopyStreamsCheckBox')
|
||||
self.ffmpeg_migrate_streams_output_options_copy_known_metadata_tags_check_box = self.findChild(QCheckBox, 'ffmpegMigrateStreamsOutputOptionsCopyKnownMetadataTagsCheckBox')
|
||||
self.ffmpeg_migrate_streams_output_options_copy_arbitrary_metadata_tags_check_box = self.findChild(QCheckBox, 'ffmpegMigrateStreamsOutputOptionsCopyArbitraryMetadataTagsCheckBox')
|
||||
self.ffmpeg_migrate_streams_hardware_acceleration_check_box = self.findChild(QCheckBox, 'ffmpegMigrateStreamsHardwareAccelerationCheckBox')
|
||||
|
||||
# Gifski settings
|
||||
@@ -396,48 +432,6 @@ class Video2XMainWindow(QMainWindow):
|
||||
# load configurations after GUI initialization
|
||||
self.load_configurations()
|
||||
|
||||
def dragEnterEvent(self, event):
|
||||
if event.mimeData().hasUrls():
|
||||
event.accept()
|
||||
else:
|
||||
event.ignore()
|
||||
|
||||
def dropEvent(self, event):
|
||||
input_paths = [pathlib.Path(u.toLocalFile()) for u in event.mimeData().urls()]
|
||||
for path in input_paths:
|
||||
if (path.is_file() or path.is_dir()) and not self.input_table_path_exists(path):
|
||||
self.input_table_data.append(path)
|
||||
|
||||
self.update_input_table()
|
||||
self.update_output_path()
|
||||
|
||||
def enable_line_edit_file_drop(self, line_edit: QLineEdit):
|
||||
line_edit.dragEnterEvent = self.dragEnterEvent
|
||||
line_edit.dropEvent = lambda event: line_edit.setText(str(pathlib.Path(event.mimeData().urls()[0].toLocalFile()).absolute()))
|
||||
|
||||
def show_ffprobe_output(self, event):
|
||||
input_paths = [pathlib.Path(u.toLocalFile()) for u in event.mimeData().urls()]
|
||||
if not input_paths[0].is_file():
|
||||
return
|
||||
|
||||
ffmpeg_object = Ffmpeg(self.ffmpeg_settings)
|
||||
file_info_json = ffmpeg_object.probe_file_info(input_paths[0])
|
||||
self.ffprobe_plain_text_edit.setPlainText(json.dumps(file_info_json, indent=2))
|
||||
|
||||
@staticmethod
|
||||
def read_config(config_file: pathlib.Path) -> dict:
|
||||
""" read video2x configurations from config file
|
||||
|
||||
Arguments:
|
||||
config_file {pathlib.Path} -- video2x configuration file pathlib.Path
|
||||
|
||||
Returns:
|
||||
dict -- dictionary of video2x configuration
|
||||
"""
|
||||
|
||||
with open(config_file, 'r') as config:
|
||||
return yaml.load(config, Loader=yaml.FullLoader)
|
||||
|
||||
def load_configurations(self):
|
||||
|
||||
# get config file path from line edit
|
||||
@@ -515,6 +509,14 @@ class Video2XMainWindow(QMainWindow):
|
||||
self.srmd_ncnn_vulkan_jobs_line_edit.setText(settings['j'])
|
||||
self.srmd_ncnn_vulkan_tta_check_box.setChecked(settings['x'])
|
||||
|
||||
# realsr-ncnn-vulkan
|
||||
settings = self.config['realsr_ncnn_vulkan']
|
||||
self.realsr_ncnn_vulkan_path_line_edit.setText(str(pathlib.Path(os.path.expandvars(settings['path'])).absolute()))
|
||||
self.realsr_ncnn_vulkan_tile_size_spin_box.setValue(settings['t'])
|
||||
self.realsr_ncnn_vulkan_gpu_id_spin_box.setValue(settings['g'])
|
||||
self.realsr_ncnn_vulkan_jobs_line_edit.setText(settings['j'])
|
||||
self.realsr_ncnn_vulkan_tta_check_box.setChecked(settings['x'])
|
||||
|
||||
# anime4k
|
||||
settings = self.config['anime4kcpp']
|
||||
self.anime4kcpp_path_line_edit.setText(str(pathlib.Path(os.path.expandvars(settings['path'])).absolute()))
|
||||
@@ -549,6 +551,7 @@ class Video2XMainWindow(QMainWindow):
|
||||
self.ffmpeg_assemble_video_output_options_video_codec_line_edit.setText(settings['output_options']['-vcodec'])
|
||||
self.ffmpeg_assemble_video_output_options_pixel_format_line_edit.setText(settings['output_options']['-pix_fmt'])
|
||||
self.ffmpeg_assemble_video_output_options_crf_spin_box.setValue(settings['output_options']['-crf'])
|
||||
self.ffmpeg_assemble_video_output_options_tune_combo_box.setCurrentText(settings['output_options']['-tune'])
|
||||
self.ffmpeg_assemble_video_output_options_bitrate_line_edit.setText(settings['output_options']['-b:v'])
|
||||
|
||||
# migrate streams
|
||||
@@ -615,6 +618,14 @@ class Video2XMainWindow(QMainWindow):
|
||||
self.config['srmd_ncnn_vulkan']['j'] = self.srmd_ncnn_vulkan_jobs_line_edit.text()
|
||||
self.config['srmd_ncnn_vulkan']['x'] = self.srmd_ncnn_vulkan_tta_check_box.isChecked()
|
||||
|
||||
# realsr-ncnn-vulkan
|
||||
self.config['realsr_ncnn_vulkan']['path'] = os.path.expandvars(self.realsr_ncnn_vulkan_path_line_edit.text())
|
||||
self.config['realsr_ncnn_vulkan']['t'] = self.realsr_ncnn_vulkan_tile_size_spin_box.value()
|
||||
self.config['realsr_ncnn_vulkan']['m'] = str((pathlib.Path(self.config['realsr_ncnn_vulkan']['path']).parent / self.realsr_ncnn_vulkan_model_combo_box.currentText()).absolute())
|
||||
self.config['realsr_ncnn_vulkan']['g'] = self.realsr_ncnn_vulkan_gpu_id_spin_box.value()
|
||||
self.config['realsr_ncnn_vulkan']['j'] = self.realsr_ncnn_vulkan_jobs_line_edit.text()
|
||||
self.config['realsr_ncnn_vulkan']['x'] = self.realsr_ncnn_vulkan_tta_check_box.isChecked()
|
||||
|
||||
# anime4k
|
||||
self.config['anime4kcpp']['path'] = os.path.expandvars(self.anime4kcpp_path_line_edit.text())
|
||||
self.config['anime4kcpp']['passes'] = self.anime4kcpp_passes_spin_box.value()
|
||||
@@ -648,6 +659,7 @@ class Video2XMainWindow(QMainWindow):
|
||||
self.config['ffmpeg']['assemble_video']['output_options']['-vcodec'] = self.ffmpeg_assemble_video_output_options_video_codec_line_edit.text()
|
||||
self.config['ffmpeg']['assemble_video']['output_options']['-pix_fmt'] = self.ffmpeg_assemble_video_output_options_pixel_format_line_edit.text()
|
||||
self.config['ffmpeg']['assemble_video']['output_options']['-crf'] = self.ffmpeg_assemble_video_output_options_crf_spin_box.value()
|
||||
self.config['ffmpeg']['assemble_video']['output_options']['-tune'] = self.ffmpeg_assemble_video_output_options_tune_combo_box.currentText()
|
||||
if self.ffmpeg_assemble_video_output_options_bitrate_line_edit.text() != '':
|
||||
self.config['ffmpeg']['assemble_video']['output_options']['-b:v'] = self.ffmpeg_assemble_video_output_options_bitrate_line_edit.text()
|
||||
else:
|
||||
@@ -691,8 +703,18 @@ class Video2XMainWindow(QMainWindow):
|
||||
|
||||
self.config['ffmpeg']['migrate_streams']['output_options']['-pix_fmt'] = self.ffmpeg_migrate_streams_output_options_pixel_format_line_edit.text()
|
||||
|
||||
if (fps := self.ffmpeg_migrate_streams_output_options_frame_interpolation_spin_box.value()) > 0:
|
||||
if ('-vf' in self.config['ffmpeg']['migrate_streams']['output_options'] and
|
||||
len(self.config['ffmpeg']['migrate_streams']['output_options']['-vf']) > 0 and
|
||||
'minterpolate=' not in self.config['ffmpeg']['migrate_streams']['output_options']['-vf']):
|
||||
self.config['ffmpeg']['migrate_streams']['output_options']['-vf'] += f',minterpolate=\'fps={fps}\''
|
||||
else:
|
||||
self.config['ffmpeg']['migrate_streams']['output_options']['-vf'] = f'minterpolate=\'fps={fps}\''
|
||||
else:
|
||||
self.config['ffmpeg']['migrate_streams']['output_options'].pop('-vf', None)
|
||||
|
||||
# copy source codec
|
||||
if self.ffmpeg_migrate_streams_output_options_copy_codec_check_box.isChecked():
|
||||
if self.ffmpeg_migrate_streams_output_options_copy_streams_check_box.isChecked():
|
||||
self.config['ffmpeg']['migrate_streams']['output_options']['-c'] = 'copy'
|
||||
else:
|
||||
self.config['ffmpeg']['migrate_streams']['output_options'].pop('-c', None)
|
||||
@@ -728,6 +750,56 @@ class Video2XMainWindow(QMainWindow):
|
||||
self.config['gifski']['once'] = self.gifski_once_check_box.isChecked()
|
||||
self.config['gifski']['quiet'] = self.gifski_quiet_check_box.isChecked()
|
||||
|
||||
def dragEnterEvent(self, event):
|
||||
if event.mimeData().hasUrls():
|
||||
event.accept()
|
||||
else:
|
||||
event.ignore()
|
||||
|
||||
def dropEvent(self, event):
|
||||
input_paths = [pathlib.Path(u.toLocalFile()) for u in event.mimeData().urls()]
|
||||
for path in input_paths:
|
||||
if (path.is_file() or path.is_dir()) and not self.input_table_path_exists(path):
|
||||
self.input_table_data.append(path)
|
||||
|
||||
self.update_output_path()
|
||||
self.update_input_table()
|
||||
|
||||
def enable_line_edit_file_drop(self, line_edit: QLineEdit):
|
||||
line_edit.dragEnterEvent = self.dragEnterEvent
|
||||
line_edit.dropEvent = lambda event: line_edit.setText(str(pathlib.Path(event.mimeData().urls()[0].toLocalFile()).absolute()))
|
||||
|
||||
def show_ffprobe_output(self, event):
|
||||
input_paths = [pathlib.Path(u.toLocalFile()) for u in event.mimeData().urls()]
|
||||
if not input_paths[0].is_file():
|
||||
return
|
||||
|
||||
ffmpeg_object = Ffmpeg(self.ffmpeg_settings)
|
||||
file_info_json = ffmpeg_object.probe_file_info(input_paths[0])
|
||||
self.ffprobe_plain_text_edit.setPlainText(json.dumps(file_info_json, indent=2))
|
||||
|
||||
@staticmethod
|
||||
def read_config(config_file: pathlib.Path) -> dict:
|
||||
""" read video2x configurations from config file
|
||||
|
||||
Arguments:
|
||||
config_file {pathlib.Path} -- video2x configuration file pathlib.Path
|
||||
|
||||
Returns:
|
||||
dict -- dictionary of video2x configuration
|
||||
"""
|
||||
|
||||
with open(config_file, 'r') as config:
|
||||
return yaml.load(config, Loader=yaml.FullLoader)
|
||||
|
||||
def mutually_exclude_frame_interpolation_stream_copy(self):
|
||||
if self.ffmpeg_migrate_streams_output_options_frame_interpolation_spin_box.value() > 0:
|
||||
self.ffmpeg_migrate_streams_output_options_copy_streams_check_box.setChecked(False)
|
||||
self.ffmpeg_migrate_streams_output_options_copy_streams_check_box.setDisabled(True)
|
||||
else:
|
||||
self.ffmpeg_migrate_streams_output_options_copy_streams_check_box.setChecked(True)
|
||||
self.ffmpeg_migrate_streams_output_options_copy_streams_check_box.setDisabled(False)
|
||||
|
||||
def update_gui_for_driver(self):
|
||||
current_driver = AVAILABLE_DRIVERS[self.driver_combo_box.currentText()]
|
||||
|
||||
@@ -744,6 +816,10 @@ class Video2XMainWindow(QMainWindow):
|
||||
self.scale_ratio_double_spin_box.setMinimum(2.0)
|
||||
self.scale_ratio_double_spin_box.setMaximum(4.0)
|
||||
self.scale_ratio_double_spin_box.setValue(2.0)
|
||||
elif current_driver == 'realsr_ncnn_vulkan':
|
||||
self.scale_ratio_double_spin_box.setMinimum(4.0)
|
||||
self.scale_ratio_double_spin_box.setMaximum(4.0)
|
||||
self.scale_ratio_double_spin_box.setValue(4.0)
|
||||
|
||||
# update preferred processes/threads count
|
||||
if current_driver == 'anime4kcpp':
|
||||
@@ -764,13 +840,16 @@ class Video2XMainWindow(QMainWindow):
|
||||
|
||||
for item in items_to_delete:
|
||||
self.input_table_data.remove(item)
|
||||
|
||||
self.update_output_path()
|
||||
self.update_input_table()
|
||||
|
||||
def input_table_clear_all(self):
|
||||
self.input_table_data = []
|
||||
self.update_output_path()
|
||||
self.update_input_table()
|
||||
|
||||
def input_table_path_exists(self, input_path):
|
||||
def input_table_path_exists(self, input_path: pathlib.Path) -> bool:
|
||||
for path in self.input_table_data:
|
||||
# not using Path.samefile since file may not exist
|
||||
if str(path.absolute()) == str(input_path.absolute()):
|
||||
@@ -790,58 +869,74 @@ class Video2XMainWindow(QMainWindow):
|
||||
return pathlib.Path(folder_selected)
|
||||
|
||||
def update_output_path(self):
|
||||
# if there is more than one input
|
||||
if len(self.input_table_data) != 1:
|
||||
return
|
||||
# if input list is empty
|
||||
# clear output path
|
||||
if len(self.input_table_data) == 0:
|
||||
self.output_line_edit.setText('')
|
||||
|
||||
input_path = self.input_table_data[0]
|
||||
# give up if input path doesn't exist or isn't a file or a directory
|
||||
if not input_path.exists() or not (input_path.is_file() or input_path.is_dir()):
|
||||
return
|
||||
# if there are multiple output files
|
||||
# use cwd/output directory for output
|
||||
elif len(self.input_table_data) > 1:
|
||||
self.output_line_edit.setText(str((pathlib.Path.cwd() / 'output').absolute()))
|
||||
|
||||
if input_path.is_file():
|
||||
# if there's only one input file
|
||||
# generate output file/directory name automatically
|
||||
elif len(self.input_table_data) == 1:
|
||||
input_path = self.input_table_data[0]
|
||||
# give up if input path doesn't exist or isn't a file or a directory
|
||||
if not input_path.exists() or not (input_path.is_file() or input_path.is_dir()):
|
||||
return
|
||||
|
||||
# generate suffix automatically
|
||||
input_file_mime_type = magic.from_file(str(input_path.absolute()), mime=True)
|
||||
input_file_type = input_file_mime_type.split('/')[0]
|
||||
input_file_subtype = input_file_mime_type.split('/')[1]
|
||||
|
||||
# if input file is an image
|
||||
if input_file_type == 'image':
|
||||
|
||||
# if file is a gif, use .gif
|
||||
if input_file_subtype == 'gif':
|
||||
suffix = '.gif'
|
||||
|
||||
# otherwise, use .png by default for all images
|
||||
else:
|
||||
suffix = '.png'
|
||||
|
||||
# if input is video, use .mp4 as output by default
|
||||
elif input_file_type == 'video':
|
||||
suffix = '.mp4'
|
||||
|
||||
# if failed to detect file type
|
||||
# use input file's suffix
|
||||
else:
|
||||
suffix = input_path.suffix
|
||||
|
||||
output_path = input_path.parent / f'{input_path.stem}_output{suffix}'
|
||||
|
||||
elif input_path.is_dir():
|
||||
output_path = input_path.parent / f'{input_path.stem}_output'
|
||||
|
||||
# try up to 1000 times
|
||||
output_path_id = 0
|
||||
while output_path.exists() and output_path_id <= 1000:
|
||||
if input_path.is_file():
|
||||
output_path = input_path.parent / pathlib.Path(f'{input_path.stem}_output_{output_path_id}{suffix}')
|
||||
elif input_path.is_dir():
|
||||
output_path = input_path.parent / pathlib.Path(f'{input_path.stem}_output_{output_path_id}')
|
||||
output_path_id += 1
|
||||
|
||||
if not output_path.exists():
|
||||
self.output_line_edit.setText(str(output_path.absolute()))
|
||||
# generate suffix automatically
|
||||
input_file_mime_type = magic.from_file(str(input_path.absolute()), mime=True)
|
||||
input_file_type = input_file_mime_type.split('/')[0]
|
||||
input_file_subtype = input_file_mime_type.split('/')[1]
|
||||
|
||||
# in case python-magic fails to detect file type
|
||||
# try guessing file mime type with mimetypes
|
||||
if input_file_type not in ['image', 'video']:
|
||||
input_file_mime_type = mimetypes.guess_type(input_path.name)[0]
|
||||
input_file_type = input_file_mime_type.split('/')[0]
|
||||
input_file_subtype = input_file_mime_type.split('/')[1]
|
||||
|
||||
# if input file is an image
|
||||
if input_file_type == 'image':
|
||||
|
||||
# if file is a gif, use .gif
|
||||
if input_file_subtype == 'gif':
|
||||
suffix = '.gif'
|
||||
|
||||
# otherwise, use .png by default for all images
|
||||
else:
|
||||
suffix = '.png'
|
||||
|
||||
# if input is video, use .mp4 as output by default
|
||||
elif input_file_type == 'video':
|
||||
suffix = '.mp4'
|
||||
|
||||
# if failed to detect file type
|
||||
# use input file's suffix
|
||||
else:
|
||||
suffix = input_path.suffix
|
||||
|
||||
output_path = input_path.parent / f'{input_path.stem}_output{suffix}'
|
||||
|
||||
elif input_path.is_dir():
|
||||
output_path = input_path.parent / f'{input_path.stem}_output'
|
||||
|
||||
# try up to 1000 times
|
||||
output_path_id = 0
|
||||
while output_path.exists() and output_path_id <= 1000:
|
||||
if input_path.is_file():
|
||||
output_path = input_path.parent / pathlib.Path(f'{input_path.stem}_output_{output_path_id}{suffix}')
|
||||
elif input_path.is_dir():
|
||||
output_path = input_path.parent / pathlib.Path(f'{input_path.stem}_output_{output_path_id}')
|
||||
output_path_id += 1
|
||||
|
||||
if not output_path.exists():
|
||||
self.output_line_edit.setText(str(output_path.absolute()))
|
||||
|
||||
def select_input_file(self):
|
||||
if ((input_file := self.select_file('Select Input File')) is None or
|
||||
@@ -880,15 +975,28 @@ class Video2XMainWindow(QMainWindow):
|
||||
self.config_line_edit.setText(str(config_file.absolute()))
|
||||
self.load_configurations()
|
||||
|
||||
def select_driver_binary_path(self, driver_line_edit):
|
||||
def select_driver_binary_path(self, driver_line_edit: QLineEdit):
|
||||
if (driver_binary_path := self.select_file('Select Driver Binary File')) is None:
|
||||
return
|
||||
driver_line_edit.setText(str(driver_binary_path.absolute()))
|
||||
|
||||
def show_about(self, message: str):
|
||||
def show_shortcuts(self):
|
||||
message_box = QMessageBox(self)
|
||||
message_box.setWindowTitle('Video2X Shortcuts')
|
||||
message_box.setTextFormat(Qt.MarkdownText)
|
||||
shortcut_information = '''**Ctrl+W**:\tExit application\\
|
||||
**Ctrl+Q**:\tExit application\\
|
||||
**Ctrl+I**:\tOpen select input file dialog\\
|
||||
**Ctrl+O**:\tOpen select output file dialog\\
|
||||
**Ctrl+Shift+I**:\tOpen select input folder dialog\\
|
||||
**Ctrl+Shift+O**:\tOpen select output folder dialog'''
|
||||
message_box.setText(shortcut_information)
|
||||
message_box.exec_()
|
||||
|
||||
def show_about(self):
|
||||
message_box = QMessageBox(self)
|
||||
message_box.setWindowTitle('About Video2X')
|
||||
message_box.setIconPixmap(QtGui.QPixmap(self.video2x_icon_path).scaled(64, 64))
|
||||
message_box.setIconPixmap(QPixmap(self.video2x_icon_path).scaled(64, 64))
|
||||
message_box.setTextFormat(Qt.MarkdownText)
|
||||
message_box.setText(LEGAL_INFO)
|
||||
message_box.exec_()
|
||||
@@ -915,14 +1023,14 @@ class Video2XMainWindow(QMainWindow):
|
||||
message_box.setTextFormat(Qt.MarkdownText)
|
||||
|
||||
error_message = '''Upscaler ran into an error:\\
|
||||
**{}**\\
|
||||
{}\\
|
||||
Check the console output for details.\\
|
||||
When reporting an error, please include console output.\\
|
||||
You can [submit an issue on GitHub](https://github.com/k4yt3x/video2x/issues/new?assignees=K4YT3X&labels=bug&template=bug-report.md&title={}) to report this error.'''
|
||||
message_box.setText(error_message.format(exception, urllib.parse.quote(str(exception))))
|
||||
message_box.exec_()
|
||||
|
||||
def progress_monitor(self, progress_callback):
|
||||
def progress_monitor(self, progress_callback: pyqtSignal):
|
||||
|
||||
# initialize progress bar values
|
||||
upscale_begin_time = time.time()
|
||||
@@ -976,7 +1084,7 @@ You can [submit an issue on GitHub](https://github.com/k4yt3x/video2x/issues/new
|
||||
|
||||
# if show frame is checked, show preview image
|
||||
if self.frame_preview_show_preview_check_box.isChecked() and last_frame_upscaled.is_file():
|
||||
last_frame_pixmap = QtGui.QPixmap(str(last_frame_upscaled.absolute()))
|
||||
last_frame_pixmap = QPixmap(str(last_frame_upscaled.absolute()))
|
||||
# the -2 here behind geometry subtracts frame size from width and height
|
||||
self.frame_preview_label.setPixmap(last_frame_pixmap.scaled(self.frame_preview_label.width() - 2,
|
||||
self.frame_preview_label.height() - 2,
|
||||
@@ -1093,13 +1201,39 @@ You can [submit an issue on GitHub](https://github.com/k4yt3x/video2x/issues/new
|
||||
self.reset_progress_display()
|
||||
|
||||
def stop(self):
|
||||
with contextlib.suppress(AttributeError):
|
||||
self.upscaler.running = False
|
||||
|
||||
def closeEvent(self, event):
|
||||
try:
|
||||
# if upscaler is running, ask the user for confirmation
|
||||
if self.upscaler.running is True:
|
||||
confirmation = QMessageBox.question(self,
|
||||
'Stopping Confirmation',
|
||||
'Are you sure you want to want to stop the upscaling process?',
|
||||
QMessageBox.Yes,
|
||||
QMessageBox.No)
|
||||
# if the user indeed wants to stop processing
|
||||
if confirmation == QMessageBox.Yes:
|
||||
with contextlib.suppress(AttributeError):
|
||||
self.upscaler.running = False
|
||||
return True
|
||||
# if the user doesn't want ot stop processing
|
||||
else:
|
||||
return False
|
||||
|
||||
# if the upscaler is not running
|
||||
else:
|
||||
return True
|
||||
|
||||
# if an AttributeError happens
|
||||
# that means the upscaler object haven't been created yet
|
||||
except AttributeError:
|
||||
return True
|
||||
|
||||
def closeEvent(self, event: QCloseEvent):
|
||||
# try cleaning up temp directories
|
||||
self.stop()
|
||||
event.accept()
|
||||
if self.stop():
|
||||
event.accept()
|
||||
else:
|
||||
event.ignore()
|
||||
|
||||
|
||||
# this file shouldn't be imported
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE QtCreatorProject>
|
||||
<!-- Written by QtCreator 4.12.0, 2020-05-14T22:33:50. -->
|
||||
<!-- Written by QtCreator 4.12.0, 2020-05-26T06:35:20. -->
|
||||
<qtcreator>
|
||||
<data>
|
||||
<variable>EnvironmentId</variable>
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>671</width>
|
||||
<height>802</height>
|
||||
<width>673</width>
|
||||
<height>844</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="acceptDrops">
|
||||
@@ -270,7 +270,57 @@
|
||||
<item>
|
||||
<widget class="QComboBox" name="driverComboBox">
|
||||
<property name="toolTip">
|
||||
<string>Driver to use for upscaling. Waifu2x Caffe is only for Nvidia GPUs.</string>
|
||||
<string><p style="-qt-block-indent: 0; text-indent: 0px; margin: 0px;"><span style="font-size: 8pt;">Driver to use for
|
||||
upscaling. </span></p>
|
||||
<ul>
|
||||
<li style="-qt-block-indent: 0; text-indent: 0px; margin: 0px;"><span style="font-size: 8pt;">Waifu2X Caffe</span>
|
||||
<ul>
|
||||
<li style="-qt-block-indent: 0; text-indent: 0px; margin: 0px;"><span
|
||||
style="font-size: 8pt; font-weight: 600;">requires Nvidia GPU and CUDA/cuDNN</span></li>
|
||||
<li style="-qt-block-indent: 0; text-indent: 0px; margin: 0px;"><span style="font-size: 8pt;">Caffe
|
||||
implementation of waifu2x which is classic and stable</span></li>
|
||||
<li style="-qt-block-indent: 0; text-indent: 0px; margin: 0px;"><span style="font-size: 8pt;">Lots of models
|
||||
available</span></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li style="-qt-block-indent: 0; text-indent: 0px; margin: 0px;"><span style="font-size: 8pt;">Waifu2X Converter
|
||||
CPP</span>
|
||||
<ul>
|
||||
<li style="-qt-block-indent: 0; text-indent: 0px; margin: 0px;"><span style="font-size: 8pt;">CPP
|
||||
implementation of waifu2x</span></li>
|
||||
<li style="-qt-block-indent: 0; text-indent: 0px; margin: 0px;"><span style="font-size: 8pt;">Uses OpenCL
|
||||
and OpenCV for graphical processing</span></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li style="-qt-block-indent: 0; text-indent: 0px; margin: 0px;"><span style="font-size: 8pt;">Waifu2X NCNN
|
||||
Vulkan</span>
|
||||
<ul>
|
||||
<li style="-qt-block-indent: 0; text-indent: 0px; margin: 0px;"><span style="font-size: 8pt;">NCNN
|
||||
implementation of waifu2x</span></li>
|
||||
<li style="-qt-block-indent: 0; text-indent: 0px; margin: 0px;"><span style="font-size: 8pt;">Uses Vulkan
|
||||
API for graphical processing</span></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li style="-qt-block-indent: 0; text-indent: 0px; margin: 0px;"><span style="font-size: 8pt;">SRMD NCNN
|
||||
Vulkan</span>
|
||||
<ul>
|
||||
<li style="-qt-block-indent: 0; text-indent: 0px; margin: 0px;"><span style="font-size: 8pt;">NCNN
|
||||
implementation of SRMD</span></li>
|
||||
<li style="-qt-block-indent: 0; text-indent: 0px; margin: 0px;"><span style="font-size: 8pt;">Uses Vulkan
|
||||
API for graphical processing</span></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li style="-qt-block-indent: 0; text-indent: 0px; margin: 0px;"><span style="font-size: 8pt;">Anime4KCPP</span>
|
||||
<ul>
|
||||
<li style="-qt-block-indent: 0; text-indent: 0px; margin: 0px;"><span style="font-size: 8pt;">CPP
|
||||
implementation of Anime4K</span></li>
|
||||
<li style="-qt-block-indent: 0; text-indent: 0px; margin: 0px;"><span style="font-size: 8pt;">Very fast but
|
||||
low quality</span></li>
|
||||
<li style="-qt-block-indent: 0; text-indent: 0px; margin: 0px;"><span style="font-size: 8pt;">Multithreading
|
||||
is preferred</span></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul></string>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
@@ -292,6 +342,11 @@
|
||||
<string>SRMD NCNN Vulkan</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>RealSR NCNN Vulkan</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Anime4KCPP</string>
|
||||
@@ -1334,6 +1389,131 @@
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="realsrNcnnVulkanTab">
|
||||
<attribute name="title">
|
||||
<string>RealSR NCNN Vulkan</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_34">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="realsrNcnnVulkanPathHorizontalLayout">
|
||||
<item>
|
||||
<widget class="QLineEdit" name="realsrNcnnVulkanPathLineEdit"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="realsrNcnnVulkanPathSelectButton">
|
||||
<property name="text">
|
||||
<string>Select Binary Path</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="realsrNcnnVulkanTileSizeHorizontalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="realsrNcnnVulkanTileSizeLabel">
|
||||
<property name="text">
|
||||
<string>Tile Size</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="realsrNcnnVulkanTileSizeSpinBox">
|
||||
<property name="minimum">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>99999</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>0</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="realsrNcnnVulkanModelHorizontalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="realsrNcnnVulkanModelLabel">
|
||||
<property name="text">
|
||||
<string>Model</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="realsrNcnnVulkanModelComboBox">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>If the input file contains very little noise, DF2K will produce sharper outputs.</p><p>However, if the input is noisy, DF2K might produce artifacts. DF2K_JPEG will then be preferred.</p></body></html></string>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>models-DF2K_JPEG</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>models-DF2K</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="realsrNcnnVulkanGpuIdHorizontalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="realsrNcnnVulkanGpuIdLabel">
|
||||
<property name="text">
|
||||
<string>GPU ID</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="realsrNcnnVulkanGpuIdSpinBox"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="realsrNcnnVulkanJobsHorizontalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="realsrNcnnVulkanJobsLabel">
|
||||
<property name="text">
|
||||
<string>Jobs</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="realsrNcnnVulkanJobsLineEdit">
|
||||
<property name="text">
|
||||
<string>1:2:2</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="realsrNcnnVulkanTtaCheckBox">
|
||||
<property name="text">
|
||||
<string>TTA</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="realsrNcnnVulkanVerticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>331</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="anime4kCppTab">
|
||||
<attribute name="title">
|
||||
<string>Anime4K CPP</string>
|
||||
@@ -1657,7 +1837,7 @@
|
||||
<item>
|
||||
<widget class="QTabWidget" name="ffmpegSettingsTabWidget">
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
<number>2</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="ffmpegGlobalOptionsTab">
|
||||
<attribute name="title">
|
||||
@@ -1879,7 +2059,7 @@
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>yuv444p10le</string>
|
||||
<string>yuv420p</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -1906,6 +2086,64 @@
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="ffmpegAssembleVideoOutputOptionsTuneHorizontalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="ffmpegAssembleVideoOutputOptionsTuneLabel">
|
||||
<property name="text">
|
||||
<string>H.264/H.265 Tune (-tune)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="ffmpegAssembleVideoOutputOptionsTuneComboBox">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>- film (x264 only): use for high quality movie content; lowers deblocking</p><p>- animation (x264 only): good for cartoons; uses higher deblocking and more reference frames</p><p>- grain: preserves the grain structure in old, grainy film material</p><p>- stillimage: (x264 only) good for slideshow-like content</p><p>- fastdecode: allows faster decoding by disabling certain filters</p><p>- zerolatency: good for fast encoding and low-latency streaming</p><p>- psnr: ignore this as it is only used for codec development</p><p>- ssim: ignore this as it is only used for codec development </p></body></html></string>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>animation</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>film</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>grain</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>stillimage</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>fastdecode</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>zerolatency</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>psnr</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>ssim</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="ffmpegAssembleVideoOutputOptionsBitrateHorizontalLayout">
|
||||
<item>
|
||||
@@ -1933,7 +2171,7 @@
|
||||
<item>
|
||||
<widget class="QCheckBox" name="ffmpegAssembleVideoOutputOptionsEnsureDivisibleCheckBox">
|
||||
<property name="text">
|
||||
<string>Ensure output width and height are divisible by 2</string>
|
||||
<string>Ensure output width and height are divisible by 2 (-vf: "pad=ceil(iw/2)*2:ceil(ih/2)*2")</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
@@ -2070,9 +2308,9 @@
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_32">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="ffmpegMigrateStreamsOutputOptionsOtherPixelFormatHorizontalLayout">
|
||||
<layout class="QHBoxLayout" name="ffmpegMigrateStreamsOutputOptionsPixelFormatHorizontalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="ffmpegMigrateStreamsOutputOptionsOtherPixelFormatLabel">
|
||||
<widget class="QLabel" name="ffmpegMigrateStreamsOutputOptionsPixelFormatLabel">
|
||||
<property name="text">
|
||||
<string>Pixel Format (-pix_fmt)</string>
|
||||
</property>
|
||||
@@ -2084,9 +2322,30 @@
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="ffmpegMigrateStreamsOutputOptionsCopyCodecCheckBox">
|
||||
<layout class="QHBoxLayout" name="ffmpegMigrateStreamsOutputOptionsFrameInterpolationHorizontalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="ffmpegMigrateStreamsOutputOptionsFrameInterpolationLabel">
|
||||
<property name="text">
|
||||
<string>Frame Interpolation (-filter "minterpolate='fps=n'")</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="ffmpegMigrateStreamsOutputOptionsFrameInterpolationSpinBox">
|
||||
<property name="maximum">
|
||||
<number>9999</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="ffmpegMigrateStreamsOutputOptionsCopyStreamsCheckBox">
|
||||
<property name="toolTip">
|
||||
<string>Copy streams without re-encoding</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Copy codec</string>
|
||||
<string>Copy streams (-c copy)</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
@@ -2094,9 +2353,9 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="ffmpegMigrateStreamsOutputOptionsOtherCopyKnownMetadataTagsCheckBox">
|
||||
<widget class="QCheckBox" name="ffmpegMigrateStreamsOutputOptionsCopyKnownMetadataTagsCheckBox">
|
||||
<property name="text">
|
||||
<string>Copy known metadata tags</string>
|
||||
<string>Copy known metadata tags (-map_metadata 0)</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
@@ -2104,9 +2363,9 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="ffmpegMigrateStreamsOutputOptionsOtherCopyArbitraryMetadataTagsCheckBox">
|
||||
<widget class="QCheckBox" name="ffmpegMigrateStreamsOutputOptionsCopyArbitraryMetadataTagsCheckBox">
|
||||
<property name="text">
|
||||
<string>Copy arbitrary metadata tags</string>
|
||||
<string>Copy arbitrary metadata tags (-movflags use_metadata_tags)</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
@@ -2114,7 +2373,7 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<spacer name="ffmpegMigrateStreamsOutputOptionsOtherVerticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
@@ -2511,7 +2770,7 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>671</width>
|
||||
<width>673</width>
|
||||
<height>21</height>
|
||||
</rect>
|
||||
</property>
|
||||
@@ -2525,6 +2784,7 @@
|
||||
<property name="title">
|
||||
<string>Help</string>
|
||||
</property>
|
||||
<addaction name="actionShortcuts"/>
|
||||
<addaction name="actionAbout"/>
|
||||
</widget>
|
||||
<addaction name="menuFile"/>
|
||||
@@ -2541,6 +2801,11 @@
|
||||
<string>About</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionShortcuts">
|
||||
<property name="text">
|
||||
<string>Shortcuts</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
Name: Video2X Setup Script
|
||||
Creator: K4YT3X
|
||||
Date Created: November 28, 2018
|
||||
Last Modified: May 16, 2020
|
||||
Last Modified: May 29, 2020
|
||||
|
||||
Editor: BrianPetkovsek
|
||||
Editor: SAT3LL
|
||||
@@ -17,8 +17,9 @@ Installation Details:
|
||||
- waifu2x-caffe: %LOCALAPPDATA%\\video2x\\waifu2x-caffe
|
||||
- waifu2x-cpp-converter: %LOCALAPPDATA%\\video2x\\waifu2x-converter-cpp
|
||||
- waifu2x_ncnn_vulkan: %LOCALAPPDATA%\\video2x\\waifu2x-ncnn-vulkan
|
||||
- anime4kcpp: %LOCALAPPDATA%\\video2x\\anime4kcpp
|
||||
- srmd_ncnn_vulkan: %LOCALAPPDATA%\\video2x\\srmd-ncnn-vulkan
|
||||
- realsr_ncnn_vulkan: %LOCALAPPDATA%\\video2x\\realsr-ncnn-vulkan
|
||||
- anime4kcpp: %LOCALAPPDATA%\\video2x\\anime4kcpp
|
||||
"""
|
||||
|
||||
# built-in imports
|
||||
@@ -43,7 +44,7 @@ import zipfile
|
||||
# Therefore, they will be installed during the Python dependency
|
||||
# installation step and imported later in the script.
|
||||
|
||||
SETUP_VERSION = '2.1.0'
|
||||
SETUP_VERSION = '2.2.0'
|
||||
|
||||
# global static variables
|
||||
LOCALAPPDATA = pathlib.Path(os.getenv('localappdata'))
|
||||
@@ -54,8 +55,9 @@ DRIVER_OPTIONS = ['all',
|
||||
'waifu2x_caffe',
|
||||
'waifu2x_converter_cpp',
|
||||
'waifu2x_ncnn_vulkan',
|
||||
'anime4kcpp',
|
||||
'srmd_ncnn_vulkan']
|
||||
'srmd_ncnn_vulkan',
|
||||
# 'realsr_ncnn_vulkan',
|
||||
'anime4kcpp']
|
||||
|
||||
|
||||
def parse_arguments():
|
||||
@@ -103,7 +105,7 @@ class Video2xSetup:
|
||||
def _install_python_requirements(self):
|
||||
""" Read requirements.txt and return its content
|
||||
"""
|
||||
pip_install('requirements.txt')
|
||||
pip_install('requirements-windows.txt')
|
||||
|
||||
def _cleanup(self):
|
||||
""" Cleanup all the temp files downloaded
|
||||
@@ -209,6 +211,32 @@ class Video2xSetup:
|
||||
# rename the newly extracted directory
|
||||
(LOCALAPPDATA / 'video2x' / zipf.namelist()[0]).rename(waifu2x_ncnn_vulkan_directory)
|
||||
|
||||
def _install_realsr_ncnn_vulkan(self):
|
||||
""" Install realsr-ncnn-vulkan
|
||||
"""
|
||||
print('\nInstalling realsr-ncnn-vulkan')
|
||||
import requests
|
||||
|
||||
# Get latest release of realsr-ncnn-vulkan via Github API
|
||||
latest_release = requests.get('https://api.github.com/repos/nihui/realsr-ncnn-vulkan/releases/latest').json()
|
||||
|
||||
for a in latest_release['assets']:
|
||||
if re.search(r'realsr-ncnn-vulkan-\d*\.zip', a['browser_download_url']):
|
||||
realsr_ncnn_vulkan_zip = download(a['browser_download_url'], tempfile.gettempdir())
|
||||
self.trash.append(realsr_ncnn_vulkan_zip)
|
||||
|
||||
# extract and rename
|
||||
realsr_ncnn_vulkan_directory = LOCALAPPDATA / 'video2x' / 'realsr-ncnn-vulkan'
|
||||
with zipfile.ZipFile(realsr_ncnn_vulkan_zip) as zipf:
|
||||
zipf.extractall(LOCALAPPDATA / 'video2x')
|
||||
|
||||
# if directory already exists, remove it
|
||||
if realsr_ncnn_vulkan_directory.exists():
|
||||
shutil.rmtree(realsr_ncnn_vulkan_directory)
|
||||
|
||||
# rename the newly extracted directory
|
||||
(LOCALAPPDATA / 'video2x' / zipf.namelist()[0]).rename(realsr_ncnn_vulkan_directory)
|
||||
|
||||
def _install_anime4kcpp(self):
|
||||
""" Install Anime4KCPP
|
||||
"""
|
||||
|
||||
0
src/wrappers/anime4kcpp.py
Normal file → Executable file
0
src/wrappers/anime4kcpp.py
Normal file → Executable file
0
src/wrappers/ffmpeg.py
Normal file → Executable file
0
src/wrappers/ffmpeg.py
Normal file → Executable file
0
src/wrappers/gifski.py
Normal file → Executable file
0
src/wrappers/gifski.py
Normal file → Executable file
102
src/wrappers/realsr_ncnn_vulkan.py
Executable file
102
src/wrappers/realsr_ncnn_vulkan.py
Executable file
@@ -0,0 +1,102 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Name: RealSR NCNN Vulkan Driver
|
||||
Creator: K4YT3X
|
||||
Date Created: May 26, 2020
|
||||
Last Modified: May 26, 2020
|
||||
|
||||
Description: This class is a high-level wrapper
|
||||
for realsr_ncnn_vulkan.
|
||||
"""
|
||||
|
||||
# built-in imports
|
||||
import argparse
|
||||
import os
|
||||
import pathlib
|
||||
import platform
|
||||
import shlex
|
||||
import subprocess
|
||||
import threading
|
||||
|
||||
# third-party imports
|
||||
from avalon_framework import Avalon
|
||||
|
||||
|
||||
class WrapperMain:
|
||||
"""This class communicates with RealSR NCNN Vulkan 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, driver_settings):
|
||||
self.driver_settings = driver_settings
|
||||
self.print_lock = threading.Lock()
|
||||
|
||||
@staticmethod
|
||||
def parse_arguments(arguments):
|
||||
parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter, add_help=False)
|
||||
parser.error = lambda message: (_ for _ in ()).throw(AttributeError(message))
|
||||
parser.add_argument('--help', action='help', help='show this help message and exit')
|
||||
parser.add_argument('-v', action='store_true', help='verbose output')
|
||||
parser.add_argument('-i', type=str, help=argparse.SUPPRESS) # help='input image path (jpg/png) or directory')
|
||||
parser.add_argument('-o', type=str, help=argparse.SUPPRESS) # help='output image path (png) or directory')
|
||||
parser.add_argument('-s', type=int, choices=[4], help='upscale ratio')
|
||||
parser.add_argument('-t', type=int, help='tile size (>=32/0=auto)')
|
||||
parser.add_argument('-m', type=str, help='realsr model path')
|
||||
parser.add_argument('-g', type=int, help='gpu device to use')
|
||||
parser.add_argument('-j', type=str, help='thread count for load/proc/save')
|
||||
parser.add_argument('-x', action='store_true', help='enable tta mode')
|
||||
return parser.parse_args(arguments)
|
||||
|
||||
def load_configurations(self, upscaler):
|
||||
self.driver_settings['s'] = int(upscaler.scale_ratio)
|
||||
self.driver_settings['j'] = '{}:{}:{}'.format(upscaler.processes, upscaler.processes, upscaler.processes)
|
||||
|
||||
def upscale(self, input_directory, output_directory):
|
||||
"""This is the core function for RealSR NCNN Vulkan class
|
||||
|
||||
Arguments:
|
||||
input_directory {string} -- source directory path
|
||||
output_directory {string} -- output directory path
|
||||
ratio {int} -- output video ratio
|
||||
"""
|
||||
|
||||
# overwrite config file settings
|
||||
self.driver_settings['i'] = input_directory
|
||||
self.driver_settings['o'] = output_directory
|
||||
|
||||
# by default, realsr-ncnn-vulkan will look for the models under the current working directory
|
||||
# change the working directory to its containing folder if model directory not specified
|
||||
if self.driver_settings['m'] is None and platform.system() == 'Windows':
|
||||
os.chdir(pathlib.Path(self.driver_settings['path']).parent)
|
||||
|
||||
# list to be executed
|
||||
# initialize the list with the binary path as the first element
|
||||
execute = [self.driver_settings['path']]
|
||||
|
||||
for key in self.driver_settings.keys():
|
||||
|
||||
value = self.driver_settings[key]
|
||||
|
||||
# null or None means that leave this option out (keep default)
|
||||
if key == 'path' or value is None or value is False:
|
||||
continue
|
||||
else:
|
||||
if len(key) == 1:
|
||||
execute.append(f'-{key}')
|
||||
else:
|
||||
execute.append(f'--{key}')
|
||||
|
||||
# true means key is an option
|
||||
if value is not True:
|
||||
execute.append(str(value))
|
||||
|
||||
# return the Popen object of the new process created
|
||||
self.print_lock.acquire()
|
||||
Avalon.debug_info(f'[upscaler] Subprocess {os.getpid()} executing: {shlex.join(execute)}')
|
||||
self.print_lock.release()
|
||||
return subprocess.Popen(execute)
|
||||
0
src/wrappers/srmd_ncnn_vulkan.py
Normal file → Executable file
0
src/wrappers/srmd_ncnn_vulkan.py
Normal file → Executable file
0
src/wrappers/waifu2x_caffe.py
Normal file → Executable file
0
src/wrappers/waifu2x_caffe.py
Normal file → Executable file
0
src/wrappers/waifu2x_converter_cpp.py
Normal file → Executable file
0
src/wrappers/waifu2x_converter_cpp.py
Normal file → Executable file
0
src/wrappers/waifu2x_ncnn_vulkan.py
Normal file → Executable file
0
src/wrappers/waifu2x_ncnn_vulkan.py
Normal file → Executable file
Reference in New Issue
Block a user