video-retailor/Program.cs

108 lines
4.7 KiB
C#

using System;
using System.Linq;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using FFMpegCore;
namespace videoRetailor
{
public class analyzedMedia
{
public List<string> path { get; set; } = new List<string>();
public List<IMediaAnalysis> ffprobed { get; set; } = new List<IMediaAnalysis>();
public double TotalSeconds { get { return ffprobed.Sum(ima => ima.Duration.TotalSeconds); } }
public double durationVariance { get; set; }
}
class Program
{
static async Task Main(string[] args)
{
Console.WriteLine(Directory.GetCurrentDirectory());
var mkvFiles = Directory.GetFiles(Directory.GetCurrentDirectory(), "*.mkv");
var mediaInfos = new List<analyzedMedia>();
var totalTime = new TimeSpan();
foreach (var file in mkvFiles.OrderBy(f => f))
{
var thisMeta = new analyzedMedia();
thisMeta.path.Add(file);
thisMeta.ffprobed.Add(await FFProbe.AnalyseAsync(file));
mediaInfos.Add(thisMeta);
}
if (mediaInfos.Count < 8)
{
Console.WriteLine($"there's only {mkvFiles.Length}, can't recombine. just going to send them all as-is.");
}
else
{
foreach (var thisMeta in mediaInfos)
{
totalTime += thisMeta.ffprobed[0].Duration;
}
var averageTime = totalTime.TotalSeconds / mediaInfos.Count();
Console.WriteLine($"average time: {averageTime}");
foreach (var thisMeta in mediaInfos)
{
thisMeta.durationVariance = thisMeta.TotalSeconds / averageTime;
Console.WriteLine($"{string.Join(", ", thisMeta.path)}: {thisMeta.TotalSeconds} seconds");
Console.WriteLine($" duration ratio: {thisMeta.durationVariance}");
}
Console.WriteLine($"...am I crashing? {mediaInfos.Min(af => af.durationVariance)}");
while (mediaInfos.Count() > 7 &&
(mediaInfos.Min(af => af.durationVariance) < 0.9))
{
Console.WriteLine("gluestick at the ready.");
var idx = 0;
var targetMinDuration = mediaInfos.Min(af => af.durationVariance);
Console.WriteLine($"targetMinDuration = {targetMinDuration}");
foreach (var af in mediaInfos)
{
if (af.durationVariance == targetMinDuration)
{
break;
}
idx++;
}
var previousDuration = (idx == 0) ? Double.MaxValue : mediaInfos[idx - 1].TotalSeconds;
var nextDuration = (idx > mediaInfos.Count() - 2) ? Double.MaxValue : mediaInfos[idx - 1].TotalSeconds;
analyzedMedia partner;
if (nextDuration > previousDuration)
{
partner = mediaInfos[idx - 1];
Console.WriteLine($"combining with previous, previously at {partner.TotalSeconds}");
partner.ffprobed.AddRange(mediaInfos[idx].ffprobed);
partner.path.AddRange(mediaInfos[idx].path);
}
else
{
partner = mediaInfos[idx + 1];
Console.WriteLine($"combining with next, previously at {partner.TotalSeconds}");
mediaInfos[idx].ffprobed.AddRange(partner.ffprobed);
partner.ffprobed = mediaInfos[idx].ffprobed;
mediaInfos[idx].path.AddRange(partner.path);
partner.path = mediaInfos[idx].path;
}
mediaInfos.RemoveAt(idx);
averageTime = totalTime.TotalSeconds / mediaInfos.Count();
foreach (var thisMeta in mediaInfos)
{
thisMeta.durationVariance = thisMeta.TotalSeconds / averageTime;
}
}
}
Console.WriteLine($"{mediaInfos.Count()} infos.");
var i = 1;
foreach (var mi in mediaInfos)
{
Console.WriteLine($"going to export {string.Join(", ", mi.path)} as part {i}");
FFMpeg.Join($"./{DateTime.Today.ToShortDateString()} (part {i}/{mediaInfos.Count()}).mp4",
mi.path.ToArray()
);
i++;
}
}
}
}