mirror of
https://github.com/n00mkrad/flowframes
synced 2024-11-16 19:10:31 +01:00
ffmpeg dupes workaround, SBS ReverseRenaming fix
This commit is contained in:
parent
4d2da35727
commit
3125670bb0
@ -95,26 +95,38 @@ namespace Flowframes
|
||||
DeleteSource(inputDir);
|
||||
}
|
||||
|
||||
public static async Task FramesToMp4Vfr(string framesFile, string outPath, bool useH265, int crf, float fps, int looptimes = -1)
|
||||
public static async Task FramesToMp4Vfr(string framesFile, string outPath, bool useH265, int crf, float fps, bool inRate)
|
||||
{
|
||||
Logger.Log($"Encoding MP4 video with CRF {crf}...");
|
||||
string enc = useH265 ? "libx265" : "libx264";
|
||||
string loopStr = (looptimes > 0) ? $"-stream_loop {looptimes}" : "";
|
||||
string presetStr = $"-preset {Config.Get("ffEncPreset")}";
|
||||
string vsyncStr = Config.GetInt("vfrMode") == 0 ? "-vsync 1" : "-vsync 2";
|
||||
string vfrFilename = Path.GetFileName(framesFile);
|
||||
string args = $" {loopStr} {vsyncStr} -f concat -r {fps.ToString().Replace(",", ".")} -i {vfrFilename} -c:v {enc} -crf {crf} {presetStr} {videoEncArgs} -threads {Config.GetInt("ffEncThreads")} -c:a copy {outPath.Wrap()}";
|
||||
|
||||
string args = $" {vsyncStr} -f concat ";
|
||||
if (inRate)
|
||||
args += $"-r {fps.ToString().Replace(",", ".")} -i {vfrFilename} ";
|
||||
else
|
||||
args += $"-i {vfrFilename} -r {fps.ToString().Replace(",", ".")} ";
|
||||
|
||||
args += $"-c:v {enc} -crf {crf} {presetStr} {videoEncArgs} -threads {Config.GetInt("ffEncThreads")} -c:a copy {outPath.Wrap()}";
|
||||
await AvProcess.RunFfmpeg(args, framesFile.GetParentDir(), AvProcess.LogMode.OnlyLastLine);
|
||||
}
|
||||
|
||||
public static async Task FramesToMp4VfrChunk(string framesFile, string outPath, bool useH265, int crf, float fps)
|
||||
public static async Task FramesToMp4VfrChunk(string framesFile, string outPath, bool useH265, int crf, float fps, bool inRate)
|
||||
{
|
||||
//Logger.Log($"Encoding MP4 chunk with CRF {crf}...");
|
||||
string enc = useH265 ? "libx265" : "libx264";
|
||||
string presetStr = $"-preset {Config.Get("ffEncPreset")}";
|
||||
string vsyncStr = Config.GetInt("vfrMode") == 0 ? "-vsync 1" : "-vsync 2";
|
||||
string vfrFilename = Path.GetFileName(framesFile);
|
||||
string args = $" {vsyncStr} -f concat -r {fps.ToString().Replace(",", ".")} -i {vfrFilename} -c:v {enc} -crf {crf} {presetStr} {videoEncArgs} -threads {Config.GetInt("ffEncThreads")} -c:a copy {outPath.Wrap()}";
|
||||
|
||||
string args = $" {vsyncStr} -f concat ";
|
||||
if (inRate)
|
||||
args += $"-r {fps.ToString().Replace(",", ".")} -i {vfrFilename} ";
|
||||
else
|
||||
args += $"-i {vfrFilename} -r {fps.ToString().Replace(",", ".")} ";
|
||||
|
||||
args += $"-c:v {enc} -crf {crf} {presetStr} {videoEncArgs} -threads {Config.GetInt("ffEncThreads")} -c:a copy {outPath.Wrap()}";
|
||||
await AvProcess.RunFfmpeg(args, framesFile.GetParentDir(), AvProcess.LogMode.Hidden);
|
||||
}
|
||||
|
||||
|
@ -84,7 +84,7 @@ namespace Flowframes.Main
|
||||
int crf = h265 ? Config.GetInt("h265Crf") : Config.GetInt("h264Crf");
|
||||
|
||||
string vfrFile = Path.Combine(framesPath.GetParentDir(), $"vfr-x{i.lastInterpFactor}.ini");
|
||||
await FFmpegCommands.FramesToMp4Vfr(vfrFile, outPath, h265, crf, fps, -1);
|
||||
await FFmpegCommands.FramesToMp4Vfr(vfrFile, outPath, h265, crf, fps, i.constantFrameRate);
|
||||
|
||||
/* DELETE THIS AS SOON AS I'M SURE I CAN USE VFR WITH TIMING DISABLED
|
||||
if (Config.GetInt("timingMode") == 1 && Config.GetInt("dedupMode") != 0)
|
||||
@ -174,7 +174,7 @@ namespace Flowframes.Main
|
||||
string vfrFile = Path.Combine(i.currentTempDir, $"vfr-chunk-temp.ini");
|
||||
File.WriteAllLines(vfrFile, IOUtils.ReadLines(vfrFileOriginal).Skip(firstFrameNum * 2).Take(framesAmount * 2));
|
||||
|
||||
await FFmpegCommands.FramesToMp4VfrChunk(vfrFile, outPath, h265, crf, i.currentOutFps);
|
||||
await FFmpegCommands.FramesToMp4VfrChunk(vfrFile, outPath, h265, crf, i.currentOutFps, i.constantFrameRate);
|
||||
IOUtils.TryDeleteIfExists(vfrFile);
|
||||
}
|
||||
|
||||
|
@ -29,6 +29,7 @@ namespace Flowframes
|
||||
public static float currentInFps;
|
||||
public static float currentOutFps;
|
||||
public static int currentInputFrameCount;
|
||||
public static bool constantFrameRate;
|
||||
public static OutMode currentOutMode;
|
||||
public static bool currentInputIsFrames;
|
||||
public static bool currentlyUsingAutoEnc;
|
||||
@ -63,6 +64,7 @@ namespace Flowframes
|
||||
Utils.PathAsciiCheck(inPath, outDir);
|
||||
lastAi = ai;
|
||||
currentInputIsFrames = IOUtils.IsPathDirectory(inPath);
|
||||
currentInputFrameCount = Utils.GetInputFrameCount(inPath);
|
||||
Program.mainForm.SetStatus("Starting...");
|
||||
Program.mainForm.SetWorking(true);
|
||||
await Task.Delay(10);
|
||||
@ -144,16 +146,19 @@ namespace Flowframes
|
||||
|
||||
public static async Task PostProcessFrames (bool sbsMode = false)
|
||||
{
|
||||
currentInputFrameCount = IOUtils.GetAmountOfFiles(currentFramesPath, false, "*.png");
|
||||
|
||||
if (!Directory.Exists(currentFramesPath) || currentInputFrameCount <= 0)
|
||||
Cancel("Input frames folder is empty!");
|
||||
if (!Directory.Exists(currentFramesPath) || currentInputFrameCount <= 0 || IOUtils.GetAmountOfFiles(currentFramesPath, false, "*.png") < 2)
|
||||
Cancel("Extracted frames folder is empty!");
|
||||
|
||||
if (Config.GetInt("dedupMode") == 1)
|
||||
await MagickDedupe.Run(currentFramesPath);
|
||||
else
|
||||
MagickDedupe.ClearCache();
|
||||
|
||||
int frameCountAfterDedupe = IOUtils.GetAmountOfFiles(currentFramesPath, false, "*.png");
|
||||
int dupesPercent = 100 - (((float)frameCountAfterDedupe / currentInputFrameCount) * 100f).RoundToInt();
|
||||
constantFrameRate = dupesPercent < 5f; // Ignore VFR timings for CFR input. TODO: Figure out how to avoid dupes when using VFR timings
|
||||
Logger.Log($"{dupesPercent}% of frames are dupes, so constantFrameRate = {constantFrameRate}");
|
||||
|
||||
if (canceled) return;
|
||||
|
||||
bool useTimestamps = Config.GetInt("timingMode") == 1; // TODO: Auto-Disable timestamps if input frames are sequential, not timestamped
|
||||
|
@ -71,9 +71,7 @@ namespace Flowframes.Main
|
||||
currentOutPath = e.outPath;
|
||||
currentTempDir = InterpolateUtils.GetTempFolderLoc(currentInPath, currentOutPath);
|
||||
currentFramesPath = Path.Combine(currentTempDir, Paths.framesDir);
|
||||
|
||||
currentInterpFramesDir = Path.Combine(currentTempDir, Paths.interpDir);
|
||||
|
||||
currentInputIsFrames = IOUtils.IsPathDirectory(currentInPath);
|
||||
}
|
||||
catch
|
||||
@ -103,6 +101,7 @@ namespace Flowframes.Main
|
||||
InterpolateUtils.ShowMessage("Failed to delete existing frames folder - Make sure no file is opened in another program!", "Error");
|
||||
return;
|
||||
}
|
||||
AiProcess.filenameMap.Clear();
|
||||
bool extractAudio = true;
|
||||
Program.mainForm.SetStatus("Extracting frames from video...");
|
||||
Size resolution = IOUtils.GetVideoRes(currentInPath);
|
||||
@ -138,7 +137,7 @@ namespace Flowframes.Main
|
||||
public static async Task DoInterpolate()
|
||||
{
|
||||
currentFramesPath = Path.Combine(currentTempDir, Paths.framesDir);
|
||||
if (!Directory.Exists(currentFramesPath))
|
||||
if (!Directory.Exists(currentFramesPath) || IOUtils.GetAmountOfFiles(currentFramesPath, false, "*.png") < 2)
|
||||
{
|
||||
InterpolateUtils.ShowMessage("There are no extracted frames that can be interpolated!\nDid you run the extraction step?", "Error");
|
||||
return;
|
||||
@ -149,10 +148,13 @@ namespace Flowframes.Main
|
||||
return;
|
||||
}
|
||||
|
||||
currentInputFrameCount = InterpolateUtils.GetInputFrameCount(currentInPath);
|
||||
|
||||
foreach (string ini in Directory.GetFiles(currentTempDir, "*.ini", SearchOption.TopDirectoryOnly))
|
||||
IOUtils.TryDeleteIfExists(ini);
|
||||
|
||||
IOUtils.ReverseRenaming(AiProcess.filenameMap, true); // Get timestamps back
|
||||
|
||||
await PostProcessFrames(true);
|
||||
|
||||
lastInterpFactor = interpFactor;
|
||||
|
@ -64,6 +64,14 @@ namespace Flowframes.Main
|
||||
bigPreviewForm.SetImage(img);
|
||||
}
|
||||
|
||||
public static int GetInputFrameCount(string path)
|
||||
{
|
||||
if (IOUtils.IsPathDirectory(path))
|
||||
return IOUtils.GetAmountOfFiles(path, false);
|
||||
else
|
||||
return FFmpegCommands.GetFrameCount(path);
|
||||
}
|
||||
|
||||
public static int GetProgressWaitTime(int numFrames)
|
||||
{
|
||||
float hddMultiplier = 2f;
|
||||
|
@ -33,9 +33,9 @@ namespace Flowframes.UI
|
||||
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.");
|
||||
if (IOUtils.IsPathDirectory(path))
|
||||
Logger.Log($"Video FPS (Loaded from fps.ini): {fpsStr} - Total Number Of Frames: {IOUtils.GetAmountOfFiles(path, false)}");
|
||||
Logger.Log($"Video FPS (Loaded from fps.ini): {fpsStr} - Total Number Of Frames: {InterpolateUtils.GetInputFrameCount(path)}");
|
||||
else
|
||||
Logger.Log($"Video FPS: {fpsStr} - Total Number Of Frames: {FFmpegCommands.GetFrameCount(path)}");
|
||||
Logger.Log($"Video FPS: {fpsStr} - Total Number Of Frames: {InterpolateUtils.GetInputFrameCount(path)}");
|
||||
await Task.Delay(10);
|
||||
await PrintResolution(path);
|
||||
MagickDedupe.ClearCache();
|
||||
|
Loading…
Reference in New Issue
Block a user