private void DownloadVideo(string id) { try { lock (this.commandLockObject) { if (!string.IsNullOrWhiteSpace(id)) { TwitchVideo video = this.Videos.Where(v => v.Id == id).FirstOrDefault(); if (video != null) { Preferences currentPrefs = this.preferencesService.CurrentPreferences.Clone(); TwitchVideoResolution resolution = video.Resolutions.Where(r => r.VideoQuality == currentPrefs.DownloadVideoQuality).FirstOrDefault(); if (resolution == null) { resolution = video.Resolutions.First(); } string filename = this.filenameService.SubstituteWildcards(currentPrefs.DownloadFileName, video); DownloadParameters downloadParams = new DownloadParameters(video, resolution, currentPrefs.DownloadFolder, filename); this.guiService.ShowDownloadDialog(downloadParams, this.DownloadCallback); } } } } catch (Exception ex) { this.guiService.ShowAndLogException(ex); } }
public string SubstituteWildcards(string filename, TwitchVideo video) { if (video == null) { throw new ArgumentNullException(nameof(video)); } if (string.IsNullOrWhiteSpace(filename)) { return(filename); } string result = filename; DateTime recorded = video.RecordedDate; TwitchVideoResolution resolution = video.Resolutions.First(); result = result.Replace(FilenameWildcards.GAME, video.Game); result = result.Replace(FilenameWildcards.DATE, recorded.ToString("yyyyMMdd")); result = result.Replace(FilenameWildcards.TIME, recorded.ToString("hhmmsstt", CultureInfo.InvariantCulture)); result = result.Replace(FilenameWildcards.ID, video.IdTrimmed); result = result.Replace(FilenameWildcards.TITLE, video.Title); result = result.Replace(FilenameWildcards.RES, resolution.Resolution); result = result.Replace(FilenameWildcards.FPS, resolution.Fps); result = this.SubstituteInvalidChars(result, "_"); return(result); }
public void ShowDownloadDialog(TwitchVideo video, TwitchVideoResolution resolution, string folder, string filename, Action <bool, DownloadParameters> dialogCompleteCallback) { if (video == null) { throw new ArgumentNullException(nameof(video)); } if (resolution == null) { throw new ArgumentNullException(nameof(resolution)); } if (string.IsNullOrWhiteSpace(folder)) { throw new ArgumentNullException(nameof(folder)); } if (string.IsNullOrWhiteSpace(filename)) { throw new ArgumentNullException(nameof(filename)); } if (dialogCompleteCallback == null) { throw new ArgumentNullException(nameof(dialogCompleteCallback)); } DownloadWindowVM vm = this.kernel.Get <DownloadWindowVM>(); vm.Video = video; vm.Resolution = resolution; vm.Folder = folder; vm.Filename = filename; DownloadWindow window = this.kernel.Get <DownloadWindow>(); window.DataContext = vm; bool?result = window.ShowDialog(); DownloadParameters resultObject = vm.ResultObject; dialogCompleteCallback(result != true, resultObject); }
private void DownloadVideo(string id) { try { lock (this.commandLockObject) { if (!string.IsNullOrWhiteSpace(id)) { if (this.twitchService.Downloads.Where(d => d.Video.Id == id).Any()) { this.guiService.ShowMessageBox("This video is already being downloaded!", "Download Video", MessageBoxButton.OK, MessageBoxImage.Information); return; } TwitchVideo video = this.Videos.Where(v => v.Id == id).FirstOrDefault(); if (video != null) { Preferences currentPrefs = this.preferencesService.CurrentPreferences.Clone(); TwitchVideoResolution resolution = video.Resolutions.Where(r => r.VideoQuality == currentPrefs.DownloadVideoQuality).FirstOrDefault(); if (resolution == null) { resolution = video.Resolutions.First(); } string filename = this.filenameService.SubstituteWildcards(currentPrefs.DownloadFileName, video); this.guiService.ShowDownloadDialog(video, resolution, currentPrefs.DownloadFolder, filename, this.DownloadCallback); } } } } catch (Exception ex) { this.guiService.ShowAndLogException(ex); } }
private string RetrievePlaylistUrlForQuality(Action <string> log, WebClient webClient, TwitchVideoResolution resolution, string urlIdTrimmed, AuthInfo authInfo) { log(Environment.NewLine + Environment.NewLine + "Retrieving m3u8 playlist urls for all VOD qualities..."); string allPlaylistsStr = webClient.DownloadString(string.Format(allPlaylistsUrl, urlIdTrimmed, authInfo.Signature, authInfo.Token)); log(" done!"); List <string> allPlaylistsList = allPlaylistsStr.Split(new string[] { "\n" }, StringSplitOptions.RemoveEmptyEntries).Where(s => !s.StartsWith("#")).ToList(); allPlaylistsList.ForEach(url => { log(Environment.NewLine + url); }); string playlistUrl = allPlaylistsList.Where(s => s.ToLowerInvariant().Contains(resolution.VideoQuality.ToTwitchQuality())).First(); log(Environment.NewLine + Environment.NewLine + "Playlist url for selected quality " + resolution.ResolutionFps + " is " + playlistUrl); return(playlistUrl); }
private void StartQueuedDownloadIfExists() { if (this.paused) { return; } if (Monitor.TryEnter(this.changeDownloadLockObject)) { try { if (!this.downloads.Where(d => d.DownloadStatus == DownloadStatus.Active).Any()) { TwitchVideoDownload download = this.downloads.Where(d => d.DownloadStatus == DownloadStatus.Queued).FirstOrDefault(); if (download == null) { return; } DownloadParameters downloadParams = download.DownloadParams; CancellationTokenSource cancellationTokenSource = new CancellationTokenSource(); CancellationToken cancellationToken = cancellationTokenSource.Token; string downloadId = download.Id; string urlIdTrimmed = downloadParams.Video.IdTrimmed; string tempDir = Path.Combine(downloadParams.Folder, TEMP_PREFIX + downloadId); string playlistFile = Path.Combine(tempDir, PLAYLIST_NAME); string ffmpegFile = Path.Combine(appDir, Environment.Is64BitOperatingSystem ? FFMPEG_EXE_X64 : FFMPEG_EXE_X86); string outputFile = downloadParams.FullPath; bool cropStart = downloadParams.CropStart; bool cropEnd = downloadParams.CropEnd; TimeSpan cropStartTime = downloadParams.CropStartTime; TimeSpan cropEndTime = downloadParams.CropEndTime; TwitchVideoResolution resolution = downloadParams.Resolution; Action <DownloadStatus> setDownloadStatus = download.SetDownloadStatus; Action <string> log = download.AppendLog; Action <string> setStatus = download.SetStatus; Action <int> setProgress = download.SetProgress; Action <bool> setIsEncoding = download.SetIsEncoding; Task downloadVideoTask = new Task(() => { setStatus("Initializing"); log("Download task has been started!"); this.WriteDownloadInfo(log, downloadParams, ffmpegFile, tempDir); this.CheckTempDirectory(log, tempDir); using (WebClient webClient = new WebClient()) { AuthInfo authInfo = this.RetrieveAuthInfo(log, webClient, urlIdTrimmed); cancellationToken.ThrowIfCancellationRequested(); string playlistUrl = this.RetrievePlaylistUrlForQuality(log, webClient, resolution, urlIdTrimmed, authInfo); cancellationToken.ThrowIfCancellationRequested(); WebChunkList webChunkList = this.RetrieveWebChunkList(log, webClient, tempDir, playlistUrl); cancellationToken.ThrowIfCancellationRequested(); CropInfo cropInfo = this.CropWebChunkList(webChunkList, cropStart, cropEnd, cropStartTime, cropEndTime); cancellationToken.ThrowIfCancellationRequested(); this.DownloadChunks(log, setStatus, setProgress, webChunkList, cancellationToken); cancellationToken.ThrowIfCancellationRequested(); this.WriteNewPlaylist(log, webChunkList, playlistFile); cancellationToken.ThrowIfCancellationRequested(); this.EncodeVideo(log, setStatus, setProgress, setIsEncoding, ffmpegFile, playlistFile, outputFile, cropInfo); } }, cancellationToken); Task continueTask = downloadVideoTask.ContinueWith(task => { log(Environment.NewLine + Environment.NewLine + "Starting temporary download folder cleanup!"); this.CleanUp(tempDir, log); setProgress(100); setIsEncoding(false); bool success = false; if (task.IsFaulted) { setDownloadStatus(DownloadStatus.Error); log(Environment.NewLine + Environment.NewLine + "Download task ended with an error!"); if (task.Exception != null) { log(Environment.NewLine + Environment.NewLine + task.Exception.ToString()); } } else if (task.IsCanceled) { setDownloadStatus(DownloadStatus.Canceled); log(Environment.NewLine + Environment.NewLine + "Download task was canceled!"); } else { success = true; setDownloadStatus(DownloadStatus.Finished); log(Environment.NewLine + Environment.NewLine + "Download task ended successfully!"); } DownloadTask downloadTask; if (!this.downloadTasks.TryRemove(downloadId, out downloadTask)) { throw new ApplicationException("Could not remove download task with ID '" + downloadId + "' from download task collection!"); } if (success && this.preferencesService.CurrentPreferences.DownloadRemoveCompleted) { this.eventAggregator.GetEvent <DownloadCompletedEvent>().Publish(downloadId); } }); if (this.downloadTasks.TryAdd(downloadId, new DownloadTask(downloadVideoTask, continueTask, cancellationTokenSource))) { downloadVideoTask.Start(); setDownloadStatus(DownloadStatus.Active); } } } finally { Monitor.Exit(this.changeDownloadLockObject); } } }