using System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Security.Policy; using System.Text; using System.Text.RegularExpressions; using System.Threading.Tasks; namespace ytdlp_gui { public class FFmpegProgressEventArgs : EventArgs { public FFmpegProgressEventArgs(float progress) { this.progress = progress; } public readonly float progress; } public class FFmpegProcess { public FFmpegProcess(Process process, string output_file) { this.process = process; this.output_file = output_file; ci = (CultureInfo)CultureInfo.CurrentCulture.Clone(); ci.NumberFormat.CurrencyDecimalSeparator = "."; } ~FFmpegProcess() { Cancel(); } public async Task Run() { if (File.Exists(output_file)) System.IO.File.Delete(output_file); process.Start(); int duration = 0; int progress = 0; string line = null; while ((line = await process.StandardError.ReadLineAsync()) != null) { Match match; match = header_regex.Match(line); if (match.Success) { GroupCollection groups = match.Groups; duration = int.Parse(groups[1].Value) * 3600 + int.Parse(groups[2].Value) * 60 + int.Parse(groups[3].Value); } match = progress_regex.Match(line); if (match.Success) { GroupCollection groups = match.Groups; progress = int.Parse(groups[1].Value) * 3600 + int.Parse(groups[2].Value) * 60 + int.Parse(groups[3].Value); Progress?.Invoke(this, new FFmpegProgressEventArgs(Math.Min((float)progress / duration, 1))); } } if (stop) return; process.WaitForExit(); Finished?.Invoke(this, new EventArgs()); return; } public void Cancel() { stop = true; if (!process.HasExited) process.Kill(); process.WaitForExit(); } private readonly Process process; private readonly string output_file; private readonly CultureInfo ci; private readonly Regex header_regex = new Regex(@"Duration: (\d+):(\d+):(\d+)\.(\d+)"); private readonly Regex progress_regex = new Regex(@"time=(\d+):(\d+):(\d+)\.(\d+)"); private bool stop = false; public event EventHandler Progress; public event EventHandler Finished; } public class FFmpeg : Program { public FFmpeg() : base("ffmpeg") { } public FFmpegProcess Convert(string from, string to) { Process process = new Process(); process.StartInfo.FileName = program; process.StartInfo.Arguments = String.Format( "-i \"{0}\" \"{1}\"", from.Replace("\"", "\"\"\""), to.Replace("\"", "\"\"\"") ); process.StartInfo.UseShellExecute = false; process.StartInfo.CreateNoWindow = true; // process.StartInfo.RedirectStandardOutput = true; process.StartInfo.RedirectStandardError = true; return new FFmpegProcess(process, to); } } }