mirror of
https://github.com/n00mkrad/flowframes.git
synced 2025-12-25 12:49:26 +01:00
Mux backup video after each vchunk
TODO: Remove .bak video after muxing final video
This commit is contained in:
@@ -21,7 +21,7 @@ namespace Flowframes.IO
|
||||
{
|
||||
class IOUtils
|
||||
{
|
||||
public static Image GetImage(string path)
|
||||
public static Image GetImage(string path, bool allowMagickFallback = true, bool log = true)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -34,12 +34,17 @@ namespace Flowframes.IO
|
||||
{
|
||||
MagickImage img = new MagickImage(path);
|
||||
Bitmap bitmap = img.ToBitmap();
|
||||
Logger.Log($"GetImage: Native image reading for '{Path.GetFileName(path)}' failed - Using Magick.NET fallback instead.", true);
|
||||
|
||||
if(log)
|
||||
Logger.Log($"GetImage: Native image reading for '{Path.GetFileName(path)}' failed - Using Magick.NET fallback instead.", true);
|
||||
|
||||
return bitmap;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.Log($"GetImage failed: {e.Message}", true);
|
||||
if (log)
|
||||
Logger.Log($"GetImage failed: {e.Message}", true);
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -128,6 +128,7 @@ namespace Flowframes.Main
|
||||
lastEncodedFrameNum = (frameLinesToEncode.Last() + 1);
|
||||
|
||||
videoIndex++;
|
||||
await CreateVideo.ChunksToVideos(Interpolate.current.tempFolder, videoChunksFolder, Interpolate.current.outPath, true);
|
||||
busy = false;
|
||||
}
|
||||
catch (Exception e)
|
||||
|
||||
@@ -11,6 +11,7 @@ using System.Diagnostics;
|
||||
using Flowframes.Data;
|
||||
using Flowframes.Media;
|
||||
using Microsoft.VisualBasic.Logging;
|
||||
using Flowframes.MiscUtils;
|
||||
|
||||
namespace Flowframes.Main
|
||||
{
|
||||
@@ -160,7 +161,7 @@ namespace Flowframes.Main
|
||||
}
|
||||
}
|
||||
|
||||
public static async Task ChunksToVideos(string tempFolder, string chunksFolder, string baseOutPath)
|
||||
public static async Task ChunksToVideos(string tempFolder, string chunksFolder, string baseOutPath, bool isBackup = false)
|
||||
{
|
||||
if (IOUtils.GetAmountOfFiles(chunksFolder, true, "*" + FFmpegUtils.GetExt(I.current.outMode)) < 1)
|
||||
{
|
||||
@@ -168,8 +169,11 @@ namespace Flowframes.Main
|
||||
return;
|
||||
}
|
||||
|
||||
await Task.Delay(10);
|
||||
Program.mainForm.SetStatus("Merging video chunks...");
|
||||
NmkdStopwatch sw = new NmkdStopwatch();
|
||||
|
||||
if(!isBackup)
|
||||
Program.mainForm.SetStatus("Merging video chunks...");
|
||||
|
||||
try
|
||||
{
|
||||
DirectoryInfo chunksDir = new DirectoryInfo(chunksFolder);
|
||||
@@ -186,21 +190,33 @@ namespace Flowframes.Main
|
||||
Logger.Log($"CreateVideo: Running MergeChunks() for frames file '{Path.GetFileName(tempConcatFile)}'", true);
|
||||
bool fpsLimit = dir.Name.Contains(Paths.fpsLimitSuffix);
|
||||
string outPath = Path.Combine(baseOutPath, await IOUtils.GetCurrentExportFilename(fpsLimit, true));
|
||||
await MergeChunks(tempConcatFile, outPath);
|
||||
await MergeChunks(tempConcatFile, outPath, isBackup);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.Log("ChunksToVideo Error: " + e.Message, false);
|
||||
MessageBox.Show("An error occured while trying to merge the video chunks.\nCheck the log for details.");
|
||||
Logger.Log("ChunksToVideo Error: " + e.Message, isBackup);
|
||||
|
||||
if (!isBackup)
|
||||
MessageBox.Show("An error occured while trying to merge the video chunks.\nCheck the log for details.");
|
||||
}
|
||||
|
||||
Logger.Log($"Merged video chunks in {sw.GetElapsedStr()}", true);
|
||||
}
|
||||
|
||||
static async Task MergeChunks(string vfrFile, string outPath)
|
||||
static async Task MergeChunks(string framesFile, string outPath, bool isIncomplete = false)
|
||||
{
|
||||
await FfmpegCommands.ConcatVideos(vfrFile, outPath, -1);
|
||||
await MuxOutputVideo(I.current.inPath, outPath);
|
||||
await Loop(outPath, await GetLoopTimes());
|
||||
if (isIncomplete)
|
||||
{
|
||||
outPath = IOUtils.FilenameSuffix(outPath, ".bak");
|
||||
await IOUtils.TryDeleteIfExistsAsync(outPath);
|
||||
}
|
||||
|
||||
await FfmpegCommands.ConcatVideos(framesFile, outPath, -1, !isIncomplete);
|
||||
await MuxOutputVideo(I.current.inPath, outPath, isIncomplete, !isIncomplete);
|
||||
|
||||
if(!isIncomplete)
|
||||
await Loop(outPath, await GetLoopTimes());
|
||||
}
|
||||
|
||||
public static async Task EncodeChunk(string outPath, I.OutMode mode, int firstFrameNum, int framesAmount)
|
||||
@@ -251,7 +267,7 @@ namespace Flowframes.Main
|
||||
return times;
|
||||
}
|
||||
|
||||
public static async Task MuxOutputVideo(string inputPath, string outVideo)
|
||||
public static async Task MuxOutputVideo(string inputPath, string outVideo, bool shortest = false, bool showLog = true)
|
||||
{
|
||||
if (!File.Exists(outVideo))
|
||||
{
|
||||
@@ -262,7 +278,8 @@ namespace Flowframes.Main
|
||||
if (!Config.GetBool(Config.Key.keepAudio) && !Config.GetBool(Config.Key.keepAudio))
|
||||
return;
|
||||
|
||||
Program.mainForm.SetStatus("Muxing audio/subtitles into video...");
|
||||
if(showLog)
|
||||
Program.mainForm.SetStatus("Muxing audio/subtitles into video...");
|
||||
|
||||
if (I.current.inputIsFrames)
|
||||
{
|
||||
@@ -272,11 +289,11 @@ namespace Flowframes.Main
|
||||
|
||||
try
|
||||
{
|
||||
await FfmpegAudioAndMetadata.MergeStreamsFromInput(inputPath, outVideo, I.current.tempFolder);
|
||||
await FfmpegAudioAndMetadata.MergeStreamsFromInput(inputPath, outVideo, I.current.tempFolder, shortest);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.Log("Failed to merge audio/subtitles with output video!");
|
||||
Logger.Log("Failed to merge audio/subtitles with output video!", !showLog);
|
||||
Logger.Log("MergeAudio() Exception: " + e.Message, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,8 @@ namespace Flowframes.Media
|
||||
partial class FfmpegAudioAndMetadata : FfmpegCommands
|
||||
{
|
||||
#region Mux From Input
|
||||
public static async Task MergeStreamsFromInput (string inputVideo, string interpVideo, string tempFolder)
|
||||
|
||||
public static async Task MergeStreamsFromInput (string inputVideo, string interpVideo, string tempFolder, bool shortest)
|
||||
{
|
||||
if (!File.Exists(inputVideo) && !I.current.inputIsFrames)
|
||||
{
|
||||
@@ -48,6 +49,7 @@ namespace Flowframes.Media
|
||||
bool isMkv = I.current.outMode == I.OutMode.VidMkv;
|
||||
string mkvFix = isMkv ? "-max_interleave_delta 0" : ""; // https://reddit.com/r/ffmpeg/comments/efddfs/starting_new_cluster_due_to_timestamp/
|
||||
string metaArg = (isMkv && meta) ? "-map 1:t?" : ""; // https://reddit.com/r/ffmpeg/comments/fw4jnh/how_to_make_ffmpeg_keep_attached_images_in_mkv_as/
|
||||
string shortestArg = shortest ? "-shortest" : "";
|
||||
|
||||
if (QuickSettingsTab.trimEnabled)
|
||||
{
|
||||
@@ -57,14 +59,14 @@ namespace Flowframes.Media
|
||||
string args1 = $"{trim[0]} -i {inputVideo.Wrap()} {trim[1]} -map 0 -map -0:v -map -0:d -c copy {audioArgs} {subArgs} {otherStreamsName}"; // Extract trimmed
|
||||
await RunFfmpeg(args1, tempFolder, LogMode.Hidden);
|
||||
|
||||
string args2 = $"-i {inName} -i {otherStreamsName} -map 0:v:0 -map 1:a:? -map 1:s:? {metaArg} -c copy {audioArgs} {subArgs} {mkvFix} {outName}"; // Merge interp + trimmed original
|
||||
string args2 = $"-i {inName} -i {otherStreamsName} -map 0:v:0 -map 1:a:? -map 1:s:? {metaArg} -c copy {audioArgs} {subArgs} {mkvFix} {shortestArg} {outName}"; // Merge interp + trimmed original
|
||||
await RunFfmpeg(args2, tempFolder, LogMode.Hidden);
|
||||
|
||||
IOUtils.TryDeleteIfExists(Path.Combine(tempFolder, otherStreamsName));
|
||||
}
|
||||
else // If trimming is disabled we can pull the streams directly from the input file
|
||||
{
|
||||
string args = $"-i {inName} -i {inputVideo.Wrap()} -map 0:v:0 -map 1:a:? -map 1:s:? {metaArg} -c copy {audioArgs} {subArgs} {mkvFix} {outName}";
|
||||
string args = $"-i {inName} -i {inputVideo.Wrap()} -map 0:v:0 -map 1:a:? -map 1:s:? {metaArg} -c copy {audioArgs} {subArgs} {mkvFix} {shortestArg} {outName}";
|
||||
await RunFfmpeg(args, tempFolder, LogMode.Hidden);
|
||||
}
|
||||
|
||||
|
||||
@@ -34,10 +34,12 @@ namespace Flowframes
|
||||
return $"pad=width=ceil(iw/{padPixels})*{padPixels}:height=ceil(ih/{padPixels})*{padPixels}:color=black@0";
|
||||
}
|
||||
|
||||
public static async Task ConcatVideos(string concatFile, string outPath, int looptimes = -1)
|
||||
public static async Task ConcatVideos(string concatFile, string outPath, int looptimes = -1, bool showLog = true)
|
||||
{
|
||||
Logger.Log($"ConcatVideos('{Path.GetFileName(concatFile)}', '{outPath}', {looptimes})", true, false, "ffmpeg");
|
||||
Logger.Log($"Merging videos...", false, Logger.GetLastLine().Contains("frame"));
|
||||
|
||||
if(showLog)
|
||||
Logger.Log($"Merging videos...", false, Logger.GetLastLine().Contains("frame"));
|
||||
|
||||
IOUtils.RenameExistingFile(outPath);
|
||||
string loopStr = (looptimes > 0) ? $"-stream_loop {looptimes}" : "";
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
using Flowframes.IO;
|
||||
using Flowframes.MiscUtils;
|
||||
using Flowframes.OS;
|
||||
using Flowframes.UI;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Drawing;
|
||||
@@ -13,7 +11,6 @@ using System.Windows.Forms;
|
||||
using Flowframes.Forms;
|
||||
using Flowframes.Main;
|
||||
using I = Flowframes.Interpolate;
|
||||
using Padding = Flowframes.Data.Padding;
|
||||
|
||||
namespace Flowframes.UI
|
||||
{
|
||||
@@ -125,7 +122,7 @@ namespace Flowframes.UI
|
||||
{
|
||||
if (bigPreviewForm == null && !preview.Visible /* ||Program.mainForm.WindowState != FormWindowState.Minimized */ /* || !Program.mainForm.IsInFocus()*/) return; // Skip if the preview is not visible or the form is not in focus
|
||||
if (timeSinceLastPreviewUpdate.IsRunning && timeSinceLastPreviewUpdate.ElapsedMilliseconds < previewUpdateRateMs) return;
|
||||
Image img = IOUtils.GetImage(latestFramePath);
|
||||
Image img = IOUtils.GetImage(latestFramePath, false, false);
|
||||
SetPreviewImg(img);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user