From dd520cea28b7d074f382e53cbaf47f2dc20bd350 Mon Sep 17 00:00:00 2001 From: N00MKRAD Date: Mon, 26 Apr 2021 14:13:22 +0200 Subject: [PATCH] Added support for fractional FPS limit --- Code/Forms/SettingsForm.cs | 5 ----- Code/IO/IOUtils.cs | 4 +++- Code/Main/CreateVideo.cs | 22 +++++++++++----------- Code/Media/FfmpegEncode.cs | 24 ++++++++++++------------ 4 files changed, 26 insertions(+), 29 deletions(-) diff --git a/Code/Forms/SettingsForm.cs b/Code/Forms/SettingsForm.cs index de72707..6d800a3 100644 --- a/Code/Forms/SettingsForm.cs +++ b/Code/Forms/SettingsForm.cs @@ -2,12 +2,7 @@ using Flowframes.MiscUtils; using Microsoft.WindowsAPICodePack.Dialogs; using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Data; using System.Drawing; -using System.Linq; -using System.Text; using System.Threading.Tasks; using System.Windows.Forms; diff --git a/Code/IO/IOUtils.cs b/Code/IO/IOUtils.cs index 7e3c071..ae85a7b 100644 --- a/Code/IO/IOUtils.cs +++ b/Code/IO/IOUtils.cs @@ -402,7 +402,9 @@ namespace Flowframes.IO public static async Task GetCurrentExportFilename(bool fpsLimit, bool withExt) { InterpSettings curr = Interpolate.current; - float fps = fpsLimit ? Config.GetFloat("maxFps") : curr.outFps.GetFloat(); + string max = Config.Get("maxFps"); + Fraction maxFps = max.Contains("/") ? new Fraction(max) : new Fraction(max.GetFloat()); + float fps = fpsLimit ? maxFps.GetFloat() : curr.outFps.GetFloat(); if (curr.outMode == Interpolate.OutMode.VidGif && fps > 50f) fps = 50f; diff --git a/Code/Main/CreateVideo.cs b/Code/Main/CreateVideo.cs index 3f19300..3490567 100644 --- a/Code/Main/CreateVideo.cs +++ b/Code/Main/CreateVideo.cs @@ -30,9 +30,7 @@ namespace Flowframes.Main { try { - //string folder = Path.Combine(outFolder, (await IOUtils.GetCurrentExportFilename(false, false))); await ExportFrames(path, stepByStep); - //await CopyOutputFrames(path, folder, stepByStep); } catch (Exception e) { @@ -53,13 +51,13 @@ namespace Flowframes.Main try { - float maxFps = Config.GetFloat("maxFps"); - bool fpsLimit = maxFps != 0 && I.current.outFps.GetFloat() > maxFps; - + string max = Config.Get("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("maxFpsMode") == 0; if (!dontEncodeFullFpsVid) - await Encode(mode, path, Path.Combine(outFolder, await IOUtils.GetCurrentExportFilename(false, true)), I.current.outFps); + 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); @@ -74,8 +72,9 @@ namespace Flowframes.Main static async Task ExportFrames (string framesPath, bool stepByStep) { Program.mainForm.SetStatus("Copying output frames..."); - float maxFps = Config.GetFloat("maxFps"); - bool fpsLimit = maxFps != 0 && I.current.outFps.GetFloat() > maxFps; + string max = Config.Get("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("maxFpsMode") == 0; string framesFile = Path.Combine(framesPath.GetParentDir(), Paths.GetFrameOrderFilename(I.current.interpFactor)); @@ -129,7 +128,7 @@ namespace Flowframes.Main } } - static async Task Encode(I.OutMode mode, string framesPath, string outPath, Fraction fps, float resampleFps = -1) + static async Task Encode(I.OutMode mode, string framesPath, string outPath, Fraction fps, Fraction resampleFps) { string currentOutFile = outPath; string framesFile = Path.Combine(framesPath.GetParentDir(), Paths.GetFrameOrderFilename(I.current.interpFactor)); @@ -205,8 +204,9 @@ namespace Flowframes.Main if (Config.GetInt("sceneChangeFillMode") == 1) await Blend.BlendSceneChanges(framesFileChunk, false); - float maxFps = Config.GetFloat("maxFps"); - bool fpsLimit = maxFps != 0 && I.current.outFps.GetFloat() > maxFps; + string max = Config.Get("maxFps"); + Fraction maxFps = max.Contains("/") ? new Fraction(max) : new Fraction(max.GetFloat()); + bool fpsLimit = maxFps.GetFloat() != 0 && I.current.outFps.GetFloat() > maxFps.GetFloat(); bool dontEncodeFullFpsVid = fpsLimit && Config.GetInt("maxFpsMode") == 0; diff --git a/Code/Media/FfmpegEncode.cs b/Code/Media/FfmpegEncode.cs index cd0a4b5..7277716 100644 --- a/Code/Media/FfmpegEncode.cs +++ b/Code/Media/FfmpegEncode.cs @@ -19,13 +19,13 @@ namespace Flowframes.Media { public static async Task FramesToVideoConcat(string framesFile, string outPath, Interpolate.OutMode outMode, Fraction fps, LogMode logMode = LogMode.OnlyLastLine, bool isChunk = false) { - await FramesToVideo(framesFile, outPath, outMode, fps, 0, logMode, isChunk); + await FramesToVideo(framesFile, outPath, outMode, fps, new Fraction(), logMode, isChunk); } - public static async Task FramesToVideo(string framesFile, string outPath, Interpolate.OutMode outMode, Fraction fps, float resampleFps, LogMode logMode = LogMode.OnlyLastLine, bool isChunk = false) + public static async Task FramesToVideo(string framesFile, string outPath, Interpolate.OutMode outMode, Fraction fps, Fraction resampleFps, LogMode logMode = LogMode.OnlyLastLine, bool isChunk = false) { if (logMode != LogMode.Hidden) - Logger.Log((resampleFps <= 0) ? "Encoding video..." : $"Encoding video resampled to {resampleFps.ToString().Replace(",", ".")} FPS..."); + Logger.Log((resampleFps.GetFloat() <= 0) ? "Encoding video..." : $"Encoding video resampled to {resampleFps.GetString()} FPS..."); Directory.CreateDirectory(outPath.GetParentDir()); string encArgs = Utils.GetEncArgs(Utils.GetCodec(outMode)); @@ -40,17 +40,17 @@ namespace Flowframes.Media } string rate = fps.ToString().Replace(",", "."); - string vf = (resampleFps <= 0) ? "" : $"-vf fps=fps={resampleFps.ToStringDot()}"; + string vf = (resampleFps.GetFloat() < 0.1f) ? "" : $"-vf fps=fps={resampleFps}"; string extraArgs = Config.Get("ffEncArgs"); string args = $"-vsync 0 -r {rate} {inArg} {encArgs} {vf} {extraArgs} -threads {Config.GetInt("ffEncThreads")} {outPath.Wrap()}"; await RunFfmpeg(args, framesFile.GetParentDir(), logMode, "error", TaskType.Encode, !isChunk); IOUtils.TryDeleteIfExists(linksDir); } - public static async Task FramesToFrames(string framesFile, string outDir, Fraction fps, float resampleFps, string format = "png", LogMode logMode = LogMode.OnlyLastLine) + public static async Task FramesToFrames(string framesFile, string outDir, Fraction fps, Fraction resampleFps, string format = "png", LogMode logMode = LogMode.OnlyLastLine) { if (logMode != LogMode.Hidden) - Logger.Log((resampleFps <= 0) ? "Exporting frames..." : $"Exporting frames resampled to {resampleFps.ToString().Replace(",", ".")} FPS..."); + Logger.Log((resampleFps.GetFloat() <= 0) ? "Exporting frames..." : $"Exporting frames resampled to {resampleFps.GetString()} FPS..."); Directory.CreateDirectory(outDir); string inArg = $"-f concat -i {Path.GetFileName(framesFile)}"; @@ -63,25 +63,25 @@ namespace Flowframes.Media } string rate = fps.ToString().Replace(",", "."); - string vf = (resampleFps <= 0) ? "" : $"-vf fps=fps={resampleFps.ToStringDot()}"; + string vf = (resampleFps.GetFloat() < 0.1f) ? "" : $"-vf fps=fps={resampleFps}"; string compression = format == "png" ? pngCompr : "-q:v 1"; string args = $"-vsync 0 -r {rate} {inArg} {compression} {vf} \"{outDir}/%{Padding.interpFrames}d.{format}\""; await RunFfmpeg(args, framesFile.GetParentDir(), logMode, "error", TaskType.Encode, true); IOUtils.TryDeleteIfExists(linksDir); } - public static async Task FramesToGifConcat(string framesFile, string outPath, Fraction rate, bool palette, int colors = 64, float resampleFps = -1, LogMode logMode = LogMode.OnlyLastLine) + public static async Task FramesToGifConcat(string framesFile, string outPath, Fraction rate, bool palette, int colors, Fraction resampleFps, LogMode logMode = LogMode.OnlyLastLine) { - if (rate.GetFloat() > 50f && resampleFps < 50f) - resampleFps = 50f; // Force limit framerate as encoding above 50 will cause problems + if (rate.GetFloat() > 50f && resampleFps.GetFloat() < 50f) + resampleFps = new Fraction(50, 1); // Force limit framerate as encoding above 50 will cause problems if (logMode != LogMode.Hidden) - Logger.Log((resampleFps <= 0) ? $"Encoding GIF..." : $"Encoding GIF resampled to {resampleFps.ToString().Replace(",", ".")} FPS..."); + Logger.Log((resampleFps.GetFloat() <= 0) ? $"Encoding GIF..." : $"Encoding GIF resampled to {resampleFps.ToString().Replace(",", ".")} FPS..."); string framesFilename = Path.GetFileName(framesFile); string dither = Config.Get("gifDitherType").Split(' ').First(); string paletteFilter = palette ? $"-vf \"split[s0][s1];[s0]palettegen={colors}[p];[s1][p]paletteuse=dither={dither}\"" : ""; - string fpsFilter = (resampleFps <= 0) ? "" : $"fps=fps={resampleFps.ToStringDot()}"; + string fpsFilter = (resampleFps.GetFloat() <= 0) ? "" : $"fps=fps={resampleFps}"; string vf = FormatUtils.ConcatStrings(new string[] { paletteFilter, fpsFilter }); string args = $"-f concat -r {rate} -i {framesFilename.Wrap()} -gifflags -offsetting {vf} {outPath.Wrap()}"; await RunFfmpeg(args, framesFile.GetParentDir(), LogMode.OnlyLastLine, "error", TaskType.Encode);