Decompiled source of YoutubeDLSharp v1.1.0

BepInEx/plugins/YoutubeDLSharp.dll

Decompiled 10 months ago
#define DEBUG
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Net.Http;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using YoutubeDLSharp.Converters;
using YoutubeDLSharp.Helpers;
using YoutubeDLSharp.Metadata;
using YoutubeDLSharp.Options;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.0", FrameworkDisplayName = ".NET Standard 2.0")]
[assembly: AssemblyCompany("Bluegrams")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyCopyright("© 2020-2024 Bluegrams")]
[assembly: AssemblyDescription("\n\t\tA simple .NET wrapper library for youtube-dl and yt-dlp.\n\nNote: Package versions >= 1.0 are optimized to work with yt-dlp.\nPackage versions 0.x retain support for the original youtube-dl.\n\t")]
[assembly: AssemblyFileVersion("1.1.0.0")]
[assembly: AssemblyInformationalVersion("1.1.0+febe9e5d0ffbe54055cac081271280501bd308d4")]
[assembly: AssemblyProduct("YoutubeDLSharp")]
[assembly: AssemblyTitle("YoutubeDLSharp")]
[assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/Lordfirespeed/YoutubeDLSharpThunderstore")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
namespace YoutubeDLSharp
{
	public enum DownloadState
	{
		None,
		PreProcessing,
		Downloading,
		PostProcessing,
		Error,
		Success
	}
	public class DownloadProgress
	{
		public DownloadState State { get; }

		public float Progress { get; }

		public string TotalDownloadSize { get; }

		public string DownloadSpeed { get; }

		public string ETA { get; }

		public int VideoIndex { get; }

		public string Data { get; }

		public DownloadProgress(DownloadState status, float progress = 0f, string totalDownloadSize = null, string downloadSpeed = null, string eta = null, int index = 1, string data = null)
		{
			State = status;
			Progress = progress;
			TotalDownloadSize = totalDownloadSize;
			DownloadSpeed = downloadSpeed;
			ETA = eta;
			VideoIndex = index;
			Data = data;
		}
	}
	public class RunResult<T>
	{
		public bool Success { get; }

		public string[] ErrorOutput { get; }

		public T Data { get; }

		public RunResult(bool success, string[] error, T result)
		{
			Success = success;
			ErrorOutput = error;
			Data = result;
		}
	}
	public static class Utils
	{
		internal class FFmpegApi
		{
			public class Root
			{
				[JsonProperty("version")]
				public string Version { get; set; }

				[JsonProperty("permalink")]
				public string Permalink { get; set; }

				[JsonProperty("bin")]
				public Bin Bin { get; set; }
			}

			public class Bin
			{
				[JsonProperty("windows-64")]
				public OsBinVersion Windows64 { get; set; }

				[JsonProperty("linux-64")]
				public OsBinVersion Linux64 { get; set; }

				[JsonProperty("osx-64")]
				public OsBinVersion Osx64 { get; set; }
			}

			public class OsBinVersion
			{
				[JsonProperty("ffmpeg")]
				public string Ffmpeg { get; set; }

				[JsonProperty("ffprobe")]
				public string Ffprobe { get; set; }
			}

			public enum BinaryType
			{
				[EnumMember(Value = "ffmpeg")]
				FFmpeg,
				[EnumMember(Value = "ffprobe")]
				FFprobe
			}
		}

		private static readonly HttpClient _client = new HttpClient();

		private static readonly Regex rgxTimestamp = new Regex("[0-9]+(?::[0-9]+)+", RegexOptions.Compiled);

		private static readonly Dictionary<char, string> accentChars = "ÂÃÄÀÁÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖŐØŒÙÚÛÜŰÝÞßàáâãäåæçèéêëìíîïðñòóôõöőøœùúûüűýþÿ".Zip(new string[68]
		{
			"A", "A", "A", "A", "A", "A", "AE", "C", "E", "E",
			"E", "E", "I", "I", "I", "I", "D", "N", "O", "O",
			"O", "O", "O", "O", "O", "OE", "U", "U", "U", "U",
			"U", "Y", "P", "ss", "a", "a", "a", "a", "a", "a",
			"ae", "c", "e", "e", "e", "e", "i", "i", "i", "i",
			"o", "n", "o", "o", "o", "o", "o", "o", "o", "oe",
			"u", "u", "u", "u", "u", "y", "p", "y"
		}, (char c, string s) => new
		{
			Key = c,
			Val = s
		}).ToDictionary(o => o.Key, o => o.Val);

		public static string YtDlpBinaryName => GetYtDlpBinaryName();

		public static string FfmpegBinaryName => GetFfmpegBinaryName();

		public static string FfprobeBinaryName => GetFfprobeBinaryName();

		public static string Sanitize(string s, bool restricted = false)
		{
			rgxTimestamp.Replace(s, (Match m) => m.Groups[0].Value.Replace(':', '_'));
			string text = string.Join("", s.Select((char c) => sanitizeChar(c, restricted)));
			text = text.Replace("__", "_").Trim(new char[1] { '_' });
			if (restricted && text.StartsWith("-_"))
			{
				text = text.Substring(2);
			}
			if (text.StartsWith("-"))
			{
				text = "_" + text.Substring(1);
			}
			text = text.TrimStart(new char[1] { '.' });
			if (string.IsNullOrWhiteSpace(text))
			{
				text = "_";
			}
			return text;
		}

		private static string sanitizeChar(char c, bool restricted)
		{
			if (restricted && accentChars.ContainsKey(c))
			{
				return accentChars[c];
			}
			if (c == '?' || c < ' ' || c == '\u007f')
			{
				return "";
			}
			switch (c)
			{
			case '"':
				return restricted ? "" : "'";
			case ':':
				return restricted ? "_-" : " -";
			default:
				if (Enumerable.Contains("\\/|*<>", c))
				{
					return "_";
				}
				if (restricted && Enumerable.Contains("!&'()[]{}$;`^,# ", c))
				{
					return "_";
				}
				if (restricted && c > '\u007f')
				{
					return "_";
				}
				return c.ToString();
			}
		}

		public static string GetFullPath(string fileName)
		{
			if (File.Exists(fileName))
			{
				return Path.GetFullPath(fileName);
			}
			string environmentVariable = Environment.GetEnvironmentVariable("PATH");
			string[] array = environmentVariable.Split(new char[1] { Path.PathSeparator });
			foreach (string path in array)
			{
				string text = Path.Combine(path, fileName);
				if (File.Exists(text))
				{
					return text;
				}
			}
			return null;
		}

		public static async Task DownloadBinaries(bool skipExisting = true, string directoryPath = "")
		{
			if (skipExisting)
			{
				if (!File.Exists(Path.Combine(directoryPath, GetYtDlpBinaryName())))
				{
					await DownloadYtDlp(directoryPath);
				}
				if (!File.Exists(Path.Combine(directoryPath, GetFfmpegBinaryName())))
				{
					await DownloadFFmpeg(directoryPath);
				}
				if (!File.Exists(Path.Combine(directoryPath, GetFfprobeBinaryName())))
				{
					await DownloadFFprobe(directoryPath);
				}
			}
			else
			{
				await DownloadYtDlp(directoryPath);
				await DownloadFFmpeg(directoryPath);
				await DownloadFFprobe(directoryPath);
			}
		}

		private static string GetYtDlpDownloadUrl()
		{
			return OSHelper.GetOSVersion() switch
			{
				OSVersion.Windows => "https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp.exe", 
				OSVersion.OSX => "https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp_macos", 
				OSVersion.Linux => "https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp", 
				_ => throw new Exception("Your OS isn't supported"), 
			};
		}

		private static string GetYtDlpBinaryName()
		{
			string ytDlpDownloadUrl = GetYtDlpDownloadUrl();
			return Path.GetFileName(ytDlpDownloadUrl);
		}

		private static string GetFfmpegBinaryName()
		{
			switch (OSHelper.GetOSVersion())
			{
			case OSVersion.Windows:
				return "ffmpeg.exe";
			case OSVersion.OSX:
			case OSVersion.Linux:
				return "ffmpeg";
			default:
				throw new Exception("Your OS isn't supported");
			}
		}

		private static string GetFfprobeBinaryName()
		{
			switch (OSHelper.GetOSVersion())
			{
			case OSVersion.Windows:
				return "ffprobe.exe";
			case OSVersion.OSX:
			case OSVersion.Linux:
				return "ffprobe";
			default:
				throw new Exception("Your OS isn't supported");
			}
		}

		public static async Task DownloadYtDlp(string directoryPath = "")
		{
			string downloadUrl = GetYtDlpDownloadUrl();
			if (string.IsNullOrEmpty(directoryPath))
			{
				directoryPath = Directory.GetCurrentDirectory();
			}
			string downloadLocation = Path.Combine(directoryPath, Path.GetFileName(downloadUrl));
			File.WriteAllBytes(downloadLocation, await DownloadFileBytesAsync(downloadUrl));
		}

		public static async Task DownloadFFmpeg(string directoryPath = "")
		{
			await FFDownloader(directoryPath);
		}

		public static async Task DownloadFFprobe(string directoryPath = "")
		{
			await FFDownloader(directoryPath, FFmpegApi.BinaryType.FFprobe);
		}

		private static async Task FFDownloader(string directoryPath = "", FFmpegApi.BinaryType binary = FFmpegApi.BinaryType.FFmpeg)
		{
			if (string.IsNullOrEmpty(directoryPath))
			{
				directoryPath = Directory.GetCurrentDirectory();
			}
			FFmpegApi.Root ffmpegVersion = JsonConvert.DeserializeObject<FFmpegApi.Root>(await (await _client.GetAsync("https://ffbinaries.com/api/v1/version/latest")).Content.ReadAsStringAsync());
			FFmpegApi.OsBinVersion ffContent = OSHelper.GetOSVersion() switch
			{
				OSVersion.Windows => ffmpegVersion?.Bin.Windows64, 
				OSVersion.OSX => ffmpegVersion?.Bin.Osx64, 
				OSVersion.Linux => ffmpegVersion?.Bin.Linux64, 
				_ => throw new NotImplementedException("Your OS isn't supported"), 
			};
			string downloadUrl = ((binary == FFmpegApi.BinaryType.FFmpeg) ? ffContent.Ffmpeg : ffContent.Ffprobe);
			using MemoryStream stream = new MemoryStream(await DownloadFileBytesAsync(downloadUrl));
			using ZipArchive archive = new ZipArchive(stream, ZipArchiveMode.Read);
			if (archive.Entries.Count > 0)
			{
				archive.Entries[0].ExtractToFile(Path.Combine(directoryPath, archive.Entries[0].FullName), overwrite: true);
			}
		}

		private static async Task<byte[]> DownloadFileBytesAsync(string uri)
		{
			if (!Uri.TryCreate(uri, UriKind.Absolute, out Uri _))
			{
				throw new InvalidOperationException("URI is invalid.");
			}
			return await _client.GetByteArrayAsync(uri);
		}

		public static void EnsureSuccess<T>(this RunResult<T> runResult)
		{
			if (!runResult.Success)
			{
				throw new Exception("Download failed:\n" + string.Join("\n", runResult.ErrorOutput));
			}
		}
	}
	public class YoutubeDL
	{
		private static readonly Regex rgxFile = new Regex("^outfile:\\s\\\"?(.*)\\\"?", RegexOptions.Compiled);

		private static Regex rgxFilePostProc = new Regex("\\[download\\] Destination: [a-zA-Z]:\\\\\\S+\\.\\S{3,}", RegexOptions.Compiled);

		protected ProcessRunner runner;

		public string YoutubeDLPath { get; set; } = Utils.YtDlpBinaryName;


		public string FFmpegPath { get; set; } = Utils.FfmpegBinaryName;


		public string OutputFolder { get; set; } = Environment.CurrentDirectory;


		public string OutputFileTemplate { get; set; } = "%(title)s [%(id)s].%(ext)s";


		public bool RestrictFilenames { get; set; } = false;


		public bool OverwriteFiles { get; set; } = true;


		public bool IgnoreDownloadErrors { get; set; } = true;


		public string PythonInterpreterPath { get; set; } = null;


		public string Version => FileVersionInfo.GetVersionInfo(Utils.GetFullPath(YoutubeDLPath)).FileVersion;

		public YoutubeDL(byte maxNumberOfProcesses = 4)
		{
			runner = new ProcessRunner(maxNumberOfProcesses);
		}

		public async Task SetMaxNumberOfProcesses(byte count)
		{
			await runner.SetTotalCount(count);
		}

		public async Task<RunResult<string[]>> RunWithOptions(string[] urls, OptionSet options, CancellationToken ct)
		{
			List<string> output = new List<string>();
			YoutubeDLProcess process = CreateYoutubeDLProcess();
			process.OutputReceived += delegate(object o, DataReceivedEventArgs e)
			{
				output.Add(e.Data);
			};
			var (code, errors) = await runner.RunThrottled(process, urls, options, ct);
			return new RunResult<string[]>(code == 0, errors, output.ToArray());
		}

		public async Task<RunResult<string>> RunWithOptions(string url, OptionSet options, CancellationToken ct = default(CancellationToken), IProgress<DownloadProgress> progress = null, IProgress<string> output = null, bool showArgs = true)
		{
			string outFile = string.Empty;
			YoutubeDLProcess process = CreateYoutubeDLProcess();
			if (showArgs)
			{
				output?.Report("Arguments: " + process.ConvertToArgs(new string[1] { url }, options) + "\n");
			}
			else
			{
				output?.Report("Starting Download: " + url);
			}
			process.OutputReceived += delegate(object o, DataReceivedEventArgs e)
			{
				Match match = rgxFilePostProc.Match(e.Data);
				if (match.Success)
				{
					outFile = match.Groups[0].ToString().Replace("[download] Destination:", "").Replace(" ", "");
					progress?.Report(new DownloadProgress(DownloadState.Success, 0f, null, null, null, 1, outFile));
				}
				output?.Report(e.Data);
			};
			var (code, errors) = await runner.RunThrottled(process, new string[1] { url }, options, ct, progress);
			return new RunResult<string>(code == 0, errors, outFile);
		}

		public async Task<string> RunUpdate()
		{
			string output = string.Empty;
			YoutubeDLProcess process = CreateYoutubeDLProcess();
			process.OutputReceived += delegate(object o, DataReceivedEventArgs e)
			{
				output = e.Data;
			};
			await process.RunAsync(null, new OptionSet
			{
				Update = true
			});
			return output;
		}

		public async Task<RunResult<VideoData>> RunVideoDataFetch(string url, CancellationToken ct = default(CancellationToken), bool flat = true, bool fetchComments = false, OptionSet overrideOptions = null)
		{
			OptionSet opts = GetDownloadOptions();
			opts.DumpSingleJson = true;
			opts.FlatPlaylist = flat;
			opts.WriteComments = fetchComments;
			if (overrideOptions != null)
			{
				opts = opts.OverrideOptions(overrideOptions);
			}
			VideoData videoData = null;
			YoutubeDLProcess process = CreateYoutubeDLProcess();
			process.OutputReceived += delegate(object o, DataReceivedEventArgs e)
			{
				try
				{
					videoData = JsonConvert.DeserializeObject<VideoData>(e.Data);
				}
				catch (JsonSerializationException)
				{
					process.RedirectToError(e);
				}
			};
			var (code, errors) = await runner.RunThrottled(process, new string[1] { url }, opts, ct);
			return new RunResult<VideoData>(code == 0, errors, videoData);
		}

		public async Task<RunResult<string>> RunVideoDownload(string url, string format = "bestvideo+bestaudio/best", DownloadMergeFormat mergeFormat = DownloadMergeFormat.Unspecified, VideoRecodeFormat recodeFormat = VideoRecodeFormat.None, CancellationToken ct = default(CancellationToken), IProgress<DownloadProgress> progress = null, IProgress<string> output = null, OptionSet overrideOptions = null)
		{
			OptionSet opts = GetDownloadOptions();
			opts.Format = format;
			opts.MergeOutputFormat = mergeFormat;
			opts.RecodeVideo = recodeFormat;
			if (overrideOptions != null)
			{
				opts = opts.OverrideOptions(overrideOptions);
			}
			string outputFile = string.Empty;
			YoutubeDLProcess process = CreateYoutubeDLProcess();
			output?.Report("Arguments: " + process.ConvertToArgs(new string[1] { url }, opts) + "\n");
			process.OutputReceived += delegate(object o, DataReceivedEventArgs e)
			{
				Match match = rgxFile.Match(e.Data);
				if (match.Success)
				{
					outputFile = match.Groups[1].ToString().Trim(new char[1] { '"' });
					progress?.Report(new DownloadProgress(DownloadState.Success, 0f, null, null, null, 1, outputFile));
				}
				output?.Report(e.Data);
			};
			var (code, errors) = await runner.RunThrottled(process, new string[1] { url }, opts, ct, progress);
			return new RunResult<string>(code == 0, errors, outputFile);
		}

		public async Task<RunResult<string[]>> RunVideoPlaylistDownload(string url, int? start = 1, int? end = null, int[] items = null, string format = "bestvideo+bestaudio/best", VideoRecodeFormat recodeFormat = VideoRecodeFormat.None, CancellationToken ct = default(CancellationToken), IProgress<DownloadProgress> progress = null, IProgress<string> output = null, OptionSet overrideOptions = null)
		{
			OptionSet opts = GetDownloadOptions();
			opts.NoPlaylist = false;
			opts.PlaylistStart = start;
			opts.PlaylistEnd = end;
			if (items != null)
			{
				opts.PlaylistItems = string.Join(",", items);
			}
			opts.Format = format;
			opts.RecodeVideo = recodeFormat;
			if (overrideOptions != null)
			{
				opts = opts.OverrideOptions(overrideOptions);
			}
			List<string> outputFiles = new List<string>();
			YoutubeDLProcess process = CreateYoutubeDLProcess();
			output?.Report("Arguments: " + process.ConvertToArgs(new string[1] { url }, opts) + "\n");
			process.OutputReceived += delegate(object o, DataReceivedEventArgs e)
			{
				Match match = rgxFile.Match(e.Data);
				if (match.Success)
				{
					string text = match.Groups[1].ToString().Trim(new char[1] { '"' });
					outputFiles.Add(text);
					progress?.Report(new DownloadProgress(DownloadState.Success, 0f, null, null, null, 1, text));
				}
				output?.Report(e.Data);
			};
			var (code, errors) = await runner.RunThrottled(process, new string[1] { url }, opts, ct, progress);
			return new RunResult<string[]>(code == 0, errors, outputFiles.ToArray());
		}

		public async Task<RunResult<string>> RunAudioDownload(string url, AudioConversionFormat format = AudioConversionFormat.Best, CancellationToken ct = default(CancellationToken), IProgress<DownloadProgress> progress = null, IProgress<string> output = null, OptionSet overrideOptions = null)
		{
			OptionSet opts = GetDownloadOptions();
			opts.Format = "bestaudio/best";
			opts.ExtractAudio = true;
			opts.AudioFormat = format;
			if (overrideOptions != null)
			{
				opts = opts.OverrideOptions(overrideOptions);
			}
			string outputFile = string.Empty;
			new List<string>();
			YoutubeDLProcess process = CreateYoutubeDLProcess();
			output?.Report("Arguments: " + process.ConvertToArgs(new string[1] { url }, opts) + "\n");
			process.OutputReceived += delegate(object o, DataReceivedEventArgs e)
			{
				Match match = rgxFile.Match(e.Data);
				if (match.Success)
				{
					outputFile = match.Groups[1].ToString().Trim(new char[1] { '"' });
					progress?.Report(new DownloadProgress(DownloadState.Success, 0f, null, null, null, 1, outputFile));
				}
				output?.Report(e.Data);
			};
			var (code, errors) = await runner.RunThrottled(process, new string[1] { url }, opts, ct, progress);
			return new RunResult<string>(code == 0, errors, outputFile);
		}

		public async Task<RunResult<string[]>> RunAudioPlaylistDownload(string url, int? start = 1, int? end = null, int[] items = null, AudioConversionFormat format = AudioConversionFormat.Best, CancellationToken ct = default(CancellationToken), IProgress<DownloadProgress> progress = null, IProgress<string> output = null, OptionSet overrideOptions = null)
		{
			List<string> outputFiles = new List<string>();
			OptionSet opts = GetDownloadOptions();
			opts.NoPlaylist = false;
			opts.PlaylistStart = start;
			opts.PlaylistEnd = end;
			if (items != null)
			{
				opts.PlaylistItems = string.Join(",", items);
			}
			opts.Format = "bestaudio/best";
			opts.ExtractAudio = true;
			opts.AudioFormat = format;
			if (overrideOptions != null)
			{
				opts = opts.OverrideOptions(overrideOptions);
			}
			YoutubeDLProcess process = CreateYoutubeDLProcess();
			output?.Report("Arguments: " + process.ConvertToArgs(new string[1] { url }, opts) + "\n");
			process.OutputReceived += delegate(object o, DataReceivedEventArgs e)
			{
				Match match = rgxFile.Match(e.Data);
				if (match.Success)
				{
					string text = match.Groups[1].ToString().Trim(new char[1] { '"' });
					outputFiles.Add(text);
					progress?.Report(new DownloadProgress(DownloadState.Success, 0f, null, null, null, 1, text));
				}
				output?.Report(e.Data);
			};
			var (code, errors) = await runner.RunThrottled(process, new string[1] { url }, opts, ct, progress);
			return new RunResult<string[]>(code == 0, errors, outputFiles.ToArray());
		}

		protected virtual OptionSet GetDownloadOptions()
		{
			return new OptionSet
			{
				IgnoreErrors = IgnoreDownloadErrors,
				IgnoreConfig = true,
				NoPlaylist = true,
				Downloader = "m3u8:native",
				DownloaderArgs = "ffmpeg:-nostats -loglevel 0",
				Output = Path.Combine(OutputFolder, OutputFileTemplate),
				RestrictFilenames = RestrictFilenames,
				ForceOverwrites = OverwriteFiles,
				NoOverwrites = !OverwriteFiles,
				NoPart = true,
				FfmpegLocation = Utils.GetFullPath(FFmpegPath),
				Exec = "echo outfile: {}"
			};
		}

		private YoutubeDLProcess CreateYoutubeDLProcess()
		{
			return new YoutubeDLProcess(YoutubeDLPath)
			{
				PythonPath = PythonInterpreterPath
			};
		}
	}
	public class YoutubeDLProcess
	{
		private static readonly Regex rgxPlaylist = new Regex("Downloading video (\\d+) of (\\d+)", RegexOptions.Compiled);

		private static readonly Regex rgxProgress = new Regex("\\[download\\]\\s+(?:(?<percent>[\\d\\.]+)%(?:\\s+of\\s+\\~?\\s*(?<total>[\\d\\.\\w]+))?\\s+at\\s+(?:(?<speed>[\\d\\.\\w]+\\/s)|[\\w\\s]+)\\s+ETA\\s(?<eta>[\\d\\:]+))?", RegexOptions.Compiled);

		private static readonly Regex rgxPost = new Regex("\\[(\\w+)\\]\\s+", RegexOptions.Compiled);

		public string PythonPath { get; set; }

		public string ExecutablePath { get; set; }

		public bool UseWindowsEncodingWorkaround { get; set; } = true;


		public event EventHandler<DataReceivedEventArgs> OutputReceived;

		public event EventHandler<DataReceivedEventArgs> ErrorReceived;

		public YoutubeDLProcess(string executablePath = "yt-dlp.exe")
		{
			ExecutablePath = executablePath;
		}

		internal string ConvertToArgs(string[] urls, OptionSet options)
		{
			return options.ToString() + " -- " + ((urls != null) ? string.Join(" ", urls.Select((string s) => "\"" + s + "\"")) : string.Empty);
		}

		internal void RedirectToError(DataReceivedEventArgs e)
		{
			this.ErrorReceived?.Invoke(this, e);
		}

		public async Task<int> RunAsync(string[] urls, OptionSet options)
		{
			return await RunAsync(urls, options, CancellationToken.None);
		}

		public async Task<int> RunAsync(string[] urls, OptionSet options, CancellationToken ct, IProgress<DownloadProgress> progress = null)
		{
			TaskCompletionSource<int> tcs = new TaskCompletionSource<int>();
			Process process = new Process();
			ProcessStartInfo startInfo = new ProcessStartInfo
			{
				CreateNoWindow = true,
				UseShellExecute = false,
				RedirectStandardOutput = true,
				RedirectStandardError = true,
				StandardOutputEncoding = Encoding.UTF8,
				StandardErrorEncoding = Encoding.UTF8
			};
			if (OSHelper.IsWindows && UseWindowsEncodingWorkaround)
			{
				startInfo.FileName = "cmd.exe";
				string runCommand = (string.IsNullOrEmpty(PythonPath) ? ("\"" + ExecutablePath + "\" " + ConvertToArgs(urls, options)) : ("\"" + PythonPath + "\" \"" + ExecutablePath + "\" " + ConvertToArgs(urls, options)));
				startInfo.Arguments = "/C chcp 65001 >nul 2>&1 && " + runCommand;
			}
			else if (!string.IsNullOrEmpty(PythonPath))
			{
				startInfo.FileName = PythonPath;
				startInfo.Arguments = "\"" + ExecutablePath + "\" " + ConvertToArgs(urls, options);
			}
			else
			{
				startInfo.FileName = ExecutablePath;
				startInfo.Arguments = ConvertToArgs(urls, options);
			}
			process.EnableRaisingEvents = true;
			process.StartInfo = startInfo;
			TaskCompletionSource<bool> tcsOut = new TaskCompletionSource<bool>();
			bool isDownloading = false;
			process.OutputDataReceived += delegate(object o, DataReceivedEventArgs e)
			{
				if (e.Data == null)
				{
					tcsOut.SetResult(result: true);
				}
				else
				{
					Match match;
					if ((match = rgxProgress.Match(e.Data)).Success)
					{
						if (match.Groups.Count > 1 && match.Groups[1].Length > 0)
						{
							float progress2 = float.Parse(match.Groups[1].ToString(), CultureInfo.InvariantCulture) / 100f;
							Group group = match.Groups["total"];
							string totalDownloadSize = (group.Success ? group.Value : null);
							Group group2 = match.Groups["speed"];
							string downloadSpeed = (group2.Success ? group2.Value : null);
							Group group3 = match.Groups["eta"];
							string eta = (group3.Success ? group3.Value : null);
							progress?.Report(new DownloadProgress(DownloadState.Downloading, progress2, totalDownloadSize, downloadSpeed, eta));
						}
						else
						{
							progress?.Report(new DownloadProgress(DownloadState.Downloading));
						}
						isDownloading = true;
					}
					else if ((match = rgxPlaylist.Match(e.Data)).Success)
					{
						int index = int.Parse(match.Groups[1].Value);
						progress?.Report(new DownloadProgress(DownloadState.PreProcessing, 0f, null, null, null, index));
						isDownloading = false;
					}
					else if (isDownloading && (match = rgxPost.Match(e.Data)).Success)
					{
						progress?.Report(new DownloadProgress(DownloadState.PostProcessing, 1f));
						isDownloading = false;
					}
					Debug.WriteLine("[yt-dlp] " + e.Data);
					this.OutputReceived?.Invoke(this, e);
				}
			};
			TaskCompletionSource<bool> tcsError = new TaskCompletionSource<bool>();
			process.ErrorDataReceived += delegate(object o, DataReceivedEventArgs e)
			{
				if (e.Data == null)
				{
					tcsError.SetResult(result: true);
				}
				else
				{
					Debug.WriteLine("[yt-dlp ERROR] " + e.Data);
					progress?.Report(new DownloadProgress(DownloadState.Error, 0f, null, null, null, 1, e.Data));
					this.ErrorReceived?.Invoke(this, e);
				}
			};
			process.Exited += async delegate
			{
				await tcsOut.Task;
				await tcsError.Task;
				tcs.TrySetResult(process.ExitCode);
				process.Dispose();
			};
			ct.Register(delegate
			{
				if (!tcs.Task.IsCompleted)
				{
					tcs.TrySetCanceled();
				}
				try
				{
					if (!process.HasExited)
					{
						process.KillTree();
					}
				}
				catch
				{
				}
			});
			Debug.WriteLine("[yt-dlp] Arguments: " + process.StartInfo.Arguments);
			if (!(await Task.Run(() => process.Start())))
			{
				tcs.TrySetException(new InvalidOperationException("Failed to start yt-dlp process."));
			}
			process.BeginOutputReadLine();
			process.BeginErrorReadLine();
			progress?.Report(new DownloadProgress(DownloadState.PreProcessing));
			return await tcs.Task;
		}
	}
}
namespace YoutubeDLSharp.Options
{
	public enum DownloadMergeFormat
	{
		Unspecified,
		Mp4,
		Mkv,
		Ogg,
		Webm,
		Flv
	}
	public enum AudioConversionFormat
	{
		Best,
		Aac,
		Flac,
		Mp3,
		M4a,
		Opus,
		Vorbis,
		Wav
	}
	public enum VideoRecodeFormat
	{
		None,
		Mp4,
		Mkv,
		Ogg,
		Webm,
		Flv,
		Avi
	}
	public interface IOption
	{
		string DefaultOptionString { get; }

		string[] OptionStrings { get; }

		bool IsSet { get; }

		bool IsCustom { get; }

		void SetFromString(string s);

		IEnumerable<string> ToStringCollection();
	}
	public class MultiOption<T> : IOption
	{
		private MultiValue<T> value;

		public string DefaultOptionString => OptionStrings.Last();

		public string[] OptionStrings { get; }

		public bool IsSet { get; private set; }

		public bool IsCustom { get; }

		public MultiValue<T> Value
		{
			get
			{
				return value;
			}
			set
			{
				IsSet = !object.Equals(value, default(T));
				this.value = value;
			}
		}

		public MultiOption(params string[] optionStrings)
		{
			OptionStrings = optionStrings;
			IsSet = false;
		}

		public MultiOption(bool isCustom, params string[] optionStrings)
		{
			OptionStrings = optionStrings;
			IsSet = false;
			IsCustom = isCustom;
		}

		public void SetFromString(string s)
		{
			string[] array = s.Split(new char[1] { ' ' });
			string stringValue = s.Substring(array[0].Length).Trim().Trim(new char[1] { '"' });
			if (!OptionStrings.Contains(array[0]))
			{
				throw new ArgumentException("Given string does not match required format.");
			}
			T val = Utils.OptionValueFromString<T>(stringValue);
			if (!IsSet)
			{
				Value = val;
			}
			else
			{
				Value.Values.Add(val);
			}
		}

		public override string ToString()
		{
			return string.Join(" ", ToStringCollection());
		}

		public IEnumerable<string> ToStringCollection()
		{
			if (!IsSet)
			{
				return new string[1] { "" };
			}
			List<string> list = new List<string>();
			foreach (T value in Value.Values)
			{
				list.Add(DefaultOptionString + Utils.OptionValueToString(value));
			}
			return list;
		}
	}
	public class MultiValue<T>
	{
		private readonly List<T> values;

		public List<T> Values => values;

		public MultiValue(params T[] values)
		{
			this.values = values.ToList();
		}

		public static implicit operator MultiValue<T>(T value)
		{
			return new MultiValue<T>(value);
		}

		public static implicit operator MultiValue<T>(T[] values)
		{
			return new MultiValue<T>(values);
		}

		public static explicit operator T(MultiValue<T> value)
		{
			if (value.Values.Count == 1)
			{
				return value.Values[0];
			}
			throw new InvalidCastException($"Cannot cast sequence of values to {typeof(T)}.");
		}

		public static explicit operator T[](MultiValue<T> value)
		{
			return value.Values.ToArray();
		}
	}
	public class Option<T> : IOption
	{
		private T value;

		public string DefaultOptionString => OptionStrings.First();

		public string[] OptionStrings { get; }

		public bool IsSet { get; private set; }

		public T Value
		{
			get
			{
				return value;
			}
			set
			{
				IsSet = !object.Equals(value, default(T));
				this.value = value;
			}
		}

		public bool IsCustom { get; }

		public Option(params string[] optionStrings)
		{
			OptionStrings = optionStrings;
			IsSet = false;
		}

		public Option(bool isCustom, params string[] optionStrings)
		{
			OptionStrings = optionStrings;
			IsSet = false;
			IsCustom = isCustom;
		}

		public void SetFromString(string s)
		{
			string[] array = s.Split(new char[1] { ' ' });
			string stringValue = s.Substring(array[0].Length).Trim().Trim(new char[1] { '"' });
			if (!OptionStrings.Contains(array[0]))
			{
				throw new ArgumentException("Given string does not match required format.");
			}
			Value = Utils.OptionValueFromString<T>(stringValue);
		}

		public override string ToString()
		{
			if (!IsSet)
			{
				return string.Empty;
			}
			string text = Utils.OptionValueToString(Value);
			return DefaultOptionString + text;
		}

		public IEnumerable<string> ToStringCollection()
		{
			return new string[1] { ToString() };
		}
	}
	internal class OptionComparer : IEqualityComparer<IOption>
	{
		public bool Equals(IOption x, IOption y)
		{
			if (x != null)
			{
				return y != null && x.ToString().Equals(y.ToString());
			}
			return y == null;
		}

		public int GetHashCode(IOption obj)
		{
			return obj.ToString().GetHashCode();
		}
	}
	public class OptionSet : ICloneable
	{
		private Option<string> username = new Option<string>("-u", "--username");

		private Option<string> password = new Option<string>("-p", "--password");

		private Option<string> twoFactor = new Option<string>("-2", "--twofactor");

		private Option<bool> netrc = new Option<bool>("-n", "--netrc");

		private Option<string> netrcLocation = new Option<string>("--netrc-location");

		private Option<string> netrcCmd = new Option<string>("--netrc-cmd");

		private Option<string> videoPassword = new Option<string>("--video-password");

		private Option<string> apMso = new Option<string>("--ap-mso");

		private Option<string> apUsername = new Option<string>("--ap-username");

		private Option<string> apPassword = new Option<string>("--ap-password");

		private Option<bool> apListMso = new Option<bool>("--ap-list-mso");

		private Option<string> clientCertificate = new Option<string>("--client-certificate");

		private Option<string> clientCertificateKey = new Option<string>("--client-certificate-key");

		private Option<string> clientCertificatePassword = new Option<string>("--client-certificate-password");

		private static readonly OptionComparer Comparer = new OptionComparer();

		public static readonly OptionSet Default = new OptionSet();

		private Option<bool> getDescription = new Option<bool>("--get-description");

		private Option<bool> getDuration = new Option<bool>("--get-duration");

		private Option<bool> getFilename = new Option<bool>("--get-filename");

		private Option<bool> getFormat = new Option<bool>("--get-format");

		private Option<bool> getId = new Option<bool>("--get-id");

		private Option<bool> getThumbnail = new Option<bool>("--get-thumbnail");

		private Option<bool> getTitle = new Option<bool>("-e", "--get-title");

		private Option<bool> getUrl = new Option<bool>("-g", "--get-url");

		private Option<string> matchTitle = new Option<string>("--match-title");

		private Option<string> rejectTitle = new Option<string>("--reject-title");

		private Option<long?> minViews = new Option<long?>("--min-views");

		private Option<long?> maxViews = new Option<long?>("--max-views");

		private Option<bool> breakOnReject = new Option<bool>("--break-on-reject");

		private Option<string> userAgent = new Option<string>("--user-agent");

		private Option<string> referer = new Option<string>("--referer");

		private Option<int?> playlistStart = new Option<int?>("--playlist-start");

		private Option<int?> playlistEnd = new Option<int?>("--playlist-end");

		private Option<bool> playlistReverse = new Option<bool>("--playlist-reverse");

		private Option<bool> noColors = new Option<bool>("--no-colors");

		private Option<bool> forceGenericExtractor = new Option<bool>("--force-generic-extractor");

		private Option<string> execBeforeDownload = new Option<string>("--exec-before-download");

		private Option<bool> noExecBeforeDownload = new Option<bool>("--no-exec-before-download");

		private Option<bool> allFormats = new Option<bool>("--all-formats");

		private Option<bool> allSubs = new Option<bool>("--all-subs");

		private Option<bool> printJson = new Option<bool>("--print-json");

		private Option<string> autonumberSize = new Option<string>("--autonumber-size");

		private Option<int?> autonumberStart = new Option<int?>("--autonumber-start");

		private Option<bool> id = new Option<bool>("--id");

		private Option<string> metadataFromTitle = new Option<string>("--metadata-from-title");

		private Option<bool> hlsPreferNative = new Option<bool>("--hls-prefer-native");

		private Option<bool> hlsPreferFfmpeg = new Option<bool>("--hls-prefer-ffmpeg");

		private Option<bool> listFormatsOld = new Option<bool>("--list-formats-old", "--no-list-formats-as-table");

		private Option<bool> listFormatsAsTable = new Option<bool>("--list-formats-as-table", "--no-list-formats-old");

		private Option<bool> youtubeSkipDashManifest = new Option<bool>("--youtube-skip-dash-manifest", "--no-youtube-include-dash-manifest");

		private Option<bool> youtubeSkipHlsManifest = new Option<bool>("--youtube-skip-hls-manifest", "--no-youtube-include-hls-manifest");

		private Option<bool> geoBypass = new Option<bool>("--geo-bypass");

		private Option<bool> noGeoBypass = new Option<bool>("--no-geo-bypass");

		private Option<string> geoBypassCountry = new Option<string>("--geo-bypass-country");

		private Option<string> geoBypassIpBlock = new Option<string>("--geo-bypass-ip-block");

		private Option<int?> concurrentFragments = new Option<int?>("-N", "--concurrent-fragments");

		private Option<long?> limitRate = new Option<long?>("-r", "--limit-rate");

		private Option<long?> throttledRate = new Option<long?>("--throttled-rate");

		private Option<int?> retries = new Option<int?>("-R", "--retries");

		private Option<int?> fileAccessRetries = new Option<int?>("--file-access-retries");

		private Option<int?> fragmentRetries = new Option<int?>("--fragment-retries");

		private MultiOption<string> retrySleep = new MultiOption<string>("--retry-sleep");

		private Option<bool> skipUnavailableFragments = new Option<bool>("--skip-unavailable-fragments", "--no-abort-on-unavailable-fragments");

		private Option<bool> abortOnUnavailableFragments = new Option<bool>("--abort-on-unavailable-fragments", "--no-skip-unavailable-fragments");

		private Option<bool> keepFragments = new Option<bool>("--keep-fragments");

		private Option<bool> noKeepFragments = new Option<bool>("--no-keep-fragments");

		private Option<long?> bufferSize = new Option<long?>("--buffer-size");

		private Option<bool> resizeBuffer = new Option<bool>("--resize-buffer");

		private Option<bool> noResizeBuffer = new Option<bool>("--no-resize-buffer");

		private Option<long?> httpChunkSize = new Option<long?>("--http-chunk-size");

		private Option<bool> playlistRandom = new Option<bool>("--playlist-random");

		private Option<bool> lazyPlaylist = new Option<bool>("--lazy-playlist");

		private Option<bool> noLazyPlaylist = new Option<bool>("--no-lazy-playlist");

		private Option<bool> xattrSetFilesize = new Option<bool>("--xattr-set-filesize");

		private Option<bool> hlsUseMpegts = new Option<bool>("--hls-use-mpegts");

		private Option<bool> noHlsUseMpegts = new Option<bool>("--no-hls-use-mpegts");

		private MultiOption<string> downloadSections = new MultiOption<string>("--download-sections");

		private MultiOption<string> downloader = new MultiOption<string>("--downloader", "--external-downloader");

		private MultiOption<string> downloaderArgs = new MultiOption<string>("--downloader-args", "--external-downloader-args");

		private Option<int?> extractorRetries = new Option<int?>("--extractor-retries");

		private Option<bool> allowDynamicMpd = new Option<bool>("--allow-dynamic-mpd", "--no-ignore-dynamic-mpd");

		private Option<bool> ignoreDynamicMpd = new Option<bool>("--ignore-dynamic-mpd", "--no-allow-dynamic-mpd");

		private Option<bool> hlsSplitDiscontinuity = new Option<bool>("--hls-split-discontinuity");

		private Option<bool> noHlsSplitDiscontinuity = new Option<bool>("--no-hls-split-discontinuity");

		private MultiOption<string> extractorArgs = new MultiOption<string>("--extractor-args");

		private Option<string> batchFile = new Option<string>("-a", "--batch-file");

		private Option<bool> noBatchFile = new Option<bool>("--no-batch-file");

		private Option<string> paths = new Option<string>("-P", "--paths");

		private Option<string> output = new Option<string>("-o", "--output");

		private Option<string> outputNaPlaceholder = new Option<string>("--output-na-placeholder");

		private Option<bool> restrictFilenames = new Option<bool>("--restrict-filenames");

		private Option<bool> noRestrictFilenames = new Option<bool>("--no-restrict-filenames");

		private Option<bool> windowsFilenames = new Option<bool>("--windows-filenames");

		private Option<bool> noWindowsFilenames = new Option<bool>("--no-windows-filenames");

		private Option<int?> trimFilenames = new Option<int?>("--trim-filenames");

		private Option<bool> noOverwrites = new Option<bool>("-w", "--no-overwrites");

		private Option<bool> forceOverwrites = new Option<bool>("--force-overwrites");

		private Option<bool> noForceOverwrites = new Option<bool>("--no-force-overwrites");

		private Option<bool> doContinue = new Option<bool>("-c", "--continue");

		private Option<bool> noContinue = new Option<bool>("--no-continue");

		private Option<bool> part = new Option<bool>("--part");

		private Option<bool> noPart = new Option<bool>("--no-part");

		private Option<bool> mtime = new Option<bool>("--mtime");

		private Option<bool> noMtime = new Option<bool>("--no-mtime");

		private Option<bool> writeDescription = new Option<bool>("--write-description");

		private Option<bool> noWriteDescription = new Option<bool>("--no-write-description");

		private Option<bool> writeInfoJson = new Option<bool>("--write-info-json");

		private Option<bool> noWriteInfoJson = new Option<bool>("--no-write-info-json");

		private Option<bool> writePlaylistMetafiles = new Option<bool>("--write-playlist-metafiles");

		private Option<bool> noWritePlaylistMetafiles = new Option<bool>("--no-write-playlist-metafiles");

		private Option<bool> cleanInfoJson = new Option<bool>("--clean-info-json");

		private Option<bool> noCleanInfoJson = new Option<bool>("--no-clean-info-json");

		private Option<bool> writeComments = new Option<bool>("--write-comments", "--get-comments");

		private Option<bool> noWriteComments = new Option<bool>("--no-write-comments", "--no-get-comments");

		private Option<string> loadInfoJson = new Option<string>("--load-info-json");

		private Option<string> cookies = new Option<string>("--cookies");

		private Option<bool> noCookies = new Option<bool>("--no-cookies");

		private Option<string> cookiesFromBrowser = new Option<string>("--cookies-from-browser");

		private Option<bool> noCookiesFromBrowser = new Option<bool>("--no-cookies-from-browser");

		private Option<string> cacheDir = new Option<string>("--cache-dir");

		private Option<bool> noCacheDir = new Option<bool>("--no-cache-dir");

		private Option<bool> removeCacheDir = new Option<bool>("--rm-cache-dir");

		private Option<bool> help = new Option<bool>("-h", "--help");

		private Option<bool> version = new Option<bool>("--version");

		private Option<bool> update = new Option<bool>("-U", "--update");

		private Option<bool> noUpdate = new Option<bool>("--no-update");

		private Option<string> updateTo = new Option<string>("--update-to");

		private Option<bool> ignoreErrors = new Option<bool>("-i", "--ignore-errors");

		private Option<bool> noAbortOnError = new Option<bool>("--no-abort-on-error");

		private Option<bool> abortOnError = new Option<bool>("--abort-on-error", "--no-ignore-errors");

		private Option<bool> dumpUserAgent = new Option<bool>("--dump-user-agent");

		private Option<bool> listExtractors = new Option<bool>("--list-extractors");

		private Option<bool> extractorDescriptions = new Option<bool>("--extractor-descriptions");

		private Option<string> useExtractors = new Option<string>("--use-extractors", "--ies");

		private Option<string> defaultSearch = new Option<string>("--default-search");

		private Option<bool> ignoreConfig = new Option<bool>("--ignore-config", "--no-config");

		private Option<bool> noConfigLocations = new Option<bool>("--no-config-locations");

		private MultiOption<string> configLocations = new MultiOption<string>("--config-locations");

		private Option<bool> flatPlaylist = new Option<bool>("--flat-playlist");

		private Option<bool> noFlatPlaylist = new Option<bool>("--no-flat-playlist");

		private Option<bool> liveFromStart = new Option<bool>("--live-from-start");

		private Option<bool> noLiveFromStart = new Option<bool>("--no-live-from-start");

		private Option<string> waitForVideo = new Option<string>("--wait-for-video");

		private Option<bool> noWaitForVideo = new Option<bool>("--no-wait-for-video");

		private Option<bool> markWatched = new Option<bool>("--mark-watched");

		private Option<bool> noMarkWatched = new Option<bool>("--no-mark-watched");

		private MultiOption<string> color = new MultiOption<string>("--color");

		private Option<string> compatOptions = new Option<string>("--compat-options");

		private MultiOption<string> alias = new MultiOption<string>("--alias");

		private Option<string> geoVerificationProxy = new Option<string>("--geo-verification-proxy");

		private Option<string> xff = new Option<string>("--xff");

		private Option<bool> writeLink = new Option<bool>("--write-link");

		private Option<bool> writeUrlLink = new Option<bool>("--write-url-link");

		private Option<bool> writeWeblocLink = new Option<bool>("--write-webloc-link");

		private Option<bool> writeDesktopLink = new Option<bool>("--write-desktop-link");

		private Option<string> proxy = new Option<string>("--proxy");

		private Option<int?> socketTimeout = new Option<int?>("--socket-timeout");

		private Option<string> sourceAddress = new Option<string>("--source-address");

		private Option<bool> forceIPv4 = new Option<bool>("-4", "--force-ipv4");

		private Option<bool> forceIPv6 = new Option<bool>("-6", "--force-ipv6");

		private Option<bool> enableFileUrls = new Option<bool>("--enable-file-urls");

		private Option<bool> extractAudio = new Option<bool>("-x", "--extract-audio");

		private Option<AudioConversionFormat> audioFormat = new Option<AudioConversionFormat>("--audio-format");

		private Option<byte?> audioQuality = new Option<byte?>("--audio-quality");

		private Option<string> remuxVideo = new Option<string>("--remux-video");

		private Option<VideoRecodeFormat> recodeVideo = new Option<VideoRecodeFormat>("--recode-video");

		private MultiOption<string> postprocessorArgs = new MultiOption<string>("--postprocessor-args", "--ppa");

		private Option<bool> keepVideo = new Option<bool>("-k", "--keep-video");

		private Option<bool> noKeepVideo = new Option<bool>("--no-keep-video");

		private Option<bool> postOverwrites = new Option<bool>("--post-overwrites");

		private Option<bool> noPostOverwrites = new Option<bool>("--no-post-overwrites");

		private Option<bool> embedSubs = new Option<bool>("--embed-subs");

		private Option<bool> noEmbedSubs = new Option<bool>("--no-embed-subs");

		private Option<bool> embedThumbnail = new Option<bool>("--embed-thumbnail");

		private Option<bool> noEmbedThumbnail = new Option<bool>("--no-embed-thumbnail");

		private Option<bool> embedMetadata = new Option<bool>("--embed-metadata", "--add-metadata");

		private Option<bool> noEmbedMetadata = new Option<bool>("--no-embed-metadata", "--no-add-metadata");

		private Option<bool> embedChapters = new Option<bool>("--embed-chapters", "--add-chapters");

		private Option<bool> noEmbedChapters = new Option<bool>("--no-embed-chapters", "--no-add-chapters");

		private Option<bool> embedInfoJson = new Option<bool>("--embed-info-json");

		private Option<bool> noEmbedInfoJson = new Option<bool>("--no-embed-info-json");

		private Option<string> parseMetadata = new Option<string>("--parse-metadata");

		private MultiOption<string> replaceInMetadata = new MultiOption<string>("--replace-in-metadata");

		private Option<bool> xattrs = new Option<bool>("--xattrs");

		private Option<string> concatPlaylist = new Option<string>("--concat-playlist");

		private Option<string> fixup = new Option<string>("--fixup");

		private Option<string> ffmpegLocation = new Option<string>("--ffmpeg-location");

		private MultiOption<string> exec = new MultiOption<string>("--exec");

		private Option<bool> noExec = new Option<bool>("--no-exec");

		private Option<string> convertSubs = new Option<string>("--convert-subs", "--convert-subtitles");

		private Option<string> convertThumbnails = new Option<string>("--convert-thumbnails");

		private Option<bool> splitChapters = new Option<bool>("--split-chapters");

		private Option<bool> noSplitChapters = new Option<bool>("--no-split-chapters");

		private MultiOption<string> removeChapters = new MultiOption<string>("--remove-chapters");

		private Option<bool> noRemoveChapters = new Option<bool>("--no-remove-chapters");

		private Option<bool> forceKeyframesAtCuts = new Option<bool>("--force-keyframes-at-cuts");

		private Option<bool> noForceKeyframesAtCuts = new Option<bool>("--no-force-keyframes-at-cuts");

		private MultiOption<string> usePostprocessor = new MultiOption<string>("--use-postprocessor");

		private Option<string> sponsorblockMark = new Option<string>("--sponsorblock-mark");

		private Option<string> sponsorblockRemove = new Option<string>("--sponsorblock-remove");

		private Option<string> sponsorblockChapterTitle = new Option<string>("--sponsorblock-chapter-title");

		private Option<bool> noSponsorblock = new Option<bool>("--no-sponsorblock");

		private Option<string> sponsorblockApi = new Option<string>("--sponsorblock-api");

		private Option<bool> writeSubs = new Option<bool>("--write-subs");

		private Option<bool> noWriteSubs = new Option<bool>("--no-write-subs");

		private Option<bool> writeAutoSubs = new Option<bool>("--write-auto-subs", "--write-automatic-subs");

		private Option<bool> noWriteAutoSubs = new Option<bool>("--no-write-auto-subs", "--no-write-automatic-subs");

		private Option<bool> listSubs = new Option<bool>("--list-subs");

		private Option<string> subFormat = new Option<string>("--sub-format");

		private Option<string> subLangs = new Option<string>("--sub-langs");

		private Option<bool> writeThumbnail = new Option<bool>("--write-thumbnail");

		private Option<bool> noWriteThumbnail = new Option<bool>("--no-write-thumbnail");

		private Option<bool> writeAllThumbnails = new Option<bool>("--write-all-thumbnails");

		private Option<bool> listThumbnails = new Option<bool>("--list-thumbnails");

		private Option<bool> quiet = new Option<bool>("-q", "--quiet");

		private Option<bool> noQuiet = new Option<bool>("--no-quiet");

		private Option<bool> noWarnings = new Option<bool>("--no-warnings");

		private Option<bool> simulate = new Option<bool>("-s", "--simulate");

		private Option<bool> noSimulate = new Option<bool>("--no-simulate");

		private Option<bool> ignoreNoFormatsError = new Option<bool>("--ignore-no-formats-error");

		private Option<bool> noIgnoreNoFormatsError = new Option<bool>("--no-ignore-no-formats-error");

		private Option<bool> skipDownload = new Option<bool>("--skip-download", "--no-download");

		private MultiOption<string> print = new MultiOption<string>("-O", "--print");

		private MultiOption<string> printToFile = new MultiOption<string>("--print-to-file");

		private Option<bool> dumpJson = new Option<bool>("-j", "--dump-json");

		private Option<bool> dumpSingleJson = new Option<bool>("-J", "--dump-single-json");

		private Option<bool> forceWriteArchive = new Option<bool>("--force-write-archive", "--force-download-archive");

		private Option<bool> newline = new Option<bool>("--newline");

		private Option<bool> noProgress = new Option<bool>("--no-progress");

		private Option<bool> progress = new Option<bool>("--progress");

		private Option<bool> consoleTitle = new Option<bool>("--console-title");

		private Option<string> progressTemplate = new Option<string>("--progress-template");

		private Option<bool> verbose = new Option<bool>("-v", "--verbose");

		private Option<bool> dumpPages = new Option<bool>("--dump-pages");

		private Option<bool> writePages = new Option<bool>("--write-pages");

		private Option<bool> printTraffic = new Option<bool>("--print-traffic");

		private Option<string> format = new Option<string>("-f", "--format");

		private Option<string> formatSort = new Option<string>("-S", "--format-sort");

		private Option<bool> formatSortForce = new Option<bool>("--format-sort-force", "--S-force");

		private Option<bool> noFormatSortForce = new Option<bool>("--no-format-sort-force");

		private Option<bool> videoMultistreams = new Option<bool>("--video-multistreams");

		private Option<bool> noVideoMultistreams = new Option<bool>("--no-video-multistreams");

		private Option<bool> audioMultistreams = new Option<bool>("--audio-multistreams");

		private Option<bool> noAudioMultistreams = new Option<bool>("--no-audio-multistreams");

		private Option<bool> preferFreeFormats = new Option<bool>("--prefer-free-formats");

		private Option<bool> noPreferFreeFormats = new Option<bool>("--no-prefer-free-formats");

		private Option<bool> checkFormats = new Option<bool>("--check-formats");

		private Option<bool> checkAllFormats = new Option<bool>("--check-all-formats");

		private Option<bool> noCheckFormats = new Option<bool>("--no-check-formats");

		private Option<bool> listFormats = new Option<bool>("-F", "--list-formats");

		private Option<DownloadMergeFormat> mergeOutputFormat = new Option<DownloadMergeFormat>("--merge-output-format");

		private Option<string> playlistItems = new Option<string>("-I", "--playlist-items");

		private Option<string> minFilesize = new Option<string>("--min-filesize");

		private Option<string> maxFilesize = new Option<string>("--max-filesize");

		private Option<DateTime> date = new Option<DateTime>("--date");

		private Option<DateTime> dateBefore = new Option<DateTime>("--datebefore");

		private Option<DateTime> dateAfter = new Option<DateTime>("--dateafter");

		private MultiOption<string> matchFilters = new MultiOption<string>("--match-filters");

		private Option<bool> noMatchFilters = new Option<bool>("--no-match-filters");

		private Option<string> breakMatchFilters = new Option<string>("--break-match-filters");

		private Option<bool> noBreakMatchFilters = new Option<bool>("--no-break-match-filters");

		private Option<bool> noPlaylist = new Option<bool>("--no-playlist");

		private Option<bool> yesPlaylist = new Option<bool>("--yes-playlist");

		private Option<byte?> ageLimit = new Option<byte?>("--age-limit");

		private Option<string> downloadArchive = new Option<string>("--download-archive");

		private Option<bool> noDownloadArchive = new Option<bool>("--no-download-archive");

		private Option<int?> maxDownloads = new Option<int?>("--max-downloads");

		private Option<bool> breakOnExisting = new Option<bool>("--break-on-existing");

		private Option<bool> breakPerInput = new Option<bool>("--break-per-input");

		private Option<bool> noBreakPerInput = new Option<bool>("--no-break-per-input");

		private Option<int?> skipPlaylistAfterErrors = new Option<int?>("--skip-playlist-after-errors");

		private Option<string> encoding = new Option<string>("--encoding");

		private Option<bool> legacyServerConnect = new Option<bool>("--legacy-server-connect");

		private Option<bool> noCheckCertificates = new Option<bool>("--no-check-certificates");

		private Option<bool> preferInsecure = new Option<bool>("--prefer-insecure");

		private MultiOption<string> addHeaders = new MultiOption<string>("--add-headers");

		private Option<bool> bidiWorkaround = new Option<bool>("--bidi-workaround");

		private Option<int?> sleepRequests = new Option<int?>("--sleep-requests");

		private Option<int?> sleepInterval = new Option<int?>("--sleep-interval", "--min-sleep-interval");

		private Option<int?> maxSleepInterval = new Option<int?>("--max-sleep-interval");

		private Option<int?> sleepSubtitles = new Option<int?>("--sleep-subtitles");

		public string Username
		{
			get
			{
				return username.Value;
			}
			set
			{
				username.Value = value;
			}
		}

		public string Password
		{
			get
			{
				return password.Value;
			}
			set
			{
				password.Value = value;
			}
		}

		public string TwoFactor
		{
			get
			{
				return twoFactor.Value;
			}
			set
			{
				twoFactor.Value = value;
			}
		}

		public bool Netrc
		{
			get
			{
				return netrc.Value;
			}
			set
			{
				netrc.Value = value;
			}
		}

		public string NetrcLocation
		{
			get
			{
				return netrcLocation.Value;
			}
			set
			{
				netrcLocation.Value = value;
			}
		}

		public string NetrcCmd
		{
			get
			{
				return netrcCmd.Value;
			}
			set
			{
				netrcCmd.Value = value;
			}
		}

		public string VideoPassword
		{
			get
			{
				return videoPassword.Value;
			}
			set
			{
				videoPassword.Value = value;
			}
		}

		public string ApMso
		{
			get
			{
				return apMso.Value;
			}
			set
			{
				apMso.Value = value;
			}
		}

		public string ApUsername
		{
			get
			{
				return apUsername.Value;
			}
			set
			{
				apUsername.Value = value;
			}
		}

		public string ApPassword
		{
			get
			{
				return apPassword.Value;
			}
			set
			{
				apPassword.Value = value;
			}
		}

		public bool ApListMso
		{
			get
			{
				return apListMso.Value;
			}
			set
			{
				apListMso.Value = value;
			}
		}

		public string ClientCertificate
		{
			get
			{
				return clientCertificate.Value;
			}
			set
			{
				clientCertificate.Value = value;
			}
		}

		public string ClientCertificateKey
		{
			get
			{
				return clientCertificateKey.Value;
			}
			set
			{
				clientCertificateKey.Value = value;
			}
		}

		public string ClientCertificatePassword
		{
			get
			{
				return clientCertificatePassword.Value;
			}
			set
			{
				clientCertificatePassword.Value = value;
			}
		}

		public IOption[] CustomOptions { get; set; } = new IOption[0];


		[Obsolete("Deprecated in favor of: --print description.")]
		public bool GetDescription
		{
			get
			{
				return getDescription.Value;
			}
			set
			{
				getDescription.Value = value;
			}
		}

		[Obsolete("Deprecated in favor of: --print duration_string.")]
		public bool GetDuration
		{
			get
			{
				return getDuration.Value;
			}
			set
			{
				getDuration.Value = value;
			}
		}

		[Obsolete("Deprecated in favor of: --print filename.")]
		public bool GetFilename
		{
			get
			{
				return getFilename.Value;
			}
			set
			{
				getFilename.Value = value;
			}
		}

		[Obsolete("Deprecated in favor of: --print format.")]
		public bool GetFormat
		{
			get
			{
				return getFormat.Value;
			}
			set
			{
				getFormat.Value = value;
			}
		}

		[Obsolete("Deprecated in favor of: --print id.")]
		public bool GetId
		{
			get
			{
				return getId.Value;
			}
			set
			{
				getId.Value = value;
			}
		}

		[Obsolete("Deprecated in favor of: --print thumbnail.")]
		public bool GetThumbnail
		{
			get
			{
				return getThumbnail.Value;
			}
			set
			{
				getThumbnail.Value = value;
			}
		}

		[Obsolete("Deprecated in favor of: --print title.")]
		public bool GetTitle
		{
			get
			{
				return getTitle.Value;
			}
			set
			{
				getTitle.Value = value;
			}
		}

		[Obsolete("Deprecated in favor of: --print urls.")]
		public bool GetUrl
		{
			get
			{
				return getUrl.Value;
			}
			set
			{
				getUrl.Value = value;
			}
		}

		[Obsolete("Deprecated in favor of: --match-filter \"title ~= (?i)REGEX\".")]
		public string MatchTitle
		{
			get
			{
				return matchTitle.Value;
			}
			set
			{
				matchTitle.Value = value;
			}
		}

		[Obsolete("Deprecated in favor of: --match-filter \"title !~= (?i)REGEX\".")]
		public string RejectTitle
		{
			get
			{
				return rejectTitle.Value;
			}
			set
			{
				rejectTitle.Value = value;
			}
		}

		[Obsolete("Deprecated in favor of: --match-filter \"view_count >=? COUNT\".")]
		public long? MinViews
		{
			get
			{
				return minViews.Value;
			}
			set
			{
				minViews.Value = value;
			}
		}

		[Obsolete("Deprecated in favor of: --match-filter \"view_count <=? COUNT\".")]
		public long? MaxViews
		{
			get
			{
				return maxViews.Value;
			}
			set
			{
				maxViews.Value = value;
			}
		}

		[Obsolete("Deprecated in favor of: Use --break-match-filter.")]
		public bool BreakOnReject
		{
			get
			{
				return breakOnReject.Value;
			}
			set
			{
				breakOnReject.Value = value;
			}
		}

		[Obsolete("Deprecated in favor of: --add-header \"User-Agent:UA\".")]
		public string UserAgent
		{
			get
			{
				return userAgent.Value;
			}
			set
			{
				userAgent.Value = value;
			}
		}

		[Obsolete("Deprecated in favor of: --add-header \"Referer:URL\".")]
		public string Referer
		{
			get
			{
				return referer.Value;
			}
			set
			{
				referer.Value = value;
			}
		}

		[Obsolete("Deprecated in favor of: -I NUMBER:.")]
		public int? PlaylistStart
		{
			get
			{
				return playlistStart.Value;
			}
			set
			{
				playlistStart.Value = value;
			}
		}

		[Obsolete("Deprecated in favor of: -I :NUMBER.")]
		public int? PlaylistEnd
		{
			get
			{
				return playlistEnd.Value;
			}
			set
			{
				playlistEnd.Value = value;
			}
		}

		[Obsolete("Deprecated in favor of: -I ::-1.")]
		public bool PlaylistReverse
		{
			get
			{
				return playlistReverse.Value;
			}
			set
			{
				playlistReverse.Value = value;
			}
		}

		[Obsolete("Deprecated in favor of: --color no_color.")]
		public bool NoColors
		{
			get
			{
				return noColors.Value;
			}
			set
			{
				noColors.Value = value;
			}
		}

		[Obsolete("Deprecated in favor of: --ies generic,default.")]
		public bool ForceGenericExtractor
		{
			get
			{
				return forceGenericExtractor.Value;
			}
			set
			{
				forceGenericExtractor.Value = value;
			}
		}

		[Obsolete("Deprecated in favor of: --exec \"before_dl:CMD\".")]
		public string ExecBeforeDownload
		{
			get
			{
				return execBeforeDownload.Value;
			}
			set
			{
				execBeforeDownload.Value = value;
			}
		}

		[Obsolete("Deprecated in favor of: --no-exec.")]
		public bool NoExecBeforeDownload
		{
			get
			{
				return noExecBeforeDownload.Value;
			}
			set
			{
				noExecBeforeDownload.Value = value;
			}
		}

		[Obsolete("Deprecated in favor of: -f all.")]
		public bool AllFormats
		{
			get
			{
				return allFormats.Value;
			}
			set
			{
				allFormats.Value = value;
			}
		}

		[Obsolete("Deprecated in favor of: --sub-langs all --write-subs.")]
		public bool AllSubs
		{
			get
			{
				return allSubs.Value;
			}
			set
			{
				allSubs.Value = value;
			}
		}

		[Obsolete("Deprecated in favor of: -j --no-simulate.")]
		public bool PrintJson
		{
			get
			{
				return printJson.Value;
			}
			set
			{
				printJson.Value = value;
			}
		}

		[Obsolete("Deprecated in favor of: Use string formatting, e.g. %(autonumber)03d.")]
		public string AutonumberSize
		{
			get
			{
				return autonumberSize.Value;
			}
			set
			{
				autonumberSize.Value = value;
			}
		}

		[Obsolete("Deprecated in favor of: Use internal field formatting like %(autonumber+NUMBER)s.")]
		public int? AutonumberStart
		{
			get
			{
				return autonumberStart.Value;
			}
			set
			{
				autonumberStart.Value = value;
			}
		}

		[Obsolete("Deprecated in favor of: -o \"%(id)s.%(ext)s\".")]
		public bool Id
		{
			get
			{
				return id.Value;
			}
			set
			{
				id.Value = value;
			}
		}

		[Obsolete("Deprecated in favor of: --parse-metadata \"%(title)s:FORMAT\".")]
		public string MetadataFromTitle
		{
			get
			{
				return metadataFromTitle.Value;
			}
			set
			{
				metadataFromTitle.Value = value;
			}
		}

		[Obsolete("Deprecated in favor of: --downloader \"m3u8:native\".")]
		public bool HlsPreferNative
		{
			get
			{
				return hlsPreferNative.Value;
			}
			set
			{
				hlsPreferNative.Value = value;
			}
		}

		[Obsolete("Deprecated in favor of: --downloader \"m3u8:ffmpeg\".")]
		public bool HlsPreferFfmpeg
		{
			get
			{
				return hlsPreferFfmpeg.Value;
			}
			set
			{
				hlsPreferFfmpeg.Value = value;
			}
		}

		[Obsolete("Deprecated in favor of: --compat-options list-formats (Alias: --no-list-formats-as-table).")]
		public bool ListFormatsOld
		{
			get
			{
				return listFormatsOld.Value;
			}
			set
			{
				listFormatsOld.Value = value;
			}
		}

		[Obsolete("Deprecated in favor of: --compat-options -list-formats [Default] (Alias: --no-list-formats-old).")]
		public bool ListFormatsAsTable
		{
			get
			{
				return listFormatsAsTable.Value;
			}
			set
			{
				listFormatsAsTable.Value = value;
			}
		}

		[Obsolete("Deprecated in favor of: --extractor-args \"youtube:skip=dash\" (Alias: --no-youtube-include-dash-manifest).")]
		public bool YoutubeSkipDashManifest
		{
			get
			{
				return youtubeSkipDashManifest.Value;
			}
			set
			{
				youtubeSkipDashManifest.Value = value;
			}
		}

		[Obsolete("Deprecated in favor of: --extractor-args \"youtube:skip=hls\" (Alias: --no-youtube-include-hls-manifest).")]
		public bool YoutubeSkipHlsManifest
		{
			get
			{
				return youtubeSkipHlsManifest.Value;
			}
			set
			{
				youtubeSkipHlsManifest.Value = value;
			}
		}

		[Obsolete("Deprecated in favor of: --xff \"default\".")]
		public bool GeoBypass
		{
			get
			{
				return geoBypass.Value;
			}
			set
			{
				geoBypass.Value = value;
			}
		}

		[Obsolete("Deprecated in favor of: --xff \"never\".")]
		public bool NoGeoBypass
		{
			get
			{
				return noGeoBypass.Value;
			}
			set
			{
				noGeoBypass.Value = value;
			}
		}

		[Obsolete("Deprecated in favor of: --xff CODE.")]
		public string GeoBypassCountry
		{
			get
			{
				return geoBypassCountry.Value;
			}
			set
			{
				geoBypassCountry.Value = value;
			}
		}

		[Obsolete("Deprecated in favor of: --xff IP_BLOCK.")]
		public string GeoBypassIpBlock
		{
			get
			{
				return geoBypassIpBlock.Value;
			}
			set
			{
				geoBypassIpBlock.Value = value;
			}
		}

		public int? ConcurrentFragments
		{
			get
			{
				return concurrentFragments.Value;
			}
			set
			{
				concurrentFragments.Value = value;
			}
		}

		public long? LimitRate
		{
			get
			{
				return limitRate.Value;
			}
			set
			{
				limitRate.Value = value;
			}
		}

		public long? ThrottledRate
		{
			get
			{
				return throttledRate.Value;
			}
			set
			{
				throttledRate.Value = value;
			}
		}

		public int? Retries
		{
			get
			{
				return retries.Value;
			}
			set
			{
				retries.Value = value;
			}
		}

		public int? FileAccessRetries
		{
			get
			{
				return fileAccessRetries.Value;
			}
			set
			{
				fileAccessRetries.Value = value;
			}
		}

		public int? FragmentRetries
		{
			get
			{
				return fragmentRetries.Value;
			}
			set
			{
				fragmentRetries.Value = value;
			}
		}

		public MultiValue<string> RetrySleep
		{
			get
			{
				return retrySleep.Value;
			}
			set
			{
				retrySleep.Value = value;
			}
		}

		public bool SkipUnavailableFragments
		{
			get
			{
				return skipUnavailableFragments.Value;
			}
			set
			{
				skipUnavailableFragments.Value = value;
			}
		}

		public bool AbortOnUnavailableFragments
		{
			get
			{
				return abortOnUnavailableFragments.Value;
			}
			set
			{
				abortOnUnavailableFragments.Value = value;
			}
		}

		public bool KeepFragments
		{
			get
			{
				return keepFragments.Value;
			}
			set
			{
				keepFragments.Value = value;
			}
		}

		public bool NoKeepFragments
		{
			get
			{
				return noKeepFragments.Value;
			}
			set
			{
				noKeepFragments.Value = value;
			}
		}

		public long? BufferSize
		{
			get
			{
				return bufferSize.Value;
			}
			set
			{
				bufferSize.Value = value;
			}
		}

		public bool ResizeBuffer
		{
			get
			{
				return resizeBuffer.Value;
			}
			set
			{
				resizeBuffer.Value = value;
			}
		}

		public bool NoResizeBuffer
		{
			get
			{
				return noResizeBuffer.Value;
			}
			set
			{
				noResizeBuffer.Value = value;
			}
		}

		public long? HttpChunkSize
		{
			get
			{
				return httpChunkSize.Value;
			}
			set
			{
				httpChunkSize.Value = value;
			}
		}

		public bool PlaylistRandom
		{
			get
			{
				return playlistRandom.Value;
			}
			set
			{
				playlistRandom.Value = value;
			}
		}

		public bool LazyPlaylist
		{
			get
			{
				return lazyPlaylist.Value;
			}
			set
			{
				lazyPlaylist.Value = value;
			}
		}

		public bool NoLazyPlaylist
		{
			get
			{
				return noLazyPlaylist.Value;
			}
			set
			{
				noLazyPlaylist.Value = value;
			}
		}

		public bool XattrSetFilesize
		{
			get
			{
				return xattrSetFilesize.Value;
			}
			set
			{
				xattrSetFilesize.Value = value;
			}
		}

		public bool HlsUseMpegts
		{
			get
			{
				return hlsUseMpegts.Value;
			}
			set
			{
				hlsUseMpegts.Value = value;
			}
		}

		public bool NoHlsUseMpegts
		{
			get
			{
				return noHlsUseMpegts.Value;
			}
			set
			{
				noHlsUseMpegts.Value = value;
			}
		}

		public MultiValue<string> DownloadSections
		{
			get
			{
				return downloadSections.Value;
			}
			set
			{
				downloadSections.Value = value;
			}
		}

		public MultiValue<string> Downloader
		{
			get
			{
				return downloader.Value;
			}
			set
			{
				downloader.Value = value;
			}
		}

		public MultiValue<string> DownloaderArgs
		{
			get
			{
				return downloaderArgs.Value;
			}
			set
			{
				downloaderArgs.Value = value;
			}
		}

		public int? ExtractorRetries
		{
			get
			{
				return extractorRetries.Value;
			}
			set
			{
				extractorRetries.Value = value;
			}
		}

		public bool AllowDynamicMpd
		{
			get
			{
				return allowDynamicMpd.Value;
			}
			set
			{
				allowDynamicMpd.Value = value;
			}
		}

		public bool IgnoreDynamicMpd
		{
			get
			{
				return ignoreDynamicMpd.Value;
			}
			set
			{
				ignoreDynamicMpd.Value = value;
			}
		}

		public bool HlsSplitDiscontinuity
		{
			get
			{
				return hlsSplitDiscontinuity.Value;
			}
			set
			{
				hlsSplitDiscontinuity.Value = value;
			}
		}

		public bool NoHlsSplitDiscontinuity
		{
			get
			{
				return noHlsSplitDiscontinuity.Value;
			}
			set
			{
				noHlsSplitDiscontinuity.Value = value;
			}
		}

		public MultiValue<string> ExtractorArgs
		{
			get
			{
				return extractorArgs.Value;
			}
			set
			{
				extractorArgs.Value = value;
			}
		}

		public string BatchFile
		{
			get
			{
				return batchFile.Value;
			}
			set
			{
				batchFile.Value = value;
			}
		}

		public bool NoBatchFile
		{
			get
			{
				return noBatchFile.Value;
			}
			set
			{
				noBatchFile.Value = value;
			}
		}

		public string Paths
		{
			get
			{
				return paths.Value;
			}
			set
			{
				paths.Value = value;
			}
		}

		public string Output
		{
			get
			{
				return output.Value;
			}
			set
			{
				output.Value = value;
			}
		}

		public string OutputNaPlaceholder
		{
			get
			{
				return outputNaPlaceholder.Value;
			}
			set
			{
				outputNaPlaceholder.Value = value;
			}
		}

		public bool RestrictFilenames
		{
			get
			{
				return restrictFilenames.Value;
			}
			set
			{
				restrictFilenames.Value = value;
			}
		}

		public bool NoRestrictFilenames
		{
			get
			{
				return noRestrictFilenames.Value;
			}
			set
			{
				noRestrictFilenames.Value = value;
			}
		}

		public bool WindowsFilenames
		{
			get
			{
				return windowsFilenames.Value;
			}
			set
			{
				windowsFilenames.Value = value;
			}
		}

		public bool NoWindowsFilenames
		{
			get
			{
				return noWindowsFilenames.Value;
			}
			set
			{
				noWindowsFilenames.Value = value;
			}
		}

		public int? TrimFilenames
		{
			get
			{
				return trimFilenames.Value;
			}
			set
			{
				trimFilenames.Value = value;
			}
		}

		public bool NoOverwrites
		{
			get
			{
				return noOverwrites.Value;
			}
			set
			{
				noOverwrites.Value = value;
			}
		}

		public bool ForceOverwrites
		{
			get
			{
				return forceOverwrites.Value;
			}
			set
			{
				forceOverwrites.Value = value;
			}
		}

		public bool NoForceOverwrites
		{
			get
			{
				return noForceOverwrites.Value;
			}
			set
			{
				noForceOverwrites.Value = value;
			}
		}

		public bool Continue
		{
			get
			{
				return doContinue.Value;
			}
			set
			{
				doContinue.Value = value;
			}
		}

		public bool NoContinue
		{
			get
			{
				return noContinue.Value;
			}
			set
			{
				noContinue.Value = value;
			}
		}

		public bool Part
		{
			get
			{
				return part.Value;
			}
			set
			{
				part.Value = value;
			}
		}

		public bool NoPart
		{
			get
			{
				return noPart.Value;
			}
			set
			{
				noPart.Value = value;
			}
		}

		public bool Mtime
		{
			get
			{
				return mtime.Value;
			}
			set
			{
				mtime.Value = value;
			}
		}

		public bool NoMtime
		{
			get
			{
				return noMtime.Value;
			}
			set
			{
				noMtime.Value = value;
			}
		}

		public bool WriteDescription
		{
			get
			{
				return writeDescription.Value;
			}
			set
			{
				writeDescription.Value = value;
			}
		}

		public bool NoWriteDescription
		{
			get
			{
				return noWriteDescription.Value;
			}
			set
			{
				noWriteDescription.Value = value;
			}
		}

		public bool WriteInfoJson
		{
			get
			{
				return writeInfoJson.Value;
			}
			set
			{
				writeInfoJson.Value = value;
			}
		}

		public bool NoWriteInfoJson
		{
			get
			{
				return noWriteInfoJson.Value;
			}
			set
			{
				noWriteInfoJson.Value = value;
			}
		}

		public bool WritePlaylistMetafiles
		{
			get
			{
				return writePlaylistMetafiles.Value;
			}
			set
			{
				writePlaylistMetafiles.Value = value;
			}
		}

		public bool NoWritePlaylistMetafiles
		{
			get
			{
				return noWritePlaylistMetafiles.Value;
			}
			set
			{
				noWritePlaylistMetafiles.Value = value;
			}
		}

		public bool CleanInfoJson
		{
			get
			{
				return cleanInfoJson.Value;
			}
			set
			{
				cleanInfoJson.Value = value;
			}
		}

		public bool NoCleanInfoJson
		{
			get
			{
				return noCleanInfoJson.Value;
			}
			set
			{
				noCleanInfoJson.Value = value;
			}
		}

		public bool WriteComments
		{
			get
			{
				return writeComments.Value;
			}
			set
			{
				writeComments.Value = value;
			}
		}

		public bool NoWriteComments
		{
			get
			{
				return noWriteComments.Value;
			}
			set
			{
				noWriteComments.Value = value;
			}
		}

		public string LoadInfoJson
		{
			get
			{
				return loadInfoJson.Value;
			}
			set
			{
				loadInfoJson.Value = value;
			}
		}

		public string Cookies
		{
			get
			{
				return cookies.Value;
			}
			set
			{
				cookies.Value = value;
			}
		}

		public bool NoCookies
		{
			get
			{
				return noCookies.Value;
			}
			set
			{
				noCookies.Value = value;
			}
		}

		public string CookiesFromBrowser
		{
			get
			{
				return cookiesFromBrowser.Value;
			}
			set
			{
				cookiesFromBrowser.Value = value;
			}
		}

		public bool NoCookiesFromBrowser
		{
			get
			{
				return noCookiesFromBrowser.Value;
			}
			set
			{
				noCookiesFromBrowser.Value = value;
			}
		}

		public string CacheDir
		{
			get
			{
				return cacheDir.Value;
			}
			set
			{
				cacheDir.Value = value;
			}
		}

		public bool NoCacheDir
		{
			get
			{
				return noCacheDir.Value;
			}
			set
			{
				noCacheDir.Value = value;
			}
		}

		public bool RemoveCacheDir
		{
			get
			{
				return removeCacheDir.Value;
			}
			set
			{
				removeCacheDir.Value = value;
			}
		}

		public bool Help
		{
			get
			{
				return help.Value;
			}
			set
			{
				help.Value = value;
			}
		}

		public bool Version
		{
			get
			{
				return version.Value;
			}
			set
			{
				version.Value = value;
			}
		}

		public bool Update
		{
			get
			{
				return update.Value;
			}
			set
			{
				update.Value = value;
			}
		}

		public bool NoUpdate
		{
			get
			{
				return noUpdate.Value;
			}
			set
			{
				noUpdate.Value = value;
			}
		}

		public string UpdateTo
		{
			get
			{
				return updateTo.Value;
			}
			set
			{
				updateTo.Value = value;
			}
		}

		public bool IgnoreErrors
		{
			get
			{
				return ignoreErrors.Value;
			}
			set
			{
				ignoreErrors.Value = value;
			}
		}

		public bool NoAbortOnError
		{
			get
			{
				return noAbortOnError.Value;
			}
			set
			{
				noAbortOnError.Value = value;
			}
		}

		public bool AbortOnError
		{
			get
			{
				return abortOnError.Value;
			}
			set
			{
				abortOnError.Value = value;
			}
		}

		public bool DumpUserAgent
		{
			get
			{
				return dumpUserAgent.Value;
			}
			set
			{
				dumpUserAgent.Value = value;
			}
		}

		public bool ListExtractors
		{
			get
			{
				return listExtractors.Value;
			}
			set
			{
				listExtractors.Value = value;
			}
		}

		public bool ExtractorDescriptions
		{
			get
			{
				return extractorDescriptions.Value;
			}
			set
			{
				extractorDescriptions.Value = value;
			}
		}

		public string UseExtractors
		{
			get
			{
				return useExtractors.Value;
			}
			set
			{
				useExtractors.Value = value;
			}
		}

		public string DefaultSearch
		{
			get
			{
				return defaultSearch.Value;
			}
			set
			{
				defaultSearch.Value = value;
			}
		}

		public bool IgnoreConfig
		{
			get
			{
				return ignoreConfig.Value;
			}
			set
			{
				ignoreConfig.Value = value;
			}
		}

		public bool NoConfigLocations
		{
			get
			{
				return noConfigLocations.Value;
			}
			set
			{
				noConfigLocations.Value = value;
			}
		}

		public MultiValue<string> ConfigLocations
		{
			get
			{
				return configLocations.Value;
			}
			set
			{
				configLocations.Value = value;
			}
		}

		public bool FlatPlaylist
		{
			get
			{
				return flatPlaylist.Value;
			}
			set
			{
				flatPlaylist.Value = value;
			}
		}

		public bool NoFlatPlaylist
		{
			get
			{
				return noFlatPlaylist.Value;
			}
			set
			{
				noFlatPlaylist.Value = value;
			}
		}

		public bool LiveFromStart
		{
			get
			{
				return liveFromStart.Value;
			}
			set
			{
				liveFromStart.Value = value;
			}
		}

		public bool NoLiveFromStart
		{
			get
			{
				return noLiveFromStart.Value;
			}
			set
			{
				noLiveFromStart.Value = value;
			}
		}

		public string WaitForVideo
		{
			get
			{
				return waitForVideo.Value;
			}
			set
			{
				waitForVideo.Value = value;
			}
		}

		public bool NoWaitForVideo
		{
			get
			{
				return noWaitForVideo.Value;
			}
			set
			{
				noWaitForVideo.Value = value;
			}
		}

		public bool MarkWatched
		{
			get
			{
				return markWatched.Value;
			}
			set
			{
				markWatched.Value = value;
			}
		}

		public bool NoMarkWatched
		{
			get
			{
				return noMarkWatched.Value;
			}
			set
			{
				noMarkWatched.Value = value;
			}
		}

		public MultiValue<string> Color
		{
			get
			{
				return color.Value;
			}
			set
			{
				color.Value = value;
			}
		}

		public string CompatOptions
		{
			get
			{
				return compatOptions.Value;
			}
			set
			{
				compatOptions.Value = value;
			}
		}

		public MultiValue<string> Alias
		{
			get
			{
				return alias.Value;
			}
			set
			{
				alias.Value = value;
			}
		}

		public string GeoVerificationProxy
		{
			get
			{
				return geoVerificationProxy.Value;
			}
			set
			{
				geoVerificationProxy.Value = value;
			}
		}

		public string Xff
		{
			get
			{
				return xff.Value;
			}
			set
			{
				xff.Value = value;
			}
		}

		public bool WriteLink
		{
			get
			{
				return writeLink.Value;
			}
			set
			{
				writeLink.Value = value;
			}
		}

		public bool WriteUrlLink
		{
			get
			{
				return writeUrlLink.Value;
			}
			set
			{
				writeUrlLink.Value = value;
			}
		}

		public bool WriteWeblocLink
		{
			get
			{
				return writeWeblocLink.Value;
			}
			set
			{
				writeWeblocLink.Value = value;
			}
		}

		public bool WriteDesktopLink
		{
			get
			{
				return writeDesktopLink.Value;
			}
			set
			{
				writeDesktopLink.Value = value;
			}
		}

		public string Proxy
		{
			get
			{
				return proxy.Value;
			}
			set
			{
				proxy.Value = value;
			}
		}

		public int? SocketTimeout
		{
			get
			{
				return socketTimeout.Value;
			}
			set
			{
				socketTimeout.Value = value;
			}
		}

		public string SourceAddress
		{
			get
			{
				return sourceAddress.Value;
			}
			set
			{
				sourceAddress.Value = value;
			}
		}

		public bool ForceIPv4
		{
			get
			{
				return forceIPv4.Value;
			}
			set
			{
				forceIPv4.Value = value;
			}
		}

		public bool ForceIPv6
		{
			get
			{
				return forceIPv6.Value;
			}
			set
			{
				forceIPv6.Value = value;
			}
		}

		public bool EnableFileUrls
		{
			get
			{
				return enableFileUrls.Value;
			}
			set
			{
				enableFileUrls.Value = value;
			}
		}

		public bool ExtractAudio
		{
			get
			{
				return extractAudio.Value;
			}
			set
			{
				extractAudio.Value = value;
			}
		}

		public AudioConversionFormat AudioFormat
		{
			get
			{
				return audioFormat.Value;
			}
			set
			{
				audioFormat.Value = value;
			}
		}

		public byte? AudioQuality
		{
			get
			{
				return audioQuality.Value;
			}
			set
			{
				audioQuality.Value = value;
			}
		}

		public string RemuxVideo
		{
			get
			{
				return remuxVideo.Value;
			}
			set
			{
				remuxVideo.Value = value;
			}
		}

		public VideoRecodeFormat RecodeVideo
		{
			get
			{
				return recodeVideo.Value;
			}
			set
			{
				recodeVideo.Value = value;
			}
		}

		public MultiValue<string> PostprocessorArgs
		{
			get
			{
				return postprocessorArgs.Value;
			}
			set
			{
				postprocessorArgs.Value = value;
			}
		}

		public bool KeepVideo
		{
			get
			{
				return keepVideo.Value;
			}
			set
			{
				keepVideo.Value = value;
			}
		}

		public bool NoKeepVideo
		{
			get
			{
				return noKeepVideo.Value;
			}
			set
			{
				noKeepVideo.Value = value;
			}
		}

		public bool PostOverwrites
		{
			get
			{
				return postOverwrites.Value;
			}
			set
			{
				postOverwrites.Value = value;
			}
		}

		public bool NoPostOverwrites
		{
			get
			{
				return noPostOverwrites.Value;
			}
			set
			{
				noPostOverwrites.Value = value;
			}
		}

		public bool EmbedSubs
		{
			get
			{
				return embedSubs.Value;
			}
			set
			{
				embedSubs.Value = value;
			}
		}

		public bool NoEmbedSubs
		{
			get
			{
				return noEmbedSubs.Value;
			}
			set
			{
				noEmbedSubs.Value = value;
			}
		}

		public bool EmbedThumbnail
		{
			get
			{
				return embedThumbnail.Value;
			}
			set
			{
				embedThumbnail.Value = value;
			}
		}

		public bool NoEmbedThumbnail
		{
			get
			{
				return noEmbedThumbnail.Value;
			}
			set
			{
				noEmbedThumbnail.Value = value;
			}
		}

		public bool EmbedMetadata
		{
			get
			{
				return embedMetadata.Value;
			}
			set
			{
				embedMetadata.Value = value;
			}
		}

		public bool NoEmbedMetadata
		{
			get
			{
				return noEmbedMetadata.Value;
			}
			set
			{
				noEmbedMetadata.Value = value;
			}
		}

		public bool EmbedChapters
		{
			get
			{
				return embedChapters.Value;
			}
			set
			{
				embedChapters.Value = value;
			}
		}

		public bool NoEmbedChapters
		{
			get
			{
				return noEmbedChapters.Value;
			}
			set
			{
				noEmbedChapters.Value = value;
			}
		}

		public bool EmbedInfoJson
		{
			get
			{
				return embedInfoJson.Value;
			}
			set
			{
				embedInfoJson.Value = value;
			}
		}

		public bool NoEmbedInfoJson
		{
			get
			{
				return noEmbedInfoJson.Value;
			}
			set
			{
				noEmbedInfoJson.Value = value;
			}
		}

		public string ParseMetadata
		{
			get
			{
				return parseMetadata.Value;
			}
			set
			{
				parseMetadata.Value = value;
			}
		}

		public MultiValue<string> ReplaceInMetadata
		{
			get
			{
				return replaceInMetadata.Value;
			}
			set
			{
				replaceInMetadata.Value = value;
			}
		}

		public bool Xattrs
		{
			get
			{
				return xattrs.Value;
			}
			set
			{
				xattrs.Value = value;
			}
		}

		public string ConcatPlaylist
		{
			get
			{
				return concatPlaylist.Value;
			}
			set
			{
				concatPlaylist.Value = value;
			}
		}

		public string Fixup
		{
			get
			{
				return fixup.Value;
			}
			set
			{
				fixup.Value = value;
			}
		}

		public string FfmpegLocation
		{
			get
			{
				return ffmpegLocation.Value;
			}
			set
			{
				ffmpegLocation.Value = value;
			}
		}

		public MultiValue<string> Exec
		{
			get
			{
				return exec.Value;
			}
			set
			{
				exec.Value = value;
			}
		}

		public bool NoExec
		{
			get
			{
				return noExec.Value;
			}
			set
			{
				noExec.Value = value;
			}
		}

		public string ConvertSubs
		{
			get
			{
				return convertSubs.Value;
			}
			set
			{
				convertSubs.Value = value;
			}
		}

		public string ConvertThumbnails
		{
			get
			{
				return convertThumbnails.Value;
			}
			set
			{
				convertThumbnails.Value = value;
			}
		}

		public bool SplitChapters
		{
			get
			{
				return splitChapters.Value;
			}
			set
			{
				splitChapters.Value = value;
			}
		}

		public bool NoSplitChapters
		{
			get
			{
				return noSplitChapters.Value;
			}
			set
			{
				noSplitChapters.Value = value;
			}
		}

		public MultiValue<string> RemoveChapters
		{
			get
			{
				return removeChapters.Value;
			}
			set
			{
				removeChapters.Value = value;
			}
		}

		public bool NoRemoveChapters
		{
			get
			{
				return noRemoveChapters.Value;
			}
			set
			{
				noRemoveChapters.Value = value;
			}
		}

		public bool ForceKeyframesAtCuts
		{
			get
			{
				return forceKeyframesAtCuts.Value;
			}
			set
			{
				forceKeyframesAtCuts.Value = value;
			}
		}

		public bool NoForceKeyframesAtCuts
		{
			get
			{
				return noForceKeyframesAtCuts.Value;
			}
			set
			{
				noForceKeyframesAtCuts.Value = value;
			}
		}

		public MultiValue<string> UsePostprocessor
		{
			get
			{
				return usePostprocessor.Value;
			}
			set
			{
				usePostprocessor.Value = value;
			}
		}

		public string SponsorblockMark
		{
			get
			{
				return sponsorblockMark.Value;
			}
			set
			{
				sponsorblockMark.Value = value;
			}
		}

		public string SponsorblockRemove
		{
			get
			{
				return sponsorblockRemove.Value;
			}
			set
			{
				sponsorblockRemove.Value = value;
			}
		}

		public string SponsorblockChapterTitle
		{
			get
			{
				return sponsorblockChapterTitle.Value;
			}
			set
			{
				sponsorblockChapterTitle.Value = value;
			}
		}

		public bool NoSponsorblock
		{
			get
			{
				return noSponsorblock.Value;
			}
			set
			{
				noSponsorblock.Value = value;
			}
		}

		public string SponsorblockApi
		{
			get
			{
				return sponsorblockApi.Value;
			}
			set
			{
				sponsorblockApi.Value = value;
			}
		}

		public bool WriteSubs
		{
			get
			{
				return writeSubs.Value;
			}
			set
			{
				writeSubs.Value = value;
			}
		}

		public bool NoWriteSubs
		{
			get
			{
				return noWriteSubs.Value;
			}
			set
			{
				noWriteSubs.Value = value;
			}
		}

		public bool WriteAutoSubs
		{
			get
			{
				return writeAutoSubs.Value;
			}
			set
			{
				writeAutoSubs.Value = value;
			}
		}

		public bool NoWriteAutoSubs
		{
			get
			{
				return noWriteAutoSubs.Value;
			}
			set
			{
				noWriteAutoSubs.Value = value;
			}
		}

		public bool ListSubs
		{
			get
			{
				return listSubs.Value;
			}
			set
			{
				listSubs.Value = value;
			}
		}

		public string SubFormat
		{
			get
			{
				return subFormat.Value;
			}
			set
			{
				subFormat.Value = value;
			}
		}

		public string SubLangs
		{
			get
			{
				return subLangs.Value;
			}
			set
			{
				subLangs.Value = value;
			}
		}

		public bool WriteThumbnail
		{
			get
			{
				return writeThumbnail.Value;
			}
			set
			{
				writeThumbnail.Value = value;
			}
		}

		public bool NoWriteThumbnail
		{
			get
			{
				return noWriteThumbnail.Value;
			}
			set
			{
				noWriteThumbnail.Value = value;
			}
		}

		public bool WriteAllThumbnails
		{
			get
			{
				return writeAllThumbnails.Value;
			}
			set
			{
				writeAllThumbnails.Value = value;
			}
		}

		public bool ListThumbnails
		{
			get
			{
				return listThumbnails.Value;
			}
			set
			{
				listThumbnails.Value = value;
			}
		}

		public bool Quiet
		{
			get
			{
				return quiet.Value;
			}
			set
			{
				quiet.Value = value;
			}
		}

		public bool NoQuiet
		{
			get
			{
				return noQuiet.Value;
			}
			set
			{
				noQuiet.Value = value;
			}
		}

		public bool NoWarnings
		{
			get
			{
				return noWarnings.Value;
			}
			set
			{
				noWarnings.Value = value;
			}
		}

		public bool Simulate
		{
			get
			{
				return simulate.Value;
			}
			set
			{
				simulate.Value = value;
			}
		}

		public bool NoSimulate
		{
			get
			{
				return noSimulate.Value;
			}
			set
			{
				noSimulate.Value = value;
			}
		}

		public bool IgnoreNoFormatsError
		{
			get
			{
				return ignoreNoFormatsError.Value;
			}
			set
			{
				ignoreNoFormatsError.Value = value;
			}
		}

		public bool NoIgnoreNoFormatsError
		{
			get
			{
				return noIgnoreNoFormatsError.Value;
			}
			set
			{
				noIgnoreNoFormatsError.Value = value;
			}
		}

		public bool SkipDownload
		{
			get
			{
				return skipDownload.Value;
			}
			set
			{
				skipDownload.Value = value;
			}
		}

		public MultiValue<string> Print
		{
			get
			{
				return print.Value;
			}
			set
			{
				print.Value = value;
			}
		}

		public MultiValue<string> PrintToFile
		{
			get
			{
				return printToFile.Value;
			}
			set
			{
				printToFile.Value = value;
			}
		}

		public bool DumpJson
		{
			get
			{
				return dumpJson.Value;
			}
			set
			{
				dumpJson.Value = value;
			}
		}

		public bool DumpSingleJson
		{
			get
			{
				return dumpSingleJson.Value;
			}
			set
			{
				dumpSingleJson.Value = value;
			}
		}

		public bool ForceWriteArchive
		{
			get
			{
				return forceWriteArchive.Value;
			}
			set
			{
				forceWriteArchive.Value = value;
			}
		}

		public bool Newline
		{
			get
			{
				return newline.Value;
			}
			set
			{
				newline.Value = value;
			}
		}

		public bool NoProgress
		{
			get
			{
				return noProgress.Value;
			}
			set
			{
				noProgress.Value = value;
			}
		}

		public bool Progress
		{
			get
			{
				return progress.Value;
			}
			set
			{
				progress.Value = value;
			}
		}

		public bool ConsoleTitle
		{
			get
			{
				return consoleTitle.Value;
			}
			set
			{
				consoleTitle.Value = value;
			}
		}

		public string ProgressTemplate
		{
			get
			{
				return progressTemplate.Value;
			}
			set
			{
				progressTemplate.Value = value;
			}
		}

		public bool Verbose
		{
			get
			{
				return verbose.Value;
			}
			set
			{
				verbose.Value = value;
			}
		}

		public bool DumpPages
		{
			get
			{
				return dumpPages.Value;
			}
			set
			{
				dumpPages.Value = value;
			}
		}

		public bool WritePages
		{
			get
			{
				return writePages.Value;
			}
			set
			{
				writePages.Value = value;
			}
		}

		public bool PrintTraffic
		{
			get
			{
				return printTraffic.Value;
			}
			set
			{
				printTraffic.Value = value;
			}
		}

		public string Format
		{
			get
			{
				return format.Value;
			}
			set
			{
				format.Value = value;
			}
		}

		public string FormatSort
		{
			get
			{
				return formatSort.Value;
			}
			set
			{
				formatSort.Value = value;
			}
		}

		public bool FormatSortForce
		{
			get
			{
				return formatSortForce.Value;
			}
			set
			{
				formatSortForce.Value = value;
			}
		}

		public bool NoFormatSortForce
		{
			get
			{
				return noFormatSortForce.Value;
			}
			set
			{
				noFormatSortForce.Value = value;
			}
		}

		public bool VideoMultistreams
		{
			get
			{
				return videoMultistreams.Value;
			}
			set
			{
				videoMultistreams.Value = value;
			}
		}

		public bool NoVideoMultistreams
		{
			get
			{
				return noVideoMultistreams.Value;
			}
			set
			{
				noVideoMultistreams.Value = value;
			}
		}

		public bool AudioMultistreams
		{
			get
			{
				return audioMultistreams.Value;
			}
			set
			{
				audioMultistreams.Value = value;
			}
		}

		public bool NoAudioMultistreams
		{
			get
			{
				return noAudioMultistreams.Value;
			}
			set
			{
				noAudioMultistreams.Value = value;
			}
		}

		public bool PreferFreeFormats
		{
			get
			{
				return preferFreeFormats.Value;
			}
			set
			{
				preferFreeFormats.Value = value;
			}
		}

		public bool NoPreferFreeFormats
		{
			get
			{
				return noPreferFreeFormats.Value;
			}
			set
			{
				noPreferFreeFormats.Value = value;
			}
		}

		public bool CheckFormats
		{
			get
			{
				return checkFormats.Value;
			}
			set
			{
				checkFormats.Value = value;
			}
		}

		public bool CheckAllFormats
		{
			get
			{
				return checkAllFormats.Value;
			}
			set
			{
				checkAllFormats.Value = value;
			}
		}

		public bool NoCheckFormats
		{
			get
			{
				return noCheckFormats.Value;
			}
			set
			{
				noCheckFormats.Value = value;
			}
		}

		public bool ListFormats
		{
			get
			{
				return listFormats.Value;
			}
			set
			{
				listFormats.Value = value;
			}
		}

		public DownloadMergeFormat MergeOutputFormat
		{
			get
			{
				return mergeOutputFormat.Value;
			}
			set
			{
				mergeOutputFormat.Value = value;
			}
		}

		public string PlaylistItems
		{
			get
			{
				return playlistItems.Value;
			}
			set
			{
				playlistItems.Value = value;
			}
		}

		public string MinFilesize
		{
			get
			{
				return minFilesize.Value;
			}
			set
			{
				minFilesize.Value = value;
			}
		}

		public string MaxFilesize
		{
			get
			{
				return maxFilesize.Value;
			}
			set
			{
				maxFilesize.Value = value;
			}
		}

		public DateTime Date
		{
			get
			{
				return date.Value;
			}
			set
			{
				date.Value = value;
			}
		}

		public DateTime DateBefore
		{
			get
			{
				return dateBefore.Value;
			}
			set
			{
				dateBefore.Value = value;
			}
		}

		public DateTime DateAfter
		{
			get
			{
				return dateAfter.Value;
			}
			set
			{
				dateAfter.Value = value;
			}
		}

		public MultiValue<string> MatchFilters
		{
			get
			{
				return matchFilters.Value;
			}
			set
			{
				matchFilters.Value = value;
			}
		}

		public bool NoMatchFilters
		{
			get
			{
				return noMatchFilters.Value;
			}
			set
			{
				noMatchFilters.Value = value;
			}
		}

		public string BreakMatchFilters
		{
			get
			{
				return breakMatchFilters.Value;
			}
			set
			{
				breakMatchFilters.Value = value;
			}
		}

		public bool NoBreakMatchFilters
		{
			get
			{
				return noBreakMatchFilters.Value;
			}
			set
			{
				noBreakMatchFilters.Value = value;
			}
		}

		public bool NoPlaylist
		{
			get
			{
				return noPlaylist.Value;
			}
			set
			{
				noPlaylist.Value = value;
			}
		}

		public bool YesPlaylist
		{
			get
			{
				return yesPlaylist.Value;
			}
			set
			{
				yesPlaylist.Value = value;
			}
		}

		public byte? AgeLimit
		{
			get
			{
				return ageLimit.Value;
			}
			set
			{
				ageLimit.Value = value;
			}
		}

		public string DownloadArchive
		{
			get
			{
				return downloadArchive.Value;
			}
			set
			{
				downloadArchive.Value = value;
			}
		}

		public bool NoDownloadArchive
		{
			get
			{
				return noDownloadArchive.Value;
			}
			set
			{
				noDownloadArchive.Value = value;
			}
		}

		public int? MaxDownloads
		{
			get
			{
				return maxDownloads.Value;
			}
			set
			{
				maxDownloads.Value = value;
			}
		}

		public bool BreakOnExisting
		{
			get
			{
				return breakOnExisting.Value;
			}
			set
			{
				breakOnExisting.Value = value;
			}
		}

		public bool BreakPerInput
		{
			get
			{
				return breakPerInput.Value;
			}
			set
			{
				breakPerInput.Value = value;
			}
		}

		public bool NoBreakPerInput
		{
			get
			{
				return noBreakPerInput.Value;
			}
			set
			{
				noBreakPerInput.Value = value;
			}
		}

		public int? SkipPlaylistAfterErrors
		{
			get
			{
				return skipPlaylistAfterErrors.Value;
			}
			set
			{
				skipPlaylistAfterErrors.Value = value;
			}
		}

		public string Encoding
		{
			get
			{
				return encoding.Value;
			}
			set
			{
				encoding.Value = value;
			}
		}

		public bool LegacyServerConnect
		{
			get
			{
				return legacyServerConnect.Value;
			}
			set
			{
				legacyServerConnect.Value = value;
			}
		}

		public bool NoCheckCertificates
		{
			get
			{
				return noCheckCertificates.Value;
			}
			set
			{
				noCheckCertificates.Value = value;
			}
		}

		public bool PreferInsecure
		{
			get
			{
				return preferInsecure.Value;
			}
			set
			{
				preferInsecure.Value = value;
			}
		}

		public MultiValue<string> AddHeaders
		{
			get
			{
				return addHeaders.Value;
			}
			set
			{
				addHeaders.Value = value;
			}
		}

		public bool BidiWorkaround
		{
			get
			{
				return bidiWorkaround.Value;
			}
			set
			{
				bidiWorkaround.Value = value;
			}
		}

		public int? SleepRequests
		{
			get
			{
				return sleepRequests.Value;
			}
			set
			{
				sleepRequests.Value = value;
			}
		}

		public int? SleepInterval
		{
			get
			{
				return sleepInterval.Value;
			}
			set
			{
				sleepInterval.Value = value;
			}
		}

		public int? MaxSleepInterval
		{
			get
			{
				return maxSleepInterval.Value;
			}
			set
			{
				maxSleepInterval.Value = value;
			}
		}

		public int? SleepSubtitles
		{
			get
			{
				return sleepSubtitles.Value;
			}
			set
			{
				sleepSubtitles.Value = value;
			}
		}

		public void WriteConfigFile(string path)
		{
			File.WriteAllLines(path, GetOptionFlags());
		}

		public override string ToString()
		{
			return " " + string.Join(" ", GetOptionFlags());
		}

		public IEnumerable<string> GetOptionFlags()
		{
			return from value in GetKnownOptions().Concat(CustomOptions).SelectMany((IOption opt) => opt.ToStringCollection())
				where !string.IsNullOrWhiteSpace(value)
				select value;
		}

		internal IEnumerable<IOption> GetKnownOptions()
		{
			return (from p in GetType().GetRuntimeFields()
				where p.FieldType.IsGenericType && p.FieldType.GetInterfaces().Contains(typeof(IOption))
				select p.GetValue(this)).Cast<IOption>();
		}

		public OptionSet OverrideOptions(OptionSet overrideOptions, bool forceOverride = false)
		{
			OptionSet optionSet = (OptionSet)Clone();
			optionSet.CustomOptions = optionSet.CustomOptions.Concat(overrideOptions.CustomOptions).Distinct(Comparer).ToArray();
			IEnumerable<FieldInfo> enumerable = from p in overrideOptions.GetType().GetRuntimeFields()
				where p.FieldType.IsGenericType && p.FieldType.GetInterfaces().Contains(typeof(IOption))
				select p;
			foreach (FieldInfo item in enumerable)
			{
				IOption option = (IOption)item.GetValue(overrideOptions);
				if (forceOverride || option.IsSet)
				{
					optionSet.GetType().GetField(item.Name, BindingFlags.Instance | BindingFlags.NonPublic).SetValue(optionSet, option);
				}
			}
			return optionSet;
		}

		public static OptionSet FromString(IEnumerable<string> lines)
		{
			OptionSet optionSet = new OptionSet();
			IOption[] customOptions = (from option in GetOptions(lines, optionSet.GetKnownOptions())
				where option.IsCustom
				select option).ToArray();
			optionSet.CustomOptions = customOptions;
			return optionSet;
		}

		private static IEnumerable<IOption> GetOptions(IEnumerable<string> lines, IEnumerable<IOption> options)
		{
			IEnumerable<IOption> knownOptions = options.ToList();
			foreach (string rawLine in lines)
			{
				string line = rawLine.Trim();
				if (!line.StartsWith("#") && !string.IsNullOrWhiteSpace(line))
				{
					string[] segments = line.Split(new char[1] { ' ' });
					string flag = segments[0];
					IOption knownOption = knownOptions.FirstOrDefault((IOption o) => o.OptionStrings.Contains(flag));
					IOption option3;
					if (segments.Length <= 1)
					{
						IOption option2 = new Option<bool>(true, flag);
						option3 = option2;
					}
					else
					{
						IOption option2 = new Option<string>(true, flag);
						option3 = option2;
					}
					IOption customOption = option3;
					IOption option = knownOption ?? customOption;
					option.SetFromString(line);
					yield return option;
				}
			}
		}

		public static OptionSet LoadConfigFile(string path)
		{
			return FromString(File.ReadAllLines(path));
		}

		public object Clone()
		{
			return FromString(GetOptionFlags());
		}

		public void AddCustomOption<T>(string optionString, T value)
		{
			Option<T> option = new Option<T>(true, optionString);
			option.Value = value;
			CustomOptions = CustomOptions.Concat(new Option<T>[1] { option }).ToArray();
		}

		public void SetCustomOption<T>(string optionString, T value)
		{
			foreach (IOption item in CustomOptions.Where((IOption o) => o.OptionStrings.Contains(optionString)))
			{
				if (item is Option<T> option)
				{
					option.Value = value;
					continue;
				}
				throw new ArgumentException($"Value passed to option '{optionString}' has invalid type '{value.GetType()}'.");
			}
		}

		public void DeleteCustomOption(string optionString)
		{
			CustomOptions = CustomOptions.Where((IOption o) => !o.OptionStrings.Contains(optionString)).ToArray();
		}
	}
	internal static class Utils
	{
		internal static T OptionValueFromString<T>(string stringValue)
		{
			if (typeof(T) == typeof(bool))
			{
				return (T)(object)true;
			}
			if (typeof(T) == typeof(Enum))
			{
				string value = CultureInfo.InvariantCulture.TextInfo.ToTitleCase(stringValue);
				return (T)Enum.Parse(typeof(T), value);
			}
			if (typeof(T) == typeof(DateTime))
			{
				return (T)(object)DateTime.ParseExact(stringValue, "yyyyMMdd", null);
			}
			TypeConverter converter = TypeDescriptor.GetConverter(typeof(T));
			return (T)converter.ConvertFrom(stringValue);
		}

		internal static string OptionValueToString<T>(T value)
		{
			if (value is bool)
			{
				return string.Empty;
			}
			if (value is Enum)
			{
				return " \"" + value.ToString().ToLower() + "\"";
			}
			if (value is DateTime)
			{
				object obj = value;
				DateTime dateTime = (DateTime)((obj is DateTime) ? obj : null);
				if (true)
				{
					return " " + dateTime.ToString("yyyyMMdd");
				}
			}
			if (value is string)
			{
				return $" \"{value}\"";
			}
			T val = value;
			return " " + val;
		}
	}
}
namespace YoutubeDLSharp.Metadata
{
	public class ChapterData
	{
		[JsonProperty("start_time")]
		public float? StartTime { get; set; }

		[JsonProperty("end_time")]
		public float? EndTime { get; set; }

		[JsonProperty("title")]
		public string Title { get; set; }
	}
	public class CommentData
	{
		[JsonProperty("id")]
		public string ID { get; set; }

		[JsonProperty("author")]
		public string Author { get; set; }

		[JsonProperty("author_id")]
		public string AuthorID { get; set; }

		[JsonProperty("author_thumbnail")]
		public string AuthorThumbnail { get; set; }

		[JsonProperty("html")]
		public string Html { get; set; }

		[JsonProperty("text")]
		public string Text { get; set; }

		[JsonProperty("timestamp")]
		[JsonConverter(typeof(UnixTimestampConverter))]
		public DateTime Timestamp { get; set; }

		[JsonProperty("parent")]
		public string Parent { get; set; }

		[JsonProperty("like_count")]
		public int? LikeCount { get; set; }

		[JsonProperty("dislike_count")]
		public int? DislikeCount { get; set; }

		[JsonProperty("is_favorited")]
		public bool? IsFavorited { get; set; }

		[JsonProperty("author_is_uploader")]
		public bool? AuthorIsUploader { get; set; }
	}
	public class FormatData
	{
		[JsonProperty("url")]
		public string Url { get; set; }

		[JsonProperty("manifest_url")]
		public string ManifestUrl { get; set; }

		[JsonProperty("ext")]
		public string Extension { get; set; }

		[JsonProperty("format")]
		public string Format { get; set; }

		[JsonProperty("format_id")]
		public string FormatId { get; set; }

		[JsonProperty("format_note")]
		public string FormatNote { get; set; }

		[JsonProperty("width")]
		public int? Width { get; set; }

		[JsonProperty("height")]
		public int? Height { get; set; }

		[JsonProperty("resolution")]
		public string Resolution { get; set; }

		[JsonProperty("dynamic_range")]
		public string DynamicRange { get; set; }

		[JsonProperty("tbr")]
		public double? Bitrate { get; set; }