mirror of
https://github.com/n00mkrad/flowframes.git
synced 2025-12-16 00:17:44 +01:00
New frame folder import code with rgb24, divisible res fix, and any->png enc
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
using Flowframes.IO;
|
||||
using Flowframes.Data;
|
||||
using Flowframes.IO;
|
||||
using System.Drawing;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
@@ -33,8 +34,7 @@ namespace Flowframes
|
||||
{
|
||||
if(!sceneDetect) Logger.Log("Extracting video frames using FFmpeg...");
|
||||
string sizeStr = (size.Width > 1 && size.Height > 1) ? $"-s {size.Width}x{size.Height}" : "";
|
||||
if (!Directory.Exists(frameFolderPath))
|
||||
Directory.CreateDirectory(frameFolderPath);
|
||||
IOUtils.CreateDir(frameFolderPath);
|
||||
string timecodeStr = timecodes ? "-copyts -r 1000 -frame_pts true" : "";
|
||||
string scnDetect = sceneDetect ? $"\"select='gt(scene,{Config.Get("scnDetectValue")})'\"," : "";
|
||||
string args = $"-i {inputFile.Wrap()} {pngComprArg} -vsync 0 -pix_fmt rgb24 {timecodeStr} -vf {scnDetect}{divisionFilter} {sizeStr} \"{frameFolderPath}/%08d.png\"";
|
||||
@@ -49,6 +49,23 @@ namespace Flowframes
|
||||
DeleteSource(inputFile);
|
||||
}
|
||||
|
||||
public static async Task ImportImages (string inpath, string outpath, bool delSrc = false, bool showLog = true)
|
||||
{
|
||||
if (showLog) Logger.Log("Importing images...");
|
||||
IOUtils.CreateDir(outpath);
|
||||
string concatFile = Path.Combine(Paths.GetDataPath(), "png-concat-temp.ini");
|
||||
string concatFileContent = "";
|
||||
foreach (string img in Directory.GetFiles(inpath))
|
||||
concatFileContent += $"file '{img.Replace(@"\", "/")}'\n";
|
||||
File.WriteAllText(concatFile, concatFileContent);
|
||||
|
||||
string args = $" -loglevel panic -f concat -safe 0 -i {concatFile.Wrap()} {pngComprArg} -pix_fmt rgb24 -vsync 0 -vf {divisionFilter} \"{outpath}/%{Padding.inputFrames}d.png\"";
|
||||
AvProcess.LogMode logMode = IOUtils.GetAmountOfFiles(inpath, false) > 50 ? AvProcess.LogMode.OnlyLastLine : AvProcess.LogMode.Hidden;
|
||||
await AvProcess.RunFfmpeg(args, logMode);
|
||||
if (delSrc)
|
||||
DeleteSource(inpath);
|
||||
}
|
||||
|
||||
public static async Task ExtractSingleFrame(string inputFile, int frameNum, bool hdr, bool delSrc)
|
||||
{
|
||||
string outPath = $"{inputFile}-frame{frameNum}.png";
|
||||
|
||||
14
Code/Data/Padding.cs
Normal file
14
Code/Data/Padding.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Flowframes.Data
|
||||
{
|
||||
class Padding
|
||||
{
|
||||
public const int inputFrames = 10;
|
||||
public const int timestampFrames = 10;
|
||||
}
|
||||
}
|
||||
@@ -170,6 +170,7 @@
|
||||
<Compile Include="Data\AI.cs" />
|
||||
<Compile Include="Data\BatchEntry.cs" />
|
||||
<Compile Include="Data\Networks.cs" />
|
||||
<Compile Include="Data\Padding.cs" />
|
||||
<Compile Include="Forms\BatchForm.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
|
||||
12
Code/Forms/SettingsForm.Designer.cs
generated
12
Code/Forms/SettingsForm.Designer.cs
generated
@@ -216,9 +216,9 @@
|
||||
this.tempDirBrowseBtn.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(64)))), ((int)(((byte)(64)))));
|
||||
this.tempDirBrowseBtn.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
|
||||
this.tempDirBrowseBtn.ForeColor = System.Drawing.Color.White;
|
||||
this.tempDirBrowseBtn.Location = new System.Drawing.Point(709, 66);
|
||||
this.tempDirBrowseBtn.Location = new System.Drawing.Point(704, 65);
|
||||
this.tempDirBrowseBtn.Name = "tempDirBrowseBtn";
|
||||
this.tempDirBrowseBtn.Size = new System.Drawing.Size(50, 23);
|
||||
this.tempDirBrowseBtn.Size = new System.Drawing.Size(55, 23);
|
||||
this.tempDirBrowseBtn.TabIndex = 70;
|
||||
this.tempDirBrowseBtn.Text = "Browse";
|
||||
this.tempDirBrowseBtn.UseVisualStyleBackColor = false;
|
||||
@@ -231,7 +231,7 @@
|
||||
this.tempDirCustom.Location = new System.Drawing.Point(486, 67);
|
||||
this.tempDirCustom.MinimumSize = new System.Drawing.Size(4, 21);
|
||||
this.tempDirCustom.Name = "tempDirCustom";
|
||||
this.tempDirCustom.Size = new System.Drawing.Size(217, 20);
|
||||
this.tempDirCustom.Size = new System.Drawing.Size(212, 20);
|
||||
this.tempDirCustom.TabIndex = 69;
|
||||
//
|
||||
// keepTempFolder
|
||||
@@ -544,7 +544,7 @@
|
||||
this.timingMode.ForeColor = System.Drawing.Color.White;
|
||||
this.timingMode.FormattingEnabled = true;
|
||||
this.timingMode.Items.AddRange(new object[] {
|
||||
"Disabled",
|
||||
"Disabled (Static)",
|
||||
"Use Timecodes From Source Video"});
|
||||
this.timingMode.Location = new System.Drawing.Point(280, 97);
|
||||
this.timingMode.Name = "timingMode";
|
||||
@@ -557,9 +557,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(197, 13);
|
||||
this.label35.Size = new System.Drawing.Size(117, 13);
|
||||
this.label35.TabIndex = 58;
|
||||
this.label35.Text = "Frame Handling Mode For Deduplication";
|
||||
this.label35.Text = "Dynamic Frame Timing ";
|
||||
//
|
||||
// label27
|
||||
//
|
||||
|
||||
@@ -515,5 +515,15 @@ namespace Flowframes.IO
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static bool CreateDir (string path) // Returns whether the dir already existed
|
||||
{
|
||||
if (!Directory.Exists(path))
|
||||
{
|
||||
Directory.CreateDirectory(path);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,7 +67,7 @@ namespace Flowframes
|
||||
if (!currentInputIsFrames) // Input is video - extract frames first
|
||||
await ExtractFrames(inPath, currentFramesPath);
|
||||
else
|
||||
IOUtils.Copy(inPath, currentFramesPath);
|
||||
await FFmpegCommands.ImportImages(inPath, currentFramesPath);
|
||||
if (canceled) return;
|
||||
sw.Restart();
|
||||
await Task.Delay(10);
|
||||
@@ -156,10 +156,12 @@ namespace Flowframes
|
||||
|
||||
if (canceled) return;
|
||||
|
||||
bool useTimestamps = Config.GetInt("timingMode") == 1; // TODO: Disable timestamps if input frames are sequential, not timestamped
|
||||
|
||||
if(sbsMode)
|
||||
await VfrDedupe.CreateTimecodeFiles(currentFramesPath, Config.GetBool("enableLoop"), firstFrameFix, -1);
|
||||
await VfrDedupe.CreateTimecodeFiles(currentFramesPath, Config.GetBool("enableLoop"), firstFrameFix, -1, useTimestamps);
|
||||
else
|
||||
await VfrDedupe.CreateTimecodeFiles(currentFramesPath, Config.GetBool("enableLoop"), firstFrameFix, lastInterpFactor);
|
||||
await VfrDedupe.CreateTimecodeFiles(currentFramesPath, Config.GetBool("enableLoop"), firstFrameFix, lastInterpFactor, useTimestamps);
|
||||
|
||||
if (canceled) return;
|
||||
|
||||
|
||||
@@ -13,18 +13,18 @@ namespace Flowframes.Main
|
||||
{
|
||||
class VfrDedupe
|
||||
{
|
||||
public static async Task CreateTimecodeFiles(string framesPath, bool loopEnabled, bool firstFrameFix, int times)
|
||||
public static async Task CreateTimecodeFiles(string framesPath, bool loopEnabled, bool firstFrameFix, int times, bool noTimestamps)
|
||||
{
|
||||
Logger.Log("Generating timecodes...");
|
||||
if(times <= 0)
|
||||
{
|
||||
await CreateTimecodeFile(framesPath, loopEnabled, 2, firstFrameFix);
|
||||
await CreateTimecodeFile(framesPath, loopEnabled, 4, firstFrameFix, true);
|
||||
await CreateTimecodeFile(framesPath, loopEnabled, 8, firstFrameFix, true);
|
||||
await CreateTimecodeFile(framesPath, loopEnabled, 2, firstFrameFix, false, noTimestamps);
|
||||
await CreateTimecodeFile(framesPath, loopEnabled, 4, firstFrameFix, true, noTimestamps);
|
||||
await CreateTimecodeFile(framesPath, loopEnabled, 8, firstFrameFix, true, noTimestamps);
|
||||
}
|
||||
else
|
||||
{
|
||||
await CreateTimecodeFile(framesPath, loopEnabled, times, firstFrameFix);
|
||||
await CreateTimecodeFile(framesPath, loopEnabled, times, firstFrameFix, false, noTimestamps);
|
||||
}
|
||||
frameFiles = null;
|
||||
Logger.Log($"Generating timecodes... Done.", false, true);
|
||||
@@ -32,7 +32,7 @@ namespace Flowframes.Main
|
||||
|
||||
static FileInfo[] frameFiles;
|
||||
|
||||
public static async Task CreateTimecodeFile(string framesPath, bool loopEnabled, int interpFactor, bool firstFrameFix, bool notFirstRun = false)
|
||||
public static async Task CreateTimecodeFile(string framesPath, bool loopEnabled, int interpFactor, bool firstFrameFix, bool notFirstRun, bool noTimestamps)
|
||||
{
|
||||
if (Interpolate.canceled) return;
|
||||
Logger.Log($"Generating timecodes for {interpFactor}x...", false, true);
|
||||
@@ -45,7 +45,7 @@ namespace Flowframes.Main
|
||||
string fileContent = "";
|
||||
|
||||
string scnFramesPath = Path.Combine(framesPath.GetParentDir(), Paths.scenesDir);
|
||||
string interpPath = Paths.interpDir; // framesPath.Replace(@"\", "/") + "-interpolated";
|
||||
string interpPath = Paths.interpDir;
|
||||
|
||||
List<string> sceneFrames = new List<string>();
|
||||
if (Directory.Exists(scnFramesPath))
|
||||
@@ -59,11 +59,15 @@ namespace Flowframes.Main
|
||||
{
|
||||
if (Interpolate.canceled) return;
|
||||
|
||||
string filename1 = frameFiles[i].Name;
|
||||
string filename2 = frameFiles[i + 1].Name;
|
||||
int durationTotal = 100; // Default for no timestamps in input filenames (divided by output fps later)
|
||||
|
||||
if (!noTimestamps) // Get timings from frame filenames
|
||||
{
|
||||
string filename1 = frameFiles[i].Name;
|
||||
string filename2 = frameFiles[i + 1].Name;
|
||||
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;
|
||||
|
||||
@@ -71,7 +75,6 @@ namespace Flowframes.Main
|
||||
|
||||
bool discardThisFrame = (sceneDetection && (i + 2) < frameFiles.Length && sceneFrames.Contains(frameFiles[i + 1].Name)); // i+2 is in scene detection folder, means i+1 is ugly interp frame
|
||||
|
||||
|
||||
// If loop is enabled, account for the extra frame added to the end for loop continuity
|
||||
if (loopEnabled && i == (frameFiles.Length - 2))
|
||||
interpFramesAmount = interpFramesAmount * 2;
|
||||
|
||||
Reference in New Issue
Block a user