public static async Task <string> GetFfmpegOutputAsync(string path, string args, string lineFilter = "") { Process process = OsUtils.NewProcess(true); process.StartInfo.Arguments = $"/C cd /D {GetAvPath().Wrap()} & ffmpeg.exe -hide_banner -y -stats -i {path.Wrap()} {args}"; return(await GetInfoAsync(path, process, lineFilter, false)); }
public override bool IsWorkingInThisEnvironment(string forFile) { if (OsUtils.IsWindowsOs()) { return(base.IsWorkingInThisEnvironment(forFile)); } return(false); }
public static async Task <string> GetFfprobeInfoAsync(string path, FfprobeMode mode, string lineFilter = "", int streamIndex = -1, bool stripKeyName = true) { Process process = OsUtils.NewProcess(true); string showFormat = mode == FfprobeMode.ShowBoth || mode == FfprobeMode.ShowFormat ? "-show_format" : ""; string showStreams = mode == FfprobeMode.ShowBoth || mode == FfprobeMode.ShowStreams ? "-show_streams" : ""; string streamSelect = (streamIndex >= 0) ? $"-select_streams {streamIndex}" : ""; process.StartInfo.Arguments = $"/C cd /D {GetAvPath().Wrap()} & ffprobe -v quiet {showFormat} {showStreams} {streamSelect} {path.Wrap()}"; return(await GetInfoAsync(path, process, lineFilter, stripKeyName)); }
private void BtnOpenFolder_Click() { try { OsUtils.OpenFolder(SaveTo); } catch { } }
private static Process ParentProcess(this Process process) { if (OsUtils.IsUnixOs()) { // TODO: find a way to implement this in mono on a mac/linux machine return(null); } var parentPid = 0; var processPid = process.Id; const uint TH32_CS_SNAPPROCESS = 2; // Take snapshot of processes var hSnapshot = CreateToolhelp32Snapshot(TH32_CS_SNAPPROCESS, 0); if (hSnapshot == IntPtr.Zero) { return(null); } var procInfo = new PROCESSENTRY32 { dwSize = (uint)Marshal.SizeOf(typeof(PROCESSENTRY32)) }; // Read first if (Process32First(hSnapshot, ref procInfo) == false) { return(null); } // Loop through the snapshot do { // If it's me, then ask for my parent. if (processPid == procInfo.th32ProcessID) { parentPid = (int)procInfo.th32ParentProcessID; } } while (parentPid == 0 && Process32Next(hSnapshot, ref procInfo)); // Read next if (parentPid <= 0) { return(null); } try { return(Process.GetProcessById(parentPid)); } catch (ArgumentException) { //Process with an Id of X is not running return(null); } }
public void BtnOpenFolder_Click(object sender, EventArgs e) { try { if (SelectedDownloaders[0].Progress.Equals(1.0)) { OsUtils.OpenFolder(SelectedDownloaders[0].LocalFile); } } catch { } }
public static ActionResult RequestGwupeRestart(Session session) { session.Log("Begin open GwupeRestart"); // send messages to all blitsme agents OsUtils.PostMessage((IntPtr)OsUtils.HWND_BROADCAST, OsUtils.WM_UPGRADEGWUPE, #if DEBUG IntPtr.Zero, #else new IntPtr(1), #endif IntPtr.Zero); return(ActionResult.Success); }
public static async Task Done() { await Cleanup(); Program.mainForm.SetWorking(false); Logger.Log("Total processing time: " + FormatUtils.Time(sw.Elapsed)); sw.Stop(); if (!BatchProcessing.busy) { OsUtils.ShowNotificationIfInBackground("Flowframes", $"Finished interpolation after {FormatUtils.Time(sw.Elapsed)}."); } Program.mainForm.InterpolationDone(); }
public static async Task <string> RunFfprobe(string args, LogMode logMode = LogMode.Hidden, string loglevel = "quiet") { bool show = Config.GetInt(Config.Key.cmdDebugMode) > 0; string processOutput = ""; Process ffprobe = OsUtils.NewProcess(!show); NmkdStopwatch timeSinceLastOutput = new NmkdStopwatch(); lastAvProcess = ffprobe; if (string.IsNullOrWhiteSpace(loglevel)) { loglevel = defLogLevel; } ffprobe.StartInfo.Arguments = $"{GetCmdArg()} cd /D {GetAvDir().Wrap()} & ffprobe -v {loglevel} {args}"; if (logMode != LogMode.Hidden) { Logger.Log("Running FFprobe...", false); } Logger.Log($"ffprobe -v {loglevel} {args}", true, false, "ffmpeg"); if (!show) { ffprobe.OutputDataReceived += (sender, outLine) => { AvOutputHandler.LogOutput(outLine.Data, ref processOutput, "ffmpeg", logMode, false); timeSinceLastOutput.sw.Restart(); }; ffprobe.ErrorDataReceived += (sender, outLine) => { AvOutputHandler.LogOutput(outLine.Data, ref processOutput, "ffmpeg", logMode, false); timeSinceLastOutput.sw.Restart(); }; } ffprobe.Start(); ffprobe.PriorityClass = ProcessPriorityClass.BelowNormal; if (!show) { ffprobe.BeginOutputReadLine(); ffprobe.BeginErrorReadLine(); } while (!ffprobe.HasExited) { await Task.Delay(10); } while (timeSinceLastOutput.ElapsedMs < 200) { await Task.Delay(50); } return(processOutput); }
public static async void Start() { if (busy) { Logger.Log("Queue: Start() has been called, but I'm already busy - Returning!", true); return; } SetBusy(true); if (Config.GetBool(Config.Key.clearLogOnInput)) { Logger.ClearLogBox(); } stopped = false; Program.mainForm.SetTab("preview"); int initTaskCount = Program.batchQueue.Count; for (int i = 0; i < initTaskCount; i++) { if (!stopped && Program.batchQueue.Count > 0) { try { Logger.Log($"Queue: Running queue task {i + 1}/{initTaskCount}, {Program.batchQueue.Count} tasks left."); await RunEntry(Program.batchQueue.Peek()); if (currentBatchForm != null) { currentBatchForm.RefreshGui(); } } catch (Exception e) { Logger.Log($"Failed to run batch queue entry. If this happened after force stopping the queue, it's non-critical. {e.Message}", true); } } await Task.Delay(500); } Logger.Log("Queue: Finished queue processing."); OsUtils.ShowNotificationIfInBackground("Flowframes Queue", "Finished queue processing."); SetBusy(false); Program.mainForm.SetTab("interpolation"); Program.mainForm.CompletionAction(); }
public static void Kill() { if (lastAvProcess == null) { return; } try { OsUtils.KillProcessTree(lastAvProcess.Id); } catch (Exception e) { Logger.Log($"Failed to kill lastAvProcess process tree: {e.Message}", true); } }
public void MoveFileExceptions() { string file1 = Path.GetTempFileName(); string file2 = Path.GetTempFileName(); Assert.Throws <IOException>(() => OsUtils.MoveFile(file1, file2)); if (OsUtils.Windows()) { // Pretty much everything is valid in a path under Linux, so only test on Windows Assert.Throws <IOException>(() => OsUtils.MoveFile(file1, file2 + ":")); } Assert.Throws <DirectoryNotFoundException>( () => OsUtils.MoveFile(file1, Path.Combine(Path.GetTempPath(), Path.GetRandomFileName(), "filename"))); }
static async Task <string> GetOutputCached(string path, Process process) { long filesize = IoUtils.GetFilesize(path); QueryInfo hash = new QueryInfo(path, filesize, process.StartInfo.Arguments); if (filesize > 0 && CacheContains(hash, ref cmdCache)) { Logger.Log($"GetVideoInfo: '{process.StartInfo.FileName} {process.StartInfo.Arguments}' cached, won't re-run.", true, false, "ffmpeg"); return(GetFromCache(hash, ref cmdCache)); } Logger.Log($"GetVideoInfo: '{process.StartInfo.FileName} {process.StartInfo.Arguments}' not cached, running.", true, false, "ffmpeg"); string output = await OsUtils.GetOutputAsync(process); cmdCache.Add(hash, output); return(output); }
public static string GetFfprobeOutput(string args) { Process ffprobe = OsUtils.NewProcess(true); ffprobe.StartInfo.Arguments = $"{GetCmdArg()} cd /D {GetAvDir().Wrap()} & ffprobe.exe {args}"; Logger.Log($"ffprobe {args}", true, false, "ffmpeg"); ffprobe.Start(); ffprobe.WaitForExit(); string output = ffprobe.StandardOutput.ReadToEnd(); string err = ffprobe.StandardError.ReadToEnd(); if (!string.IsNullOrWhiteSpace(err)) { output += "\n" + err; } return(output); }
public static string MoveToSaveFolder(string formatString, Programme progInfo, Episode epInfo, string baseSavePath, string extension, string sourceFile) { string rootName = Path.Combine(baseSavePath, CreateSaveFileName(formatString, progInfo, epInfo)); // Make sure the save folder exists (to support subfolders in the save file name template) Directory.CreateDirectory(OsUtils.GetDirectoryName(rootName)); for (int diffNum = 0; ; diffNum++) { string savePath = rootName + (diffNum > 0 ? diffNum.ToString(CultureInfo.CurrentCulture) : string.Empty) + "." + extension; if (savePath == sourceFile) { // File is already named correctly, nothing to do return(savePath); } if (!File.Exists(savePath)) { try { OsUtils.MoveFile(sourceFile, savePath); } catch (IOException e) { // We only want to handle IOException itself as a // number of IOException subclasses are thrown for // other cases we don't want to handle if (e.GetType() == typeof(IOException)) { // Destination file created since File.Exists check continue; } throw; } return(savePath); } } }
public static ActionResult OpenGwupeIfNotOpen(Session session) { session.Log("Begin open GwupeIfNotOpen"); Process pr = OsUtils.GetMyProcess("BlitsMe.Agent", null, OsUtils.ProgramFilesx86 + "\\BlitsMe" + BuildMarker + "\\BlitsMe.Agent.exe"); Process pr2 = OsUtils.GetMyProcess("Gwupe.Agent", null, OsUtils.ProgramFilesx86 + "\\Gwupe" + BuildMarker + "\\Gwupe.Agent.exe"); if (pr == null && pr2 == null) { // Now start Gwupe try { Process.Start(OsUtils.ProgramFilesx86 + "\\Gwupe" + BuildMarker + "\\Gwupe.Agent.exe"); } catch (Exception e) { session.Log("GwupeIfNotOpen caught exception : " + e.Message + "\n" + e); return(ActionResult.Failure); } return(ActionResult.Success); } return(ActionResult.Success); }
public override bool IsWorkingInThisEnvironment(string forFile) => OsUtils.IsWindowsOs() && base.IsWorkingInThisEnvironment(forFile);
public static string GetFullOsName() { var name = OsUtils.GetFullOsNameFromWmi(); return(name.Trim().Replace(' ', '_')); }
public static string GetOsName() { var name = TransformEasyOsName(OsUtils.GetFullOsNameFromWmi()); return(name.Trim().Replace(' ', '_')); }
public override bool IsWorkingInThisEnvironment(string forFile) { return(OsUtils.IsWindowsOs() && base.IsWorkingInThisEnvironment(forFile) && LaunchedFromVisualStudio()); }
public static async Task InitInput(TextBox outputTbox, TextBox inputTbox, TextBox fpsInTbox, bool start = false) { Program.mainForm.SetTab("interpolate"); Program.mainForm.ResetInputInfo(); string path = inputTbox.Text.Trim(); GetFrameCountCached.Clear(); GetMediaResolutionCached.Clear(); if (Config.GetBool(Config.Key.clearLogOnInput)) { Logger.ClearLogBox(); } SetOutPath(outputTbox, inputTbox.Text.Trim().GetParentDir()); Program.lastInputPath = path; Program.lastInputPathIsSsd = OsUtils.DriveIsSSD(path); if (!Program.lastInputPathIsSsd) { Logger.Log("Your file seems to be on an HDD or USB device. It is recommended to interpolate videos on an SSD drive for best performance."); } Logger.Log("Loading metadata..."); Program.mainForm.currInDuration = FfmpegCommands.GetDuration(path); Program.mainForm.currInDurationCut = Program.mainForm.currInDuration; int frameCount = await GetFrameCountCached.GetFrameCountAsync(path); string fpsStr = "Not Found"; Fraction fps = (await IoUtils.GetFpsFolderOrVideo(path)); Program.mainForm.currInFpsDetected = fps; fpsInTbox.Text = fps.GetString(); if (fps.GetFloat() > 0) { fpsStr = $"{fps} (~{fps.GetFloat()})"; } Logger.Log($"Video FPS: {fpsStr} - Total Number Of Frames: {frameCount}", false, true); Program.mainForm.GetInputFpsTextbox().ReadOnly = (fps.GetFloat() > 0 && !Config.GetBool("allowCustomInputRate", false)); Program.mainForm.currInFps = fps; Program.mainForm.currInFrames = frameCount; Program.mainForm.UpdateInputInfo(); CheckExistingFolder(path, outputTbox.Text.Trim()); await Task.Delay(10); await PrintResolution(path); Dedupe.ClearCache(); await Task.Delay(10); InterpolationProgress.SetPreviewImg(await GetThumbnail(path)); if (AutoEncodeResume.resumeNextRun) { Logger.Log($"Incomplete interpolation detected. Flowframes will resume the interpolation."); } if (start) { Program.mainForm.runBtn_Click(null, null); } }
public static ActionResult CloseGwupe(Session session) { session.Log("Begin terminate Gwupe"); // send messages to all blitsme agents OsUtils.PostMessage((IntPtr)OsUtils.HWND_BROADCAST, OsUtils.WM_SHUTDOWNGWUPE, #if DEBUG IntPtr.Zero, #else new IntPtr(1), #endif IntPtr.Zero); // now we kill if necessary Process[] prs = Process.GetProcesses(); foreach (Process pr in prs) { try { if (pr.ProcessName == "BlitsMe.Agent" && (OsUtils.ProgramFilesx86 + "\\BlitsMe" + BuildMarker + "\\BlitsMe.Agent.exe") .Equals(OsUtils.GetMainModuleFilepath(pr.Id))) { session.Log("Agent is still alive and kicking so we gonna kill 'im after 5 seconds"); if (!pr.WaitForExit(5000)) { session.Log("Agent: times up"); try { pr.Kill(); } catch (Exception e) { session.Log("CloseBlitsMeAgent caught exception : " + e.Message + "\n" + e); } } } if (pr.ProcessName == "Gwupe.Agent" && (OsUtils.ProgramFilesx86 + "\\Gwupe" + BuildMarker + "\\Gwupe.Agent.exe") .Equals(OsUtils.GetMainModuleFilepath(pr.Id))) { session.Log("Gwupe is still alive and kicking so we gonna kill 'im after 5 seconds"); if (!pr.WaitForExit(5000)) { session.Log("Gwupe: times up"); try { pr.Kill(); } catch (Exception e) { session.Log("CloseGwupe caught exception : " + e.Message + "\n" + e); } } } } catch (Exception e) { session.Log("Problem accessing " + pr.ProcessName + " : " + e.Message); } } return(ActionResult.Success); }
public static async Task RemoveDupeFrames(string path, float threshold, string ext, bool testRun = false, bool debugLog = false, bool skipIfNoDupes = false) { Stopwatch sw = new Stopwatch(); sw.Restart(); Logger.Log("Removing duplicate frames - Threshold: " + threshold.ToString("0.00")); FileInfo[] framePaths = IoUtils.GetFileInfosSorted(path, false, "*." + ext); List <string> framesToDelete = new List <string>(); int bufferSize = await GetBufferSize(); int currentOutFrame = 1; int currentDupeCount = 0; int statsFramesKept = 0; int statsFramesDeleted = 0; bool hasReachedEnd = false; string fileContent = ""; for (int i = 0; i < framePaths.Length; i++) // Loop through frames { if (hasReachedEnd) { break; } string frame1 = framePaths[i].FullName; int compareWithIndex = i + 1; while (true) // Loop dupes { //compareWithIndex++; if (compareWithIndex >= framePaths.Length) { hasReachedEnd = true; break; } if (framesToDelete.Contains(framePaths[compareWithIndex].FullName) || !File.Exists(framePaths[compareWithIndex].FullName)) { //Logger.Log($"Frame {compareWithIndex} was already deleted - skipping"); compareWithIndex++; } else { string frame2 = framePaths[compareWithIndex].FullName; float diff = GetDifference(frame1, frame2); if (diff < threshold) // Is a duped frame. { if (!testRun) { framesToDelete.Add(frame2); if (debugLog) { Logger.Log("Deduplication: Deleted " + Path.GetFileName(frame2)); } } statsFramesDeleted++; currentDupeCount++; } else { fileContent += $"{Path.GetFileNameWithoutExtension(framePaths[i].Name)}:{currentDupeCount}\n"; statsFramesKept++; currentOutFrame++; currentDupeCount = 0; break; } } } if (sw.ElapsedMilliseconds >= 500 || (i + 1) == framePaths.Length) // Print every 0.5s (or when done) { sw.Restart(); Logger.Log($"Deduplication: Running de-duplication ({i}/{framePaths.Length}), deleted {statsFramesDeleted} ({(((float)statsFramesDeleted / framePaths.Length) * 100f).ToString("0")}%) duplicate frames so far...", false, true); Program.mainForm.SetProgress((int)Math.Round(((float)i / framePaths.Length) * 100f)); if (imageCache.Count > bufferSize || (imageCache.Count > 50 && OsUtils.GetFreeRamMb() < 3500)) { ClearCache(); } } // int oldIndex = -1; // TODO: Compare with 1st to fix loops? // if (i >= framePaths.Length) // If this is the last frame, compare with 1st to avoid OutOfRange error // { // oldIndex = i; // i = 0; // } if (i % 3 == 0) { await Task.Delay(1); } if (Interpolate.canceled) { return; } } foreach (string frame in framesToDelete) { IoUtils.TryDeleteIfExists(frame); } string testStr = testRun ? " [TestRun]" : ""; if (Interpolate.canceled) { return; } int framesLeft = IoUtils.GetAmountOfFiles(path, false, "*" + Interpolate.current.framesExt); int framesDeleted = framePaths.Length - framesLeft; float percentDeleted = ((float)framesDeleted / framePaths.Length) * 100f; string keptPercent = $"{(100f - percentDeleted).ToString("0.0")}%"; Logger.Log($"[Deduplication]{testStr} Done. Kept {framesLeft} ({keptPercent}) frames, deleted {framesDeleted} frames.", false, true); if (statsFramesKept <= 0) { Interpolate.Cancel("No frames were left after de-duplication!\n\nTry decreasing the de-duplication threshold."); } }
public static async Task <string> RunFfmpeg(string args, string workingDir, LogMode logMode, string loglevel, bool reliableOutput = true, bool progressBar = false) { bool show = Config.GetInt(Config.Key.cmdDebugMode) > 0; string processOutput = ""; Process ffmpeg = OsUtils.NewProcess(!show); NmkdStopwatch timeSinceLastOutput = new NmkdStopwatch(); lastAvProcess = ffmpeg; if (string.IsNullOrWhiteSpace(loglevel)) { loglevel = defLogLevel; } string beforeArgs = $"-hide_banner -stats -loglevel {loglevel} -y"; if (!string.IsNullOrWhiteSpace(workingDir)) { ffmpeg.StartInfo.Arguments = $"{GetCmdArg()} cd /D {workingDir.Wrap()} & {Path.Combine(GetAvDir(), "ffmpeg.exe").Wrap()} {beforeArgs} {args}"; } else { ffmpeg.StartInfo.Arguments = $"{GetCmdArg()} cd /D {GetAvDir().Wrap()} & ffmpeg {beforeArgs} {args}"; } if (logMode != LogMode.Hidden) { Logger.Log("Running FFmpeg...", false); } Logger.Log($"ffmpeg {beforeArgs} {args}", true, false, "ffmpeg"); if (!show) { ffmpeg.OutputDataReceived += (sender, outLine) => { AvOutputHandler.LogOutput(outLine.Data, ref processOutput, "ffmpeg", logMode, progressBar); timeSinceLastOutput.sw.Restart(); }; ffmpeg.ErrorDataReceived += (sender, outLine) => { AvOutputHandler.LogOutput(outLine.Data, ref processOutput, "ffmpeg", logMode, progressBar); timeSinceLastOutput.sw.Restart(); }; } ffmpeg.Start(); ffmpeg.PriorityClass = ProcessPriorityClass.BelowNormal; if (!show) { ffmpeg.BeginOutputReadLine(); ffmpeg.BeginErrorReadLine(); } while (!ffmpeg.HasExited) { await Task.Delay(10); } while (reliableOutput && timeSinceLastOutput.ElapsedMs < 200) { await Task.Delay(50); } if (progressBar) { Program.mainForm.SetProgress(0); } return(processOutput); }
public override bool IsWorkingInThisEnvironment(string forFile) { return(OsUtils.IsWindowsOs() && base.IsWorkingInThisEnvironment(forFile) && PATH != null); }
static void Main() { // never run as system user if (System.Environment.UserName.Equals("SYSTEM")) { Console.WriteLine("Cannot run as system user"); return; } Process[] prs = Process.GetProcesses(); try { foreach (Process pr in prs) { Console.WriteLine(pr.ProcessName); if (pr.ProcessName == "Gwupe.Agent" || pr.ProcessName == "BlitsMe.Agent") { // If Gwupe was started by an elevated process we can't get the module path. String path = OsUtils.GetMainModuleFilepath(pr.Id); String owner = OsUtils.GetProcessOwner(pr.Id); Console.WriteLine("Testing " + pr.ProcessName + ", " + path + " owned by " + owner); if (path != null) { if ( ((OsUtils.ProgramFilesx86 + "\\Gwupe" + BuildMarker + "\\Gwupe.Agent.exe").Equals(path) || (OsUtils.ProgramFilesx86 + "\\BlitsMe" + BuildMarker + "\\BlitsMe.Agent.exe").Equals( path)) && (Environment.UserDomainName + "\\" + Environment.UserName).Equals(owner)) { Console.WriteLine("Killing " + pr.Id + "(" + pr.ProcessName + ")"); try { if (!pr.WaitForExit(20000)) { pr.Kill(); } } catch (Exception e) { Console.WriteLine("Failed to kill " + pr.Id + " : " + e.Message); } } } else { // We have an elevated process, we need to wait for it to die (its quitting internally) Console.WriteLine("Elevated process found, we will wait for it to die just in case"); try { pr.WaitForExit(20000); } catch (Exception e) { Console.WriteLine("Failed to wait for process to die : " + e.Message); } } } } } catch (Exception e) { Console.WriteLine("Failed to kill other instances of BlitsMe or Gwupe : " + e.Message); } // Now start Gwupe try { //string fileName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location.Replace("BlitsMe", "Gwupe")) + "\\Gwupe.Agent.exe"; string fileName = OsUtils.ProgramFilesx86 + "\\Gwupe" + BuildMarker + "\\Gwupe.Agent.exe"; Process.Start(fileName); Console.WriteLine("Started " + fileName); } catch (Exception e) { Console.WriteLine("Failed to execute Gwupe.exe : " + e.Message); } }
public static async Task MainLoop(string interpFramesPath) { if (!AutoEncodeResume.resumeNextRun) { AutoEncodeResume.Reset(); } debug = Config.GetBool("autoEncDebug", false); try { 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); } encodedFrameLines.Clear(); unencodedFrameLines.Clear(); Logger.Log($"[AE] Starting AutoEncode MainLoop - Chunk Size: {chunkSize} Frames - Safety Buffer: {safetyBufferFrames} Frames", true); int chunkNo = AutoEncodeResume.encodedChunks + 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(1000); } int lastEncodedFrameNum = 0; while (HasWorkToDo()) // Loop while proc is running and not all frames have been encoded { if (Interpolate.canceled) { return; } if (paused) { await Task.Delay(200); continue; } unencodedFrameLines.Clear(); bool aiRunning = !AiProcess.lastAiProcess.HasExited; for (int frameLineNum = lastEncodedFrameNum; frameLineNum < interpFramesLines.Length; frameLineNum++) { if (aiRunning && interpFramesLines[frameLineNum].Contains(InterpolationProgress.lastFrame.ToString().PadLeft(Padding.interpFrames, '0'))) { break; } unencodedFrameLines.Add(frameLineNum); } if (Config.GetBool(Config.Key.alwaysWaitForAutoEnc)) { int maxFrames = chunkSize + (0.5f * chunkSize).RoundToInt() + safetyBufferFrames; bool overwhelmed = unencodedFrameLines.Count > maxFrames; if (overwhelmed && !AiProcessSuspend.aiProcFrozen && OsUtils.IsProcessHidden(AiProcess.lastAiProcess)) { string dirSize = FormatUtils.Bytes(IoUtils.GetDirSize(Interpolate.current.interpFolder, true)); Logger.Log($"AutoEnc is overwhelmed! ({unencodedFrameLines.Count} unencoded frames > {maxFrames}) - Pausing.", true); AiProcessSuspend.SuspendResumeAi(true); } else if (!overwhelmed && AiProcessSuspend.aiProcFrozen) { AiProcessSuspend.SuspendResumeAi(false); } } if (unencodedFrameLines.Count > 0 && (unencodedFrameLines.Count >= (chunkSize + safetyBufferFrames) || !aiRunning)) // Encode every n frames, or after process has exited { try { List <int> frameLinesToEncode = aiRunning ? unencodedFrameLines.Take(chunkSize).ToList() : unencodedFrameLines; // Take all remaining frames if process is done string lastOfChunk = Path.Combine(interpFramesPath, interpFramesLines[frameLinesToEncode.Last()]); if (!File.Exists(lastOfChunk)) { if (debug) { Logger.Log($"[AE] Last frame of chunk doesn't exist; skipping loop iteration ({lastOfChunk})", true); } await Task.Delay(500); continue; } busy = true; string outpath = Path.Combine(videoChunksFolder, "chunks", $"{chunkNo.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 #{chunkNo} to using line {frameLinesToEncode.First()} ({firstFile}) through {frameLinesToEncode.Last()} ({lastFile}) - {unencodedFrameLines.Count} unencoded frames left in total", true, false, "ffmpeg"); await Export.EncodeChunk(outpath, Interpolate.current.interpFolder, chunkNo, Interpolate.current.outMode, frameLinesToEncode.First(), frameLinesToEncode.Count); if (Interpolate.canceled) { return; } if (aiRunning && Config.GetInt(Config.Key.autoEncMode) == 2) { Task.Run(() => DeleteOldFramesAsync(interpFramesPath, frameLinesToEncode)); } if (Interpolate.canceled) { return; } encodedFrameLines.AddRange(frameLinesToEncode); Logger.Log("[AE] Done Encoding Chunk #" + chunkNo, true, false, "ffmpeg"); lastEncodedFrameNum = (frameLinesToEncode.Last() + 1); chunkNo++; AutoEncodeResume.Save(); if (!imgSeq && Config.GetInt(Config.Key.autoEncBackupMode) > 0) { if (aiRunning && (currentMuxTask == null || (currentMuxTask != null && currentMuxTask.IsCompleted))) { currentMuxTask = Task.Run(() => Export.ChunksToVideo(Interpolate.current.tempFolder, videoChunksFolder, Interpolate.current.outPath, true)); } else { Logger.Log($"[AE] Skipping backup because {(!aiRunning ? "this is the final chunk" : "previous mux task has not finished yet")}!", true, false, "ffmpeg"); } } busy = false; } catch (Exception e) { Logger.Log($"AutoEnc Chunk Encoding Error: {e.Message}. Stack Trace:\n{e.StackTrace}"); Interpolate.Cancel("Auto-Encode encountered an error."); } } await Task.Delay(50); } if (Interpolate.canceled) { return; } while (currentMuxTask != null && !currentMuxTask.IsCompleted) { await Task.Delay(100); } if (imgSeq) { return; } await Export.ChunksToVideo(Interpolate.current.tempFolder, videoChunksFolder, Interpolate.current.outPath); } catch (Exception e) { Logger.Log($"AutoEnc Error: {e.Message}. Stack Trace:\n{e.StackTrace}"); Interpolate.Cancel("Auto-Encode encountered an error."); } }