2021-09-28 20:44:08 +02:00
using Flowframes.Data ;
using Flowframes.IO ;
using System ;
using System.Collections.Generic ;
using System.Diagnostics ;
using System.IO ;
using System.Linq ;
using System.Text ;
using System.Threading.Tasks ;
using Flowframes.MiscUtils ;
using Flowframes.Ui ;
using I = Flowframes . Interpolate ;
using Newtonsoft.Json ;
namespace Flowframes.Main
{
class AutoEncodeResume
{
public static List < string > processedInputFrames = new List < string > ( ) ;
public static int encodedChunks = 0 ;
public static int encodedFrames = 0 ;
2021-09-29 11:22:43 +02:00
public static bool resumeNextRun ;
public static string interpSettingsFilename = "settings.json" ;
public static string chunksFilename = "chunks.json" ;
public static string inputFramesFilename = "input-frames.json" ;
2021-09-28 20:44:08 +02:00
public static void Reset ( )
{
processedInputFrames = new List < string > ( ) ;
encodedChunks = 0 ;
encodedFrames = 0 ;
}
public static void Save ( )
{
2022-07-20 18:10:31 +02:00
string saveDir = Path . Combine ( I . currentSettings . tempFolder , Paths . resumeDir ) ;
2021-09-28 20:44:08 +02:00
Directory . CreateDirectory ( saveDir ) ;
2021-09-29 11:22:43 +02:00
string chunksJsonPath = Path . Combine ( saveDir , chunksFilename ) ;
2021-09-28 20:44:08 +02:00
Dictionary < string , string > saveData = new Dictionary < string , string > ( ) ;
saveData . Add ( "encodedChunks" , encodedChunks . ToString ( ) ) ;
saveData . Add ( "encodedFrames" , encodedFrames . ToString ( ) ) ;
File . WriteAllText ( chunksJsonPath , JsonConvert . SerializeObject ( saveData , Formatting . Indented ) ) ;
2021-09-29 11:22:43 +02:00
string inputFramesJsonPath = Path . Combine ( saveDir , inputFramesFilename ) ;
2021-09-28 20:44:08 +02:00
File . WriteAllText ( inputFramesJsonPath , JsonConvert . SerializeObject ( processedInputFrames , Formatting . Indented ) ) ;
2021-09-29 11:22:43 +02:00
string settingsJsonPath = Path . Combine ( saveDir , interpSettingsFilename ) ;
2022-07-20 18:10:31 +02:00
File . WriteAllText ( settingsJsonPath , JsonConvert . SerializeObject ( I . currentSettings , Formatting . Indented ) ) ;
2021-09-29 11:22:43 +02:00
}
public static void LoadTempFolder ( string tempFolderPath )
{
try
{
string resumeFolderPath = Path . Combine ( tempFolderPath , Paths . resumeDir ) ;
string settingsJsonPath = Path . Combine ( resumeFolderPath , interpSettingsFilename ) ;
InterpSettings interpSettings = JsonConvert . DeserializeObject < InterpSettings > ( File . ReadAllText ( settingsJsonPath ) ) ;
Program . mainForm . LoadBatchEntry ( interpSettings ) ;
}
catch ( Exception e )
{
Logger . Log ( $"Failed to load resume data: {e.Message}\n{e.StackTrace}" ) ;
resumeNextRun = false ;
}
}
public static async Task < bool > PrepareResumedRun ( ) // Remove already interpolated frames, return true if interpolation should be skipped
{
if ( ! resumeNextRun ) return false ;
try
{
2022-07-20 18:10:31 +02:00
string chunkJsonPath = Path . Combine ( I . currentSettings . tempFolder , Paths . resumeDir , chunksFilename ) ;
string inFramesJsonPath = Path . Combine ( I . currentSettings . tempFolder , Paths . resumeDir , inputFramesFilename ) ;
2021-09-29 11:22:43 +02:00
dynamic chunksData = JsonConvert . DeserializeObject ( File . ReadAllText ( chunkJsonPath ) ) ;
encodedChunks = chunksData . encodedChunks ;
encodedFrames = chunksData . encodedFrames ;
List < string > processedInputFrames = JsonConvert . DeserializeObject < List < string > > ( File . ReadAllText ( inFramesJsonPath ) ) ;
int uniqueInputFrames = processedInputFrames . Distinct ( ) . Count ( ) ;
foreach ( string inputFrameName in processedInputFrames )
{
2022-07-20 18:10:31 +02:00
string inputFrameFullPath = Path . Combine ( I . currentSettings . tempFolder , Paths . framesDir , inputFrameName ) ;
2021-09-29 11:22:43 +02:00
IoUtils . TryDeleteIfExists ( inputFrameFullPath ) ;
}
2022-07-20 18:10:31 +02:00
string videoChunksFolder = Path . Combine ( I . currentSettings . tempFolder , Paths . chunksDir ) ;
2021-09-29 23:49:26 +02:00
2021-09-30 00:33:19 +02:00
FileInfo [ ] invalidChunks = IoUtils . GetFileInfosSorted ( videoChunksFolder , true , "????.*" ) . Skip ( encodedChunks ) . ToArray ( ) ;
2021-09-29 23:49:26 +02:00
foreach ( FileInfo chunk in invalidChunks )
chunk . Delete ( ) ;
2022-07-20 18:10:31 +02:00
int inputFramesLeft = IoUtils . GetAmountOfFiles ( Path . Combine ( I . currentSettings . tempFolder , Paths . framesDir ) , false ) ;
2021-09-29 11:22:43 +02:00
2021-09-30 19:57:59 +02:00
Logger . Log ( $"Resume: Already encoded {encodedFrames} frames in {encodedChunks} chunks. There are now {inputFramesLeft} input frames left to interpolate." ) ;
2021-09-29 11:22:43 +02:00
if ( inputFramesLeft < 2 )
{
if ( IoUtils . GetAmountOfFiles ( videoChunksFolder , true , "*.*" ) > 0 )
{
Logger . Log ( $"No more frames left to interpolate - Merging existing video chunks instead." ) ;
2022-07-20 18:10:31 +02:00
await Export . ChunksToVideo ( I . currentSettings . tempFolder , videoChunksFolder , I . currentSettings . outPath ) ;
2021-09-29 11:22:43 +02:00
await I . Done ( ) ;
}
else
{
I . Cancel ( "There are no more frames left to interpolate in this temp folder!" ) ;
}
return true ;
}
return false ;
}
catch ( Exception e )
{
Logger . Log ( $"Failed to prepare resumed run: {e.Message}\n{e.StackTrace}" ) ;
I . Cancel ( "Failed to resume interpolation. Check the logs for details." ) ;
resumeNextRun = false ;
return true ;
}
// string stateFilepath = Path.Combine(I.current.tempFolder, Paths.resumeDir, resumeFilename);
// ResumeState state = new ResumeState(File.ReadAllText(stateFilepath));
//
// string fileMapFilepath = Path.Combine(I.current.tempFolder, Paths.resumeDir, filenameMapFilename);
// List<string> inputFrameLines = File.ReadAllLines(fileMapFilepath).Where(l => l.Trim().Length > 3).ToList();
// List<string> inputFrames = inputFrameLines.Select(l => Path.Combine(I.current.framesFolder, l.Split('|')[1])).ToList();
//
// for (int i = 0; i < state.interpolatedInputFrames; i++)
// {
// IoUtils.TryDeleteIfExists(inputFrames[i]);
// if (i % 1000 == 0) await Task.Delay(1);
// }
//
// Directory.Move(I.current.interpFolder, I.current.interpFolder + Paths.prevSuffix); // Move existing interp frames
// Directory.CreateDirectory(I.current.interpFolder); // Re-create empty interp folder
2021-09-28 20:44:08 +02:00
}
}
}