127 lines
3.7 KiB
C#
127 lines
3.7 KiB
C#
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<FFmpegProgressEventArgs> 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);
|
|
}
|
|
}
|
|
}
|