예제 #1
0
        public static async Task VideoToFrames(string inputFile, string framesDir, bool alpha, Fraction rate, bool deDupe, bool delSrc, Size size, string format)
        {
            Logger.Log("Extracting video frames from input video...");
            Logger.Log($"VideoToFrames() - Alpha: {alpha} - Rate: {rate} - Size: {size} - Format: {format}", true, false, "ffmpeg");
            string sizeStr = (size.Width > 1 && size.Height > 1) ? $"-s {size.Width}x{size.Height}" : "";

            IoUtils.CreateDir(framesDir);
            string  mpStr   = deDupe ? ((Config.GetInt(Config.Key.mpdecimateMode) == 0) ? mpDecDef : mpDecAggr) : "";
            string  filters = FormatUtils.ConcatStrings(new[] { GetPadFilter(), mpStr });
            string  vf      = filters.Length > 2 ? $"-vf {filters}" : "";
            string  rateArg = (rate.GetFloat() > 0) ? $" -r {rate}" : "";
            string  args    = $"{GetTrimArg(true)} -i {inputFile.Wrap()} {GetImgArgs(format, true, alpha)} -vsync 0 {rateArg} -frame_pts 1 {vf} {sizeStr} {GetTrimArg(false)} \"{framesDir}/%{Padding.inputFrames}d{format}\"";
            LogMode logMode = await Interpolate.GetCurrentInputFrameCount() > 50 ? LogMode.OnlyLastLine : LogMode.Hidden;

            await RunFfmpeg(args, logMode, true);

            int amount = IoUtils.GetAmountOfFiles(framesDir, false, "*" + format);

            Logger.Log($"Extracted {amount} {(amount == 1 ? "frame" : "frames")} from input.", false, true);
            await Task.Delay(1);

            if (delSrc)
            {
                DeleteSource(inputFile);
            }
        }
예제 #2
0
        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);
            }
        }
예제 #3
0
        public static async Task ExtractSceneChanges(string inPath, string outDir, Fraction rate, bool inputIsFrames, string format)
        {
            Logger.Log("Extracting scene changes...");
            Directory.CreateDirectory(outDir);

            string inArg = $"-i {inPath.Wrap()}";

            if (inputIsFrames)
            {
                string concatFile = Path.Combine(Paths.GetDataPath(), "png-scndetect-concat-temp.ini");
                FfmpegUtils.CreateConcatFile(inPath, concatFile, Filetypes.imagesInterpCompat);
                inArg = $"-f concat -safe 0 -i {concatFile.Wrap()}";
            }

            string scnDetect = $"-vf \"select='gt(scene,{Config.GetFloatString(Config.Key.scnDetectValue)})'\"";
            string rateArg   = (rate.GetFloat() > 0) ? $"-r {rate}" : "";
            string args      = $"-vsync 0 {GetTrimArg(true)} {inArg} {GetImgArgs(format)} {rateArg} {scnDetect} -frame_pts 1 -s 256x144 {GetTrimArg(false)} \"{outDir}/%{Padding.inputFrames}d{format}\"";

            LogMode logMode = await Interpolate.GetCurrentInputFrameCount() > 50 ? LogMode.OnlyLastLine : LogMode.Hidden;

            await RunFfmpeg(args, logMode, inputIsFrames? "panic" : "warning", true);

            bool hiddenLog = await Interpolate.GetCurrentInputFrameCount() <= 50;

            int amount = IoUtils.GetAmountOfFiles(outDir, false);

            Logger.Log($"Detected {amount} scene {(amount == 1 ? "change" : "changes")}.".Replace(" 0 ", " no "), false, !hiddenLog);
        }
예제 #4
0
        public static async Task ImportImages(string inPath, string outPath, bool alpha, Size size, bool showLog, string format)
        {
            if (showLog)
            {
                Logger.Log($"Importing images from {new DirectoryInfo(inPath).Name}...");
            }
            Logger.Log($"ImportImages() - Alpha: {alpha} - Size: {size} - Format: {format}", true, false, "ffmpeg");
            IoUtils.CreateDir(outPath);
            string concatFile = Path.Combine(Paths.GetDataPath(), "import-concat-temp.ini");

            FfmpegUtils.CreateConcatFile(inPath, concatFile, Filetypes.imagesInterpCompat);

            string inArg    = $"-f concat -safe 0 -i {concatFile.Wrap()}";
            string linksDir = Path.Combine(concatFile + Paths.symlinksSuffix);

            if (Config.GetBool(Config.Key.allowSymlinkEncoding, true) && Symlinks.SymlinksAllowed())
            {
                if (await Symlinks.MakeSymlinksForEncode(concatFile, linksDir, Padding.interpFrames))
                {
                    inArg = $"-i \"{linksDir}/%{Padding.interpFrames}d{FfmpegEncode.GetConcatFileExt(concatFile)}\"";
                }
            }

            string  sizeStr = (size.Width > 1 && size.Height > 1) ? $"-s {size.Width}x{size.Height}" : "";
            string  vf      = $"-vf {GetPadFilter()}";
            string  args    = $"-r 25 {inArg} {GetImgArgs(format, true, alpha)} {sizeStr} -vsync 0 -start_number 0 {vf} \"{outPath}/%{Padding.inputFrames}d{format}\"";
            LogMode logMode = IoUtils.GetAmountOfFiles(inPath, false) > 50 ? LogMode.OnlyLastLine : LogMode.Hidden;

            await RunFfmpeg(args, logMode, "panic");
        }
예제 #5
0
        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);
        }
예제 #6
0
        public static bool CheckAiAvailable(AI ai, ModelCollection.ModelInfo model)
        {
            if (IoUtils.GetAmountOfFiles(Path.Combine(Paths.GetPkgPath(), ai.pkgDir), true) < 1)
            {
                UiUtils.ShowMessageBox("The selected AI is not installed!", UiUtils.MessageType.Error);
                I.Cancel("Selected AI not available.", true);
                return(false);
            }

            if (model == null || model.dir.Trim() == "")
            {
                UiUtils.ShowMessageBox("No valid AI model has been selected!", UiUtils.MessageType.Error);
                I.Cancel("No valid model selected.", true);
                return(false);
            }

            if (I.current.ai.aiName.ToUpper().Contains("CUDA") && NvApi.gpuList.Count < 1)
            {
                UiUtils.ShowMessageBox("Warning: No Nvidia GPU was detected. CUDA might fall back to CPU!\n\nTry an NCNN implementation instead if you don't have an Nvidia GPU.", UiUtils.MessageType.Error);

                if (!Config.GetBool("allowCudaWithoutDetectedGpu", true))
                {
                    I.Cancel("No CUDA-capable graphics card available.", true);
                    return(false);
                }
            }

            return(true);
        }
예제 #7
0
        static void CheckExistingFolder(string inpath, string outpath)
        {
            if (Interpolate.current == null || !Interpolate.current.stepByStep)
            {
                return;
            }
            string tmpFolder = InterpolateUtils.GetTempFolderLoc(inpath, outpath);

            if (Directory.Exists(tmpFolder))
            {
                int    scnFrmAmount    = IoUtils.GetAmountOfFiles(Path.Combine(tmpFolder, Paths.scenesDir), false, "*" + Interpolate.current.interpExt); // TODO: Make this work if the frames extension was changed
                string scnFrames       = scnFrmAmount > 0 ? $"{scnFrmAmount} scene frames" : "no scene frames";
                int    srcFrmAmount    = IoUtils.GetAmountOfFiles(Path.Combine(tmpFolder, Paths.framesDir), false, "*" + Interpolate.current.interpExt);
                string srcFrames       = srcFrmAmount > 1 ? $"{srcFrmAmount} source frames" : "no source frames";
                int    interpFrmAmount = IoUtils.GetAmountOfFiles(Path.Combine(tmpFolder, Paths.interpDir), false);
                string interpFrames    = interpFrmAmount > 2 ? $"{interpFrmAmount} interpolated frames" : "no interpolated frames";
                string msg             = $"A temporary folder for this video already exists. It contains {scnFrames}, {srcFrames}, {interpFrames}.";

                DialogResult dialogResult = MessageBox.Show($"{msg}\n\nClick \"Yes\" to use the existing files or \"No\" to delete them.", "Use files from existing temp folder?", MessageBoxButtons.YesNo);
                if (dialogResult == DialogResult.No)
                {
                    IoUtils.TryDeleteIfExists(tmpFolder);
                    Logger.Log("Deleted old temp folder.");
                }
            }
        }
예제 #8
0
        static async Task AiFinished(string aiName)
        {
            if (Interpolate.canceled)
            {
                return;
            }
            Program.mainForm.SetProgress(100);
            AiProcessSuspend.SetRunning(false);
            int interpFramesFiles = IoUtils.GetAmountOfFiles(Interpolate.current.interpFolder, false, "*" + Interpolate.current.interpExt);
            int interpFramesCount = interpFramesFiles + InterpolationProgress.deletedFramesCount;

            InterpolationProgress.UpdateInterpProgress(interpFramesCount, InterpolationProgress.targetFrames);
            string logStr = $"Done running {aiName} - Interpolation took {FormatUtils.Time(processTime.Elapsed)}. Peak Output FPS: {InterpolationProgress.peakFpsOut.ToString("0.00")}";

            if (Interpolate.currentlyUsingAutoEnc && AutoEncode.HasWorkToDo())
            {
                logStr += " - Waiting for encoding to finish...";
                Program.mainForm.SetStatus("Creating output video from frames...");
            }

            Logger.Log(logStr);
            processTime.Stop();

            if (interpFramesCount < 3)
            {
                string[] logLines = File.ReadAllLines(Path.Combine(Paths.GetLogPath(), lastLogName + ".txt"));
                string   log      = string.Join("\n", logLines.Reverse().Take(10).Reverse().Select(x => x.Split("]: ").Last()).ToList());
                string   amount   = interpFramesCount > 0 ? $"Only {interpFramesCount}" : "No";
                Interpolate.Cancel($"Interpolation failed - {amount} interpolated frames were created.\n\n\nLast 10 log lines:\n{log}\n\nCheck the log '{lastLogName}' for more details.");
                return;
            }

            try
            {
                while (Interpolate.currentlyUsingAutoEnc && Program.busy)
                {
                    if (AvProcess.lastAvProcess != null && !AvProcess.lastAvProcess.HasExited)
                    {
                        if (Logger.LastLogLine.ToLower().Contains("frame: "))
                        {
                            Logger.Log(FormatUtils.BeautifyFfmpegStats(Logger.LastLogLine), false, Logger.LastUiLine.ToLower().Contains("frame"));
                        }
                    }

                    if (AvProcess.lastAvProcess.HasExited && !AutoEncode.HasWorkToDo())     // Stop logging if ffmpeg is not running & AE is done
                    {
                        break;
                    }

                    await Task.Delay(500);
                }
            }
            catch (Exception e)
            {
                Logger.Log($"AiFinished encoder logging error: {e.Message}\n{e.StackTrace}", true);
            }
        }
예제 #9
0
        public static async Task ExportFrames(string path, string outFolder, I.OutMode mode, bool stepByStep)
        {
            if (Config.GetInt(Config.Key.sceneChangeFillMode) == 1)
            {
                string frameFile = Path.Combine(I.current.tempFolder, Paths.GetFrameOrderFilename(I.current.interpFactor));
                await Blend.BlendSceneChanges(frameFile);
            }

            if (!mode.ToString().ToLower().Contains("vid"))     // Copy interp frames out of temp folder and skip video export for image seq export
            {
                try
                {
                    await ExportImageSequence(path, stepByStep);
                }
                catch (Exception e)
                {
                    Logger.Log("Failed to move interpolated frames: " + e.Message);
                    Logger.Log("Stack Trace:\n " + e.StackTrace, true);
                }

                return;
            }

            if (IoUtils.GetAmountOfFiles(path, false, "*" + I.current.interpExt) <= 1)
            {
                I.Cancel("Output folder does not contain frames - An error must have occured during interpolation!", AiProcess.hasShownError);
                return;
            }

            Program.mainForm.SetStatus("Creating output video from frames...");

            try
            {
                string   max                  = Config.Get(Config.Key.maxFps);
                Fraction maxFps               = max.Contains("/") ? new Fraction(max) : new Fraction(max.GetFloat());
                bool     fpsLimit             = maxFps.GetFloat() > 0f && I.current.outFps.GetFloat() > maxFps.GetFloat();
                bool     dontEncodeFullFpsVid = fpsLimit && Config.GetInt(Config.Key.maxFpsMode) == 0;

                if (!dontEncodeFullFpsVid)
                {
                    await Encode(mode, path, Path.Combine(outFolder, await IoUtils.GetCurrentExportFilename(false, true)), I.current.outFps, new Fraction());
                }

                if (fpsLimit)
                {
                    await Encode(mode, path, Path.Combine(outFolder, await 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.");
            }
        }
예제 #10
0
        public static async Task ChunksToVideo(string tempFolder, string chunksFolder, string baseOutPath, bool isBackup = false)
        {
            if (IoUtils.GetAmountOfFiles(chunksFolder, true, "*" + FfmpegUtils.GetExt(I.current.outMode)) < 1)
            {
                I.Cancel("No video chunks found - An error must have occured during chunk encoding!", AiProcess.hasShownError);
                return;
            }

            NmkdStopwatch sw = new NmkdStopwatch();

            if (!isBackup)
            {
                Program.mainForm.SetStatus("Merging video chunks...");
            }

            try
            {
                DirectoryInfo chunksDir = new DirectoryInfo(chunksFolder);
                foreach (DirectoryInfo dir in chunksDir.GetDirectories())
                {
                    string suffix            = dir.Name.Replace("chunks", "");
                    string tempConcatFile    = Path.Combine(tempFolder, $"chunks-concat{suffix}.ini");
                    string concatFileContent = "";

                    foreach (string vid in IoUtils.GetFilesSorted(dir.FullName))
                    {
                        concatFileContent += $"file '{Paths.chunksDir}/{dir.Name}/{Path.GetFileName(vid)}'\n";
                    }

                    File.WriteAllText(tempConcatFile, concatFileContent);
                    Logger.Log($"CreateVideo: Running MergeChunks() for frames file '{Path.GetFileName(tempConcatFile)}'", true);
                    bool   fpsLimit = dir.Name.Contains(Paths.fpsLimitSuffix);
                    string outPath  = Path.Combine(baseOutPath, await IoUtils.GetCurrentExportFilename(fpsLimit, true));
                    await MergeChunks(tempConcatFile, outPath, isBackup);

                    if (!isBackup)
                    {
                        Task.Run(async() => { await IoUtils.TryDeleteIfExistsAsync(IoUtils.FilenameSuffix(outPath, Paths.backupSuffix)); });
                    }
                }
            }
            catch (Exception e)
            {
                Logger.Log("ChunksToVideo Error: " + e.Message, isBackup);

                if (!isBackup)
                {
                    MessageBox.Show("An error occured while trying to merge the video chunks.\nCheck the log for details.");
                }
            }

            Logger.Log($"Merged video chunks in {sw}", true);
        }
예제 #11
0
        public static async Task <int> GetFrameCountAsync(string path, int retryCount = 3)
        {
            Logger.Log($"Getting frame count ({path})", true);

            long      filesize = IoUtils.GetFilesize(path);
            QueryInfo hash     = new QueryInfo(path, filesize);

            if (filesize > 0 && CacheContains(hash))
            {
                Logger.Log($"Cache contains this hash, using cached value.", true);
                return(GetFromCache(hash));
            }
            else
            {
                Logger.Log($"Hash not cached, reading frame count.", true);
            }

            int frameCount;

            if (IoUtils.IsPathDirectory(path))
            {
                frameCount = IoUtils.GetAmountOfFiles(path, false);
            }
            else
            {
                frameCount = await FfmpegCommands.GetFrameCountAsync(path);
            }

            if (frameCount > 0)
            {
                Logger.Log($"Adding hash with value {frameCount} to cache.", true);
                cache.Add(hash, frameCount);
            }
            else
            {
                if (retryCount > 0)
                {
                    Logger.Log($"Got {frameCount} frames, retrying ({retryCount} left)", true);
                    Clear();
                    frameCount = await GetFrameCountAsync(path, retryCount - 1);
                }
                else
                {
                    Logger.Log($"Failed to get frames and out of retries ({frameCount} frames for {path})", true);
                }
            }

            return(frameCount);
        }
예제 #12
0
        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);
        }
예제 #13
0
        public static void UpdateChunkAndBufferSizes()
        {
            chunkSize = GetChunkSize((IoUtils.GetAmountOfFiles(Interpolate.current.framesFolder, false, "*" + Interpolate.current.framesExt) * Interpolate.current.interpFactor).RoundToInt());

            safetyBufferFrames = 90;

            if (Interpolate.current.ai.backend == AI.Backend.Ncnn)
            {
                safetyBufferFrames = Config.GetInt(Config.Key.autoEncSafeBufferNcnn, 150);
            }

            if (Interpolate.current.ai.backend == AI.Backend.Pytorch)
            {
                safetyBufferFrames = Config.GetInt(Config.Key.autoEncSafeBufferCuda, 90);
            }
        }
예제 #14
0
        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);
            }
        }
예제 #15
0
        static void SetProgressCheck(string interpPath, float factor)
        {
            int frames = IoUtils.GetAmountOfFiles(lastInPath, false);
            int target = ((frames * factor) - (factor - 1)).RoundToInt();

            InterpolationProgress.progressPaused = false;
            InterpolationProgress.currentFactor  = factor;

            if (InterpolationProgress.progCheckRunning)
            {
                InterpolationProgress.targetFrames = target;
            }
            else
            {
                InterpolationProgress.GetProgressByFrameAmount(interpPath, target);
            }
        }
예제 #16
0
        public static void Cancel(string reason = "", bool noMsgBox = false)
        {
            if (current == null)
            {
                return;
            }

            canceled = true;
            Program.mainForm.SetStatus("Canceled.");
            Program.mainForm.SetProgress(0);
            AiProcess.Kill();
            AvProcess.Kill();

            if (!current.stepByStep && !Config.GetBool(Config.Key.keepTempFolder))
            {
                if (!BatchProcessing.busy && IoUtils.GetAmountOfFiles(Path.Combine(current.tempFolder, Paths.resumeDir), true) > 0)
                {
                    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)
                    {
                        Task.Run(async() => { await IoUtils.TryDeleteIfExistsAsync(current.tempFolder); });
                    }
                }
                else
                {
                    Task.Run(async() => { await IoUtils.TryDeleteIfExistsAsync(current.tempFolder); });
                }
            }

            AutoEncode.busy = false;
            Program.mainForm.SetWorking(false);
            Program.mainForm.SetTab("interpolation");
            Logger.LogIfLastLineDoesNotContainMsg("Canceled interpolation.");

            if (!string.IsNullOrWhiteSpace(reason) && !noMsgBox)
            {
                UiUtils.ShowMessageBox($"Canceled:\n\n{reason}");
            }
        }
예제 #17
0
        static bool EntryIsValid(InterpSettings entry)
        {
            if (entry.inPath == null || (IoUtils.IsPathDirectory(entry.inPath) && !Directory.Exists(entry.inPath)) || (!IoUtils.IsPathDirectory(entry.inPath) && !File.Exists(entry.inPath)))
            {
                Logger.Log("Queue: Can't process queue entry: Input path is invalid.");
                return(false);
            }

            if (entry.outPath == null || (!Directory.Exists(entry.outPath) && Config.GetInt("outFolderLoc") != 1))
            {
                Logger.Log("Queue: Can't process queue entry: Output path is invalid.");
                return(false);
            }

            if (IoUtils.GetAmountOfFiles(Path.Combine(Paths.GetPkgPath(), entry.ai.pkgDir), true) < 1)
            {
                Logger.Log("Queue: Can't process queue entry: Selected AI is not available.");
                return(false);
            }

            return(true);
        }
예제 #18
0
        public static bool CanUseAutoEnc(bool stepByStep, InterpSettings current)
        {
            AutoEncode.UpdateChunkAndBufferSizes();

            if (Config.GetInt(Config.Key.cmdDebugMode) > 0)
            {
                Logger.Log($"Not Using AutoEnc: CMD window is shown (cmdDebugMode > 0)", true);
                return(false);
            }

            if (current.outMode == I.OutMode.VidGif)
            {
                Logger.Log($"Not Using AutoEnc: Using GIF output", 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);
                return(false);
            }

            if (!stepByStep && Config.GetInt(Config.Key.autoEncMode) == 0)
            {
                Logger.Log($"Not Using AutoEnc: 'autoEncMode' is 0", true);
                return(false);
            }

            int inFrames = IoUtils.GetAmountOfFiles(current.framesFolder, false);

            if (inFrames * current.interpFactor < (AutoEncode.chunkSize + AutoEncode.safetyBufferFrames) * 1.2f)
            {
                Logger.Log($"Not Using AutoEnc: Input frames ({inFrames}) * factor ({current.interpFactor}) is smaller than (chunkSize ({AutoEncode.chunkSize}) + safetyBufferFrames ({AutoEncode.safetyBufferFrames}) * 1.2f)", true);
                return(false);
            }

            return(true);
        }
예제 #19
0
        static async Task RunRifeNcnnProcess(string inPath, float factor, string outPath, string mdl)
        {
            Directory.CreateDirectory(outPath);
            Process rifeNcnn = OsUtils.NewProcess(!OsUtils.ShowHiddenCmd());

            AiStarted(rifeNcnn, 1500, inPath);
            SetProgressCheck(outPath, factor);
            int targetFrames = ((IoUtils.GetAmountOfFiles(lastInPath, false, "*.*") * factor).RoundToInt()); // TODO: Maybe won't work with fractional factors ??

            string frames = mdl.Contains("v4") ? $"-n {targetFrames}" : "";
            string uhdStr = await InterpolateUtils.UseUhd() ? "-u" : "";

            string ttaStr = Config.GetBool(Config.Key.rifeNcnnUseTta, false) ? "-x" : "";

            rifeNcnn.StartInfo.Arguments = $"{OsUtils.GetCmdArg()} cd /D {Path.Combine(Paths.GetPkgPath(), Implementations.rifeNcnn.pkgDir).Wrap()} & rife-ncnn-vulkan.exe " +
                                           $" -v -i {inPath.Wrap()} -o {outPath.Wrap()} {frames} -m {mdl.ToLower()} {ttaStr} {uhdStr} -g {Config.Get(Config.Key.ncnnGpus)} -f {GetNcnnPattern()} -j {GetNcnnThreads()}";

            Logger.Log("cmd.exe " + rifeNcnn.StartInfo.Arguments, true);

            if (!OsUtils.ShowHiddenCmd())
            {
                rifeNcnn.OutputDataReceived += (sender, outLine) => { LogOutput("[O] " + outLine.Data, "rife-ncnn-log"); };
                rifeNcnn.ErrorDataReceived  += (sender, outLine) => { LogOutput("[E] " + outLine.Data, "rife-ncnn-log", true); };
            }

            rifeNcnn.Start();

            if (!OsUtils.ShowHiddenCmd())
            {
                rifeNcnn.BeginOutputReadLine();
                rifeNcnn.BeginErrorReadLine();
            }

            while (!rifeNcnn.HasExited)
            {
                await Task.Delay(1);
            }
        }
예제 #20
0
        public static async Task RunDainNcnnProcess(string framesPath, string outPath, float factor, string mdl, int tilesize)
        {
            string dainDir = Path.Combine(Paths.GetPkgPath(), Implementations.dainNcnn.pkgDir);

            Directory.CreateDirectory(outPath);
            Process dain = OsUtils.NewProcess(!OsUtils.ShowHiddenCmd());

            AiStarted(dain, 1500);
            SetProgressCheck(outPath, factor);
            int targetFrames = ((IoUtils.GetAmountOfFiles(lastInPath, false, "*.*") * factor).RoundToInt());

            string args = $" -v -i {framesPath.Wrap()} -o {outPath.Wrap()} -n {targetFrames} -m {mdl.ToLower()}" +
                          $" -t {GetNcnnTilesize(tilesize)} -g {Config.Get(Config.Key.ncnnGpus)} -f {GetNcnnPattern()} -j 2:1:2";

            dain.StartInfo.Arguments = $"{OsUtils.GetCmdArg()} cd /D {dainDir.Wrap()} & dain-ncnn-vulkan.exe {args}";
            Logger.Log("Running DAIN...", false);
            Logger.Log("cmd.exe " + dain.StartInfo.Arguments, true);

            if (!OsUtils.ShowHiddenCmd())
            {
                dain.OutputDataReceived += (sender, outLine) => { LogOutput("[O] " + outLine.Data, "dain-ncnn-log"); };
                dain.ErrorDataReceived  += (sender, outLine) => { LogOutput("[E] " + outLine.Data, "dain-ncnn-log", true); };
            }

            dain.Start();

            if (!OsUtils.ShowHiddenCmd())
            {
                dain.BeginOutputReadLine();
                dain.BeginErrorReadLine();
            }

            while (!dain.HasExited)
            {
                await Task.Delay(100);
            }
        }
예제 #21
0
        public void DragDropHandler(string[] files)
        {
            if (Program.busy)
            {
                return;
            }

            bool start = Program.initialRun && Program.args.Contains("start");

            if (files.Length > 1)
            {
                queueBtn_Click(null, null);
                if (BatchProcessing.currentBatchForm != null)
                {
                    BatchProcessing.currentBatchForm.LoadDroppedPaths(files, start);
                }
            }
            else
            {
                SetTab("interpolation");
                Logger.Log("Selected video/directory: " + Path.GetFileName(files[0]), true);
                inputTbox.Text = files[0];

                bool resume = (IoUtils.GetAmountOfFiles(Path.Combine(files[0], Paths.resumeDir), true, "*.json") > 0);
                AutoEncodeResume.resumeNextRun = resume;

                if (resume)
                {
                    AutoEncodeResume.LoadTempFolder(files[0]);
                }

                trimCombox.SelectedIndex = 0;

                MainUiFunctions.InitInput(outputTbox, inputTbox, fpsInTbox, start);
            }
        }
예제 #22
0
        public static void FixConsecutiveSceneFrames(string sceneFramesPath, string sourceFramesPath)
        {
            if (!Directory.Exists(sceneFramesPath) || IoUtils.GetAmountOfFiles(sceneFramesPath, false) < 1)
            {
                return;
            }

            List <string> sceneFrames         = IoUtils.GetFilesSorted(sceneFramesPath).Select(x => Path.GetFileNameWithoutExtension(x)).ToList();
            List <string> sourceFrames        = IoUtils.GetFilesSorted(sourceFramesPath).Select(x => Path.GetFileNameWithoutExtension(x)).ToList();
            List <string> sceneFramesToDelete = new List <string>();

            foreach (string scnFrame in sceneFrames)
            {
                if (sceneFramesToDelete.Contains(scnFrame))
                {
                    continue;
                }

                int sourceIndexForScnFrame = sourceFrames.IndexOf(scnFrame);            // Get source index of scene frame
                if ((sourceIndexForScnFrame + 1) == sourceFrames.Count)
                {
                    continue;
                }
                string followingFrame = sourceFrames[sourceIndexForScnFrame + 1];       // Get filename/timestamp of the next source frame

                if (sceneFrames.Contains(followingFrame))                               // If next source frame is in scene folder, add to deletion list
                {
                    sceneFramesToDelete.Add(followingFrame);
                }
            }

            foreach (string frame in sceneFramesToDelete)
            {
                IoUtils.TryDeleteIfExists(Path.Combine(sceneFramesPath, frame + I.current.framesExt));
            }
        }
예제 #23
0
        public static async Task <bool> PrepareResumedRun() // Remove already interpolated frames, return true if interpolation should be skipped
        {
            if (!resumeNextRun)
            {
                return(false);
            }

            try
            {
                string chunkJsonPath    = Path.Combine(I.current.tempFolder, Paths.resumeDir, chunksFilename);
                string inFramesJsonPath = Path.Combine(I.current.tempFolder, Paths.resumeDir, inputFramesFilename);

                dynamic chunksData = JsonConvert.DeserializeObject(File.ReadAllText(chunkJsonPath));
                encodedChunks = chunksData.encodedChunks;
                encodedFrames = chunksData.encodedFrames;

                List <string> processedInputFrames = JsonConvert.DeserializeObject <List <string> >(File.ReadAllText(inFramesJsonPath));
                int           uniqueInputFrames    = processedInputFrames.Distinct().Count();

                foreach (string inputFrameName in processedInputFrames)
                {
                    string inputFrameFullPath = Path.Combine(I.current.tempFolder, Paths.framesDir, inputFrameName);
                    IoUtils.TryDeleteIfExists(inputFrameFullPath);
                }

                string videoChunksFolder = Path.Combine(I.current.tempFolder, Paths.chunksDir);

                FileInfo[] invalidChunks = IoUtils.GetFileInfosSorted(videoChunksFolder, true, "????.*").Skip(encodedChunks).ToArray();

                foreach (FileInfo chunk in invalidChunks)
                {
                    chunk.Delete();
                }

                int inputFramesLeft = IoUtils.GetAmountOfFiles(Path.Combine(I.current.tempFolder, Paths.framesDir), false);

                Logger.Log($"Resume: Already encoded {encodedFrames} frames in {encodedChunks} chunks. There are now {inputFramesLeft} input frames left to interpolate.");

                if (inputFramesLeft < 2)
                {
                    if (IoUtils.GetAmountOfFiles(videoChunksFolder, true, "*.*") > 0)
                    {
                        Logger.Log($"No more frames left to interpolate - Merging existing video chunks instead.");
                        await Export.ChunksToVideo(I.current.tempFolder, videoChunksFolder, I.current.outPath);

                        await I.Done();
                    }
                    else
                    {
                        I.Cancel("There are no more frames left to interpolate in this temp folder!");
                    }

                    return(true);
                }

                return(false);
            }
            catch (Exception e)
            {
                Logger.Log($"Failed to prepare resumed run: {e.Message}\n{e.StackTrace}");
                I.Cancel("Failed to resume interpolation. Check the logs for details.");
                resumeNextRun = false;
                return(true);
            }

            // string stateFilepath = Path.Combine(I.current.tempFolder, Paths.resumeDir, resumeFilename);
            // ResumeState state = new ResumeState(File.ReadAllText(stateFilepath));
            //
            // string fileMapFilepath = Path.Combine(I.current.tempFolder, Paths.resumeDir, filenameMapFilename);
            // List<string> inputFrameLines = File.ReadAllLines(fileMapFilepath).Where(l => l.Trim().Length > 3).ToList();
            // List<string> inputFrames = inputFrameLines.Select(l => Path.Combine(I.current.framesFolder, l.Split('|')[1])).ToList();
            //
            // for (int i = 0; i < state.interpolatedInputFrames; i++)
            // {
            //     IoUtils.TryDeleteIfExists(inputFrames[i]);
            //     if (i % 1000 == 0) await Task.Delay(1);
            // }
            //
            // Directory.Move(I.current.interpFolder, I.current.interpFolder + Paths.prevSuffix);  // Move existing interp frames
            // Directory.CreateDirectory(I.current.interpFolder);  // Re-create empty interp folder
        }
예제 #24
0
 static int GetInterpFramesAmount()
 {
     return(IoUtils.GetAmountOfFiles(interpFramesFolder, false, "*" + Interpolate.current.interpExt));
 }
예제 #25
0
        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.");
            }
        }
예제 #26
0
        public static async Task EncodeChunk(string outPath, string interpDir, int chunkNo, I.OutMode mode, int firstFrameNum, int framesAmount)
        {
            string framesFileFull = Path.Combine(I.current.tempFolder, Paths.GetFrameOrderFilename(I.current.interpFactor));
            string concatFile     = Path.Combine(I.current.tempFolder, Paths.GetFrameOrderFilenameChunk(firstFrameNum, firstFrameNum + framesAmount));

            File.WriteAllLines(concatFile, IoUtils.ReadLines(framesFileFull).Skip(firstFrameNum).Take(framesAmount));

            List <string> inputFrames = JsonConvert.DeserializeObject <List <string> >(File.ReadAllText(framesFileFull + ".inputframes.json")).Skip(firstFrameNum).Take(framesAmount).ToList();

            if (Config.GetInt(Config.Key.sceneChangeFillMode) == 1)
            {
                await Blend.BlendSceneChanges(concatFile, false);
            }

            string       max       = Config.Get(Config.Key.maxFps);
            Fraction     maxFps    = max.Contains("/") ? new Fraction(max) : new Fraction(max.GetFloat());
            bool         fpsLimit  = maxFps.GetFloat() != 0 && I.current.outFps.GetFloat() > maxFps.GetFloat();
            VidExtraData extraData = await FfmpegCommands.GetVidExtraInfo(I.current.inPath);

            bool dontEncodeFullFpsVid = fpsLimit && Config.GetInt(Config.Key.maxFpsMode) == 0;

            if (mode.ToString().ToLower().StartsWith("img"))    // Image Sequence output mode, not video
            {
                string desiredFormat   = Config.Get(Config.Key.imgSeqFormat);
                string availableFormat = Path.GetExtension(IoUtils.GetFilesSorted(interpDir)[0]).Remove(".").ToUpper();

                if (!dontEncodeFullFpsVid)
                {
                    string outFolderPath = Path.Combine(I.current.outPath, await IoUtils.GetCurrentExportFilename(false, false));
                    int    startNo       = IoUtils.GetAmountOfFiles(outFolderPath, false) + 1;

                    if (chunkNo == 1)    // Only check for existing folder on first chunk, otherwise each chunk makes a new folder
                    {
                        IoUtils.RenameExistingFolder(outFolderPath);
                    }

                    if (desiredFormat.ToUpper() == availableFormat.ToUpper())   // Move if frames are already in the desired format
                    {
                        await CopyOutputFrames(interpDir, concatFile, outFolderPath, startNo, fpsLimit, true);
                    }
                    else    // Encode if frames are not in desired format
                    {
                        await FfmpegEncode.FramesToFrames(concatFile, outFolderPath, startNo, I.current.outFps, new Fraction(), desiredFormat, GetImgSeqQ(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(concatFile, outputFolderPath, startNumber, I.current.outFps, maxFps, desiredFormat, GetImgSeqQ(desiredFormat), AvProcess.LogMode.Hidden);
                }
            }
            else
            {
                if (!dontEncodeFullFpsVid)
                {
                    await FfmpegEncode.FramesToVideo(concatFile, 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(concatFile, outPath, mode, I.current.outFps, maxFps, I.current.outItsScale, extraData, AvProcess.LogMode.Hidden, true);     // Encode with limited fps
                }
            }

            AutoEncodeResume.encodedChunks += 1;
            AutoEncodeResume.encodedFrames += framesAmount;
            AutoEncodeResume.processedInputFrames.AddRange(inputFrames);
        }
예제 #27
0
        static async Task DeleteNcnnDupes(string dir, float factor)
        {
            int dupeCount = InterpolateUtils.GetRoundedInterpFramesPerInputFrame(factor);
            var files     = IoUtils.GetFileInfosSorted(dir, false).Reverse().Take(dupeCount).ToList();

            Logger.Log($"DeleteNcnnDupes: Calculated dupe count from factor; deleting last {dupeCount} interp frames of {IoUtils.GetAmountOfFiles(dir, false)} ({string.Join(", ", files.Select(x => x.Name))})", true);

            int attempts = 4;

            while (attempts > 0)
            {
                try
                {
                    files.ForEach(x => x.Delete());
                    break;
                }
                catch (Exception ex)
                {
                    attempts--;

                    if (attempts < 1)
                    {
                        Logger.Log($"DeleteNcnnDupes Error: {ex.Message}", true);
                        break;
                    }
                    else
                    {
                        await Task.Delay(500);
                    }
                }
            }
        }