private void DownloadVideo(string id) { try { lock (_commandLockObject) { if (!string.IsNullOrWhiteSpace(id)) { TwitchVideo video = Videos.Where(v => v.Id == id).FirstOrDefault(); if (video != null) { TwitchVideoAuthInfo vodAuthInfo = _apiService.GetVodAuthInfo(video.Id); if (!vodAuthInfo.Privileged && vodAuthInfo.SubOnly) { if (_isAuthenticatedSubOnly) { _dialogService.ShowMessageBox("This video is sub-only but you are not subscribed to the channel!", "Download", MessageBoxButton.OK, MessageBoxImage.Exclamation); } else { _dialogService.ShowMessageBox("This video is sub-only! You need to enable sub-only video download support first!", "Download", MessageBoxButton.OK, MessageBoxImage.Exclamation); } return; } Dictionary <TwitchVideoQuality, string> playlistInfo = _apiService.GetPlaylistInfo(id, vodAuthInfo); List <TwitchVideoQuality> qualities = playlistInfo.Keys.OrderBy(q => q).ToList(); Preferences currentPrefs = _preferencesService.CurrentPreferences.Clone(); TwitchVideoQuality selectedQuality = GetSelectedQuality(qualities, currentPrefs.DownloadDefaultQuality); string folder = currentPrefs.DownloadSubfoldersForFav && _preferencesService.IsChannelInFavourites(video.Channel) ? Path.Combine(currentPrefs.DownloadFolder, video.Channel) : currentPrefs.DownloadFolder; string filename = _filenameService.SubstituteWildcards(currentPrefs.DownloadFileName, video, selectedQuality); filename = _filenameService.EnsureExtension(filename, currentPrefs.DownloadDisableConversion); DownloadParameters downloadParams = new DownloadParameters(video, qualities, selectedQuality, folder, filename, currentPrefs.DownloadDisableConversion); if (video.StartTime.HasValue) { downloadParams.CropStartTime = video.StartTime.Value; } _navigationService.ShowDownload(downloadParams); } } } } catch (Exception ex) { _dialogService.ShowAndLogException(ex); } }
private void WriteVodAuthInfo(Action <string> log, TwitchVideoAuthInfo vodAuthInfo) { log(Environment.NewLine + Environment.NewLine + "ACCESS INFO"); log(Environment.NewLine + "--------------------------------------------------------------------------------------------"); log(Environment.NewLine + "Token: " + vodAuthInfo.Token); log(Environment.NewLine + "Signature: " + vodAuthInfo.Signature); log(Environment.NewLine + "Sub-Only: " + (vodAuthInfo.SubOnly ? "Yes" : "No")); log(Environment.NewLine + "Privileged: " + (vodAuthInfo.Privileged ? "Yes" : "No")); }
public Dictionary <TwitchVideoQuality, string> GetPlaylistInfo(string vodId, TwitchVideoAuthInfo vodAuthInfo) { using (WebClient webClient = CreateWebClientWithEncoding()) { webClient.Headers.Add("Accept", "*/*"); webClient.QueryString.Add("allow_source", "true"); webClient.QueryString.Add("allow_audio_only", "true"); webClient.QueryString.Add("token", vodAuthInfo.Token); webClient.QueryString.Add("sig", vodAuthInfo.Signature); string playlist = webClient.DownloadString(string.Format(PLAYLISTS_URL, vodId)); List <string> lines = playlist.Split(new string[] { "\n" }, StringSplitOptions.RemoveEmptyEntries).ToList(); Dictionary <TwitchVideoQuality, string> playlistInfo = new Dictionary <TwitchVideoQuality, string>(); for (int i = 0; i < lines.Count; i++) { string line = lines[i]; if (!line.StartsWith("#")) { string mediaInfo = lines[i - 2]; string streamInfo = lines[i - 1]; Match groupMatch = _rxGroup.Match(mediaInfo); string id = groupMatch.Groups["group"].Value; Match nameMatch = _rxName.Match(mediaInfo); string name = nameMatch.Groups["name"].Value; string resolution = null; Match resolutionMatch = _rxResolution.Match(streamInfo); if (resolutionMatch.Success) { resolution = resolutionMatch.Groups["resolution"].Value; } TwitchVideoQuality quality = new TwitchVideoQuality(id, name, resolution); playlistInfo.Add(quality, line); } } return(playlistInfo); } }
private void StartQueuedDownloadIfExists() { if (_paused) { return; } if (Monitor.TryEnter(_changeDownloadLockObject)) { try { if (!_downloads.Where(d => d.DownloadState == DownloadState.Downloading).Any()) { TwitchVideoDownload download = _downloads.Where(d => d.DownloadState == DownloadState.Queued).FirstOrDefault(); if (download == null) { return; } DownloadParameters downloadParams = download.DownloadParams; CancellationTokenSource cancellationTokenSource = new CancellationTokenSource(); CancellationToken cancellationToken = cancellationTokenSource.Token; string downloadId = download.Id; string vodId = downloadParams.Video.Id; string tempDir = Path.Combine(_preferencesService.CurrentPreferences.DownloadTempFolder, downloadId); string ffmpegFile = _processingService.FFMPEGExe; string concatFile = Path.Combine(tempDir, Path.GetFileNameWithoutExtension(downloadParams.FullPath) + ".ts"); string outputFile = downloadParams.FullPath; bool disableConversion = downloadParams.DisableConversion; bool cropStart = downloadParams.CropStart; bool cropEnd = downloadParams.CropEnd; TimeSpan cropStartTime = downloadParams.CropStartTime; TimeSpan cropEndTime = downloadParams.CropEndTime; TwitchVideoQuality quality = downloadParams.SelectedQuality; Action <DownloadState> setDownloadState = download.SetDownloadState; Action <string> log = download.AppendLog; Action <string> setStatus = download.SetStatus; Action <double> setProgress = download.SetProgress; Action <bool> setIsIndeterminate = download.SetIsIndeterminate; Task downloadVideoTask = new Task(() => { setStatus("Initializing"); log("Download task has been started!"); WriteDownloadInfo(log, downloadParams, ffmpegFile, tempDir); cancellationToken.ThrowIfCancellationRequested(); log(Environment.NewLine + Environment.NewLine + "Retrieving VOD access information..."); TwitchVideoAuthInfo vodAuthInfo = _apiService.GetVodAuthInfo(vodId); log(" done!"); cancellationToken.ThrowIfCancellationRequested(); WriteVodAuthInfo(log, vodAuthInfo); cancellationToken.ThrowIfCancellationRequested(); CheckTempDirectory(log, tempDir); cancellationToken.ThrowIfCancellationRequested(); log(Environment.NewLine + Environment.NewLine + "Retrieving playlist information for all VOD qualities..."); Dictionary <TwitchVideoQuality, string> playlistInfo = _apiService.GetPlaylistInfo(vodId, vodAuthInfo); log(" done!"); cancellationToken.ThrowIfCancellationRequested(); WritePlaylistInfo(log, playlistInfo); cancellationToken.ThrowIfCancellationRequested(); TwitchPlaylist vodPlaylist = GetVodPlaylist(log, tempDir, playlistInfo, quality); cancellationToken.ThrowIfCancellationRequested(); CropInfo cropInfo = CropVodPlaylist(vodPlaylist, cropStart, cropEnd, cropStartTime, cropEndTime); cancellationToken.ThrowIfCancellationRequested(); DownloadParts(log, setStatus, setProgress, vodPlaylist, cancellationToken); cancellationToken.ThrowIfCancellationRequested(); _processingService.ConcatParts(log, setStatus, setProgress, vodPlaylist, disableConversion ? outputFile : concatFile); if (!disableConversion) { cancellationToken.ThrowIfCancellationRequested(); _processingService.ConvertVideo(log, setStatus, setProgress, setIsIndeterminate, concatFile, outputFile, cropInfo); } }, cancellationToken); Task continueTask = downloadVideoTask.ContinueWith(task => { log(Environment.NewLine + Environment.NewLine + "Starting temporary download folder cleanup!"); CleanUp(tempDir, log); setProgress(100); setIsIndeterminate(false); bool success = false; if (task.IsFaulted) { setDownloadState(DownloadState.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) { setDownloadState(DownloadState.Canceled); log(Environment.NewLine + Environment.NewLine + "Download task was canceled!"); } else { success = true; setDownloadState(DownloadState.Done); log(Environment.NewLine + Environment.NewLine + "Download task ended successfully!"); } if (!_downloadTasks.TryRemove(downloadId, out DownloadTask downloadTask)) { throw new ApplicationException("Could not remove download task with ID '" + downloadId + "' from download task collection!"); } if (success && _preferencesService.CurrentPreferences.DownloadRemoveCompleted) { _eventAggregator.GetEvent <RemoveDownloadEvent>().Publish(downloadId); } }); if (_downloadTasks.TryAdd(downloadId, new DownloadTask(downloadVideoTask, continueTask, cancellationTokenSource))) { downloadVideoTask.Start(); setDownloadState(DownloadState.Downloading); } } } finally { Monitor.Exit(_changeDownloadLockObject); } } }