From 6c37cedaf3bb5ab5c00efe0b9eef0eb78f7c76a7 Mon Sep 17 00:00:00 2001 From: ScrubN <72096833+ScrubN@users.noreply.github.com> Date: Mon, 20 Nov 2023 02:12:57 -0500 Subject: [PATCH 1/2] Support downloading audio from twitch vods --- .../Modes/Arguments/VideoDownloadArgs.cs | 2 +- TwitchDownloaderCLI/Modes/DownloadVideo.cs | 15 ++++++++++++++- TwitchDownloaderCore/TwitchHelper.cs | 2 +- TwitchDownloaderCore/VideoDownloader.cs | 4 ++-- TwitchDownloaderWPF/PageVodDownload.xaml.cs | 4 ++-- 5 files changed, 20 insertions(+), 7 deletions(-) diff --git a/TwitchDownloaderCLI/Modes/Arguments/VideoDownloadArgs.cs b/TwitchDownloaderCLI/Modes/Arguments/VideoDownloadArgs.cs index 33de037e..9acd96d1 100644 --- a/TwitchDownloaderCLI/Modes/Arguments/VideoDownloadArgs.cs +++ b/TwitchDownloaderCLI/Modes/Arguments/VideoDownloadArgs.cs @@ -8,7 +8,7 @@ public class VideoDownloadArgs : ITwitchDownloaderArgs [Option('u', "id", Required = true, HelpText = "The ID or URL of the VOD to download.")] public string Id { get; set; } - [Option('o', "output", Required = true, HelpText = "Path to output file.")] + [Option('o', "output", Required = true, HelpText = "Path to output file. File extension will be used to determine download type. Valid extensions are: .mp4 and .m4a.")] public string OutputFile { get; set; } [Option('q', "quality", HelpText = "The quality the program will attempt to download.")] diff --git a/TwitchDownloaderCLI/Modes/DownloadVideo.cs b/TwitchDownloaderCLI/Modes/DownloadVideo.cs index 0f96a4b0..b7a1574f 100644 --- a/TwitchDownloaderCLI/Modes/DownloadVideo.cs +++ b/TwitchDownloaderCLI/Modes/DownloadVideo.cs @@ -38,6 +38,14 @@ private static VideoDownloadOptions GetDownloadOptions(VideoDownloadArgs inputOp Environment.Exit(1); } + if (!Path.HasExtension(inputOptions.OutputFile) && inputOptions.Quality is { Length: > 0 }) + { + if (char.IsDigit(inputOptions.Quality[0])) + inputOptions.OutputFile += ".mp4"; + else if (char.ToLower(inputOptions.Quality[0]) is 'a') + inputOptions.OutputFile += ".m4a"; + } + VideoDownloadOptions downloadOptions = new() { DownloadThreads = inputOptions.DownloadThreads, @@ -45,7 +53,12 @@ private static VideoDownloadOptions GetDownloadOptions(VideoDownloadArgs inputOp Id = int.Parse(vodIdMatch.ValueSpan), Oauth = inputOptions.Oauth, Filename = inputOptions.OutputFile, - Quality = inputOptions.Quality, + Quality = Path.GetExtension(inputOptions.OutputFile)!.ToLower() switch + { + ".mp4" => inputOptions.Quality, + ".m4a" => "Audio", + _ => throw new ArgumentException("Only MP4 and M4A audio files are supported.") + }, CropBeginning = inputOptions.CropBeginningTime > 0.0, CropBeginningTime = inputOptions.CropBeginningTime, CropEnding = inputOptions.CropEndingTime > 0.0, diff --git a/TwitchDownloaderCore/TwitchHelper.cs b/TwitchDownloaderCore/TwitchHelper.cs index 54d5b372..06fc4934 100644 --- a/TwitchDownloaderCore/TwitchHelper.cs +++ b/TwitchDownloaderCore/TwitchHelper.cs @@ -58,7 +58,7 @@ public static async Task GetVideoPlaylist(int videoId, string token, s { var request = new HttpRequestMessage() { - RequestUri = new Uri($"http://usher.ttvnw.net/vod/{videoId}?nauth={token}&nauthsig={sig}&allow_source=true&player=twitchweb"), + RequestUri = new Uri($"http://usher.ttvnw.net/vod/{videoId}?nauth={token}&nauthsig={sig}&allow_audio_only=true&allow_source=true&player=twitchweb"), Method = HttpMethod.Get }; request.Headers.Add("Client-ID", "kimne78kx3ncx6brgo4mv6wki5h1ko"); diff --git a/TwitchDownloaderCore/VideoDownloader.cs b/TwitchDownloaderCore/VideoDownloader.cs index bd604ff2..ac8fed2c 100644 --- a/TwitchDownloaderCore/VideoDownloader.cs +++ b/TwitchDownloaderCore/VideoDownloader.cs @@ -585,9 +585,9 @@ private static async Task DownloadVideoPartAsync(HttpClient httpClient, Uri base } } - if (downloadOptions.Quality != null && videoQualities.Any(x => x.Key.StartsWith(downloadOptions.Quality))) + if (downloadOptions.Quality != null && videoQualities.Any(x => x.Key.StartsWith(downloadOptions.Quality, StringComparison.OrdinalIgnoreCase))) { - return videoQualities.Last(x => x.Key.StartsWith(downloadOptions.Quality)).Value; + return videoQualities.Last(x => x.Key.StartsWith(downloadOptions.Quality, StringComparison.OrdinalIgnoreCase)).Value; } // Unable to find specified quality, defaulting to highest quality diff --git a/TwitchDownloaderWPF/PageVodDownload.xaml.cs b/TwitchDownloaderWPF/PageVodDownload.xaml.cs index 98717176..734e0863 100644 --- a/TwitchDownloaderWPF/PageVodDownload.xaml.cs +++ b/TwitchDownloaderWPF/PageVodDownload.xaml.cs @@ -207,7 +207,7 @@ public VideoDownloadOptions GetOptions(string filename, string folder) Filename = filename ?? Path.Combine(folder, FilenameService.GetFilename(Settings.Default.TemplateVod, textTitle.Text, currentVideoId.ToString(), currentVideoTime, textStreamer.Text, checkStart.IsChecked == true ? new TimeSpan((int)numStartHour.Value, (int)numStartMinute.Value, (int)numStartSecond.Value) : TimeSpan.Zero, checkEnd.IsChecked == true ? new TimeSpan((int)numEndHour.Value, (int)numEndMinute.Value, (int)numEndSecond.Value) : vodLength, - viewCount.ToString(), game) + ".mp4"), + viewCount.ToString(), game) + (comboQuality.Text.Contains("Audio", StringComparison.OrdinalIgnoreCase) ? ".m4a" : ".mp4")), Oauth = TextOauth.Text, Quality = GetQualityWithoutSize(comboQuality.Text).ToString(), Id = currentVideoId, @@ -402,7 +402,7 @@ private async void SplitBtnDownloader_Click(object sender, RoutedEventArgs e) SaveFileDialog saveFileDialog = new SaveFileDialog { - Filter = "MP4 Files | *.mp4", + Filter = comboQuality.Text.Contains("Audio", StringComparison.OrdinalIgnoreCase) ? "M4A Files | *.m4a" : "MP4 Files | *.mp4", FileName = FilenameService.GetFilename(Settings.Default.TemplateVod, textTitle.Text, currentVideoId.ToString(), currentVideoTime, textStreamer.Text, checkStart.IsChecked == true ? new TimeSpan((int)numStartHour.Value, (int)numStartMinute.Value, (int)numStartSecond.Value) : TimeSpan.Zero, checkEnd.IsChecked == true ? new TimeSpan((int)numEndHour.Value, (int)numEndMinute.Value, (int)numEndSecond.Value) : vodLength, From 477589a1d537df1cbb27d667d60340f765d992cd Mon Sep 17 00:00:00 2001 From: ScrubN <72096833+ScrubN@users.noreply.github.com> Date: Mon, 20 Nov 2023 02:13:39 -0500 Subject: [PATCH 2/2] Update CLI README --- TwitchDownloaderCLI/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TwitchDownloaderCLI/README.md b/TwitchDownloaderCLI/README.md index 15ba5328..74735c81 100644 --- a/TwitchDownloaderCLI/README.md +++ b/TwitchDownloaderCLI/README.md @@ -21,7 +21,7 @@ A cross platform command line tool that can do the main functions of the GUI pro The ID or URL of the VOD to download. **-o / --output (REQUIRED)** -File the program will output to. +File the program will output to. File extension will be used to determine download type. Valid extensions are: `.mp4` and `.m4a`. **-q / --quality** The quality the program will attempt to download, for example "1080p60", if not found will download highest quality stream.