public static Size GetOutputResolution(Size inputRes, bool print = false, bool returnZeroIfUnchanged = false) { int maxHeightValue = Config.GetInt(Config.Key.maxVidHeight); int maxHeight = RoundDivisibleBy(maxHeightValue, FfmpegCommands.GetPadding()); if (inputRes.Height > maxHeight) { float factor = (float)maxHeight / inputRes.Height; Logger.Log($"Un-rounded downscaled size: {(inputRes.Width * factor).ToString("0.00")}x{maxHeightValue}", true); int width = RoundDivisibleBy((inputRes.Width * factor).RoundToInt(), FfmpegCommands.GetPadding()); if (print) { Logger.Log($"Video is bigger than the maximum - Downscaling to {width}x{maxHeight}."); } return(new Size(width, maxHeight)); } else { if (returnZeroIfUnchanged) { return(new Size()); } else { return(inputRes); } } }
public static Size GetVideoRes(string path) { Size size = new Size(0, 0); try { ShellFile shellFile = ShellFile.FromFilePath(path); int w = (int)shellFile.Properties.System.Video.FrameWidth.Value; int h = (int)shellFile.Properties.System.Video.FrameHeight.Value; return(new Size(w, h)); } catch (Exception e) { Logger.Log($"Failed to read video size ({e.Message}) - Trying alternative method...", true); try { size = FfmpegCommands.GetSize(path); Logger.Log($"Detected video size of {Path.GetFileName(path)} as {size.Width}x{size.Height}", true); } catch { Logger.Log("Failed to read video size!"); } } return(size); }
public static async Task <int> GetInputFrameCountAsync(string path) { long filesize = IOUtils.GetFilesize(path); PseudoUniqueFile hash = new PseudoUniqueFile(path, filesize); if (filesize > 0 && FrameCountCacheContains(hash)) { Logger.Log($"FrameCountCache contains this hash, using cached frame count.", true); return(GetFrameCountFromCache(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); } Logger.Log($"Adding hash with frame count {frameCount} to cache.", true); frameCountCache.Add(hash, frameCount); return(frameCount); }
static async Task MergeChunks(string vfrFile, string outPath) { await FfmpegCommands.ConcatVideos(vfrFile, outPath, -1); await MuxOutputVideo(I.current.inPath, outPath); await Loop(outPath, GetLoopTimes()); }
static async Task Loop(string outPath, int looptimes) { if (looptimes < 1 || !Config.GetBool("enableLoop")) { return; } Logger.Log($"Looping {looptimes} {(looptimes == 1 ? "time" : "times")} to reach target length of {Config.GetInt("minOutVidLength")}s..."); await FfmpegCommands.LoopVideo(outPath, looptimes, Config.GetInt("loopMode") == 0); }
public static async Task InitInput(TextBox outputTbox, TextBox inputTbox, TextBox fpsInTbox) { Program.mainForm.SetTab("interpolate"); Program.mainForm.ResetInputInfo(); string path = inputTbox.Text.Trim(); InterpolateUtils.PathAsciiCheck(path, "input path"); if (Config.GetBool("clearLogOnInput")) { Logger.ClearLogBox(); } outputTbox.Text = 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 InterpolateUtils.GetInputFrameCountAsync(path); string fpsStr = "Not Found"; float fps = await IOUtils.GetFpsFolderOrVideo(path); fpsInTbox.Text = fps.ToString(); if (fps > 0) { fpsStr = fps.ToString(); } Logger.Log($"Video FPS: {fpsStr} - Total Number Of Frames: {frameCount}", false, true); Program.mainForm.GetInputFpsTextbox().ReadOnly = fps > 0; 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); InterpolateUtils.SetPreviewImg(await GetThumbnail(path)); }
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); }
public static Size GetVideoRes(string path) { Size size = new Size(0, 0); try { size = FfmpegCommands.GetSize(path); Logger.Log($"Detected video size of {Path.GetFileName(path)} as {size.Width}x{size.Height}", true); } catch { Logger.Log("Failed to read video size!"); } return(size); }
public static async Task <float> GetVideoFramerate(string path) { float fps = 0; try { fps = await FfmpegCommands.GetFramerate(path); Logger.Log("Detected FPS of " + Path.GetFileName(path) + " as " + fps + " FPS", true); } catch { Logger.Log("Failed to read FPS - Please enter it manually."); } return(fps); }
public static async Task <bool> CheckEncoderValid() { string enc = FfmpegUtils.GetEnc(FfmpegUtils.GetCodec(I.current.outMode)); if (!enc.ToLower().Contains("nvenc")) { return(true); } if (!(await FfmpegCommands.IsEncoderCompatible(enc))) { UiUtils.ShowMessageBox("NVENC encoding is not available on your hardware!\nPlease use a different encoder.", UiUtils.MessageType.Error); I.Cancel(); return(false); } return(true); }
public static string GetAudioExt(string videoFile, int streamIndex = -1) { switch (FfmpegCommands.GetAudioCodec(videoFile, streamIndex)) { case "vorbis": return("ogg"); case "opus": return("ogg"); case "mp2": return("mp2"); case "aac": return("m4a"); case "ac3": return("ac3"); case "dts": return("dts"); default: return("wav"); } }
public static async Task <Fraction> GetVideoFramerate(string path) { string[] preferFfmpegReadoutFormats = new string[] { ".gif", ".png", ".apng", ".webp" }; bool preferFfmpegReadout = preferFfmpegReadoutFormats.Contains(Path.GetExtension(path).ToLower()); Fraction fps = new Fraction(); try { fps = await FfmpegCommands.GetFramerate(path, preferFfmpegReadout); Logger.Log("Detected FPS of " + Path.GetFileName(path) + " as " + fps + " FPS", true); } catch { Logger.Log("Failed to read FPS - Please enter it manually."); } return(fps); }
static async Task MergeChunks(string framesFile, string outPath, bool isBackup = false) { if (isBackup) { outPath = IoUtils.FilenameSuffix(outPath, Paths.backupSuffix); await IoUtils.TryDeleteIfExistsAsync(outPath); } await FfmpegCommands.ConcatVideos(framesFile, outPath, -1, !isBackup); if (!isBackup || (isBackup && Config.GetInt(Config.Key.autoEncBackupMode) == 2)) // Mux if no backup, or if backup AND muxing is enabled for backups { await MuxOutputVideo(I.current.inPath, outPath, isBackup, !isBackup); } if (!isBackup) { await Loop(outPath, await GetLoopTimes()); } }
static async Task Encode(I.OutMode mode, string framesPath, string outPath, Fraction fps, Fraction resampleFps) { string framesFile = Path.Combine(framesPath.GetParentDir(), Paths.GetFrameOrderFilename(I.current.interpFactor)); if (!File.Exists(framesFile)) { bool sbs = Config.GetInt(Config.Key.processingMode) == 1; I.Cancel($"Frame order file for this interpolation factor not found!{(sbs ? "\n\nDid you run the interpolation step with the current factor?" : "")}"); return; } if (mode == I.OutMode.VidGif) { await FfmpegEncode.FramesToGifConcat(framesFile, outPath, fps, true, Config.GetInt(Config.Key.gifColors), resampleFps, I.current.outItsScale); } else { VidExtraData extraData = await FfmpegCommands.GetVidExtraInfo(I.current.inPath); await FfmpegEncode.FramesToVideo(framesFile, outPath, mode, fps, resampleFps, I.current.outItsScale, extraData); await MuxOutputVideo(I.current.inPath, outPath); await Loop(outPath, await GetLoopTimes()); } }
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 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); }