From 124aa6bfb4b8896a65ec99cd0e6eb27cf157c587 Mon Sep 17 00:00:00 2001 From: N00MKRAD Date: Thu, 7 Jan 2021 12:15:13 +0100 Subject: [PATCH] Check GIF max framerate, minor QOL & logging improvements --- Code/AudioVideo/AvProcess.cs | 3 ++- Code/AudioVideo/FFmpegCommands.cs | 14 +++++++------- Code/ExtensionMethods.cs | 11 +++++++++++ Code/Magick/Dedupe.cs | 2 +- Code/Main/Interpolate.cs | 2 +- Code/Main/InterpolateSteps.cs | 2 +- Code/Main/InterpolateUtils.cs | 9 +++++++-- Code/OS/AiProcess.cs | 8 ++++---- Code/UI/MainUiFunctions.cs | 4 ++-- 9 files changed, 36 insertions(+), 19 deletions(-) diff --git a/Code/AudioVideo/AvProcess.cs b/Code/AudioVideo/AvProcess.cs index 1416a11..ec4e048 100644 --- a/Code/AudioVideo/AvProcess.cs +++ b/Code/AudioVideo/AvProcess.cs @@ -24,11 +24,12 @@ namespace Flowframes public static async Task RunFfmpeg(string args, LogMode logMode, TaskType taskType = TaskType.Other) { - await RunFfmpeg(args, "", logMode); + await RunFfmpeg(args, "", logMode, taskType); } public static async Task RunFfmpeg(string args, string workingDir, LogMode logMode, TaskType taskType = TaskType.Other) { + args = args.TrimWhitespacesSafe(); lastOutputFfmpeg = ""; currentLogMode = logMode; Process ffmpeg = OSUtils.NewProcess(true); diff --git a/Code/AudioVideo/FFmpegCommands.cs b/Code/AudioVideo/FFmpegCommands.cs index 8ceb937..c9246d4 100644 --- a/Code/AudioVideo/FFmpegCommands.cs +++ b/Code/AudioVideo/FFmpegCommands.cs @@ -79,19 +79,19 @@ namespace Flowframes DeleteSource(inpath); } - public static async Task ExtractSingleFrame(string inputFile, int frameNum, bool hdr, bool delSrc) + public static async Task ExtractSingleFrame(string inputFile, int frameNum) { string outPath = $"{inputFile}-frame{frameNum}.png"; - await ExtractSingleFrame(inputFile, outPath, frameNum, hdr, delSrc); + await ExtractSingleFrame(inputFile, outPath, frameNum); } - public static async Task ExtractSingleFrame(string inputFile, string outputPath, int frameNum, bool hdr, bool delSrc) + public static async Task ExtractSingleFrame(string inputFile, string outputPath, int frameNum) { - string hdrStr = hdr ? hdrFilter : ""; - string args = $"-i {inputFile.Wrap()} {pngComprArg} {hdrStr }-vf \"select=eq(n\\,{frameNum})\" -vframes 1 {outputPath.Wrap()}"; + bool isPng = (Path.GetExtension(outputPath).ToLower() == ".png"); + string comprArg = isPng ? pngComprArg : ""; + string pixFmt = "-pix_fmt " + (isPng ? "rgb24" : "yuvj420p"); + string args = $"-i {inputFile.Wrap()} {comprArg} -vf \"select=eq(n\\,{frameNum})\" -vframes 1 {pixFmt} {outputPath.Wrap()}"; await AvProcess.RunFfmpeg(args, AvProcess.LogMode.Hidden, AvProcess.TaskType.ExtractFrames); - if (delSrc) - DeleteSource(inputFile); } public static async Task FramesToVideoConcat(string framesFile, string outPath, Interpolate.OutMode outMode, float fps, AvProcess.LogMode logMode = AvProcess.LogMode.OnlyLastLine, bool isChunk = false) diff --git a/Code/ExtensionMethods.cs b/Code/ExtensionMethods.cs index 475afcf..41cf49d 100644 --- a/Code/ExtensionMethods.cs +++ b/Code/ExtensionMethods.cs @@ -124,6 +124,17 @@ namespace Flowframes return str.Replace(stringToRemove, ""); } + public static string TrimWhitespacesSafe (this string str) // Trim whitespaces, unless they are "quoted" (to avoid trimming file paths) + { + var result = str.Split('"').Select((element, index) => index % 2 == 0 ? element.TrimWhitespaces() : element.Wrap()); + string resultJoined = string.Join("", result); + + result = resultJoined.Split('\'').Select((element, index) => index % 2 == 0 ? element.TrimWhitespaces() : "'" + element + "'"); + resultJoined = string.Join("", result); + + return resultJoined; + } + public static string TrimWhitespaces(this string str) { if (str == null) return str; diff --git a/Code/Magick/Dedupe.cs b/Code/Magick/Dedupe.cs index 23c306b..3ec2384 100644 --- a/Code/Magick/Dedupe.cs +++ b/Code/Magick/Dedupe.cs @@ -127,7 +127,7 @@ namespace Flowframes.Magick break; } - if (sw.ElapsedMilliseconds >= 1000 || (i+1) == framePaths.Length) // Print every 1s (or when done) + if (sw.ElapsedMilliseconds >= 500 || (i+1) == framePaths.Length) // Print every 0.5s (or when done) { sw.Restart(); Logger.Log($"[Deduplication] Running de-duplication ({i}/{framePaths.Length}), deleted {statsFramesDeleted} ({(((float)statsFramesDeleted / framePaths.Length) * 100f).ToString("0")}%) duplicate frames so far...", false, true); diff --git a/Code/Main/Interpolate.cs b/Code/Main/Interpolate.cs index b306925..8289a82 100644 --- a/Code/Main/Interpolate.cs +++ b/Code/Main/Interpolate.cs @@ -36,7 +36,7 @@ namespace Flowframes public static async Task Start() { canceled = false; - if (!Utils.InputIsValid(current.inPath, current.outPath, current.outFps, current.interpFactor, current.tilesize)) return; // General input checks + if (!Utils.InputIsValid(current.inPath, current.outPath, current.outFps, current.interpFactor, current.tilesize, current.outMode)) return; // General input checks if (!Utils.CheckAiAvailable(current.ai)) return; // Check if selected AI pkg is installed if (!Utils.CheckDeleteOldTempFolder()) return; // Try to delete temp folder if an old one exists if(!Utils.CheckPathValid(current.inPath)) return; // Check if input path/file is valid diff --git a/Code/Main/InterpolateSteps.cs b/Code/Main/InterpolateSteps.cs index 2d9c125..2642725 100644 --- a/Code/Main/InterpolateSteps.cs +++ b/Code/Main/InterpolateSteps.cs @@ -30,7 +30,7 @@ namespace Flowframes.Main Program.mainForm.SetWorking(true); current = Program.mainForm.GetCurrentSettings(); - if (!InterpolateUtils.InputIsValid(current.inPath, current.outPath, current.outFps, current.interpFactor, current.tilesize)) return; // General input checks + if (!InterpolateUtils.InputIsValid(current.inPath, current.outPath, current.outFps, current.interpFactor, current.tilesize, current.outMode)) return; // General input checks if (step.Contains("Extract Scene Changes")) { diff --git a/Code/Main/InterpolateUtils.cs b/Code/Main/InterpolateUtils.cs index d17f122..671c7bb 100644 --- a/Code/Main/InterpolateUtils.cs +++ b/Code/Main/InterpolateUtils.cs @@ -176,7 +176,7 @@ namespace Flowframes.Main return Path.Combine(basePath, Path.GetFileNameWithoutExtension(inPath).StripBadChars().Remove(" ").Trunc(30, false) + "-temp"); } - public static bool InputIsValid(string inDir, string outDir, float fpsOut, int interp, int tilesize) + public static bool InputIsValid(string inDir, string outDir, float fpsOut, int interp, int tilesize, Interpolate.OutMode outMode) { bool passes = true; @@ -197,9 +197,14 @@ namespace Flowframes.Main ShowMessage("Interpolation factor is not valid!"); passes = false; } + if (passes && outMode == i.OutMode.VidGif && fpsOut >= 50) + { + ShowMessage("Invalid output frame rate!\nGIF does not properly support frame rates above 40 FPS.\nPlease use MP4, WEBM or another video format."); + passes = false; + } if (passes && fpsOut < 1 || fpsOut > 500) { - ShowMessage("Invalid target frame rate - Must be 1-500."); + ShowMessage("Invalid output frame rate - Must be 1-500."); passes = false; } if (passes && tilesize % 32 != 0 || tilesize < 128) diff --git a/Code/OS/AiProcess.cs b/Code/OS/AiProcess.cs index 024a269..cea5e98 100644 --- a/Code/OS/AiProcess.cs +++ b/Code/OS/AiProcess.cs @@ -67,7 +67,7 @@ namespace Flowframes string dainDir = Path.Combine(Paths.GetPkgPath(), Path.GetFileNameWithoutExtension(Packages.dainNcnn.fileName)); Process dain = OSUtils.NewProcess(!OSUtils.ShowHiddenCmd()); AiStarted(dain, 1500, Interpolate.current.interpFactor); - dain.StartInfo.Arguments = $"{OSUtils.GetCmdArg()} cd /D {dainDir.Wrap()} & dain-ncnn-vulkan.exe {args} -f {InterpolateUtils.GetOutExt()} -j {GetNcnnThreads()}"; + dain.StartInfo.Arguments = $"{OSUtils.GetCmdArg()} cd /D {dainDir.Wrap()} & dain-ncnn-vulkan.exe {args} -f {InterpolateUtils.GetOutExt()} -j {GetNcnnThreads()}".TrimWhitespacesSafe(); Logger.Log("Running DAIN...", false); Logger.Log("cmd.exe " + dain.StartInfo.Arguments, true); if (!OSUtils.ShowHiddenCmd()) @@ -140,7 +140,7 @@ namespace Flowframes string cainExe = "cain-ncnn-vulkan.exe"; Process cain = OSUtils.NewProcess(!OSUtils.ShowHiddenCmd()); AiStarted(cain, 1500, 2); - cain.StartInfo.Arguments = $"{OSUtils.GetCmdArg()} cd /D {cainDir.Wrap()} & {cainExe} {args} -f {InterpolateUtils.GetOutExt()} -j {GetNcnnThreads()}"; + cain.StartInfo.Arguments = $"{OSUtils.GetCmdArg()} cd /D {cainDir.Wrap()} & {cainExe} {args} -f {InterpolateUtils.GetOutExt()} -j {GetNcnnThreads()}".TrimWhitespacesSafe(); Logger.Log("cmd.exe " + cain.StartInfo.Arguments, true); if (!OSUtils.ShowHiddenCmd()) { @@ -172,7 +172,7 @@ namespace Flowframes Process rifePy = OSUtils.NewProcess(!OSUtils.ShowHiddenCmd()); AiStarted(rifePy, 3500, Interpolate.current.interpFactor); rifePy.StartInfo.Arguments = $"{OSUtils.GetCmdArg()} cd /D {PkgUtils.GetPkgFolder(Packages.rifeCuda).Wrap()} & " + - $"set CUDA_VISIBLE_DEVICES={Config.Get("torchGpus")} & {Python.GetPyCmd()} {script} {args}"; + $"set CUDA_VISIBLE_DEVICES={Config.Get("torchGpus")} & {Python.GetPyCmd()} {script} {args}".TrimWhitespacesSafe(); Logger.Log($"Running RIFE {(InterpolateUtils.UseUHD() ? "(UHD Mode)" : "")} ({script})...".TrimWhitespaces(), false); Logger.Log("cmd.exe " + rifePy.StartInfo.Arguments, true); if (!OSUtils.ShowHiddenCmd()) @@ -245,7 +245,7 @@ namespace Flowframes string uhdStr = InterpolateUtils.UseUHD() ? "-u" : ""; rifeNcnn.StartInfo.Arguments = $"{OSUtils.GetCmdArg()} cd /D {PkgUtils.GetPkgFolder(Packages.rifeNcnn).Wrap()} & rife-ncnn-vulkan.exe " + - $" -v -i {inPath.Wrap()} -o {outPath.Wrap()} -m rife1.7 {uhdStr} -g {Config.Get("ncnnGpus")} -f {InterpolateUtils.GetOutExt()} -j {GetNcnnThreads()}"; + $" -v -i {inPath.Wrap()} -o {outPath.Wrap()} -m rife1.7 {uhdStr} -g {Config.Get("ncnnGpus")} -f {InterpolateUtils.GetOutExt()} -j {GetNcnnThreads()}".TrimWhitespacesSafe(); Logger.Log("cmd.exe " + rifeNcnn.StartInfo.Arguments, true); diff --git a/Code/UI/MainUiFunctions.cs b/Code/UI/MainUiFunctions.cs index 84a13c5..d6675e2 100644 --- a/Code/UI/MainUiFunctions.cs +++ b/Code/UI/MainUiFunctions.cs @@ -106,12 +106,12 @@ namespace Flowframes.UI static async Task GetThumbnail (string path) { - string imgOnDisk = Path.Combine(Paths.GetDataPath(), "thumb-temp.png"); + string imgOnDisk = Path.Combine(Paths.GetDataPath(), "thumb-temp.jpg"); try { if (!IOUtils.IsPathDirectory(path)) // If path is video - Extract first frame { - await FFmpegCommands.ExtractSingleFrame(path, imgOnDisk, 1, false, false); + await FFmpegCommands.ExtractSingleFrame(path, imgOnDisk, 1); return IOUtils.GetImage(imgOnDisk); } else // Path is frame folder - Get first frame