mirror of
https://github.com/n00mkrad/flowframes.git
synced 2026-07-12 13:31:56 +02:00
Check GIF max framerate, minor QOL & logging improvements
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"))
|
||||
{
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -106,12 +106,12 @@ namespace Flowframes.UI
|
||||
|
||||
static async Task<Image> 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
|
||||
|
||||
Reference in New Issue
Block a user