mirror of
https://github.com/n00mkrad/flowframes.git
synced 2025-12-16 16:37:48 +01:00
Fix more FPS readout issues
This commit is contained in:
@@ -4,8 +4,8 @@
|
|||||||
{
|
{
|
||||||
public Fraction Fps { get; set; }
|
public Fraction Fps { get; set; }
|
||||||
public Fraction SpecifiedFps { get; set; }
|
public Fraction SpecifiedFps { get; set; }
|
||||||
public float VfrRatio { get => Fps.GetFloat() / SpecifiedFps.GetFloat(); }
|
public float VfrRatio { get => Fps.Float / SpecifiedFps.Float; }
|
||||||
public float VfrRatioInverse { get => SpecifiedFps.GetFloat() / Fps.GetFloat(); }
|
public float VfrRatioInverse { get => SpecifiedFps.Float / Fps.Float; }
|
||||||
|
|
||||||
public FpsInfo() { }
|
public FpsInfo() { }
|
||||||
|
|
||||||
|
|||||||
@@ -85,8 +85,6 @@ namespace Flowframes.Data
|
|||||||
Denominator = 1;
|
Denominator = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Console.WriteLine($"Fraction from String: Fraction(\"{text}\") => {Numerator}/{Denominator}", true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static long GetGreatestCommonDenominator(long a, long b)
|
private static long GetGreatestCommonDenominator(long a, long b)
|
||||||
@@ -248,33 +246,19 @@ namespace Flowframes.Data
|
|||||||
return new Fraction(fraction1 * fraction2.GetReciprocal()).GetReduced();
|
return new Fraction(fraction1 * fraction2.GetReciprocal()).GetReduced();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public double Double() => (double)Numerator / Denominator;
|
||||||
public double ToDouble()
|
|
||||||
{
|
|
||||||
return (double)this.Numerator / this.Denominator;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
return Numerator + "/" + Denominator;
|
return $"{Numerator}/{Denominator}";
|
||||||
}
|
}
|
||||||
|
|
||||||
public float GetFloat()
|
public float Float => Denominator < 1 ? 0f : (float)Numerator / (float)Denominator;
|
||||||
{
|
public long Long => Denominator < 1 ? 0L : (long)Numerator / (long)Denominator;
|
||||||
if (Denominator < 1) // Avoid div by zero
|
|
||||||
return 0f;
|
|
||||||
|
|
||||||
return (float)Numerator / (float)Denominator;
|
public string GetString(string format = "0.#####")
|
||||||
}
|
|
||||||
|
|
||||||
public long GetLong()
|
|
||||||
{
|
{
|
||||||
return (long)Numerator / (long)Denominator;
|
return ((float)Numerator / Denominator).ToString(format);
|
||||||
}
|
|
||||||
|
|
||||||
public string GetString()
|
|
||||||
{
|
|
||||||
return ((float)Numerator / Denominator).ToString();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ using System.IO;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
using Flowframes.Data;
|
using Flowframes.Data;
|
||||||
using System.Management.Automation;
|
using System.Management.Automation;
|
||||||
@@ -13,7 +12,6 @@ using System.Drawing;
|
|||||||
using Flowframes.MiscUtils;
|
using Flowframes.MiscUtils;
|
||||||
using Newtonsoft.Json.Converters;
|
using Newtonsoft.Json.Converters;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Win32Interop.Structs;
|
|
||||||
|
|
||||||
namespace Flowframes
|
namespace Flowframes
|
||||||
{
|
{
|
||||||
@@ -428,5 +426,11 @@ namespace Flowframes
|
|||||||
|
|
||||||
return JsonConvert.SerializeObject(o, indent ? Formatting.Indented : Formatting.None, settings);
|
return JsonConvert.SerializeObject(o, indent ? Formatting.Indented : Formatting.None, settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Remove once NmkdUtils has been adopted
|
||||||
|
public static bool EqualsRoughly(this float a, float b, float tolerance = 0.0001f)
|
||||||
|
{
|
||||||
|
return Math.Abs(a - b) < tolerance;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ namespace Flowframes.Forms
|
|||||||
InterpSettings entry = Program.batchQueue.ElementAt(i);
|
InterpSettings entry = Program.batchQueue.ElementAt(i);
|
||||||
string outFormat = Strings.OutputFormat.Get(entry.outSettings.Format.ToString());
|
string outFormat = Strings.OutputFormat.Get(entry.outSettings.Format.ToString());
|
||||||
string inPath = string.IsNullOrWhiteSpace(entry.inPath) ? "No Path" : Path.GetFileName(entry.inPath).Trunc(40);
|
string inPath = string.IsNullOrWhiteSpace(entry.inPath) ? "No Path" : Path.GetFileName(entry.inPath).Trunc(40);
|
||||||
string str = $"#{i+1}: {inPath} - {entry.inFps.GetFloat()} FPS => {entry.interpFactor}x {entry.ai.NameShort} ({entry.model.Name}) => {outFormat}";
|
string str = $"#{i+1}: {inPath} - {entry.inFps.Float} FPS => {entry.interpFactor}x {entry.ai.NameShort} ({entry.model.Name}) => {outFormat}";
|
||||||
taskList.Items.Add(str);
|
taskList.Items.Add(str);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -159,7 +159,7 @@ namespace Flowframes.Forms
|
|||||||
current.inFpsDetected = await IoUtils.GetFpsFolderOrVideo(path);
|
current.inFpsDetected = await IoUtils.GetFpsFolderOrVideo(path);
|
||||||
current.inFps = current.inFpsDetected;
|
current.inFps = current.inFpsDetected;
|
||||||
|
|
||||||
if(current.inFps.GetFloat() <= 0)
|
if(current.inFps.Float <= 0)
|
||||||
current.inFps = InterpolateUtils.AskForFramerate(new DirectoryInfo(path).Name, false);
|
current.inFps = InterpolateUtils.AskForFramerate(new DirectoryInfo(path).Name, false);
|
||||||
|
|
||||||
current.outFps = current.inFps * current.interpFactor;
|
current.outFps = current.inFps * current.interpFactor;
|
||||||
|
|||||||
@@ -387,7 +387,7 @@ namespace Flowframes.Forms.Main
|
|||||||
public void UpdateInputInfo()
|
public void UpdateInputInfo()
|
||||||
{
|
{
|
||||||
string str = $"Size: {(!currInRes.IsEmpty ? $"{currInRes.Width}x{currInRes.Height}" : "Unknown")} - ";
|
string str = $"Size: {(!currInRes.IsEmpty ? $"{currInRes.Width}x{currInRes.Height}" : "Unknown")} - ";
|
||||||
str += $"FPS: {(currInFpsDetected.GetFloat() > 0f ? FormatUtils.Fraction(currInFpsDetected) : "Unknown")} - ";
|
str += $"FPS: {(currInFpsDetected.Float > 0f ? FormatUtils.Fraction(currInFpsDetected) : "Unknown")} - ";
|
||||||
str += $"Frames: {(currInFrames > 0 ? $"{currInFrames}" : "Unknown")} - ";
|
str += $"Frames: {(currInFrames > 0 ? $"{currInFrames}" : "Unknown")} - ";
|
||||||
str += $"Duration: {(currInDuration > 0 ? FormatUtils.MsToTimestamp(currInDuration) : "Unknown")}";
|
str += $"Duration: {(currInDuration > 0 ? FormatUtils.MsToTimestamp(currInDuration) : "Unknown")}";
|
||||||
inputInfo.Text = str;
|
inputInfo.Text = str;
|
||||||
|
|||||||
@@ -599,7 +599,7 @@ namespace Flowframes.IO
|
|||||||
InterpSettings curr = Interpolate.currentSettings;
|
InterpSettings curr = Interpolate.currentSettings;
|
||||||
string max = Config.Get(Config.Key.maxFps);
|
string max = Config.Get(Config.Key.maxFps);
|
||||||
Fraction maxFps = max.Contains("/") ? new Fraction(max) : new Fraction(max.GetFloat());
|
Fraction maxFps = max.Contains("/") ? new Fraction(max) : new Fraction(max.GetFloat());
|
||||||
float fps = fpsLimit ? maxFps.GetFloat() : curr.outFps.GetFloat();
|
float fps = fpsLimit ? maxFps.Float : curr.outFps.Float;
|
||||||
|
|
||||||
Size outRes = await InterpolateUtils.GetOutputResolution(curr.inPath, true);
|
Size outRes = await InterpolateUtils.GetOutputResolution(curr.inPath, true);
|
||||||
string pattern = Config.Get(Config.Key.exportNamePattern);
|
string pattern = Config.Get(Config.Key.exportNamePattern);
|
||||||
@@ -664,14 +664,14 @@ namespace Flowframes.IO
|
|||||||
{
|
{
|
||||||
Fraction dirFps = GetVideoFramerateForDir(path);
|
Fraction dirFps = GetVideoFramerateForDir(path);
|
||||||
|
|
||||||
if (dirFps.GetFloat() > 0)
|
if (dirFps.Float > 0)
|
||||||
return dirFps;
|
return dirFps;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Fraction vidFps = await GetVideoFramerate(path);
|
Fraction vidFps = await GetVideoFramerate(path);
|
||||||
|
|
||||||
if (vidFps.GetFloat() > 0)
|
if (vidFps.Float > 0)
|
||||||
return vidFps;
|
return vidFps;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ namespace Flowframes.Main
|
|||||||
{
|
{
|
||||||
string max = Config.Get(Config.Key.maxFps);
|
string max = Config.Get(Config.Key.maxFps);
|
||||||
Fraction maxFps = max.Contains("/") ? new Fraction(max) : new Fraction(max.GetFloat());
|
Fraction maxFps = max.Contains("/") ? new Fraction(max) : new Fraction(max.GetFloat());
|
||||||
bool fpsLimit = maxFps.GetFloat() > 0f && I.currentSettings.outFps.GetFloat() > maxFps.GetFloat();
|
bool fpsLimit = maxFps.Float > 0f && I.currentSettings.outFps.Float > maxFps.Float;
|
||||||
bool dontEncodeFullFpsVid = fpsLimit && Config.GetInt(Config.Key.maxFpsMode) == 0;
|
bool dontEncodeFullFpsVid = fpsLimit && Config.GetInt(Config.Key.maxFpsMode) == 0;
|
||||||
|
|
||||||
if (!dontEncodeFullFpsVid)
|
if (!dontEncodeFullFpsVid)
|
||||||
@@ -76,11 +76,11 @@ namespace Flowframes.Main
|
|||||||
public static async Task<string> GetPipedFfmpegCmd(bool ffplay = false)
|
public static async Task<string> GetPipedFfmpegCmd(bool ffplay = false)
|
||||||
{
|
{
|
||||||
InterpSettings s = I.currentSettings;
|
InterpSettings s = I.currentSettings;
|
||||||
string encArgs = FfmpegUtils.GetEncArgs(s.outSettings, (s.ScaledResolution.IsEmpty ? s.InputResolution : s.ScaledResolution), s.outFps.GetFloat(), true).FirstOrDefault();
|
string encArgs = FfmpegUtils.GetEncArgs(s.outSettings, (s.ScaledResolution.IsEmpty ? s.InputResolution : s.ScaledResolution), s.outFps.Float, true).FirstOrDefault();
|
||||||
|
|
||||||
string max = Config.Get(Config.Key.maxFps);
|
string max = Config.Get(Config.Key.maxFps);
|
||||||
Fraction maxFps = max.Contains("/") ? new Fraction(max) : new Fraction(max.GetFloat());
|
Fraction maxFps = max.Contains("/") ? new Fraction(max) : new Fraction(max.GetFloat());
|
||||||
bool fpsLimit = maxFps.GetFloat() > 0f && s.outFps.GetFloat() > maxFps.GetFloat();
|
bool fpsLimit = maxFps.Float > 0f && s.outFps.Float > maxFps.Float;
|
||||||
|
|
||||||
// Logger.Log($"VFR Ratio: {I.currentMediaFile.VideoStreams.First().FpsInfo.VfrRatio} ({I.currentMediaFile.VideoStreams.First().FpsInfo.Fps} FPS Specified, {I.currentMediaFile.VideoStreams.First().FpsInfo.SpecifiedFps} FPS Avg)");
|
// Logger.Log($"VFR Ratio: {I.currentMediaFile.VideoStreams.First().FpsInfo.VfrRatio} ({I.currentMediaFile.VideoStreams.First().FpsInfo.Fps} FPS Specified, {I.currentMediaFile.VideoStreams.First().FpsInfo.SpecifiedFps} FPS Avg)");
|
||||||
|
|
||||||
@@ -129,7 +129,7 @@ namespace Flowframes.Main
|
|||||||
string availableFormat = Path.GetExtension(IoUtils.GetFilesSorted(framesPath, "*.*")[0]).Remove(".").Upper();
|
string availableFormat = Path.GetExtension(IoUtils.GetFilesSorted(framesPath, "*.*")[0]).Remove(".").Upper();
|
||||||
string max = Config.Get(Config.Key.maxFps);
|
string max = Config.Get(Config.Key.maxFps);
|
||||||
Fraction maxFps = max.Contains("/") ? new Fraction(max) : new Fraction(max.GetFloat());
|
Fraction maxFps = max.Contains("/") ? new Fraction(max) : new Fraction(max.GetFloat());
|
||||||
bool fpsLimit = maxFps.GetFloat() > 0f && I.currentSettings.outFps.GetFloat() > maxFps.GetFloat();
|
bool fpsLimit = maxFps.Float > 0f && I.currentSettings.outFps.Float > maxFps.Float;
|
||||||
bool dontEncodeFullFpsSeq = fpsLimit && Config.GetInt(Config.Key.maxFpsMode) == 0;
|
bool dontEncodeFullFpsSeq = fpsLimit && Config.GetInt(Config.Key.maxFpsMode) == 0;
|
||||||
string framesFile = Path.Combine(framesPath.GetParentDir(), Paths.GetFrameOrderFilename(I.currentSettings.interpFactor));
|
string framesFile = Path.Combine(framesPath.GetParentDir(), Paths.GetFrameOrderFilename(I.currentSettings.interpFactor));
|
||||||
|
|
||||||
@@ -293,7 +293,7 @@ namespace Flowframes.Main
|
|||||||
|
|
||||||
string max = Config.Get(Config.Key.maxFps);
|
string max = Config.Get(Config.Key.maxFps);
|
||||||
Fraction maxFps = max.Contains("/") ? new Fraction(max) : new Fraction(max.GetFloat());
|
Fraction maxFps = max.Contains("/") ? new Fraction(max) : new Fraction(max.GetFloat());
|
||||||
bool fpsLimit = maxFps.GetFloat() != 0 && I.currentSettings.outFps.GetFloat() > maxFps.GetFloat();
|
bool fpsLimit = maxFps.Float != 0 && I.currentSettings.outFps.Float > maxFps.Float;
|
||||||
VidExtraData extraData = await FfmpegCommands.GetVidExtraInfo(I.currentSettings.inPath);
|
VidExtraData extraData = await FfmpegCommands.GetVidExtraInfo(I.currentSettings.inPath);
|
||||||
|
|
||||||
bool dontEncodeFullFpsVid = fpsLimit && Config.GetInt(Config.Key.maxFpsMode) == 0;
|
bool dontEncodeFullFpsVid = fpsLimit && Config.GetInt(Config.Key.maxFpsMode) == 0;
|
||||||
@@ -354,9 +354,9 @@ namespace Flowframes.Main
|
|||||||
{
|
{
|
||||||
int times = -1;
|
int times = -1;
|
||||||
int minLength = Config.GetInt(Config.Key.minOutVidLength);
|
int minLength = Config.GetInt(Config.Key.minOutVidLength);
|
||||||
int minFrameCount = (minLength * I.currentSettings.outFps.GetFloat()).RoundToInt();
|
int minFrameCount = (minLength * I.currentSettings.outFps.Float).RoundToInt();
|
||||||
int outFrames = (I.currentMediaFile.FrameCount * I.currentSettings.interpFactor).RoundToInt();
|
int outFrames = (I.currentMediaFile.FrameCount * I.currentSettings.interpFactor).RoundToInt();
|
||||||
if (outFrames / I.currentSettings.outFps.GetFloat() < minLength)
|
if (outFrames / I.currentSettings.outFps.Float < minLength)
|
||||||
times = (int)Math.Ceiling((double)minFrameCount / (double)outFrames);
|
times = (int)Math.Ceiling((double)minFrameCount / (double)outFrames);
|
||||||
times--; // Not counting the 1st play (0 loops)
|
times--; // Not counting the 1st play (0 loops)
|
||||||
if (times <= 0) return -1; // Never try to loop 0 times, idk what would happen, probably nothing
|
if (times <= 0) return -1; // Never try to loop 0 times, idk what would happen, probably nothing
|
||||||
|
|||||||
@@ -88,7 +88,7 @@ namespace Flowframes.Main
|
|||||||
|
|
||||||
for (int i = 0; i < targetFrameCount; i++)
|
for (int i = 0; i < targetFrameCount; i++)
|
||||||
{
|
{
|
||||||
float currentFrameTime = 1 + (step * i).GetFloat();
|
float currentFrameTime = 1 + (step * i).Float;
|
||||||
int sourceFrameIdx = (int)Math.Floor(currentFrameTime) - 1;
|
int sourceFrameIdx = (int)Math.Floor(currentFrameTime) - 1;
|
||||||
|
|
||||||
framesList.Add(i);
|
framesList.Add(i);
|
||||||
@@ -272,7 +272,7 @@ namespace Flowframes.Main
|
|||||||
{
|
{
|
||||||
if (Interpolate.canceled) return;
|
if (Interpolate.canceled) return;
|
||||||
|
|
||||||
float currentFrameTime = 1 + (step * i).GetFloat();
|
float currentFrameTime = 1 + (step * i).Float;
|
||||||
int sourceFrameIdx = (int)Math.Floor(currentFrameTime) - 1;
|
int sourceFrameIdx = (int)Math.Floor(currentFrameTime) - 1;
|
||||||
float timestep = (currentFrameTime - (int)Math.Floor(currentFrameTime));
|
float timestep = (currentFrameTime - (int)Math.Floor(currentFrameTime));
|
||||||
bool sceneChange = (sceneDetection && (sourceFrameIdx + 1) < FrameRename.importFilenames.Length && sceneFrames.Contains(GetNameNoExt(FrameRename.importFilenames[sourceFrameIdx + 1])));
|
bool sceneChange = (sceneDetection && (sourceFrameIdx + 1) < FrameRename.importFilenames.Length && sceneFrames.Contains(GetNameNoExt(FrameRename.importFilenames[sourceFrameIdx + 1])));
|
||||||
|
|||||||
@@ -131,20 +131,20 @@ namespace Flowframes.Main
|
|||||||
}
|
}
|
||||||
|
|
||||||
string fpsLimitValue = Config.Get(Config.Key.maxFps);
|
string fpsLimitValue = Config.Get(Config.Key.maxFps);
|
||||||
float fpsLimit = (fpsLimitValue.Contains("/") ? new Fraction(fpsLimitValue).GetFloat() : fpsLimitValue.GetFloat());
|
float fpsLimit = (fpsLimitValue.Contains("/") ? new Fraction(fpsLimitValue).Float : fpsLimitValue.GetFloat());
|
||||||
int maxFps = s.outSettings.Encoder.GetInfo().MaxFramerate;
|
int maxFps = s.outSettings.Encoder.GetInfo().MaxFramerate;
|
||||||
|
|
||||||
if (passes && s.outFps.GetFloat() < 1f || (s.outFps.GetFloat() > maxFps && !(fpsLimit > 0 && fpsLimit <= maxFps)))
|
if (passes && s.outFps.Float < 1f || (s.outFps.Float > maxFps && !(fpsLimit > 0 && fpsLimit <= maxFps)))
|
||||||
{
|
{
|
||||||
string imgSeqNote = isFile ? "" : "\n\nWhen using an image sequence as input, you always have to specify the frame rate manually.";
|
string imgSeqNote = isFile ? "" : "\n\nWhen using an image sequence as input, you always have to specify the frame rate manually.";
|
||||||
UiUtils.ShowMessageBox($"Invalid output frame rate ({s.outFps.GetFloat()}).\nMust be 1-{maxFps}. Either lower the interpolation factor or use the \"Maximum Output Frame Rate\" option.{imgSeqNote}");
|
UiUtils.ShowMessageBox($"Invalid output frame rate ({s.outFps.Float}).\nMust be 1-{maxFps}. Either lower the interpolation factor or use the \"Maximum Output Frame Rate\" option.{imgSeqNote}");
|
||||||
passes = false;
|
passes = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
float fpsLimitFloat = fpsLimitValue.GetFloat();
|
float fpsLimitFloat = fpsLimitValue.GetFloat();
|
||||||
|
|
||||||
if (fpsLimitFloat > 0 && fpsLimitFloat < s.outFps.GetFloat())
|
if (fpsLimitFloat > 0 && fpsLimitFloat < s.outFps.Float)
|
||||||
Interpolate.InterpProgressMultiplier = s.outFps.GetFloat() / fpsLimitFloat;
|
Interpolate.InterpProgressMultiplier = s.outFps.Float / fpsLimitFloat;
|
||||||
else
|
else
|
||||||
Interpolate.InterpProgressMultiplier = 1f;
|
Interpolate.InterpProgressMultiplier = 1f;
|
||||||
|
|
||||||
|
|||||||
@@ -95,12 +95,12 @@ namespace Flowframes
|
|||||||
{
|
{
|
||||||
Logger.Log($"GetDuration({inputFile}) - Reading duration by demuxing.", true, false, "ffmpeg");
|
Logger.Log($"GetDuration({inputFile}) - Reading duration by demuxing.", true, false, "ffmpeg");
|
||||||
string args = $"ffmpeg -loglevel panic -stats -i {inputFile.Wrap()} -map 0:v:0 -c copy -f null NUL";
|
string args = $"ffmpeg -loglevel panic -stats -i {inputFile.Wrap()} -map 0:v:0 -c copy -f null NUL";
|
||||||
string output = NUtilsTemp.OsUtils.RunCommand($"cd /D {GetAvDir().Wrap()} && {args}");
|
var outputLines = NUtilsTemp.OsUtils.RunCommand($"cd /D {GetAvDir().Wrap()} && {args}").SplitIntoLines().Where(l => l.IsNotEmpty() && l.MatchesWildcard("*time=* *"));
|
||||||
|
|
||||||
if (!output.MatchesWildcard("*time=* *"))
|
if (outputLines == null || outputLines.Count() == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
output = output.Split("time=")[1].Split(" ")[0];
|
string output = outputLines.Last().Split("time=")[1].Split(" ")[0];
|
||||||
return (long)TimeSpan.ParseExact(output, @"hh\:mm\:ss\.ff", null).TotalMilliseconds;
|
return (long)TimeSpan.ParseExact(output, @"hh\:mm\:ss\.ff", null).TotalMilliseconds;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -145,14 +145,14 @@ namespace Flowframes
|
|||||||
|
|
||||||
if (preferFfmpeg)
|
if (preferFfmpeg)
|
||||||
{
|
{
|
||||||
if (ffmpegFps.GetFloat() > 0)
|
if (ffmpegFps.Float > 0)
|
||||||
return ffmpegFps;
|
return ffmpegFps;
|
||||||
else
|
else
|
||||||
return ffprobeFps;
|
return ffprobeFps;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (ffprobeFps.GetFloat() > 0)
|
if (ffprobeFps.Float > 0)
|
||||||
return ffprobeFps;
|
return ffprobeFps;
|
||||||
else
|
else
|
||||||
return ffmpegFps;
|
return ffmpegFps;
|
||||||
|
|||||||
@@ -15,11 +15,11 @@ namespace Flowframes.Media
|
|||||||
public static async Task FramesToVideo(string framesFile, string outPath, OutputSettings settings, Fraction fps, Fraction resampleFps, float itsScale, VidExtraData extraData, LogMode logMode = LogMode.OnlyLastLine, bool isChunk = false)
|
public static async Task FramesToVideo(string framesFile, string outPath, OutputSettings settings, Fraction fps, Fraction resampleFps, float itsScale, VidExtraData extraData, LogMode logMode = LogMode.OnlyLastLine, bool isChunk = false)
|
||||||
{
|
{
|
||||||
if (logMode != LogMode.Hidden)
|
if (logMode != LogMode.Hidden)
|
||||||
Logger.Log((resampleFps.GetFloat() <= 0) ? "Encoding video..." : $"Encoding video resampled to {resampleFps.GetString()} FPS...");
|
Logger.Log((resampleFps.Float <= 0) ? "Encoding video..." : $"Encoding video resampled to {resampleFps.GetString()} FPS...");
|
||||||
|
|
||||||
IoUtils.RenameExistingFileOrDir(outPath);
|
IoUtils.RenameExistingFileOrDir(outPath);
|
||||||
Directory.CreateDirectory(outPath.GetParentDir());
|
Directory.CreateDirectory(outPath.GetParentDir());
|
||||||
string[] encArgs = Utils.GetEncArgs(settings, (Interpolate.currentSettings.ScaledResolution.IsEmpty ? Interpolate.currentSettings.InputResolution : Interpolate.currentSettings.ScaledResolution), Interpolate.currentSettings.outFps.GetFloat());
|
string[] encArgs = Utils.GetEncArgs(settings, (Interpolate.currentSettings.ScaledResolution.IsEmpty ? Interpolate.currentSettings.InputResolution : Interpolate.currentSettings.ScaledResolution), Interpolate.currentSettings.outFps.Float);
|
||||||
|
|
||||||
string inArg = $"-f concat -i {Path.GetFileName(framesFile)}";
|
string inArg = $"-f concat -i {Path.GetFileName(framesFile)}";
|
||||||
string linksDir = Path.Combine(framesFile + Paths.symlinksSuffix);
|
string linksDir = Path.Combine(framesFile + Paths.symlinksSuffix);
|
||||||
@@ -59,7 +59,7 @@ namespace Flowframes.Media
|
|||||||
var filters = new List<string>();
|
var filters = new List<string>();
|
||||||
var extraArgs = new List<string> { Config.Get(Config.Key.ffEncArgs) };
|
var extraArgs = new List<string> { Config.Get(Config.Key.ffEncArgs) };
|
||||||
|
|
||||||
if (resampleFps.GetFloat() >= 0.1f)
|
if (resampleFps.Float >= 0.1f)
|
||||||
filters.Add($"fps={resampleFps}");
|
filters.Add($"fps={resampleFps}");
|
||||||
|
|
||||||
if (Config.GetBool(Config.Key.keepColorSpace) && extraData.HasAllValues())
|
if (Config.GetBool(Config.Key.keepColorSpace) && extraData.HasAllValues())
|
||||||
@@ -122,7 +122,7 @@ namespace Flowframes.Media
|
|||||||
|
|
||||||
string sn = $"-start_number {startNo}";
|
string sn = $"-start_number {startNo}";
|
||||||
string rate = fps.ToString().Replace(",", ".");
|
string rate = fps.ToString().Replace(",", ".");
|
||||||
string vf = (resampleFps.GetFloat() < 0.1f) ? "" : $"-vf fps=fps={resampleFps}";
|
string vf = (resampleFps.Float < 0.1f) ? "" : $"-vf fps=fps={resampleFps}";
|
||||||
string compression = format == Enums.Encoding.Encoder.Png ? pngCompr : $"-q:v {lossyQ}";
|
string compression = format == Enums.Encoding.Encoder.Png ? pngCompr : $"-q:v {lossyQ}";
|
||||||
string codec = format == Enums.Encoding.Encoder.Webp ? "-c:v libwebp" : ""; // Specify libwebp to avoid putting all frames into single animated WEBP
|
string codec = format == Enums.Encoding.Encoder.Webp ? "-c:v libwebp" : ""; // Specify libwebp to avoid putting all frames into single animated WEBP
|
||||||
string args = $"-r {rate} {inArg} {codec} {compression} {sn} {vf} -fps_mode passthrough \"{outDir}/%{Padding.interpFrames}d.{format.GetInfo().OverideExtension}\"";
|
string args = $"-r {rate} {inArg} {codec} {compression} {sn} {vf} -fps_mode passthrough \"{outDir}/%{Padding.interpFrames}d.{format.GetInfo().OverideExtension}\"";
|
||||||
@@ -132,16 +132,16 @@ namespace Flowframes.Media
|
|||||||
|
|
||||||
public static async Task FramesToGifConcat(string framesFile, string outPath, Fraction rate, bool palette, int colors, Fraction resampleFps, float itsScale, LogMode logMode = LogMode.OnlyLastLine)
|
public static async Task FramesToGifConcat(string framesFile, string outPath, Fraction rate, bool palette, int colors, Fraction resampleFps, float itsScale, LogMode logMode = LogMode.OnlyLastLine)
|
||||||
{
|
{
|
||||||
if (rate.GetFloat() > 50f && (resampleFps.GetFloat() > 50f || resampleFps.GetFloat() < 1))
|
if (rate.Float > 50f && (resampleFps.Float > 50f || resampleFps.Float < 1))
|
||||||
resampleFps = new Fraction(50, 1); // Force limit framerate as encoding above 50 will cause problems
|
resampleFps = new Fraction(50, 1); // Force limit framerate as encoding above 50 will cause problems
|
||||||
|
|
||||||
if (logMode != LogMode.Hidden)
|
if (logMode != LogMode.Hidden)
|
||||||
Logger.Log((resampleFps.GetFloat() <= 0) ? $"Encoding GIF..." : $"Encoding GIF resampled to {resampleFps.GetFloat().ToString().Replace(",", ".")} FPS...");
|
Logger.Log((resampleFps.Float <= 0) ? $"Encoding GIF..." : $"Encoding GIF resampled to {resampleFps.Float.ToString().Replace(",", ".")} FPS...");
|
||||||
|
|
||||||
string framesFilename = Path.GetFileName(framesFile);
|
string framesFilename = Path.GetFileName(framesFile);
|
||||||
string dither = Config.Get(Config.Key.gifDitherType).Split(' ').First();
|
string dither = Config.Get(Config.Key.gifDitherType).Split(' ').First();
|
||||||
string paletteFilter = palette ? $"-vf \"split[s0][s1];[s0]palettegen={colors}[p];[s1][p]paletteuse=dither={dither}\"" : "";
|
string paletteFilter = palette ? $"-vf \"split[s0][s1];[s0]palettegen={colors}[p];[s1][p]paletteuse=dither={dither}\"" : "";
|
||||||
string fpsFilter = (resampleFps.GetFloat() <= 0) ? "" : $"fps=fps={resampleFps}";
|
string fpsFilter = (resampleFps.Float <= 0) ? "" : $"fps=fps={resampleFps}";
|
||||||
string vf = FormatUtils.ConcatStrings(new string[] { paletteFilter, fpsFilter });
|
string vf = FormatUtils.ConcatStrings(new string[] { paletteFilter, fpsFilter });
|
||||||
string extraArgs = Config.Get(Config.Key.ffEncArgs);
|
string extraArgs = Config.Get(Config.Key.ffEncArgs);
|
||||||
rate = rate / new Fraction(itsScale);
|
rate = rate / new Fraction(itsScale);
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ namespace Flowframes.Media
|
|||||||
}
|
}
|
||||||
|
|
||||||
string scnDetect = $"-vf \"select='gt(scene,{Config.GetFloatString(Config.Key.scnDetectValue)})'\"";
|
string scnDetect = $"-vf \"select='gt(scene,{Config.GetFloatString(Config.Key.scnDetectValue)})'\"";
|
||||||
string rateArg = (rate.GetFloat() > 0) ? $"-fps_mode cfr -r {rate}" : "-fps_mode passthrough";
|
string rateArg = (rate.Float > 0) ? $"-fps_mode cfr -r {rate}" : "-fps_mode passthrough";
|
||||||
string args = $"{GetTrimArg(true)} {inArg} {GetImgArgs(format)} {rateArg} {scnDetect} -frame_pts 1 -s 256x144 {GetTrimArg(false)} \"{outDir}/%{Padding.inputFrames}d{format}\"";
|
string args = $"{GetTrimArg(true)} {inArg} {GetImgArgs(format)} {rateArg} {scnDetect} -frame_pts 1 -s 256x144 {GetTrimArg(false)} \"{outDir}/%{Padding.inputFrames}d{format}\"";
|
||||||
|
|
||||||
LogMode logMode = Interpolate.currentMediaFile.FrameCount > 50 ? LogMode.OnlyLastLine : LogMode.Hidden;
|
LogMode logMode = Interpolate.currentMediaFile.FrameCount > 50 ? LogMode.OnlyLastLine : LogMode.Hidden;
|
||||||
@@ -106,7 +106,7 @@ namespace Flowframes.Media
|
|||||||
string mpStr = deDupe ? GetMpdecimate(true) : "";
|
string mpStr = deDupe ? GetMpdecimate(true) : "";
|
||||||
string filters = FormatUtils.ConcatStrings(new[] { GetPadFilter(), mpStr });
|
string filters = FormatUtils.ConcatStrings(new[] { GetPadFilter(), mpStr });
|
||||||
string vf = filters.Length > 2 ? $"-vf {filters}" : "";
|
string vf = filters.Length > 2 ? $"-vf {filters}" : "";
|
||||||
bool allowCfr = rate.GetFloat() > 0 && !deDupe && Path.GetExtension(inputFile).Lower() != ".gif"; // Forcing CFR on GIFs causes issues // TODO: Maybe never use CFR???
|
bool allowCfr = rate.Float > 0 && !deDupe && Path.GetExtension(inputFile).Lower() != ".gif"; // Forcing CFR on GIFs causes issues // TODO: Maybe never use CFR???
|
||||||
string rateArg = allowCfr ? $" -fps_mode cfr -r {rate}" : "-fps_mode passthrough";
|
string rateArg = allowCfr ? $" -fps_mode cfr -r {rate}" : "-fps_mode passthrough";
|
||||||
string args = $"{GetTrimArg(true)} -itsscale {Interpolate.currentMediaFile.VideoStreams.First().FpsInfo.VfrRatio} -i {inputFile.Wrap()} {GetImgArgs(format, true, alpha)} {rateArg} -frame_pts 1 {vf} {sizeStr} {GetTrimArg(false)} \"{framesDir}/%{Padding.inputFrames}d{format}\""; LogMode logMode = Interpolate.currentMediaFile.FrameCount > 50 ? LogMode.OnlyLastLine : LogMode.Hidden;
|
string args = $"{GetTrimArg(true)} -itsscale {Interpolate.currentMediaFile.VideoStreams.First().FpsInfo.VfrRatio} -i {inputFile.Wrap()} {GetImgArgs(format, true, alpha)} {rateArg} -frame_pts 1 {vf} {sizeStr} {GetTrimArg(false)} \"{framesDir}/%{Padding.inputFrames}d{format}\""; LogMode logMode = Interpolate.currentMediaFile.FrameCount > 50 ? LogMode.OnlyLastLine : LogMode.Hidden;
|
||||||
await RunFfmpeg(args, logMode, true);
|
await RunFfmpeg(args, logMode, true);
|
||||||
|
|||||||
@@ -173,27 +173,31 @@ namespace Flowframes.Media
|
|||||||
|
|
||||||
if (streamStr.Contains("fps, ") && streamStr.Contains(" tbr"))
|
if (streamStr.Contains("fps, ") && streamStr.Contains(" tbr"))
|
||||||
{
|
{
|
||||||
string fps = streamStr.Split(", ").Where(s => s.Contains(" fps")).First().Trim().Split(' ')[0];
|
float ffmpegFps = streamStr.Split(", ").Where(s => s.Contains(" fps")).First().Trim().Split(' ')[0].GetFloat();
|
||||||
string tbr = streamStr.Split("fps, ")[1].Split(" tbr")[0].Trim();
|
float ffmpegTbr = streamStr.Split("fps, ")[1].Split(" tbr")[0].GetFloat();
|
||||||
|
var ffprobeFps = new Fraction(await GetFfprobeInfoAsync(path, showStreams, "r_frame_rate", streamIdx));
|
||||||
|
var ffprobeFpsAvg = new Fraction(await GetFfprobeInfoAsync(path, showStreams, "avg_frame_rate", streamIdx));
|
||||||
long durationMs = Interpolate.currentMediaFile.DurationMs;
|
long durationMs = Interpolate.currentMediaFile.DurationMs;
|
||||||
float fpsCalc = (float)frameCount / (durationMs / 1000f);
|
float calculatedFps = (float)Math.Round(frameCount / (durationMs / 1000f), 5);
|
||||||
fpsCalc = (float)Math.Round(fpsCalc, 5);
|
|
||||||
|
|
||||||
var info = new FpsInfo(new Fraction(fps.GetFloat())); // Set both true FPS and average FPS to this number for now
|
Fraction fps = ffprobeFps.Float > 0f ? ffprobeFps : new Fraction(ffmpegFps);
|
||||||
|
Fraction avgFps = ffprobeFpsAvg.Float > 0f ? ffprobeFpsAvg : new Fraction(ffmpegTbr);
|
||||||
|
|
||||||
Logger.Log($"FPS: {fps} - TBR: {tbr} - Est. FPS: {fpsCalc.ToString("0.#####")}", true);
|
Logger.Log($"Ffprobe FPS: {ffprobeFps} ({ffprobeFps.GetString()}) - Ffprobe Avg FPS: {ffprobeFpsAvg} ({ffprobeFpsAvg.GetString()}) - Ffmpeg FPS: {ffmpegFps} - Ffmpeg TBR: {ffmpegTbr} - Est. FPS: {calculatedFps.ToString("0.#####")}", true);
|
||||||
|
|
||||||
if (tbr != fps)
|
var info = new FpsInfo(fps); // Set both true FPS and average FPS to this number, assuming they match
|
||||||
|
|
||||||
|
if (!avgFps.Float.EqualsRoughly(fps.Float, 0.01f))
|
||||||
{
|
{
|
||||||
info.SpecifiedFps = new Fraction(tbr); // Change FPS to TBR if they mismatch
|
info.SpecifiedFps = new Fraction(avgFps); // Change FPS to TBR if they mismatch
|
||||||
}
|
}
|
||||||
|
|
||||||
float fpsEstTolerance = GetFpsEstimationTolerance(durationMs);
|
float fpsEstTolerance = GetFpsEstimationTolerance(durationMs);
|
||||||
|
|
||||||
if (Math.Abs(fps.GetFloat() - fpsCalc) > fpsEstTolerance)
|
if (Math.Abs(fps.Float - calculatedFps) > fpsEstTolerance)
|
||||||
{
|
{
|
||||||
Logger.Log($"Detected FPS {fps} is not within tolerance (+-{fpsEstTolerance}) of calculated FPS ({fpsCalc}), using estimated FPS.", true);
|
Logger.Log($"Detected FPS {fps} is not within tolerance (+-{fpsEstTolerance}) of calculated FPS ({calculatedFps}), using estimated FPS.", true);
|
||||||
info.Fps = new Fraction(fpsCalc); // Change true FPS to the estimated FPS if the estimate does not match the specified FPS
|
info.Fps = new Fraction(calculatedFps); // Change true FPS to the estimated FPS if the estimate does not match the specified FPS
|
||||||
}
|
}
|
||||||
|
|
||||||
return info;
|
return info;
|
||||||
|
|||||||
@@ -206,8 +206,8 @@ namespace Flowframes.MiscUtils
|
|||||||
return f.Numerator.ToString();
|
return f.Numerator.ToString();
|
||||||
|
|
||||||
// If number is actually fractional, show the fraction as well as the approx. decimal number
|
// If number is actually fractional, show the fraction as well as the approx. decimal number
|
||||||
string decimalStr = f.GetFloat().ToString("0.###");
|
string decimalStr = f.Float.ToString("0.###");
|
||||||
bool isPrecise = decimalStr == f.GetFloat().ToString("0.####"); // If 0.___ matches with 0.____ it means we have enough decimal places and thus it's precise
|
bool isPrecise = decimalStr == f.Float.ToString("0.####"); // If 0.___ matches with 0.____ it means we have enough decimal places and thus it's precise
|
||||||
string t = showTildeForApprox && !isPrecise ? "~" : "";
|
string t = showTildeForApprox && !isPrecise ? "~" : "";
|
||||||
return $"{f} ({t}{decimalStr})";
|
return $"{f} ({t}{decimalStr})";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,8 +43,8 @@ namespace Flowframes.Os
|
|||||||
long frameCount = (long)Interpolate.currentMediaFile.FrameCount;
|
long frameCount = (long)Interpolate.currentMediaFile.FrameCount;
|
||||||
|
|
||||||
bool trim = QuickSettingsTab.trimEnabled;
|
bool trim = QuickSettingsTab.trimEnabled;
|
||||||
long srcTrimStartFrame = trim ? (long)(Math.Round(FormatUtils.TimestampToMs(QuickSettingsTab.trimStart) / 1000f * s.InterpSettings.inFps.GetFloat())) : 0;
|
long srcTrimStartFrame = trim ? (long)(Math.Round(FormatUtils.TimestampToMs(QuickSettingsTab.trimStart) / 1000f * s.InterpSettings.inFps.Float)) : 0;
|
||||||
long srcTrimEndFrame = trim && QuickSettingsTab.doTrimEnd ? (long)(Math.Round(FormatUtils.TimestampToMs(QuickSettingsTab.trimEnd) / 1000f * s.InterpSettings.inFps.GetFloat())) - 1 : frameCount - 1;
|
long srcTrimEndFrame = trim && QuickSettingsTab.doTrimEnd ? (long)(Math.Round(FormatUtils.TimestampToMs(QuickSettingsTab.trimEnd) / 1000f * s.InterpSettings.inFps.Float)) - 1 : frameCount - 1;
|
||||||
|
|
||||||
if(trim)
|
if(trim)
|
||||||
frameCount = srcTrimEndFrame - srcTrimStartFrame;
|
frameCount = srcTrimEndFrame - srcTrimStartFrame;
|
||||||
|
|||||||
@@ -48,11 +48,11 @@ namespace Flowframes.Ui
|
|||||||
Program.mainForm.currInDuration = Interpolate.currentMediaFile.DurationMs;
|
Program.mainForm.currInDuration = Interpolate.currentMediaFile.DurationMs;
|
||||||
Program.mainForm.currInDurationCut = Program.mainForm.currInDuration;
|
Program.mainForm.currInDurationCut = Program.mainForm.currInDuration;
|
||||||
Fraction fps = Interpolate.currentMediaFile.VideoStreams.Count > 0 ? Interpolate.currentMediaFile.VideoStreams[0].Rate : new Fraction();
|
Fraction fps = Interpolate.currentMediaFile.VideoStreams.Count > 0 ? Interpolate.currentMediaFile.VideoStreams[0].Rate : new Fraction();
|
||||||
string fpsStr = fps.GetFloat() > 0 ? FormatUtils.Fraction(fps) : "Not Found";
|
string fpsStr = fps.Float > 0 ? FormatUtils.Fraction(fps) : "Not Found";
|
||||||
Program.mainForm.currInFpsDetected = fps;
|
Program.mainForm.currInFpsDetected = fps;
|
||||||
fpsInTbox.Text = fps.GetString();
|
fpsInTbox.Text = fps.GetString();
|
||||||
Logger.Log($"Video FPS: {fpsStr} - Total Number Of Frames: {Interpolate.currentMediaFile.FrameCount}", false, true);
|
Logger.Log($"Video FPS: {fpsStr} - Total Number Of Frames: {Interpolate.currentMediaFile.FrameCount}", false, true);
|
||||||
Program.mainForm.GetInputFpsTextbox().ReadOnly = (fps.GetFloat() > 0 && !Config.GetBool("allowCustomInputRate", false));
|
Program.mainForm.GetInputFpsTextbox().ReadOnly = (fps.Float > 0 && !Config.GetBool("allowCustomInputRate", false));
|
||||||
Program.mainForm.currInFps = fps;
|
Program.mainForm.currInFps = fps;
|
||||||
Program.mainForm.currInFrames = Interpolate.currentMediaFile.FrameCount;
|
Program.mainForm.currInFrames = Interpolate.currentMediaFile.FrameCount;
|
||||||
Program.mainForm.UpdateInputInfo();
|
Program.mainForm.UpdateInputInfo();
|
||||||
|
|||||||
Reference in New Issue
Block a user