mirror of
https://github.com/n00mkrad/flowframes.git
synced 2025-12-16 16:37:48 +01:00
Cleaner code for Interpolate.cs
This commit is contained in:
@@ -103,7 +103,7 @@ namespace Flowframes
|
|||||||
string enc = useH265 ? "libx265" : "libx264";
|
string enc = useH265 ? "libx265" : "libx264";
|
||||||
string presetStr = $"-preset {Config.Get("ffEncPreset")}";
|
string presetStr = $"-preset {Config.Get("ffEncPreset")}";
|
||||||
string vfrFilename = Path.GetFileName(framesFile);
|
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()}";
|
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);
|
await AvProcess.RunFfmpeg(args, framesFile.GetParentDir(), logMode);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
52
Code/Data/InterpSettings.cs
Normal file
52
Code/Data/InterpSettings.cs
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -190,7 +190,7 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="AudioVideo\GifskiCommands.cs" />
|
<Compile Include="AudioVideo\GifskiCommands.cs" />
|
||||||
<Compile Include="Data\AI.cs" />
|
<Compile Include="Data\AI.cs" />
|
||||||
<Compile Include="Data\BatchEntry.cs" />
|
<Compile Include="Data\InterpSettings.cs" />
|
||||||
<Compile Include="Data\Networks.cs" />
|
<Compile Include="Data\Networks.cs" />
|
||||||
<Compile Include="Data\Padding.cs" />
|
<Compile Include="Data\Padding.cs" />
|
||||||
<Compile Include="Data\SemVer.cs" />
|
<Compile Include="Data\SemVer.cs" />
|
||||||
|
|||||||
@@ -86,13 +86,13 @@ namespace Flowframes
|
|||||||
mainTabControl.Update();
|
mainTabControl.Update();
|
||||||
}
|
}
|
||||||
|
|
||||||
public BatchEntry GetBatchEntry()
|
public InterpSettings GetCurrentSettings()
|
||||||
{
|
{
|
||||||
SetTab("interpolate");
|
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;
|
inputTbox.Text = entry.inPath;
|
||||||
outputTbox.Text = entry.outPath;
|
outputTbox.Text = entry.outPath;
|
||||||
@@ -157,13 +157,9 @@ namespace Flowframes
|
|||||||
{
|
{
|
||||||
if (!BatchProcessing.busy) // Don't load values from gui if batch processing is used
|
if (!BatchProcessing.busy) // Don't load values from gui if batch processing is used
|
||||||
{
|
{
|
||||||
SetTab("interpolation");
|
Interpolate.current = GetCurrentSettings();
|
||||||
Interpolate.SetFps(fpsInTbox.GetFloat());
|
|
||||||
Interpolate.interpFactor = interpFactorCombox.GetInt();
|
|
||||||
}
|
}
|
||||||
string inPath = inputTbox.Text.Trim();
|
Interpolate.Start();
|
||||||
string outPath = outputTbox.Text.Trim();
|
|
||||||
Interpolate.Start(inPath, outPath, GetTilesize(), GetOutMode(), GetAi());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public int GetTilesize()
|
public int GetTilesize()
|
||||||
@@ -213,7 +209,7 @@ namespace Flowframes
|
|||||||
private void fpsInTbox_TextChanged(object sender, EventArgs e)
|
private void fpsInTbox_TextChanged(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
fpsInTbox.Text = fpsInTbox.Text.TrimNumbers(true);
|
fpsInTbox.Text = fpsInTbox.Text.TrimNumbers(true);
|
||||||
Interpolate.SetFps(fpsInTbox.GetFloat());
|
//Interpolate.SetFps(fpsInTbox.GetFloat());
|
||||||
UpdateOutputFPS();
|
UpdateOutputFPS();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -221,14 +217,15 @@ namespace Flowframes
|
|||||||
{
|
{
|
||||||
float fpsOut = fpsInTbox.GetFloat() * interpFactorCombox.GetFloat();
|
float fpsOut = fpsInTbox.GetFloat() * interpFactorCombox.GetFloat();
|
||||||
fpsOutTbox.Text = fpsOut.ToString();
|
fpsOutTbox.Text = fpsOut.ToString();
|
||||||
Interpolate.interpFactor = interpFactorCombox.GetInt();
|
//Interpolate.interpFactor = interpFactorCombox.GetInt();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void interpFactorCombox_SelectedIndexChanged(object sender, EventArgs e)
|
private void interpFactorCombox_SelectedIndexChanged(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
UpdateOutputFPS();
|
UpdateOutputFPS();
|
||||||
if (Interpolate.interpFactor > 2 && !GetAi().supportsAnyExp && Config.GetInt("autoEncMode") > 0)
|
int guiInterpFactor = interpFactorCombox.GetInt();
|
||||||
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.");
|
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)
|
public void SetWorking(bool state)
|
||||||
@@ -404,7 +401,7 @@ namespace Flowframes
|
|||||||
private async void runStepBtn_Click(object sender, EventArgs e)
|
private async void runStepBtn_Click(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
SetTab("interpolate");
|
SetTab("interpolate");
|
||||||
Interpolate.SetFps(fpsInTbox.GetFloat());
|
//Interpolate.SetFps(fpsInTbox.GetFloat());
|
||||||
await InterpolateSteps.Run(stepSelector.Text);
|
await InterpolateSteps.Run(stepSelector.Text);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ namespace Flowframes.Forms
|
|||||||
|
|
||||||
private void addToQueue_Click(object sender, EventArgs e)
|
private void addToQueue_Click(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
Program.batchQueue.Enqueue(Program.mainForm.GetBatchEntry());
|
Program.batchQueue.Enqueue(Program.mainForm.GetCurrentSettings());
|
||||||
RefreshGui();
|
RefreshGui();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -30,7 +30,7 @@ namespace Flowframes.Forms
|
|||||||
string nl = Environment.NewLine;
|
string nl = Environment.NewLine;
|
||||||
for (int i = 0; i < Program.batchQueue.Count; i++)
|
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 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}";
|
string str = $"#{i}: {Path.GetFileName(entry.inPath).Trunc(45)} - {entry.inFps} FPS => {entry.interpFactor}x{nl} {entry.ai.aiNameShort} => {niceOutMode}";
|
||||||
taskList.Items.Add(str);
|
taskList.Items.Add(str);
|
||||||
@@ -88,7 +88,7 @@ namespace Flowframes.Forms
|
|||||||
{
|
{
|
||||||
if (taskList.SelectedItem == null) return;
|
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++)
|
for(int i = 0; i < Program.batchQueue.Count; i++)
|
||||||
{
|
{
|
||||||
@@ -125,7 +125,7 @@ namespace Flowframes.Forms
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
BatchEntry dragDropEntry = Program.mainForm.GetBatchEntry();
|
InterpSettings dragDropEntry = Program.mainForm.GetCurrentSettings();
|
||||||
dragDropEntry.inPath = path;
|
dragDropEntry.inPath = path;
|
||||||
dragDropEntry.outPath = path.GetParentDir();
|
dragDropEntry.outPath = path.GetParentDir();
|
||||||
dragDropEntry.inFps = GetFramerate(path);
|
dragDropEntry.inFps = GetFramerate(path);
|
||||||
@@ -137,7 +137,7 @@ namespace Flowframes.Forms
|
|||||||
|
|
||||||
float GetFramerate (string path)
|
float GetFramerate (string path)
|
||||||
{
|
{
|
||||||
float fps = Interpolate.currentInFps;
|
float fps = Interpolate.current.inFps;
|
||||||
float fpsFromFile = IOUtils.GetFpsFolderOrVideo(path);
|
float fpsFromFile = IOUtils.GetFpsFolderOrVideo(path);
|
||||||
if (fpsFromFile > 0)
|
if (fpsFromFile > 0)
|
||||||
return fpsFromFile;
|
return fpsFromFile;
|
||||||
|
|||||||
@@ -322,7 +322,7 @@ namespace Flowframes.IO
|
|||||||
fps = float.Parse(ReadLines(fpsFile)[0]);
|
fps = float.Parse(ReadLines(fpsFile)[0]);
|
||||||
Logger.Log($"Got {fps} FPS from file: " + fpsFile);
|
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" +
|
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);
|
$"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);
|
||||||
|
|||||||
@@ -216,7 +216,7 @@ namespace Flowframes.Magick
|
|||||||
|
|
||||||
string ext = InterpolateUtils.GetExt();
|
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;
|
if (!File.Exists(dupeInfoFile)) return;
|
||||||
|
|
||||||
Logger.Log("Re-Duplicating frames to fix timing...");
|
Logger.Log("Re-Duplicating frames to fix timing...");
|
||||||
@@ -227,7 +227,7 @@ namespace Flowframes.Magick
|
|||||||
string tempSubFolder = Path.Combine(path, "temp");
|
string tempSubFolder = Path.Combine(path, "temp");
|
||||||
Directory.CreateDirectory(tempSubFolder);
|
Directory.CreateDirectory(tempSubFolder);
|
||||||
|
|
||||||
int interpFramesPerRealFrame = Interpolate.interpFactor - 1;
|
int interpFramesPerRealFrame = Interpolate.current.interpFactor - 1;
|
||||||
|
|
||||||
int sourceFrameNum = 0;
|
int sourceFrameNum = 0;
|
||||||
int outFrameNum = 1;
|
int outFrameNum = 1;
|
||||||
|
|||||||
@@ -31,8 +31,8 @@ namespace Flowframes.Main
|
|||||||
encodedFrames.Clear();
|
encodedFrames.Clear();
|
||||||
unencodedFrames.Clear();
|
unencodedFrames.Clear();
|
||||||
|
|
||||||
chunkSize = GetChunkSize(IOUtils.GetAmountOfFiles(Interpolate.currentFramesPath, false, "*.png") * Interpolate.lastInterpFactor);
|
chunkSize = GetChunkSize(IOUtils.GetAmountOfFiles(Interpolate.current.framesFolder, false, "*.png") * Interpolate.current.interpFactor);
|
||||||
safetyBufferFrames = Interpolate.lastAi.aiName.ToUpper().Contains("NCNN") ? 60 : 30; // Use bigger safety buffer for NCNN
|
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);
|
Logger.Log($"Starting AutoEncode MainLoop - Chunk Size: {chunkSize} Frames - Safety Buffer: {safetyBufferFrames} Frames", true);
|
||||||
|
|
||||||
int videoIndex = 1;
|
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
|
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();
|
int firstFrameNum = Path.GetFileNameWithoutExtension(framesToEncode[0]).GetInt();
|
||||||
await CreateVideo.EncodeChunk(outpath, firstFrameNum - 1, framesToEncode.Count);
|
await CreateVideo.EncodeChunk(outpath, firstFrameNum - 1, framesToEncode.Count);
|
||||||
|
|
||||||
@@ -98,7 +98,7 @@ namespace Flowframes.Main
|
|||||||
|
|
||||||
IOUtils.ReverseRenaming(AiProcess.filenameMap, true); // Get timestamps back
|
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 ()
|
public static bool HasWorkToDo ()
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ namespace Flowframes.Main
|
|||||||
stopped = true;
|
stopped = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static async Task RunEntry(BatchEntry entry)
|
static async Task RunEntry(InterpSettings entry)
|
||||||
{
|
{
|
||||||
if (!EntryIsValid(entry))
|
if (!EntryIsValid(entry))
|
||||||
{
|
{
|
||||||
@@ -58,8 +58,9 @@ namespace Flowframes.Main
|
|||||||
|
|
||||||
SetBusy(true);
|
SetBusy(true);
|
||||||
Program.mainForm.LoadBatchEntry(entry); // Load entry into GUI
|
Program.mainForm.LoadBatchEntry(entry); // Load entry into GUI
|
||||||
Interpolate.interpFactor = entry.interpFactor;
|
Interpolate.current = entry;
|
||||||
Interpolate.SetFps(entry.inFps);
|
// Interpolate.interpFactor = entry.interpFactor;
|
||||||
|
// Interpolate.SetFps(entry.inFps);
|
||||||
Program.mainForm.runBtn_Click(null, null);
|
Program.mainForm.runBtn_Click(null, null);
|
||||||
|
|
||||||
await Task.Delay(2000);
|
await Task.Delay(2000);
|
||||||
@@ -81,7 +82,7 @@ namespace Flowframes.Main
|
|||||||
Program.mainForm.GetMainTabControl().Enabled = !state; // Lock GUI
|
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)))
|
if (entry.inPath == null || (IOUtils.IsPathDirectory(entry.inPath) && !Directory.Exists(entry.inPath)) || (!IOUtils.IsPathDirectory(entry.inPath) && !File.Exists(entry.inPath)))
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ namespace Flowframes.Main
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
Logger.Log("Moving interpolated frames out of temp folder...");
|
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}");
|
Logger.Log($"{path} -> {copyPath}");
|
||||||
IOUtils.CreateDir(copyPath);
|
IOUtils.CreateDir(copyPath);
|
||||||
IOUtils.Copy(path, copyPath, true);
|
IOUtils.Copy(path, copyPath, true);
|
||||||
@@ -51,10 +51,10 @@ namespace Flowframes.Main
|
|||||||
int maxFps = Config.GetInt("maxFps");
|
int maxFps = Config.GetInt("maxFps");
|
||||||
if (maxFps == 0) maxFps = 500;
|
if (maxFps == 0) maxFps = 500;
|
||||||
|
|
||||||
if (mode == i.OutMode.VidMp4 && i.currentOutFps > maxFps)
|
if (mode == i.OutMode.VidMp4 && i.current.outFps > maxFps)
|
||||||
await Encode(mode, path, outPath, i.currentOutFps, maxFps, (Config.GetInt("maxFpsMode") == 1));
|
await Encode(mode, path, outPath, i.current.outFps, maxFps, (Config.GetInt("maxFpsMode") == 1));
|
||||||
else
|
else
|
||||||
await Encode(mode, path, outPath, i.currentOutFps);
|
await Encode(mode, path, outPath, i.current.outFps);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
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)
|
static async Task Encode(i.OutMode mode, string framesPath, string outPath, float fps, float changeFps = -1, bool keepOriginalFpsVid = true)
|
||||||
{
|
{
|
||||||
currentOutFile = outPath;
|
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)
|
if (mode == i.OutMode.VidGif)
|
||||||
await FFmpegCommands.FramesToGifVfr(vfrFile, outPath, true, Config.GetInt("gifColors"));
|
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");
|
int crf = h265 ? Config.GetInt("h265Crf") : Config.GetInt("h264Crf");
|
||||||
|
|
||||||
await FFmpegCommands.FramesToMp4Vfr(vfrFile, outPath, h265, crf, fps);
|
await FFmpegCommands.FramesToMp4Vfr(vfrFile, outPath, h265, crf, fps);
|
||||||
await MergeAudio(i.lastInputPath, outPath);
|
await MergeAudio(i.current.inPath, outPath);
|
||||||
|
|
||||||
if (changeFps > 0)
|
if (changeFps > 0)
|
||||||
{
|
{
|
||||||
currentOutFile = IOUtils.FilenameSuffix(outPath, $"-{changeFps.ToString("0")}fps");
|
currentOutFile = IOUtils.FilenameSuffix(outPath, $"-{changeFps.ToString("0")}fps");
|
||||||
Program.mainForm.SetStatus("Creating video with desired frame rate...");
|
Program.mainForm.SetStatus("Creating video with desired frame rate...");
|
||||||
await FFmpegCommands.ConvertFramerate(outPath, currentOutFile, h265, crf, changeFps, !keepOriginalFpsVid);
|
await FFmpegCommands.ConvertFramerate(outPath, currentOutFile, h265, crf, changeFps, !keepOriginalFpsVid);
|
||||||
await MergeAudio(i.lastInputPath, currentOutFile);
|
await MergeAudio(i.current.inPath, currentOutFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (looptimes > 0)
|
if (looptimes > 0)
|
||||||
@@ -108,10 +108,10 @@ namespace Flowframes.Main
|
|||||||
int maxFps = Config.GetInt("maxFps");
|
int maxFps = Config.GetInt("maxFps");
|
||||||
if (maxFps == 0) maxFps = 500;
|
if (maxFps == 0) maxFps = 500;
|
||||||
|
|
||||||
if (i.currentOutFps > maxFps)
|
if (i.current.outFps > maxFps)
|
||||||
await MergeChunks(chunksPath, vfrFile, outPath, i.currentOutFps, maxFps, (Config.GetInt("maxFpsMode") == 1));
|
await MergeChunks(chunksPath, vfrFile, outPath, i.current.outFps, maxFps, (Config.GetInt("maxFpsMode") == 1));
|
||||||
else
|
else
|
||||||
await MergeChunks(chunksPath, vfrFile, outPath, i.currentOutFps);
|
await MergeChunks(chunksPath, vfrFile, outPath, i.current.outFps);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
@@ -128,7 +128,7 @@ namespace Flowframes.Main
|
|||||||
int crf = h265 ? Config.GetInt("h265Crf") : Config.GetInt("h264Crf");
|
int crf = h265 ? Config.GetInt("h265Crf") : Config.GetInt("h264Crf");
|
||||||
|
|
||||||
await FFmpegCommands.ConcatVideos(vfrFile, outPath, fps, -1);
|
await FFmpegCommands.ConcatVideos(vfrFile, outPath, fps, -1);
|
||||||
await MergeAudio(i.lastInputPath, outPath);
|
await MergeAudio(i.current.inPath, outPath);
|
||||||
|
|
||||||
if (looptimes > 0)
|
if (looptimes > 0)
|
||||||
await Loop(outPath, looptimes);
|
await Loop(outPath, looptimes);
|
||||||
@@ -138,7 +138,7 @@ namespace Flowframes.Main
|
|||||||
string newOutPath = IOUtils.FilenameSuffix(outPath, $"-{changeFps.ToString("0")}fps");
|
string newOutPath = IOUtils.FilenameSuffix(outPath, $"-{changeFps.ToString("0")}fps");
|
||||||
Program.mainForm.SetStatus("Creating video with desired frame rate...");
|
Program.mainForm.SetStatus("Creating video with desired frame rate...");
|
||||||
await FFmpegCommands.ConvertFramerate(outPath, newOutPath, h265, crf, changeFps, !keepOriginalFpsVid);
|
await FFmpegCommands.ConvertFramerate(outPath, newOutPath, h265, crf, changeFps, !keepOriginalFpsVid);
|
||||||
await MergeAudio(i.lastInputPath, newOutPath);
|
await MergeAudio(i.current.inPath, newOutPath);
|
||||||
if (looptimes > 0)
|
if (looptimes > 0)
|
||||||
await Loop(newOutPath, looptimes);
|
await Loop(newOutPath, looptimes);
|
||||||
}
|
}
|
||||||
@@ -149,11 +149,11 @@ namespace Flowframes.Main
|
|||||||
bool h265 = Config.GetInt("mp4Enc") == 1;
|
bool h265 = Config.GetInt("mp4Enc") == 1;
|
||||||
int crf = h265 ? Config.GetInt("h265Crf") : Config.GetInt("h264Crf");
|
int crf = h265 ? Config.GetInt("h265Crf") : Config.GetInt("h264Crf");
|
||||||
|
|
||||||
string vfrFileOriginal = Path.Combine(i.currentTempDir, $"vfr-{i.lastInterpFactor}x.ini");
|
string vfrFileOriginal = Path.Combine(i.current.tempFolder, $"vfr-{i.current.interpFactor}x.ini");
|
||||||
string vfrFile = Path.Combine(i.currentTempDir, $"vfr-chunk-{firstFrameNum}-{firstFrameNum + framesAmount}.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));
|
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)
|
static async Task Loop(string outPath, int looptimes)
|
||||||
@@ -168,12 +168,12 @@ namespace Flowframes.Main
|
|||||||
int times = -1;
|
int times = -1;
|
||||||
int minLength = Config.GetInt("minOutVidLength");
|
int minLength = Config.GetInt("minOutVidLength");
|
||||||
//Logger.Log("minLength: " + minLength);
|
//Logger.Log("minLength: " + minLength);
|
||||||
int minFrameCount = (minLength * i.currentOutFps).RoundToInt();
|
int minFrameCount = (minLength * i.current.outFps).RoundToInt();
|
||||||
//Logger.Log("minFrameCount: " + minFrameCount);
|
//Logger.Log("minFrameCount: " + minFrameCount);
|
||||||
//int outFrames = new DirectoryInfo(framesOutPath).GetFiles($"*.{InterpolateUtils.GetExt()}", SearchOption.TopDirectoryOnly).Length;
|
//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);
|
//Logger.Log("outFrames: " + outFrames);
|
||||||
if (outFrames / i.currentOutFps < minLength)
|
if (outFrames / i.current.outFps < minLength)
|
||||||
times = (int)Math.Ceiling((double)minFrameCount / (double)outFrames);
|
times = (int)Math.Ceiling((double)minFrameCount / (double)outFrames);
|
||||||
//Logger.Log("times: " + times);
|
//Logger.Log("times: " + times);
|
||||||
times--; // Account for this calculation not counting the 1st play (0 loops)
|
times--; // Account for this calculation not counting the 1st play (0 loops)
|
||||||
@@ -186,10 +186,10 @@ namespace Flowframes.Main
|
|||||||
if (!Config.GetBool("enableAudio")) return;
|
if (!Config.GetBool("enableAudio")) return;
|
||||||
try
|
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
|
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)))
|
if (!File.Exists(IOUtils.GetAudioFile(audioFileBasePath)))
|
||||||
await FFmpegCommands.ExtractAudio(inputPath, audioFileBasePath); // Extract from sourceVideo to audioFile unless it already exists
|
await FFmpegCommands.ExtractAudio(inputPath, audioFileBasePath); // Extract from sourceVideo to audioFile unless it already exists
|
||||||
|
|||||||
@@ -23,20 +23,10 @@ namespace Flowframes
|
|||||||
{
|
{
|
||||||
public enum OutMode { VidMp4, VidGif, ImgPng }
|
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 int currentInputFrameCount;
|
||||||
public static bool constantFrameRate;
|
|
||||||
public static OutMode currentOutMode;
|
|
||||||
public static bool currentInputIsFrames;
|
|
||||||
public static bool currentlyUsingAutoEnc;
|
public static bool currentlyUsingAutoEnc;
|
||||||
public static int lastInterpFactor;
|
|
||||||
public static string lastInputPath;
|
public static InterpSettings current;
|
||||||
public static string nextOutPath;
|
|
||||||
public static AI lastAi;
|
|
||||||
|
|
||||||
public static bool canceled = false;
|
public static bool canceled = false;
|
||||||
|
|
||||||
@@ -45,50 +35,42 @@ namespace Flowframes
|
|||||||
|
|
||||||
public static void SetFps(float inFps)
|
public static void SetFps(float inFps)
|
||||||
{
|
{
|
||||||
currentInFps = inFps;
|
// TODO: Can't I remove this?
|
||||||
currentOutFps = inFps * interpFactor;
|
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;
|
canceled = false;
|
||||||
if (!Utils.InputIsValid(inPath, outDir, currentOutFps, interpFactor, tilesize)) return; // General input checks
|
if (!Utils.InputIsValid(current.inPath, current.outPath, current.outFps, current.interpFactor, current.tilesize)) return; // General input checks
|
||||||
if (!Utils.CheckAiAvailable(ai)) return; // Check if selected AI pkg is installed
|
if (!Utils.CheckAiAvailable(current.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.CheckDeleteOldTempFolder()) return; // Try to delete temp folder if an old one exists
|
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
|
if(!Utils.CheckPathValid(current.inPath)) return; // Check if input path/file is valid
|
||||||
Utils.PathAsciiCheck(inPath, outDir);
|
Utils.PathAsciiCheck(current.inPath, current.outPath);
|
||||||
lastAi = ai;
|
currentInputFrameCount = Utils.GetInputFrameCount(current.inPath);
|
||||||
currentInputIsFrames = IOUtils.IsPathDirectory(inPath);
|
|
||||||
currentInputFrameCount = Utils.GetInputFrameCount(inPath);
|
|
||||||
Program.mainForm.SetStatus("Starting...");
|
Program.mainForm.SetStatus("Starting...");
|
||||||
Program.mainForm.SetWorking(true);
|
Program.mainForm.SetWorking(true);
|
||||||
await Task.Delay(10);
|
await Task.Delay(10);
|
||||||
if (!currentInputIsFrames) // Input is video - extract frames first
|
if (!current.inputIsFrames) // Input is video - extract frames first
|
||||||
await ExtractFrames(inPath, currentFramesPath);
|
await ExtractFrames(current.inPath, current.framesFolder);
|
||||||
else
|
else
|
||||||
await FFmpegCommands.ImportImages(inPath, currentFramesPath);
|
await FFmpegCommands.ImportImages(current.inPath, current.framesFolder);
|
||||||
if (canceled) return;
|
if (canceled) return;
|
||||||
sw.Restart();
|
sw.Restart();
|
||||||
await Task.Delay(10);
|
await Task.Delay(10);
|
||||||
await PostProcessFrames();
|
await PostProcessFrames();
|
||||||
if (canceled) return;
|
if (canceled) return;
|
||||||
string interpFramesDir = Path.Combine(currentTempDir, Paths.interpDir);
|
string interpFramesDir = Path.Combine(current.tempFolder, Paths.interpDir);
|
||||||
nextOutPath = Path.Combine(outDir, Path.GetFileNameWithoutExtension(inPath) + IOUtils.GetAiSuffix(ai, interpFactor) + Utils.GetExt(outMode));
|
int frames = IOUtils.GetAmountOfFiles(current.framesFolder, false, "*.png");
|
||||||
int frames = IOUtils.GetAmountOfFiles(currentFramesPath, false, "*.png");
|
int targetFrameCount = frames * current.interpFactor;
|
||||||
int targetFrameCount = frames * interpFactor;
|
|
||||||
GetProgressByFrameAmount(interpFramesDir, targetFrameCount);
|
GetProgressByFrameAmount(interpFramesDir, targetFrameCount);
|
||||||
if (canceled) return;
|
if (canceled) return;
|
||||||
Program.mainForm.SetStatus("Running AI...");
|
Program.mainForm.SetStatus("Running AI...");
|
||||||
await RunAi(interpFramesDir, targetFrameCount, tilesize, ai);
|
await RunAi(interpFramesDir, targetFrameCount, current.tilesize, current.ai);
|
||||||
if (canceled) return;
|
if (canceled) return;
|
||||||
Program.mainForm.SetProgress(100);
|
Program.mainForm.SetProgress(100);
|
||||||
if(!currentlyUsingAutoEnc)
|
if(!currentlyUsingAutoEnc)
|
||||||
await CreateVideo.Export(interpFramesDir, nextOutPath, outMode);
|
await CreateVideo.Export(interpFramesDir, current.outFilename, current.outMode);
|
||||||
IOUtils.ReverseRenaming(AiProcess.filenameMap, true); // Get timestamps back
|
IOUtils.ReverseRenaming(AiProcess.filenameMap, true); // Get timestamps back
|
||||||
Cleanup(interpFramesDir);
|
Cleanup(interpFramesDir);
|
||||||
Program.mainForm.SetWorking(false);
|
Program.mainForm.SetWorking(false);
|
||||||
@@ -103,7 +85,7 @@ namespace Flowframes
|
|||||||
if (Config.GetBool("scnDetect"))
|
if (Config.GetBool("scnDetect"))
|
||||||
{
|
{
|
||||||
Program.mainForm.SetStatus("Extracting scenes from video...");
|
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);
|
await Task.Delay(10);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -112,7 +94,7 @@ namespace Flowframes
|
|||||||
|
|
||||||
if (extractAudio)
|
if (extractAudio)
|
||||||
{
|
{
|
||||||
string audioFile = Path.Combine(currentTempDir, "audio.m4a");
|
string audioFile = Path.Combine(current.tempFolder, "audio.m4a");
|
||||||
if (audioFile != null && !File.Exists(audioFile))
|
if (audioFile != null && !File.Exists(audioFile))
|
||||||
await FFmpegCommands.ExtractAudio(inPath, audioFile);
|
await FFmpegCommands.ExtractAudio(inPath, audioFile);
|
||||||
}
|
}
|
||||||
@@ -131,8 +113,8 @@ namespace Flowframes
|
|||||||
{
|
{
|
||||||
if (canceled) return;
|
if (canceled) return;
|
||||||
|
|
||||||
int extractedFrames = IOUtils.GetAmountOfFiles(currentFramesPath, false, "*.png");
|
int extractedFrames = IOUtils.GetAmountOfFiles(current.framesFolder, false, "*.png");
|
||||||
if (!Directory.Exists(currentFramesPath) || currentInputFrameCount <= 0 || extractedFrames < 2)
|
if (!Directory.Exists(current.framesFolder) || currentInputFrameCount <= 0 || extractedFrames < 2)
|
||||||
{
|
{
|
||||||
if(extractedFrames == 1)
|
if(extractedFrames == 1)
|
||||||
Cancel("Only a single frame was extracted from your input file!\n\nPossibly your input is an image, not a video?");
|
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)
|
if (Config.GetInt("dedupMode") == 1)
|
||||||
await MagickDedupe.Run(currentFramesPath);
|
await MagickDedupe.Run(current.framesFolder);
|
||||||
else
|
else
|
||||||
MagickDedupe.ClearCache();
|
MagickDedupe.ClearCache();
|
||||||
|
|
||||||
if (canceled) return;
|
if (canceled) return;
|
||||||
|
|
||||||
bool useTimestamps = Config.GetInt("timingMode") == 1; // TODO: Auto-Disable timestamps if input frames are sequential, not timestamped
|
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;
|
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)
|
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))
|
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
|
else
|
||||||
currentlyUsingAutoEnc = false;
|
currentlyUsingAutoEnc = false;
|
||||||
|
|
||||||
@@ -167,16 +149,16 @@ namespace Flowframes
|
|||||||
List<Task> tasks = new List<Task>();
|
List<Task> tasks = new List<Task>();
|
||||||
|
|
||||||
if (ai.aiName == Networks.dainNcnn.aiName)
|
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)
|
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)
|
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)
|
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)
|
if (currentlyUsingAutoEnc)
|
||||||
{
|
{
|
||||||
@@ -220,7 +202,7 @@ namespace Flowframes
|
|||||||
Program.mainForm.SetStatus("Canceled.");
|
Program.mainForm.SetStatus("Canceled.");
|
||||||
Program.mainForm.SetProgress(0);
|
Program.mainForm.SetProgress(0);
|
||||||
if (Config.GetInt("processingMode") == 0 && !Config.GetBool("keepTempFolder"))
|
if (Config.GetInt("processingMode") == 0 && !Config.GetBool("keepTempFolder"))
|
||||||
IOUtils.TryDeleteIfExists(currentTempDir);
|
IOUtils.TryDeleteIfExists(current.tempFolder);
|
||||||
Program.mainForm.SetWorking(false);
|
Program.mainForm.SetWorking(false);
|
||||||
Program.mainForm.SetTab("interpolation");
|
Program.mainForm.SetTab("interpolation");
|
||||||
if(!Logger.GetLastLine().Contains("Canceled interpolation."))
|
if(!Logger.GetLastLine().Contains("Canceled interpolation."))
|
||||||
@@ -236,8 +218,8 @@ namespace Flowframes
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (Config.GetBool("keepFrames"))
|
if (Config.GetBool("keepFrames"))
|
||||||
IOUtils.Copy(interpFramesDir, Path.Combine(currentTempDir.GetParentDir(), Path.GetFileName(currentTempDir).Replace("-temp", "-interpframes")));
|
IOUtils.Copy(interpFramesDir, Path.Combine(current.tempFolder.GetParentDir(), Path.GetFileName(current.tempFolder).Replace("-temp", "-interpframes")));
|
||||||
Directory.Delete(currentTempDir, true);
|
Directory.Delete(current.tempFolder, true);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -16,23 +16,23 @@ namespace Flowframes.Main
|
|||||||
{
|
{
|
||||||
public enum Step { ExtractScnChanges, ExtractFrames, Interpolate, CreateVid, Reset }
|
public enum Step { ExtractScnChanges, ExtractFrames, Interpolate, CreateVid, Reset }
|
||||||
|
|
||||||
public static string currentInPath;
|
//public static string current.inPath;
|
||||||
public static string currentOutPath;
|
//public static string currentOutPath;
|
||||||
public static string currentInterpFramesDir;
|
//public static string current.interpFolder;
|
||||||
public static AI currentAi;
|
//public static AI currentAi;
|
||||||
public static OutMode currentOutMode;
|
//public static OutMode currentOutMode;
|
||||||
|
|
||||||
public static async Task Run(string step)
|
public static async Task Run(string step)
|
||||||
{
|
{
|
||||||
canceled = false;
|
canceled = false;
|
||||||
Program.mainForm.SetWorking(true);
|
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 (step.Contains("Extract Scene Changes"))
|
||||||
{
|
{
|
||||||
if (!currentInputIsFrames) // Input is video - extract frames first
|
if (!current.inputIsFrames) // Input is video - extract frames first
|
||||||
await ExtractSceneChanges();
|
await ExtractSceneChanges();
|
||||||
else
|
else
|
||||||
InterpolateUtils.ShowMessage("Scene changes can only be extracted from videos, not frames!", "Error");
|
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 (step.Contains("Extract Frames"))
|
||||||
{
|
{
|
||||||
if (!currentInputIsFrames) // Input is video - extract frames first
|
if (!current.inputIsFrames) // Input is video - extract frames first
|
||||||
await ExtractVideoFrames();
|
await ExtractVideoFrames();
|
||||||
else
|
else
|
||||||
await FFmpegCommands.ImportImages(currentInPath, currentFramesPath);
|
await FFmpegCommands.ImportImages(current.inPath, current.framesFolder);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (step.Contains("Run Interpolation"))
|
if (step.Contains("Run Interpolation"))
|
||||||
@@ -59,44 +59,22 @@ namespace Flowframes.Main
|
|||||||
Logger.Log("Done running this step.");
|
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()
|
public static async Task ExtractSceneChanges()
|
||||||
{
|
{
|
||||||
string scenesPath = Path.Combine(currentTempDir, Paths.scenesDir);
|
string scenesPath = Path.Combine(current.tempFolder, Paths.scenesDir);
|
||||||
if (!IOUtils.TryDeleteIfExists(scenesPath))
|
if (!IOUtils.TryDeleteIfExists(scenesPath))
|
||||||
{
|
{
|
||||||
InterpolateUtils.ShowMessage("Failed to delete existing scenes folder - Make sure no file is opened in another program!", "Error");
|
InterpolateUtils.ShowMessage("Failed to delete existing scenes folder - Make sure no file is opened in another program!", "Error");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Program.mainForm.SetStatus("Extracting scenes from video...");
|
Program.mainForm.SetStatus("Extracting scenes from video...");
|
||||||
await FFmpegCommands.ExtractSceneChanges(currentInPath, scenesPath);
|
await FFmpegCommands.ExtractSceneChanges(current.inPath, scenesPath);
|
||||||
await Task.Delay(10);
|
await Task.Delay(10);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async Task ExtractVideoFrames()
|
public static async Task ExtractVideoFrames()
|
||||||
{
|
{
|
||||||
currentFramesPath = Path.Combine(currentTempDir, Paths.framesDir);
|
if (!IOUtils.TryDeleteIfExists(current.framesFolder))
|
||||||
if (!IOUtils.TryDeleteIfExists(currentFramesPath))
|
|
||||||
{
|
{
|
||||||
InterpolateUtils.ShowMessage("Failed to delete existing frames folder - Make sure no file is opened in another program!", "Error");
|
InterpolateUtils.ShowMessage("Failed to delete existing frames folder - Make sure no file is opened in another program!", "Error");
|
||||||
return;
|
return;
|
||||||
@@ -105,20 +83,20 @@ namespace Flowframes.Main
|
|||||||
AiProcess.filenameMap.Clear();
|
AiProcess.filenameMap.Clear();
|
||||||
bool extractAudio = true;
|
bool extractAudio = true;
|
||||||
Program.mainForm.SetStatus("Extracting frames from video...");
|
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)
|
if (extractAudio)
|
||||||
{
|
{
|
||||||
string audioFile = Path.Combine(currentTempDir, "audio.m4a");
|
string audioFile = Path.Combine(current.tempFolder, "audio.m4a");
|
||||||
if (audioFile != null && !File.Exists(audioFile))
|
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)
|
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;
|
int newNum = Path.GetFileName(lastFrame).GetInt() + 1;
|
||||||
string newFilename = Path.Combine(lastFrame.GetParentDir(), newNum.ToString().PadLeft(Padding.inputFrames, '0') + ".png");
|
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);
|
File.Copy(firstFrame, newFilename);
|
||||||
Logger.Log("Copied loop frame.");
|
Logger.Log("Copied loop frame.");
|
||||||
}
|
}
|
||||||
@@ -126,44 +104,44 @@ namespace Flowframes.Main
|
|||||||
|
|
||||||
public static async Task DoInterpolate()
|
public static async Task DoInterpolate()
|
||||||
{
|
{
|
||||||
currentFramesPath = Path.Combine(currentTempDir, Paths.framesDir);
|
current.framesFolder = Path.Combine(current.tempFolder, Paths.framesDir);
|
||||||
if (!Directory.Exists(currentFramesPath) || IOUtils.GetAmountOfFiles(currentFramesPath, false, "*.png") < 2)
|
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");
|
InterpolateUtils.ShowMessage("There are no extracted frames that can be interpolated!\nDid you run the extraction step?", "Error");
|
||||||
return;
|
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");
|
InterpolateUtils.ShowMessage("Failed to delete existing frames folder - Make sure no file is opened in another program!", "Error");
|
||||||
return;
|
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.TryDeleteIfExists(ini);
|
||||||
|
|
||||||
IOUtils.ReverseRenaming(AiProcess.filenameMap, true); // Get timestamps back
|
IOUtils.ReverseRenaming(AiProcess.filenameMap, true); // Get timestamps back
|
||||||
lastInterpFactor = interpFactor;
|
|
||||||
|
|
||||||
if (Config.GetBool("sbsAllowAutoEnc"))
|
// TODO: Check if this works lol, remove if it does
|
||||||
nextOutPath = Path.Combine(currentOutPath, Path.GetFileNameWithoutExtension(currentInPath) + IOUtils.GetAiSuffix(currentAi, lastInterpFactor) + InterpolateUtils.GetExt(currentOutMode));
|
//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);
|
await PostProcessFrames(true);
|
||||||
|
|
||||||
int frames = IOUtils.GetAmountOfFiles(currentFramesPath, false, "*.png");
|
int frames = IOUtils.GetAmountOfFiles(current.framesFolder, false, "*.png");
|
||||||
int targetFrameCount = frames * lastInterpFactor;
|
int targetFrameCount = frames * current.interpFactor;
|
||||||
GetProgressByFrameAmount(currentInterpFramesDir, targetFrameCount);
|
GetProgressByFrameAmount(current.interpFolder, targetFrameCount);
|
||||||
if (canceled) return;
|
if (canceled) return;
|
||||||
Program.mainForm.SetStatus("Running AI...");
|
Program.mainForm.SetStatus("Running AI...");
|
||||||
int tilesize = currentAi.supportsTiling ? Config.GetInt($"tilesize_{currentAi.aiName}") : 512;
|
int tilesize = current.ai.supportsTiling ? Config.GetInt($"tilesize_{current.ai.aiName}") : 512;
|
||||||
await RunAi(currentInterpFramesDir, targetFrameCount, tilesize, currentAi, true);
|
await RunAi(current.interpFolder, targetFrameCount, tilesize, current.ai, true);
|
||||||
Program.mainForm.SetProgress(0);
|
Program.mainForm.SetProgress(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async Task CreateOutputVid()
|
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]))
|
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 " +
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
currentOutMode = Program.mainForm.GetBatchEntry().outMode;
|
string outPath = Path.Combine(current.outPath, Path.GetFileNameWithoutExtension(current.inPath) + IOUtils.GetAiSuffix(current.ai, current.interpFactor) + InterpolateUtils.GetExt(current.outMode));
|
||||||
string outPath = Path.Combine(currentOutPath, Path.GetFileNameWithoutExtension(currentInPath) + IOUtils.GetAiSuffix(currentAi, lastInterpFactor) + InterpolateUtils.GetExt(currentOutMode));
|
await CreateVideo.Export(current.interpFolder, outPath, current.outMode);
|
||||||
await CreateVideo.Export(currentInterpFramesDir, outPath, currentOutMode);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async Task Reset()
|
public static async Task Reset()
|
||||||
{
|
{
|
||||||
Cleanup(currentInterpFramesDir, true);
|
Cleanup(current.interpFolder, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ namespace Flowframes.Main
|
|||||||
|
|
||||||
float generousTime = ((AiProcess.processTime.ElapsedMilliseconds - AiProcess.lastStartupTimeMs) / 1000f);
|
float generousTime = ((AiProcess.processTime.ElapsedMilliseconds - AiProcess.lastStartupTimeMs) / 1000f);
|
||||||
float fps = (float)frames / generousTime;
|
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");
|
string fpsOut = fps.ToString("0.00");
|
||||||
|
|
||||||
float secondsPerFrame = generousTime / (float)frames;
|
float secondsPerFrame = generousTime / (float)frames;
|
||||||
@@ -50,7 +50,7 @@ namespace Flowframes.Main
|
|||||||
|
|
||||||
try
|
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
|
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);
|
Image img = IOUtils.GetImage(latestFramePath);
|
||||||
@@ -204,7 +204,7 @@ namespace Flowframes.Main
|
|||||||
|
|
||||||
public static bool CheckDeleteOldTempFolder ()
|
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");
|
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();
|
i.Cancel();
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ namespace Flowframes
|
|||||||
public static string lastInputPath;
|
public static string lastInputPath;
|
||||||
public static bool lastInputPathIsSsd;
|
public static bool lastInputPathIsSsd;
|
||||||
|
|
||||||
public static Queue<BatchEntry> batchQueue = new Queue<BatchEntry>();
|
public static Queue<InterpSettings> batchQueue = new Queue<InterpSettings>();
|
||||||
|
|
||||||
[STAThread]
|
[STAThread]
|
||||||
static void Main()
|
static void Main()
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ namespace Flowframes.UI
|
|||||||
fpsStr = fps.ToString();
|
fpsStr = fps.ToString();
|
||||||
fpsInTbox.Text = fpsStr;
|
fpsInTbox.Text = fpsStr;
|
||||||
}
|
}
|
||||||
Interpolate.SetFps(fps);
|
//Interpolate.SetFps(fps);
|
||||||
Program.lastInputPathIsSsd = OSUtils.DriveIsSSD(path);
|
Program.lastInputPathIsSsd = OSUtils.DriveIsSSD(path);
|
||||||
if (!Program.lastInputPathIsSsd)
|
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.");
|
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.");
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ namespace Flowframes.UI
|
|||||||
string outPath = Path.ChangeExtension(videoPath, null) + "-extracted";
|
string outPath = Path.ChangeExtension(videoPath, null) + "-extracted";
|
||||||
Program.mainForm.SetWorking(true);
|
Program.mainForm.SetWorking(true);
|
||||||
await FFmpegCommands.VideoToFrames(videoPath, Path.Combine(outPath, Paths.framesDir), false, false, false);
|
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)
|
if (withAudio)
|
||||||
await FFmpegCommands.ExtractAudio(videoPath, Path.Combine(outPath, "audio"));
|
await FFmpegCommands.ExtractAudio(videoPath, Path.Combine(outPath, "audio"));
|
||||||
Program.mainForm.SetWorking(false);
|
Program.mainForm.SetWorking(false);
|
||||||
|
|||||||
Reference in New Issue
Block a user