mirror of
https://github.com/n00mkrad/flowframes.git
synced 2025-12-16 16:37:48 +01:00
Removed firstframefix, fixed autoenc with multi iteration interp, zero padding fixes
This commit is contained in:
@@ -521,5 +521,37 @@ namespace Flowframes.IO
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void ZeroPadDir(string path, string ext, int targetLength, bool recursive = false)
|
||||
{
|
||||
FileInfo[] files;
|
||||
if (recursive)
|
||||
files = new DirectoryInfo(path).GetFiles($"*.{ext}", SearchOption.AllDirectories);
|
||||
else
|
||||
files = new DirectoryInfo(path).GetFiles($"*.{ext}", SearchOption.TopDirectoryOnly);
|
||||
|
||||
ZeroPadDir(files.Select(x => x.FullName).ToList(), targetLength);
|
||||
}
|
||||
|
||||
public static void ZeroPadDir(List<string> files, int targetLength, List<string> exclude = null)
|
||||
{
|
||||
if(exclude != null)
|
||||
files = files.Except(exclude).ToList();
|
||||
|
||||
foreach (string file in files)
|
||||
{
|
||||
string fname = Path.GetFileNameWithoutExtension(file);
|
||||
string targetFilename = Path.Combine(Path.GetDirectoryName(file), fname.PadLeft(targetLength, '0') + Path.GetExtension(file));
|
||||
try
|
||||
{
|
||||
if (targetFilename != file)
|
||||
File.Move(file, targetFilename);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.Log($"Failed to zero-pad {file} => {targetFilename}: {e.Message}", true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -231,7 +231,7 @@ namespace Flowframes.Magick
|
||||
|
||||
Logger.Log("Re-Duplicating frames to fix timing...");
|
||||
RenameCounterDir(path, ext);
|
||||
ZeroPadDir(path, ext, 8);
|
||||
IOUtils.ZeroPadDir(path, ext, 8);
|
||||
|
||||
string[] dupeFrameLines = IOUtils.ReadLines(dupeInfoFile);
|
||||
string tempSubFolder = Path.Combine(path, "temp");
|
||||
@@ -300,7 +300,7 @@ namespace Flowframes.Magick
|
||||
}
|
||||
}
|
||||
}
|
||||
ZeroPadDir(tempSubFolder, ext, 8);
|
||||
IOUtils.ZeroPadDir(tempSubFolder, ext, 8);
|
||||
|
||||
foreach (FileInfo file in new DirectoryInfo(path).GetFiles($"*.{ext}", SearchOption.TopDirectoryOnly))
|
||||
file.Delete();
|
||||
@@ -325,21 +325,5 @@ namespace Flowframes.Magick
|
||||
counter++;
|
||||
}
|
||||
}
|
||||
|
||||
public static void ZeroPadDir(string path, string ext, int targetLength, bool recursive = false)
|
||||
{
|
||||
FileInfo[] files;
|
||||
if (recursive)
|
||||
files = new DirectoryInfo(path).GetFiles($"*.{ext}", SearchOption.AllDirectories);
|
||||
else
|
||||
files = new DirectoryInfo(path).GetFiles($"*.{ext}", SearchOption.TopDirectoryOnly);
|
||||
|
||||
foreach (FileInfo file in files)
|
||||
{
|
||||
string fnameNoExt = Path.GetFileNameWithoutExtension(file.Name);
|
||||
string ext2 = Path.GetExtension(file.Name); ;
|
||||
File.Move(file.FullName, Path.Combine(Path.GetDirectoryName(file.FullName), fnameNoExt.PadLeft(targetLength, '0') + ext2));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Flowframes.IO;
|
||||
using Flowframes.Data;
|
||||
using Flowframes.IO;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
@@ -19,6 +20,8 @@ namespace Flowframes.Main
|
||||
|
||||
public static bool busy;
|
||||
|
||||
public static bool paused;
|
||||
|
||||
|
||||
public static async Task MainLoop(string interpFramesPath)
|
||||
{
|
||||
@@ -28,20 +31,25 @@ namespace Flowframes.Main
|
||||
encodedFrames.Clear();
|
||||
unencodedFrames.Clear();
|
||||
|
||||
int interpFramesAmount;
|
||||
chunkSize = GetChunkSize(IOUtils.GetAmountOfFiles(Interpolate.currentFramesPath, false, "*.png") * Interpolate.lastInterpFactor);
|
||||
|
||||
int videoIndex = 1;
|
||||
|
||||
while (!Interpolate.canceled && GetInterpFramesAmount() < 2)
|
||||
await Task.Delay(100);
|
||||
await Task.Delay(1000);
|
||||
|
||||
while (HasWorkToDo()) // Loop while proc is running and not all frames have been encoded
|
||||
{
|
||||
if (Interpolate.canceled) return;
|
||||
|
||||
if (paused)
|
||||
{
|
||||
await Task.Delay(100);
|
||||
continue;
|
||||
}
|
||||
|
||||
IOUtils.ZeroPadDir(Directory.GetFiles(interpFramesFolder, $"*.{InterpolateUtils.lastExt}").ToList(), Padding.interpFrames, encodedFrames);
|
||||
string[] interpFrames = Directory.GetFiles(interpFramesFolder, $"*.{InterpolateUtils.lastExt}");
|
||||
interpFramesAmount = interpFrames.Length;
|
||||
unencodedFrames = interpFrames.ToList().Except(encodedFrames).ToList();
|
||||
|
||||
Directory.CreateDirectory(videoChunksFolder);
|
||||
@@ -54,6 +62,7 @@ namespace Flowframes.Main
|
||||
Logger.Log("Encoding Chunk #" + videoIndex, true, false, "ffmpeg.txt");
|
||||
|
||||
List<string> framesToEncode = aiRunning ? unencodedFrames.Take(chunkSize).ToList() : unencodedFrames; // Take all remaining frames if process is done
|
||||
IOUtils.ZeroPadDir(framesToEncode, Padding.interpFrames); // Zero-pad frames before encoding to make sure filenames match with VFR file
|
||||
|
||||
string outpath = Path.Combine(videoChunksFolder, $"{videoIndex.ToString().PadLeft(4, '0')}{InterpolateUtils.GetExt(Interpolate.currentOutMode)}");
|
||||
int firstFrameNum = Path.GetFileNameWithoutExtension(framesToEncode[0]).GetInt();
|
||||
|
||||
@@ -9,9 +9,9 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
using Padding = Flowframes.Data.Padding;
|
||||
using i = Flowframes.Interpolate;
|
||||
|
||||
namespace Flowframes.Main
|
||||
@@ -37,6 +37,9 @@ namespace Flowframes.Main
|
||||
return;
|
||||
}
|
||||
|
||||
//Logger.Log("zero-padding " + path);
|
||||
//IOUtils.ZeroPadDir(path, $"*.{InterpolateUtils.lastExt}", Padding.interpFrames);
|
||||
|
||||
if (IOUtils.GetAmountOfFiles(path, false, $"*.{InterpolateUtils.lastExt}") <= 1)
|
||||
{
|
||||
i.Cancel("Output folder does not contain frames - An error must have occured during interpolation!", AiProcess.hasShownError);
|
||||
|
||||
@@ -143,13 +143,11 @@ namespace Flowframes
|
||||
|
||||
public static async Task PostProcessFrames (bool sbsMode = false)
|
||||
{
|
||||
bool firstFrameFix = (!sbsMode && lastAi.aiName == Networks.rifeCuda.aiName) || (sbsMode && InterpolateSteps.currentAi.aiName == Networks.rifeCuda.aiName);
|
||||
firstFrameFix = false; // TODO: Remove firstframefix if new rife code works
|
||||
//bool firstFrameFix = (!sbsMode && lastAi.aiName == Networks.rifeCuda.aiName) || (sbsMode && InterpolateSteps.currentAi.aiName == Networks.rifeCuda.aiName);
|
||||
//firstFrameFix = false; // TODO: Remove firstframefix if new rife code works
|
||||
|
||||
if (!Directory.Exists(currentFramesPath) || IOUtils.GetAmountOfFiles(currentFramesPath, false, "*.png") <= 0)
|
||||
{
|
||||
Cancel("Input frames folder is empty!");
|
||||
}
|
||||
|
||||
if (Config.GetInt("dedupMode") == 1)
|
||||
await MagickDedupe.Run(currentFramesPath);
|
||||
@@ -161,24 +159,13 @@ namespace Flowframes
|
||||
bool useTimestamps = Config.GetInt("timingMode") == 1; // TODO: Auto-Disable timestamps if input frames are sequential, not timestamped
|
||||
|
||||
if(sbsMode)
|
||||
await VfrDedupe.CreateTimecodeFiles(currentFramesPath, Config.GetBool("enableLoop"), firstFrameFix, -1, !useTimestamps);
|
||||
await VfrDedupe.CreateTimecodeFiles(currentFramesPath, Config.GetBool("enableLoop"), -1, !useTimestamps);
|
||||
else
|
||||
await VfrDedupe.CreateTimecodeFiles(currentFramesPath, Config.GetBool("enableLoop"), firstFrameFix, lastInterpFactor, !useTimestamps);
|
||||
await VfrDedupe.CreateTimecodeFiles(currentFramesPath, Config.GetBool("enableLoop"), lastInterpFactor, !useTimestamps);
|
||||
|
||||
if (canceled) return;
|
||||
|
||||
AiProcess.filenameMap = IOUtils.RenameCounterDirReversible(currentFramesPath, "png", 1, 8);
|
||||
|
||||
//string hasPreprocessedFile = Path.Combine(currentTempDir, ".preprocessed");
|
||||
//if (File.Exists(hasPreprocessedFile)) return;
|
||||
|
||||
if (firstFrameFix)
|
||||
{
|
||||
bool s = IOUtils.TryCopy(new DirectoryInfo(currentFramesPath).GetFiles("*.png")[0].FullName, Path.Combine(currentFramesPath, "00000000.png"), true);
|
||||
Logger.Log("FirstFrameFix TryCopy Success: " + s, true);
|
||||
}
|
||||
|
||||
//File.Create(hasPreprocessedFile);
|
||||
}
|
||||
|
||||
public static async Task RunAi(string outpath, int targetFrames, int tilesize, AI ai)
|
||||
|
||||
@@ -103,12 +103,12 @@ namespace Flowframes.Main
|
||||
basePath = custPath;
|
||||
}
|
||||
|
||||
return Path.Combine(basePath, Path.GetFileNameWithoutExtension(inPath).StripBadChars().Trunc(30, false) + "-temp");
|
||||
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)
|
||||
{
|
||||
bool passes = true;
|
||||
bool passes = true;
|
||||
|
||||
bool isFile = !IOUtils.IsPathDirectory(inDir);
|
||||
|
||||
|
||||
@@ -14,18 +14,18 @@ namespace Flowframes.Main
|
||||
{
|
||||
class VfrDedupe
|
||||
{
|
||||
public static async Task CreateTimecodeFiles(string framesPath, bool loopEnabled, bool firstFrameFix, int times, bool noTimestamps)
|
||||
public static async Task CreateTimecodeFiles(string framesPath, bool loopEnabled, int times, bool noTimestamps)
|
||||
{
|
||||
Logger.Log("Generating timecodes...");
|
||||
if(times <= 0)
|
||||
{
|
||||
await CreateTimecodeFile(framesPath, loopEnabled, 2, firstFrameFix, false, noTimestamps);
|
||||
await CreateTimecodeFile(framesPath, loopEnabled, 4, firstFrameFix, true, noTimestamps);
|
||||
await CreateTimecodeFile(framesPath, loopEnabled, 8, firstFrameFix, true, noTimestamps);
|
||||
await CreateTimecodeFile(framesPath, loopEnabled, 2, false, noTimestamps);
|
||||
await CreateTimecodeFile(framesPath, loopEnabled, 4, true, noTimestamps);
|
||||
await CreateTimecodeFile(framesPath, loopEnabled, 8, true, noTimestamps);
|
||||
}
|
||||
else
|
||||
{
|
||||
await CreateTimecodeFile(framesPath, loopEnabled, times, firstFrameFix, false, noTimestamps);
|
||||
await CreateTimecodeFile(framesPath, loopEnabled, times, false, noTimestamps);
|
||||
}
|
||||
frameFiles = null;
|
||||
Logger.Log($"Generating timecodes... Done.", false, true);
|
||||
@@ -33,7 +33,7 @@ namespace Flowframes.Main
|
||||
|
||||
static FileInfo[] frameFiles;
|
||||
|
||||
public static async Task CreateTimecodeFile(string framesPath, bool loopEnabled, int interpFactor, bool firstFrameFix, bool notFirstRun, bool noTimestamps)
|
||||
public static async Task CreateTimecodeFile(string framesPath, bool loopEnabled, int interpFactor, bool notFirstRun, bool noTimestamps)
|
||||
{
|
||||
if (Interpolate.canceled) return;
|
||||
Logger.Log($"Generating timecodes for {interpFactor}x...", false, true);
|
||||
@@ -88,7 +88,7 @@ namespace Flowframes.Main
|
||||
{
|
||||
string durationStr = ((durationPerInterpFrame / 1000f) * 1).ToString("0.00000", CultureInfo.InvariantCulture);
|
||||
|
||||
if (discardThisFrame)
|
||||
if (discardThisFrame && totalFileCount > 1) // Never discard 1st frame
|
||||
{
|
||||
int lastNum = totalFileCount - 1;
|
||||
for (int dupeCount = 1; dupeCount < interpFramesAmount; dupeCount++)
|
||||
@@ -111,14 +111,6 @@ namespace Flowframes.Main
|
||||
|
||||
if (notFirstRun) return; // Skip all steps that only need to be done once
|
||||
|
||||
if (firstFrameFix)
|
||||
{
|
||||
string[] lines = IOUtils.ReadLines(vfrFile);
|
||||
File.WriteAllText(vfrFile, lines[0].Replace($"{"1".PadLeft(Padding.interpFrames, '0')}.png", $"{"0".PadLeft(Padding.interpFrames, '0')}.png"));
|
||||
File.AppendAllText(vfrFile, "\n" + lines[1] + "\n");
|
||||
File.AppendAllLines(vfrFile, lines);
|
||||
}
|
||||
|
||||
if (Config.GetBool("enableLoop"))
|
||||
{
|
||||
int lastFileNumber = frameFiles.Last().Name.GetInt();
|
||||
|
||||
@@ -10,6 +10,7 @@ using System.Threading.Tasks;
|
||||
using Flowframes.OS;
|
||||
using Flowframes.UI;
|
||||
using Flowframes.Main;
|
||||
using Flowframes.Data;
|
||||
|
||||
namespace Flowframes
|
||||
{
|
||||
@@ -70,7 +71,10 @@ namespace Flowframes
|
||||
await Task.Delay(1);
|
||||
|
||||
if (Interpolate.canceled) return;
|
||||
Magick.MagickDedupe.ZeroPadDir(outPath, InterpolateUtils.lastExt, 8);
|
||||
|
||||
if (!Interpolate.currentlyUsingAutoEnc)
|
||||
IOUtils.ZeroPadDir(outPath, InterpolateUtils.lastExt, Padding.interpFrames);
|
||||
|
||||
AiFinished("DAIN");
|
||||
}
|
||||
|
||||
@@ -109,7 +113,9 @@ namespace Flowframes
|
||||
}
|
||||
|
||||
if (Interpolate.canceled) return;
|
||||
Magick.MagickDedupe.ZeroPadDir(outPath, InterpolateUtils.lastExt, 8);
|
||||
|
||||
if (!Interpolate.currentlyUsingAutoEnc)
|
||||
IOUtils.ZeroPadDir(outPath, InterpolateUtils.lastExt, Padding.interpFrames);
|
||||
|
||||
AiFinished("CAIN");
|
||||
}
|
||||
@@ -178,7 +184,11 @@ namespace Flowframes
|
||||
processTimeMulti.Restart();
|
||||
Logger.Log("Running RIFE...", false);
|
||||
|
||||
string args = $" -v -i {framesPath.Wrap()} -o {outPath.Wrap()} -t {tilesize} -g {Config.Get("ncnnGpus")} -f {InterpolateUtils.lastExt} -j 4:{Config.Get("ncnnThreads")}:4";
|
||||
bool useAutoEnc = Interpolate.currentlyUsingAutoEnc;
|
||||
if(times > 2)
|
||||
AutoEncode.paused = true; // Disable autoenc until the last iteration
|
||||
|
||||
string args = $" -v -i {framesPath.Wrap()} -o {outPath.Wrap()}";
|
||||
await RunRifePartial(args);
|
||||
|
||||
if (times == 4 || times == 8) // #2
|
||||
@@ -189,7 +199,9 @@ namespace Flowframes
|
||||
IOUtils.TryDeleteIfExists(run1ResultsPath);
|
||||
Directory.Move(outPath, run1ResultsPath);
|
||||
Directory.CreateDirectory(outPath);
|
||||
args = $" -v -i {run1ResultsPath.Wrap()} -o {outPath.Wrap()} -t {tilesize} -g {Config.Get("ncnnGpus")} -f {InterpolateUtils.lastExt} -j 4:{Config.Get("ncnnThreads")}:4";
|
||||
if (useAutoEnc && times == 4)
|
||||
AutoEncode.paused = false;
|
||||
args = $" -v -i {run1ResultsPath.Wrap()} -o {outPath.Wrap()}";
|
||||
await RunRifePartial(args);
|
||||
IOUtils.TryDeleteIfExists(run1ResultsPath);
|
||||
}
|
||||
@@ -202,13 +214,20 @@ namespace Flowframes
|
||||
IOUtils.TryDeleteIfExists(run2ResultsPath);
|
||||
Directory.Move(outPath, run2ResultsPath);
|
||||
Directory.CreateDirectory(outPath);
|
||||
args = $" -v -i {run2ResultsPath.Wrap()} -o {outPath.Wrap()} -t {tilesize} -g {Config.Get("ncnnGpus")} -f {InterpolateUtils.lastExt} -j 4:{Config.Get("ncnnThreads")}:4";
|
||||
if (useAutoEnc && times == 8)
|
||||
AutoEncode.paused = false;
|
||||
args = $" -v -i {run2ResultsPath.Wrap()} -o {outPath.Wrap()}";
|
||||
await RunRifePartial(args);
|
||||
IOUtils.TryDeleteIfExists(run2ResultsPath);
|
||||
}
|
||||
|
||||
if (Interpolate.canceled) return;
|
||||
Magick.MagickDedupe.ZeroPadDir(outPath, InterpolateUtils.lastExt, 8);
|
||||
|
||||
if (!Interpolate.currentlyUsingAutoEnc)
|
||||
{
|
||||
Logger.Log($"zero padding {outPath} with ext \"{InterpolateUtils.lastExt}\" to length {Padding.interpFrames}");
|
||||
IOUtils.ZeroPadDir(outPath, InterpolateUtils.lastExt, Padding.interpFrames);
|
||||
}
|
||||
|
||||
AiFinished("RIFE");
|
||||
}
|
||||
@@ -217,7 +236,7 @@ namespace Flowframes
|
||||
{
|
||||
Process rifeNcnn = OSUtils.NewProcess(!OSUtils.ShowHiddenCmd());
|
||||
AiStarted(rifeNcnn, 1500);
|
||||
rifeNcnn.StartInfo.Arguments = $"{OSUtils.GetCmdArg()} cd /D {PkgUtils.GetPkgFolder(Packages.rifeNcnn).Wrap()} & rife-ncnn-vulkan.exe {args} -f {InterpolateUtils.lastExt} -j 4:{Config.Get("ncnnThreads")}:4";
|
||||
rifeNcnn.StartInfo.Arguments = $"{OSUtils.GetCmdArg()} cd /D {PkgUtils.GetPkgFolder(Packages.rifeNcnn).Wrap()} & rife-ncnn-vulkan.exe {args} -g {Config.Get("ncnnGpus")} -f {InterpolateUtils.lastExt} -j 4:{Config.Get("ncnnThreads")}:4";
|
||||
Logger.Log("cmd.exe " + rifeNcnn.StartInfo.Arguments, true);
|
||||
if (!OSUtils.ShowHiddenCmd())
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user