public static void DownloadAudio(IEnumerable <VideoInfo> videoInfos) { try { VideoInfo video = videoInfos.Where(info => info.CanExtractAudio).OrderByDescending(info => info.AudioBitrate).First(); if (video.RequiresDecryption) { DownloadUrlResolver.DecryptDownloadUrl(video); } string path = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + "\\YouTubeAudios"; if (!Directory.Exists(path)) { Directory.CreateDirectory(path); } var savePath = Path.Combine(path, YouTubeHelpers.RemoveIllegalPathCharacters(video.Title) + video.AudioExtension); var audioDownloader = new AudioDownloader(video, savePath); audioDownloader.DownloadProgressChanged += (sender, args) => Console.WriteLine(args.ProgressPercentage * 0.85); audioDownloader.AudioExtractionProgressChanged += (sender, args) => Console.WriteLine(85 + args.ProgressPercentage * 0.15); audioDownloader.Execute(); } catch (Exception ex) { throw ex; } }
public IUrlInfo GetInfo(string url) { if (url == null) { throw new ArgumentNullException(nameof(url)); } url = url.Trim(); if (!new Regex(YoutuberRegexp).Match(url).Success) { throw new Exception("Link is not valid for youtube video"); } url = UrlFormatter.RemoveParametersFromUrl(url); IEnumerable <VideoInfo> videoInfos = DownloadUrlResolver.GetDownloadUrls(url); VideoInfo videoInfo = videoInfos.First(info => info.VideoType == VideoType.Mp4 && info.Resolution == 360); Headers headers = HttpRequester.GetHeaders(videoInfo.DownloadUrl); var artistAndSong = GetArtistAndSongName(videoInfo.Title); return(new UrlInfo() { Artist = artistAndSong.Artist, Song = artistAndSong.Song, ContentLength = headers.ContentLenght, VideoId = UrlFormatter.GetYoutubeVideoIdentifier(url), }); }
private void Button_Click(object sender, RoutedEventArgs e) { ProgressBarLoad.Minimum = 0; ProgressBarLoad.Maximum = 100; IEnumerable <VideoInfo> videos = DownloadUrlResolver.GetDownloadUrls(UriTextBox.Text); VideoInfo video = videos.First(p => p.VideoType == VideoType.Mp4 && p.Resolution == Convert.ToInt32(ResolutionCombobox.Text)); if (video.RequiresDecryption) { DownloadUrlResolver.DecryptDownloadUrl(video); } VideoDownloader downloader = new VideoDownloader(video, System.IO.Path.Combine(Environment.CurrentDirectory)); downloader.DownloadProgressChanged += DownloadProgressChanged; Thread thread = new Thread(() => { downloader.Execute(); }) { IsBackground = true }; thread.Start(); }
//Returns VideoInfo List (Shared by both audio and video models) public static IEnumerable <VideoInfo> GetVideoInfos(YoutubeModel model) { //Get the available video formats. IEnumerable <VideoInfo> videoInfos = DownloadUrlResolver.GetDownloadUrls(model.Link); return(videoInfos); }
internal static void DownloadVideo(IEnumerable <VideoInfo> videoInfos) { /* * Select the first .mp4 video with 360p resolution */ VideoInfo video = videoInfos .First(info => info.VideoType == VideoType.Mp4 && info.Resolution == 360); /* * If the video has a decrypted signature, decipher it */ if (video.RequiresDecryption) { DownloadUrlResolver.DecryptDownloadUrl(video); } /* * Create the video downloader. * The first argument is the video to download. * The second argument is the path to save the video file. */ var videoDownloader = new VideoDownloader(video, Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), RemoveIllegalPathCharacters(video.Title) + video.VideoExtension)); // Register the ProgressChanged event and print the current progress videoDownloader.DownloadProgressChanged += (sender, args) => Console.WriteLine(args.ProgressPercentage); /* * Execute the video downloader. * For GUI applications note, that this method runs synchronously. */ videoDownloader.Execute(); }
/* * private static void DownloadAudio(IEnumerable<VideoInfo> videoInfos, string dir, ProgressBar progress) * { * * p = progress; * * * VideoInfo video = videoInfos.First(info => info.VideoType == VideoType.Mp4); // youtube gives always mp4 * if (video.RequiresDecryption) * { * DownloadUrlResolver.DecryptDownloadUrl(video); * } * * string tempF =dir + "\\Downloaded"; * if (!Directory.Exists(tempF)) Directory.CreateDirectory(tempF); * * var videoDownloader = new VideoDownloader(video, Path.Combine(dir+ "/Downloaded", video.Title + video.AudioExtension)); * videoDownloader.DownloadStarted += progress_zero; * videoDownloader.DownloadProgressChanged += pregress_changed; * videoDownloader.DownloadFinished += progress_full; * videoDownloader.Execute(); * * // Convert mp4 to mp3 * // ------------------- * var inputFile = new MediaFile { Filename = Path.Combine(dir + "/Downloaded", video.Title + video.AudioExtension) }; * var outputFile = new MediaFile { Filename = Path.Combine(dir + "/Downloaded", video.Title + ".mp3") }; * progress.Value = 0; * using (var engine = new Engine()) * { * engine.GetMetadata(inputFile); * progress.Value = 70; * engine.Convert(inputFile, outputFile); * progress.Value = 100; * } * File.Delete(Path.Combine(dir + "/Downloaded", video.Title + video.AudioExtension)); * * } * * private static void progress_full(object sender, EventArgs e) * { * p.Value = 100; * } * * private static void pregress_changed(object sender, ProgressEventArgs e) * { * if(p.Value<100) p.Value ++; * } * * private static void progress_zero(object sender, EventArgs e) * { * p.Value = 0; * } */ private void a_button_Click(object sender, EventArgs e) { if (URL.Text.Equals("") || URL.Text.Equals("Paste URL here")) { MessageBox.Show("No URL here, man"); } else { Clipboard.Clear(); string[] targets = URL.Lines; string rejected = ""; foreach (string target in targets) { if (!target.Equals("") && (target.Contains("youtube") || target.Contains("youtu.be")) && target.Contains("http")) { IEnumerable <VideoInfo> videoInfos = DownloadUrlResolver.GetDownloadUrls(target, false); VideoInfo video = videoInfos.First(info => info.VideoType == VideoType.Mp4); // youtube gives always mp4 YoutubeVideo add = new YoutubeVideo(video.Title, target); URLS.Items.Add(add); } else { rejected += target + "\n"; } } URL.Text = rejected; } }
static void youtubeDownloader() { string link = "https://www.youtube.com/watch?v=0YOVPIQuvAw"; IEnumerable <VideoInfo> videoInfos = DownloadUrlResolver.GetDownloadUrls(link); int i = 2; }
public void Download(string filename) { var video = GetVideoInfo(); /* * If the video has a decrypted signature, decipher it */ if (video.RequiresDecryption) { DownloadUrlResolver.DecryptDownloadUrl(video); } /* * Create the audio downloader. * The first argument is the video where the audio should be extracted from. * The second argument is the path to save the audio file. */ var audioDownloader = new AudioDownloader(video, filename); // Register the progress events. We treat the download progress as 85% of the progress and the extraction progress only as 15% of the progress, // because the download will take much longer than the audio extraction. audioDownloader.DownloadProgressChanged += (sender, args) => RaiseProgressEvent(args.ProgressPercentage * 0.85); audioDownloader.AudioExtractionProgressChanged += (sender, args) => RaiseProgressEvent(85 + args.ProgressPercentage * 0.15); audioDownloader.DownloadFinished += (sender, args) => RaiseProgressEvent(101.0); /* * Execute the audio downloader. * For GUI applications note, that this method runs synchronously. */ audioDownloader.Execute(); }
private VideoInfo GetVideoInfo() { // Our test youtube link string link = Song.Url; /* * Get the available video formats. * We'll work with them in the video and audio download examples. */ try { var videoInfos = DownloadUrlResolver.GetDownloadUrls(link); /* * We want the first extractable video with the highest audio quality. */ var video = videoInfos .Where(info => info.CanExtractAudio) .OrderByDescending(info => info.AudioBitrate) .First(); return(video); } catch (VideoNotAvailableException) { return(null); } catch (YoutubeParseException) { return(null); } }
public async Task LoadContextMenu() { this.IsLoadingContextMenu = true; var infos = new List <VideoInfo>(0); try { infos = await Task.Run(() => DownloadUrlResolver.GetDownloadUrls(this.Path, false).ToList()); } catch (YoutubeParseException ex) { this.Log().ErrorException("Failed to load the available YouTube videos", ex); } catch (VideoNotAvailableException ex) { this.Log().ErrorException("Failed to load the available YouTube videos", ex); } catch (WebException ex) { this.Log().ErrorException("Failed to load the available YouTube videos", ex); } this.VideosToDownload = infos.Where(x => x.AdaptiveType == AdaptiveType.None && x.VideoType != VideoType.Unknown) .OrderBy(x => x.VideoType) .ThenByDescending(x => x.Resolution) .ToList(); this.AudioToDownload = infos.Where(x => x.CanExtractAudio).OrderByDescending(x => x.AudioBitrate).ToList(); this.IsLoadingContextMenu = false; }
private async Task DownloadFromYoutube(VideoInfo videoInfo, Func <Task> downloadFunction) { this.DownloadProgress = 0; this.DownloadFailed = false; try { await Task.Run(() => DownloadUrlResolver.DecryptDownloadUrl(videoInfo)); } catch (YoutubeParseException) { this.DownloadFailed = true; return; } try { await downloadFunction(); } catch (YoutubeDownloadException) { this.DownloadFailed = true; } }
//this method download the video in background. Also makes the GUI responsive private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) { try { string link = textBox1.Text; IEnumerable <VideoInfo> videoInfo = DownloadUrlResolver.GetDownloadUrls(link); VideoInfo video = videoInfo.FirstOrDefault();//we take the first video from that url. if (video.RequiresDecryption) { DownloadUrlResolver.DecryptDownloadUrl(video); } //just a trick to allow method call in background worker control; var videoDownloader = new VideoDownloader(video, Path.Combine(Invoke((Func <string>)(() => { return(GetPath("")); })).ToString(), video.Title.Replace(" ", string.Empty).Replace("/", "") + video.VideoExtension)); //report the progress for progressbar1 videoDownloader.DownloadProgressChanged += (y, x) => backgroundWorker1.ReportProgress((int)x.ProgressPercentage); videoDownloader.Execute(); } catch (Exception ex) { MessageBox.Show(ex.ToString()); } }
private void buttonDownloadAudio_Click(object sender, EventArgs e) { // const string link = "https://www.youtube.com/watch?v=B0jMPI_pUec"; // http://www.youtube.com/watch?v=O3UBOOZw-FE"; labelStatus.Text = "Starting..."; string link = editUrl.Text.Trim(); if (string.IsNullOrEmpty(link)) { MessageBox.Show("Please Enter URL", "Missing URL"); return; } /* * Get the available video formats. * We'll work with them in the video and audio download examples. */ try { IEnumerable <VideoInfo> videoInfos = DownloadUrlResolver.GetDownloadUrls(link, false); downloadAudio(videoInfos); } catch (Exception ex) { MessageBox.Show("Could note contact URL", "Bad URL"); return; } }
public static void TestYoutubeExtractor(string[] queries) { using (var cli = Client.For(YouTube.Default)) { for (int i = 0; i < queries.Length; i++) { string query = queries[i]; var video = cli.GetVideo(query); string uri = video.GetUri(); try { var uris = DownloadUrlResolver .GetDownloadUrls(query) .Select(v => v.DownloadUrl); Console.WriteLine($"Link #{i + 1}"); foreach (var v in uris) { Console.WriteLine(v); Console.WriteLine(); } } catch { } } } }
private string DownloadAudio(string videoId, string albumName) { string location = "/storage/external_SD/Muzika"; string youtubeLink = "https://www.youtube.com/watch?v=" + videoId; IEnumerable <VideoInfo> videoInfos = DownloadUrlResolver.GetDownloadUrls(youtubeLink); VideoInfo video = videoInfos .Where(info => info.AudioType == AudioType.Aac) .OrderByDescending(info => info.AudioBitrate) .FirstOrDefault(); if (video == null) { throw new NullReferenceException("Audio was not found"); } /* * If the video has a decrypted signature, decipher it */ if (video.RequiresDecryption) { DownloadUrlResolver.DecryptDownloadUrl(video); } var downloadUrl = video.DownloadUrl; return(""); }
public void DoDownloadVideo(string url) { DownloadItem downloadItem = new DownloadItem("Last Download", FormatType.None, "Pending", 0); downloadList.addToDownloadsList(downloadItem); IEnumerable <VideoInfo> videoInfos = DownloadUrlResolver.GetDownloadUrls(url); VideoInfo video = videoInfos .First(info => info.VideoType == VideoType.Mp4 && info.Resolution == 720 || info.Resolution == 480); if (video.RequiresDecryption) { DownloadUrlResolver.DecryptDownloadUrl(video); } downloadItem.Progress = 0; downloadItem.Status = "Downloading"; downloadItem.Title = video.Title; downloadItem.Type = FormatType.Mp4; ExtendedVideoDownloader videoDownloader = new ExtendedVideoDownloader(video, Path.Combine(SavePath, video.Title + video.VideoExtension), downloadItem); videoDownloader.DownloadProgressChanged += new EventHandler <ProgressEventArgs>(OnProgressChangedVideo); videoDownloader.DownloadFinished += new EventHandler(OnDownloadFinishVideo); try{ videoDownloader.Execute(); } catch (Exception exc) { MessageDialog md = new MessageDialog(null, DialogFlags.Modal, MessageType.Error, ButtonsType.Ok, "Download " + video.Title + " failed!\n" + exc.Message); md.Run(); md.Destroy(); } }
public ActionResult Download(string ids) { var videosIds = ids.Split(',').ToList(); var index = 1; foreach (var id in videosIds) { var url = $"https://www.youtube.com/watch?v={ id }"; try { IEnumerable <VideoInfo> videoInfos = DownloadUrlResolver.GetDownloadUrls(url); YouTubeDownload.DownloadVideo(videoInfos, index); index++; } catch (Exception ex) { return(Json(new { Message = ex.Message, Status = "Erro" }, JsonRequestBehavior.AllowGet)); } } return(Json(new { Message = "OK", Status = "Sucesso" }, JsonRequestBehavior.AllowGet)); }
private void btnDownload_Click(object sender, EventArgs e) { progressBar1.Minimum = 0; progressBar1.Maximum = 100; try { IEnumerable <VideoInfo> videos = DownloadUrlResolver.GetDownloadUrls(txtUrl.Text); VideoInfo video = videos.First(p => p.VideoType == VideoType.Mp4 && p.Resolution == Convert.ToInt32(cmbQuality.Text)); cmbQuality.Text = video.Resolution.ToString(); if (video.RequiresDecryption) { DownloadUrlResolver.DecryptDownloadUrl(video); } VideoDownloader downloader = new VideoDownloader(video, Path.Combine(Application.StartupPath + "\\", video.Title + video.VideoExtension)); downloader.DownloadProgressChanged += downloader_DownloadProgressChanged; Thread thread = new Thread(() => { downloader.Execute(); }) { IsBackground = true }; thread.Start(); } catch (System.Net.WebException) { MessageBox.Show("There is a problem with your internet connection"); } catch (System.ArgumentException o) { MessageBox.Show(o.Message); } }
public async Task DownloadTrailer(string moviePath) { string movieName = Path.GetFileNameWithoutExtension(Path.GetFileName(moviePath)); string link = await SearchVideo($"{movieName} trailer"); if (link == null) { _logger.LogWarning($"No trailer for {movieName}"); return; } IEnumerable <VideoInfo> videoInfos = DownloadUrlResolver.GetDownloadUrls(link); VideoInfo video = videoInfos.OrderByDescending(x => x.Resolution) .First(x => x.VideoType == VideoType.Mp4 && x.AdaptiveType == AdaptiveType.None); if (video.RequiresDecryption) { DownloadUrlResolver.DecryptDownloadUrl(video); } var videoDownloader = new VideoDownloader(video, Path.Combine(Path.GetDirectoryName(moviePath), $"{video.Title.RemoveIllegalCharacters()}-trailer{video.VideoExtension}")); _logger.LogInformation($"Start downloading trailer for {movieName}"); videoDownloader.Execute(); _logger.LogInformation($"Downloading trailer for {movieName} finished."); }
private string DownloadVideoAndReturnPath(VideoSearchComponents video, string outputPath) { var toDownload = DownloadUrlResolver.GetDownloadUrls(video.getUrl()) .OrderBy(x => x.FileSize) .First(x => x.AudioBitrate > 0 && x.FileSize > 0); var dl = new VideoDownloader(); var videoExtension = toDownload.VideoExtension; if (toDownload.RequiresDecryption) { DownloadUrlResolver.DecryptDownloadUrl(toDownload); } var basePath = Path.Combine(outputPath, Path.GetRandomFileName()); var request = (HttpWebRequest)WebRequest.Create(toDownload.DownloadUrl); var response = (HttpWebResponse)request.GetResponse(); var outFilePath = basePath + videoExtension; using (var reader = new StreamReader(response.GetResponseStream())) { var ms = new MemoryStream(); response.GetResponseStream().CopyTo(ms); var outFile = File.Create(outFilePath); ms.WriteTo(outFile); outFile.Close(); } return(outFilePath); }
private void button1_Click(object sender, EventArgs e) { progress.Value = 0; progress.Maximum = list.Items.Count; progress.Update(); foreach (var item in list.Items) { /* * Get the available video formats. * We'll work with them in the video and audio download examples. */ IEnumerable <VideoInfo> videoInfos = DownloadUrlResolver.GetDownloadUrls(item.ToString(), false); string fileName = ""; console.Text = "Procesing " + progress.Value + 1 + " of " + progress.Maximum + ": " + item; try { DownloadAudio(videoInfos, out fileName); //DownloadVideo(videoInfos, out fileName); } catch (Exception ex) { console.Text = fileName + ": " + ex.Message; } progress.Value++; progress.Update(); } }
public async Task CanExtractLinks() { IEnumerable <VideoInfo> videoInfos = await DownloadUrlResolver.GetDownloadUrlsAsync("https://www.youtube.com/watch?v=rKTUAESacQM"); Assert.IsTrue(videoInfos != null); Assert.IsTrue(videoInfos.Any()); }
protected override void OnCreate(Bundle savedInstanceState) { base.OnCreate(savedInstanceState); // Set our view from the "main" layout resource SetContentView(Resource.Layout.Main); // Get our button from the layout resource, // and attach an event to it Button button = FindViewById <Button>(Resource.Id.myButton); button.Click += delegate { string url = "https://www.youtube.com/watch?v=ALUhXkqXuHs"; IEnumerable <VideoInfo> videoInfos = DownloadUrlResolver.GetDownloadUrls(url, false); VideoInfo video = videoInfos .First(info => info.VideoType == VideoType.Mp4); if (video.RequiresDecryption) { DownloadUrlResolver.DecryptDownloadUrl(video); } string DestinationFile = Path.Combine(Environment.ExternalStorageDirectory.AbsolutePath, "test.mp4"); Download download = new Download(); download.Run(video.DownloadUrl, DestinationFile); }; }
void ResolveLink() { var query = RequestText; try { var video = DownloadUrlResolver.GetDownloadUrls(Searches.FindYoutubeUrlByKeywords(query)) .Where(v => v.AdaptiveType == AdaptiveType.Audio) .OrderByDescending(v => v.AudioBitrate).FirstOrDefault(); if (video == null) { throw new Exception("Could not load any video elements"); } StreamUrl = video.DownloadUrl; Title = video.Title; string invalidChars = new string(Path.GetInvalidFileNameChars()) + new string(Path.GetInvalidPathChars()); foreach (char c in invalidChars) { FileName = FileName.Replace(c.ToString(), "_"); } StartBuffering(); LinkResolved = true; Channel.Send($"{User.Mention}, Queued **{video.Title}**"); } catch (Exception e) { // Send a message to the guy that queued that Channel.SendMessage("This video is unavailable in the country the Bot is running in, or you enter an invalid name or url."); Console.WriteLine("Cannot parse youtube url: " + query); Cancel(); } }
public IHttpActionResult DownloadYT(int channelId, [FromBody] MyUrl url) { IEnumerable <VideoInfo> videoInfos = DownloadUrlResolver.GetDownloadUrls(url.Url); VideoInfo video = videoInfos.First(info => info.VideoType == VideoType.Mp4); if (video.RequiresDecryption) { DownloadUrlResolver.DecryptDownloadUrl(video); } string videoPath = Path.Combine(FileLocations.BaseDir, video.Title + video.VideoExtension); var videoDownloader = new VideoDownloader(video, videoPath); videoDownloader.DownloadProgressChanged += (sender, args) => Console.WriteLine(args.ProgressPercentage); videoDownloader.Execute(); string mp3Path = Path.Combine(FileLocations.BaseDir, video.Title + ".mp3"); var inputFile = new MediaFile { Filename = videoPath }; var outputFile = new MediaFile { Filename = mp3Path }; using (var engine = new Engine()) { engine.Convert(inputFile, outputFile); } return(Ok(mp3Path)); }
protected override CompletionResult DownloadImpDefault(DownloadInfo info) { if (info.SelectedVideoInfo.RequiresDecryption) { DownloadUrlResolver.DecryptDownloadUrl(info.SelectedVideoInfo); } var forMatTitle = new string(info.SelectedVideoInfo.Title.Where(x => !(Path.GetInvalidPathChars().Contains(x) || Path.GetInvalidFileNameChars().Contains(x))).ToArray()) + info.Extension; VideoDownloader downloader = new VideoDownloader(info.SelectedVideoInfo, info.OutputPath + forMatTitle); downloader.DownloadProgressChanged += (obj, e) => { Reporter.Report(e.ProgressPercentage); }; try { downloader.Execute(); return(new CompletionResult("Download Successful:" + Environment.NewLine + info.OutputPath + forMatTitle)); } catch (Exception e) { return(new CompletionResult(string.Format("Download Failed :( - {0} : {1}", e.GetType().Name, e.Message), e) { RanToCompletion = false }); } }
private static void bw_downloadAudio(object send, DoWorkEventArgs e) { isVideo_ = false; isAudio_ = true; BackgroundWorker worker = send as BackgroundWorker; if (dir_ != " ") { //Parameter for video type IEnumerable <VideoInfo> videoInfos = DownloadUrlResolver.GetDownloadUrls(url_); VideoInfo video = videoInfos.Where(info => info.CanExtractAudio).OrderByDescending(info => info.AudioBitrate).First(); if (video.RequiresDecryption) { DownloadUrlResolver.DecryptDownloadUrl(video); } audioDownloader_ = new AudioDownloader(video, dir_); audioDownloader_.AudioExtractionProgressChanged += (sender, args) => progBar_.Invoke((Action)(() => { worker.ReportProgress((int)(85 + args.ProgressPercentage * 0.15)); })); try { audioDownloader_.Execute(); } catch (WebException we) { MessageBox.Show("The video returned an error, please try again later", we.Response.ToString(), MessageBoxButtons.OK, MessageBoxIcon.Error); } } }
public static void Download(string urlRaw, bool audioOnly) { // todo: store location somewhere, folder on desktop for now string pathString = System.IO.Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.Desktop), "test"); System.IO.Directory.CreateDirectory(pathString); // get possible formats for download IEnumerable <VideoInfo> videoInfos = DownloadUrlResolver.GetDownloadUrls(urlRaw); // find an mp4 format VideoInfo video = videoInfos .First(info => info.VideoType == VideoType.Mp4 && info.Resolution == 360); // download the video string videoPath = Path.Combine(pathString, video.Title + video.VideoExtension); var videoDownloader = new VideoDownloader(video, videoPath); videoDownloader.Execute(); // if only audio is wanted, convert to mp3 using ffmpeg if (audioOnly) { AudioConverter.toMp3(videoPath); } }
public override void LoadToCache() { this.IsCaching = true; string tempPath = Path.GetTempFileName(); IEnumerable <VideoInfo> videoInfos = DownloadUrlResolver.GetDownloadUrls(this.OriginalPath); VideoInfo video = videoInfos .Where(info => info.CanExtractAudio) .First(info => info.VideoFormat == VideoFormat.FlashMp3HighQuality || info.VideoFormat == VideoFormat.FlashMp3LowQuality); var downloader = new AudioDownloader(video, tempPath); downloader.ProgressChanged += (sender, args) => { this.CachingProgress = (int)args.ProgressPercentage; }; downloader.Execute(); this.StreamingPath = tempPath; this.IsCached = true; }
public static void DownloadVideo(IEnumerable <VideoInfo> videoInfos, int index) { try { VideoInfo video = videoInfos.First(info => info.VideoType == VideoType.Mp4 && info.Resolution == 360); if (video.RequiresDecryption) { DownloadUrlResolver.DecryptDownloadUrl(video); } string path = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + "\\YouTubeVideos"; if (!Directory.Exists(path)) { Directory.CreateDirectory(path); } var filename = $"{ index } - { YouTubeHelpers.RemoveIllegalPathCharacters(video.Title) + video.VideoExtension }"; var savePath = Path.Combine(path, filename); var videoDownloader = new VideoDownloader(video, savePath); videoDownloader.DownloadProgressChanged += (sender, args) => Console.WriteLine(args.ProgressPercentage); videoDownloader.Execute(); } catch (Exception ex) { throw ex; } }