twitch vod downloading done
ffmpeg essentials fix Project reorganized git lfs ffmpeg removed ffmpeg added
This commit is contained in:
229
VDownload.Core/VDownload.Core.Tasks/DownloadTask.cs
Normal file
229
VDownload.Core/VDownload.Core.Tasks/DownloadTask.cs
Normal file
@@ -0,0 +1,229 @@
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using VDownload.Models;
|
||||
using VDownload.Services.Utility.FFmpeg;
|
||||
using VDownload.Services.Data.Configuration;
|
||||
using VDownload.Services.Data.Settings;
|
||||
using Windows.System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Windows.Storage;
|
||||
using System.IO;
|
||||
using VDownload.Services.UI.Notifications;
|
||||
using VDownload.Services.UI.StringResources;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace VDownload.Core.Tasks
|
||||
{
|
||||
public partial class DownloadTask : ObservableObject
|
||||
{
|
||||
#region SERVICES
|
||||
|
||||
protected readonly IConfigurationService _configurationService;
|
||||
protected readonly ISettingsService _settingsService;
|
||||
protected readonly IFFmpegService _ffmpegService;
|
||||
protected readonly IStringResourcesService _stringResourcesService;
|
||||
protected readonly INotificationsService _notificationsService;
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region FIELDS
|
||||
|
||||
private readonly DispatcherQueue _dispatcherQueue = DispatcherQueue.GetForCurrentThread();
|
||||
|
||||
private CancellationTokenSource? _cancellationTokenSource;
|
||||
|
||||
private Task _downloadTask;
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region PROPERTIES
|
||||
|
||||
[ObservableProperty]
|
||||
protected Guid _id;
|
||||
|
||||
[ObservableProperty]
|
||||
protected Video _video;
|
||||
|
||||
[ObservableProperty]
|
||||
protected VideoDownloadOptions _downloadOptions;
|
||||
|
||||
[ObservableProperty]
|
||||
protected DownloadTaskStatus _status;
|
||||
|
||||
[ObservableProperty]
|
||||
protected DateTime _createDate;
|
||||
|
||||
[ObservableProperty]
|
||||
protected double _progress;
|
||||
|
||||
[ObservableProperty]
|
||||
protected string? _error;
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region CONSTRUCTORS
|
||||
|
||||
internal DownloadTask(Video video, VideoDownloadOptions downloadOptions, IConfigurationService configurationService, ISettingsService settingsService, IFFmpegService ffmpegService, IStringResourcesService stringResourcesService, INotificationsService notificationsService)
|
||||
{
|
||||
_configurationService = configurationService;
|
||||
_settingsService = settingsService;
|
||||
_ffmpegService = ffmpegService;
|
||||
_stringResourcesService = stringResourcesService;
|
||||
_notificationsService = notificationsService;
|
||||
|
||||
_video = video;
|
||||
_downloadOptions = downloadOptions;
|
||||
_id = Guid.NewGuid();
|
||||
_status = DownloadTaskStatus.Idle;
|
||||
_createDate = DateTime.Now;
|
||||
_progress = 0;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region PUBLIC METHODS
|
||||
|
||||
public void Enqueue()
|
||||
{
|
||||
DownloadTaskStatus[] statuses =
|
||||
[
|
||||
DownloadTaskStatus.Idle,
|
||||
DownloadTaskStatus.EndedUnsuccessfully,
|
||||
DownloadTaskStatus.EndedSuccessfully,
|
||||
DownloadTaskStatus.EndedCancelled,
|
||||
];
|
||||
if (statuses.Contains(Status))
|
||||
{
|
||||
Status = DownloadTaskStatus.Queued;
|
||||
}
|
||||
}
|
||||
|
||||
internal void Start()
|
||||
{
|
||||
_cancellationTokenSource = new CancellationTokenSource();
|
||||
|
||||
UpdateStatusWithDispatcher(DownloadTaskStatus.Initializing);
|
||||
|
||||
_downloadTask = Download();
|
||||
}
|
||||
|
||||
public async Task Cancel()
|
||||
{
|
||||
if (_cancellationTokenSource is not null)
|
||||
{
|
||||
_cancellationTokenSource.Cancel();
|
||||
await _downloadTask;
|
||||
_cancellationTokenSource.Dispose();
|
||||
_cancellationTokenSource = null;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region PRIVATE METHODS
|
||||
|
||||
private async Task Download()
|
||||
{
|
||||
CancellationToken token = _cancellationTokenSource.Token;
|
||||
|
||||
await _settingsService.Load();
|
||||
|
||||
string tempDirectory = $"{_settingsService.Data.Common.TempDirectory}\\{_configurationService.Common.Path.Temp.TasksDirectory}\\{_id}";
|
||||
Directory.CreateDirectory(tempDirectory);
|
||||
|
||||
List<string> content = new List<string>()
|
||||
{
|
||||
$"{_stringResourcesService.NotificationsResources.Get("Title")}: {Video.Title}",
|
||||
$"{_stringResourcesService.NotificationsResources.Get("Author")}: {Video.Author}"
|
||||
};
|
||||
|
||||
try
|
||||
{
|
||||
IProgress<double> onProgressDownloading = new Progress<double>((value) =>
|
||||
{
|
||||
UpdateStatusWithDispatcher(DownloadTaskStatus.Downloading);
|
||||
UpdateProgressWithDispatcher(value);
|
||||
});
|
||||
|
||||
VideoStreamDownloadResult downloadResult = await DownloadOptions.SelectedStream.Download(tempDirectory, onProgressDownloading, token, DownloadOptions.TrimStart, DownloadOptions.TrimEnd);
|
||||
|
||||
Action<double> onProgressProcessing = (value) =>
|
||||
{
|
||||
UpdateStatusWithDispatcher(DownloadTaskStatus.Processing);
|
||||
UpdateProgressWithDispatcher(value);
|
||||
};
|
||||
string outputPath = $"{tempDirectory}\\processed.{DownloadOptions.Extension}";
|
||||
|
||||
FFmpegBuilder ffmpegBuilder = _ffmpegService.CreateBuilder();
|
||||
if (downloadResult.NewTrimStart != TimeSpan.Zero)
|
||||
{
|
||||
ffmpegBuilder.TrimStart(downloadResult.NewTrimStart);
|
||||
}
|
||||
if (downloadResult.NewTrimEnd != downloadResult.NewDuration)
|
||||
{
|
||||
ffmpegBuilder.TrimEnd(downloadResult.NewTrimEnd);
|
||||
}
|
||||
ffmpegBuilder.SetMediaType(DownloadOptions.MediaType)
|
||||
.JoinCancellationToken(token)
|
||||
.JoinProgressReporter(onProgressProcessing, downloadResult.NewDuration);
|
||||
await ffmpegBuilder.RunAsync(downloadResult.File, outputPath);
|
||||
|
||||
UpdateStatusWithDispatcher(DownloadTaskStatus.Finalizing);
|
||||
|
||||
string destination = $"{DownloadOptions.Directory}\\{DownloadOptions.Filename}.{DownloadOptions.Extension}";
|
||||
File.Copy(outputPath, destination, true);
|
||||
|
||||
UpdateStatusWithDispatcher(DownloadTaskStatus.EndedSuccessfully);
|
||||
|
||||
if (_settingsService.Data.Common.Notifications.OnSuccessful)
|
||||
{
|
||||
string title = _stringResourcesService.NotificationsResources.Get("OnSuccessfulTitle");
|
||||
_notificationsService.SendNotification(title, content);
|
||||
}
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
UpdateStatusWithDispatcher(DownloadTaskStatus.EndedCancelled);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
UpdateErrorWithDispatcher(ex.Message);
|
||||
UpdateStatusWithDispatcher(DownloadTaskStatus.EndedUnsuccessfully);
|
||||
|
||||
if (_settingsService.Data.Common.Notifications.OnUnsuccessful)
|
||||
{
|
||||
string title = _stringResourcesService.NotificationsResources.Get("OnSuccessfulTitle");
|
||||
content.Add($"{_stringResourcesService.NotificationsResources.Get("Message")}: {ex.Message}");
|
||||
_notificationsService.SendNotification(title, content);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (Status != DownloadTaskStatus.EndedUnsuccessfully || _settingsService.Data.Common.DeleteTempOnError)
|
||||
{
|
||||
Directory.Delete(tempDirectory, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateStatusWithDispatcher(DownloadTaskStatus status) => _dispatcherQueue.TryEnqueue(() => Status = status);
|
||||
|
||||
private void UpdateProgressWithDispatcher(double progress) => _dispatcherQueue.TryEnqueue(() => Progress = progress);
|
||||
|
||||
private void UpdateErrorWithDispatcher(string message) => _dispatcherQueue.TryEnqueue(() => Error = message);
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user