Skip to content

Commit 6c618af

Browse files
authored
Merge pull request #167 from TNTwise/2.3.8
2.3.8
2 parents 3100d98 + 292f029 commit 6c618af

36 files changed

+1925
-4232
lines changed

.github/workflows/prerelease.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ on:
44
workflow_dispatch:
55

66
env:
7-
APP_VERSION: 2.3.7
7+
APP_VERSION: 2.3.8
88

99
jobs:
1010

CHANGELOG.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,15 @@
1+
# RVE 2.3.8 pre-release
2+
### Added
3+
- Open output folder button
4+
- Cap output scale based on model scale
5+
### Changed
6+
- UI Tweaks
7+
### Fixed
8+
- ROCm showing cuda on front end.
9+
- GMFSS not working
10+
### Removed
11+
- GIMM.
12+
- locking the app to 1 instance.
113
# RVE 2.3.7
214
### Added:
315
- PyTorch 2.9

README.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
[![pypresence](https://img.shields.io/badge/using-pypresence-00bb88.svg?style=for-the-badge&logo=discord&logoWidth=20)](https://github.com/qwertyquerty/pypresence)
44

55
![license](https://img.shields.io/github/license/tntwise/real-video-enhancer)
6-
![Version](https://img.shields.io/badge/Version-2.3.6-blue)
6+
![Version](https://img.shields.io/badge/Version-2.3.8-blue)
77
![downloads_total](https://img.shields.io/github/downloads/tntwise/REAL-Video-Enhancer/total.svg?label=downloads%40total)
88
<a href="https://discord.gg/hwGHXga8ck">
99
<img src="https://img.shields.io/discord/1041502781808328704?label=Discord" alt="Discord Shield"/></a>
@@ -40,7 +40,7 @@
4040

4141
# Introduction
4242

43-
<strong>REAL Video Enhancer</strong> is a redesigned and enhanced version of the original Rife ESRGAN App for Linux. This program offers convenient access to frame interpolation and upscaling functionalities on Windows, Linux and MacOS , and is an alternative to outdated software like <a rel="noopener noreferrer" href="https://nmkd.itch.io/flowframes" target="_blank" >Flowframes</a> or <a rel="noopener noreferrer" href="https://github.com/mafiosnik777/enhancr" target="_blank">enhancr</a>.
43+
<strong>REAL Video Enhancer</strong> is a redesigned and enhanced version of the original Rife ESRGAN App for Linux. This program offers convenient access to frame interpolation and upscaling functionalities on Windows, Linux and MacOS, and is an alternative to outdated software like <a rel="noopener noreferrer" href="https://nmkd.itch.io/flowframes" target="_blank" >Flowframes</a> or <a rel="noopener noreferrer" href="https://github.com/mafiosnik777/enhancr" target="_blank">enhancr</a>.
4444

4545
<p align=center>
4646
<img src="https://github.com/TNTwise/REAL-Video-Enhancer/blob/v2-main/screenshots/demo.png?raw=true" width = "100%">
@@ -128,7 +128,7 @@
128128
git clone --recurse-submodules https://github.com/TNTwise/REAL-Video-Enhancer
129129
130130
# Stable
131-
git clone --recurse-submodules https://github.com/TNTwise/REAL-Video-Enhancer --branch 2.3.6
131+
git clone --recurse-submodules https://github.com/TNTwise/REAL-Video-Enhancer --branch 2.3.8
132132
```
133133
# Building:
134134

@@ -161,6 +161,7 @@ python3 build.py --build BUILD_OPTION --copy_backend
161161
| Software Used | For | Link|
162162
|--|--|--|
163163
| FFmpeg | Multimedia framework for handling video, audio, and other media files | https://ffmpeg.org/
164+
| QT | GUI framework | https://qt.io/
164165
| FFMpeg Builds | Pre-compiled builds of FFMpeg. | Windows/Linux: https://github.com/BtbN/FFmpeg-Builds, MacOS: https://github.com/eko5624/mpv-mac
165166
| PyTorch | Neural Network Inference (CUDA/ROCm/TensorRT) | https://pytorch.org/
166167
| NCNN | Neural Network Inference (Vulkan) | https://github.com/tencent/ncnn

REAL-Video-Enhancer.nsi

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,12 @@
88
; Custom defines
99
!define NAME "REAL Video Enhancer"
1010
!define APPFILE "REAL-Video-Enhancer.exe"
11-
!define VERSION "2.3.7"
11+
!define VERSION "2.3.8"
1212
!define SLUG "${NAME} v${VERSION}"
1313
!define COMPANYNAME "TNTwise"
1414
!define VERSIONMAJOR 2
1515
!define VERSIONMINOR 3
16-
!define VERSIONBUILD 7
16+
!define VERSIONBUILD 8
1717
!define DISPLAYVERSION "${VERSIONMAJOR}.${VERSIONMINOR}.${VERSIONBUILD}"
1818
!define INSTALLSIZE 297000
1919

REAL-Video-Enhancer.py

Lines changed: 27 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -340,25 +340,27 @@ def switchToDownloadPage(self):
340340
self.animationHandler.fadeInAnimation(self.stackedWidget)
341341

342342
def updateVideoGUIText(self):
343+
self.settings.readSettings()
343344
if self.isVideoLoaded:
344345
upscaleModelName = self.upscaleModelComboBox.currentText()
345346
interpolateModelName = self.interpolateModelComboBox.currentText()
346347
interpolateTimes = self.getInterpolationMultiplier(interpolateModelName)
347348
scale = self.getUpscaleModelScale(upscaleModelName)
348-
text = (
349+
new_bitrate = 8 if "10" not in self.settingsTab.in_pix_fmt else 10
350+
inputText = (
349351
f"FPS: {round(self.videoFps, 0)} -> {round(self.videoFps * interpolateTimes, 0)}\n"
350352
+ f"Resolution: {self.videoWidth}x{self.videoHeight} -> {self.videoWidth * scale}x{self.videoHeight * scale}\n"
351353
+ f"Frame Count: {self.videoFrameCount} -> {int(round(self.videoFrameCount * interpolateTimes, 0))}\n"
352-
+ f"Bitrate: {self.videoBitrate}\n"
353-
+ f"Encoder: {self.videoEncoder}\n"
354-
+ f"Container: {self.videoContainer}\n"
355-
+ f"Color Space: {self.colorSpace}\n"
356-
+ f"Pixel Format: {self.pixelFMT}\n"
357-
+ f"HDR: {self.videoHDR}\n"
358-
+ f"Bit Depth: {self.videoBitDepth} bit\n"
354+
+ f"Encoder: {self.videoEncoder} -> {self.settings.settings['encoder']}\n"
355+
+ f"Container: {self.videoContainer} -> {self.settings.settings['video_container']}\n"
356+
+ f"Color Space: {self.colorSpace} -> {self.colorSpace}\n"
357+
+ f"Pixel Format: {self.settingsTab.in_pix_fmt} -> {self.settingsTab.out_pixel_fmt}\n"
358+
+ f"HDR: {self.videoHDR} -> {self.videoHDR if self.settings.settings['auto_hdr_mode'] == 'True' else 'False'}\n"
359+
+ f"Bit Depth: {self.videoBitDepth} bit -> {new_bitrate if self.settings.settings['auto_hdr_mode'] == 'True' else 8} bit\n"
359360
)
360-
self.videoInfoTextEdit.setFontPointSize(10)
361-
self.videoInfoTextEdit.setText(text)
361+
362+
self.inputVideoInfoTextEdit.setFontPointSize(10)
363+
self.inputVideoInfoTextEdit.setText(inputText)
362364

363365
def getInterpolationMultiplier(self, interpolateModelName):
364366
if interpolateModelName == "None" or not self.interpolateCheckBox.isChecked():
@@ -427,6 +429,7 @@ def updateVideoGUIDetails(self):
427429
isDeblur = self.deblurCheckBox.isChecked()
428430
isDenoise = self.denoiseCheckBox.isChecked()
429431
isDecompress = self.decompressCheckBox.isChecked()
432+
430433
self.interpolationContainer.setVisible(isInterpolate)
431434
self.interpolateContainer_2.setVisible(isInterpolate)
432435
self.deblurContainer.setVisible(isDeblur)
@@ -446,7 +449,13 @@ def updateVideoGUIDetails(self):
446449
self.startTimeSpinBox.setMaximum(self.videoLength)
447450
self.endTimeSpinBox.setMaximum(self.videoLength)
448451
self.timeInVideoScrollBar.setMaximum(self.videoLength)
449-
452+
if isUpscale and (self.upscaleModelComboBox.currentText() != "" or self.upscaleModelComboBox.currentText() != "None"):
453+
try:
454+
max_scale = totalModels[self.upscaleModelComboBox.currentText()][2]
455+
self.upscaleScaleSpinBox.setMaximum(max_scale if max_scale > 0 else 4)
456+
except KeyError: # idk why it does this, gui is shit tbh.
457+
self.upscaleScaleSpinBox.setMaximum(4)
458+
450459
def getCurrentRenderOptions(self, input_file=None, output_path=None):
451460
interpolate = self.interpolateModelComboBox.currentText()
452461
upscale = self.upscaleModelComboBox.currentText()
@@ -679,6 +688,8 @@ def disableProcessPage(self):
679688
child.setEnabled(False)
680689
for child in self.renderQueueTab.children():
681690
child.setEnabled(False)
691+
for child in self.encoderSettings.children():
692+
child.setEnabled(False)
682693
self.RenderedPreviewControlsContainer.setEnabled(False)
683694
self.scrollArea_4.setEnabled(True)
684695
self.scrollAreaWidgetContents_4.setEnabled(False)
@@ -691,6 +702,8 @@ def enableProcessPage(self):
691702
child.setEnabled(True)
692703
for child in self.renderQueueTab.children():
693704
child.setEnabled(True)
705+
for child in self.encoderSettings.children():
706+
child.setEnabled(True)
694707
self.RenderedPreviewControlsContainer.setEnabled(True)
695708
self.scrollAreaWidgetContents_4.setEnabled(True)
696709

@@ -753,6 +766,7 @@ def loadVideo(self, inputFile, multi_file=False):
753766
self.outputFileText.setEnabled(True)
754767

755768
self.outputFileSelectButton.setEnabled(True)
769+
self.openOutputFolderButton.setEnabled(True)
756770
self.isVideoLoaded = True
757771
self.updateVideoGUIDetails()
758772

@@ -915,11 +929,11 @@ def main():
915929
app.setStyle("Fusion")
916930
app.setPalette(Palette())
917931

918-
if not "--unlock" in sys.argv:
932+
"""if not "--unlock" in sys.argv:
919933
lock_file = QLockFile(LOCKFILE)
920934
if not lock_file.tryLock(10):
921935
QMessageBox.warning(None, "Instance Running", "Another instance is already running.")
922-
sys.exit(0)
936+
sys.exit(0)"""
923937

924938
# setting the pallette
925939
window = MainWindow()
@@ -933,7 +947,6 @@ def main():
933947
"""
934948
custom command args
935949
--debug: runs the app in debug mode
936-
--unlock: allows more than one instance to be launched
937950
--fullscreen: runs the app in fullscreen
938951
--swap-flatpak-checks: swaps the flatpak checks, ex if the app is running in flatpak, it will run as if it is not
939952
"""

backend/rve-backend.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
import argparse
33
import sys
44
from src.version import __version__
5+
from src.utils.Util import log
6+
57

68
class HandleApplication:
79
def __init__(self):
@@ -14,7 +16,7 @@ def __init__(self):
1416
"""from pyinstrument import Profiler
1517
profiler = Profiler()
1618
profiler.start()"""
17-
19+
1820
from src.utils.VideoInfo import OpenCVInfo, print_video_info
1921

2022
if self.args.print_video_info:
@@ -35,6 +37,13 @@ def __init__(self):
3537
download_ffmpeg()
3638

3739
if not self.batchProcessing():
40+
buffer_str = "=" * len(str(sys.argv[0]))
41+
log(buffer_str, False)
42+
log("RVE Backend Version: " + __version__, False)
43+
log(buffer_str, False)
44+
log("CLI Arguments: ", False)
45+
log(str(sys.argv), False)
46+
log(buffer_str, False)
3847
self.renderVideo()
3948

4049
else:

backend/src/FFmpegBuffers.py

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import queue
2+
import sys
23
from abc import ABC, abstractmethod
34
import os
45
import subprocess
56
import queue
6-
import sys
77
import time
88
import cv2
99
import numpy as np
@@ -36,15 +36,16 @@ def __init__(self, inputFile, width, height, start_time, end_time, borderX, bord
3636
self.color_transfer = color_transfer
3737
self.input_pixel_format = input_pixel_format
3838
self.yuv420pMOD = self.input_pixel_format == "yuv420p" and not self.hdr_mode
39-
39+
#self.yuv420pMOD = False
4040
if self.hdr_mode:
4141
self.inputFrameChunkSize = width * height * 6
4242
else:
4343
if self.yuv420pMOD:
4444
self.inputFrameChunkSize = width * height * 3 // 2
4545
else:
4646
self.inputFrameChunkSize = width * height * 3
47-
47+
command = self.command()
48+
log("FFMPEG READ COMMAND: " + str(command))
4849
self.readProcess = subprocess_popen_without_terminal(
4950
self.command(),
5051
stdout=subprocess.PIPE,
@@ -53,15 +54,14 @@ def __init__(self, inputFile, width, height, start_time, end_time, borderX, bord
5354
self.readQueue = queue.Queue(maxsize=25)
5455

5556
def command(self):
56-
log("Generating FFmpeg READ command...")
5757

5858
command = [
5959
f"{FFMPEG_PATH}",
6060
"-i",
6161
f"{self.inputFile}",
6262
]
63-
64-
filter_string = f"crop={self.width}:{self.height}:{self.borderX}:{self.borderY},scale=w=iw*sar:h=ih" # fix dar != sar
63+
64+
filter_string = f"crop={self.width}:{self.height}:{self.borderX}:{self.borderY},scale=w=iw*sar:h=ih" #+ ":in_range=limited:out_range=full,format=yuv420p" if self.yuv420pMOD == "yuv420p" else "" # fix dar != sar
6565
#if not self.hdr_mode:
6666
# if self.input_pixel_format == "yuv420p":
6767
# filter_string += ":in_range=tv:out_range=pc" # color shifts a smidgen but helps with artifacts when converting yuv to raw
@@ -182,17 +182,17 @@ def __init__(
182182
self.color_space = color_space
183183
self.color_primaries = color_primaries
184184
self.color_transfer = color_transfer
185-
log(f"FFmpegWrite parameters: inputFile={inputFile}, outputFile={outputFile}, width={width}, height={height}, start_time={start_time}, end_time={end_time}, fps={fps}, crf={crf}, audio_bitrate={audio_bitrate}, pixelFormat={pixelFormat}, overwrite={overwrite}, custom_encoder={custom_encoder}, benchmark={benchmark}, slowmo_mode={slowmo_mode}, upscaleTimes={upscaleTimes}, interpolateFactor={interpolateFactor}, ceilInterpolateFactor={ceilInterpolateFactor}, video_encoder={video_encoder}, audio_encoder={audio_encoder}, subtitle_encoder={subtitle_encoder}, hdr_mode={hdr_mode}, mpv_output={mpv_output}, merge_subtitles={merge_subtitles}")
186185
self.outputFPS = (
187186
(self.fps * self.interpolateFactor)
188187
if not self.slowmo_mode
189188
else self.fps
190189
)
191190
self.ffmpeg_log = open(FFMPEG_LOG_FILE, "w", encoding='utf-8')
192191
try:
193-
192+
command = self.command()
193+
log("\nFFMPEG WRITE COMMAND: " + str(command) + "\n")
194194
self.writeProcess = subprocess_popen_without_terminal(
195-
self.command(),
195+
command,
196196
stdin=subprocess.PIPE,
197197
stderr=self.ffmpeg_log,
198198
stdout=subprocess.PIPE if self.mpv_output else self.ffmpeg_log,
@@ -386,7 +386,7 @@ def command(self):
386386
"-",
387387
]
388388

389-
log("FFMPEG WRITE COMMAND: " + str(command))
389+
390390
return command
391391

392392
def get_num_frames_rendered(self):
@@ -440,7 +440,7 @@ def merge_subtitles(self):
440440
log("Benchmark mode enabled, skipping subtitle merge.")
441441
return
442442

443-
temp_output = self.outputFile + ".temp.mkv"
443+
temp_output = self.outputFile + "-" + str(os.getpid()) + "-temp.mkv"
444444
os.rename(self.outputFile, temp_output)
445445

446446
command = [
@@ -462,16 +462,14 @@ def merge_subtitles(self):
462462
self.outputFile,
463463
]
464464

465-
if self.overwrite:
466-
command.append("-y")
467-
468465
log("Merging subtitles with command: " + " ".join(command))
469466

470467
try:
471468
result = subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
472469
if result.returncode != 0:
473470
log("Failed to merge subtitles. FFmpeg error:")
474471
log(result.stderr.decode())
472+
os.remove(self.outputFile) # Remove incomplete output file
475473
os.rename(temp_output, self.outputFile) # Restore original file
476474
return
477475
os.remove(temp_output)

backend/src/RenderVideo.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
from .FFmpeg import InformationWriteOut
1212
from .utils.Encoders import EncoderSettings
1313
from .utils.SceneDetect import SceneDetect
14-
from .utils.Util import log, bytesToImg, resize_image_bytes
14+
from .utils.Util import log, resize_image_bytes
1515
from .utils.BorderDetect import BorderDetect
1616
from .utils.VideoInfo import OpenCVInfo
1717
import numpy as np
@@ -215,7 +215,7 @@ def __init__(
215215
log(f"Interpolate Factor: {self.interpolateFactor}")
216216
log(f"Total Output Frames: {self.totalOutputFrames}")
217217
log("Model Scale: " + str(self.modelScale))
218-
print("HDR Mode: " + str(hdr_mode), file=sys.stderr)
218+
log("HDR Mode: " + str(hdr_mode))
219219

220220
self.readBuffer = FFmpegRead( # input width
221221
inputFile=inputFile,

0 commit comments

Comments
 (0)