mirror of
https://github.com/n00mkrad/flowframes.git
synced 2026-07-10 04:21:49 +02:00
Fixed AutoEncode getting stuck when using scn+magickdedup
This commit is contained in:
@@ -9,6 +9,7 @@ using ImageMagick;
|
||||
using Flowframes.OS;
|
||||
using Flowframes.Data;
|
||||
using System.Drawing;
|
||||
using Paths = Flowframes.IO.Paths;
|
||||
|
||||
namespace Flowframes.Magick
|
||||
{
|
||||
@@ -205,7 +206,7 @@ namespace Flowframes.Magick
|
||||
return bufferSize;
|
||||
}
|
||||
|
||||
public static async Task CreateDupesFileMpdecimate (string framesPath, int lastFrameNum)
|
||||
public static async Task CreateDupesFile (string framesPath, int lastFrameNum)
|
||||
{
|
||||
string infoFile = Path.Combine(framesPath.GetParentDir(), $"dupes.ini");
|
||||
string fileContent = "";
|
||||
@@ -221,6 +222,9 @@ namespace Flowframes.Magick
|
||||
int diff = frameNum2 - frameNum1;
|
||||
int dupes = diff - 1;
|
||||
|
||||
//if (File.Exists(Path.Combine(framesPath.GetParentDir(), Paths.scenesDir, frameFiles[i].Name)))
|
||||
// dupes = 0;
|
||||
|
||||
fileContent += $"{Path.GetFileNameWithoutExtension(frameFiles[i].Name)}:{dupes}\n";
|
||||
}
|
||||
|
||||
|
||||
@@ -32,85 +32,98 @@ namespace Flowframes.Main
|
||||
|
||||
public static async Task MainLoop(string interpFramesPath)
|
||||
{
|
||||
UpdateChunkAndBufferSizes();
|
||||
|
||||
interpFramesFolder = interpFramesPath;
|
||||
videoChunksFolder = Path.Combine(interpFramesPath.GetParentDir(), Paths.chunksDir);
|
||||
if (Interpolate.currentlyUsingAutoEnc)
|
||||
Directory.CreateDirectory(videoChunksFolder);
|
||||
|
||||
encodedFrameLines.Clear();
|
||||
unencodedFrameLines.Clear();
|
||||
|
||||
Logger.Log($"Starting AutoEncode MainLoop - Chunk Size: {chunkSize} Frames - Safety Buffer: {safetyBufferFrames} Frames", true);
|
||||
int videoIndex = 1;
|
||||
string encFile = Path.Combine(interpFramesPath.GetParentDir(), $"vfr-{Interpolate.current.interpFactor}x.ini");
|
||||
interpFramesLines = IOUtils.ReadLines(encFile).Select(x => x.Split('/').Last().Remove("'")).ToArray(); // Array with frame filenames
|
||||
|
||||
while (!Interpolate.canceled && GetInterpFramesAmount() < 2)
|
||||
await Task.Delay(1000);
|
||||
|
||||
while (HasWorkToDo()) // Loop while proc is running and not all frames have been encoded
|
||||
try
|
||||
{
|
||||
if (Interpolate.canceled) return;
|
||||
UpdateChunkAndBufferSizes();
|
||||
|
||||
if (paused)
|
||||
{
|
||||
await Task.Delay(100);
|
||||
continue;
|
||||
}
|
||||
|
||||
//Logger.Log($"{unencodedFrameLines.Count} unencoded frame lines, {encodedFrameLines.Count} encoded frame lines", true, false, "ffmpeg");
|
||||
interpFramesFolder = interpFramesPath;
|
||||
videoChunksFolder = Path.Combine(interpFramesPath.GetParentDir(), Paths.chunksDir);
|
||||
if (Interpolate.currentlyUsingAutoEnc)
|
||||
Directory.CreateDirectory(videoChunksFolder);
|
||||
|
||||
encodedFrameLines.Clear();
|
||||
unencodedFrameLines.Clear();
|
||||
for(int vfrLine = 0; vfrLine < interpFramesLines.Length; vfrLine++)
|
||||
|
||||
Logger.Log($"Starting AutoEncode MainLoop - Chunk Size: {chunkSize} Frames - Safety Buffer: {safetyBufferFrames} Frames", true);
|
||||
int videoIndex = 1;
|
||||
string encFile = Path.Combine(interpFramesPath.GetParentDir(), $"vfr-{Interpolate.current.interpFactor}x.ini");
|
||||
interpFramesLines = IOUtils.ReadLines(encFile).Select(x => x.Split('/').Last().Remove("'").Split('#').First()).ToArray(); // Array with frame filenames
|
||||
|
||||
while (!Interpolate.canceled && GetInterpFramesAmount() < 2)
|
||||
{
|
||||
if (File.Exists(Path.Combine(interpFramesPath, interpFramesLines[vfrLine])) && !encodedFrameLines.Contains(vfrLine))
|
||||
unencodedFrameLines.Add(vfrLine);
|
||||
// Logger.Log("autoenc waiting for 2s because GetInterpFramesAmount() < 2");
|
||||
await Task.Delay(2000);
|
||||
}
|
||||
|
||||
bool aiRunning = !AiProcess.currentAiProcess.HasExited;
|
||||
|
||||
if (unencodedFrameLines.Count >= (chunkSize + safetyBufferFrames) || !aiRunning) // Encode every n frames, or after process has exited
|
||||
while (HasWorkToDo()) // Loop while proc is running and not all frames have been encoded
|
||||
{
|
||||
busy = true;
|
||||
if (Interpolate.canceled) return;
|
||||
|
||||
List<int> frameLinesToEncode = aiRunning ? unencodedFrameLines.Take(chunkSize).ToList() : unencodedFrameLines; // Take all remaining frames if process is done
|
||||
//Logger.Log($"{unencodedFrameLines.Count} unencoded frame lines, {IOUtils.GetAmountOfFiles(interpFramesFolder, false)} frames in interp folder", true, false, "ffmpeg");
|
||||
|
||||
string outpath = Path.Combine(videoChunksFolder, "chunks", $"{videoIndex.ToString().PadLeft(4, '0')}{FFmpegUtils.GetExt(Interpolate.current.outMode)}");
|
||||
int firstFrameNum = frameLinesToEncode[0];
|
||||
Logger.Log($"Encoding Chunk #{videoIndex} to '{outpath}' using {Path.GetFileName(interpFramesLines[frameLinesToEncode.First()])} through {Path.GetFileName(Path.GetFileName(interpFramesLines[frameLinesToEncode.Last()]))}", true, false, "ffmpeg");
|
||||
await CreateVideo.EncodeChunk(outpath, Interpolate.current.outMode, firstFrameNum, frameLinesToEncode.Count);
|
||||
|
||||
if(Interpolate.canceled) return;
|
||||
|
||||
if (Config.GetInt("autoEncMode") == 2)
|
||||
if (paused)
|
||||
{
|
||||
foreach (int frame in frameLinesToEncode)
|
||||
{
|
||||
if(!FrameIsStillNeeded(interpFramesLines[frame], frame)) // Make sure frames are no longer needed (e.g. for dupes) before deleting!
|
||||
{
|
||||
string framePath = Path.Combine(interpFramesPath, interpFramesLines[frame]);
|
||||
File.WriteAllText(framePath, "THIS IS A DUMMY FILE - DO NOT DELETE ME"); // Overwrite to save space without breaking progress counter
|
||||
}
|
||||
}
|
||||
Logger.Log("autoenc paused");
|
||||
await Task.Delay(100);
|
||||
continue;
|
||||
}
|
||||
|
||||
encodedFrameLines.AddRange(frameLinesToEncode);
|
||||
//Logger.Log($"Adding {frameLinesToEncode.Count} frameLinesToEncode to encodedFrameLines, new count is {encodedFrameLines.Count}");
|
||||
unencodedFrameLines.Clear();
|
||||
for (int vfrLine = 0; vfrLine < interpFramesLines.Length; vfrLine++)
|
||||
{
|
||||
if (File.Exists(Path.Combine(interpFramesPath, interpFramesLines[vfrLine])) && !encodedFrameLines.Contains(vfrLine))
|
||||
unencodedFrameLines.Add(vfrLine);
|
||||
}
|
||||
|
||||
Logger.Log("Done Encoding Chunk #" + videoIndex, true, false, "ffmpeg");
|
||||
videoIndex++;
|
||||
busy = false;
|
||||
// Logger.Log($"{unencodedFrameLines.Count} unencoded frame lines, {encodedFrameLines.Count} encoded frame lines", false, false, "ffmpeg");
|
||||
|
||||
bool aiRunning = !AiProcess.currentAiProcess.HasExited;
|
||||
|
||||
if (unencodedFrameLines.Count > 0 && (unencodedFrameLines.Count >= (chunkSize + safetyBufferFrames) || !aiRunning)) // Encode every n frames, or after process has exited
|
||||
{
|
||||
busy = true;
|
||||
|
||||
Logger.Log("unencodedFrameLines: " + unencodedFrameLines.Count, true, false, "autoenc");
|
||||
List<int> frameLinesToEncode = aiRunning ? unencodedFrameLines.Take(chunkSize).ToList() : unencodedFrameLines; // Take all remaining frames if process is done
|
||||
Logger.Log("frameLinesToEncode: " + frameLinesToEncode.Count, true, false, "autoenc");
|
||||
|
||||
string outpath = Path.Combine(videoChunksFolder, "chunks", $"{videoIndex.ToString().PadLeft(4, '0')}{FFmpegUtils.GetExt(Interpolate.current.outMode)}");
|
||||
int firstFrameNum = frameLinesToEncode[0];
|
||||
Logger.Log($"Encoding Chunk #{videoIndex} to '{outpath}' using {Path.GetFileName(interpFramesLines[frameLinesToEncode.First()])} through {Path.GetFileName(Path.GetFileName(interpFramesLines[frameLinesToEncode.Last()]))}", true, false, "ffmpeg");
|
||||
await CreateVideo.EncodeChunk(outpath, Interpolate.current.outMode, firstFrameNum, frameLinesToEncode.Count);
|
||||
|
||||
if (Interpolate.canceled) return;
|
||||
|
||||
if (Config.GetInt("autoEncMode") == 2)
|
||||
{
|
||||
foreach (int frame in frameLinesToEncode)
|
||||
{
|
||||
if (!FrameIsStillNeeded(interpFramesLines[frame], frame)) // Make sure frames are no longer needed (e.g. for dupes) before deleting!
|
||||
{
|
||||
string framePath = Path.Combine(interpFramesPath, interpFramesLines[frame]);
|
||||
File.WriteAllText(framePath, "THIS IS A DUMMY FILE - DO NOT DELETE ME"); // Overwrite to save space without breaking progress counter
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
encodedFrameLines.AddRange(frameLinesToEncode);
|
||||
//Logger.Log($"Adding {frameLinesToEncode.Count} frameLinesToEncode to encodedFrameLines, new count is {encodedFrameLines.Count}");
|
||||
|
||||
Logger.Log("Done Encoding Chunk #" + videoIndex, true, false, "ffmpeg");
|
||||
videoIndex++;
|
||||
busy = false;
|
||||
}
|
||||
await Task.Delay(50);
|
||||
}
|
||||
await Task.Delay(50);
|
||||
|
||||
if (Interpolate.canceled) return;
|
||||
|
||||
IOUtils.ReverseRenaming(AiProcess.filenameMap, true); // Get timestamps back
|
||||
await CreateVideo.ChunksToVideos(Interpolate.current.tempFolder, videoChunksFolder, Interpolate.current.outFilename);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.Log($"AutoEnc Error: {e.Message}. Stack Trace:\n{e.StackTrace}");
|
||||
Interpolate.Cancel("Auto-Encode encountered an error.");
|
||||
}
|
||||
|
||||
if (Interpolate.canceled) return;
|
||||
|
||||
IOUtils.ReverseRenaming(AiProcess.filenameMap, true); // Get timestamps back
|
||||
await CreateVideo.ChunksToVideos(Interpolate.current.tempFolder, videoChunksFolder, Interpolate.current.outFilename);
|
||||
}
|
||||
|
||||
static bool FrameIsStillNeeded (string frameName, int frameIndex)
|
||||
@@ -123,7 +136,7 @@ namespace Flowframes.Main
|
||||
public static bool HasWorkToDo ()
|
||||
{
|
||||
if (Interpolate.canceled || interpFramesFolder == null) return false;
|
||||
//Logger.Log($"HasWorkToDo - Process Running: {(AiProcess.currentAiProcess != null && !AiProcess.currentAiProcess.HasExited)} - encodedFrameLines.Count: {encodedFrameLines.Count} - interpFramesLines.Length: {interpFramesLines.Length}");
|
||||
// Logger.Log($"HasWorkToDo - Process Running: {(AiProcess.currentAiProcess != null && !AiProcess.currentAiProcess.HasExited)} - encodedFrameLines.Count: {encodedFrameLines.Count} - interpFramesLines.Length: {interpFramesLines.Length}");
|
||||
return ((AiProcess.currentAiProcess != null && !AiProcess.currentAiProcess.HasExited) || encodedFrameLines.Count < interpFramesLines.Length);
|
||||
}
|
||||
|
||||
|
||||
@@ -217,7 +217,7 @@ namespace Flowframes.Main
|
||||
|
||||
if (debug) Logger.Log($"Writing frame {totalFileCount} [Discarding Next]", true);
|
||||
//fileContent += $"file '{interpPath}/{totalFileCount.ToString().PadLeft(Padding.interpFrames, '0')}.{ext}'\n";
|
||||
fileContent = WriteFrameWithDupes(dupesAmount, fileContent, totalFileCount, interpPath, ext, debug);
|
||||
fileContent = WriteFrameWithDupes(dupesAmount, fileContent, totalFileCount, interpPath, ext, debug, $"[i={i}] [{frameFiles[i].Name}] scn: discarding next [{frameFiles[i+1].Name}]");
|
||||
totalFileCount++;
|
||||
|
||||
if (debug) Logger.Log("Discarding interp frames with out num " + totalFileCount);
|
||||
@@ -225,7 +225,7 @@ namespace Flowframes.Main
|
||||
{
|
||||
if (debug) Logger.Log($"Writing frame {totalFileCount} which is actually repeated frame {lastNum}");
|
||||
//fileContent += $"file '{interpPath}/{lastNum.ToString().PadLeft(Padding.interpFrames, '0')}.{ext}'\n";
|
||||
fileContent = WriteFrameWithDupes(dupesAmount, fileContent, lastNum, interpPath, ext, debug);
|
||||
fileContent = WriteFrameWithDupes(dupesAmount, fileContent, lastNum, interpPath, ext, debug, $"[{inputFilenameNoExt}] scn: repeated last frame");
|
||||
totalFileCount++;
|
||||
}
|
||||
|
||||
@@ -233,7 +233,7 @@ namespace Flowframes.Main
|
||||
}
|
||||
else
|
||||
{
|
||||
fileContent = WriteFrameWithDupes(dupesAmount, fileContent, totalFileCount, interpPath, ext, debug);
|
||||
fileContent = WriteFrameWithDupes(dupesAmount, fileContent, totalFileCount, interpPath, ext, debug, $"[{inputFilenameNoExt}]");
|
||||
totalFileCount++;
|
||||
}
|
||||
}
|
||||
@@ -242,10 +242,14 @@ namespace Flowframes.Main
|
||||
await Task.Delay(1);
|
||||
}
|
||||
|
||||
// Use average frame duration for last frame - TODO: Use real duration??
|
||||
//string durationStrLast = ((totalDuration / (totalFileCount - 1)) / timebase).ToString("0.0000000", CultureInfo.InvariantCulture);
|
||||
fileContent += $"file '{interpPath}/{totalFileCount.ToString().PadLeft(Padding.interpFrames, '0')}.{ext}'\n";
|
||||
totalFileCount++;
|
||||
if(debug) Logger.Log("target: " + ((frameFiles.Length * interpFactor) - (interpFactor - 1)), true);
|
||||
if(debug) Logger.Log("totalFileCount: " + totalFileCount, true);
|
||||
|
||||
if (totalFileCount < (frameFiles.Length * interpFactor) - (interpFactor - 1))
|
||||
{
|
||||
fileContent += $"file '{interpPath}/{totalFileCount.ToString().PadLeft(Padding.interpFrames, '0')}.{ext}'\n";
|
||||
totalFileCount++;
|
||||
}
|
||||
|
||||
string finalFileContent = fileContent.Trim();
|
||||
if(loop)
|
||||
@@ -268,12 +272,12 @@ namespace Flowframes.Main
|
||||
}
|
||||
}
|
||||
|
||||
static string WriteFrameWithDupes (int dupesAmount, string fileContent, int frameNum, string interpPath, string ext, bool debug)
|
||||
static string WriteFrameWithDupes (int dupesAmount, string fileContent, int frameNum, string interpPath, string ext, bool debug, string note = "")
|
||||
{
|
||||
for (int writtenDupes = -1; writtenDupes < dupesAmount; writtenDupes++) // Write duplicates
|
||||
{
|
||||
if (debug) Logger.Log($"Writing frame {frameNum} (writtenDupes {writtenDupes})", true, false);
|
||||
fileContent += $"file '{interpPath}/{frameNum.ToString().PadLeft(Padding.interpFrames, '0')}.{ext}'\n";
|
||||
fileContent += $"file '{interpPath}/{frameNum.ToString().PadLeft(Padding.interpFrames, '0')}.{ext}'{(debug ? ($"# Dupe {writtenDupes+1} {note}") : "" )}\n";
|
||||
}
|
||||
return fileContent;
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ namespace Flowframes
|
||||
await PostProcessFrames();
|
||||
if (canceled) return;
|
||||
int frames = IOUtils.GetAmountOfFiles(current.framesFolder, false, "*.png");
|
||||
int targetFrameCount = frames * current.interpFactor;
|
||||
int targetFrameCount = (frames * current.interpFactor) - (current.interpFactor - 1);
|
||||
Utils.GetProgressByFrameAmount(current.interpFolder, targetFrameCount);
|
||||
if (canceled) return;
|
||||
Program.mainForm.SetStatus("Running AI...");
|
||||
@@ -132,7 +132,7 @@ namespace Flowframes
|
||||
Dedupe.ClearCache();
|
||||
|
||||
if (Config.GetInt("dedupMode") == 2 || Config.GetInt("dedupMode") == 1)
|
||||
await Dedupe.CreateDupesFileMpdecimate(current.framesFolder, currentInputFrameCount);
|
||||
await Dedupe.CreateDupesFile(current.framesFolder, currentInputFrameCount);
|
||||
|
||||
if (canceled) return;
|
||||
|
||||
|
||||
@@ -49,14 +49,22 @@ namespace Flowframes
|
||||
logStr += " - Waiting for encoding to finish...";
|
||||
Logger.Log(logStr);
|
||||
processTime.Stop();
|
||||
|
||||
Stopwatch timeSinceFfmpegRan = new Stopwatch();
|
||||
timeSinceFfmpegRan.Restart();
|
||||
|
||||
while (Interpolate.currentlyUsingAutoEnc && Program.busy)
|
||||
{
|
||||
if (AvProcess.lastProcess != null && !AvProcess.lastProcess.HasExited && AvProcess.lastTask == AvProcess.TaskType.Encode)
|
||||
{
|
||||
timeSinceFfmpegRan.Restart();
|
||||
string lastLine = AvProcess.lastOutputFfmpeg.SplitIntoLines().Last();
|
||||
Logger.Log(lastLine.Trim().TrimWhitespaces(), false, Logger.GetLastLine().Contains("frame"));
|
||||
}
|
||||
await Task.Delay(1000);
|
||||
if (timeSinceFfmpegRan.ElapsedMilliseconds > 3000)
|
||||
break;
|
||||
// Logger.Log($"AiProcess loop - Program.busy = {Program.busy}");
|
||||
await Task.Delay(500);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user