Exemple #1
0
        public void Retry(string id)
        {
            if (this.paused)
            {
                return;
            }

            lock (this.changeDownloadLockObject)
            {
                DownloadTask downloadTask;

                if (!this.downloadTasks.TryGetValue(id, out downloadTask))
                {
                    TwitchVideoDownload download = this.Downloads.Where(d => d.Video.Id == id).FirstOrDefault();

                    if (download != null && (download.DownloadStatus == DownloadStatus.Canceled || download.DownloadStatus == DownloadStatus.Error))
                    {
                        download.ResetLog();
                        download.Progress       = 0;
                        download.DownloadStatus = DownloadStatus.Queued;
                        download.Status         = "Initializing";
                    }
                }
            }
        }
        private void ViewVideo(string id)
        {
            try
            {
                lock (_commandLockObject)
                {
                    if (!string.IsNullOrWhiteSpace(id))
                    {
                        TwitchVideoDownload download = Downloads.Where(d => d.Id == id).FirstOrDefault();

                        if (download != null)
                        {
                            string folder = download.DownloadParams.Folder;

                            if (Directory.Exists(folder))
                            {
                                Process.Start(folder);
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                _dialogService.ShowAndLogException(ex);
            }
        }
Exemple #3
0
        private void ViewVideo(string id)
        {
            try
            {
                lock (this.commandLockObject)
                {
                    if (!string.IsNullOrWhiteSpace(id))
                    {
                        TwitchVideoDownload download = this.Downloads.Where(d => d.Video.Id == id).FirstOrDefault();

                        if (download != null)
                        {
                            string folder = Path.GetDirectoryName(download.DownloadParams.Filename);

                            if (Directory.Exists(folder))
                            {
                                Process.Start(folder);
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                this.guiService.ShowAndLogException(ex);
            }
        }
        public void ShowLog(TwitchVideoDownload download)
        {
            LogViewVM vm = this._kernel.Get <LogViewVM>();

            vm.Download = download ?? throw new ArgumentNullException(nameof(download));

            this.Navigate(vm);
        }
Exemple #5
0
 private void CleanUp(string directory, TwitchVideoDownload download)
 {
     try
     {
         download.AppendLog(Environment.NewLine + "Deleting directory '" + directory + "'...");
         FileSystem.DeleteDirectory(directory);
         download.AppendLog(" done!");
     }
     catch
     {
     }
 }
        public void Remove(string id)
        {
            lock (_changeDownloadLockObject)
            {
                if (!_downloadTasks.TryGetValue(id, out DownloadTask downloadTask))
                {
                    TwitchVideoDownload download = _downloads.Where(d => d.Id == id).FirstOrDefault();

                    if (download != null)
                    {
                        _downloads.Remove(download);
                    }
                }
            }
        }
Exemple #7
0
        public void ShowLog(TwitchVideoDownload download)
        {
            if (download == null)
            {
                throw new ArgumentNullException(nameof(download));
            }

            LogWindowVM vm = this.kernel.Get <LogWindowVM>();

            vm.Download = download;

            LogWindow window = this.kernel.Get <LogWindow>();

            window.DataContext = vm;

            window.ShowDialog();
        }
Exemple #8
0
        public void Remove(string id)
        {
            lock (this.changeDownloadLockObject)
            {
                DownloadTask downloadTask;

                if (!this.downloadTasks.TryGetValue(id, out downloadTask))
                {
                    TwitchVideoDownload download = this.Downloads.Where(d => d.Video.Id == id).FirstOrDefault();

                    if (download != null)
                    {
                        this.Downloads.Remove(download);
                    }
                }
            }
        }
        private void ShowLog(string id)
        {
            try {
                lock (this._commandLockObject) {
                    if (!string.IsNullOrWhiteSpace(id))
                    {
                        TwitchVideoDownload download = this.Downloads.Where(d => d.Id == id).FirstOrDefault();

                        if (download != null)
                        {
                            this._navigationService.ShowLog(download);
                        }
                    }
                }
            }
            catch (Exception ex) {
                this._dialogService.ShowAndLogException(ex);
            }
        }
        public void Retry(string id)
        {
            if (_paused)
            {
                return;
            }

            lock (_changeDownloadLockObject)
            {
                if (!_downloadTasks.TryGetValue(id, out DownloadTask downloadTask))
                {
                    TwitchVideoDownload download = _downloads.Where(d => d.Id == id).FirstOrDefault();

                    if (download != null && (download.DownloadState == DownloadState.Canceled || download.DownloadState == DownloadState.Error))
                    {
                        download.ResetLog();
                        download.SetProgress(0);
                        download.SetDownloadState(DownloadState.Queued);
                        download.SetStatus("Initializing");
                    }
                }
            }
        }
 public FailedRecord(TwitchVideoDownload download) : base(download)
 {
     Retried = false;
 }
        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);
                }
            }
        }
Exemple #13
0
        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)
                        {
                            TwitchVideo        video          = download.Video;
                            DownloadParameters downloadParams = download.DownloadParams;

                            CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
                            CancellationToken       cancellationToken       = cancellationTokenSource.Token;

                            long completedChunkDownloads = 0;

                            int maxConnectionCount = ServicePointManager.DefaultConnectionLimit;

                            string urlId        = video.IdTrimmed;
                            string quality      = downloadParams.Resolution.VideoQuality.ToTwitchQuality();
                            string qualityFps   = downloadParams.Resolution.ResolutionFps;
                            string outputDir    = Path.Combine(this.preferencesService.CurrentPreferences.DownloadTempFolder, TEMP_PREFIX + urlId);
                            string playlistFile = Path.Combine(outputDir, "vod.m3u8");
                            string ffmpegFile   = Path.Combine(appDir, Environment.Is64BitOperatingSystem ? FFMPEG_EXE_X64 : FFMPEG_EXE_X86);
                            string outputFile   = downloadParams.Filename;

                            Task downloadVideoTask = new Task(() =>
                            {
                                download.Status = "Initializing";

                                download.AppendLog("Download task has been started!");

                                download.AppendLog(Environment.NewLine + Environment.NewLine + "VOD ID: " + urlId);
                                download.AppendLog(Environment.NewLine + "Selected Quality: " + qualityFps);
                                download.AppendLog(Environment.NewLine + "Download Url: " + video.Url.ToString());
                                download.AppendLog(Environment.NewLine + "Output File: " + outputFile);
                                download.AppendLog(Environment.NewLine + "FFMPEG Path: " + ffmpegFile);
                                download.AppendLog(Environment.NewLine + "Temporary Download Folder: " + outputDir);

                                if (!Directory.Exists(outputDir))
                                {
                                    download.AppendLog(Environment.NewLine + Environment.NewLine + "Creating directory '" + outputDir + "'...");
                                    FileSystem.CreateDirectory(outputDir);
                                    download.AppendLog(" done!");
                                }

                                if (Directory.EnumerateFileSystemEntries(outputDir).Any())
                                {
                                    throw new ApplicationException("Temporary download directory '" + outputDir + "' is not empty!");
                                }

                                using (WebClient webClient = new WebClient())
                                {
                                    download.AppendLog(Environment.NewLine + Environment.NewLine + "Retrieving access token and signature...");
                                    string accessTokenStr = webClient.DownloadString(string.Format(accessTokenUrl, urlId));
                                    download.AppendLog(" done!");

                                    dynamic accessTokenJson = JsonConvert.DeserializeObject(accessTokenStr);

                                    string token = Uri.EscapeDataString(accessTokenJson.token.ToString());
                                    string sig   = accessTokenJson.sig.ToString();

                                    download.AppendLog(Environment.NewLine + "Token: " + token);
                                    download.AppendLog(Environment.NewLine + "Signature: " + sig);

                                    cancellationToken.ThrowIfCancellationRequested();

                                    download.AppendLog(Environment.NewLine + Environment.NewLine + "Retrieving m3u8 playlist urls for all VOD qualities...");
                                    string allPlaylistsStr = webClient.DownloadString(string.Format(allPlaylistsUrl, urlId, sig, token));
                                    download.AppendLog(" done!");

                                    List <string> allPlaylistsList = allPlaylistsStr.Split(new string[] { "\n" }, StringSplitOptions.RemoveEmptyEntries).Where(s => !s.StartsWith("#")).ToList();

                                    allPlaylistsList.ForEach(url =>
                                    {
                                        download.AppendLog(Environment.NewLine + url);
                                    });

                                    string playlistUrl = allPlaylistsList.Where(s => s.ToLowerInvariant().Contains(quality)).First();

                                    download.AppendLog(Environment.NewLine + Environment.NewLine + "Playlist url for selected quality " + qualityFps + " is " + playlistUrl);

                                    cancellationToken.ThrowIfCancellationRequested();

                                    download.AppendLog(Environment.NewLine + Environment.NewLine + "Retrieving list of video chunks...");
                                    string playlistStr = webClient.DownloadString(playlistUrl);
                                    download.AppendLog(" done!");

                                    List <string> playlistLines = playlistStr.Split(new string[] { "\n" }, StringSplitOptions.RemoveEmptyEntries).ToList();

                                    List <string> webChunkList = playlistLines.Where(s => !s.StartsWith("#")).ToList();

                                    string webChunkUrlPrefix = playlistUrl.Substring(0, playlistUrl.LastIndexOf("/") + 1);

                                    long webChunkCount = webChunkList.Count;
                                    download.AppendLog(Environment.NewLine + "Number of video chunks to download: " + webChunkCount);
                                    download.AppendLog(Environment.NewLine + "Maximum connection count: " + maxConnectionCount);

                                    List <string> webChunkFilenames = new List <string>();

                                    List <WebChunk> downloadQueue = new List <WebChunk>();

                                    int counter = 0;

                                    download.AppendLog(Environment.NewLine + Environment.NewLine + "Initializing video chunk download queue...");

                                    foreach (string webChunk in webChunkList)
                                    {
                                        string filename = Path.Combine(outputDir, counter.ToString("D8") + ".ts");
                                        webChunkFilenames.Add(filename);
                                        downloadQueue.Add(new WebChunk(filename, webChunkUrlPrefix + webChunk));
                                        counter++;

                                        cancellationToken.ThrowIfCancellationRequested();
                                    }

                                    download.AppendLog(" done!");

                                    download.AppendLog(Environment.NewLine + "Starting parallel video chunk download...");

                                    download.Status = "Downloading";

                                    download.AppendLog(Environment.NewLine + Environment.NewLine + "Parallel video chunk download is running...");

                                    object percentageLock = new object();

                                    Parallel.ForEach(downloadQueue, new ParallelOptions()
                                    {
                                        MaxDegreeOfParallelism = maxConnectionCount - 1
                                    }, (webChunk, loopState) =>
                                    {
                                        using (WebClient downloadClient = new WebClient())
                                        {
                                            byte[] bytes = downloadClient.DownloadData(webChunk.Url);

                                            Interlocked.Increment(ref completedChunkDownloads);

                                            FileSystem.DeleteFile(webChunk.Filename);

                                            File.WriteAllBytes(webChunk.Filename, bytes);

                                            long completed = Interlocked.Read(ref completedChunkDownloads);

                                            lock (percentageLock)
                                            {
                                                download.Progress = (int)(completedChunkDownloads * 100 / webChunkCount);
                                            }
                                        }

                                        if (cancellationToken.IsCancellationRequested)
                                        {
                                            loopState.Stop();
                                        }
                                    });

                                    download.Progress = 100;

                                    cancellationToken.ThrowIfCancellationRequested();

                                    download.AppendLog(" done!");

                                    download.AppendLog(Environment.NewLine + Environment.NewLine + "Download of all video chunks complete!");

                                    download.AppendLog(Environment.NewLine + Environment.NewLine + "Creating local m3u8 playlist for FFMPEG");

                                    int chunkIndex = 0;

                                    for (int i = 0; i < playlistLines.Count; i++)
                                    {
                                        if (!playlistLines[i].StartsWith("#"))
                                        {
                                            playlistLines[i] = webChunkFilenames[chunkIndex];
                                            chunkIndex++;
                                        }
                                    }

                                    string newPlaylistStr = string.Join("\n", playlistLines);

                                    FileSystem.DeleteFile(playlistFile);

                                    download.AppendLog(Environment.NewLine + "Writing playlist to '" + playlistFile + "'");
                                    File.WriteAllText(playlistFile, newPlaylistStr);

                                    download.Status = "Encoding";

                                    download.Progress = 0;

                                    download.AppendLog(Environment.NewLine + Environment.NewLine + "Executing '" + ffmpegFile + "' on local playlist...");

                                    cancellationToken.ThrowIfCancellationRequested();

                                    ProcessStartInfo psi       = new ProcessStartInfo(ffmpegFile);
                                    psi.Arguments              = "-y -i \"" + playlistFile + "\" -c:v copy -c:a copy -bsf:a aac_adtstoasc \"" + outputFile + "\"";
                                    psi.RedirectStandardError  = true;
                                    psi.RedirectStandardOutput = true;
                                    psi.StandardErrorEncoding  = Encoding.UTF8;
                                    psi.StandardOutputEncoding = Encoding.UTF8;
                                    psi.UseShellExecute        = false;
                                    psi.CreateNoWindow         = true;

                                    download.AppendLog(Environment.NewLine + "Command line arguments: " + psi.Arguments + Environment.NewLine);

                                    using (Process p = new Process())
                                    {
                                        TimeSpan duration = new TimeSpan();

                                        DataReceivedEventHandler outputDataReceived = new DataReceivedEventHandler((s, e) =>
                                        {
                                            if (!string.IsNullOrWhiteSpace(e.Data))
                                            {
                                                string dataTrimmed = e.Data.Trim();

                                                if (dataTrimmed.StartsWith("Duration"))
                                                {
                                                    string durationStr = dataTrimmed.Substring(dataTrimmed.IndexOf(":") + 1).Trim();
                                                    durationStr        = durationStr.Substring(0, durationStr.IndexOf(",")).Trim();
                                                    duration           = TimeSpan.Parse(durationStr);
                                                }

                                                if (dataTrimmed.StartsWith("frame"))
                                                {
                                                    string timeStr   = dataTrimmed.Substring(dataTrimmed.IndexOf("time") + 4).Trim();
                                                    timeStr          = timeStr.Substring(timeStr.IndexOf("=") + 1).Trim();
                                                    timeStr          = timeStr.Substring(0, timeStr.IndexOf(" ")).Trim();
                                                    TimeSpan current = TimeSpan.Parse(timeStr);

                                                    lock (percentageLock)
                                                    {
                                                        download.Progress = (int)(current.TotalMilliseconds * 100 / duration.TotalMilliseconds);
                                                    }
                                                }

                                                download.AppendLog(Environment.NewLine + e.Data);
                                            }
                                        });

                                        p.OutputDataReceived += outputDataReceived;
                                        p.ErrorDataReceived  += outputDataReceived;
                                        p.StartInfo           = psi;
                                        p.Start();
                                        p.BeginErrorReadLine();
                                        p.BeginOutputReadLine();
                                        p.WaitForExit();
                                    }

                                    download.AppendLog(Environment.NewLine + Environment.NewLine + "Encoding complete!");
                                }
                            }, cancellationTokenSource.Token);

                            Task continueTask = downloadVideoTask.ContinueWith(task =>
                            {
                                download.AppendLog(Environment.NewLine + Environment.NewLine + "Starting temporary download folder cleanup!");
                                this.CleanUp(outputDir, download);

                                download.Progress = 100;

                                if (task.IsFaulted)
                                {
                                    download.DownloadStatus = DownloadStatus.Error;
                                    download.AppendLog(Environment.NewLine + Environment.NewLine + "Download task ended with an error!");

                                    if (task.Exception != null)
                                    {
                                        download.AppendLog(Environment.NewLine + Environment.NewLine + task.Exception.ToString());
                                    }
                                }
                                else if (task.IsCanceled)
                                {
                                    download.DownloadStatus = DownloadStatus.Canceled;
                                    download.AppendLog(Environment.NewLine + Environment.NewLine + "Download task was canceled!");
                                }
                                else
                                {
                                    download.DownloadStatus = DownloadStatus.Finished;
                                    download.AppendLog(Environment.NewLine + Environment.NewLine + "Download task ended successfully!");
                                }

                                DownloadTask downloadTask;

                                if (!this.downloadTasks.TryRemove(video.Id, out downloadTask))
                                {
                                    throw new ApplicationException("Could not remove download task with ID '" + video.Id + "' from download task collection!");
                                }
                            });

                            if (this.downloadTasks.TryAdd(video.Id, new DownloadTask(downloadVideoTask, continueTask, cancellationTokenSource)))
                            {
                                downloadVideoTask.Start();
                                download.DownloadStatus = DownloadStatus.Active;
                            }
                        }
                    }
                }
                finally
                {
                    Monitor.Exit(this.changeDownloadLockObject);
                }
            }
        }
Exemple #14
0
        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);
                }
            }
        }
 public DownloadRecord(TwitchVideoDownload download)
 {
     this.DownloadString = Convert.ToBase64String(Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(download)));
     Download            = download;
 }