diff --git a/Ytdlp.NET.slnx b/Ytdlp.NET.slnx index 2e25347..0628478 100644 --- a/Ytdlp.NET.slnx +++ b/Ytdlp.NET.slnx @@ -4,11 +4,9 @@ - - diff --git a/archives/feature/Ytdlp.NET.vNext.Console/Program.cs b/archives/feature/Ytdlp.NET.vNext.Console/Program.cs deleted file mode 100644 index 8ba8151..0000000 --- a/archives/feature/Ytdlp.NET.vNext.Console/Program.cs +++ /dev/null @@ -1,365 +0,0 @@ -using ManuHub.Ytdlp; -using ManuHub.Ytdlp.Core; - -class Program -{ - static async Task Main() - { - Console.WriteLine("==== Ytdlp Interactive Console App ===="); - - // Ask for yt-dlp executable path - Console.Write("Enter path to yt-dlp executable (or leave empty to use default): "); - string? ytDlpPath = Console.ReadLine(); - ytDlpPath = string.IsNullOrWhiteSpace(ytDlpPath) ? "tools\\yt-dlp.exe" : ytDlpPath.Trim(); - - // Optional FFmpeg path for downloads - Console.Write("Enter path to ffmpeg executable (for downloads) or leave empty: "); - string? ffmpegPath = Console.ReadLine(); - ffmpegPath = string.IsNullOrWhiteSpace(ffmpegPath) ? "tools" : ffmpegPath.Trim(); - - var root = Ytdlp.Create(ytDlpPath); - - while (true) - { - Console.WriteLine("\nSelect mode:"); - Console.WriteLine("1) General (version / update)"); - Console.WriteLine("2) Probe (formats / metadata)"); - Console.WriteLine("3) Download (single or batch)"); - Console.WriteLine("0) Exit"); - Console.Write("Choice: "); - string? choice = Console.ReadLine(); - - if (choice == "0") break; - - try - { - switch (choice) - { - case "1": - await GeneralModeAsync(root); - break; - case "2": - await ProbeModeAsync(root); - break; - case "3": - await DownloadModeAsync(root, ffmpegPath); - break; - default: - Console.WriteLine("Invalid choice."); - break; - } - } - catch (Exception ex) - { - Console.WriteLine($"Error: {ex.Message}"); - } - } - - Console.WriteLine("Goodbye!"); - } - - // ================= General ================= - static async Task GeneralModeAsync(YtdlpRootBuilder root) - { - var general = root.General(); - Console.WriteLine("\nGeneral Mode:"); - Console.WriteLine("1) Get yt-dlp version"); - Console.WriteLine("2) Update yt-dlp"); - Console.Write("Choice: "); - string? gChoice = Console.ReadLine(); - - switch (gChoice) - { - case "1": - string version = await general.VersionAsync(); - Console.WriteLine($"yt-dlp version: {version}"); - break; - case "2": - Console.Write("Use nightly channel? (y/n): "); - bool nightly = (Console.ReadLine()?.Trim().ToLower() == "y"); - string updatedVersion = await general.UpdateAsync( - nightly ? UpdateChannel.Nightly : UpdateChannel.Stable); - Console.WriteLine($"yt-dlp updated to: {updatedVersion}"); - break; - default: - Console.WriteLine("Invalid choice."); - break; - } - } - - // ================= Probe ================= - static async Task ProbeModeAsync(YtdlpRootBuilder root) - { - Console.Write("Enter video URL: "); - string? url = Console.ReadLine(); - if (string.IsNullOrWhiteSpace(url)) return; - - var probe = root.Probe(url.Trim()); - - Console.WriteLine("\nProbe Mode:"); - Console.WriteLine("1) List available formats"); - Console.WriteLine("2) Get detailed formats (JSON)"); - Console.WriteLine("3) Get video metadata"); - Console.WriteLine("4) Get best audio format"); - Console.WriteLine("5) Get best video format"); - Console.WriteLine("6) Get file size approx"); - Console.Write("Choice: "); - string? pChoice = Console.ReadLine(); - - switch (pChoice) - { - case "1": - var formats = await probe.GetAvailableFormatsAsync(); - Console.WriteLine("Available formats:"); - foreach (var f in formats) - Console.WriteLine($"- {f.Id} | {f.Extension} | {f.Resolution} | {f.Note}"); - break; - - case "2": - var detailed = await probe.GetFormatsDetailedAsync(); - Console.WriteLine("Detailed formats:"); - foreach (var f in detailed) - Console.WriteLine($"- {f.Id} | {f.Extension} | {f.Resolution} | {f.VideoCodec}/{f.AudioCodec} | {f.FileSizeApprox} bytes"); - break; - - case "3": - var metadata = await probe.GetVideoMetadataAsync(); - if (metadata != null) - { - Console.WriteLine($"Title: {metadata.Title}"); - Console.WriteLine($"Uploader: {metadata.Uploader}"); - Console.WriteLine($"Duration: {metadata.Duration} sec"); - Console.WriteLine($"View count: {metadata.ViewCount}"); - } - else - Console.WriteLine("Failed to fetch metadata."); - break; - - case "4": - var bestAudioId = await probe.GetBestAudioFormatIdAsync(); - Console.WriteLine($"BestAudioId: {bestAudioId}"); - break; - - case "5": - var bestVideoId = await probe.GetBestVideoFormatIdAsync(); - Console.WriteLine($"BestVideoId: {bestVideoId}"); - break; - - case "6": - var fileSize = await probe.GetFileSizeAsync(); - Console.WriteLine($"FileSize: {fileSize}"); - break; - - default: - Console.WriteLine("Invalid choice."); - break; - } - } - - - // ================= Download ================= - static async Task DownloadModeAsync(YtdlpRootBuilder root, string? ffmpegPath) - { - Console.WriteLine("Enter video URLs (comma-separated for batch, or single URL): "); - string? input = Console.ReadLine(); - if (string.IsNullOrWhiteSpace(input)) return; - - var urls = input.Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries).ToList(); - bool isBatch = urls.Count > 1; - - Console.WriteLine("Choose format:"); - Console.WriteLine("1) bestvideo+bestaudio (default)"); - Console.WriteLine("2) bestaudio only"); - Console.WriteLine("3) Custom (yt-dlp format selector)"); - Console.Write("Choice: "); - string? fChoice = Console.ReadLine(); - - string format = fChoice switch - { - "2" => "bestaudio", - "3" => AskCustomFormat(), - _ => "bestvideo+bestaudio" - }; - - var downloadBuilder = root.Download() - .WithFormat(format) - .WithOutputFolder("Downloads"); - - if (!string.IsNullOrWhiteSpace(ffmpegPath)) - downloadBuilder.WithFFmpegLocation(ffmpegPath); - - if (isBatch) - { - Console.WriteLine($"\nStarting batch download for {urls.Count} videos...\n"); - - var command = downloadBuilder.Build(); - - // Subscribe to events - command.OnProgressDownload += (s, e) => - { - Console.WriteLine($"Progress: {e.Percent:F1}% - {e.Speed} - ETA: {e.ETA}"); - }; - command.OnCompleteDownload += (s, file) => - { - Console.WriteLine($"Download completed: {file}"); - }; - command.OnErrorMessage += (s, msg) => - { - Console.WriteLine($"Error: {msg}"); - }; - - var results = await command.ExecuteBatchAsync(urls, maxConcurrency: 2); - - foreach (var r in results) - { - if (r.Error != null) - Console.WriteLine($"Failed: {r.Url} - {r.Error.Message}"); - else - Console.WriteLine($"Success: {r.Url}"); - } - } - else - { - string url = urls[0]; - var command = downloadBuilder.Build(); - - // Subscribe to events - command.OnProgressDownload += (s, e) => - { - Console.WriteLine($"Progress: {e.Percent:F1}% - {e.Speed} - ETA: {e.ETA}"); - }; - command.OnCompleteDownload += (s, file) => - { - Console.WriteLine($"Download completed: {file}"); - }; - command.OnErrorMessage += (s, msg) => - { - Console.WriteLine($"Error: {msg}"); - }; - - Console.WriteLine($"\nStarting download: {url}\n"); - await command.ExecuteAsync(url); - } - } - - static string AskCustomFormat() - { - Console.Write("Enter yt-dlp format selector (e.g., 'bestvideo[height<=1080]+bestaudio'): "); - string? custom = Console.ReadLine(); - return string.IsNullOrWhiteSpace(custom) ? "bestvideo+bestaudio" : custom.Trim(); - } -} - -//internal class Program -//{ - - -// static async Task Main(string[] args) -// { -// Replace with your local yt-dlp path if needed -// string ytDlpPath = "tools\\yt-dlp.exe"; - -// string videoUrl = "https://www.youtube.com/watch?v=dQw4w9WgXcQ"; - -// var ytdlp = Ytdlp.Create(ytDlpPath); - -// Console.WriteLine("=== GENERAL MODE ==="); -// await TestGeneralAsync(ytdlp); - -// Console.WriteLine("\n=== PROBE MODE ==="); -// await TestProbeAsync(ytdlp, videoUrl); - -// Console.WriteLine("\n=== DOWNLOAD MODE ==="); -// await TestDownloadAsync(ytdlp, videoUrl); -// } - -// static async Task TestGeneralAsync(YtdlpRootBuilder root) -// { -// try -// { -// var general = root.General(); - -// string version = await general.VersionAsync(); -// Console.WriteLine($"yt-dlp Version: {version}"); - -// Optional: update yt-dlp (will actually try to update) -// string updatedVersion = await general.UpdateAsync(); -// Console.WriteLine($"yt-dlp Updated Version: {updatedVersion}"); -// } -// catch (Exception ex) -// { -// Console.WriteLine($"General mode error: {ex.Message}"); -// } -// } - -// static async Task TestProbeAsync(YtdlpRootBuilder root, string url) -// { -// try -// { -// var probe = root.Probe(url); - -// Get all formats detailed -// var formats = await probe.GetFormatsDetailedAsync(); -// Console.WriteLine("Available formats:"); -// foreach (var f in formats) -// { -// Console.WriteLine($" {f.Id} | {f.Extension} | {f.Resolution} | {f.VideoCodec}/{f.AudioCodec}"); -// } - -// Get best audio and video format IDs -// string? bestAudio = await probe.GetBestAudioFormatIdAsync(); -// string? bestVideo = await probe.GetBestVideoFormatIdAsync(); - -// Console.WriteLine($"Best audio format ID: {bestAudio}"); -// Console.WriteLine($"Best video format ID: {bestVideo}"); - -// Get file size -// string? fileSize = await probe.GetFileSizeAsync(); -// Console.WriteLine($"Approx file size: {fileSize ?? "unknown"} bytes"); - -// Get metadata -// var metadata = await probe.GetVideoMetadataAsync(); -// Console.WriteLine($"Video title: {metadata?.Title}"); -// Console.WriteLine($"Uploader: {metadata?.Uploader}"); -// } -// catch (Exception ex) -// { -// Console.WriteLine($"Probe mode error: {ex.Message}"); -// } -// } - -// static async Task TestDownloadAsync(YtdlpRootBuilder root, string url) -// { -// try -// { -// var download = root.Download() -// .WithFormat("bestvideo+bestaudio") -// .WithFFmpegLocation(toolsPath) -// .WithOutputFolder("Downloads"); - -// var command = download.Build(); - -// Subscribe to events -// command.OnProgressDownload += (s, e) => -// { -// Console.WriteLine($"Progress: {e.Percent:F1}% - {e.Speed} - ETA: {e.ETA}"); -// }; -// command.OnCompleteDownload += (s, file) => -// { -// Console.WriteLine($"Download completed: {file}"); -// }; -// command.OnErrorMessage += (s, msg) => -// { -// Console.WriteLine($"Error: {msg}"); -// }; - -// await command.ExecuteAsync(url); -// } -// catch (Exception ex) -// { -// Console.WriteLine($"Download mode error: {ex.Message}"); -// } -// } -//} - - diff --git a/archives/feature/Ytdlp.NET.vNext.Console/Ytdlp.NET.vNext.Console.csproj b/archives/feature/Ytdlp.NET.vNext.Console/Ytdlp.NET.vNext.Console.csproj deleted file mode 100644 index 26ae3bd..0000000 --- a/archives/feature/Ytdlp.NET.vNext.Console/Ytdlp.NET.vNext.Console.csproj +++ /dev/null @@ -1,21 +0,0 @@ - - - - Exe - net10.0 - enable - enable - - - - - - - - - - - - - - diff --git a/archives/legacy/Ytdlp.Wrapper.Console/Program.cs b/archives/legacy/Ytdlp.Wrapper.Console/Program.cs deleted file mode 100644 index 780d184..0000000 --- a/archives/legacy/Ytdlp.Wrapper.Console/Program.cs +++ /dev/null @@ -1,112 +0,0 @@ -using YtDlpWrapper; - -Console.Clear(); - -string outputDirectory = @"C:\Downloads"; - -// Initialize the YtDlpEngine -//var ytDlpEngine = new YtDlpEngine(); - -// Subscribe to the download progress event -//ytDlpEngine.OnProgressMessage += (sender, e) => Console.WriteLine($"{e}"); - -// Subscribe to the download progress event -//ytDlpEngine.OnErrorMessage += (sender, e) => Console.WriteLine($"{e}"); - -// Subscribe to the download progress event -//ytDlpEngine.OnProgressDownload += (sender, e) => Console.WriteLine($"Downloading: {e.Percent}% of {e.Size} ETA:{e.ETA}"); - -// Input video URL and output directory -//Console.Write("Enter the video URL: "); -//var videoUrl = Console.ReadLine(); - -//if (string.IsNullOrEmpty(videoUrl)) -//{ -// Console.WriteLine("Invalid URL"); -// return; -//} - -// Start downloading the video -//var videoInfo = await ytDlpEngine.GetVideoInfo(videoUrl); -//Console.WriteLine(videoInfos); - -// Get available formats -//var formats = await ytDlpEngine.GetAvailableFormatsAsync(videoUrl); -//foreach (var format in formats) -//{ -// Console.WriteLine($"{format.ID} - {format.Type} -{format.Resolution} - {format.AdditionalInfo}"); -//} - -//Start downloading the video -//await ytDlpEngine.DownloadVideoAsync(videoUrl, outputDirectory, VideoQuality.Worst); - -// Start downloading the playlist -// await ytDlpEngine.DownloadPlaylistAsync(videoUrl, outputDirectory); - -// Start downloading the audio -//await ytDlpEngine.DownloadAudioAsync(videoUrl, outputDirectory, AudioQuality.WorstAudio); - -// Start downloading the subtitiles // not works -//await ytDlpEngine.DownloadSubtitlesAsync(videoUrl, outputDirectory); - -// Start downloading the thumbnail -// await ytDlpEngine.DownloadThumbnailAsync(videoUrl, outputDirectory); - -// Start downloading the all -//await ytDlpEngine.DownloadAllAsync(videoUrl, outputDirectory); - -// Start downloading the all playlist -//await ytDlpEngine.DownloadAllPlaylistAsync(videoUrl, outputDirectory); - -// Get thumbnail to app folder -//var thumnail = await ytDlpEngine.GetThumbnailAsync(videoUrl); -//Console.WriteLine(thumnail); - -var ytdlp = new Ytdlp($"{AppContext.BaseDirectory}\\Tools\\yt-dlp.exe"); - -// Subscribe to the detailed progress event -//ytdlp.OnDetailedProgress += progress => -//{ -// Console.WriteLine($"Progress: {progress.Percentage}%"); -// Console.WriteLine($"Downloaded: {progress.DownloadedSize}"); -// Console.WriteLine($"Speed: {progress.Speed}"); -// Console.WriteLine($"Time Left: {progress.TimeLeft}"); -//}; - -// Subscribe to the error event -ytdlp.OnProgressMessage += (sender, e) => Console.WriteLine($"{e}"); - -// Subscribe to the download progress event -ytdlp.OnErrorMessage += (sender, e) => Console.WriteLine($"{e}"); - -// Subscribe to the download progress event -ytdlp.OnProgressDownload += (sender, e) => Console.WriteLine($"Downloading: {e.Percent}% of {e.Size} ETA:{e.ETA}"); - - -//ytdlp.OnProgressDownload += (sender, e) => -//{ -// Console.WriteLine($"{e.Percent} {e.Size} {e.Speed} {e.ETA} {e.Fragments}"); -//}; - -// Configure the command (e.g., set output template, show progress) - -//var fortmats = await ytdlp.GetAvailableFormatsAsync(videoUrl); - -//foreach (var format in fortmats) -//{ -// Console.WriteLine($"{format.ID} {format.Type} {format.Resolution} {format.FPS}"); -//} - -// Input video URL and output directory -Console.Write("Enter the video URL: "); -var videoUrl = Console.ReadLine(); - -if (string.IsNullOrEmpty(videoUrl)) -{ - Console.WriteLine("Invalid URL"); - return; -} - -await ytdlp.SetOutputFolder(outputDirectory) - //.Version() - .ExecuteAsync(videoUrl); diff --git a/archives/legacy/Ytdlp.Wrapper.Console/Ytdlp.Wrapper.Console.csproj b/archives/legacy/Ytdlp.Wrapper.Console/Ytdlp.Wrapper.Console.csproj deleted file mode 100644 index c7ec028..0000000 --- a/archives/legacy/Ytdlp.Wrapper.Console/Ytdlp.Wrapper.Console.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - Exe - net10.0 - enable - enable - - - - - - - diff --git a/src/Ytdlp.NET.Console/Ytdlp.NET.Console.csproj b/src/Ytdlp.NET.Console/Ytdlp.NET.Console.csproj index 34d779e..de26ece 100644 --- a/src/Ytdlp.NET.Console/Ytdlp.NET.Console.csproj +++ b/src/Ytdlp.NET.Console/Ytdlp.NET.Console.csproj @@ -9,10 +9,10 @@ - - - - + + + + diff --git a/src/Ytdlp.NET/Ytdlp.cs b/src/Ytdlp.NET/Ytdlp.cs index 6368511..b861d77 100644 --- a/src/Ytdlp.NET/Ytdlp.cs +++ b/src/Ytdlp.NET/Ytdlp.cs @@ -398,6 +398,65 @@ private List BuildArguments(string url) return args; } + /// + /// Builds the command-line arguments for a probe operation (metadata extraction) for a given URL based on the current configuration. + /// + /// + /// + /// + private List BuildProbeArguments(string url, IEnumerable probeFlags) + { + var args = new List(); + + // Authentication (Needed for protected or members-only videos during probe/metadata extraction) + if (_auth is not null) + { + args.Add("--username"); + args.Add(_auth.Username); + args.Add("--password"); + args.Add("-"); // tells yt-dlp to read from stdin + } + + // Adobe Pass authentication + if (_adobePass is not null) + { + args.Add("--ap-mso"); + args.Add(_adobePass.Mso); + args.Add("--ap-username"); + args.Add(_adobePass.Username); + args.Add("--ap-password"); + args.Add("-"); + } + + // Custom user flags (Safe to include for probes) + if (_flags.Length > 0) + args.AddRange(_flags); + + // Custom user options (Safe to include for probes, e.g., proxies, cookies, user-agent) + if (_options.Length > 0) + { + foreach (var kv in _options) + { + args.Add(kv.Key); + if (kv.Value != null) + args.Add(kv.Value); + } + } + + // Global utility settings + if (_cookiesFile is not null) { args.Add("--cookies"); args.Add(_cookiesFile); } + if (_cookiesFromBrowser is not null) { args.Add("--cookies-from-browser"); args.Add(_cookiesFromBrowser); } + if (_proxy is not null) { args.Add("--proxy"); args.Add(_proxy); } + + // Append the specific probe flags requested by the caller (e.g. --dump-single-json, -F, --list-subs) + args.AddRange(probeFlags); + + // URL last + args.Add(url); + + return args; + } + private static string Quote(string? value) { if (string.IsNullOrWhiteSpace(value)) return "\"\""; diff --git a/src/Ytdlp.NET/Ytdlp/Ytdlp.Execute.cs b/src/Ytdlp.NET/Ytdlp/Ytdlp.Execute.cs index 90637a7..a3c43e3 100644 --- a/src/Ytdlp.NET/Ytdlp/Ytdlp.Execute.cs +++ b/src/Ytdlp.NET/Ytdlp/Ytdlp.Execute.cs @@ -41,10 +41,10 @@ public async Task ExecuteRawAsync(string arguments, runner.ErrorReceived += OnErrorMessageHandler; runner.CommandCompleted += OnCommandCompletedHandler; - bool captureFullOutput = (onLineReceived == null); - try { + bool captureFullOutput = (onLineReceived == null); + return await runner.ExecuteAsync( arguments: arguments, // Now we know it's "cleaner" auth: _auth, diff --git a/src/Ytdlp.NET/Ytdlp/Ytdlp.Probe.cs b/src/Ytdlp.NET/Ytdlp/Ytdlp.Probe.cs index 9d8ea79..d258cb9 100644 --- a/src/Ytdlp.NET/Ytdlp/Ytdlp.Probe.cs +++ b/src/Ytdlp.NET/Ytdlp/Ytdlp.Probe.cs @@ -1,5 +1,4 @@ using System.Globalization; -using System.Text; using System.Text.Json; using System.Text.Json.Serialization; using System.Text.RegularExpressions; @@ -223,7 +222,9 @@ public async Task> GetFormatsAsync(string url, CancellationToken ct if (string.IsNullOrWhiteSpace(url)) throw new ArgumentException("Video URL cannot be empty.", nameof(url)); - var output = await RunProbeAsync($"-F {Quote(url)}", ct, tuneProcess); + var probeFlags = new[] { "-F" }; + var output = await RunProbeWithOptionsAsync(url, probeFlags, ct, tuneProcess); + return string.IsNullOrWhiteSpace(output) ? new List() : ParseFormats(output); @@ -260,11 +261,17 @@ public async Task> GetFormatsAsync(string url, CancellationToken ct "%(description).500s" }; - var arguments = - $"--print \"{string.Join(separator, fields)}\" " + - $"--skip-download --no-playlist --quiet {Quote(url)}"; + var printFormat = string.Join(separator, fields); - var output = await RunProbeAsync(arguments, ct, tuneProcess); + var probeFlags = new[] + { + "--print", printFormat, + "--skip-download", + "--no-playlist", + "--quiet" + }; + + var output = await RunProbeWithOptionsAsync(url, probeFlags, ct, tuneProcess); if (string.IsNullOrWhiteSpace(output)) return null; var parts = output.Trim().Split(separator); @@ -320,11 +327,16 @@ public async Task> GetFormatsAsync(string url, CancellationToken ct { var separator = $"|||{Guid.NewGuid():N}|||"; var printFormat = string.Join(separator, fieldList.Select(f => $"%({f})s")); - var arguments = - $"--print \"{printFormat}\" " + - $"--skip-download --no-playlist --quiet {Quote(url)}"; - var rawOutput = await RunProbeAsync(arguments, ct, tuneProcess); + var probeFlags = new[] + { + "--print", printFormat, + "--skip-download", + "--no-playlist", + "--quiet" + }; + + var rawOutput = await RunProbeWithOptionsAsync(url, probeFlags, ct, tuneProcess); if (string.IsNullOrWhiteSpace(rawOutput)) return null; var parts = rawOutput.Trim().Split(separator); @@ -443,6 +455,8 @@ public async Task> GetSubtitlesAsync(string url, Cancellatio var result = await runner.ExecuteAsync( arguments, + auth: _auth, + adobePass: _adobePass, onLineReceived: null, ct: ct, tuneProcess: tuneProcess, @@ -475,15 +489,33 @@ public async Task> GetSubtitlesAsync(string url, Cancellatio if (string.IsNullOrWhiteSpace(url)) throw new ArgumentException("URL cannot be empty.", nameof(url)); - var arguments = - "--dump-single-json " + - "--simulate " + - "--skip-download " + - (flat ? "--flat-playlist " : "") + - "--lazy-playlist " + - "--quiet " + - "--no-warnings " + - $"{Quote(url)}"; + var probeFlags = new List + { + "--dump-single-json", + "--simulate", + "--skip-download" + }; + + if (flat) + { + probeFlags.Add("--flat-playlist"); + probeFlags.Add("--lazy-playlist"); + } + + probeFlags.Add("--quiet"); + probeFlags.Add("--no-warnings"); + + return await RunProbeWithOptionsAsync(url, probeFlags, ct, tuneProcess); + } + + private async Task RunProbeWithOptionsAsync(string url, IEnumerable probeFlags, CancellationToken ct, bool tuneProcess) + { + if (string.IsNullOrWhiteSpace(url)) + throw new ArgumentException("URL cannot be empty.", nameof(url)); + + var argsList = BuildProbeArguments(url, probeFlags); + + var arguments = string.Join(" ", argsList.Select(EscapeArgument)); return await RunProbeAsync(arguments, ct, tuneProcess); } @@ -523,7 +555,7 @@ private List ParseSubtitles(string output) var subtitles = new List(); var lines = output.Split(new[] { "\r\n", "\r", "\n" }, StringSplitOptions.RemoveEmptyEntries); - var rowRegex = new System.Text.RegularExpressions.Regex(@"^(\S+)\s+(.+?)\s{2,}([a-z0-9, ]+)$"); + var rowRegex = new Regex(@"^(\S+)\s+(.+?)\s{2,}([a-z0-9, ]+)$"); bool foundStartPoint = false; bool foundHeader = false;