AutoEnc now works with image sequences, WIP, needs more testing

This commit is contained in:
n00mkrad 2021-08-31 00:43:22 +02:00
parent 9b72b88526
commit 024c723fd2
6 changed files with 70 additions and 39 deletions

View File

@ -314,9 +314,8 @@ namespace Flowframes.IO
autoEncBackupMode,
autoEncDebug,
autoEncMode,
autoEncSafeBufferFlavrCuda,
autoEncSafeBufferCuda,
autoEncSafeBufferNcnn,
autoEncSafeBufferRifeCuda,
aviCodec,
aviColors,
clearLogOnInput,

View File

@ -36,14 +36,11 @@ namespace Flowframes.Main
safetyBufferFrames = 90;
if (Interpolate.current.ai.aiName.ToUpper().Contains("NCNN"))
if (Interpolate.current.ai.backend == AI.Backend.Ncnn)
safetyBufferFrames = Config.GetInt(Config.Key.autoEncSafeBufferNcnn, 150);
if (Interpolate.current.ai.aiName == Implementations.rifeCuda.aiName)
safetyBufferFrames = Config.GetInt(Config.Key.autoEncSafeBufferRifeCuda, 90);
if (Interpolate.current.ai.aiName == Implementations.flavrCuda.aiName)
safetyBufferFrames = Config.GetInt(Config.Key.autoEncSafeBufferFlavrCuda, 90);
if (Interpolate.current.ai.backend == AI.Backend.Pytorch)
safetyBufferFrames = Config.GetInt(Config.Key.autoEncSafeBufferCuda, 90);
}
public static async Task MainLoop(string interpFramesPath)
@ -54,8 +51,10 @@ namespace Flowframes.Main
{
UpdateChunkAndBufferSizes();
bool imgSeq = Interpolate.current.outMode.ToString().ToLower().StartsWith("img");
interpFramesFolder = interpFramesPath;
videoChunksFolder = Path.Combine(interpFramesPath.GetParentDir(), Paths.chunksDir);
if (Interpolate.currentlyUsingAutoEnc)
Directory.CreateDirectory(videoChunksFolder);
@ -63,12 +62,12 @@ namespace Flowframes.Main
unencodedFrameLines.Clear();
Logger.Log($"[AE] Starting AutoEncode MainLoop - Chunk Size: {chunkSize} Frames - Safety Buffer: {safetyBufferFrames} Frames", true);
int videoIndex = 1;
int chunkIndex = 1;
string encFile = Path.Combine(interpFramesPath.GetParentDir(), Paths.GetFrameOrderFilename(Interpolate.current.interpFactor));
interpFramesLines = IoUtils.ReadLines(encFile).Select(x => x.Split('/').Last().Remove("'").Split('#').First()).ToArray(); // Array with frame filenames
while (!Interpolate.canceled && GetInterpFramesAmount() < 2)
await Task.Delay(2000);
await Task.Delay(1000);
int lastEncodedFrameNum = 0;
@ -128,12 +127,12 @@ namespace Flowframes.Main
}
busy = true;
string outpath = Path.Combine(videoChunksFolder, "chunks", $"{videoIndex.ToString().PadLeft(4, '0')}{FfmpegUtils.GetExt(Interpolate.current.outMode)}");
int firstLineNum = frameLinesToEncode.First();
int lastLineNum = frameLinesToEncode.Last();
Logger.Log($"[AE] Encoding Chunk #{videoIndex} to '{outpath}' using line {firstLineNum} ({Path.GetFileName(interpFramesLines[firstLineNum])}) through {lastLineNum} ({Path.GetFileName(Path.GetFileName(interpFramesLines[frameLinesToEncode.Last()]))})", true, false, "ffmpeg");
string outpath = Path.Combine(videoChunksFolder, "chunks", $"{chunkIndex.ToString().PadLeft(4, '0')}{FfmpegUtils.GetExt(Interpolate.current.outMode)}");
string firstFile = Path.GetFileName(interpFramesLines[frameLinesToEncode.First()].Trim());
string lastFile = Path.GetFileName(interpFramesLines[frameLinesToEncode.Last()].Trim());
Logger.Log($"[AE] Encoding Chunk #{chunkIndex} to using line {frameLinesToEncode.First()} ({firstFile}) through {frameLinesToEncode.Last()} ({lastFile})", true, false, "ffmpeg");
await CreateVideo.EncodeChunk(outpath, Interpolate.current.outMode, firstLineNum, frameLinesToEncode.Count);
await CreateVideo.EncodeChunk(outpath, Interpolate.current.interpFolder, Interpolate.current.outMode, frameLinesToEncode.First(), frameLinesToEncode.Count);
if (Interpolate.canceled) return;
@ -144,12 +143,12 @@ namespace Flowframes.Main
encodedFrameLines.AddRange(frameLinesToEncode);
Logger.Log("[AE] Done Encoding Chunk #" + videoIndex, true, false, "ffmpeg");
Logger.Log("[AE] Done Encoding Chunk #" + chunkIndex, true, false, "ffmpeg");
lastEncodedFrameNum = (frameLinesToEncode.Last() + 1);
videoIndex++;
chunkIndex++;
if(Config.GetInt(Config.Key.autoEncBackupMode) > 0)
if(!imgSeq && Config.GetInt(Config.Key.autoEncBackupMode) > 0)
{
if (aiRunning && (currentMuxTask == null || (currentMuxTask != null && currentMuxTask.IsCompleted)))
currentMuxTask = Task.Run(() => CreateVideo.ChunksToVideos(Interpolate.current.tempFolder, videoChunksFolder, Interpolate.current.outPath, true));
@ -174,6 +173,9 @@ namespace Flowframes.Main
while (currentMuxTask != null && !currentMuxTask.IsCompleted)
await Task.Delay(100);
if (imgSeq)
return;
await CreateVideo.ChunksToVideos(Interpolate.current.tempFolder, videoChunksFolder, Interpolate.current.outPath);
}
catch (Exception e)

View File

@ -48,7 +48,6 @@ namespace Flowframes.Main
return;
}
await Task.Delay(10);
Program.mainForm.SetStatus("Creating output video from frames...");
try
@ -88,17 +87,17 @@ namespace Flowframes.Main
IoUtils.RenameExistingFolder(outputFolderPath);
Logger.Log($"Exporting {desiredFormat.ToUpper()} frames to '{Path.GetFileName(outputFolderPath)}'...");
if (desiredFormat.ToUpper() == availableFormat.ToUpper()) // Move as the frames are already in the desired format
if (desiredFormat.ToUpper() == availableFormat.ToUpper()) // Move if frames are already in the desired format
await CopyOutputFrames(framesPath, framesFile, outputFolderPath, fpsLimit);
else // Encode with ffmpeg
await FfmpegEncode.FramesToFrames(framesFile, outputFolderPath, I.current.outFps, new Fraction(), desiredFormat);
else // Encode if frames are not in desired format
await FfmpegEncode.FramesToFrames(framesFile, outputFolderPath, 0, I.current.outFps, new Fraction(), desiredFormat);
}
if (fpsLimit)
{
string outputFolderPath = Path.Combine(I.current.outPath, await IoUtils.GetCurrentExportFilename(true, false));
Logger.Log($"Exporting {desiredFormat.ToUpper()} frames to '{Path.GetFileName(outputFolderPath)}' (Resampled to {maxFps} FPS)...");
await FfmpegEncode.FramesToFrames(framesFile, outputFolderPath, I.current.outFps, maxFps, desiredFormat);
await FfmpegEncode.FramesToFrames(framesFile, outputFolderPath, 0, I.current.outFps, maxFps, desiredFormat);
}
if (!stepByStep)
@ -222,7 +221,7 @@ namespace Flowframes.Main
await Loop(outPath, await GetLoopTimes());
}
public static async Task EncodeChunk(string outPath, I.OutMode mode, int firstFrameNum, int framesAmount)
public static async Task EncodeChunk(string outPath, string interpDir, I.OutMode mode, int firstFrameNum, int framesAmount)
{
string framesFileFull = Path.Combine(I.current.tempFolder, Paths.GetFrameOrderFilename(I.current.interpFactor));
string framesFileChunk = Path.Combine(I.current.tempFolder, Paths.GetFrameOrderFilenameChunk(firstFrameNum, firstFrameNum + framesAmount));
@ -238,15 +237,43 @@ namespace Flowframes.Main
bool dontEncodeFullFpsVid = fpsLimit && Config.GetInt(Config.Key.maxFpsMode) == 0;
if (!dontEncodeFullFpsVid)
await FfmpegEncode.FramesToVideo(framesFileChunk, outPath, mode, I.current.outFps, new Fraction(), I.current.outItsScale, extraData, AvProcess.LogMode.Hidden, true); // Encode
if (fpsLimit)
if (mode.ToString().ToLower().StartsWith("img")) // Image Sequence output mode, not video
{
string filename = Path.GetFileName(outPath);
string newParentDir = outPath.GetParentDir() + Paths.fpsLimitSuffix;
outPath = Path.Combine(newParentDir, filename);
await FfmpegEncode.FramesToVideo(framesFileChunk, outPath, mode, I.current.outFps, maxFps, I.current.outItsScale, extraData, AvProcess.LogMode.Hidden, true); // Encode with limited fps
//await FfmpegEncode.FramesToFrames(framesFileChunk, outPath, I.current.outFps, maxFps, Config.Get(Config.Key.imgSeqFormat).ToUpper(), AvProcess.LogMode.Hidden);
string desiredFormat = Config.Get(Config.Key.imgSeqFormat);
string availableFormat = Path.GetExtension(IoUtils.GetFilesSorted(interpDir)[0]).Remove(".").ToUpper();
if (!dontEncodeFullFpsVid)
{
string outputFolderPath = Path.Combine(I.current.outPath, await IoUtils.GetCurrentExportFilename(false, false));
int startNumber = IoUtils.GetAmountOfFiles(outputFolderPath, false) + 1;
if (desiredFormat.ToUpper() == availableFormat.ToUpper()) // Move if frames are already in the desired format
await CopyOutputFrames(interpDir, framesFileChunk, outputFolderPath, fpsLimit);
else // Encode if frames are not in desired format
await FfmpegEncode.FramesToFrames(framesFileChunk, outputFolderPath, startNumber, I.current.outFps, new Fraction(), desiredFormat, AvProcess.LogMode.Hidden);
}
if (fpsLimit)
{
string outputFolderPath = Path.Combine(I.current.outPath, await IoUtils.GetCurrentExportFilename(true, false));
int startNumber = IoUtils.GetAmountOfFiles(outputFolderPath, false) + 1;
await FfmpegEncode.FramesToFrames(framesFileChunk, outputFolderPath, startNumber, I.current.outFps, maxFps, desiredFormat, AvProcess.LogMode.Hidden);
}
}
else
{
if (!dontEncodeFullFpsVid)
await FfmpegEncode.FramesToVideo(framesFileChunk, outPath, mode, I.current.outFps, new Fraction(), I.current.outItsScale, extraData, AvProcess.LogMode.Hidden, true); // Encode
if (fpsLimit)
{
string filename = Path.GetFileName(outPath);
string newParentDir = outPath.GetParentDir() + Paths.fpsLimitSuffix;
outPath = Path.Combine(newParentDir, filename);
await FfmpegEncode.FramesToVideo(framesFileChunk, outPath, mode, I.current.outFps, maxFps, I.current.outItsScale, extraData, AvProcess.LogMode.Hidden, true); // Encode with limited fps
}
}
}

View File

@ -279,21 +279,21 @@ namespace Flowframes.Main
{
AutoEncode.UpdateChunkAndBufferSizes();
if (!current.outMode.ToString().ToLower().Contains("vid") || current.outMode.ToString().ToLower().Contains("gif"))
if (Config.GetInt(Config.Key.cmdDebugMode) > 0)
{
Logger.Log($"Not Using AutoEnc: Out Mode is not video ({current.outMode.ToString()})", true);
Logger.Log($"Not Using AutoEnc: CMD window is shown (cmdDebugMode > 0)", true);
return false;
}
if (stepByStep && !Config.GetBool(Config.Key.sbsAllowAutoEnc))
{
Logger.Log($"Not Using AutoEnc: Using step-by-step mode, but 'sbsAllowAutoEnc' is false.", true);
Logger.Log($"Not Using AutoEnc: Using step-by-step mode, but 'sbsAllowAutoEnc' is false", true);
return false;
}
if (!stepByStep && Config.GetInt(Config.Key.autoEncMode) == 0)
{
Logger.Log($"Not Using AutoEnc: 'autoEncMode' is 0.", true);
Logger.Log($"Not Using AutoEnc: 'autoEncMode' is 0", true);
return false;
}

View File

@ -65,11 +65,12 @@ namespace Flowframes.Media
return "";
}
public static async Task FramesToFrames(string framesFile, string outDir, Fraction fps, Fraction resampleFps, string format = "png", LogMode logMode = LogMode.OnlyLastLine)
public static async Task FramesToFrames(string framesFile, string outDir, int startNo, Fraction fps, Fraction resampleFps, string format = "png", LogMode logMode = LogMode.OnlyLastLine)
{
Directory.CreateDirectory(outDir);
string inArg = $"-f concat -i {Path.GetFileName(framesFile)}";
string linksDir = Path.Combine(framesFile + Paths.symlinksSuffix);
format = format.ToLower();
if (Config.GetBool(Config.Key.allowSymlinkEncoding, true) && Symlinks.SymlinksAllowed())
{
@ -77,11 +78,12 @@ namespace Flowframes.Media
inArg = $"-i {Path.GetFileName(framesFile) + Paths.symlinksSuffix}/%{Padding.interpFrames}d{GetConcatFileExt(framesFile)}";
}
string sn = $"-start_number {startNo}";
string rate = fps.ToString().Replace(",", ".");
string vf = (resampleFps.GetFloat() < 0.1f) ? "" : $"-vf fps=fps={resampleFps}";
string compression = format == "png" ? pngCompr : "-q:v 1";
string codec = format.ToLower() == "webp" ? "-c:v libwebp" : ""; // Specify libwebp to avoid putting all frames into single AWEBP
string args = $"-vsync 0 -r {rate} {inArg} {codec} {compression} {vf} \"{outDir}/%{Padding.interpFrames}d.{format}\"";
string codec = format == "webp" ? "-c:v libwebp" : ""; // Specify libwebp to avoid putting all frames into single animated WEBP
string args = $"-vsync 0 -r {rate} {inArg} {codec} {compression} {sn} {vf} \"{outDir}/%{Padding.interpFrames}d.{format}\"";
await RunFfmpeg(args, framesFile.GetParentDir(), logMode, "error", TaskType.Encode, true);
IoUtils.TryDeleteIfExists(linksDir);
}

View File

@ -8,6 +8,7 @@ Flowframes 1.32.0 Changelog:
- Added config option to enable custom interpolation factor (if compatible)
- ProRes now supports Alpha output when used with profile 4444 or 4444xq
- Fixed ProRes being locked to YUV420 colors on all presets
- Fixed WEBP image sequence export not working correctly
Flowframes 1.31.1 Changelog: