mirror of
https://github.com/unclshura/splitter.git
synced 2026-06-22 00:22:01 +00:00
Logger is a non static class now. Interface extracted
This commit is contained in:
parent
78f1bb17d6
commit
14bcd31efe
13
ILogger.cs
Normal file
13
ILogger.cs
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
namespace splitter;
|
||||||
|
|
||||||
|
public interface ILogger
|
||||||
|
{
|
||||||
|
void ClearProgress(int progressLevel);
|
||||||
|
void DrawProgress(string name, int progressLine, double progress, TimeSpan eta, double speed);
|
||||||
|
void Log(string prefix, ConsoleColor color, string msg);
|
||||||
|
|
||||||
|
void LogInfo(string msg) => Log("[INFO]", ConsoleColor.Cyan, msg);
|
||||||
|
void LogSuccess(string msg) => Log("[ OK ]", ConsoleColor.Green, msg);
|
||||||
|
void LogWarn(string msg) => Log("[WARN]", ConsoleColor.Yellow, msg);
|
||||||
|
void LogError(string msg) => Log("[ERR ]", ConsoleColor.Red, msg);
|
||||||
|
}
|
||||||
35
Logger.cs
35
Logger.cs
@ -1,17 +1,15 @@
|
|||||||
namespace splitter;
|
namespace splitter;
|
||||||
|
|
||||||
public static class Logger
|
public class Logger(CommandLine cmd) : ILogger
|
||||||
{
|
{
|
||||||
static int _logLines = 0;
|
int _logLines = Math.Max(1, Environment.ProcessorCount / 2) * 2;
|
||||||
static readonly object _consoleLock = new();
|
readonly object _consoleLock = new();
|
||||||
|
|
||||||
public static bool PlainText { get; set; }
|
public void Log(string prefix, ConsoleColor color, string msg)
|
||||||
|
|
||||||
public static void Log(string prefix, ConsoleColor color, string msg)
|
|
||||||
{
|
{
|
||||||
lock (_consoleLock)
|
lock (_consoleLock)
|
||||||
{
|
{
|
||||||
if (PlainText)
|
if (cmd.PlainText)
|
||||||
{
|
{
|
||||||
Console.WriteLine($"{prefix} {msg}");
|
Console.WriteLine($"{prefix} {msg}");
|
||||||
}
|
}
|
||||||
@ -32,16 +30,11 @@ public static class Logger
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void LogInfo(string msg) => Log("[INFO]", ConsoleColor.Cyan, msg);
|
private readonly Dictionary<int, int> _progressTrack = new();
|
||||||
public static void LogSuccess(string msg) => Log("[ OK ]", ConsoleColor.Green, msg);
|
|
||||||
public static void LogWarn(string msg) => Log("[WARN]", ConsoleColor.Yellow, msg);
|
|
||||||
public static void LogError(string msg) => Log("[ERR ]", ConsoleColor.Red, msg);
|
|
||||||
|
|
||||||
private static readonly Dictionary<int, int> _progressTrack = new();
|
public void DrawProgress(string name, int progressLine, double progress, TimeSpan eta, double speed)
|
||||||
|
|
||||||
public static void DrawProgress(string name, int progressLevel, double progress, TimeSpan eta, double speed)
|
|
||||||
{
|
{
|
||||||
if (PlainText || progressLevel < 0)
|
if (cmd.PlainText || progressLine < 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Crop name to max 20 chars
|
// Crop name to max 20 chars
|
||||||
@ -60,17 +53,17 @@ public static class Logger
|
|||||||
if (filled > barWidth) filled = barWidth;
|
if (filled > barWidth) filled = barWidth;
|
||||||
|
|
||||||
// --- NEW: skip drawing if visually unchanged ---
|
// --- NEW: skip drawing if visually unchanged ---
|
||||||
if (_progressTrack.TryGetValue(progressLevel, out var lastFilled) &&
|
if (_progressTrack.TryGetValue(progressLine, out var lastFilled) &&
|
||||||
lastFilled == filled)
|
lastFilled == filled)
|
||||||
{
|
{
|
||||||
return; // no visual change → skip
|
return; // no visual change → skip
|
||||||
}
|
}
|
||||||
|
|
||||||
_progressTrack[progressLevel] = filled;
|
_progressTrack[progressLine] = filled;
|
||||||
// ------------------------------------------------
|
// ------------------------------------------------
|
||||||
|
|
||||||
var barLine = _logLines + 1 + progressLevel * 2;
|
var barLine = _logLines + 1 + progressLine * 2;
|
||||||
var infoLine = _logLines + 2 + progressLevel * 2;
|
var infoLine = _logLines + 2 + progressLine * 2;
|
||||||
|
|
||||||
// Draw progress bar
|
// Draw progress bar
|
||||||
Console.SetCursorPosition(0, barLine);
|
Console.SetCursorPosition(0, barLine);
|
||||||
@ -101,9 +94,9 @@ public static class Logger
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static void ClearProgress(int progressLevel)
|
public void ClearProgress(int progressLevel)
|
||||||
{
|
{
|
||||||
if (PlainText || progressLevel < 0)
|
if (cmd.PlainText || progressLevel < 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
lock (_consoleLock)
|
lock (_consoleLock)
|
||||||
|
|||||||
@ -1,23 +1,23 @@
|
|||||||
using System;
|
using System;
|
||||||
namespace splitter;
|
namespace splitter;
|
||||||
|
|
||||||
public abstract class LoggingBase(int progressLine)
|
public abstract class LoggingBase(ILogger _logger, int _progressLine)
|
||||||
{
|
{
|
||||||
protected void Log(string level, ConsoleColor color, string message)
|
protected void Log(string level, ConsoleColor color, string message)
|
||||||
=> Logger.Log(level, color, message);
|
=> _logger.Log(level, color, message);
|
||||||
|
|
||||||
protected void LogInfo(string message)
|
protected void LogInfo(string message)
|
||||||
=> Logger.LogInfo(message);
|
=> _logger.LogInfo(message);
|
||||||
|
|
||||||
protected void LogWarn(string message)
|
protected void LogWarn(string message)
|
||||||
=> Logger.LogWarn(message);
|
=> _logger.LogWarn(message);
|
||||||
|
|
||||||
protected void LogError(string message)
|
protected void LogError(string message)
|
||||||
=> Logger.LogError(message);
|
=> _logger.LogError(message);
|
||||||
|
|
||||||
protected void DrawProgress(string name, double percent, TimeSpan eta, double fps)
|
protected void DrawProgress(string name, double percent, TimeSpan eta, double fps)
|
||||||
=> Logger.DrawProgress(name, progressLine, percent, eta, fps);
|
=> _logger.DrawProgress(name, _progressLine, percent, eta, fps);
|
||||||
|
|
||||||
protected void ClearProgress()
|
protected void ClearProgress()
|
||||||
=> Logger.ClearProgress(progressLine);
|
=> _logger.ClearProgress(_progressLine);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,7 +7,7 @@ using FFmpeg.AutoGen;
|
|||||||
|
|
||||||
namespace splitter;
|
namespace splitter;
|
||||||
|
|
||||||
public class SimpleSplitter(int segmentNo) : LoggingBase(segmentNo), ISegmentProcessor
|
public class SimpleSplitter(int segmentNo, ILogger logger) : LoggingBase(logger, segmentNo), ISegmentProcessor
|
||||||
{
|
{
|
||||||
public async Task ProcessSegment(string inputFile, string outputFile, double start, double length, string[] passthrough)
|
public async Task ProcessSegment(string inputFile, string outputFile, double start, double length, string[] passthrough)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -18,8 +18,8 @@ public class TrackingSplitter : LoggingBase, ISegmentProcessor, IDisposable
|
|||||||
private readonly IObjectDetector _detector;
|
private readonly IObjectDetector _detector;
|
||||||
private readonly CommandLine _cmd;
|
private readonly CommandLine _cmd;
|
||||||
|
|
||||||
public TrackingSplitter(int segmentNo, int cropWidth, int cropHeight, bool debugOverlay, bool plainText, IObjectDetector detector, CommandLine cmd)
|
public TrackingSplitter(int segmentNo, int cropWidth, int cropHeight, bool debugOverlay, bool plainText, IObjectDetector detector, CommandLine cmd, ILogger logger)
|
||||||
: base(segmentNo)
|
: base(logger, segmentNo)
|
||||||
{
|
{
|
||||||
_segmentNo = segmentNo;
|
_segmentNo = segmentNo;
|
||||||
_cropWidth = cropWidth;
|
_cropWidth = cropWidth;
|
||||||
|
|||||||
@ -9,7 +9,7 @@ public sealed class UltraFaceDetector: LoggingBase, IDisposable, IObjectDetector
|
|||||||
{
|
{
|
||||||
private readonly UltraFace _ultraFace;
|
private readonly UltraFace _ultraFace;
|
||||||
|
|
||||||
public UltraFaceDetector() : base(-1)
|
public UltraFaceDetector(ILogger logger) : base(logger, -1)
|
||||||
{
|
{
|
||||||
var basePath = AppDomain.CurrentDomain.BaseDirectory;
|
var basePath = AppDomain.CurrentDomain.BaseDirectory;
|
||||||
var param = new UltraFaceParameter
|
var param = new UltraFaceParameter
|
||||||
|
|||||||
@ -59,7 +59,7 @@ public sealed class YoloOnnxObjectDetector : LoggingBase, IObjectDetector, IDisp
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public YoloOnnxObjectDetector() : base(-1)
|
public YoloOnnxObjectDetector(ILogger logger) : base(logger, -1)
|
||||||
{
|
{
|
||||||
var options = new SessionOptions();
|
var options = new SessionOptions();
|
||||||
options.AppendExecutionProvider_DML();
|
options.AppendExecutionProvider_DML();
|
||||||
|
|||||||
59
splitter.cs
59
splitter.cs
@ -5,49 +5,38 @@ using splitter;
|
|||||||
|
|
||||||
static class Program
|
static class Program
|
||||||
{
|
{
|
||||||
|
private static ILogger _logger = null!;
|
||||||
static async Task Main(string[] args)
|
static async Task Main(string[] args)
|
||||||
{
|
{
|
||||||
var cmd = new CommandLine(args);
|
var cmd = new CommandLine(args);
|
||||||
|
_logger = new Logger(cmd);
|
||||||
|
|
||||||
var estimateOnly = cmd.EstimateOnly;
|
if (!File.Exists(cmd.InputFile))
|
||||||
var forceFixed = cmd.ForceFixed;
|
|
||||||
var passthrough = cmd.Passthrough;
|
|
||||||
var inputFile = cmd.InputFile;
|
|
||||||
var outputFolder = cmd.OutputFolder;
|
|
||||||
(int width, int height)? crop = cmd.Crop;
|
|
||||||
string? mask = cmd.Mask;
|
|
||||||
var debug = cmd.Debug;
|
|
||||||
string? detect = cmd.Detect;
|
|
||||||
double? overrideTargetDuration = cmd.OverrideTargetDuration;
|
|
||||||
Logger.PlainText = cmd.PlainText;
|
|
||||||
|
|
||||||
if (!File.Exists(inputFile))
|
|
||||||
{
|
{
|
||||||
LogError("Input file not found.");
|
LogError("Input file not found.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Directory.Exists(outputFolder))
|
if (!Directory.Exists(cmd.OutputFolder))
|
||||||
Directory.CreateDirectory(outputFolder);
|
Directory.CreateDirectory(cmd.OutputFolder);
|
||||||
|
|
||||||
var baseName = Path.GetFileNameWithoutExtension(inputFile);
|
|
||||||
var outputMask = mask ?? $"{baseName}_Seg%03d.mp4";
|
|
||||||
|
|
||||||
|
var baseName = Path.GetFileNameWithoutExtension(cmd.InputFile);
|
||||||
|
var outputMask = cmd.Mask ?? $"{baseName}_Seg%03d.mp4";
|
||||||
LogInfo("Reading duration via ffprobe...");
|
LogInfo("Reading duration via ffprobe...");
|
||||||
|
|
||||||
var duration = GetDuration(inputFile);
|
var duration = GetDuration(cmd.InputFile);
|
||||||
if (duration <= 0)
|
if (duration <= 0)
|
||||||
{
|
{
|
||||||
LogError("Could not read duration.");
|
LogError("Could not read duration.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var target = overrideTargetDuration ?? 58.0;
|
var target = cmd.OverrideTargetDuration ?? 58.0;
|
||||||
|
|
||||||
int segments;
|
int segments;
|
||||||
double segmentLength;
|
double segmentLength;
|
||||||
|
|
||||||
if (forceFixed)
|
if (cmd.ForceFixed)
|
||||||
{
|
{
|
||||||
// Fixed chunk size, last one may be shorter
|
// Fixed chunk size, last one may be shorter
|
||||||
segments = (int)Math.Ceiling(duration / target);
|
segments = (int)Math.Ceiling(duration / target);
|
||||||
@ -60,13 +49,13 @@ static class Program
|
|||||||
segmentLength = duration / segments;
|
segmentLength = duration / segments;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (estimateOnly)
|
if (cmd.EstimateOnly)
|
||||||
{
|
{
|
||||||
LogInfo("=== ESTIMATE MODE ===");
|
LogInfo("=== ESTIMATE MODE ===");
|
||||||
LogInfo($"Total duration: {duration:F2}s");
|
LogInfo($"Total duration: {duration:F2}s");
|
||||||
LogInfo($"Target duration: {target:F2}s");
|
LogInfo($"Target duration: {target:F2}s");
|
||||||
LogInfo($"Segments: {segments}");
|
LogInfo($"Segments: {segments}");
|
||||||
LogInfo(forceFixed
|
LogInfo(cmd.ForceFixed
|
||||||
? $"Fixed segment length: {segmentLength:F2}s (last may be shorter)"
|
? $"Fixed segment length: {segmentLength:F2}s (last may be shorter)"
|
||||||
: $"Equalized segment length: {segmentLength:F2}s");
|
: $"Equalized segment length: {segmentLength:F2}s");
|
||||||
return;
|
return;
|
||||||
@ -77,45 +66,45 @@ static class Program
|
|||||||
LogInfo($"Equal segment length: {segmentLength:F3}s");
|
LogInfo($"Equal segment length: {segmentLength:F3}s");
|
||||||
|
|
||||||
Func<int, ISegmentProcessor> processorFactory;
|
Func<int, ISegmentProcessor> processorFactory;
|
||||||
if (crop != null)
|
if (cmd.Crop != null)
|
||||||
{
|
{
|
||||||
processorFactory = i =>
|
processorFactory = i =>
|
||||||
{
|
{
|
||||||
IObjectDetector detector = detect switch
|
IObjectDetector detector = cmd.Detect switch
|
||||||
{
|
{
|
||||||
"face" => new UltraFaceDetector(),
|
"face" => new UltraFaceDetector(_logger),
|
||||||
"body" => new YoloOnnxObjectDetector(),
|
"body" => new YoloOnnxObjectDetector(_logger),
|
||||||
_ => throw new InvalidOperationException($"Unknown detector: {detect}")
|
_ => throw new InvalidOperationException($"Unknown detector: {cmd.Detect}")
|
||||||
};
|
};
|
||||||
return new TrackingSplitter(i, crop.Value.width, crop.Value.height, debug, cmd.PlainText, detector, cmd);
|
return new TrackingSplitter(i, cmd.Crop.Value.width, cmd.Crop.Value.height, cmd.Debug, cmd.PlainText, detector, cmd, _logger);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
processorFactory = i => new SimpleSplitter(i);
|
processorFactory = i => new SimpleSplitter(i, _logger);
|
||||||
}
|
}
|
||||||
if (cmd.SingleThreaded)
|
if (cmd.SingleThreaded)
|
||||||
{
|
{
|
||||||
LogInfo("Starting single-threaded splitting...");
|
LogInfo("Starting single-threaded splitting...");
|
||||||
await RunSingleThreaded(processorFactory, inputFile, outputFolder, outputMask, duration, segments, segmentLength, passthrough);
|
await RunSingleThreaded(processorFactory, cmd.InputFile, cmd.OutputFolder, outputMask, duration, segments, segmentLength, cmd.Passthrough);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LogInfo("Starting multi-threaded splitting...");
|
LogInfo("Starting multi-threaded splitting...");
|
||||||
await RunMultiThreaded(processorFactory, inputFile, outputFolder, outputMask, duration, segments, segmentLength, passthrough);
|
await RunMultiThreaded(processorFactory, cmd.InputFile, cmd.OutputFolder, outputMask, duration, segments, segmentLength, cmd.Passthrough);
|
||||||
}
|
}
|
||||||
|
|
||||||
LogInfo("Done.");
|
LogInfo("Done.");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void LogInfo(string message)
|
private static void LogInfo(string message)
|
||||||
=> Logger.LogInfo(message);
|
=> _logger.LogInfo(message);
|
||||||
|
|
||||||
private static void LogWarn(string message)
|
private static void LogWarn(string message)
|
||||||
=> Logger.LogWarn(message);
|
=> _logger.LogWarn(message);
|
||||||
|
|
||||||
private static void LogError(string message)
|
private static void LogError(string message)
|
||||||
=> Logger.LogError(message);
|
=> _logger.LogError(message);
|
||||||
|
|
||||||
// -----------------------------
|
// -----------------------------
|
||||||
// ffprobe
|
// ffprobe
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user