mirror of
https://github.com/n00mkrad/flowframes.git
synced 2025-12-16 16:37:48 +01:00
Semi-fixed CAIN exe, fixed JPEG frames, finished VFR deduping, more
This commit is contained in:
@@ -34,9 +34,9 @@ namespace Flowframes
|
||||
ffmpeg.StartInfo.FileName = "cmd.exe";
|
||||
ffmpeg.StartInfo.Arguments = "/C cd /D \"" + GetAvDir() + "\" & ffmpeg.exe -hide_banner -loglevel warning -y -stats " + args;
|
||||
if(logMode != LogMode.Hidden) Logger.Log("Running ffmpeg...", false);
|
||||
Logger.Log("cmd.exe " + ffmpeg.StartInfo.Arguments, true);
|
||||
ffmpeg.OutputDataReceived += new DataReceivedEventHandler(OutputHandler);
|
||||
ffmpeg.ErrorDataReceived += new DataReceivedEventHandler(OutputHandler);
|
||||
Logger.Log("cmd.exe " + ffmpeg.StartInfo.Arguments, true, false, "ffmpeg.txt");
|
||||
ffmpeg.OutputDataReceived += new DataReceivedEventHandler(FfmpegOutputHandler);
|
||||
ffmpeg.ErrorDataReceived += new DataReceivedEventHandler(FfmpegOutputHandler);
|
||||
ffmpeg.Start();
|
||||
ffmpeg.BeginOutputReadLine();
|
||||
ffmpeg.BeginErrorReadLine();
|
||||
@@ -45,12 +45,13 @@ namespace Flowframes
|
||||
Logger.Log("Done running ffmpeg.", true);
|
||||
}
|
||||
|
||||
static void OutputHandler(object sendingProcess, DataReceivedEventArgs outLine)
|
||||
static void FfmpegOutputHandler(object sendingProcess, DataReceivedEventArgs outLine)
|
||||
{
|
||||
lastOutputFfmpeg = lastOutputFfmpeg + outLine.Data + "\n";
|
||||
bool hidden = currentLogMode == LogMode.Hidden;
|
||||
bool replaceLastLine = currentLogMode == LogMode.OnlyLastLine;
|
||||
Logger.Log(outLine.Data, hidden, replaceLastLine, "ffmpeg.txt");
|
||||
string trimmedLine = outLine.Data.Remove("q=-0.0").Remove("size=N/A").Remove("bitrate=N/A").TrimWhitespaces();
|
||||
Logger.Log(trimmedLine, hidden, replaceLastLine, "ffmpeg.txt");
|
||||
}
|
||||
|
||||
public static string GetFfmpegOutput (string args)
|
||||
@@ -70,7 +71,7 @@ namespace Flowframes
|
||||
{
|
||||
Process ffprobe = OSUtils.NewProcess(true);
|
||||
ffprobe.StartInfo.Arguments = $"/C cd /D {GetAvDir().Wrap()} & ffprobe.exe {args}";
|
||||
Logger.Log("cmd.exe " + ffprobe.StartInfo.Arguments, true);
|
||||
Logger.Log("cmd.exe " + ffprobe.StartInfo.Arguments, true, false, "ffmpeg.txt");
|
||||
ffprobe.Start();
|
||||
ffprobe.WaitForExit();
|
||||
string output = ffprobe.StandardOutput.ReadToEnd();
|
||||
@@ -87,7 +88,7 @@ namespace Flowframes
|
||||
lastProcess = gifski;
|
||||
gifski.StartInfo.Arguments = $"/C cd /D {GetAvDir().Wrap()} & gifski.exe {args}";
|
||||
Logger.Log("Running gifski...");
|
||||
Logger.Log("cmd.exe " + gifski.StartInfo.Arguments, true);
|
||||
Logger.Log("cmd.exe " + gifski.StartInfo.Arguments, true, false, "ffmpeg.txt");
|
||||
gifski.OutputDataReceived += new DataReceivedEventHandler(OutputHandlerGifski);
|
||||
gifski.ErrorDataReceived += new DataReceivedEventHandler(OutputHandlerGifski);
|
||||
gifski.Start();
|
||||
|
||||
@@ -13,6 +13,9 @@ namespace Flowframes
|
||||
static string divisionFilter = "\"crop = trunc(iw / 2) * 2:trunc(ih / 2) * 2\"";
|
||||
static string pngComprArg = "-compression_level 3";
|
||||
|
||||
static string mpDecDef = "\"mpdecimate\"";
|
||||
static string mpDecAggr = "\"mpdecimate=hi=64*32:lo=64*32:frac=0.1\"";
|
||||
|
||||
public static async Task VideoToFrames(string inputFile, string frameFolderPath, bool deDupe, bool delSrc)
|
||||
{
|
||||
await VideoToFrames(inputFile, frameFolderPath, deDupe, delSrc, new Size());
|
||||
@@ -24,8 +27,12 @@ namespace Flowframes
|
||||
if (size.Width > 1 && size.Height > 1) sizeStr = $"-s {size.Width}x{size.Height}";
|
||||
if (!Directory.Exists(frameFolderPath))
|
||||
Directory.CreateDirectory(frameFolderPath);
|
||||
string args = $"-i {inputFile.Wrap()} {pngComprArg} -vsync 0 -pix_fmt rgb24 -vf {divisionFilter} {sizeStr} \"{frameFolderPath}/%08d.png\"";
|
||||
if(deDupe) args = $"-i {inputFile.Wrap()} -copyts -r 1000 {pngComprArg} -vsync 0 -frame_pts true -vf mpdecimate,{divisionFilter} {sizeStr} \"{frameFolderPath}/%08d.png\"";
|
||||
string args = $"-i {inputFile.Wrap()} {pngComprArg} -vsync 0 -pix_fmt rgb24 -copyts -r 1000 -frame_pts true -vf {divisionFilter} {sizeStr} \"{frameFolderPath}/%08d.png\"";
|
||||
if (deDupe)
|
||||
{
|
||||
string mpStr = (Config.GetInt("mpdecimateMode") == 0) ? mpDecDef : mpDecAggr;
|
||||
args = $"-i {inputFile.Wrap()} -copyts -r 1000 {pngComprArg} -vsync 0 -pix_fmt rgb24 -frame_pts true -vf {mpStr},{divisionFilter} {sizeStr} \"{frameFolderPath}/%08d.png\"";
|
||||
}
|
||||
await AvProcess.RunFfmpeg(args, AvProcess.LogMode.OnlyLastLine);
|
||||
await Task.Delay(1);
|
||||
if (delSrc)
|
||||
@@ -47,8 +54,7 @@ namespace Flowframes
|
||||
{
|
||||
Logger.Log($"Encoding MP4 video with CRF {crf}...");
|
||||
int nums = IOUtils.GetFilenameCounterLength(Directory.GetFiles(inputDir, $"*.{imgFormat}")[0], prefix);
|
||||
string enc = "libx264";
|
||||
if (useH265) enc = "libx265";
|
||||
string enc = useH265 ? "libx265" : "libx264";
|
||||
string loopStr = "";
|
||||
if (looptimes > 0) loopStr = $"-stream_loop {looptimes}";
|
||||
string args = $" {loopStr} -framerate {fps.ToString().Replace(",",".")} -i \"{inputDir}\\{prefix}%0{nums}d.{imgFormat}\" -c:v {enc} -crf {crf} {videoEncArgs} -threads {Config.GetInt("ffEncThreads")} -c:a copy {outPath.Wrap()}";
|
||||
@@ -57,6 +63,16 @@ namespace Flowframes
|
||||
DeleteSource(inputDir);
|
||||
}
|
||||
|
||||
public static async Task FramesToMp4Vfr(string framesFile, string outPath, bool useH265, int crf, float fps, int looptimes = -1)
|
||||
{
|
||||
Logger.Log($"Encoding MP4 video with CRF {crf}...");
|
||||
string enc = useH265 ? "libx265" : "libx264";
|
||||
string loopStr = "";
|
||||
if (looptimes > 0) loopStr = $"-stream_loop {looptimes}";
|
||||
string args = $" {loopStr} -vsync 1 -f concat -safe 0 -i {framesFile.Wrap()} -r {fps.ToString().Replace(",", ".")} -c:v {enc} -crf {crf} {videoEncArgs} -threads {Config.GetInt("ffEncThreads")} -c:a copy {outPath.Wrap()}";
|
||||
await AvProcess.RunFfmpeg(args, AvProcess.LogMode.OnlyLastLine);
|
||||
}
|
||||
|
||||
public static async Task ConvertFramerate (string inputPath, string outPath, bool useH265, int crf, float newFps, bool delSrc = false)
|
||||
{
|
||||
Logger.Log($"Changing video frame rate...");
|
||||
|
||||
@@ -10,108 +10,137 @@ using System.Windows.Forms;
|
||||
|
||||
namespace Flowframes
|
||||
{
|
||||
public static class ExtensionMethods
|
||||
public static class ExtensionMethods
|
||||
{
|
||||
public static string TrimNumbers(this string s, bool allowDotComma = false)
|
||||
{
|
||||
if(!allowDotComma)
|
||||
s = Regex.Replace(s, "[^0-9]", "");
|
||||
else
|
||||
s = Regex.Replace(s, "[^.,0-9]", "");
|
||||
return s.Trim();
|
||||
}
|
||||
|
||||
public static int GetInt(this TextBox textbox)
|
||||
{
|
||||
return GetInt(textbox.Text);
|
||||
}
|
||||
|
||||
public static int GetInt(this ComboBox combobox)
|
||||
{
|
||||
return GetInt(combobox.Text);
|
||||
}
|
||||
|
||||
public static int GetInt (this string str)
|
||||
public static string TrimNumbers(this string s, bool allowDotComma = false)
|
||||
{
|
||||
if (str.Length < 1 || str == null)
|
||||
return 0;
|
||||
try { return int.Parse(str.TrimNumbers()); }
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.Log("Failed to parse \"" + str + "\" to int: " + e, true);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (!allowDotComma)
|
||||
s = Regex.Replace(s, "[^0-9]", "");
|
||||
else
|
||||
s = Regex.Replace(s, "[^.,0-9]", "");
|
||||
return s.Trim();
|
||||
}
|
||||
|
||||
public static float GetFloat(this TextBox textbox)
|
||||
{
|
||||
return GetFloat(textbox.Text);
|
||||
}
|
||||
|
||||
public static float GetFloat(this ComboBox combobox)
|
||||
{
|
||||
return GetFloat(combobox.Text);
|
||||
}
|
||||
|
||||
public static float GetFloat (this string str)
|
||||
public static int GetInt(this TextBox textbox)
|
||||
{
|
||||
if (str.Length < 1 || str == null)
|
||||
return 0f;
|
||||
string num = str.TrimNumbers(true).Replace(",", ".");
|
||||
float value;
|
||||
float.TryParse(num, NumberStyles.Any, CultureInfo.InvariantCulture, out value);
|
||||
return value;
|
||||
}
|
||||
return GetInt(textbox.Text);
|
||||
}
|
||||
|
||||
public static string Wrap(this string path, bool addSpaceFront = false, bool addSpaceEnd = false)
|
||||
{
|
||||
string s = "\"" + path + "\"";
|
||||
if (addSpaceFront)
|
||||
s = " " + s;
|
||||
if (addSpaceEnd)
|
||||
s = s + " ";
|
||||
return s;
|
||||
}
|
||||
|
||||
public static string GetParentDir(this string path)
|
||||
{
|
||||
return Directory.GetParent(path).FullName;
|
||||
}
|
||||
|
||||
public static int RoundToInt(this float f)
|
||||
{
|
||||
return (int)Math.Round(f);
|
||||
}
|
||||
|
||||
public static int Clamp(this int i, int min, int max)
|
||||
{
|
||||
if (i < min)
|
||||
i = min;
|
||||
if (i > max)
|
||||
i = max;
|
||||
return i;
|
||||
}
|
||||
|
||||
public static string[] SplitIntoLines (this string str)
|
||||
public static int GetInt(this ComboBox combobox)
|
||||
{
|
||||
return Regex.Split(str, "\r\n|\r|\n");
|
||||
}
|
||||
return GetInt(combobox.Text);
|
||||
}
|
||||
|
||||
public static string Trunc (this string value, int maxChars)
|
||||
{
|
||||
return value.Length <= maxChars ? value : value.Substring(0, maxChars) + "…";
|
||||
}
|
||||
|
||||
public static string StripBadChars (this string str)
|
||||
public static int GetInt(this string str)
|
||||
{
|
||||
string outStr = Regex.Replace(str, @"[^\u0020-\u007E]", string.Empty);
|
||||
outStr = outStr.Replace("(", "").Replace(")", "").Replace("[", "").Replace("]", "").Replace("{", "").Replace("}", "").Replace("%", "");
|
||||
return outStr;
|
||||
}
|
||||
if (str.Length < 1 || str == null)
|
||||
return 0;
|
||||
try { return int.Parse(str.TrimNumbers()); }
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.Log("Failed to parse \"" + str + "\" to int: " + e, true);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public static string StripNumbers (this string str)
|
||||
public static float GetFloat(this TextBox textbox)
|
||||
{
|
||||
return new string(str.Where(c => c != '-' && (c < '0' || c > '9')).ToArray());
|
||||
}
|
||||
}
|
||||
return GetFloat(textbox.Text);
|
||||
}
|
||||
|
||||
public static float GetFloat(this ComboBox combobox)
|
||||
{
|
||||
return GetFloat(combobox.Text);
|
||||
}
|
||||
|
||||
public static float GetFloat(this string str)
|
||||
{
|
||||
if (str.Length < 1 || str == null)
|
||||
return 0f;
|
||||
string num = str.TrimNumbers(true).Replace(",", ".");
|
||||
float value;
|
||||
float.TryParse(num, NumberStyles.Any, CultureInfo.InvariantCulture, out value);
|
||||
return value;
|
||||
}
|
||||
|
||||
public static string Wrap(this string path, bool addSpaceFront = false, bool addSpaceEnd = false)
|
||||
{
|
||||
string s = "\"" + path + "\"";
|
||||
if (addSpaceFront)
|
||||
s = " " + s;
|
||||
if (addSpaceEnd)
|
||||
s = s + " ";
|
||||
return s;
|
||||
}
|
||||
|
||||
public static string GetParentDir(this string path)
|
||||
{
|
||||
return Directory.GetParent(path).FullName;
|
||||
}
|
||||
|
||||
public static int RoundToInt(this float f)
|
||||
{
|
||||
return (int)Math.Round(f);
|
||||
}
|
||||
|
||||
public static int Clamp(this int i, int min, int max)
|
||||
{
|
||||
if (i < min)
|
||||
i = min;
|
||||
if (i > max)
|
||||
i = max;
|
||||
return i;
|
||||
}
|
||||
|
||||
public static string[] SplitIntoLines(this string str)
|
||||
{
|
||||
return Regex.Split(str, "\r\n|\r|\n");
|
||||
}
|
||||
|
||||
public static string Trunc(this string value, int maxChars)
|
||||
{
|
||||
return value.Length <= maxChars ? value : value.Substring(0, maxChars) + "…";
|
||||
}
|
||||
|
||||
public static string StripBadChars(this string str)
|
||||
{
|
||||
string outStr = Regex.Replace(str, @"[^\u0020-\u007E]", string.Empty);
|
||||
outStr = outStr.Replace("(", "").Replace(")", "").Replace("[", "").Replace("]", "").Replace("{", "").Replace("}", "").Replace("%", "");
|
||||
return outStr;
|
||||
}
|
||||
|
||||
public static string StripNumbers(this string str)
|
||||
{
|
||||
return new string(str.Where(c => c != '-' && (c < '0' || c > '9')).ToArray());
|
||||
}
|
||||
|
||||
public static string Remove(this string str, string stringToRemove)
|
||||
{
|
||||
if (str == null || stringToRemove == null)
|
||||
return str;
|
||||
return str.Replace(stringToRemove, "");
|
||||
}
|
||||
|
||||
public static string TrimWhitespaces(this string str)
|
||||
{
|
||||
if (str == null) return str;
|
||||
var newString = new StringBuilder();
|
||||
bool previousIsWhitespace = false;
|
||||
for (int i = 0; i < str.Length; i++)
|
||||
{
|
||||
if (Char.IsWhiteSpace(str[i]))
|
||||
{
|
||||
if (previousIsWhitespace)
|
||||
continue;
|
||||
previousIsWhitespace = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
previousIsWhitespace = false;
|
||||
}
|
||||
newString.Append(str[i]);
|
||||
}
|
||||
return newString.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -128,7 +128,7 @@ namespace Flowframes
|
||||
outputTbox.Text = inputTbox.Text.Trim().GetParentDir();
|
||||
string path = inputTbox.Text.Trim();
|
||||
Program.lastInputPath = path;
|
||||
string fpsStr = "Not Found.";
|
||||
string fpsStr = "Not Found";
|
||||
float fps = IOUtils.GetFpsFolderOrVideo(path);
|
||||
if(fps > 0)
|
||||
{
|
||||
|
||||
180
Code/Forms/SettingsForm.Designer.cs
generated
180
Code/Forms/SettingsForm.Designer.cs
generated
@@ -47,9 +47,16 @@
|
||||
this.deleteLogsOnStartup = new System.Windows.Forms.CheckBox();
|
||||
this.label11 = new System.Windows.Forms.Label();
|
||||
this.tabListPage2 = new Cyotek.Windows.Forms.TabListPage();
|
||||
this.mpDedupePanel = new System.Windows.Forms.Panel();
|
||||
this.panel13 = new System.Windows.Forms.Panel();
|
||||
this.mpdecimateMode = new System.Windows.Forms.ComboBox();
|
||||
this.label42 = new System.Windows.Forms.Label();
|
||||
this.magickDedupePanel = new System.Windows.Forms.Panel();
|
||||
this.panel3 = new System.Windows.Forms.Panel();
|
||||
this.dedupThresh = new System.Windows.Forms.ComboBox();
|
||||
this.label4 = new System.Windows.Forms.Label();
|
||||
this.timingMode = new System.Windows.Forms.ComboBox();
|
||||
this.label35 = new System.Windows.Forms.Label();
|
||||
this.panel3 = new System.Windows.Forms.Panel();
|
||||
this.label27 = new System.Windows.Forms.Label();
|
||||
this.jpegInterps = new System.Windows.Forms.CheckBox();
|
||||
this.label25 = new System.Windows.Forms.Label();
|
||||
@@ -57,8 +64,6 @@
|
||||
this.label24 = new System.Windows.Forms.Label();
|
||||
this.enableLoop = new System.Windows.Forms.CheckBox();
|
||||
this.label15 = new System.Windows.Forms.Label();
|
||||
this.label4 = new System.Windows.Forms.Label();
|
||||
this.dedupThresh = new System.Windows.Forms.ComboBox();
|
||||
this.dedupMode = new System.Windows.Forms.ComboBox();
|
||||
this.label2 = new System.Windows.Forms.Label();
|
||||
this.enableAudio = new System.Windows.Forms.CheckBox();
|
||||
@@ -120,6 +125,8 @@
|
||||
this.settingsTabList.SuspendLayout();
|
||||
this.generalTab.SuspendLayout();
|
||||
this.tabListPage2.SuspendLayout();
|
||||
this.mpDedupePanel.SuspendLayout();
|
||||
this.magickDedupePanel.SuspendLayout();
|
||||
this.aiOptsPage.SuspendLayout();
|
||||
this.vidExportTab.SuspendLayout();
|
||||
this.debugTab.SuspendLayout();
|
||||
@@ -330,9 +337,10 @@
|
||||
// tabListPage2
|
||||
//
|
||||
this.tabListPage2.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(48)))), ((int)(((byte)(48)))), ((int)(((byte)(48)))));
|
||||
this.tabListPage2.Controls.Add(this.mpDedupePanel);
|
||||
this.tabListPage2.Controls.Add(this.magickDedupePanel);
|
||||
this.tabListPage2.Controls.Add(this.timingMode);
|
||||
this.tabListPage2.Controls.Add(this.label35);
|
||||
this.tabListPage2.Controls.Add(this.panel3);
|
||||
this.tabListPage2.Controls.Add(this.label27);
|
||||
this.tabListPage2.Controls.Add(this.jpegInterps);
|
||||
this.tabListPage2.Controls.Add(this.label25);
|
||||
@@ -340,8 +348,6 @@
|
||||
this.tabListPage2.Controls.Add(this.label24);
|
||||
this.tabListPage2.Controls.Add(this.enableLoop);
|
||||
this.tabListPage2.Controls.Add(this.label15);
|
||||
this.tabListPage2.Controls.Add(this.label4);
|
||||
this.tabListPage2.Controls.Add(this.dedupThresh);
|
||||
this.tabListPage2.Controls.Add(this.dedupMode);
|
||||
this.tabListPage2.Controls.Add(this.label2);
|
||||
this.tabListPage2.Controls.Add(this.enableAudio);
|
||||
@@ -350,6 +356,104 @@
|
||||
this.tabListPage2.Size = new System.Drawing.Size(762, 419);
|
||||
this.tabListPage2.Text = "Interpolation";
|
||||
//
|
||||
// mpDedupePanel
|
||||
//
|
||||
this.mpDedupePanel.Controls.Add(this.panel13);
|
||||
this.mpDedupePanel.Controls.Add(this.mpdecimateMode);
|
||||
this.mpDedupePanel.Controls.Add(this.label42);
|
||||
this.mpDedupePanel.Location = new System.Drawing.Point(536, 67);
|
||||
this.mpDedupePanel.Margin = new System.Windows.Forms.Padding(0);
|
||||
this.mpDedupePanel.Name = "mpDedupePanel";
|
||||
this.mpDedupePanel.Size = new System.Drawing.Size(218, 21);
|
||||
this.mpDedupePanel.TabIndex = 61;
|
||||
//
|
||||
// panel13
|
||||
//
|
||||
this.panel13.BackgroundImage = global::Flowframes.Properties.Resources.baseline_create_white_18dp_semiTransparent;
|
||||
this.panel13.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Zoom;
|
||||
this.panel13.Location = new System.Drawing.Point(164, 0);
|
||||
this.panel13.Name = "panel13";
|
||||
this.panel13.Size = new System.Drawing.Size(21, 21);
|
||||
this.panel13.TabIndex = 57;
|
||||
this.toolTip1.SetToolTip(this.panel13, "Allows custom input.");
|
||||
//
|
||||
// mpdecimateMode
|
||||
//
|
||||
this.mpdecimateMode.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(64)))), ((int)(((byte)(64)))));
|
||||
this.mpdecimateMode.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
|
||||
this.mpdecimateMode.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
|
||||
this.mpdecimateMode.ForeColor = System.Drawing.Color.White;
|
||||
this.mpdecimateMode.FormattingEnabled = true;
|
||||
this.mpdecimateMode.Items.AddRange(new object[] {
|
||||
"Normal",
|
||||
"Aggressive"});
|
||||
this.mpdecimateMode.Location = new System.Drawing.Point(46, 0);
|
||||
this.mpdecimateMode.Margin = new System.Windows.Forms.Padding(3, 3, 8, 3);
|
||||
this.mpdecimateMode.Name = "mpdecimateMode";
|
||||
this.mpdecimateMode.Size = new System.Drawing.Size(107, 21);
|
||||
this.mpdecimateMode.TabIndex = 28;
|
||||
//
|
||||
// label42
|
||||
//
|
||||
this.label42.AutoSize = true;
|
||||
this.label42.Location = new System.Drawing.Point(3, 3);
|
||||
this.label42.Margin = new System.Windows.Forms.Padding(3);
|
||||
this.label42.Name = "label42";
|
||||
this.label42.Size = new System.Drawing.Size(37, 13);
|
||||
this.label42.TabIndex = 29;
|
||||
this.label42.Text = "Mode:";
|
||||
//
|
||||
// magickDedupePanel
|
||||
//
|
||||
this.magickDedupePanel.Controls.Add(this.panel3);
|
||||
this.magickDedupePanel.Controls.Add(this.dedupThresh);
|
||||
this.magickDedupePanel.Controls.Add(this.label4);
|
||||
this.magickDedupePanel.Location = new System.Drawing.Point(536, 67);
|
||||
this.magickDedupePanel.Margin = new System.Windows.Forms.Padding(0);
|
||||
this.magickDedupePanel.Name = "magickDedupePanel";
|
||||
this.magickDedupePanel.Size = new System.Drawing.Size(218, 21);
|
||||
this.magickDedupePanel.TabIndex = 60;
|
||||
//
|
||||
// panel3
|
||||
//
|
||||
this.panel3.BackgroundImage = global::Flowframes.Properties.Resources.baseline_create_white_18dp_semiTransparent;
|
||||
this.panel3.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Zoom;
|
||||
this.panel3.Location = new System.Drawing.Point(164, 0);
|
||||
this.panel3.Name = "panel3";
|
||||
this.panel3.Size = new System.Drawing.Size(21, 21);
|
||||
this.panel3.TabIndex = 57;
|
||||
this.toolTip1.SetToolTip(this.panel3, "Allows custom input.");
|
||||
//
|
||||
// dedupThresh
|
||||
//
|
||||
this.dedupThresh.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(64)))), ((int)(((byte)(64)))));
|
||||
this.dedupThresh.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
|
||||
this.dedupThresh.ForeColor = System.Drawing.Color.White;
|
||||
this.dedupThresh.FormattingEnabled = true;
|
||||
this.dedupThresh.Items.AddRange(new object[] {
|
||||
"1%",
|
||||
"2%",
|
||||
"3%",
|
||||
"4%",
|
||||
"5%",
|
||||
"10%"});
|
||||
this.dedupThresh.Location = new System.Drawing.Point(66, 0);
|
||||
this.dedupThresh.Margin = new System.Windows.Forms.Padding(3, 3, 8, 3);
|
||||
this.dedupThresh.Name = "dedupThresh";
|
||||
this.dedupThresh.Size = new System.Drawing.Size(87, 21);
|
||||
this.dedupThresh.TabIndex = 28;
|
||||
this.dedupThresh.Leave += new System.EventHandler(this.dedupThresh_Leave);
|
||||
//
|
||||
// label4
|
||||
//
|
||||
this.label4.AutoSize = true;
|
||||
this.label4.Location = new System.Drawing.Point(3, 3);
|
||||
this.label4.Margin = new System.Windows.Forms.Padding(3);
|
||||
this.label4.Name = "label4";
|
||||
this.label4.Size = new System.Drawing.Size(57, 13);
|
||||
this.label4.TabIndex = 29;
|
||||
this.label4.Text = "Threshold:";
|
||||
//
|
||||
// timingMode
|
||||
//
|
||||
this.timingMode.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(64)))), ((int)(((byte)(64)))));
|
||||
@@ -359,10 +463,10 @@
|
||||
this.timingMode.FormattingEnabled = true;
|
||||
this.timingMode.Items.AddRange(new object[] {
|
||||
"Disabled",
|
||||
"Re-Duplicate Deleted Frames"});
|
||||
"Use Timecodes From Source Video"});
|
||||
this.timingMode.Location = new System.Drawing.Point(280, 97);
|
||||
this.timingMode.Name = "timingMode";
|
||||
this.timingMode.Size = new System.Drawing.Size(200, 21);
|
||||
this.timingMode.Size = new System.Drawing.Size(250, 21);
|
||||
this.timingMode.TabIndex = 59;
|
||||
//
|
||||
// label35
|
||||
@@ -371,19 +475,9 @@
|
||||
this.label35.Location = new System.Drawing.Point(10, 100);
|
||||
this.label35.Margin = new System.Windows.Forms.Padding(10, 10, 10, 7);
|
||||
this.label35.Name = "label35";
|
||||
this.label35.Size = new System.Drawing.Size(122, 13);
|
||||
this.label35.Size = new System.Drawing.Size(197, 13);
|
||||
this.label35.TabIndex = 58;
|
||||
this.label35.Text = "Fix Video Timing/Length";
|
||||
//
|
||||
// panel3
|
||||
//
|
||||
this.panel3.BackgroundImage = global::Flowframes.Properties.Resources.baseline_create_white_18dp_semiTransparent;
|
||||
this.panel3.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Zoom;
|
||||
this.panel3.Location = new System.Drawing.Point(647, 67);
|
||||
this.panel3.Name = "panel3";
|
||||
this.panel3.Size = new System.Drawing.Size(21, 21);
|
||||
this.panel3.TabIndex = 57;
|
||||
this.toolTip1.SetToolTip(this.panel3, "Allows custom input.");
|
||||
this.label35.Text = "Frame Handling Mode For Deduplication";
|
||||
//
|
||||
// label27
|
||||
//
|
||||
@@ -457,36 +551,6 @@
|
||||
this.label15.TabIndex = 30;
|
||||
this.label15.Text = "Animation Loop (Copy First Frame As Last)";
|
||||
//
|
||||
// label4
|
||||
//
|
||||
this.label4.AutoSize = true;
|
||||
this.label4.Location = new System.Drawing.Point(486, 70);
|
||||
this.label4.Margin = new System.Windows.Forms.Padding(3);
|
||||
this.label4.Name = "label4";
|
||||
this.label4.Size = new System.Drawing.Size(57, 13);
|
||||
this.label4.TabIndex = 29;
|
||||
this.label4.Text = "Threshold:";
|
||||
//
|
||||
// dedupThresh
|
||||
//
|
||||
this.dedupThresh.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(64)))), ((int)(((byte)(64)))));
|
||||
this.dedupThresh.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
|
||||
this.dedupThresh.ForeColor = System.Drawing.Color.White;
|
||||
this.dedupThresh.FormattingEnabled = true;
|
||||
this.dedupThresh.Items.AddRange(new object[] {
|
||||
"1%",
|
||||
"2%",
|
||||
"3%",
|
||||
"4%",
|
||||
"5%",
|
||||
"10%"});
|
||||
this.dedupThresh.Location = new System.Drawing.Point(549, 67);
|
||||
this.dedupThresh.Margin = new System.Windows.Forms.Padding(3, 3, 8, 3);
|
||||
this.dedupThresh.Name = "dedupThresh";
|
||||
this.dedupThresh.Size = new System.Drawing.Size(87, 21);
|
||||
this.dedupThresh.TabIndex = 28;
|
||||
this.dedupThresh.Leave += new System.EventHandler(this.dedupThresh_Leave);
|
||||
//
|
||||
// dedupMode
|
||||
//
|
||||
this.dedupMode.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(64)))), ((int)(((byte)(64)))));
|
||||
@@ -496,12 +560,13 @@
|
||||
this.dedupMode.FormattingEnabled = true;
|
||||
this.dedupMode.Items.AddRange(new object[] {
|
||||
"Disabled",
|
||||
"Always Enabled",
|
||||
"Detect Automatically For Each Video"});
|
||||
"Remove After Extraction - Slow, Accurate",
|
||||
"Remove During Extraction - Fast, Less Accurate"});
|
||||
this.dedupMode.Location = new System.Drawing.Point(280, 67);
|
||||
this.dedupMode.Name = "dedupMode";
|
||||
this.dedupMode.Size = new System.Drawing.Size(200, 21);
|
||||
this.dedupMode.Size = new System.Drawing.Size(250, 21);
|
||||
this.dedupMode.TabIndex = 27;
|
||||
this.dedupMode.SelectedIndexChanged += new System.EventHandler(this.dedupMode_SelectedIndexChanged);
|
||||
//
|
||||
// label2
|
||||
//
|
||||
@@ -1210,6 +1275,10 @@
|
||||
this.generalTab.PerformLayout();
|
||||
this.tabListPage2.ResumeLayout(false);
|
||||
this.tabListPage2.PerformLayout();
|
||||
this.mpDedupePanel.ResumeLayout(false);
|
||||
this.mpDedupePanel.PerformLayout();
|
||||
this.magickDedupePanel.ResumeLayout(false);
|
||||
this.magickDedupePanel.PerformLayout();
|
||||
this.aiOptsPage.ResumeLayout(false);
|
||||
this.aiOptsPage.PerformLayout();
|
||||
this.vidExportTab.ResumeLayout(false);
|
||||
@@ -1310,5 +1379,10 @@
|
||||
private System.Windows.Forms.Label label41;
|
||||
private System.Windows.Forms.CheckBox ffprobeCountFrames;
|
||||
private System.Windows.Forms.Label label40;
|
||||
private System.Windows.Forms.Panel mpDedupePanel;
|
||||
private System.Windows.Forms.Panel panel13;
|
||||
private System.Windows.Forms.ComboBox mpdecimateMode;
|
||||
private System.Windows.Forms.Label label42;
|
||||
private System.Windows.Forms.Panel magickDedupePanel;
|
||||
}
|
||||
}
|
||||
@@ -51,6 +51,7 @@ namespace Flowframes.Forms
|
||||
// Interpolation
|
||||
ConfigParser.SaveGuiElement(enableAudio);
|
||||
ConfigParser.SaveComboxIndex(dedupMode);
|
||||
ConfigParser.SaveComboxIndex(mpdecimateMode);
|
||||
ConfigParser.SaveGuiElement(dedupThresh, ConfigParser.StringMode.Float);
|
||||
ConfigParser.SaveComboxIndex(timingMode);
|
||||
ConfigParser.SaveGuiElement(enableLoop);
|
||||
@@ -87,6 +88,7 @@ namespace Flowframes.Forms
|
||||
// Interpolation
|
||||
ConfigParser.LoadGuiElement(enableAudio);
|
||||
ConfigParser.LoadComboxIndex(dedupMode);
|
||||
ConfigParser.LoadComboxIndex(mpdecimateMode);
|
||||
ConfigParser.LoadGuiElement(dedupThresh, "%");
|
||||
ConfigParser.LoadComboxIndex(timingMode);
|
||||
ConfigParser.LoadGuiElement(enableLoop);
|
||||
@@ -137,5 +139,11 @@ namespace Flowframes.Forms
|
||||
if (initialized && cmdDebugMode.SelectedIndex == 2)
|
||||
MessageBox.Show("If you enable this, you need to close the CMD window manually after the process has finished, otherwise processing will be paused!", "Notice");
|
||||
}
|
||||
|
||||
private void dedupMode_SelectedIndexChanged(object sender, EventArgs e)
|
||||
{
|
||||
magickDedupePanel.Visible = dedupMode.SelectedIndex == 1;
|
||||
mpDedupePanel.Visible = dedupMode.SelectedIndex == 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -89,7 +89,7 @@ namespace Flowframes.IO
|
||||
if (key == "torchGpus") return WriteDefault("torchGpus", "0");
|
||||
if (key == "keepTempFolder") return WriteDefault("keepTempFolder", "False");
|
||||
if (key == "deleteLogsOnStartup") return WriteDefault("deleteLogsOnStartup", "True");
|
||||
if (key == "autoDedupFrames") return WriteDefault("autoDedupFrames", "10");
|
||||
if (key == "autoDedupFrames") return WriteDefault("autoDedupFrames", "15");
|
||||
if (key == "minOutVidLength") return WriteDefault("minOutVidLength", "2");
|
||||
if (key == "mp4Enc") return WriteDefault("mp4Enc", "0");
|
||||
if (key == "h264Crf") return WriteDefault("h264Crf", "20");
|
||||
|
||||
@@ -31,16 +31,6 @@ namespace Flowframes.IO
|
||||
packages.Add(Packages.licenses);
|
||||
}
|
||||
|
||||
public static FlowPackage GetPkg(string friendlyName)
|
||||
{
|
||||
foreach (FlowPackage pkg in packages)
|
||||
{
|
||||
if (pkg.friendlyName == friendlyName)
|
||||
return pkg;
|
||||
}
|
||||
return new FlowPackage();
|
||||
}
|
||||
|
||||
static Stopwatch sw = new Stopwatch();
|
||||
public static async Task DownloadAndInstall(string filename, bool showDialog = true)
|
||||
{
|
||||
@@ -112,25 +102,6 @@ namespace Flowframes.IO
|
||||
}
|
||||
}
|
||||
|
||||
public static bool IsInstalled(FlowPackage pkg)
|
||||
{
|
||||
return IsInstalled(pkg.fileName);
|
||||
}
|
||||
|
||||
public static bool IsInstalled(string filename)
|
||||
{
|
||||
Logger.Log("PkgInstaller.IsInstalled - Checking for pkg with filename " + filename, true);
|
||||
string path = Path.Combine(Paths.GetPkgPath(), Path.GetFileNameWithoutExtension(filename));
|
||||
return Directory.Exists(path);
|
||||
}
|
||||
|
||||
|
||||
public static bool IsAiAvailable(AI ai, bool msg = true)
|
||||
{
|
||||
Logger.Log("PkgInstaller.IsAiAvailable - Checking for AI " + ai.aiName, true);
|
||||
return IsInstalled(ai.pkg);
|
||||
}
|
||||
|
||||
static void Print(string s, bool replaceLastLine = false)
|
||||
{
|
||||
if (installerForm != null)
|
||||
|
||||
52
Code/IO/PkgUtils.cs
Normal file
52
Code/IO/PkgUtils.cs
Normal file
@@ -0,0 +1,52 @@
|
||||
using Flowframes.Data;
|
||||
using Flowframes.Forms;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace Flowframes.IO
|
||||
{
|
||||
class PkgUtils
|
||||
{
|
||||
public static FlowPackage GetPkg(string friendlyNameOrFilename)
|
||||
{
|
||||
foreach (FlowPackage pkg in PkgInstaller.packages)
|
||||
{
|
||||
if (pkg.fileName == friendlyNameOrFilename)
|
||||
return pkg;
|
||||
if (pkg.friendlyName == friendlyNameOrFilename)
|
||||
return pkg;
|
||||
}
|
||||
return new FlowPackage();
|
||||
}
|
||||
|
||||
public static string GetPkgFolder (FlowPackage pkg)
|
||||
{
|
||||
return Path.Combine(Paths.GetPkgPath(), Path.GetFileNameWithoutExtension(pkg.fileName));
|
||||
}
|
||||
|
||||
public static bool IsInstalled(FlowPackage pkg)
|
||||
{
|
||||
string path = GetPkgFolder(pkg);
|
||||
return (Directory.Exists(path) && IOUtils.GetAmountOfFiles(path, true) > 0);
|
||||
}
|
||||
|
||||
public static bool IsUpToDate(FlowPackage pkg, int minVersion)
|
||||
{
|
||||
return (GetVersion(pkg) >= minVersion);
|
||||
}
|
||||
|
||||
public static int GetVersion (FlowPackage pkg)
|
||||
{
|
||||
string versionFilePath = Path.Combine(GetPkgFolder(pkg), "ver.ini");
|
||||
return IOUtils.ReadLines(versionFilePath)[0].Split('#')[0].GetInt();
|
||||
}
|
||||
|
||||
public static bool IsAiAvailable(AI ai, bool msg = true)
|
||||
{
|
||||
Logger.Log("PkgInstaller.IsAiAvailable - Checking for AI " + ai.aiName, true);
|
||||
return IsInstalled(ai.pkg);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -143,8 +143,9 @@ namespace Flowframes.Magick
|
||||
|
||||
Program.mainForm.SetProgress((int)Math.Round(((float)i / framePaths.Length) * 100f));
|
||||
await Task.Delay(10);
|
||||
if (Interpolate.cancelled) return;
|
||||
|
||||
if(!testRun && skipIfNoDupes && !hasEncounteredAnyDupes && i >= skipAfterNoDupesFrames)
|
||||
if (!testRun && skipIfNoDupes && !hasEncounteredAnyDupes && i >= skipAfterNoDupesFrames)
|
||||
{
|
||||
skipped = true;
|
||||
break;
|
||||
@@ -166,8 +167,11 @@ namespace Flowframes.Magick
|
||||
Logger.Log($"[FrameDedup]{testStr} Done. Kept {statsFramesKept} frames, deleted {statsFramesDeleted} frames.", false, true);
|
||||
}
|
||||
|
||||
RenameCounterDir(path, "png");
|
||||
ZeroPadDir(path, ext, 8);
|
||||
if (statsFramesKept <= 0)
|
||||
Interpolate.Cancel("No frames were left after de-duplication.");
|
||||
|
||||
//RenameCounterDir(path, "png");
|
||||
//ZeroPadDir(path, ext, 8);
|
||||
}
|
||||
|
||||
static Dictionary<int, int> UpdateDupeDict(Dictionary<int, int> dict, int frame, int amount)
|
||||
@@ -315,7 +319,7 @@ namespace Flowframes.Magick
|
||||
}
|
||||
}
|
||||
|
||||
static void ZeroPadDir(string path, string ext, int targetLength, bool recursive = false)
|
||||
public static void ZeroPadDir(string path, string ext, int targetLength, bool recursive = false)
|
||||
{
|
||||
FileInfo[] files;
|
||||
if (recursive)
|
||||
|
||||
@@ -7,8 +7,6 @@ using Flowframes.OS;
|
||||
using Flowframes.UI;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
@@ -29,8 +27,8 @@ namespace Flowframes.Main
|
||||
return;
|
||||
}
|
||||
await Task.Delay(10);
|
||||
if(Config.GetInt("timingMode") == 1)
|
||||
await MagickDedupe.Reduplicate(path);
|
||||
//if(Config.GetInt("timingMode") == 1)
|
||||
// await MagickDedupe.Reduplicate(path);
|
||||
Program.mainForm.SetStatus("Creating output video from frames...");
|
||||
try
|
||||
{
|
||||
@@ -76,7 +74,15 @@ namespace Flowframes.Main
|
||||
bool h265 = Config.GetInt("mp4Enc") == 1;
|
||||
int crf = h265 ? Config.GetInt("h265Crf") : Config.GetInt("h264Crf");
|
||||
|
||||
await FFmpegCommands.FramesToMp4(framesPath, outPath, h265, crf, fps, "", false, looptimes, ext);
|
||||
if (Config.GetInt("timingMode") == 1 && Config.GetInt("dedupMode") != 0)
|
||||
{
|
||||
string vfrFile = Path.Combine(framesPath.GetParentDir(), "vfr.ini");
|
||||
await FFmpegCommands.FramesToMp4Vfr(vfrFile, outPath, h265, crf, fps, looptimes);
|
||||
}
|
||||
else
|
||||
{
|
||||
await FFmpegCommands.FramesToMp4(framesPath, outPath, h265, crf, fps, "", false, looptimes, ext);
|
||||
}
|
||||
await MergeAudio(i.lastInputPath, outPath);
|
||||
|
||||
if (changeFps > 0)
|
||||
|
||||
@@ -62,9 +62,7 @@ namespace Flowframes
|
||||
if (cancelled) return;
|
||||
sw.Restart();
|
||||
await Task.Delay(10);
|
||||
if (Config.GetBool("vfrDedupe"))
|
||||
VfrDedupe.CreateTimecodeFile(framesPath, Config.GetBool("enableLoop"), interpFactor);
|
||||
await MagickDedupe.Run(framesPath);
|
||||
await PostProcessFrames();
|
||||
if (cancelled) return;
|
||||
string interpFramesDir = Path.Combine(currentTempDir, "frames-interpolated");
|
||||
string outPath = Path.Combine(outDir, Path.GetFileNameWithoutExtension(inPath) + IOUtils.GetAiSuffix(ai, interpFactor) + Utils.GetExt(outMode));
|
||||
@@ -96,11 +94,11 @@ namespace Flowframes
|
||||
float factor = (float)maxHeight / resolution.Height;
|
||||
int width = (resolution.Width * factor).RoundToInt();
|
||||
Logger.Log($"Video is bigger than the maximum - Downscaling to {width}x{maxHeight}.");
|
||||
await FFmpegCommands.VideoToFrames(inPath, outPath, Config.GetBool("vfrDedupe"), false, new Size(width, maxHeight));
|
||||
await FFmpegCommands.VideoToFrames(inPath, outPath, Config.GetInt("dedupMode") == 2, false, new Size(width, maxHeight));
|
||||
}
|
||||
else
|
||||
{
|
||||
await FFmpegCommands.VideoToFrames(inPath, outPath, Config.GetBool("vfrDedupe"), false);
|
||||
await FFmpegCommands.VideoToFrames(inPath, outPath, Config.GetInt("dedupMode") == 2, false);
|
||||
}
|
||||
/*
|
||||
if (AvProcess.lastOutputFfmpeg.ToLower().Contains("invalid"))
|
||||
@@ -115,17 +113,37 @@ namespace Flowframes
|
||||
if (audioFile != null && !File.Exists(audioFile))
|
||||
await FFmpegCommands.ExtractAudio(inPath, audioFile);
|
||||
}
|
||||
if (!cancelled && Config.GetBool("enableLoop"))
|
||||
if (!cancelled && Config.GetBool("enableLoop") && Config.GetInt("timingMode") != 1)
|
||||
{
|
||||
string lastFrame = IOUtils.GetHighestFrameNumPath(outPath);
|
||||
int newNum = Path.GetFileName(lastFrame).GetInt() + 1;
|
||||
string newFilename = Path.Combine(lastFrame.GetParentDir(), newNum.ToString().PadLeft(8, '0') + ".png");
|
||||
string firstFrame = Path.Combine(lastFrame.GetParentDir(), 1.ToString().PadLeft(8, '0') + ".png");
|
||||
string firstFrame = new DirectoryInfo(outPath).GetFiles("*.png")[0].FullName;
|
||||
File.Copy(firstFrame, newFilename);
|
||||
Logger.Log("Copied loop frame.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static bool firstFrameFix;
|
||||
static async Task PostProcessFrames ()
|
||||
{
|
||||
if (Config.GetInt("dedupMode") == 1)
|
||||
await MagickDedupe.Run(framesPath);
|
||||
|
||||
//await Task.Delay(10000);
|
||||
|
||||
if (Config.GetInt("timingMode") == 1 && Config.GetInt("dedupMode") != 0)
|
||||
await VfrDedupe.CreateTimecodeFile(framesPath, Config.GetBool("enableLoop"), interpFactor, firstFrameFix);
|
||||
|
||||
if (cancelled) return;
|
||||
MagickDedupe.RenameCounterDir(framesPath, "png");
|
||||
MagickDedupe.ZeroPadDir(framesPath, "png", 8);
|
||||
|
||||
if (firstFrameFix)
|
||||
IOUtils.TryCopy(new DirectoryInfo(framesPath).GetFiles("*.png")[0].FullName, Path.Combine(framesPath, "00000000.png"), true);
|
||||
}
|
||||
|
||||
static async Task RunAi(string outpath, int targetFrames, int tilesize, AI ai)
|
||||
{
|
||||
Directory.CreateDirectory(outpath);
|
||||
|
||||
@@ -26,7 +26,7 @@ namespace Flowframes.Main
|
||||
int percent = (int)Math.Round(((float)frames / target) * 100f);
|
||||
Program.mainForm.SetProgress(percent);
|
||||
|
||||
float generousTime = ((AiProcess.processTime.ElapsedMilliseconds - 1000) / 1000f);
|
||||
float generousTime = ((AiProcess.processTime.ElapsedMilliseconds - 2000) / 1000f);
|
||||
float fps = (float)frames / generousTime;
|
||||
string fpsIn = (fps / Interpolate.interpFactor).ToString("0.00");
|
||||
string fpsOut = fps.ToString("0.00");
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
using System;
|
||||
using Flowframes.IO;
|
||||
using Flowframes.UI;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
@@ -9,10 +12,15 @@ namespace Flowframes.Main
|
||||
{
|
||||
class VfrDedupe
|
||||
{
|
||||
public static void CreateTimecodeFile(string framesPath, bool loopEnabled, int interpFactor)
|
||||
public static async Task CreateTimecodeFile(string framesPath, bool loopEnabled, int interpFactor, bool firstFrameFix)
|
||||
{
|
||||
Logger.Log("Generating timecodes...");
|
||||
|
||||
FileInfo[] frameFiles = new DirectoryInfo(framesPath).GetFiles("*.png");
|
||||
string vfrFile = Path.Combine(framesPath.GetParentDir(), "vfr.ini");
|
||||
string fileContent = "";
|
||||
|
||||
string interpPath = framesPath.Replace(@"\", "/") + "-interpolated";
|
||||
|
||||
int lastFrameDuration = 1;
|
||||
|
||||
@@ -20,13 +28,15 @@ namespace Flowframes.Main
|
||||
int totalFileCount = 1;
|
||||
for (int i = 0; i < (frameFiles.Length - 1); i++)
|
||||
{
|
||||
if (Interpolate.cancelled) return;
|
||||
|
||||
string filename1 = frameFiles[i].Name;
|
||||
string filename2 = frameFiles[i + 1].Name;
|
||||
//Logger.Log("durationTotal = " + Path.GetFileNameWithoutExtension(filename2).GetInt() + " - " + Path.GetFileNameWithoutExtension(filename1).GetInt());
|
||||
|
||||
int durationTotal = Path.GetFileNameWithoutExtension(filename2).GetInt() - Path.GetFileNameWithoutExtension(filename1).GetInt();
|
||||
lastFrameDuration = durationTotal;
|
||||
float durationPerInterpFrame = (float)durationTotal / interpFactor;
|
||||
//Logger.Log("durationPerInterpFrame = " + durationPerInterpFrame);
|
||||
|
||||
int interpolatedFrameCount = interpFactor;
|
||||
|
||||
// If loop is enabled, account for the extra frame added to the end for loop continuity
|
||||
@@ -36,10 +46,34 @@ namespace Flowframes.Main
|
||||
// Generate frames file lines
|
||||
for (int frm = 0; frm < interpolatedFrameCount; frm++)
|
||||
{
|
||||
string durationStr = (durationPerInterpFrame / 1000f).ToString("0.00000").Replace(",", ".");
|
||||
File.AppendAllText(vfrFile, $"{totalFileCount.ToString().PadLeft(8, '0')}.png\nduration {durationStr}\n");
|
||||
string durationStr = ((durationPerInterpFrame / 1000f) * 1).ToString("0.00000").Replace(",", ".");
|
||||
fileContent += $"file '{interpPath}/{totalFileCount.ToString().PadLeft(8, '0')}.png'\nduration {durationStr}\n";
|
||||
totalFileCount++;
|
||||
}
|
||||
|
||||
if((i+1) % 50 == 0)
|
||||
{
|
||||
Logger.Log($"Generating timecodes... {i + 1}/{frameFiles.Length}", false, true);
|
||||
await Task.Delay(1);
|
||||
}
|
||||
}
|
||||
|
||||
File.WriteAllText(vfrFile, fileContent);
|
||||
Logger.Log($"Generating timecodes... Done.", false, true);
|
||||
|
||||
if (firstFrameFix)
|
||||
{
|
||||
string[] lines = IOUtils.ReadLines(vfrFile);
|
||||
File.WriteAllText(vfrFile, lines[0].Replace("00000001.png", "00000000.png"));
|
||||
File.AppendAllText(vfrFile, "\n" + lines[1] + "\n");
|
||||
File.AppendAllLines(vfrFile, lines);
|
||||
}
|
||||
|
||||
if (Config.GetBool("enableLoop"))
|
||||
{
|
||||
int lastFileNumber = frameFiles.Last().Name.GetInt();
|
||||
lastFileNumber += lastFrameDuration;
|
||||
File.Copy(frameFiles.First().FullName, Path.Combine(frameFiles.First().FullName.GetParentDir(), lastFileNumber + ".png"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,9 +20,10 @@ namespace Flowframes
|
||||
public static Process currentAiProcess;
|
||||
public static Stopwatch processTime = new Stopwatch();
|
||||
|
||||
static void Init (Process proc, string ext = "png")
|
||||
static void Init (Process proc, string defaultExt = "png", bool needsFirstFrameFix = false)
|
||||
{
|
||||
InterpolateUtils.lastExt = ext;
|
||||
Interpolate.firstFrameFix = needsFirstFrameFix;
|
||||
InterpolateUtils.lastExt = defaultExt;
|
||||
if (Config.GetBool("jpegInterps")) InterpolateUtils.lastExt = "jpg";
|
||||
processTime.Restart();
|
||||
currentAiProcess = proc;
|
||||
@@ -35,6 +36,7 @@ namespace Flowframes
|
||||
|
||||
string dainDir = Path.Combine(Paths.GetPkgPath(), Path.GetFileNameWithoutExtension(Packages.dainNcnn.fileName));
|
||||
Process dain = OSUtils.NewProcess(!OSUtils.ShowHiddenCmd());
|
||||
Init(dain);
|
||||
dain.StartInfo.Arguments = $"{OSUtils.GetHiddenCmdArg()} cd /D {dainDir.Wrap()} & dain-ncnn-vulkan.exe {args} -f {InterpolateUtils.lastExt}";
|
||||
Logger.Log("Running DAIN...", false);
|
||||
Logger.Log("cmd.exe " + dain.StartInfo.Arguments, true);
|
||||
@@ -43,7 +45,6 @@ namespace Flowframes
|
||||
dain.OutputDataReceived += (sender, outLine) => { LogOutput(outLine.Data, "dain-ncnn-log.txt"); };
|
||||
dain.ErrorDataReceived += (sender, outLine) => { LogOutput("[E] " + outLine.Data, "dain-ncnn-log.txt"); };
|
||||
}
|
||||
Init(dain);
|
||||
dain.Start();
|
||||
if (!OSUtils.ShowHiddenCmd())
|
||||
{
|
||||
@@ -96,6 +97,7 @@ namespace Flowframes
|
||||
string cainDir = Path.Combine(Paths.GetPkgPath(), Path.GetFileNameWithoutExtension(Packages.cainNcnn.fileName));
|
||||
string cainExe = "cain-ncnn-vulkan.exe";
|
||||
Process cain = OSUtils.NewProcess(!OSUtils.ShowHiddenCmd());
|
||||
Init(cain);
|
||||
cain.StartInfo.Arguments = $"{OSUtils.GetHiddenCmdArg()} cd /D {cainDir.Wrap()} & {cainExe} {args} -f {InterpolateUtils.lastExt}";
|
||||
Logger.Log("cmd.exe " + cain.StartInfo.Arguments, true);
|
||||
if (!OSUtils.ShowHiddenCmd())
|
||||
@@ -103,7 +105,6 @@ namespace Flowframes
|
||||
cain.OutputDataReceived += (sender, outLine) => { LogOutput(outLine.Data, "cain-ncnn-log.txt"); };
|
||||
cain.ErrorDataReceived += (sender, outLine) => { LogOutput("[E] " + outLine.Data, "cain-ncnn-log.txt"); };
|
||||
}
|
||||
Init(cain);
|
||||
cain.Start();
|
||||
if (!OSUtils.ShowHiddenCmd())
|
||||
{
|
||||
@@ -117,11 +118,12 @@ namespace Flowframes
|
||||
public static async Task RunRifeCuda(string framesPath, int interpFactor)
|
||||
{
|
||||
string script = "interp-parallel.py";
|
||||
if(Config.GetInt("rifeMode") == 0 || IOUtils.GetAmountOfFiles(framesPath, false) < 30)
|
||||
if(Config.GetInt("rifeMode") == 0 || IOUtils.GetAmountOfFiles(framesPath, false) < 10)
|
||||
script = "interp-basic.py";
|
||||
|
||||
string rifeDir = Path.Combine(Paths.GetPkgPath(), Path.GetFileNameWithoutExtension(Packages.rifeCuda.fileName));
|
||||
Process rifePy = OSUtils.NewProcess(!OSUtils.ShowHiddenCmd());
|
||||
Init(rifePy, "png", true);
|
||||
string args = $" --input {framesPath.Wrap()} --times {(int)Math.Log(interpFactor, 2)}";
|
||||
rifePy.StartInfo.Arguments = $"{OSUtils.GetHiddenCmdArg()} cd /D {rifeDir.Wrap()} & " +
|
||||
$"set CUDA_VISIBLE_DEVICES={Config.Get("torchGpus")} & {Python.GetPyCmd()} {script} {args} --imgformat {InterpolateUtils.lastExt}";
|
||||
@@ -132,7 +134,6 @@ namespace Flowframes
|
||||
rifePy.OutputDataReceived += (sender, outLine) => { LogOutput(outLine.Data, "rife-cuda-log.txt"); };
|
||||
rifePy.ErrorDataReceived += (sender, outLine) => { LogOutput("[E] " + outLine.Data, "rife-cuda-log.txt"); };
|
||||
}
|
||||
Init(rifePy);
|
||||
rifePy.Start();
|
||||
if (!OSUtils.ShowHiddenCmd())
|
||||
{
|
||||
|
||||
Binary file not shown.
@@ -100,8 +100,8 @@ def clear_buffer(user_args):
|
||||
if item is None:
|
||||
break
|
||||
if user_args.png:
|
||||
print('Writing {}/{:0>7d}.png'.format(interp_output_path, cnt))
|
||||
cv2.imwrite('{}/{:0>7d}.png'.format(interp_output_path, cnt), item[:, :, ::1])
|
||||
print('Writing {}/{:0>8d}.png'.format(interp_output_path, cnt))
|
||||
cv2.imwrite('{}/{:0>8d}.png'.format(interp_output_path, cnt), item[:, :, ::1])
|
||||
cnt += 1
|
||||
else:
|
||||
vid_out.write(item[:, :, ::-1])
|
||||
|
||||
Reference in New Issue
Block a user