diff --git a/TwitchDownloaderCLI/Modes/Arguments/ClipDownloadArgs.cs b/TwitchDownloaderCLI/Modes/Arguments/ClipDownloadArgs.cs index d8374a18..ec06dd27 100644 --- a/TwitchDownloaderCLI/Modes/Arguments/ClipDownloadArgs.cs +++ b/TwitchDownloaderCLI/Modes/Arguments/ClipDownloadArgs.cs @@ -18,6 +18,15 @@ public class ClipDownloadArgs : ITwitchDownloaderArgs [Option("bandwidth", Default = -1, HelpText = "The maximum bandwidth the clip downloader is allowed to use in kibibytes per second (KiB/s), or -1 for no maximum.")] public int ThrottleKib { get; set; } + [Option("encode-metadata", Default = true, HelpText = "Uses FFmpeg to add metadata to the clip output file.")] + public bool? EncodeMetadata { get; set; } + + [Option("ffmpeg-path", HelpText = "Path to FFmpeg executable.")] + public string FfmpegPath { get; set; } + + [Option("temp-path", Default = "", HelpText = "Path to temporary caching folder.")] + public string TempFolder { get; set; } + [Option("banner", Default = true, HelpText = "Displays a banner containing version and copyright information.")] public bool? ShowBanner { get; set; } } diff --git a/TwitchDownloaderCLI/Modes/DownloadClip.cs b/TwitchDownloaderCLI/Modes/DownloadClip.cs index 62538574..fa9191f1 100644 --- a/TwitchDownloaderCLI/Modes/DownloadClip.cs +++ b/TwitchDownloaderCLI/Modes/DownloadClip.cs @@ -1,6 +1,8 @@ using System; using System.Text.RegularExpressions; +using System.Threading; using TwitchDownloaderCLI.Modes.Arguments; +using TwitchDownloaderCLI.Tools; using TwitchDownloaderCore; using TwitchDownloaderCore.Options; @@ -10,10 +12,18 @@ internal static class DownloadClip { internal static void Download(ClipDownloadArgs inputOptions) { + if (inputOptions.EncodeMetadata == true) + { + FfmpegHandler.DetectFfmpeg(inputOptions.FfmpegPath); + } + + Progress progress = new(); + progress.ProgressChanged += ProgressHandler.Progress_ProgressChanged; + var downloadOptions = GetDownloadOptions(inputOptions); - ClipDownloader clipDownloader = new(downloadOptions); - clipDownloader.DownloadAsync().Wait(); + ClipDownloader clipDownloader = new(downloadOptions, progress); + clipDownloader.DownloadAsync(new CancellationToken()).Wait(); } private static ClipDownloadOptions GetDownloadOptions(ClipDownloadArgs inputOptions) @@ -37,7 +47,10 @@ private static ClipDownloadOptions GetDownloadOptions(ClipDownloadArgs inputOpti Id = clipIdMatch.Value, Filename = inputOptions.OutputFile, Quality = inputOptions.Quality, - ThrottleKib = inputOptions.ThrottleKib + ThrottleKib = inputOptions.ThrottleKib, + FfmpegPath = inputOptions.FfmpegPath, + EncodeMetadata = inputOptions.EncodeMetadata!.Value, + TempFolder = inputOptions.TempFolder }; return downloadOptions; diff --git a/TwitchDownloaderCLI/README.md b/TwitchDownloaderCLI/README.md index 895ef074..6dfa94db 100644 --- a/TwitchDownloaderCLI/README.md +++ b/TwitchDownloaderCLI/README.md @@ -67,6 +67,15 @@ The quality the program will attempt to download, for example "1080p60", if not **--bandwidth** (Default: `-1`) The maximum bandwidth the clip downloader is allowed to use in kibibytes per second (KiB/s), or `-1` for no maximum. +**--encode-metadata** +(Default: `true`) Uses FFmpeg to add metadata to the clip output file. + +**--ffmpeg-path** +Path to FFmpeg executable. + +**--temp-path** +Path to temporary folder for cache. + **--banner** (Default: `true`) Displays a banner containing version and copyright information. diff --git a/TwitchDownloaderCore/ClipDownloader.cs b/TwitchDownloaderCore/ClipDownloader.cs index 62e88303..68ea8498 100644 --- a/TwitchDownloaderCore/ClipDownloader.cs +++ b/TwitchDownloaderCore/ClipDownloader.cs @@ -1,5 +1,5 @@ using System; -using System.Collections.Generic; +using System.Diagnostics; using System.IO; using System.Linq; using System.Net.Http; @@ -8,23 +8,72 @@ using System.Web; using TwitchDownloaderCore.Options; using TwitchDownloaderCore.Tools; -using TwitchDownloaderCore.TwitchObjects.Gql; namespace TwitchDownloaderCore { public sealed class ClipDownloader { private readonly ClipDownloadOptions downloadOptions; - private static HttpClient httpClient = new HttpClient(); + private readonly IProgress _progress; + private static readonly HttpClient HttpClient = new(); - public ClipDownloader(ClipDownloadOptions DownloadOptions) + public ClipDownloader(ClipDownloadOptions clipDownloadOptions, IProgress progress) { - downloadOptions = DownloadOptions; + downloadOptions = clipDownloadOptions; + _progress = progress; + downloadOptions.TempFolder = Path.Combine( + string.IsNullOrWhiteSpace(downloadOptions.TempFolder) ? Path.GetTempPath() : downloadOptions.TempFolder, + "TwitchDownloader"); } - public async Task DownloadAsync(CancellationToken cancellationToken = new()) + public async Task DownloadAsync(CancellationToken cancellationToken) { - List listLinks = await TwitchHelper.GetClipLinks(downloadOptions.Id); + _progress.Report(new ProgressReport(ReportType.NewLineStatus, "Fetching Clip Info")); + + var downloadUrl = await GetDownloadUrl(); + + cancellationToken.ThrowIfCancellationRequested(); + + var clipDirectory = Directory.GetParent(Path.GetFullPath(downloadOptions.Filename))!; + if (!clipDirectory.Exists) + { + TwitchHelper.CreateDirectory(clipDirectory.FullName); + } + + _progress.Report(new ProgressReport(ReportType.NewLineStatus, "Downloading Clip")); + + if (!downloadOptions.EncodeMetadata) + { + await DownloadFileTaskAsync(downloadUrl, downloadOptions.Filename, downloadOptions.ThrottleKib, cancellationToken); + _progress.Report(new ProgressReport(100)); + return; + } + + if (!Directory.Exists(downloadOptions.TempFolder)) + { + TwitchHelper.CreateDirectory(downloadOptions.TempFolder); + } + + var tempFile = Path.Combine(downloadOptions.TempFolder, $"clip_{DateTimeOffset.Now.ToUnixTimeMilliseconds()}_{Path.GetRandomFileName()}"); + try + { + await DownloadFileTaskAsync(downloadUrl, tempFile, downloadOptions.ThrottleKib, cancellationToken); + + _progress.Report(new ProgressReport(ReportType.NewLineStatus, "Encoding Clip Metadata")); + + await EncodeClipMetadata(tempFile, downloadOptions.Filename, cancellationToken); + + _progress.Report(new ProgressReport(100)); + } + finally + { + File.Delete(tempFile); + } + } + + private async Task GetDownloadUrl() + { + var listLinks = await TwitchHelper.GetClipLinks(downloadOptions.Id); if (listLinks[0].data.clip.playbackAccessToken is null) { @@ -51,31 +100,59 @@ public ClipDownloader(ClipDownloadOptions DownloadOptions) downloadUrl = listLinks[0].data.clip.videoQualities.First().sourceURL; } - downloadUrl += "?sig=" + listLinks[0].data.clip.playbackAccessToken.signature + "&token=" + HttpUtility.UrlEncode(listLinks[0].data.clip.playbackAccessToken.value); - - cancellationToken.ThrowIfCancellationRequested(); - - var clipDirectory = Directory.GetParent(Path.GetFullPath(downloadOptions.Filename))!; - if (!clipDirectory.Exists) - { - TwitchHelper.CreateDirectory(clipDirectory.FullName); - } + return downloadUrl + "?sig=" + listLinks[0].data.clip.playbackAccessToken.signature + "&token=" + HttpUtility.UrlEncode(listLinks[0].data.clip.playbackAccessToken.value); + } - var request = new HttpRequestMessage(HttpMethod.Get, downloadUrl); - using var response = await httpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false); + private static async Task DownloadFileTaskAsync(string url, string destinationFile, int throttleKib, CancellationToken cancellationToken) + { + var request = new HttpRequestMessage(HttpMethod.Get, url); + using var response = await HttpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false); response.EnsureSuccessStatusCode(); - if (downloadOptions.ThrottleKib == -1) + if (throttleKib == -1) { - await using var fs = new FileStream(downloadOptions.Filename, FileMode.Create, FileAccess.Write, FileShare.Read); + await using var fs = new FileStream(destinationFile, FileMode.Create, FileAccess.Write, FileShare.Read); await response.Content.CopyToAsync(fs, cancellationToken).ConfigureAwait(false); } else { - await using var throttledStream = new ThrottledStream(await response.Content.ReadAsStreamAsync(cancellationToken), downloadOptions.ThrottleKib); - await using var fs = new FileStream(downloadOptions.Filename, FileMode.Create, FileAccess.Write, FileShare.Read); + await using var throttledStream = new ThrottledStream(await response.Content.ReadAsStreamAsync(cancellationToken), throttleKib); + await using var fs = new FileStream(destinationFile, FileMode.Create, FileAccess.Write, FileShare.Read); await throttledStream.CopyToAsync(fs, cancellationToken).ConfigureAwait(false); } } + + private async Task EncodeClipMetadata(string inputFile, string destinationFile, CancellationToken cancellationToken) + { + var metadataFile = $"{Path.GetFileNameWithoutExtension(inputFile)}_metadata{Path.GetExtension(inputFile)}"; + var clipInfo = await TwitchHelper.GetClipInfo(downloadOptions.Id); + + try + { + await FfmpegMetadata.SerializeAsync(metadataFile, clipInfo.data.clip.broadcaster.displayName, downloadOptions.Id, clipInfo.data.clip.title, clipInfo.data.clip.createdAt, + clipInfo.data.clip.viewCount, cancellationToken: cancellationToken); + + var process = new Process + { + StartInfo = + { + FileName = downloadOptions.FfmpegPath, + Arguments = $"-i \"{inputFile}\" -i \"{metadataFile}\" -map_metadata 1 -c copy \"{destinationFile}\"", + UseShellExecute = false, + CreateNoWindow = true, + RedirectStandardInput = false, + RedirectStandardOutput = true, + RedirectStandardError = true + } + }; + + process.Start(); + await process.WaitForExitAsync(cancellationToken); + } + finally + { + File.Delete(metadataFile); + } + } } } diff --git a/TwitchDownloaderCore/Options/ClipDownloadOptions.cs b/TwitchDownloaderCore/Options/ClipDownloadOptions.cs index 912f5f26..9f8c6ce9 100644 --- a/TwitchDownloaderCore/Options/ClipDownloadOptions.cs +++ b/TwitchDownloaderCore/Options/ClipDownloadOptions.cs @@ -1,8 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace TwitchDownloaderCore.Options +namespace TwitchDownloaderCore.Options { public class ClipDownloadOptions { @@ -10,5 +6,8 @@ public class ClipDownloadOptions public string Quality { get; set; } public string Filename { get; set; } public int ThrottleKib { get; set; } + public string TempFolder { get; set; } + public bool EncodeMetadata { get; set; } + public string FfmpegPath { get; set; } } -} +} \ No newline at end of file diff --git a/TwitchDownloaderCore/Tools/FfmpegMetadata.cs b/TwitchDownloaderCore/Tools/FfmpegMetadata.cs index aafff4b2..f8aa3851 100644 --- a/TwitchDownloaderCore/Tools/FfmpegMetadata.cs +++ b/TwitchDownloaderCore/Tools/FfmpegMetadata.cs @@ -13,30 +13,36 @@ public static class FfmpegMetadata { private const string LINE_FEED = "\u000A"; - public static async Task SerializeAsync(string filePath, string streamerName, double startOffsetSeconds, int videoId, string videoTitle, DateTime videoCreation, List videoMomentEdges = default, CancellationToken cancellationToken = default) + public static async Task SerializeAsync(string filePath, string streamerName, string videoId, string videoTitle, DateTime videoCreation, int viewCount, double startOffsetSeconds = default, List videoMomentEdges = default, CancellationToken cancellationToken = default) { await using var fs = new FileStream(filePath, FileMode.CreateNew, FileAccess.ReadWrite, FileShare.None); await using var sw = new StreamWriter(fs) { NewLine = LINE_FEED }; - await SerializeGlobalMetadata(sw, streamerName, videoId, videoTitle, videoCreation); + await SerializeGlobalMetadata(sw, streamerName, videoId, videoTitle, videoCreation, viewCount); await fs.FlushAsync(cancellationToken); await SerializeChapters(sw, videoMomentEdges, startOffsetSeconds); await fs.FlushAsync(cancellationToken); } - private static async Task SerializeGlobalMetadata(StreamWriter sw, string streamerName, int videoId, string videoTitle, DateTime videoCreation) + private static async Task SerializeGlobalMetadata(StreamWriter sw, string streamerName, string videoId, string videoTitle, DateTime videoCreation, int viewCount) { await sw.WriteLineAsync(";FFMETADATA1"); - await sw.WriteLineAsync($"title={SanitizeKeyValue(videoTitle)} ({videoId})"); + await sw.WriteLineAsync($"title={SanitizeKeyValue(videoTitle)} ({SanitizeKeyValue(videoId)})"); await sw.WriteLineAsync($"artist={SanitizeKeyValue(streamerName)}"); await sw.WriteLineAsync($"date={videoCreation:yyyy}"); // The 'date' key becomes 'year' in most formats await sw.WriteLineAsync(@$"comment=Originally aired: {SanitizeKeyValue(videoCreation.ToString("u"))}\"); - await sw.WriteLineAsync($"Video id: {videoId}"); + await sw.WriteLineAsync(@$"Video id: {SanitizeKeyValue(videoId)}\"); + await sw.WriteLineAsync($"Views: {viewCount}"); } private static async Task SerializeChapters(StreamWriter sw, List videoMomentEdges, double startOffsetSeconds) { + if (videoMomentEdges is null) + { + return; + } + // Note: FFmpeg automatically handles out of range chapters for us var startOffsetMillis = (int)(startOffsetSeconds * 1000); foreach (var momentEdge in videoMomentEdges) diff --git a/TwitchDownloaderCore/VideoDownloader.cs b/TwitchDownloaderCore/VideoDownloader.cs index 21960172..cc0b7976 100644 --- a/TwitchDownloaderCore/VideoDownloader.cs +++ b/TwitchDownloaderCore/VideoDownloader.cs @@ -96,8 +96,8 @@ public async Task DownloadAsync(CancellationToken cancellationToken) double seekDuration = Math.Round(downloadOptions.CropEndingTime - seekTime); string metadataPath = Path.Combine(downloadFolder, "metadata.txt"); - await FfmpegMetadata.SerializeAsync(metadataPath, videoInfoResponse.data.video.owner.displayName, startOffset, downloadOptions.Id, - videoInfoResponse.data.video.title, videoInfoResponse.data.video.createdAt, videoChapterResponse.data.video.moments.edges, cancellationToken); + await FfmpegMetadata.SerializeAsync(metadataPath, videoInfoResponse.data.video.owner.displayName, downloadOptions.Id.ToString(), videoInfoResponse.data.video.title, + videoInfoResponse.data.video.createdAt, videoInfoResponse.data.video.viewCount, startOffset, videoChapterResponse.data.video.moments.edges, cancellationToken); var finalizedFileDirectory = Directory.GetParent(Path.GetFullPath(downloadOptions.Filename))!; if (!finalizedFileDirectory.Exists) diff --git a/TwitchDownloaderWPF/App.config b/TwitchDownloaderWPF/App.config index f80fb568..1493b5c6 100644 --- a/TwitchDownloaderWPF/App.config +++ b/TwitchDownloaderWPF/App.config @@ -242,6 +242,9 @@ False + + True + \ No newline at end of file diff --git a/TwitchDownloaderWPF/PageClipDownload.xaml b/TwitchDownloaderWPF/PageClipDownload.xaml index 6ac2fffb..3d2c6903 100644 --- a/TwitchDownloaderWPF/PageClipDownload.xaml +++ b/TwitchDownloaderWPF/PageClipDownload.xaml @@ -67,10 +67,12 @@ + + diff --git a/TwitchDownloaderWPF/PageClipDownload.xaml.cs b/TwitchDownloaderWPF/PageClipDownload.xaml.cs index cbaeac7e..02e43618 100644 --- a/TwitchDownloaderWPF/PageClipDownload.xaml.cs +++ b/TwitchDownloaderWPF/PageClipDownload.xaml.cs @@ -90,9 +90,7 @@ private async Task GetClipInfo() } comboQuality.SelectedIndex = 0; - comboQuality.IsEnabled = true; - SplitBtnDownload.IsEnabled = true; - btnGetInfo.IsEnabled = true; + SetEnabled(true); } catch (Exception ex) { @@ -102,8 +100,8 @@ private async Task GetClipInfo() { MessageBox.Show(ex.ToString(), Translations.Strings.VerboseErrorOutput, MessageBoxButton.OK, MessageBoxImage.Error); } - btnGetInfo.IsEnabled = true; } + btnGetInfo.IsEnabled = true; } private void UpdateActionButtons(bool isDownloading) @@ -136,8 +134,31 @@ private void AppendLog(string message) private void Page_Initialized(object sender, EventArgs e) { - comboQuality.IsEnabled = false; - SplitBtnDownload.IsEnabled = false; + SetEnabled(false); + CheckMetadata.IsChecked = Settings.Default.EncodeClipMetadata; + } + + private void SetEnabled(bool enabled) + { + comboQuality.IsEnabled = enabled; + SplitBtnDownload.IsEnabled = enabled; + CheckMetadata.IsEnabled = enabled; + } + + private void OnProgressChanged(ProgressReport progress) + { + switch (progress.ReportType) + { + case ReportType.Percent: + statusProgressBar.Value = (int)progress.Data; + break; + case ReportType.NewLineStatus or ReportType.SameLineStatus: + statusMessage.Text = (string)progress.Data; + break; + case ReportType.Log: + AppendLog((string)progress.Data); + break; + } } public void SetImage(string imageUri, bool isGif) @@ -191,8 +212,7 @@ private async void SplitBtnDownload_Click(object sender, RoutedEventArgs e) return; } - comboQuality.IsEnabled = false; - btnGetInfo.IsEnabled = false; + SetEnabled(false); ClipDownloadOptions downloadOptions = GetOptions(saveFileDialog.FileName); _cancellationTokenSource = new CancellationTokenSource(); @@ -202,7 +222,9 @@ private async void SplitBtnDownload_Click(object sender, RoutedEventArgs e) UpdateActionButtons(true); try { - await new ClipDownloader(downloadOptions).DownloadAsync(_cancellationTokenSource.Token); + var downloadProgress = new Progress(OnProgressChanged); + await new ClipDownloader(downloadOptions, downloadProgress) + .DownloadAsync(_cancellationTokenSource.Token); statusMessage.Text = Translations.Strings.StatusDone; SetImage("Images/ppHop.gif", true); @@ -238,6 +260,9 @@ private ClipDownloadOptions GetOptions(string fileName) ThrottleKib = Settings.Default.DownloadThrottleEnabled ? Settings.Default.MaximumBandwidthKib : -1, + TempFolder = Settings.Default.TempPath, + EncodeMetadata = CheckMetadata.IsChecked!.Value, + FfmpegPath = "ffmpeg", }; } @@ -264,6 +289,15 @@ private async void TextUrl_OnKeyDown(object sender, KeyEventArgs e) await GetClipInfo(); } } + + private void CheckMetadata_OnCheckStateChanged(object sender, RoutedEventArgs e) + { + if (IsInitialized) + { + Settings.Default.EncodeClipMetadata = CheckMetadata.IsChecked!.Value; + Settings.Default.Save(); + } + } } } diff --git a/TwitchDownloaderWPF/Properties/Settings.Designer.cs b/TwitchDownloaderWPF/Properties/Settings.Designer.cs index 1e059976..66d5e122 100644 --- a/TwitchDownloaderWPF/Properties/Settings.Designer.cs +++ b/TwitchDownloaderWPF/Properties/Settings.Designer.cs @@ -885,5 +885,17 @@ public bool AlternateMessageBackgrounds { this["AlternateMessageBackgrounds"] = value; } } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("True")] + public bool EncodeClipMetadata { + get { + return ((bool)(this["EncodeClipMetadata"])); + } + set { + this["EncodeClipMetadata"] = value; + } + } } } diff --git a/TwitchDownloaderWPF/Properties/Settings.settings b/TwitchDownloaderWPF/Properties/Settings.settings index 701d6825..39ca35c0 100644 --- a/TwitchDownloaderWPF/Properties/Settings.settings +++ b/TwitchDownloaderWPF/Properties/Settings.settings @@ -218,6 +218,9 @@ False + + True + diff --git a/TwitchDownloaderWPF/README.md b/TwitchDownloaderWPF/README.md index e46b96cd..0c89207d 100644 --- a/TwitchDownloaderWPF/README.md +++ b/TwitchDownloaderWPF/README.md @@ -57,6 +57,8 @@ To get started, input a valid link or ID to a clip. From there the the download **Quality**: Selects the quality of the clip before downloading. +**Encode Metadata**: Encodes clip metadata such as the airing date and clip ID into the final mp4 file using FFmpeg. + **Download**: Starts the download job. If instead you open the dropdown, you can send it to the [Task Queue](#task-queue) with the *Enqueue* option. The current download settings will be used in both scenarios. ### Chat Download diff --git a/TwitchDownloaderWPF/Translations/Strings.Designer.cs b/TwitchDownloaderWPF/Translations/Strings.Designer.cs index 88f1bd47..d48b9b2c 100644 --- a/TwitchDownloaderWPF/Translations/Strings.Designer.cs +++ b/TwitchDownloaderWPF/Translations/Strings.Designer.cs @@ -653,6 +653,15 @@ public static string EmoteSpacingScale { } } + /// + /// Looks up a localized string similar to Encode Metadata:. + /// + public static string EncodeClipMetadata { + get { + return ResourceManager.GetString("EncodeClipMetadata", resourceCulture); + } + } + /// /// Looks up a localized string similar to Enqueue Download. /// @@ -708,7 +717,7 @@ public static string FfmpegInputArguments { } /// - /// Looks up a localized string similar to Click here to learn about Ffmpeg options. + /// Looks up a localized string similar to Click here to learn about FFmpeg options. /// public static string FfmpegOptionsHyperlink { get { @@ -1176,7 +1185,7 @@ public static string RenderTabEncoding { } /// - /// Looks up a localized string similar to Ffmpeg. + /// Looks up a localized string similar to FFmpeg. /// public static string RenderTabFfmpeg { get { diff --git a/TwitchDownloaderWPF/Translations/Strings.es.resx b/TwitchDownloaderWPF/Translations/Strings.es.resx index cbd5423d..4f80b6fc 100644 --- a/TwitchDownloaderWPF/Translations/Strings.es.resx +++ b/TwitchDownloaderWPF/Translations/Strings.es.resx @@ -763,4 +763,7 @@ Alterna el color de fondo de cada mensaje de chat para ayudar a distinguirlos. + + Inclure les métadonnées: + \ No newline at end of file diff --git a/TwitchDownloaderWPF/Translations/Strings.fr.resx b/TwitchDownloaderWPF/Translations/Strings.fr.resx index d41dc472..0fedcbdb 100644 --- a/TwitchDownloaderWPF/Translations/Strings.fr.resx +++ b/TwitchDownloaderWPF/Translations/Strings.fr.resx @@ -762,4 +762,7 @@ Alterne la couleur d'arrière-plan de tous les messages de chat impairs pour les différencier. + + Encode Metadata: + \ No newline at end of file diff --git a/TwitchDownloaderWPF/Translations/Strings.pl.resx b/TwitchDownloaderWPF/Translations/Strings.pl.resx index b97f3de9..eee61889 100644 --- a/TwitchDownloaderWPF/Translations/Strings.pl.resx +++ b/TwitchDownloaderWPF/Translations/Strings.pl.resx @@ -762,4 +762,7 @@ Alternates the background color of every other chat message to help tell them apart. + + Encode Metadata: + \ No newline at end of file diff --git a/TwitchDownloaderWPF/Translations/Strings.resx b/TwitchDownloaderWPF/Translations/Strings.resx index 39fa3d4f..1e176954 100644 --- a/TwitchDownloaderWPF/Translations/Strings.resx +++ b/TwitchDownloaderWPF/Translations/Strings.resx @@ -761,4 +761,7 @@ Alternates the background color of every other chat message to help tell them apart. + + Encode Metadata: + \ No newline at end of file diff --git a/TwitchDownloaderWPF/Translations/Strings.ru.resx b/TwitchDownloaderWPF/Translations/Strings.ru.resx index 5fe8b395..edbefc61 100644 --- a/TwitchDownloaderWPF/Translations/Strings.ru.resx +++ b/TwitchDownloaderWPF/Translations/Strings.ru.resx @@ -762,4 +762,7 @@ Alternates the background color of every other chat message to help tell them apart. + + Encode Metadata: + \ No newline at end of file diff --git a/TwitchDownloaderWPF/Translations/Strings.tr.resx b/TwitchDownloaderWPF/Translations/Strings.tr.resx index ad86426c..d6741d90 100644 --- a/TwitchDownloaderWPF/Translations/Strings.tr.resx +++ b/TwitchDownloaderWPF/Translations/Strings.tr.resx @@ -763,4 +763,7 @@ Alternates the background color of every other chat message to help tell them apart. + + Encode Metadata: + \ No newline at end of file diff --git a/TwitchDownloaderWPF/Translations/Strings.zh.resx b/TwitchDownloaderWPF/Translations/Strings.zh.resx index 5e10962e..1de19502 100644 --- a/TwitchDownloaderWPF/Translations/Strings.zh.resx +++ b/TwitchDownloaderWPF/Translations/Strings.zh.resx @@ -761,4 +761,7 @@ Alternates the background color of every other chat message to help tell them apart. + + Encode Metadata: + \ No newline at end of file diff --git a/TwitchDownloaderWPF/TwitchTasks/ClipDownloadTask.cs b/TwitchDownloaderWPF/TwitchTasks/ClipDownloadTask.cs index e5518b0d..a768cb62 100644 --- a/TwitchDownloaderWPF/TwitchTasks/ClipDownloadTask.cs +++ b/TwitchDownloaderWPF/TwitchTasks/ClipDownloadTask.cs @@ -56,9 +56,10 @@ public async Task RunAsync() return; } - ClipDownloader downloader = new ClipDownloader(DownloadOptions); + Progress progress = new Progress(); progress.ProgressChanged += Progress_ProgressChanged; + ClipDownloader downloader = new ClipDownloader(DownloadOptions, progress); ChangeStatus(TwitchTaskStatus.Running); try { diff --git a/TwitchDownloaderWPF/WindowQueueOptions.xaml.cs b/TwitchDownloaderWPF/WindowQueueOptions.xaml.cs index 93874879..1ff65b10 100644 --- a/TwitchDownloaderWPF/WindowQueueOptions.xaml.cs +++ b/TwitchDownloaderWPF/WindowQueueOptions.xaml.cs @@ -204,6 +204,9 @@ private async void btnQueue_Click(object sender, RoutedEventArgs e) downloadOptions.ThrottleKib = Settings.Default.DownloadThrottleEnabled ? Settings.Default.MaximumBandwidthKib : -1; + downloadOptions.TempFolder = Settings.Default.TempPath; + downloadOptions.EncodeMetadata = clipPage.CheckMetadata.IsChecked!.Value; + downloadOptions.FfmpegPath = "ffmpeg"; downloadTask.DownloadOptions = downloadOptions; downloadTask.Info.Title = clipPage.textTitle.Text; downloadTask.Info.Thumbnail = clipPage.imgThumbnail.Source; @@ -433,6 +436,9 @@ private async void btnQueue_Click(object sender, RoutedEventArgs e) downloadOptions.ThrottleKib = Settings.Default.DownloadThrottleEnabled ? Settings.Default.MaximumBandwidthKib : -1; + downloadOptions.TempFolder = Settings.Default.TempPath; + downloadOptions.EncodeMetadata = Settings.Default.EncodeClipMetadata; + downloadOptions.FfmpegPath = "ffmpeg"; downloadTask.DownloadOptions = downloadOptions; downloadTask.Info.Title = taskData.Title; downloadTask.Info.Thumbnail = taskData.Thumbnail;