private static void SetupDownload(YoutubeDL ydl) { ydl.process = new Process { StartInfo = ydl.processStartInfo, EnableRaisingEvents = true }; ydl.stdOutputTokenSource = new CancellationTokenSource(); ydl.stdErrorTokenSource = new CancellationTokenSource(); ydl.process.Exited += (sender, args) => ydl.KillProcess(); // Note that synchronous calls are needed in order to process the output line by line. // Asynchronous output reading results in batches of output lines coming in all at once. // The following two threads convert synchronous output reads into asynchronous events. ThreadPool.QueueUserWorkItem(ydl.StandardOutput, ydl.stdOutputTokenSource.Token); ThreadPool.QueueUserWorkItem(ydl.StandardError, ydl.stdErrorTokenSource.Token); if (ydl.Info != null) { ydl.StandardOutputEvent += (sender, output) => ydl.Info.ParseOutput(sender, output.Trim()); ydl.StandardErrorEvent += (sender, output) => ydl.Info.ParseError(sender, output.Trim()); } ydl.process.Start(); }
private void UiDownloadButton_Click(object sender, EventArgs e) { string url = uiUrlTextBox.Text; if (String.IsNullOrWhiteSpace(url)) { MessageBox.Show("Please enter a video URL", "No URL Entered", MessageBoxButtons.OK, MessageBoxIcon.Error); uiUrlTextBox.Focus(); return; } uiDownloadButton.Enabled = false; string videoLocation = Path.Combine(Constants.VideoCacheLocation, "temp_video_download.mp4"); this.InvokeIfRequired(() => uiStatusLabel.Text = "Starting download... Please wait as this can take a few seconds to start."); try { youtubeDl = new YoutubeDL { YoutubeDlPath = "youtube-dl.exe", VideoUrl = url, }; youtubeDl.Options.FilesystemOptions.Output = videoLocation; youtubeDl.Options.GeneralOptions.IgnoreErrors = true; youtubeDl.PrepareDownload(); youtubeDl.Info.PropertyChanged += (o, args) => { DownloadInfo info = (DownloadInfo)o; string status = info.Status; this.InvokeIfRequired(() => uiDownloadProgressBar.Value = info.VideoProgress); this.InvokeIfRequired(() => uiStatusLabel.Text = $"Status: {status} Video size: {info.VideoSize} Download speed: {info.DownloadRate} ETA: {info.Eta}"); if (status == "Error") { this.InvokeIfRequired(() => uiStatusLabel.Text = "Error downloading video."); this.InvokeIfRequired(() => uiDownloadButton.Enabled = true); youtubeDl.KillProcess(); } if (status == "Done" || info.VideoProgress == 100) { this.InvokeIfRequired(() => uiDownloadButton.Enabled = true); this.InvokeIfRequired(() => uiStatusLabel.Text = "Status: Download complete. Processing video."); if (!hasFired) //this can fire multiple times, so stop it from happening with flag. Need to reset after download completed! { hasFired = true; youtubeDl.KillProcess(); VideoDownloadComplete?.Invoke(this, EventArgs.Empty); this.InvokeIfRequired(() => Close()); } } }; youtubeDl.DownloadAsync(); } catch (ArgumentOutOfRangeException) { MessageBox.Show("An error has occured attempting to download this video.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Warning); } }