mirror of
https://github.com/n00mkrad/flowframes.git
synced 2025-12-16 08:27:44 +01:00
Fix timestamps for loop frames for VFR loop videos
This commit is contained in:
@@ -32,6 +32,7 @@ namespace Flowframes
|
||||
public string framesFolder;
|
||||
public string interpFolder;
|
||||
public bool inputIsFrames;
|
||||
public bool dedupe;
|
||||
|
||||
private Size _inputResolution = new Size();
|
||||
public Size InputResolution
|
||||
|
||||
@@ -41,6 +41,7 @@ namespace Flowframes.Data
|
||||
public bool SequenceInitialized = false;
|
||||
public bool IsVfr = false;
|
||||
public List<float> InputTimestamps = new List<float>();
|
||||
public List<float> InputTimestampDurations = new List<float>();
|
||||
|
||||
public int FileCount = 1;
|
||||
public int FrameCount { get { return VideoStreams.Count > 0 ? VideoStreams[0].FrameCount : 0; } }
|
||||
|
||||
@@ -308,6 +308,7 @@ namespace Flowframes.Forms.Main
|
||||
inPath = inputTbox.Text.Trim(),
|
||||
outPath = outputTbox.Text.Trim(),
|
||||
ai = ai,
|
||||
dedupe = Config.GetInt(Config.Key.dedupMode) != 0,
|
||||
inFpsDetected = currInFpsDetected,
|
||||
inFps = currInFps,
|
||||
interpFactor = interpFactorCombox.GetFloat(),
|
||||
|
||||
@@ -387,7 +387,16 @@ namespace Flowframes.Main
|
||||
|
||||
public static void MuxTimestamps(string vidPath)
|
||||
{
|
||||
Logger.Log($"Muxing timestamps for '{vidPath}'", hidden: true);
|
||||
if (I.currentSettings.dedupe)
|
||||
{
|
||||
Logger.Log($"{nameof(MuxTimestamps)}: Dedupe was used; won't mux timestamps for '{vidPath}'", hidden: true);
|
||||
return;
|
||||
}
|
||||
|
||||
Logger.Log($"{nameof(MuxTimestamps)}: Muxing timestamps for '{vidPath}'", hidden: true);
|
||||
float avgDuration = I.currentMediaFile.InputTimestampDurations.Average();
|
||||
I.currentMediaFile.InputTimestamps.Add(I.currentMediaFile.InputTimestamps.Last() + avgDuration); // Add extra frame using avg. duration, needed for duration matching or looping
|
||||
|
||||
var resampledTs = I.currentMediaFile.GetResampledTimestamps(I.currentMediaFile.InputTimestamps, I.currentSettings.interpFactor);
|
||||
var tsFileLines = new List<string>() { "# timecode format v2" };
|
||||
|
||||
@@ -401,15 +410,20 @@ namespace Flowframes.Main
|
||||
string outPath = Path.ChangeExtension(vidPath, ".tmp.mkv");
|
||||
string args = $"mkvmerge --output {outPath.Wrap()} --timestamps \"0:{tsFile}\" {vidPath.Wrap()}";
|
||||
var outputMux = NUtilsTemp.OsUtils.RunCommand($"cd /D {Path.Combine(Paths.GetPkgPath(), Paths.audioVideoDir).Wrap()} && {args}");
|
||||
Logger.Log(outputMux, hidden: true);
|
||||
|
||||
// Check if file exists and is not too small (min. 80% of input file)
|
||||
if (File.Exists(outPath) && ((double)new FileInfo(outPath).Length / (double)new FileInfo(vidPath).Length) > 0.8d)
|
||||
{
|
||||
Logger.Log($"Deleting '{vidPath}' and moving '{outPath}' to '{vidPath}'", hidden: true);
|
||||
Logger.Log($"{nameof(MuxTimestamps)}: Deleting '{vidPath}' and moving '{outPath}' to '{vidPath}'", hidden: true);
|
||||
File.Delete(vidPath);
|
||||
File.Move(outPath, vidPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.Log(outputMux, hidden: true);
|
||||
Logger.Log($"{nameof(MuxTimestamps)}: Timestamp muxing failed, keeping original video file", hidden: true);
|
||||
IoUtils.TryDeleteIfExists(outPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -219,12 +219,15 @@ namespace Flowframes
|
||||
|
||||
mediaFile.InputTimestamps = new List<float>(timestamps);
|
||||
|
||||
float avgDuration = timestampDurations.Average();
|
||||
float maxDeviationMs = (timestampDurations.Max() - timestampDurations.Min()) * 1000f;
|
||||
float maxDeviationPercent = ((timestampDurations.Max() / timestampDurations.Min()) * 100f) - 100;
|
||||
// float maxDeviationMsResampled = (timestampDurationsRes.Max() - timestampDurationsRes.Min()) * 1000f;
|
||||
Logger.Log($"Min ts duration: {timestampDurations.Min() * 1000f} ms - Max ts duration: {timestampDurations.Max() * 1000f} ms - Biggest deviation: {maxDeviationMs.ToString("0.##")} ms", hidden: true);
|
||||
Logger.Log($"Timestamp durations - Min: {timestampDurations.Min() * 1000f} ms - Max: {timestampDurations.Max() * 1000f} ms - Avg: {avgDuration * 1000f} - Biggest deviation: {maxDeviationMs.ToString("0.##")} ms", hidden: true);
|
||||
// Logger.Log($"Resampled - Min ts duration: {timestampDurationsRes.Min() * 1000f} ms - Max ts duration: {timestampDurationsRes.Max() * 1000f} ms - Biggest deviation: {maxDeviationMsResampled.ToString("0.##")} ms", hidden: true);
|
||||
|
||||
mediaFile.InputTimestampDurations = new List<float>(timestampDurations);
|
||||
|
||||
if (maxDeviationPercent > 20f)
|
||||
{
|
||||
Logger.Log($"Max timestamp deviation is {maxDeviationPercent.ToString("0.##")}% or {maxDeviationMs} ms - Assuming VFR input!", hidden: true);
|
||||
|
||||
@@ -68,7 +68,7 @@ namespace Flowframes.Media
|
||||
|
||||
if (resampleFps.Float >= 0.1f)
|
||||
{
|
||||
if (Interpolate.currentMediaFile.IsVfr)
|
||||
if (Interpolate.currentMediaFile.IsVfr && !Interpolate.currentSettings.dedupe)
|
||||
{
|
||||
Logger.Log($"Ignoring {resampleFps.Float} FPS limit as this is currently unsupported for variable framerate videos.");
|
||||
}
|
||||
|
||||
@@ -381,7 +381,7 @@ namespace Flowframes.Os
|
||||
string pkgDir = Path.Combine(Paths.GetPkgPath(), Implementations.rifeNcnnVs.PkgDir);
|
||||
int gpuId = Config.Get(Config.Key.ncnnGpus).Split(',')[0].GetInt();
|
||||
|
||||
VapourSynthUtils.VsSettings vsSettings = new VapourSynthUtils.VsSettings()
|
||||
var vsSettings = new VapourSynthUtils.VsSettings()
|
||||
{
|
||||
InterpSettings = Interpolate.currentSettings,
|
||||
ModelDir = mdl,
|
||||
@@ -409,7 +409,8 @@ namespace Flowframes.Os
|
||||
AiStarted(rifeNcnnVs, 1000, inPath);
|
||||
}
|
||||
|
||||
rifeNcnnVs.StartInfo.Arguments = $"{OsUtils.GetCmdArg()} cd /D {pkgDir.Wrap()} & vspipe {VapourSynthUtils.CreateScript(vsSettings).Wrap()} {VapourSynthUtils.GetVsPipeArgs(vsSettings)} -c y4m - | {pipedTargetArgs}";
|
||||
string vsPipeArgs = $"{VapourSynthUtils.CreateScript(vsSettings).Wrap()} {VapourSynthUtils.GetVsPipeArgs(vsSettings)} -c y4m -";
|
||||
rifeNcnnVs.StartInfo.Arguments = $"{OsUtils.GetCmdArg()} cd /D {pkgDir.Wrap()} & vspipe {vsPipeArgs} | {pipedTargetArgs}";
|
||||
|
||||
Logger.Log("cmd.exe " + rifeNcnnVs.StartInfo.Arguments, true);
|
||||
|
||||
|
||||
@@ -154,12 +154,12 @@ namespace Flowframes.Os
|
||||
{
|
||||
if (s.Loop)
|
||||
{
|
||||
l.Add($"clip = clip.std.Trim(0, {targetFrameCountMatchDuration - 1}) # Trim, loop enabled"); // -1 because we use index, not count
|
||||
l.Add($"clip = clip.std.Trim(length={targetFrameCountMatchDuration}) # Trim, loop enabled");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!s.MatchDuration)
|
||||
l.Add($"clip = clip.std.Trim(0, {targetFrameCountTrue - 1}) # Trim, loop disabled, duration matching disabled"); // -1 because we use index, not count
|
||||
l.Add($"clip = clip.std.Trim(length={targetFrameCountTrue}) # Trim, loop disabled, duration matching disabled");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user