public static async Task CreateOutputVid() { if (IoUtils.GetAmountOfFiles(current.interpFolder, false) < 2) { if (Config.GetBool(Config.Key.sbsRunPreviousStepIfNeeded)) { Logger.Log($"There are no interpolated frames to export - Running interpolation step first..."); await InterpolateStep(); } if (IoUtils.GetAmountOfFiles(current.interpFolder, false) < 2) { Cancel($"There are no interpolated frames to encode!\n\nDid you delete the folder?"); return; } } if (!(await InterpolateUtils.CheckEncoderValid())) { return; } string[] outFrames = IoUtils.GetFilesSorted(current.interpFolder, current.interpExt); if (outFrames.Length > 0 && !IoUtils.CheckImageValid(outFrames[0])) { UiUtils.ShowMessageBox("Invalid frame files detected!\n\nIf you used Auto-Encode, this is normal, and you don't need to run " + "this step as the video was already created in the \"Interpolate\" step.", UiUtils.MessageType.Error); return; } await Export.ExportFrames(current.interpFolder, current.outPath, current.outMode, true); }
public static async Task ExtractFrames(string inPath, string outPath, bool alpha) { if (canceled) { return; } Program.mainForm.SetStatus("Extracting frames from video..."); current.RefreshExtensions(InterpSettings.FrameType.Import); bool mpdecimate = Config.GetInt(Config.Key.dedupMode) == 2; Size res = await Utils.GetOutputResolution(inPath, true, true); await FfmpegExtract.VideoToFrames(inPath, outPath, alpha, current.inFpsDetected, mpdecimate, false, res, current.framesExt); if (mpdecimate) { int framesLeft = IoUtils.GetAmountOfFiles(outPath, false, "*" + current.framesExt); int framesDeleted = currentInputFrameCount - framesLeft; float percentDeleted = ((float)framesDeleted / currentInputFrameCount) * 100f; string keptPercent = $"{(100f - percentDeleted).ToString("0.0")}%"; if (QuickSettingsTab.trimEnabled) { Logger.Log($"Deduplication: Kept {framesLeft} frames."); } else { Logger.Log($"Deduplication: Kept {framesLeft} ({keptPercent}) frames, deleted {framesDeleted} frames."); } } if (!Config.GetBool("allowConsecutiveSceneChanges", true)) { Utils.FixConsecutiveSceneFrames(Path.Combine(current.tempFolder, Paths.scenesDir), current.framesFolder); } }
public static async Task CreateOutputVid() { if (!Directory.Exists(current.interpFolder) || IOUtils.GetAmountOfFiles(current.interpFolder, false) < 2) { Cancel($"There are no interpolated frames to encode!\n\nDid you delete the folder?"); return; } if (!(await InterpolateUtils.CheckEncoderValid())) { return; } string[] outFrames = IOUtils.GetFilesSorted(current.interpFolder, $"*.{InterpolateUtils.GetOutExt()}"); 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 " + "this step as the video was already created in the \"Interpolate\" step.", "Error"); return; } string outPath = Path.Combine(current.outPath, Path.GetFileNameWithoutExtension(current.inPath) + IOUtils.GetCurrentExportSuffix() + FFmpegUtils.GetExt(current.outMode)); await CreateVideo.Export(current.interpFolder, outPath, current.outMode, true); }
public static void Cancel(string reason = "", bool noMsgBox = false) { canceled = true; Program.mainForm.SetStatus("Canceled."); Program.mainForm.SetProgress(0); AiProcess.Kill(); AvProcess.Kill(); if (!current.stepByStep && !Config.GetBool("keepTempFolder")) { if (false /* IOUtils.GetAmountOfFiles(Path.Combine(current.tempFolder, Paths.resumeDir), true) > 0 */) // TODO: Uncomment for 1.23 { DialogResult dialogResult = MessageBox.Show($"Delete the temp folder (Yes) or keep it for resuming later (No)?", "Delete temporary files?", MessageBoxButtons.YesNo); if (dialogResult == DialogResult.Yes) { IOUtils.TryDeleteIfExists(current.tempFolder); } } else { IOUtils.TryDeleteIfExists(current.tempFolder); } } AutoEncode.busy = false; Program.mainForm.SetWorking(false); Program.mainForm.SetTab("interpolation"); Logger.LogIfLastLineDoesNotContainMsg("Canceled interpolation."); if (!string.IsNullOrWhiteSpace(reason) && !noMsgBox) { Utils.ShowMessage($"Canceled:\n\n{reason}"); } }
public static async Task ExtractFrames(string inPath, string outPath, bool alpha, bool sceneDetect) { if (sceneDetect && Config.GetBool("scnDetect")) { Program.mainForm.SetStatus("Extracting scenes from video..."); await FfmpegExtract.ExtractSceneChanges(inPath, Path.Combine(current.tempFolder, Paths.scenesDir), current.inFps); await Task.Delay(10); } if (canceled) { return; } Program.mainForm.SetStatus("Extracting frames from video..."); bool mpdecimate = Config.GetInt("dedupMode") == 2; await FfmpegExtract.VideoToFrames(inPath, outPath, alpha, current.inFps, mpdecimate, false, await Utils.GetOutputResolution(inPath, true, true)); if (mpdecimate) { int framesLeft = IOUtils.GetAmountOfFiles(outPath, false, $"*.png"); int framesDeleted = currentInputFrameCount - framesLeft; float percentDeleted = ((float)framesDeleted / currentInputFrameCount) * 100f; string keptPercent = $"{(100f - percentDeleted).ToString("0.0")}%"; Logger.Log($"[Deduplication] Kept {framesLeft} ({keptPercent}) frames, deleted {framesDeleted} frames."); } if (!Config.GetBool("allowConsecutiveSceneChanges", true)) { Utils.FixConsecutiveSceneFrames(Path.Combine(current.tempFolder, Paths.scenesDir), current.framesFolder); } if (canceled) { return; } if (Config.GetBool("keepAudio")) { Program.mainForm.SetStatus("Extracting audio from video..."); await FfmpegAudioAndMetadata.ExtractAudioTracks(inPath, current.tempFolder); } if (canceled) { return; } if (Config.GetBool("keepSubs")) { Program.mainForm.SetStatus("Extracting subtitles from video..."); await FfmpegAudioAndMetadata.ExtractSubtitles(inPath, current.tempFolder, current.outMode); } }
public static async Task Run(string step) { Logger.Log($"[SBS] Running step '{step}'", true); canceled = false; Program.mainForm.SetWorking(true); if (current == null) { Logger.Log($"[SBS] Getting new current settings", true); current = Program.mainForm.GetCurrentSettings(); } else { Logger.Log($"[SBS] Updating current settings", true); current = Program.mainForm.UpdateCurrentSettings(current); } current.RefreshAlpha(); current.stepByStep = true; if (!InterpolateUtils.InputIsValid(current.inPath, current.outPath, current.inFps, current.interpFactor, current.outMode)) { return; // General input checks } if (!InterpolateUtils.CheckPathValid(current.inPath)) { return; // Check if input path/file is valid } if (step.Contains("Extract Frames")) { await ExtractFramesStep(); } if (step.Contains("Run Interpolation")) { await InterpolateStep(); } if (step.Contains("Export")) { await CreateOutputVid(); } if (step.Contains("Cleanup")) { await Reset(); } Program.mainForm.SetWorking(false); Program.mainForm.SetStatus("Done running step."); Logger.Log("Done running this step."); }
static string currentOutFile; // Keeps track of the out file, in case it gets renamed (FPS limiting, looping, etc) before finishing export public static async Task Export(string path, string outFolder, I.OutMode mode, bool stepByStep) { if (!mode.ToString().ToLower().Contains("vid")) // Copy interp frames out of temp folder and skip video export for image seq export { try { string folder = Path.Combine(outFolder, IOUtils.GetCurrentExportFilename(false, false)); await CopyOutputFrames(path, folder, stepByStep); } catch (Exception e) { Logger.Log("Failed to move interp frames folder: " + e.Message); } return; } if (IOUtils.GetAmountOfFiles(path, false, $"*.{InterpolateUtils.GetOutExt()}") <= 1) { I.Cancel("Output folder does not contain frames - An error must have occured during interpolation!", AiProcess.hasShownError); return; } await Task.Delay(10); Program.mainForm.SetStatus("Creating output video from frames..."); try { float maxFps = Config.GetFloat("maxFps"); bool fpsLimit = maxFps != 0 && I.current.outFps > maxFps; bool dontEncodeFullFpsVid = fpsLimit && Config.GetInt("maxFpsMode") == 0; if (!dontEncodeFullFpsVid) { await Encode(mode, path, Path.Combine(outFolder, IOUtils.GetCurrentExportFilename(false, true)), I.current.outFps); } if (fpsLimit) { await Encode(mode, path, Path.Combine(outFolder, IOUtils.GetCurrentExportFilename(true, true)), I.current.outFps, maxFps); } } catch (Exception e) { Logger.Log("FramesToVideo Error: " + e.Message, false); MessageBox.Show("An error occured while trying to convert the interpolated frames to a video.\nCheck the log for details."); } }
public static async Task ExtractSceneChanges() { string scenesPath = Path.Combine(current.tempFolder, Paths.scenesDir); if (!IOUtils.TryDeleteIfExists(scenesPath)) { InterpolateUtils.ShowMessage("Failed to delete existing scenes folder - Make sure no file is opened in another program!", "Error"); return; } Program.mainForm.SetStatus("Extracting scenes from video..."); await FfmpegExtract.ExtractSceneChanges(current.inPath, scenesPath, current.inFps); await Task.Delay(10); }
public static async Task InterpolateStep() { if (!InterpolateUtils.CheckAiAvailable(current.ai, current.model)) { return; } current.framesFolder = Path.Combine(current.tempFolder, Paths.framesDir); if (IoUtils.GetAmountOfFiles(current.framesFolder, false, "*") < 2) { if (Config.GetBool(Config.Key.sbsRunPreviousStepIfNeeded)) { Logger.Log($"There are no extracted frames to interpolate - Running extract step first..."); await ExtractFramesStep(); } if (IoUtils.GetAmountOfFiles(current.framesFolder, false, "*") < 2) { UiUtils.ShowMessageBox("There are no extracted frames that can be interpolated!\nDid you run the extraction step?", UiUtils.MessageType.Error); return; } } if (!(await IoUtils.TryDeleteIfExistsAsync(current.interpFolder))) { UiUtils.ShowMessageBox("Failed to delete existing frames folder - Make sure no file is opened in another program!", UiUtils.MessageType.Error); return; } currentInputFrameCount = await GetFrameCountCached.GetFrameCountAsync(current.inPath); if (Config.GetBool(Config.Key.sbsAllowAutoEnc) && !(await InterpolateUtils.CheckEncoderValid())) { return; } if (canceled) { return; } Program.mainForm.SetStatus("Running AI..."); await RunAi(current.interpFolder, current.ai, true); await Task.Run(async() => { await FrameRename.Unrename(); }); // Get timestamps back Program.mainForm.SetProgress(0); }
static async Task GenerateFrameLines(int number, int startIndex, int count, int factor, bool loopEnabled, bool sceneDetection, bool debug) { int totalFileCount = (startIndex) * factor; int interpFramesAmount = factor; string ext = InterpolateUtils.GetOutExt(); string fileContent = ""; for (int i = startIndex; i < (startIndex + count); i++) { if (Interpolate.canceled) { return; } if (i >= frameFilesWithoutLast.Length) { break; } if (debug && i == startIndex) { fileContent += $"# NEW THREAD - {startIndex} to {startIndex + count}\n"; } string inputFilenameNoExt = Path.GetFileNameWithoutExtension(frameFilesWithoutLast[i].Name); int dupesAmount = dupesDict.ContainsKey(inputFilenameNoExt) ? dupesDict[inputFilenameNoExt] : 0; bool discardThisFrame = (sceneDetection && (i + 2) < frameFilesWithoutLast.Length && sceneFrames.Contains(Path.GetFileNameWithoutExtension(frameFilesWithoutLast[i + 1].Name))); // i+2 is in scene detection folder, means i+1 is ugly interp frame if (i + 1 == frameFilesWithoutLast.Length) // Is last frame { if (sceneDetection && sceneFrames.Contains(Path.GetFileNameWithoutExtension(frameFiles.Last().Name))) // Scene detection for last frame { discardThisFrame = true; } } if (loopEnabled && i == (frameFiles.Length - 2)) // If loop is enabled, account for the extra frame for loop continuity { interpFramesAmount = interpFramesAmount * 2; } for (int frm = 0; frm < interpFramesAmount; frm++) // Generate frames file lines { if (discardThisFrame) // If frame is scene cut frame { totalFileCount++; int lastNum = totalFileCount; fileContent = WriteFrameWithDupes(dupesAmount, fileContent, totalFileCount, ext, debug, $"[In: {inputFilenameNoExt}] [{((frm == 0) ? " Source " : $"Interp {frm}")}] [DiscardNext]");
public static async Task PostProcessFrames(bool stepByStep) { if (canceled) { return; } Program.mainForm.SetStatus("Processing frames..."); int extractedFrames = IoUtils.GetAmountOfFiles(current.framesFolder, false, "*" + current.framesExt); if (!Directory.Exists(current.framesFolder) || currentInputFrameCount <= 0 || extractedFrames < 2) { if (extractedFrames == 1) { Cancel("Only a single frame was extracted from your input file!\n\nPossibly your input is an image, not a video?"); } else { Cancel($"Frame extraction failed!\nExtracted {extractedFrames} frames - current.framesFolder exists: {Directory.Exists(current.framesFolder)} - currentInputFrameCount = {currentInputFrameCount} - extractedFrames = {extractedFrames}.\n\nYour input file might be incompatible."); } } if (Config.GetInt(Config.Key.dedupMode) == 1) { await Dedupe.Run(current.framesFolder); } else { Dedupe.ClearCache(); } if (!Config.GetBool(Config.Key.enableLoop)) { await Utils.CopyLastFrame(currentInputFrameCount); } else { FileInfo[] frameFiles = IoUtils.GetFileInfosSorted(current.framesFolder); string ext = frameFiles.First().Extension; int lastNum = frameFiles.Last().Name.GetInt() + 1; string loopFrameTargetPath = Path.Combine(current.framesFolder, lastNum.ToString().PadLeft(Padding.inputFrames, '0') + ext); File.Copy(frameFiles.First().FullName, loopFrameTargetPath, true); Logger.Log($"Copied loop frame to {loopFrameTargetPath}.", true); } }
public static async Task RunAi(string outpath, AI ai, bool stepByStep = false) { Program.mainForm.SetStatus("Downloading models..."); await ModelDownloader.DownloadModelFiles(ai.pkgDir, current.model); if (canceled) { return; } currentlyUsingAutoEnc = Utils.CanUseAutoEnc(stepByStep, current); IOUtils.CreateDir(outpath); List <Task> tasks = new List <Task>(); if (ai.aiName == Networks.rifeCuda.aiName) { tasks.Add(AiProcess.RunRifeCuda(current.framesFolder, current.interpFactor, current.model)); } if (ai.aiName == Networks.rifeNcnn.aiName) { tasks.Add(AiProcess.RunRifeNcnn(current.framesFolder, outpath, (int)current.interpFactor, current.model)); } if (ai.aiName == Networks.flavrCuda.aiName) { tasks.Add(AiProcess.RunFlavrCuda(current.framesFolder, current.interpFactor, current.model)); } if (ai.aiName == Networks.dainNcnn.aiName) { tasks.Add(AiProcess.RunDainNcnn(current.framesFolder, outpath, current.interpFactor, current.model, Config.GetInt("dainNcnnTilesize", 512))); } if (currentlyUsingAutoEnc) { Logger.Log($"{Logger.GetLastLine()} (Using Auto-Encode)", true); tasks.Add(AutoEncode.MainLoop(outpath)); } Program.mainForm.SetStatus("Running AI..."); await Task.WhenAll(tasks); }
public static async Task ExtractFramesStep() { // if (Config.GetBool("scnDetect") && !current.inputIsFrames) // Input is video - extract frames first // await ExtractSceneChanges(); if (!IOUtils.TryDeleteIfExists(current.framesFolder)) { InterpolateUtils.ShowMessage("Failed to delete existing frames folder - Make sure no file is opened in another program!", "Error"); return; } currentInputFrameCount = await InterpolateUtils.GetInputFrameCountAsync(current.inPath); AiProcess.filenameMap.Clear(); await GetFrames(); await PostProcessFrames(true); }
public static async Task DoInterpolate() { if (!InterpolateUtils.CheckAiAvailable(current.ai)) { return; } current.framesFolder = Path.Combine(current.tempFolder, Paths.framesDir); 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"); return; } if (!IOUtils.TryDeleteIfExists(current.interpFolder)) { InterpolateUtils.ShowMessage("Failed to delete existing frames folder - Make sure no file is opened in another program!", "Error"); return; } currentInputFrameCount = await InterpolateUtils.GetInputFrameCountAsync(current.inPath); // TODO: Check if this works lol, remove if it does //if (Config.GetBool("sbsAllowAutoEnc")) // nextOutPath = Path.Combine(currentOutPath, Path.GetFileNameWithoutExtension(current.inPath) + IOUtils.GetAiSuffix(current.ai, current.interpFactor) + InterpolateUtils.GetExt(current.outMode)); if (Config.GetBool("sbsAllowAutoEnc") && !(await InterpolateUtils.CheckEncoderValid())) { return; } if (canceled) { return; } Program.mainForm.SetStatus("Running AI..."); await RunAi(current.interpFolder, current.ai, true); await IOUtils.ReverseRenaming(current.framesFolder, AiProcess.filenameMap); // Get timestamps back AiProcess.filenameMap.Clear(); Program.mainForm.SetProgress(0); }
public static async Task CreateEncFile(string framesPath, bool loopEnabled, float interpFactor, bool notFirstRun) { if (Interpolate.canceled) { return; } Logger.Log($"Generating frame order information for {interpFactor}x...", false, true); bool loop = Config.GetBool("enableLoop"); bool sceneDetection = true; string ext = InterpolateUtils.GetOutExt(); frameFileContents.Clear(); lastOutFileCount = 0; frameFiles = new DirectoryInfo(framesPath).GetFiles($"*.png"); frameFilesWithoutLast = frameFiles; Array.Resize(ref frameFilesWithoutLast, frameFilesWithoutLast.Length - 1); string vfrFile = Path.Combine(framesPath.GetParentDir(), Paths.GetFrameOrderFilename(interpFactor)); string fileContent = ""; string dupesFile = Path.Combine(framesPath.GetParentDir(), $"dupes.ini"); LoadDupesFile(dupesFile); string scnFramesPath = Path.Combine(framesPath.GetParentDir(), Paths.scenesDir); sceneFrames.Clear(); if (Directory.Exists(scnFramesPath)) { sceneFrames = Directory.GetFiles(scnFramesPath).Select(file => Path.GetFileNameWithoutExtension(file)).ToList(); } bool debug = Config.GetBool("frameOrderDebug", false); int interpFramesAmount = (int)interpFactor; // TODO: This code won't work with fractional factors List <Task> tasks = new List <Task>(); int linesPerTask = 400 / (int)interpFactor; int num = 0; for (int i = 0; i < frameFilesWithoutLast.Length; i += linesPerTask) { tasks.Add(GenerateFrameLines(num, i, linesPerTask, (int)interpFactor, loopEnabled, sceneDetection, debug)); num++; } await Task.WhenAll(tasks); for (int x = 0; x < frameFileContents.Count; x++) { fileContent += frameFileContents[x]; } lastOutFileCount++; fileContent += $"file '{Paths.interpDir}/{lastOutFileCount.ToString().PadLeft(Padding.interpFrames, '0')}.{ext}'"; // Last frame (source) if (loop) { fileContent = fileContent.Remove(fileContent.LastIndexOf("\n")); } File.WriteAllText(vfrFile, fileContent); if (notFirstRun) { return; // Skip all steps that only need to be done once } if (loop) { int lastFileNumber = frameFiles.Last().Name.GetInt() + 1; string loopFrameTargetPath = Path.Combine(frameFilesWithoutLast.First().FullName.GetParentDir(), lastFileNumber.ToString().PadLeft(Padding.inputFrames, '0') + $".png"); if (File.Exists(loopFrameTargetPath)) { if (debug) { Logger.Log($"Won't copy loop frame - {Path.GetFileName(loopFrameTargetPath)} already exists.", true); } return; } File.Copy(frameFilesWithoutLast.First().FullName, loopFrameTargetPath); if (debug) { Logger.Log($"Copied loop frame to {loopFrameTargetPath}.", true); } } }
public static async Task GetFrames() { current.RefreshAlpha(); if (Config.GetBool("scnDetect")) { Program.mainForm.SetStatus("Extracting scenes from video..."); await FfmpegExtract.ExtractSceneChanges(current.inPath, Path.Combine(current.tempFolder, Paths.scenesDir), current.inFps, current.inputIsFrames); } if (!current.inputIsFrames) // Extract if input is video, import if image sequence { await ExtractFrames(current.inPath, current.framesFolder, current.alpha); } else { await FfmpegExtract.ImportImages(current.inPath, current.framesFolder, current.alpha, await Utils.GetOutputResolution(current.inPath, true)); } }
public static async Task Start() { if (!BatchProcessing.busy && Program.busy) { return; } canceled = false; Program.mainForm.SetWorking(true); if (!Utils.InputIsValid(current.inPath, current.outPath, current.outFps, current.interpFactor, current.outMode)) { return; // General input checks } if (!Utils.CheckAiAvailable(current.ai)) { return; // Check if selected AI pkg is installed } if (!ResumeUtils.resumeNextRun && !Utils.CheckDeleteOldTempFolder()) { return; // Try to delete temp folder if an old one exists } if (!Utils.CheckPathValid(current.inPath)) { return; // Check if input path/file is valid } if (!(await Utils.CheckEncoderValid())) { return; // Check NVENC compat } Utils.PathAsciiCheck(current.outPath, "output path"); currentInputFrameCount = await Utils.GetInputFrameCountAsync(current.inPath); current.stepByStep = false; Program.mainForm.SetStatus("Starting..."); if (!ResumeUtils.resumeNextRun) { await GetFrames(); if (canceled) { return; } sw.Restart(); await PostProcessFrames(false); } if (canceled) { return; } await ResumeUtils.PrepareResumedRun(); //Task.Run(() => Utils.DeleteInterpolatedInputFrames()); await RunAi(current.interpFolder, current.ai); if (canceled) { return; } Program.mainForm.SetProgress(100); if (!currentlyUsingAutoEnc) { await CreateVideo.Export(current.interpFolder, current.outFilename, current.outMode, false); } await IOUtils.ReverseRenaming(current.framesFolder, AiProcess.filenameMap); // Get timestamps back AiProcess.filenameMap.Clear(); await Cleanup(); Program.mainForm.SetWorking(false); Logger.Log("Total processing time: " + FormatUtils.Time(sw.Elapsed)); sw.Stop(); Program.mainForm.SetStatus("Done interpolating!"); }
public static async Task PostProcessFrames(bool stepByStep) { if (canceled) { return; } int extractedFrames = IOUtils.GetAmountOfFiles(current.framesFolder, false, "*.png"); if (!Directory.Exists(current.framesFolder) || currentInputFrameCount <= 0 || extractedFrames < 2) { if (extractedFrames == 1) { Cancel("Only a single frame was extracted from your input file!\n\nPossibly your input is an image, not a video?"); } else { Cancel("Frame extraction failed!\n\nYour input file might be incompatible."); } } if (Config.GetInt("dedupMode") == 1) { await Dedupe.Run(current.framesFolder); } else { Dedupe.ClearCache(); } if (!Config.GetBool("enableLoop")) { await Utils.CopyLastFrame(currentInputFrameCount); } if (Config.GetInt("dedupMode") > 0) { await Dedupe.CreateDupesFile(current.framesFolder, currentInputFrameCount); } if (canceled) { return; } await FrameOrder.CreateFrameOrderFile(current.framesFolder, Config.GetBool("enableLoop"), current.interpFactor); if (canceled) { return; } try { Dictionary <string, string> renamedFilesDict = await IOUtils.RenameCounterDirReversibleAsync(current.framesFolder, "png", 1, Padding.inputFramesRenamed); if (stepByStep) { AiProcess.filenameMap = renamedFilesDict.ToDictionary(x => Path.GetFileName(x.Key), x => Path.GetFileName(x.Value)); // Save rel paths } } catch (Exception e) { Logger.Log($"Error renaming frame files: {e.Message}"); Cancel("Error renaming frame files. Check the log for details."); } if (current.alpha) { Program.mainForm.SetStatus("Extracting transparency..."); Logger.Log("Extracting transparency... (1/2)"); await FfmpegAlpha.ExtractAlphaDir(current.framesFolder, current.framesFolder + Paths.alphaSuffix); Logger.Log("Extracting transparency... (2/2)", false, true); await FfmpegAlpha.RemoveAlpha(current.framesFolder, current.framesFolder); } }
public static async Task RunAi(string outpath, AI ai, bool stepByStep = false) { if (canceled) { return; } await Task.Run(async() => { await Dedupe.CreateDupesFile(current.framesFolder, currentInputFrameCount, current.framesExt); }); await Task.Run(async() => { await FrameRename.Rename(); }); await Task.Run(async() => { await FrameOrder.CreateFrameOrderFile(current.framesFolder, Config.GetBool(Config.Key.enableLoop), current.interpFactor); }); Program.mainForm.SetStatus("Downloading models..."); await ModelDownloader.DownloadModelFiles(ai, current.model.dir); if (canceled) { return; } currentlyUsingAutoEnc = Utils.CanUseAutoEnc(stepByStep, current); IoUtils.CreateDir(outpath); List <Task> tasks = new List <Task>(); if (ai.aiName == Implementations.rifeCuda.aiName) { tasks.Add(AiProcess.RunRifeCuda(current.framesFolder, current.interpFactor, current.model.dir)); } if (ai.aiName == Implementations.rifeNcnn.aiName) { tasks.Add(AiProcess.RunRifeNcnn(current.framesFolder, outpath, current.interpFactor, current.model.dir)); } if (ai.aiName == Implementations.flavrCuda.aiName) { tasks.Add(AiProcess.RunFlavrCuda(current.framesFolder, current.interpFactor, current.model.dir)); } if (ai.aiName == Implementations.dainNcnn.aiName) { tasks.Add(AiProcess.RunDainNcnn(current.framesFolder, outpath, current.interpFactor, current.model.dir, Config.GetInt(Config.Key.dainNcnnTilesize, 512))); } if (ai.aiName == Implementations.xvfiCuda.aiName) { tasks.Add(AiProcess.RunXvfiCuda(current.framesFolder, current.interpFactor, current.model.dir)); } if (currentlyUsingAutoEnc) { Logger.Log($"{Logger.GetLastLine()} (Using Auto-Encode)", true); tasks.Add(AutoEncode.MainLoop(outpath)); } Program.mainForm.SetStatus("Running AI..."); await Task.WhenAll(tasks); }
static async Task GenerateFrameLinesFloat(int sourceFrameCount, int targetFrameCount, float factor, bool sceneDetection, bool debug) { int totalFileCount = 0; string ext = Interpolate.current.interpExt; Fraction step = new Fraction(sourceFrameCount, targetFrameCount + InterpolateUtils.GetRoundedInterpFramesPerInputFrame(factor)); string fileContent = ""; for (int i = 0; i < targetFrameCount; i++) { if (Interpolate.canceled) { return; } float currentFrameTime = 1 + (step * i).GetFloat(); string filename = $"{Paths.interpDir}/{(i + 1).ToString().PadLeft(Padding.interpFrames, '0')}{ext}"; int sourceFrameIdx = (int)Math.Floor(currentFrameTime) - 1; string timestep = (currentFrameTime - (int)Math.Floor(currentFrameTime)).ToString("0.000000").Split('.').Last(); string frames = sourceFrameIdx + 1 >= frameFiles.Length ? $"{frameFiles[sourceFrameIdx].Name}" : $"{frameFiles[sourceFrameIdx].Name} to {frameFiles[sourceFrameIdx + 1].Name}"; string note = $"Output frame {(i+1).ToString().PadLeft(8, '0')} => {frames} at {timestep}"; fileContent += $"file '{filename}' # {note}\n"; } if (totalFileCount > lastOutFileCount) { lastOutFileCount = totalFileCount; } frameFileContents[0] = fileContent; }
public static async Task Start() { if (!BatchProcessing.busy && Program.busy) { return; } canceled = false; Program.initialRun = false; Program.mainForm.SetWorking(true); if (!Utils.InputIsValid(current.inPath, current.outPath, current.inFps, current.interpFactor, current.outMode)) { return; // General input checks } if (!Utils.CheckAiAvailable(current.ai, current.model)) { return; // Check if selected AI pkg is installed } if (!AutoEncodeResume.resumeNextRun && !Utils.CheckDeleteOldTempFolder()) { return; // Try to delete temp folder if an old one exists } if (!Utils.CheckPathValid(current.inPath)) { return; // Check if input path/file is valid } if (!(await Utils.CheckEncoderValid())) { return; // Check NVENC compat } Utils.ShowWarnings(current.interpFactor, current.ai); currentInputFrameCount = await GetFrameCountCached.GetFrameCountAsync(current.inPath); current.stepByStep = false; Program.mainForm.SetStatus("Starting..."); sw.Restart(); if (!AutoEncodeResume.resumeNextRun) { await GetFrames(); if (canceled) { return; } await PostProcessFrames(false); } if (canceled) { return; } bool skip = await AutoEncodeResume.PrepareResumedRun(); if (skip || canceled) { return; } //Task.Run(() => Utils.DeleteInterpolatedInputFrames()); await RunAi(current.interpFolder, current.ai); if (canceled) { return; } Program.mainForm.SetProgress(100); if (!currentlyUsingAutoEnc) { await Export.ExportFrames(current.interpFolder, current.outPath, current.outMode, false); } if (!AutoEncodeResume.resumeNextRun && Config.GetBool(Config.Key.keepTempFolder)) { await Task.Run(async() => { await FrameRename.Unrename(); }); } await Done(); }
public static async Task GetFrames(bool stepByStep = false) { current.RefreshAlpha(); if (!current.inputIsFrames) // Extract if input is video, import if image sequence { await ExtractFrames(current.inPath, current.framesFolder, current.alpha, !stepByStep); } else { await FfmpegExtract.ImportImages(current.inPath, current.framesFolder, current.alpha, await Utils.GetOutputResolution(current.inPath, true)); } }
public static async Task CreateEncFile(string framesPath, bool loopEnabled, float interpFactor) { if (Interpolate.canceled) { return; } Logger.Log($"Generating frame order information for {interpFactor}x...", false, true); bool loop = Config.GetBool(Config.Key.enableLoop); bool sceneDetection = true; string ext = Interpolate.current.interpExt; frameFileContents.Clear(); lastOutFileCount = 0; frameFiles = new DirectoryInfo(framesPath).GetFiles("*" + Interpolate.current.framesExt); frameFilesWithoutLast = frameFiles; Array.Resize(ref frameFilesWithoutLast, frameFilesWithoutLast.Length - 1); string framesFile = Path.Combine(framesPath.GetParentDir(), Paths.GetFrameOrderFilename(interpFactor)); string fileContent = ""; string dupesFile = Path.Combine(framesPath.GetParentDir(), "dupes.ini"); LoadDupesFile(dupesFile); string scnFramesPath = Path.Combine(framesPath.GetParentDir(), Paths.scenesDir); sceneFrames.Clear(); if (Directory.Exists(scnFramesPath)) { sceneFrames = Directory.GetFiles(scnFramesPath).Select(file => GetNameNoExt(file)).ToList(); } inputFilenames.Clear(); bool debug = Config.GetBool("frameOrderDebug", false); List <Task> tasks = new List <Task>(); int linesPerTask = (400 / interpFactor).RoundToInt(); int num = 0; int targetFrameCount = (frameFiles.Length * interpFactor).RoundToInt() - InterpolateUtils.GetRoundedInterpFramesPerInputFrame(interpFactor); if (interpFactor == (int)interpFactor) // Use old multi-threaded code if factor is not fractional { for (int i = 0; i < frameFilesWithoutLast.Length; i += linesPerTask) { tasks.Add(GenerateFrameLines(num, i, linesPerTask, (int)interpFactor, sceneDetection, debug)); num++; } } else { await GenerateFrameLinesFloat(frameFiles.Length, targetFrameCount, interpFactor, sceneDetection, debug); } await Task.WhenAll(tasks); for (int x = 0; x < frameFileContents.Count; x++) { fileContent += frameFileContents[x]; } lastOutFileCount++; if (Config.GetBool(Config.Key.fixOutputDuration)) // Match input duration by padding duping last frame until interp frames == (inputframes * factor) { int neededFrames = (frameFiles.Length * interpFactor).RoundToInt() - fileContent.SplitIntoLines().Where(x => x.StartsWith("'file ")).Count(); for (int i = 0; i < neededFrames; i++) { fileContent += fileContent.SplitIntoLines().Where(x => x.StartsWith("'file ")).Last(); } } //int lastFrameTimes = Config.GetBool(Config.Key.fixOutputDuration) ? (int)interpFactor : 1; // //for (int i = 0; i < lastFrameTimes; i++) //{ // fileContent += $"{(i > 0 ? "\n" : "")}file '{Paths.interpDir}/{lastOutFileCount.ToString().PadLeft(Padding.interpFrames, '0')}{ext}'"; // Last frame (source) // inputFilenames.Add(frameFiles.Last().Name); //} if (loop) { fileContent = fileContent.Remove(fileContent.LastIndexOf("\n")); //inputFilenames.Remove(inputFilenames.Last()); } File.WriteAllText(framesFile, fileContent); File.WriteAllText(framesFile + ".inputframes.json", JsonConvert.SerializeObject(inputFilenames, Formatting.Indented)); }
static int GetInterpFramesAmount() { return(IOUtils.GetAmountOfFiles(interpFramesFolder, false, $"*.{InterpolateUtils.GetOutExt()}")); }