mpdecimate improvements, fix custom out path, lwi caching, alpha tests (wip)

This commit is contained in:
N00MKRAD
2025-03-23 19:36:57 +01:00
parent 15ad7f4316
commit e57a32d5b9
16 changed files with 167 additions and 87 deletions

View File

@@ -35,7 +35,7 @@
public class Interpolation
{
public enum MpDecimateSens { Normal, High, VeryHigh, Extreme }
public enum MpDecimateSens { Low, Normal, High, VeryHigh, Extreme }
}
}
}

View File

@@ -105,7 +105,7 @@ namespace Flowframes
return;
inPath = inputPath;
outPath = (Config.GetInt("outFolderLoc") == 0) ? inputPath.GetParentDir() : Config.Get("custOutDir").Trim();
// outPath = (Config.GetInt("outFolderLoc") == 0) ? inputPath.GetParentDir() : Config.Get("custOutDir").Trim();
tempFolder = InterpolateUtils.GetTempFolderLoc(inPath, outPath);
framesFolder = Path.Combine(tempFolder, Paths.framesDir);
interpFolder = Path.Combine(tempFolder, Paths.interpDir);

View File

@@ -86,7 +86,14 @@ namespace Flowframes.IO
return path;
}
public static string GetSessionDataPath()
public static string GetCachePath()
{
string path = Path.Combine(GetDataPath(), "cache");
Directory.CreateDirectory(path);
return path;
}
public static string GetSessionDataPath()
{
string path = Path.Combine(GetSessionsPath(), sessionTimestamp);
Directory.CreateDirectory(path);

View File

@@ -0,0 +1,16 @@
using System;
using System.IO;
using System.Text;
namespace Flowframes.Data
{
internal class PseudoHash
{
public static string GetHash(string path, bool b64 = true)
{
var file = new FileInfo(path);
string hash = $"{file.Name}{file.Length}{file.LastWriteTime.ToString("yyyyMMddHHmmss")}";
return b64 ? Convert.ToBase64String(Encoding.UTF8.GetBytes(hash)).TrimEnd('=') : hash;
}
}
}

View File

@@ -382,6 +382,7 @@
<Compile Include="Data\FpsInfo.cs" />
<Compile Include="Data\MediaFile.cs" />
<Compile Include="Data\ModelCollection.cs" />
<Compile Include="Data\PseudoHash.cs" />
<Compile Include="Data\Servers.cs" />
<Compile Include="Data\Streams\AttachmentStream.cs" />
<Compile Include="Data\Streams\AudioStream.cs" />

View File

@@ -115,8 +115,8 @@ namespace Flowframes.Forms
ConfigParser.SaveGuiElement(onlyShowRelevantSettings);
ConfigParser.SaveComboxIndex(processingMode);
ConfigParser.SaveGuiElement(maxVidHeight, ConfigParser.StringMode.Int);
ConfigParser.SaveComboxIndex(tempFolderLoc);
ConfigParser.SaveComboxIndex(outFolderLoc);
ConfigParser.SaveComboxIndex(tempFolderLoc); ConfigParser.SaveGuiElement(tempDirCustom);
ConfigParser.SaveComboxIndex(outFolderLoc); ConfigParser.SaveGuiElement(custOutDir);
ConfigParser.SaveGuiElement(keepTempFolder);
ConfigParser.SaveGuiElement(exportNamePattern);
ConfigParser.SaveGuiElement(exportNamePatternLoop);

View File

@@ -275,6 +275,7 @@ namespace Flowframes.IO
// Debug / Other / Experimental
if (key == Key.ffEncPreset) return WriteDefault(key, "fast");
if (key == Key.sbsRunPreviousStepIfNeeded) return WriteDefault(key, true);
if (keyStr == "mpdecimateMode") return WriteDefault(keyStr, "1");
if (type == Type.Int || type == Type.Float) return WriteDefault(key, "0"); // Write default int/float (0)
if (type == Type.Bool) return WriteDefault(key, false); // Write default bool (False)
return WriteDefault(key, "");

View File

@@ -309,9 +309,9 @@ namespace Flowframes.Magick
Logger.Log($"Dedupe: Factor is 1, will not redupe; overriding factor to {frameCount}/{inputFrames.Count} = {Interpolate.currentSettings.interpFactor.ToString("0.######")}", true);
}
if (keepPercentage > 95f)
if (keepPercentage > 85f)
{
Logger.Log("Deduplication: Less than 5% duplicate frames detected; disabling for this video.");
Logger.Log("Deduplication: Less than 15% duplicate frames detected; disabling for this video.");
Interpolate.currentSettings.dedupe = false;
}

View File

@@ -72,16 +72,32 @@ namespace Flowframes.Main
}
private const bool _useNutPipe = true;
public enum AlphaMode { None, AlphaOut, AlphaIn }
public static async Task<string> GetPipedFfmpegCmd(bool ffplay = false)
public static async Task<string> GetPipedFfmpegCmd(bool ffplay = false, AlphaMode alpha = AlphaMode.None)
{
InterpSettings s = I.currentSettings;
string encArgs = FfmpegUtils.GetEncArgs(s.outSettings, (s.OutputResolution.IsEmpty ? s.InputResolution : s.OutputResolution), s.outFps.Float, true).FirstOrDefault();
var alphaOutSettings = new OutputSettings { Encoder = Enums.Encoding.Encoder.X264, PixelFormat = Enums.Encoding.PixelFormat.Yuv444P, CustomQuality = "20" };
var outSettings = alpha == AlphaMode.AlphaOut ? alphaOutSettings : s.outSettings;
var outRes = s.OutputResolution.IsEmpty ? s.InputResolution : s.OutputResolution;
string encArgs = FfmpegUtils.GetEncArgs(outSettings, outRes, s.outFps.Float, true).First();
bool fpsLimit = MaxFpsFrac.Float > 0f && s.outFps.Float > MaxFpsFrac.Float;
bool gifInput = I.currentMediaFile.Format.Upper() == "GIF"; // If input is GIF, we don't need to check the color space etc
VidExtraData extraData = gifInput ? new VidExtraData() : await FfmpegCommands.GetVidExtraInfo(s.inPath);
string extraArgsIn = await FfmpegEncode.GetFfmpegExportArgsIn(I.currentMediaFile.IsVfr ? s.outFpsResampled : s.outFps, s.outItsScale, extraData.Rotation);
string extraArgsOut = await FfmpegEncode.GetFfmpegExportArgsOut(fpsLimit ? MaxFpsFrac : new Fraction(), extraData, s.outSettings);
string extraArgsOut;
string alphaPassFile = Path.Combine(s.tempFolder, "alpha.mkv");
Fraction fps = fpsLimit ? MaxFpsFrac : new Fraction();
if (alpha == AlphaMode.AlphaOut)
{
extraArgsOut = await FfmpegEncode.GetFfmpegExportArgsOut(fps, new VidExtraData(), alphaOutSettings);
return $"{extraArgsIn} -i - {extraArgsOut} {encArgs} {alphaPassFile.Wrap()}";
}
else
{
extraArgsOut = await FfmpegEncode.GetFfmpegExportArgsOut(fps, extraData, s.outSettings, alphaPassFile: alpha == AlphaMode.AlphaIn ? alphaPassFile : "");
}
// For EXR, force bt709 input flags. Not sure if this really does anything
if (s.outSettings.Encoder == Enums.Encoding.Encoder.Exr)
@@ -95,7 +111,7 @@ namespace Flowframes.Main
string format = _useNutPipe ? "nut" : "yuv4mpegpipe";
return
$"{extraArgsIn} -i pipe: {encArgs} {extraArgsOut} -f {format} - | ffplay - " +
$"{extraArgsIn} -i - {encArgs} {""} -f {format} - | ffplay - " +
$"-autoexit -seek_interval {VapourSynthUtils.GetSeekSeconds(Program.mainForm.currInDuration)} " +
$"-window_title \"Flowframes Realtime Interpolation ({s.inFps.GetString()} FPS x{s.interpFactor} = {s.outFps.GetString()} FPS) ({s.model.Name})\" ";
}
@@ -111,7 +127,13 @@ namespace Flowframes.Main
s.FullOutPath += $"/%{Padding.interpFrames}d.{s.outSettings.Encoder.GetInfo().OverideExtension}";
}
return $"{extraArgsIn} -i pipe: {extraArgsOut} {encArgs} {s.FullOutPath.Wrap()}";
// Merge alpha
if (alpha == AlphaMode.AlphaIn)
{
return $"{extraArgsIn} -i - {extraArgsOut} {encArgs} {s.FullOutPath.Wrap()}";
}
return $"{extraArgsIn} -i - {extraArgsOut} {encArgs} {s.FullOutPath.Wrap()}";
}
}
@@ -400,7 +422,7 @@ namespace Flowframes.Main
return;
}
if(I.currentMediaFile.IsVfr && I.currentMediaFile.OutputFrameIndexes != null && I.currentMediaFile.OutputFrameIndexes.Count > 0)
if (I.currentMediaFile.IsVfr && I.currentMediaFile.OutputFrameIndexes != null && I.currentMediaFile.OutputFrameIndexes.Count > 0)
{
Logger.Log($"{nameof(MuxTimestamps)}: CFR conversion due to FPS limit was applied (picked {I.currentMediaFile.OutputFrameIndexes.Count} frames for {I.currentSettings.outFpsResampled} FPS); won't mux timestamps.", hidden: true);
return;

View File

@@ -16,20 +16,30 @@ namespace Flowframes
public static string hdrFilter = @"-vf zscale=t=linear:npl=100,format=gbrpf32le,zscale=p=bt709,tonemap=tonemap=hable:desat=0,zscale=t=bt709:m=bt709:r=tv,format=yuv420p";
public static string pngCompr = "-compression_level 3";
public static Dictionary<Enums.Interpolation.MpDecimateSens, int> MpDecSensLookup = new Dictionary<Enums.Interpolation.MpDecimateSens, int>
/// <summary> Lookup table for mpdecimate sensitivity preset values (lo/hi/frac). </summary>
public static Dictionary<Enums.Interpolation.MpDecimateSens, (int, int, float)> MpDecSensLookup = new Dictionary<Enums.Interpolation.MpDecimateSens,(int, int, float)>
{
{ Enums.Interpolation.MpDecimateSens.Normal, 4 },
{ Enums.Interpolation.MpDecimateSens.High, 20 },
{ Enums.Interpolation.MpDecimateSens.VeryHigh, 32 },
{ Enums.Interpolation.MpDecimateSens.Extreme, 40 }
{ Enums.Interpolation.MpDecimateSens.Low, (3, 10, 0.33f) },
{ Enums.Interpolation.MpDecimateSens.Normal, (4, 12, 0.50f) },
{ Enums.Interpolation.MpDecimateSens.High, (20, 18, 0.65f) },
{ Enums.Interpolation.MpDecimateSens.VeryHigh, (32, 24, 0.75f) },
{ Enums.Interpolation.MpDecimateSens.Extreme, (40, 30, 0.90f) },
};
public static string GetMpdecimate(bool wrap = true)
/// <summary>
/// Construct mpdecimate filter with prefiltering: <paramref name="scaleSize"/> limits resolution, <paramref name="cropSize"/> center-crops the frame using a factor,
/// <paramref name="lumaOnly"/> only processes luma channel.<br/><paramref name="wrap"/> wraps the filter in double quotes.
/// </summary>
public static string GetMpdecimate(bool wrap = true, int scaleSize = 640, float cropSize = 0.8f, bool lumaOnly = true)
{
int mpdValIndex = Config.GetInt(Config.Key.mpdecimateMode);
int mpdVal = MpDecSensLookup[(Enums.Interpolation.MpDecimateSens)mpdValIndex];
string mpd = $"mpdecimate=hi=64*12:lo=64*{mpdVal}:frac=1.0";
return wrap ? mpd.Wrap() : mpd;
(int lo, int hi, float frac) = MpDecSensLookup[(Enums.Interpolation.MpDecimateSens)mpdValIndex];
string format = lumaOnly ? $"format=yuv420p,extractplanes=y" : "";
string scale = scaleSize > 64 ? $"scale='min({scaleSize},iw)':min'({scaleSize},ih)':force_original_aspect_ratio=decrease:force_divisible_by=2" : "";
string crop = cropSize > 0.1f && cropSize < 0.99f ? $"crop=iw*{cropSize}:ih*{cropSize}" : "";
string mpdec = $"mpdecimate=hi=64*{hi}:lo=64*{lo}:frac={frac.ToString("0.0#")}";
string filters = string.Join(",", new string[] { format, crop, scale, mpdec }.Where(s => s.IsNotEmpty())); // Only take non-empty filter strings
return wrap ? filters.Wrap() : filters;
}
public enum ModuloMode { Disabled, ForInterpolation, ForEncoding }

View File

@@ -49,12 +49,12 @@ namespace Flowframes.Media
var args = new List<string>();
fps = fps / new Fraction(itsScale);
if(fps > 0.1f)
if (fps > 0.1f)
{
args.Add($"-r {fps}");
}
if(rotation != 0)
if (rotation != 0)
{
args.Add($"-display_rotation {rotation}");
}
@@ -62,24 +62,13 @@ namespace Flowframes.Media
return string.Join(" ", args);
}
public static async Task<string> GetFfmpegExportArgsOut(Fraction resampleFps, VidExtraData extraData, OutputSettings settings, bool isChunk = false)
public static async Task<string> GetFfmpegExportArgsOut(Fraction resampleFps, VidExtraData extraData, OutputSettings settings, bool isChunk = false, string alphaPassFile = "")
{
var beforeArgs = new List<string>();
var filters = new List<string>();
var extraArgs = new List<string> { Config.Get(Config.Key.ffEncArgs) };
var mf = Interpolate.currentMediaFile;
if (resampleFps.Float >= 0.1f)
{
if (Interpolate.currentMediaFile.IsVfr && !Interpolate.currentSettings.dedupe)
{
Logger.Log($"Won't add fps filter as VFR handling already outputs at desired frame rate ({resampleFps.Float} FPS)", true);
}
else
{
filters.Add($"fps={resampleFps}");
}
}
int inputs = 1;
if (Config.GetBool(Config.Key.keepColorSpace) && extraData.HasAllColorValues())
{
@@ -93,24 +82,42 @@ namespace Flowframes.Media
if (!isChunk && settings.Format == Enums.Output.Format.Mp4 || settings.Format == Enums.Output.Format.Mov)
extraArgs.Add($"-movflags +faststart");
if (resampleFps.Float >= 0.1f)
{
if (Interpolate.currentMediaFile.IsVfr && !Interpolate.currentSettings.dedupe)
{
Logger.Log($"Won't add fps filter as VFR handling already outputs at desired frame rate ({resampleFps.Float} FPS)", true);
}
else
{
filters.Add($"fps={resampleFps}");
}
}
if (alphaPassFile.IsNotEmpty())
{
beforeArgs.Add($"-i {alphaPassFile.Wrap()}");
filters.Add($"[{inputs}:v]alphamerge");
inputs++;
}
if (settings.Format == Enums.Output.Format.Gif)
{
string dither = Config.Get(Config.Key.gifDitherType).Split(' ').First();
string palettePath = Path.Combine(Paths.GetSessionDataPath(), "palette.png");
string paletteFilter = $"[1:v]paletteuse=dither={dither}";
int colors = OutputUtils.GetGifColors(ParseUtils.GetEnum<Enums.Encoding.Quality.GifColors>(settings.Quality, true, Strings.VideoQuality));
string palettePath = Path.Combine(Paths.GetSessionDataPath(), "palette.png");
await FfmpegExtract.GeneratePalette(mf.ImportPath, palettePath, colors);
if (File.Exists(palettePath))
{
beforeArgs.Add($"-i {palettePath.Wrap()}");
filters.Add(paletteFilter);
inputs++;
filters.Add($"[{inputs - 1}:v]paletteuse=dither={dither}");
}
}
else if (settings.Encoder == Enums.Encoding.Encoder.Exr)
{
if(mf.Format.Upper() != "EXR")
if (mf.Format.Upper() != "EXR")
filters.Add($"zscale=transfer=linear,format={settings.PixelFormat.ToString().Lower()}".Wrap());
}

View File

@@ -71,13 +71,11 @@ namespace Flowframes.MiscUtils
}
// Otherwise return "numerator/denominator"
Logger.Log($"Approximated fraction for {value}: {bestNum}/{bestDen} (={((float)bestNum / bestDen).ToString("0.0#######")})", true);
// Logger.Log($"Approximated fraction for {value}: {bestNum}/{bestDen} (={((float)bestNum / bestDen).ToString("0.0#######")})", true);
return (bestNum, bestDen);
}
/// <summary>
/// Computes the greatest common divisor (Euclid's algorithm).
/// </summary>
/// <summary> Computes the greatest common divisor (Euclid's algorithm). </summary>
private static int GCD(int a, int b)
{
a = Math.Abs(a);

View File

@@ -375,7 +375,6 @@ namespace Flowframes.Os
IoUtils.CreateDir(outPath);
Process rifeNcnnVs = OsUtils.NewProcess(!OsUtils.ShowHiddenCmd());
string avDir = Path.Combine(Paths.GetPkgPath(), Paths.audioVideoDir);
string pipedTargetArgs = $"{Path.Combine(avDir, "ffmpeg").Wrap()} -loglevel warning -stats -y {await Export.GetPipedFfmpegCmd(rt)}";
string pkgDir = Path.Combine(Paths.GetPkgPath(), Implementations.rifeNcnnVs.PkgDir);
int gpuId = NcnnGpuIds.Split(',')[0].GetInt();
@@ -408,26 +407,26 @@ namespace Flowframes.Os
AiStarted(rifeNcnnVs, 1000, inPath);
}
string scriptPath = Path.Combine(Paths.GetPkgPath(), Implementations.rifeNcnnVs.PkgDir, "rife.py");
string vsPipeArgs = $"{scriptPath} {VapourSynthUtils.GetVsPipeArgs(vsSettings)} -c y4m -";
rifeNcnnVs.StartInfo.Arguments = $"{OsUtils.GetCmdArg()} cd /D {pkgDir.Wrap()} & vspipe {vsPipeArgs} | {pipedTargetArgs}";
IoUtils.TryDeleteIfExists(Path.Combine(Interpolate.currentSettings.tempFolder, "alpha.mkv"));
string vspipe = $"vspipe rife.py {VapourSynthUtils.GetVsPipeArgs(vsSettings)}";
string ffmpeg = $"{Path.Combine(avDir, "ffmpeg").Wrap()} -loglevel warning -stats -y";
string baseArgs = $"{OsUtils.GetCmdArg()} cd /D {pkgDir.Wrap()}";
if(vsSettings.Alpha)
{
rifeNcnnVs.StartInfo.Arguments = $"{baseArgs} && {vspipe} --arg alpha=\"True\" -c y4m - | {ffmpeg} {await Export.GetPipedFfmpegCmd(alpha: Export.AlphaMode.AlphaOut)} && {vspipe} -c y4m - | {ffmpeg} {await Export.GetPipedFfmpegCmd(alpha: Export.AlphaMode.AlphaIn)}";
}
else
{
rifeNcnnVs.StartInfo.Arguments = $"{baseArgs} && {vspipe} -c y4m - | {ffmpeg} {await Export.GetPipedFfmpegCmd(rt)}";
}
Logger.Log($"cmd.exe {rifeNcnnVs.StartInfo.Arguments}", true);
if (!OsUtils.ShowHiddenCmd())
{
rifeNcnnVs.OutputDataReceived += (sender, outLine) => { LogOutput("[O] " + outLine.Data, Implementations.rifeNcnnVs); };
rifeNcnnVs.ErrorDataReceived += (sender, outLine) => { LogOutput("[E] " + outLine.Data, Implementations.rifeNcnnVs, true); };
}
rifeNcnnVs.OutputDataReceived += (sender, outLine) => { LogOutput("[O] " + outLine.Data, Implementations.rifeNcnnVs); };
rifeNcnnVs.ErrorDataReceived += (sender, outLine) => { LogOutput("[E] " + outLine.Data, Implementations.rifeNcnnVs, true); };
rifeNcnnVs.Start();
if (!OsUtils.ShowHiddenCmd())
{
rifeNcnnVs.BeginOutputReadLine();
rifeNcnnVs.BeginErrorReadLine();
}
rifeNcnnVs.BeginOutputReadLine();
rifeNcnnVs.BeginErrorReadLine();
while (!rifeNcnnVs.HasExited) await Task.Delay(1);
}

View File

@@ -18,6 +18,7 @@ namespace Flowframes.Os
public InterpSettings InterpSettings { get; set; }
public string ModelDir { get; set; } = "";
public float Factor { get; set; } = 2.0f;
public bool Alpha { get; set; } = false;
public Size Res { get; set; } = new Size();
public bool Uhd { get; set; } = false;
public float SceneDetectSensitivity { get; set; } = 0.15f;
@@ -37,17 +38,17 @@ namespace Flowframes.Os
{
Logger.Log($"Preparing RIFE VS args. Model: {s.ModelDir}, Factor: {s.Factor}, Res: {s.Res.Width}x{s.Res.Height}, UHD: {s.Uhd}, SC Sens: {s.SceneDetectSensitivity}, " +
$"GPU ID: {s.GpuId}, GPU Threads: {s.GpuThreads}, TTA: {s.Tta}, Loop: {s.Loop}, Match Duration: {s.MatchDuration}, Dedupe: {s.Dedupe}, RT: {s.Realtime}{(s.Osd ? $", OSD: {s.Osd}" : "")}", true);
bool debug = Program.Debug && !(System.Windows.Input.Keyboard.Modifiers == System.Windows.Input.ModifierKeys.Shift);
var args = new List<(string, object)>()
{
("input", s.InterpSettings.inPath), // Input path
("tmpDir", s.InterpSettings.tempFolder), // Temp dir path
("cache", Path.Combine(Paths.GetCachePath(), PseudoHash.GetHash(s.InterpSettings.inPath) + ".lwi")), // File PseudoHash to allow caching
("inFps", s.InterpSettings.inFps), // Input FPS
("outFps", !s.InterpSettings.inputIsFrames ? Interpolate.currentMediaFile.VideoStreams.First().FpsInfo.SpecifiedFps * s.Factor : s.InterpSettings.inFps * s.Factor), // Output FPS
("outFpsRes", s.InterpSettings.outFpsResampled),
("resIn", s.InterpSettings.InputResolution.ToStringShort()),
("resSc", s.InterpSettings.ScaledResolution.ToStringShort()),
("resOut", s.InterpSettings.OutputResolution.ToStringShort()),
("pad", $"{s.InterpSettings.InterpResolution.Width - s.InterpSettings.ScaledResolution.Width}x{s.InterpSettings.InterpResolution.Height - s.InterpSettings.ScaledResolution.Height}"), // Padding
("frames", s.InterpSettings.inputIsFrames), // Input is frames?
("dedupe", s.InterpSettings.dedupe), // Dedupe?
@@ -56,16 +57,15 @@ namespace Flowframes.Os
("sc", s.SceneDetectSensitivity), // Scene change detection sensitivity
("loop", s.Loop), // Loop?
("factor", new Fraction(s.Factor)),
("mdlPath", Path.Combine(Paths.GetPkgPath(), Implementations.rifeNcnnVs.PkgDir, s.ModelDir).Replace(@"\", "/")), // Model path
("gpuThreads", s.GpuThreads), // GPU threads
("mdl", s.ModelDir), // Path.Combine(Paths.GetPkgPath(), Implementations.rifeNcnnVs.PkgDir, s.ModelDir).Replace(@"\", "/")), // Model path
("gpuThrds", s.GpuThreads), // GPU threads
("uhd", s.Uhd), // UHD?
("tta", s.Tta), // TTA?
("gpu", s.GpuId), // GPU ID
("rt", s.Realtime), // Realtime?
("osd", s.Osd), // OSD?
("debugFrNums", Program.Debug), // Show debug overlay with frame nums?
("debugVars", Program.Debug), // Show debug overlay with variables?
("txtScale", (s.InterpSettings.ScaledResolution.Width / 1000f).RoundToInt().Clamp(1, 4)), // Text scale
("osd", debug), // OSD?
("debugFrNums", debug), // Show debug overlay with frame nums?
("debugVars", debug), // Show debug overlay with variables?
};
long frameCount = Interpolate.currentMediaFile.FrameCount;
@@ -100,6 +100,7 @@ namespace Flowframes.Os
args.Add(("cMatrix", use470bg ? "470bg" : ""));
args.Add(("targetMatch", targetFrameCountMatchDuration));
args = args.Where(a => a.Item2.ToString() != "False" && a.Item2.ToString() != "").ToList();
return string.Join(" ", args.Select(a => $"--arg {a.Item1}={a.Item2.ToString().Wrap()}"));
}

View File

@@ -141,6 +141,14 @@ namespace Flowframes
{
IoUtils.TryDeleteIfExists(installerTempDir);
}
foreach (var cacheFile in IoUtils.GetFileInfosSorted(Paths.GetCachePath(), true))
{
if ((DateTime.Now - cacheFile.LastWriteTime).TotalDays > 3d)
{
IoUtils.TryDeleteIfExists(cacheFile.FullName);
}
}
}
catch (Exception e)
{

View File

@@ -10,6 +10,7 @@ core = vs.core
# Vars from command line (via VSPipe)
input_path = globals()["input"]
temp_dir_path = globals()["tmpDir"]
cache_file = globals()["cache"]
fps_in = globals()["inFps"]
fps_out = globals()["outFps"]
fps_out_resampled = globals()["outFpsRes"]
@@ -30,6 +31,12 @@ show_vars = globals()["debugVars"] == 'True'
txt_scale = globals()["txtScale"]
trim = globals()["trim"]
override_c_matrix = globals()["cMatrix"]
alpha = globals()["alpha"] == 'True'
if alpha:
show_frame_nums = False
show_vars = False
perf_osd = False
# Construct & parse additional variables
frames_dir = os.path.join(temp_dir_path, 'frames')
@@ -52,8 +59,10 @@ if frames:
clip = core.imwri.Read(rf"{pattern}", firstnum=int(first)) # Load the image sequence with imwri
clip = core.std.AssumeFPS(clip, fpsnum=infps_num, fpsden=infps_den) # Set the frame rate for the image sequence
else:
index_file_path = os.path.join(temp_dir_path, 'index.lwi') if os.path.isdir(temp_dir_path) else f'{input_path}.index.lwi'
clip = core.lsmas.LWLibavSource(input_path, cachefile=index_file_path) # Load video with lsmash
clip = core.lsmas.LWLibavSource(input_path, cachefile=cache_file) # Load video with lsmash
if alpha:
clip = core.std.PropToClip(clip, prop='_Alpha') # Process only alpha channel
src_frames = len(clip) # Amount of source frames
@@ -107,6 +116,10 @@ resize = res_scaled and res_scaled != "0x0" and res_scaled != res_input
res_w = res_scaled_x if resize else res_in_x
res_h = res_scaled_y if resize else res_in_y
# Scene change detection
if sc_sens > 0.01:
clip = core.misc.SCDetect(clip=clip, threshold=sc_sens)
# Convert to RGBS from YUV or RGB
colors = "YUV" if clip.format.color_family == vs.YUV else "RGB"
if colors == "YUV":
@@ -121,10 +134,6 @@ info_str += f"Loop: {loop}\nScn Detect: {sc_sens}\nMatch Dur: {match_duration}\n
if pad_x > 0 or pad_y > 0:
clip = core.std.AddBorders(clip, right=pad_x, bottom=pad_y)
# Scene change detection
if sc_sens > 0.01:
clip = core.misc.SCDetect(clip=clip, threshold=sc_sens)
pre_interp_frames = len(clip)
frames_processed_total = 0
@@ -153,17 +162,21 @@ r_fac_num, r_fac_den = map(int, factor.split('/'))
clip = core.rife.RIFE(clip, factor_num=r_fac_num, factor_den=r_fac_den, model_path=r_mdlpath, gpu_id=(None if r_gpu < 0 else r_gpu), gpu_thread=r_threads, tta=r_tta, uhd=r_uhd, sc=sc_sens > 0.01)
# Reduplication
if dedupe and allow_redupe and not realtime:
def reorder_clip(clip, frames_vs_json_path):
reordered_clip = clip[0]
with open(frames_vs_json_path) as json_file:
with open(frames_vs_json_path, 'r') as json_file:
frame_list = json.load(json_file)
for i in frame_list:
if i < clip.num_frames:
reordered_clip = reordered_clip + clip[i]
clip = reordered_clip.std.Trim(1, reordered_clip.num_frames - 1) # Redupe trim
# Redupe trim and return the result
return reordered_clip.std.Trim(1, reordered_clip.num_frames - 1) # Redupe trim
if dedupe and allow_redupe and not realtime:
clip = reorder_clip(clip, frames_vs_json_path)
# Set output format & color matrix
clip = vs.core.resize.Bicubic(clip, format=vs.YUV444P16, matrix_s=c_matrix)
clip = vs.core.resize.Bicubic(clip, format=vs.YUV444P16, matrix_s=c_matrix) if not alpha else vs.core.resize.Bicubic(clip, format=vs.GRAY8, matrix_s=c_matrix)
# Undo compatibility padding by cropping the same area
if pad_x > 0 or pad_y > 0:
@@ -231,7 +244,4 @@ if os.path.isfile(vfr_json_path):
if realtime and loop:
clip = clip.std.Loop(0)
clip.set_output()
if os.path.isfile(index_file_path):
os.remove(index_file_path)
clip.set_output()