public PlaylistReader(string url, int[] videos, bool reverse) { string json_dir = Common.GetJsonDirectory(); _playlist_id = Helper.GetPlaylistId(url); string range = string.Empty; if (videos != null && videos.Length > 0) { // Make sure the video indexes is sorted, otherwise reversing wont do anything Array.Sort(videos); range = string.Format(CmdPlaylistRange, string.Join(",", videos)); } string reverseS = reverse ? CmdPlaylistReverse : string.Empty; _arguments = string.Format(CmdPlaylistInfo, json_dir, _playlist_id, range, reverseS, url); _url = url; _logger = OperationLogger.Create(OperationLogger.YTDLogFile); YTD.LogHeader(_logger, _arguments); _youtubeDl = Helper.StartProcess(YTD.YouTubeDlPath, _arguments, OutputReadLine, ErrorReadLine, null, _logger); _youtubeDl.Exited += delegate { _processFinished = true; YTD.LogFooter(_logger); }; }
protected override void WorkerDoWork(DoWorkEventArgs e) { var task = YTD.GetVideoInfoBatchAsync(this.Inputs, video => { this.Videos.Add(video); }, null, _logger); try { int count = 0; while (count < this.Videos.Count || !task.IsCompleted) { if (this.CancellationPending) { break; } // Wait for more videos? while (count == this.Videos.Count) { Thread.Sleep(200); continue; } // Reset variable(s) _downloaderSuccessful = null; _downloader.Files.Clear(); // Get video, then increment count variable after var video = this.Videos[count++]; if (video.Failure) { // Something failed retrieving video info _failures++; continue; } var format = Helper.GetPreferredFormat(video, _preferredQuality); // Update properties for new video this.ReportProgress(-1, new Dictionary <string, object>() { { nameof(Title), $"({count}/{this.Videos.Count}) {video.Title}" }, { nameof(Duration), video.Duration }, { nameof(FileSize), format.FileSize } }); string prefix = _prefix ? count + ". " : string.Empty; string finalFile = Path.Combine(this.Output, $"{prefix}{Helper.FormatTitle(format.VideoInfo.Title)}.{format.Extension}"); this.DownloadedFiles.Add(finalFile); if (_ignoreExisting == false) { // Overwrite if finalFile already exists Helper.DeleteFiles(finalFile); } else if (File.Exists(finalFile)) { _downloads++; this.ReportProgress(EventFileDownloadComplete, finalFile); _logger.LogLine($"Skipped existing {finalFile}..."); goto finish; } if (format.AudioOnly) { _downloader.Files.Add(new FileDownload(finalFile, format.DownloadUrl)); } else { VideoFormat audioFormat = Helper.GetAudioFormat(format); // Add '_audio' & '_video' to end of filename. Only get filename, not full path. string audioFile = Regex.Replace(finalFile, @"^(.*)(\..*)$", "$1_audio$2"); string videoFile = Regex.Replace(finalFile, @"^(.*)(\..*)$", "$1_video$2"); // Download audio and video _downloader.Files.Add(new FileDownload(audioFile, audioFormat.DownloadUrl)); _downloader.Files.Add(new FileDownload(videoFile, format.DownloadUrl)); // Delete _audio and _video files in case they exists from a previous attempt Helper.DeleteFiles(_downloader.Files[0].Path, _downloader.Files[1].Path); } _downloader.Start(); // Wait for downloader to finish while (_downloader.IsBusy || _downloader.IsPaused) { if (this.CancellationPending) { _downloader.Stop(); break; } Thread.Sleep(200); } if (_downloaderSuccessful == true) { // Combine video and audio if necessary if (!format.AudioOnly) { this.ReportProgress(-1, new Dictionary <string, object>() { { nameof(Progress), 0 } }); this.ReportProgress(ProgressMax, null); Exception combineException; if (!OperationHelpers.Combine( _downloader.Files[0].Path, _downloader.Files[1].Path, this.Title, _logger, out combineException, this.ReportProgress)) { _failures++; } this.ErrorsInternal.Add(combineException.Message); this.ReportProgress(-1, new Dictionary <string, object>() { { nameof(Progress), 0 } }); } _downloads++; this.ReportProgress(EventFileDownloadComplete, finalFile); } else if (_downloaderSuccessful == false) { // Download failed, cleanup and continue _failures++; // Delete all related files. Helper method will check if it exists, throwing no errors Helper.DeleteFiles(_downloader.Files.Select(x => x.Path).ToArray()); } finish: // Reset before starting new download. this.ReportProgress(ProgressMin, null); } // Throw stored exception if it exists. For example TimeoutException from 'GetPlaylistInfoAsync' if (_operationException != null) { throw _operationException; } e.Result = this.CancellationPending ? OperationStatus.Canceled : OperationStatus.Success; } catch (Exception ex) { Common.SaveException(ex); e.Result = OperationStatus.Failed; _operationException = ex; } finally { _logger?.Close(); _logger = null; } }