Cleaner code for Interpolate.cs

This commit is contained in:
N00MKRAD
2020-12-17 11:32:45 +01:00
parent d45034f531
commit 4df2949681
17 changed files with 176 additions and 196 deletions

View File

@@ -103,7 +103,7 @@ namespace Flowframes
string enc = useH265 ? "libx265" : "libx264";
string presetStr = $"-preset {Config.Get("ffEncPreset")}";
string vfrFilename = Path.GetFileName(framesFile);
string vsync = (Interpolate.lastInterpFactor == 2) ? "-vsync 1" : "-vsync 2";
string vsync = (Interpolate.current.interpFactor == 2) ? "-vsync 1" : "-vsync 2";
string args = $"{vsync} -f concat -i {vfrFilename} -r {fps.ToString().Replace(",", ".")} -c:v {enc} -crf {crf} {presetStr} {videoEncArgs} -threads {Config.GetInt("ffEncThreads")} -c:a copy {outPath.Wrap()}";
await AvProcess.RunFfmpeg(args, framesFile.GetParentDir(), logMode);
}

View File

@@ -1,29 +0,0 @@
using Flowframes.Data;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Flowframes
{
public struct BatchEntry
{
public string inPath;
public string outPath;
public AI ai;
public float inFps;
public int interpFactor;
public Interpolate.OutMode outMode;
public BatchEntry(string inPathArg, string outPathArg, AI aiArg, float inFpsArg, int interpFactorArg, Interpolate.OutMode outModeArg)
{
inPath = inPathArg;
outPath = outPathArg;
ai = aiArg;
inFps = inFpsArg;
interpFactor = interpFactorArg;
outMode = outModeArg;
}
}
}

View File

@@ -0,0 +1,52 @@
using Flowframes.Data;
using Flowframes.IO;
using Flowframes.Main;
using System;
using System.Collections.Generic;
using System.IO;
namespace Flowframes
{
public struct InterpSettings
{
public string inPath;
public string outPath;
public AI ai;
public float inFps;
public float outFps;
public int interpFactor;
public Interpolate.OutMode outMode;
public int tilesize;
public string tempFolder;
public string framesFolder;
public string interpFolder;
public bool inputIsFrames;
public string outFilename;
public InterpSettings(string inPathArg, string outPathArg, AI aiArg, float inFpsArg, int interpFactorArg, Interpolate.OutMode outModeArg, int tilesizeArg = 512)
{
inPath = inPathArg;
outPath = outPathArg;
ai = aiArg;
inFps = inFpsArg;
interpFactor = interpFactorArg;
outFps = inFpsArg * interpFactorArg;
outMode = outModeArg;
tilesize = tilesizeArg;
tempFolder = InterpolateUtils.GetTempFolderLoc(inPath, outPath);
framesFolder = Path.Combine(tempFolder, Paths.framesDir);
interpFolder = Path.Combine(tempFolder, Paths.interpDir);
inputIsFrames = IOUtils.IsPathDirectory(inPath);
outFilename = Path.Combine(outPath, Path.GetFileNameWithoutExtension(inPath) + IOUtils.GetAiSuffix(ai, interpFactor) + InterpolateUtils.GetExt(outMode));
}
public void SetFps(float inFpsArg)
{
inFps = inFpsArg;
outFps = inFps * interpFactor;
}
}
}

View File

@@ -190,7 +190,7 @@
<ItemGroup>
<Compile Include="AudioVideo\GifskiCommands.cs" />
<Compile Include="Data\AI.cs" />
<Compile Include="Data\BatchEntry.cs" />
<Compile Include="Data\InterpSettings.cs" />
<Compile Include="Data\Networks.cs" />
<Compile Include="Data\Padding.cs" />
<Compile Include="Data\SemVer.cs" />

View File

@@ -86,13 +86,13 @@ namespace Flowframes
mainTabControl.Update();
}
public BatchEntry GetBatchEntry()
public InterpSettings GetCurrentSettings()
{
SetTab("interpolate");
return new BatchEntry(inputTbox.Text.Trim(), outputTbox.Text.Trim(), GetAi(), fpsInTbox.GetFloat(), interpFactorCombox.GetInt(), GetOutMode());
return new InterpSettings(inputTbox.Text.Trim(), outputTbox.Text.Trim(), GetAi(), fpsInTbox.GetFloat(), interpFactorCombox.GetInt(), GetOutMode(), GetTilesize());
}
public void LoadBatchEntry(BatchEntry entry)
public void LoadBatchEntry(InterpSettings entry)
{
inputTbox.Text = entry.inPath;
outputTbox.Text = entry.outPath;
@@ -157,13 +157,9 @@ namespace Flowframes
{
if (!BatchProcessing.busy) // Don't load values from gui if batch processing is used
{
SetTab("interpolation");
Interpolate.SetFps(fpsInTbox.GetFloat());
Interpolate.interpFactor = interpFactorCombox.GetInt();
Interpolate.current = GetCurrentSettings();
}
string inPath = inputTbox.Text.Trim();
string outPath = outputTbox.Text.Trim();
Interpolate.Start(inPath, outPath, GetTilesize(), GetOutMode(), GetAi());
Interpolate.Start();
}
public int GetTilesize()
@@ -213,7 +209,7 @@ namespace Flowframes
private void fpsInTbox_TextChanged(object sender, EventArgs e)
{
fpsInTbox.Text = fpsInTbox.Text.TrimNumbers(true);
Interpolate.SetFps(fpsInTbox.GetFloat());
//Interpolate.SetFps(fpsInTbox.GetFloat());
UpdateOutputFPS();
}
@@ -221,14 +217,15 @@ namespace Flowframes
{
float fpsOut = fpsInTbox.GetFloat() * interpFactorCombox.GetFloat();
fpsOutTbox.Text = fpsOut.ToString();
Interpolate.interpFactor = interpFactorCombox.GetInt();
//Interpolate.interpFactor = interpFactorCombox.GetInt();
}
private void interpFactorCombox_SelectedIndexChanged(object sender, EventArgs e)
{
UpdateOutputFPS();
if (Interpolate.interpFactor > 2 && !GetAi().supportsAnyExp && Config.GetInt("autoEncMode") > 0)
Logger.Log($"Warning: {GetAi().aiName.Replace("_", "-")} doesn't natively support 4x/8x and will run multiple times for {Interpolate.interpFactor}x. Auto-Encode will only work on the last run.");
int guiInterpFactor = interpFactorCombox.GetInt();
if (guiInterpFactor > 2 && !GetAi().supportsAnyExp && Config.GetInt("autoEncMode") > 0)
Logger.Log($"Warning: {GetAi().aiName.Replace("_", "-")} doesn't natively support 4x/8x and will run multiple times for {guiInterpFactor}x. Auto-Encode will only work on the last run.");
}
public void SetWorking(bool state)
@@ -404,7 +401,7 @@ namespace Flowframes
private async void runStepBtn_Click(object sender, EventArgs e)
{
SetTab("interpolate");
Interpolate.SetFps(fpsInTbox.GetFloat());
//Interpolate.SetFps(fpsInTbox.GetFloat());
await InterpolateSteps.Run(stepSelector.Text);
}

View File

@@ -20,7 +20,7 @@ namespace Flowframes.Forms
private void addToQueue_Click(object sender, EventArgs e)
{
Program.batchQueue.Enqueue(Program.mainForm.GetBatchEntry());
Program.batchQueue.Enqueue(Program.mainForm.GetCurrentSettings());
RefreshGui();
}
@@ -30,7 +30,7 @@ namespace Flowframes.Forms
string nl = Environment.NewLine;
for (int i = 0; i < Program.batchQueue.Count; i++)
{
BatchEntry entry = Program.batchQueue.ElementAt(i);
InterpSettings entry = Program.batchQueue.ElementAt(i);
string niceOutMode = entry.outMode.ToString().ToUpper().Replace("VID", "").Replace("IMG", "");
string str = $"#{i}: {Path.GetFileName(entry.inPath).Trunc(45)} - {entry.inFps} FPS => {entry.interpFactor}x{nl} {entry.ai.aiNameShort} => {niceOutMode}";
taskList.Items.Add(str);
@@ -88,7 +88,7 @@ namespace Flowframes.Forms
{
if (taskList.SelectedItem == null) return;
Queue<BatchEntry> temp = new Queue<BatchEntry>();
Queue<InterpSettings> temp = new Queue<InterpSettings>();
for(int i = 0; i < Program.batchQueue.Count; i++)
{
@@ -125,7 +125,7 @@ namespace Flowframes.Forms
continue;
}
BatchEntry dragDropEntry = Program.mainForm.GetBatchEntry();
InterpSettings dragDropEntry = Program.mainForm.GetCurrentSettings();
dragDropEntry.inPath = path;
dragDropEntry.outPath = path.GetParentDir();
dragDropEntry.inFps = GetFramerate(path);
@@ -137,7 +137,7 @@ namespace Flowframes.Forms
float GetFramerate (string path)
{
float fps = Interpolate.currentInFps;
float fps = Interpolate.current.inFps;
float fpsFromFile = IOUtils.GetFpsFolderOrVideo(path);
if (fpsFromFile > 0)
return fpsFromFile;

View File

@@ -322,7 +322,7 @@ namespace Flowframes.IO
fps = float.Parse(ReadLines(fpsFile)[0]);
Logger.Log($"Got {fps} FPS from file: " + fpsFile);
float guiFps = Program.mainForm.GetBatchEntry().inFps;
float guiFps = Program.mainForm.GetCurrentSettings().inFps;
DialogResult dialogResult = MessageBox.Show("A frame rate file has been found in the parent directory.\n\n" +
$"Click \"Yes\" to use frame rate from the file ({fps}) or \"No\" to use current FPS set in GUI ({guiFps})", "Load Frame Rate From fps.ini?", MessageBoxButtons.YesNo);

View File

@@ -216,7 +216,7 @@ namespace Flowframes.Magick
string ext = InterpolateUtils.GetExt();
string dupeInfoFile = Path.Combine(Interpolate.currentTempDir, "dupes.ini");
string dupeInfoFile = Path.Combine(Interpolate.current.tempFolder, "dupes.ini");
if (!File.Exists(dupeInfoFile)) return;
Logger.Log("Re-Duplicating frames to fix timing...");
@@ -227,7 +227,7 @@ namespace Flowframes.Magick
string tempSubFolder = Path.Combine(path, "temp");
Directory.CreateDirectory(tempSubFolder);
int interpFramesPerRealFrame = Interpolate.interpFactor - 1;
int interpFramesPerRealFrame = Interpolate.current.interpFactor - 1;
int sourceFrameNum = 0;
int outFrameNum = 1;

View File

@@ -31,8 +31,8 @@ namespace Flowframes.Main
encodedFrames.Clear();
unencodedFrames.Clear();
chunkSize = GetChunkSize(IOUtils.GetAmountOfFiles(Interpolate.currentFramesPath, false, "*.png") * Interpolate.lastInterpFactor);
safetyBufferFrames = Interpolate.lastAi.aiName.ToUpper().Contains("NCNN") ? 60 : 30; // Use bigger safety buffer for NCNN
chunkSize = GetChunkSize(IOUtils.GetAmountOfFiles(Interpolate.current.framesFolder, false, "*.png") * Interpolate.current.interpFactor);
safetyBufferFrames = Interpolate.current.ai.aiName.ToUpper().Contains("NCNN") ? 60 : 30; // Use bigger safety buffer for NCNN
Logger.Log($"Starting AutoEncode MainLoop - Chunk Size: {chunkSize} Frames - Safety Buffer: {safetyBufferFrames} Frames", true);
int videoIndex = 1;
@@ -67,7 +67,7 @@ namespace Flowframes.Main
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)}");
string outpath = Path.Combine(videoChunksFolder, $"{videoIndex.ToString().PadLeft(4, '0')}{InterpolateUtils.GetExt(Interpolate.current.outMode)}");
int firstFrameNum = Path.GetFileNameWithoutExtension(framesToEncode[0]).GetInt();
await CreateVideo.EncodeChunk(outpath, firstFrameNum - 1, framesToEncode.Count);
@@ -98,7 +98,7 @@ namespace Flowframes.Main
IOUtils.ReverseRenaming(AiProcess.filenameMap, true); // Get timestamps back
await CreateVideo.ChunksToVideo(videoChunksFolder, concatFile, Interpolate.nextOutPath);
await CreateVideo.ChunksToVideo(videoChunksFolder, concatFile, Interpolate.current.outFilename);
}
public static bool HasWorkToDo ()

View File

@@ -43,7 +43,7 @@ namespace Flowframes.Main
stopped = true;
}
static async Task RunEntry(BatchEntry entry)
static async Task RunEntry(InterpSettings entry)
{
if (!EntryIsValid(entry))
{
@@ -58,8 +58,9 @@ namespace Flowframes.Main
SetBusy(true);
Program.mainForm.LoadBatchEntry(entry); // Load entry into GUI
Interpolate.interpFactor = entry.interpFactor;
Interpolate.SetFps(entry.inFps);
Interpolate.current = entry;
// Interpolate.interpFactor = entry.interpFactor;
// Interpolate.SetFps(entry.inFps);
Program.mainForm.runBtn_Click(null, null);
await Task.Delay(2000);
@@ -81,7 +82,7 @@ namespace Flowframes.Main
Program.mainForm.GetMainTabControl().Enabled = !state; // Lock GUI
}
static bool EntryIsValid(BatchEntry entry)
static bool EntryIsValid(InterpSettings entry)
{
if (entry.inPath == null || (IOUtils.IsPathDirectory(entry.inPath) && !Directory.Exists(entry.inPath)) || (!IOUtils.IsPathDirectory(entry.inPath) && !File.Exists(entry.inPath)))

View File

@@ -27,7 +27,7 @@ namespace Flowframes.Main
try
{
Logger.Log("Moving interpolated frames out of temp folder...");
string copyPath = Path.Combine(i.currentTempDir.ReplaceLast("-temp", "-interpolated"));
string copyPath = Path.Combine(i.current.tempFolder.ReplaceLast("-temp", "-interpolated"));
Logger.Log($"{path} -> {copyPath}");
IOUtils.CreateDir(copyPath);
IOUtils.Copy(path, copyPath, true);
@@ -51,10 +51,10 @@ namespace Flowframes.Main
int maxFps = Config.GetInt("maxFps");
if (maxFps == 0) maxFps = 500;
if (mode == i.OutMode.VidMp4 && i.currentOutFps > maxFps)
await Encode(mode, path, outPath, i.currentOutFps, maxFps, (Config.GetInt("maxFpsMode") == 1));
if (mode == i.OutMode.VidMp4 && i.current.outFps > maxFps)
await Encode(mode, path, outPath, i.current.outFps, maxFps, (Config.GetInt("maxFpsMode") == 1));
else
await Encode(mode, path, outPath, i.currentOutFps);
await Encode(mode, path, outPath, i.current.outFps);
}
catch (Exception e)
{
@@ -66,7 +66,7 @@ namespace Flowframes.Main
static async Task Encode(i.OutMode mode, string framesPath, string outPath, float fps, float changeFps = -1, bool keepOriginalFpsVid = true)
{
currentOutFile = outPath;
string vfrFile = Path.Combine(framesPath.GetParentDir(), $"vfr-{i.lastInterpFactor}x.ini");
string vfrFile = Path.Combine(framesPath.GetParentDir(), $"vfr-{i.current.interpFactor}x.ini");
if (mode == i.OutMode.VidGif)
await FFmpegCommands.FramesToGifVfr(vfrFile, outPath, true, Config.GetInt("gifColors"));
@@ -78,14 +78,14 @@ namespace Flowframes.Main
int crf = h265 ? Config.GetInt("h265Crf") : Config.GetInt("h264Crf");
await FFmpegCommands.FramesToMp4Vfr(vfrFile, outPath, h265, crf, fps);
await MergeAudio(i.lastInputPath, outPath);
await MergeAudio(i.current.inPath, outPath);
if (changeFps > 0)
{
currentOutFile = IOUtils.FilenameSuffix(outPath, $"-{changeFps.ToString("0")}fps");
Program.mainForm.SetStatus("Creating video with desired frame rate...");
await FFmpegCommands.ConvertFramerate(outPath, currentOutFile, h265, crf, changeFps, !keepOriginalFpsVid);
await MergeAudio(i.lastInputPath, currentOutFile);
await MergeAudio(i.current.inPath, currentOutFile);
}
if (looptimes > 0)
@@ -108,10 +108,10 @@ namespace Flowframes.Main
int maxFps = Config.GetInt("maxFps");
if (maxFps == 0) maxFps = 500;
if (i.currentOutFps > maxFps)
await MergeChunks(chunksPath, vfrFile, outPath, i.currentOutFps, maxFps, (Config.GetInt("maxFpsMode") == 1));
if (i.current.outFps > maxFps)
await MergeChunks(chunksPath, vfrFile, outPath, i.current.outFps, maxFps, (Config.GetInt("maxFpsMode") == 1));
else
await MergeChunks(chunksPath, vfrFile, outPath, i.currentOutFps);
await MergeChunks(chunksPath, vfrFile, outPath, i.current.outFps);
}
catch (Exception e)
{
@@ -128,7 +128,7 @@ namespace Flowframes.Main
int crf = h265 ? Config.GetInt("h265Crf") : Config.GetInt("h264Crf");
await FFmpegCommands.ConcatVideos(vfrFile, outPath, fps, -1);
await MergeAudio(i.lastInputPath, outPath);
await MergeAudio(i.current.inPath, outPath);
if (looptimes > 0)
await Loop(outPath, looptimes);
@@ -138,7 +138,7 @@ namespace Flowframes.Main
string newOutPath = IOUtils.FilenameSuffix(outPath, $"-{changeFps.ToString("0")}fps");
Program.mainForm.SetStatus("Creating video with desired frame rate...");
await FFmpegCommands.ConvertFramerate(outPath, newOutPath, h265, crf, changeFps, !keepOriginalFpsVid);
await MergeAudio(i.lastInputPath, newOutPath);
await MergeAudio(i.current.inPath, newOutPath);
if (looptimes > 0)
await Loop(newOutPath, looptimes);
}
@@ -149,11 +149,11 @@ namespace Flowframes.Main
bool h265 = Config.GetInt("mp4Enc") == 1;
int crf = h265 ? Config.GetInt("h265Crf") : Config.GetInt("h264Crf");
string vfrFileOriginal = Path.Combine(i.currentTempDir, $"vfr-{i.lastInterpFactor}x.ini");
string vfrFile = Path.Combine(i.currentTempDir, $"vfr-chunk-{firstFrameNum}-{firstFrameNum + framesAmount}.ini");
string vfrFileOriginal = Path.Combine(i.current.tempFolder, $"vfr-{i.current.interpFactor}x.ini");
string vfrFile = Path.Combine(i.current.tempFolder, $"vfr-chunk-{firstFrameNum}-{firstFrameNum + framesAmount}.ini");
File.WriteAllLines(vfrFile, IOUtils.ReadLines(vfrFileOriginal).Skip(firstFrameNum * 2).Take(framesAmount * 2));
await FFmpegCommands.FramesToMp4Vfr(vfrFile, outPath, h265, crf, i.currentOutFps, AvProcess.LogMode.Hidden);
await FFmpegCommands.FramesToMp4Vfr(vfrFile, outPath, h265, crf, i.current.outFps, AvProcess.LogMode.Hidden);
}
static async Task Loop(string outPath, int looptimes)
@@ -168,12 +168,12 @@ namespace Flowframes.Main
int times = -1;
int minLength = Config.GetInt("minOutVidLength");
//Logger.Log("minLength: " + minLength);
int minFrameCount = (minLength * i.currentOutFps).RoundToInt();
int minFrameCount = (minLength * i.current.outFps).RoundToInt();
//Logger.Log("minFrameCount: " + minFrameCount);
//int outFrames = new DirectoryInfo(framesOutPath).GetFiles($"*.{InterpolateUtils.GetExt()}", SearchOption.TopDirectoryOnly).Length;
int outFrames = i.currentInputFrameCount * i.lastInterpFactor;
int outFrames = i.currentInputFrameCount * i.current.interpFactor;
//Logger.Log("outFrames: " + outFrames);
if (outFrames / i.currentOutFps < minLength)
if (outFrames / i.current.outFps < minLength)
times = (int)Math.Ceiling((double)minFrameCount / (double)outFrames);
//Logger.Log("times: " + times);
times--; // Account for this calculation not counting the 1st play (0 loops)
@@ -186,10 +186,10 @@ namespace Flowframes.Main
if (!Config.GetBool("enableAudio")) return;
try
{
string audioFileBasePath = Path.Combine(i.currentTempDir, "audio");
string audioFileBasePath = Path.Combine(i.current.tempFolder, "audio");
if (inputPath != null && IOUtils.IsPathDirectory(inputPath) && !File.Exists(IOUtils.GetAudioFile(audioFileBasePath))) // Try loading out of same folder as input if input is a folder
audioFileBasePath = Path.Combine(i.currentTempDir.GetParentDir(), "audio");
audioFileBasePath = Path.Combine(i.current.tempFolder.GetParentDir(), "audio");
if (!File.Exists(IOUtils.GetAudioFile(audioFileBasePath)))
await FFmpegCommands.ExtractAudio(inputPath, audioFileBasePath); // Extract from sourceVideo to audioFile unless it already exists

View File

@@ -23,20 +23,10 @@ namespace Flowframes
{
public enum OutMode { VidMp4, VidGif, ImgPng }
public static string currentTempDir;
public static string currentFramesPath;
public static int interpFactor;
public static float currentInFps;
public static float currentOutFps;
public static int currentInputFrameCount;
public static bool constantFrameRate;
public static OutMode currentOutMode;
public static bool currentInputIsFrames;
public static bool currentlyUsingAutoEnc;
public static int lastInterpFactor;
public static string lastInputPath;
public static string nextOutPath;
public static AI lastAi;
public static InterpSettings current;
public static bool canceled = false;
@@ -45,50 +35,42 @@ namespace Flowframes
public static void SetFps(float inFps)
{
currentInFps = inFps;
currentOutFps = inFps * interpFactor;
// TODO: Can't I remove this?
current.SetFps(inFps);
}
public static async void Start(string inPath, string outDir, int tilesize, OutMode outMode, AI ai)
public static async void Start()
{
canceled = false;
if (!Utils.InputIsValid(inPath, outDir, currentOutFps, interpFactor, tilesize)) return; // General input checks
if (!Utils.CheckAiAvailable(ai)) return; // Check if selected AI pkg is installed
lastInterpFactor = interpFactor;
lastInputPath = inPath;
currentTempDir = Utils.GetTempFolderLoc(inPath, outDir);
currentFramesPath = Path.Combine(currentTempDir, Paths.framesDir);
currentOutMode = outMode;
if (!Utils.InputIsValid(current.inPath, current.outPath, current.outFps, current.interpFactor, current.tilesize)) 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(inPath)) return; // Check if input path/file is valid
Utils.PathAsciiCheck(inPath, outDir);
lastAi = ai;
currentInputIsFrames = IOUtils.IsPathDirectory(inPath);
currentInputFrameCount = Utils.GetInputFrameCount(inPath);
if(!Utils.CheckPathValid(current.inPath)) return; // Check if input path/file is valid
Utils.PathAsciiCheck(current.inPath, current.outPath);
currentInputFrameCount = Utils.GetInputFrameCount(current.inPath);
Program.mainForm.SetStatus("Starting...");
Program.mainForm.SetWorking(true);
await Task.Delay(10);
if (!currentInputIsFrames) // Input is video - extract frames first
await ExtractFrames(inPath, currentFramesPath);
if (!current.inputIsFrames) // Input is video - extract frames first
await ExtractFrames(current.inPath, current.framesFolder);
else
await FFmpegCommands.ImportImages(inPath, currentFramesPath);
await FFmpegCommands.ImportImages(current.inPath, current.framesFolder);
if (canceled) return;
sw.Restart();
await Task.Delay(10);
await PostProcessFrames();
if (canceled) return;
string interpFramesDir = Path.Combine(currentTempDir, Paths.interpDir);
nextOutPath = Path.Combine(outDir, Path.GetFileNameWithoutExtension(inPath) + IOUtils.GetAiSuffix(ai, interpFactor) + Utils.GetExt(outMode));
int frames = IOUtils.GetAmountOfFiles(currentFramesPath, false, "*.png");
int targetFrameCount = frames * interpFactor;
string interpFramesDir = Path.Combine(current.tempFolder, Paths.interpDir);
int frames = IOUtils.GetAmountOfFiles(current.framesFolder, false, "*.png");
int targetFrameCount = frames * current.interpFactor;
GetProgressByFrameAmount(interpFramesDir, targetFrameCount);
if (canceled) return;
Program.mainForm.SetStatus("Running AI...");
await RunAi(interpFramesDir, targetFrameCount, tilesize, ai);
await RunAi(interpFramesDir, targetFrameCount, current.tilesize, current.ai);
if (canceled) return;
Program.mainForm.SetProgress(100);
if(!currentlyUsingAutoEnc)
await CreateVideo.Export(interpFramesDir, nextOutPath, outMode);
await CreateVideo.Export(interpFramesDir, current.outFilename, current.outMode);
IOUtils.ReverseRenaming(AiProcess.filenameMap, true); // Get timestamps back
Cleanup(interpFramesDir);
Program.mainForm.SetWorking(false);
@@ -103,7 +85,7 @@ namespace Flowframes
if (Config.GetBool("scnDetect"))
{
Program.mainForm.SetStatus("Extracting scenes from video...");
await FFmpegCommands.ExtractSceneChanges(inPath, Path.Combine(currentTempDir, Paths.scenesDir));
await FFmpegCommands.ExtractSceneChanges(inPath, Path.Combine(current.tempFolder, Paths.scenesDir));
await Task.Delay(10);
}
@@ -112,7 +94,7 @@ namespace Flowframes
if (extractAudio)
{
string audioFile = Path.Combine(currentTempDir, "audio.m4a");
string audioFile = Path.Combine(current.tempFolder, "audio.m4a");
if (audioFile != null && !File.Exists(audioFile))
await FFmpegCommands.ExtractAudio(inPath, audioFile);
}
@@ -131,8 +113,8 @@ namespace Flowframes
{
if (canceled) return;
int extractedFrames = IOUtils.GetAmountOfFiles(currentFramesPath, false, "*.png");
if (!Directory.Exists(currentFramesPath) || currentInputFrameCount <= 0 || extractedFrames < 2)
int extractedFrames = IOUtils.GetAmountOfFiles(current.framesFolder, false, "*.png");
if (!Directory.Exists(current.framesFolder) || currentInputFrameCount <= 0 || extractedFrames < 2)
{
if(extractedFrames == 1)
Cancel("Only a single frame was extracted from your input file!\n\nPossibly your input is an image, not a video?");
@@ -141,24 +123,24 @@ namespace Flowframes
}
if (Config.GetInt("dedupMode") == 1)
await MagickDedupe.Run(currentFramesPath);
await MagickDedupe.Run(current.framesFolder);
else
MagickDedupe.ClearCache();
if (canceled) return;
bool useTimestamps = Config.GetInt("timingMode") == 1; // TODO: Auto-Disable timestamps if input frames are sequential, not timestamped
await FrameTiming.CreateTimecodeFiles(currentFramesPath, Config.GetBool("enableLoop"), lastInterpFactor, !useTimestamps);
await FrameTiming.CreateTimecodeFiles(current.framesFolder, Config.GetBool("enableLoop"), current.interpFactor, !useTimestamps);
if (canceled) return;
AiProcess.filenameMap = IOUtils.RenameCounterDirReversible(currentFramesPath, "png", 1, 8);
AiProcess.filenameMap = IOUtils.RenameCounterDirReversible(current.framesFolder, "png", 1, 8);
}
public static async Task RunAi(string outpath, int targetFrames, int tilesize, AI ai, bool stepByStep = false)
{
if ((stepByStep && Config.GetBool("sbsAllowAutoEnc")) || (!stepByStep && Config.GetInt("autoEncMode") > 0))
currentlyUsingAutoEnc = currentOutMode == OutMode.VidMp4 && IOUtils.GetAmountOfFiles(currentFramesPath, false) * lastInterpFactor >= (AutoEncode.chunkSize + AutoEncode.safetyBufferFrames) * 1.1f;
currentlyUsingAutoEnc = current.outMode == OutMode.VidMp4 && IOUtils.GetAmountOfFiles(current.framesFolder, false) * current.interpFactor >= (AutoEncode.chunkSize + AutoEncode.safetyBufferFrames) * 1.1f;
else
currentlyUsingAutoEnc = false;
@@ -167,16 +149,16 @@ namespace Flowframes
List<Task> tasks = new List<Task>();
if (ai.aiName == Networks.dainNcnn.aiName)
tasks.Add(AiProcess.RunDainNcnn(currentFramesPath, outpath, targetFrames, tilesize));
tasks.Add(AiProcess.RunDainNcnn(current.framesFolder, outpath, targetFrames, tilesize));
if (ai.aiName == Networks.cainNcnn.aiName)
tasks.Add(AiProcess.RunCainNcnnMulti(currentFramesPath, outpath, tilesize, interpFactor));
tasks.Add(AiProcess.RunCainNcnnMulti(current.framesFolder, outpath, tilesize, current.interpFactor));
if (ai.aiName == Networks.rifeCuda.aiName)
tasks.Add(AiProcess.RunRifeCuda(currentFramesPath, interpFactor));
tasks.Add(AiProcess.RunRifeCuda(current.framesFolder, current.interpFactor));
if (ai.aiName == Networks.rifeNcnn.aiName)
tasks.Add(AiProcess.RunRifeNcnnMulti(currentFramesPath, outpath, tilesize, interpFactor));
tasks.Add(AiProcess.RunRifeNcnnMulti(current.framesFolder, outpath, tilesize, current.interpFactor));
if (currentlyUsingAutoEnc)
{
@@ -220,7 +202,7 @@ namespace Flowframes
Program.mainForm.SetStatus("Canceled.");
Program.mainForm.SetProgress(0);
if (Config.GetInt("processingMode") == 0 && !Config.GetBool("keepTempFolder"))
IOUtils.TryDeleteIfExists(currentTempDir);
IOUtils.TryDeleteIfExists(current.tempFolder);
Program.mainForm.SetWorking(false);
Program.mainForm.SetTab("interpolation");
if(!Logger.GetLastLine().Contains("Canceled interpolation."))
@@ -236,8 +218,8 @@ namespace Flowframes
try
{
if (Config.GetBool("keepFrames"))
IOUtils.Copy(interpFramesDir, Path.Combine(currentTempDir.GetParentDir(), Path.GetFileName(currentTempDir).Replace("-temp", "-interpframes")));
Directory.Delete(currentTempDir, true);
IOUtils.Copy(interpFramesDir, Path.Combine(current.tempFolder.GetParentDir(), Path.GetFileName(current.tempFolder).Replace("-temp", "-interpframes")));
Directory.Delete(current.tempFolder, true);
}
catch (Exception e)
{

View File

@@ -16,23 +16,23 @@ namespace Flowframes.Main
{
public enum Step { ExtractScnChanges, ExtractFrames, Interpolate, CreateVid, Reset }
public static string currentInPath;
public static string currentOutPath;
public static string currentInterpFramesDir;
public static AI currentAi;
public static OutMode currentOutMode;
//public static string current.inPath;
//public static string currentOutPath;
//public static string current.interpFolder;
//public static AI currentAi;
//public static OutMode currentOutMode;
public static async Task Run(string step)
{
canceled = false;
Program.mainForm.SetWorking(true);
InitState();
current = Program.mainForm.GetCurrentSettings();
if (!InterpolateUtils.InputIsValid(currentInPath, currentOutPath, currentOutFps, interpFactor, Program.mainForm.GetTilesize())) return; // General input checks
if (!InterpolateUtils.InputIsValid(current.inPath, current.outPath, current.outFps, current.interpFactor, current.tilesize)) return; // General input checks
if (step.Contains("Extract Scene Changes"))
{
if (!currentInputIsFrames) // Input is video - extract frames first
if (!current.inputIsFrames) // Input is video - extract frames first
await ExtractSceneChanges();
else
InterpolateUtils.ShowMessage("Scene changes can only be extracted from videos, not frames!", "Error");
@@ -40,10 +40,10 @@ namespace Flowframes.Main
if (step.Contains("Extract Frames"))
{
if (!currentInputIsFrames) // Input is video - extract frames first
if (!current.inputIsFrames) // Input is video - extract frames first
await ExtractVideoFrames();
else
await FFmpegCommands.ImportImages(currentInPath, currentFramesPath);
await FFmpegCommands.ImportImages(current.inPath, current.framesFolder);
}
if (step.Contains("Run Interpolation"))
@@ -59,44 +59,22 @@ namespace Flowframes.Main
Logger.Log("Done running this step.");
}
static void InitState()
{
BatchEntry e = Program.mainForm.GetBatchEntry();
interpFactor = e.interpFactor;
currentAi = e.ai;
try
{
currentInPath = e.inPath;
currentOutPath = e.outPath;
currentTempDir = InterpolateUtils.GetTempFolderLoc(currentInPath, currentOutPath);
currentFramesPath = Path.Combine(currentTempDir, Paths.framesDir);
currentInterpFramesDir = Path.Combine(currentTempDir, Paths.interpDir);
currentInputIsFrames = IOUtils.IsPathDirectory(currentInPath);
}
catch
{
// Handled later basically
}
}
public static async Task ExtractSceneChanges()
{
string scenesPath = Path.Combine(currentTempDir, Paths.scenesDir);
string scenesPath = Path.Combine(current.tempFolder, Paths.scenesDir);
if (!IOUtils.TryDeleteIfExists(scenesPath))
{
InterpolateUtils.ShowMessage("Failed to delete existing scenes folder - Make sure no file is opened in another program!", "Error");
return;
}
Program.mainForm.SetStatus("Extracting scenes from video...");
await FFmpegCommands.ExtractSceneChanges(currentInPath, scenesPath);
await FFmpegCommands.ExtractSceneChanges(current.inPath, scenesPath);
await Task.Delay(10);
}
public static async Task ExtractVideoFrames()
{
currentFramesPath = Path.Combine(currentTempDir, Paths.framesDir);
if (!IOUtils.TryDeleteIfExists(currentFramesPath))
if (!IOUtils.TryDeleteIfExists(current.framesFolder))
{
InterpolateUtils.ShowMessage("Failed to delete existing frames folder - Make sure no file is opened in another program!", "Error");
return;
@@ -105,20 +83,20 @@ namespace Flowframes.Main
AiProcess.filenameMap.Clear();
bool extractAudio = true;
Program.mainForm.SetStatus("Extracting frames from video...");
await FFmpegCommands.VideoToFrames(currentInPath, currentFramesPath, Config.GetInt("dedupMode") == 2, false, InterpolateUtils.GetOutputResolution(currentInPath));
await FFmpegCommands.VideoToFrames(current.inPath, current.framesFolder, Config.GetInt("dedupMode") == 2, false, InterpolateUtils.GetOutputResolution(current.inPath));
if (extractAudio)
{
string audioFile = Path.Combine(currentTempDir, "audio.m4a");
string audioFile = Path.Combine(current.tempFolder, "audio.m4a");
if (audioFile != null && !File.Exists(audioFile))
await FFmpegCommands.ExtractAudio(currentInPath, audioFile);
await FFmpegCommands.ExtractAudio(current.inPath, audioFile);
}
if (!canceled && Config.GetBool("enableLoop") && Config.GetInt("timingMode") != 1)
{
string lastFrame = IOUtils.GetHighestFrameNumPath(currentFramesPath);
string lastFrame = IOUtils.GetHighestFrameNumPath(current.framesFolder);
int newNum = Path.GetFileName(lastFrame).GetInt() + 1;
string newFilename = Path.Combine(lastFrame.GetParentDir(), newNum.ToString().PadLeft(Padding.inputFrames, '0') + ".png");
string firstFrame = new DirectoryInfo(currentFramesPath).GetFiles("*.png")[0].FullName;
string firstFrame = new DirectoryInfo(current.framesFolder).GetFiles("*.png")[0].FullName;
File.Copy(firstFrame, newFilename);
Logger.Log("Copied loop frame.");
}
@@ -126,44 +104,44 @@ namespace Flowframes.Main
public static async Task DoInterpolate()
{
currentFramesPath = Path.Combine(currentTempDir, Paths.framesDir);
if (!Directory.Exists(currentFramesPath) || IOUtils.GetAmountOfFiles(currentFramesPath, false, "*.png") < 2)
current.framesFolder = Path.Combine(current.tempFolder, Paths.framesDir);
if (!Directory.Exists(current.framesFolder) || IOUtils.GetAmountOfFiles(current.framesFolder, false, "*.png") < 2)
{
InterpolateUtils.ShowMessage("There are no extracted frames that can be interpolated!\nDid you run the extraction step?", "Error");
return;
}
if (!IOUtils.TryDeleteIfExists(currentInterpFramesDir))
if (!IOUtils.TryDeleteIfExists(current.interpFolder))
{
InterpolateUtils.ShowMessage("Failed to delete existing frames folder - Make sure no file is opened in another program!", "Error");
return;
}
currentInputFrameCount = InterpolateUtils.GetInputFrameCount(currentInPath);
currentInputFrameCount = InterpolateUtils.GetInputFrameCount(current.inPath);
foreach (string ini in Directory.GetFiles(currentTempDir, "*.ini", SearchOption.TopDirectoryOnly))
foreach (string ini in Directory.GetFiles(current.tempFolder, "*.ini", SearchOption.TopDirectoryOnly))
IOUtils.TryDeleteIfExists(ini);
IOUtils.ReverseRenaming(AiProcess.filenameMap, true); // Get timestamps back
lastInterpFactor = interpFactor;
if (Config.GetBool("sbsAllowAutoEnc"))
nextOutPath = Path.Combine(currentOutPath, Path.GetFileNameWithoutExtension(currentInPath) + IOUtils.GetAiSuffix(currentAi, lastInterpFactor) + InterpolateUtils.GetExt(currentOutMode));
// TODO: Check if this works lol, remove if it does
//if (Config.GetBool("sbsAllowAutoEnc"))
// nextOutPath = Path.Combine(currentOutPath, Path.GetFileNameWithoutExtension(current.inPath) + IOUtils.GetAiSuffix(current.ai, current.interpFactor) + InterpolateUtils.GetExt(current.outMode));
await PostProcessFrames(true);
int frames = IOUtils.GetAmountOfFiles(currentFramesPath, false, "*.png");
int targetFrameCount = frames * lastInterpFactor;
GetProgressByFrameAmount(currentInterpFramesDir, targetFrameCount);
int frames = IOUtils.GetAmountOfFiles(current.framesFolder, false, "*.png");
int targetFrameCount = frames * current.interpFactor;
GetProgressByFrameAmount(current.interpFolder, targetFrameCount);
if (canceled) return;
Program.mainForm.SetStatus("Running AI...");
int tilesize = currentAi.supportsTiling ? Config.GetInt($"tilesize_{currentAi.aiName}") : 512;
await RunAi(currentInterpFramesDir, targetFrameCount, tilesize, currentAi, true);
int tilesize = current.ai.supportsTiling ? Config.GetInt($"tilesize_{current.ai.aiName}") : 512;
await RunAi(current.interpFolder, targetFrameCount, tilesize, current.ai, true);
Program.mainForm.SetProgress(0);
}
public static async Task CreateOutputVid()
{
string[] outFrames = Directory.GetFiles(currentInterpFramesDir, $"*.{InterpolateUtils.GetExt()}");
string[] outFrames = Directory.GetFiles(current.interpFolder, $"*.{InterpolateUtils.GetExt()}");
if (outFrames.Length > 0 && !IOUtils.CheckImageValid(outFrames[0]))
{
InterpolateUtils.ShowMessage("Invalid frame files detected!\n\nIf you used Auto-Encode, this is normal, and you don't need to run " +
@@ -171,14 +149,13 @@ namespace Flowframes.Main
return;
}
currentOutMode = Program.mainForm.GetBatchEntry().outMode;
string outPath = Path.Combine(currentOutPath, Path.GetFileNameWithoutExtension(currentInPath) + IOUtils.GetAiSuffix(currentAi, lastInterpFactor) + InterpolateUtils.GetExt(currentOutMode));
await CreateVideo.Export(currentInterpFramesDir, outPath, currentOutMode);
string outPath = Path.Combine(current.outPath, Path.GetFileNameWithoutExtension(current.inPath) + IOUtils.GetAiSuffix(current.ai, current.interpFactor) + InterpolateUtils.GetExt(current.outMode));
await CreateVideo.Export(current.interpFolder, outPath, current.outMode);
}
public static async Task Reset()
{
Cleanup(currentInterpFramesDir, true);
Cleanup(current.interpFolder, true);
}
}
}

View File

@@ -33,7 +33,7 @@ namespace Flowframes.Main
float generousTime = ((AiProcess.processTime.ElapsedMilliseconds - AiProcess.lastStartupTimeMs) / 1000f);
float fps = (float)frames / generousTime;
string fpsIn = (fps / i.interpFactor).ToString("0.00");
string fpsIn = (fps / i.current.interpFactor).ToString("0.00");
string fpsOut = fps.ToString("0.00");
float secondsPerFrame = generousTime / (float)frames;
@@ -50,7 +50,7 @@ namespace Flowframes.Main
try
{
if (!string.IsNullOrWhiteSpace(latestFramePath) && frames > i.interpFactor)
if (!string.IsNullOrWhiteSpace(latestFramePath) && frames > i.current.interpFactor)
{
if (bigPreviewForm == null && !preview.Visible /* ||Program.mainForm.WindowState != FormWindowState.Minimized */ /* || !Program.mainForm.IsInFocus()*/) return; // Skip if the preview is not visible or the form is not in focus
Image img = IOUtils.GetImage(latestFramePath);
@@ -204,7 +204,7 @@ namespace Flowframes.Main
public static bool CheckDeleteOldTempFolder ()
{
if (!IOUtils.TryDeleteIfExists(i.currentTempDir))
if (!IOUtils.TryDeleteIfExists(i.current.tempFolder))
{
ShowMessage("Failed to remove an existing temp folder of this video!\nMake sure you didn't open any frames in an editor.", "Error");
i.Cancel();

View File

@@ -19,7 +19,7 @@ namespace Flowframes
public static string lastInputPath;
public static bool lastInputPathIsSsd;
public static Queue<BatchEntry> batchQueue = new Queue<BatchEntry>();
public static Queue<InterpSettings> batchQueue = new Queue<InterpSettings>();
[STAThread]
static void Main()

View File

@@ -28,7 +28,7 @@ namespace Flowframes.UI
fpsStr = fps.ToString();
fpsInTbox.Text = fpsStr;
}
Interpolate.SetFps(fps);
//Interpolate.SetFps(fps);
Program.lastInputPathIsSsd = OSUtils.DriveIsSSD(path);
if (!Program.lastInputPathIsSsd)
Logger.Log("Your file seems to be on an HDD or USB device. It is recommended to interpolate videos on an SSD drive for best performance.");

View File

@@ -20,7 +20,7 @@ namespace Flowframes.UI
string outPath = Path.ChangeExtension(videoPath, null) + "-extracted";
Program.mainForm.SetWorking(true);
await FFmpegCommands.VideoToFrames(videoPath, Path.Combine(outPath, Paths.framesDir), false, false, false);
File.WriteAllText(Path.Combine(outPath, "fps.ini"), Interpolate.currentInFps.ToString());
File.WriteAllText(Path.Combine(outPath, "fps.ini"), Interpolate.current.inFps.ToString());
if (withAudio)
await FFmpegCommands.ExtractAudio(videoPath, Path.Combine(outPath, "audio"));
Program.mainForm.SetWorking(false);