using System.Globalization; namespace splitter; public class SingleJob { /// /// File path of the input video. This is required for each job and should be /// set to a valid video file path. The splitter will read this file, analyze it, /// and split it into segments based on the specified parameters. /// The output segments will be saved in the OutputFolder with names /// derived from this input file and the Mask pattern if provided. /// public string InputFile { get; set; } = null!; /// /// Output folder where the split segments will be saved. This should be set /// to a valid directory path. /// public string OutputFolder { get; set; } = null!; /// /// Crop parameters. Width and height for cropping the video. If set, the /// splitter will crop the video to the specified dimensions while tracking the subject. /// public (int width, int height)? Crop { get; set; } /// /// The fallback point to gravitate towards when tracking the subject. Coordinates are normalized (0.0 to 1.0). /// By default , the splitter gravitates towards the center of the frame (0.5, 0.5). /// Setting this allows you to bias the tracking towards a specific area of the frame, /// such as left-center (0.2, 0.5) or top-right (0.8, 0.2). This can be useful for /// videos where the subject tends to be off-center or for creative framing choices. /// public Point2f GravitateTo { get; set; } = new Point2f(0.5f, 0.5f); /// /// Destination file mask. /// public string? Mask { get; set; } /// /// Instead of producing the output, just generate debug frames with tracking /// overlay to visually verify that the tracking is working correctly. /// public bool Debug { get; set; } /// /// Type of detector to use for tracking. Supported values are: face (UltraFace), /// body (YoloOnnx, default), none (no tracking, just a center point). /// public string? Detect { get; set; } /// /// Detection confidence threshold. This is a value between 0.0 and 1.0 that sets the minimum confidence /// public float ScoreThreshold { get; set; } = 0.25f; /// /// Face or human detectors should only report detections if their upper bound starts below this threshold. /// This is a value between 0.0 and 1.0 mapped to 0..Height. /// public float DetectAbove { get; set; } = 0.7f; /// /// Object ID to track. This is a hexadecimal string that identifies a specific face or /// person to track across segments. This is useful when you want to consistently track the same person /// publacross all segments of a video, even if there are multiple people present /// The ID can be obtained when running with --debug or from the debug overlay. /// public ulong? DetectId { get; set; } /// /// Set starget segments length explicitly. By default, the splitter calculates segment /// lengths to be equal and not exceed 58 seconds. /// public double? OverrideTargetDuration { get; set; } /// /// Parameters to pass thru to ffmpeg. These are specified after "--" in the command /// line and are passed directly to the ffmpeg command line for each segment. /// public string[] Passthrough { get; set; } = []; /// /// Debugging parameter. Instead of text UI putput lines in plain text. /// This is useful when the output is being piped to a file or another program, /// or when the user prefers a simpler log format without progress bars and dynamic updates. /// public bool PlainText { get; set; } /// /// Debugging parameter. Just show estimated segments length, count, and other info /// without actually performing the splitting. /// public bool EstimateOnly { get; set; } /// /// Do not adapt segment length. When set, the splitter will use the exact /// segment duration specified by --duration for all segments except possibly /// the last one, which may be shorter. /// public bool ForceFixed { get; set; } /// /// Use single thread for operations. When set, the splitter will not run /// multiple ffmpeg processes in parallel. /// public bool SingleThreaded { get; set; } /// /// Rotation angle: 90, 180, or 270 degrees. This is useful for videos that /// have incorrect orientation metadata. /// public int? Rotate { get; set; } /// /// Autodetect if rotation is needed. Not very reliable but can work for some videos. /// Uses edge orientation statistics to determine if the video is rotated and /// applies the appropriate rotation if needed. /// public bool RotateAuto { get; set; } /// /// Override internal parameters. This allows you to set custom parameters for the /// object detector or rotation detector. /// public Dictionary Parameters { get; set; } = []; /// /// Increase output resolution by x4 using super-resolution RealBasicVSR_x4 model. /// public bool Enhance { get; set; } public void Override(ref T member, string name) { if (!Parameters.TryGetValue(name, out var raw)) return; try { // Convert.ChangeType handles int, float, double, etc. var converted = (T)Convert.ChangeType( raw, typeof(T), CultureInfo.InvariantCulture ); member = converted; } catch { Console.WriteLine($"Invalid value for parameter '{name}': {raw}"); } } public void CopyTo(SingleJob target) { target.OutputFolder = OutputFolder; target.Crop = Crop; target.GravitateTo = GravitateTo; target.Mask = Mask; target.Debug = Debug; target.Detect = Detect; target.ScoreThreshold = ScoreThreshold; target.DetectAbove = DetectAbove; target.DetectId = DetectId; target.OverrideTargetDuration = OverrideTargetDuration; target.Passthrough = Passthrough.ToArray(); target.PlainText = PlainText; target.EstimateOnly = EstimateOnly; target.ForceFixed = ForceFixed; target.SingleThreaded = SingleThreaded; target.Rotate = Rotate; target.RotateAuto = RotateAuto; target.Parameters = new Dictionary(Parameters); target.Enhance = Enhance; } public void CopyFrom(SingleJob source) => source.CopyTo(this); }