Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add new options and fixes #984

Closed
wants to merge 29 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
ead6379
Update VideoDownloadArgs.cs
superbonaci Mar 8, 2024
4cc2088
Update DownloadVideo.cs
superbonaci Mar 8, 2024
415a710
Update README.md
superbonaci Mar 8, 2024
ad9fe57
Update VideoDownloadOptions.cs
superbonaci Mar 8, 2024
ece0bc5
Update VideoDownloader.cs
superbonaci Mar 8, 2024
7a68f9c
Merge pull request #1 from superbonaci/superbonaci-improvements-1
superbonaci Mar 8, 2024
702e6bc
Merge pull request #2 from superbonaci/superbonaci-patch-1
superbonaci Mar 8, 2024
8be69af
Merge pull request #3 from superbonaci/superbonaci-patch-2
superbonaci Mar 8, 2024
8199263
Merge pull request #4 from superbonaci/superbonaci-patch-3
superbonaci Mar 8, 2024
10a6506
Merge pull request #5 from superbonaci/superbonaci-patch-4
superbonaci Mar 8, 2024
458f83d
Update VideoDownloader.cs
superbonaci Mar 8, 2024
8674f0f
Update VideoDownloader.cs
superbonaci Mar 8, 2024
d8ab3e1
Update DownloadVideo.cs
superbonaci Mar 8, 2024
8cd8845
Update DownloadVideo.cs
superbonaci Mar 8, 2024
6078ca4
Update DownloadVideo.cs
superbonaci Mar 8, 2024
e7e9c3f
Update README.md
superbonaci Mar 8, 2024
73c7e5e
Update README.md
superbonaci Mar 8, 2024
6c183a3
Update VideoDownloader.cs
superbonaci Mar 8, 2024
ecacc60
Update VideoDownloader.cs
superbonaci Mar 8, 2024
1c0c101
Update VideoDownloader.cs
superbonaci Mar 8, 2024
1a6eff8
Update VideoDownloader.cs
superbonaci Mar 8, 2024
34b3047
Update ChatDownloadArgs.cs
superbonaci Mar 8, 2024
827c54f
Update ChatRenderArgs.cs
superbonaci Mar 8, 2024
d0dbe20
Update ChatUpdateArgs.cs
superbonaci Mar 8, 2024
35e1c72
Update README.md
superbonaci Mar 8, 2024
3ec3a5e
Update TsMerger.cs
superbonaci Mar 8, 2024
9feb9db
Update VideoDownloader.cs
superbonaci Mar 8, 2024
47cc56d
Update ClipDownloader.cs
superbonaci Mar 10, 2024
ad4d54a
Update ChatDownloader.cs
superbonaci Mar 10, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions TwitchDownloaderCLI/Modes/Arguments/ChatDownloadArgs.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using CommandLine;
using CommandLine;
using TwitchDownloaderCore.Tools;

namespace TwitchDownloaderCLI.Modes.Arguments
Expand All @@ -15,10 +15,10 @@ public class ChatDownloadArgs : ITwitchDownloaderArgs
[Option("compression", Default = ChatCompression.None, HelpText = "Compresses an output json chat file using a specified compression, usually resulting in 40-90% size reductions. Valid values are: None, Gzip.")]
public ChatCompression Compression { get; set; }

[Option('b', "beginning", HelpText = "Time in seconds to crop beginning.")]
[Option('b', "beginning", HelpText = "Time in seconds where the crop begins.")]
public double CropBeginningTime { get; set; }

[Option('e', "ending", HelpText = "Time in seconds to crop ending.")]
[Option('e', "ending", HelpText = "Time in seconds where the crop ends.")]
public double CropEndingTime { get; set; }

[Option('E', "embed-images", Default = false, HelpText = "Embed first party emotes, badges, and cheermotes into the chat download for offline rendering.")]
Expand Down Expand Up @@ -48,4 +48,4 @@ public class ChatDownloadArgs : ITwitchDownloaderArgs
[Option("banner", Default = true, HelpText = "Displays a banner containing version and copyright information.")]
public bool? ShowBanner { get; set; }
}
}
}
8 changes: 4 additions & 4 deletions TwitchDownloaderCLI/Modes/Arguments/ChatRenderArgs.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using CommandLine;
using CommandLine;

namespace TwitchDownloaderCLI.Modes.Arguments
{
Expand Down Expand Up @@ -26,10 +26,10 @@ public class ChatRenderArgs : ITwitchDownloaderArgs
[Option('h', "chat-height", Default = 600, HelpText = "Height of chat render.")]
public int ChatHeight { get; set; }

[Option('b', "beginning", Default = -1, HelpText = "Time in seconds to crop beginning of the render.")]
[Option('b', "beginning", Default = -1, HelpText = "Time in seconds where the crop begins.")]
public int CropBeginningTime { get; set; }

[Option('e', "ending", Default = -1, HelpText = "Time in seconds to crop ending of the render.")]
[Option('e', "ending", Default = -1, HelpText = "Time in seconds where the crop ends.")]
public int CropEndingTime { get; set; }

[Option("bttv", Default = true, HelpText = "Enable BTTV emotes.")]
Expand Down Expand Up @@ -155,4 +155,4 @@ public class ChatRenderArgs : ITwitchDownloaderArgs
[Option("banner", Default = true, HelpText = "Displays a banner containing version and copyright information.")]
public bool? ShowBanner { get; set; }
}
}
}
6 changes: 3 additions & 3 deletions TwitchDownloaderCLI/Modes/Arguments/ChatUpdateArgs.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using CommandLine;
using CommandLine;
using TwitchDownloaderCore.Tools;

namespace TwitchDownloaderCLI.Modes.Arguments
Expand All @@ -21,10 +21,10 @@ public class ChatUpdateArgs : ITwitchDownloaderArgs
[Option('R', "replace-embeds", Default = false, HelpText = "Replace all embedded emotes, badges, and cheermotes in the file. All embedded images will be overwritten!")]
public bool ReplaceEmbeds { get; set; }

[Option('b', "beginning", Default = -1, HelpText = "New time in seconds for chat beginning. Comments may be added but not removed. -1 = No crop.")]
[Option('b', "beginning", Default = -1, HelpText = "New time in seconds where the chat begins. Comments may be added but not removed. -1 = No crop.")]
public int CropBeginningTime { get; set; }

[Option('e', "ending", Default = -1, HelpText = "New time in seconds for chat ending. Comments may be added but not removed. -1 = No crop.")]
[Option('e', "ending", Default = -1, HelpText = "New time in seconds where the chat ends. Comments may be added but not removed. -1 = No crop.")]
public int CropEndingTime { get; set; }

[Option("bttv", Default = true, HelpText = "Enable BTTV embedding in chat download.")]
Expand Down
17 changes: 13 additions & 4 deletions TwitchDownloaderCLI/Modes/Arguments/VideoDownloadArgs.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using CommandLine;
using CommandLine;

namespace TwitchDownloaderCLI.Modes.Arguments
{
Expand All @@ -8,16 +8,25 @@ 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. File extension will be used to determine download type. Valid extensions are: .mp4 and .m4a.")]
[Option('o', "output", Required = false, 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.")]
public string Quality { get; set; }

[Option('b', "beginning", HelpText = "Time in seconds to crop beginning.")]
[Option('K', "cache", Required = false, HelpText = "Keep entire cache folder. Overrides \"-k\".")]
public bool KeepCache { get; set; }

[Option('k', "cache-noparts", Required = false, HelpText = "Keep cache folder except .ts parts.")]
public bool KeepCacheNoParts { get; set; }

[Option('F', "skip-storagecheck", HelpText = "Skip checking for free storage space.")]
public bool SkipStorageCheck { get; set; }

[Option('b', "beginning", HelpText = "Time in seconds where the crop begins.")]
public int CropBeginningTime { get; set; }

[Option('e', "ending", HelpText = "Time in seconds to crop ending.")]
[Option('e', "ending", HelpText = "Time in seconds where the crop ends.")]
public int CropEndingTime { get; set; }

[Option('t', "threads", Default = 4, HelpText = "Number of download threads.")]
Expand Down
50 changes: 31 additions & 19 deletions TwitchDownloaderCLI/Modes/DownloadVideo.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System;
using System;
using System.IO;
using System.Threading;
using TwitchDownloaderCLI.Modes.Arguments;
Expand Down Expand Up @@ -47,29 +47,15 @@ private static VideoDownloadOptions GetDownloadOptions(VideoDownloadArgs inputOp
Environment.Exit(1);
}

if (!Path.HasExtension(inputOptions.OutputFile) && inputOptions.Quality is { Length: > 0 })
{
if (inputOptions.Quality.Contains("audio", StringComparison.OrdinalIgnoreCase))
inputOptions.OutputFile += ".m4a";
else if (char.IsDigit(inputOptions.Quality[0])
|| inputOptions.Quality.Contains("source", StringComparison.OrdinalIgnoreCase)
|| inputOptions.Quality.Contains("chunked", StringComparison.OrdinalIgnoreCase))
inputOptions.OutputFile += ".mp4";
}

VideoDownloadOptions downloadOptions = new()
{
DownloadThreads = inputOptions.DownloadThreads,
ThrottleKib = inputOptions.ThrottleKib,
Id = int.Parse(vodIdMatch.ValueSpan),
Oauth = inputOptions.Oauth,
Filename = inputOptions.OutputFile,
Quality = Path.GetExtension(inputOptions.OutputFile)!.ToLower() switch
{
".mp4" => inputOptions.Quality,
".m4a" => "Audio",
_ => throw new ArgumentException("Only MP4 and M4A audio files are supported.")
},
KeepCache = inputOptions.KeepCache,
KeepCacheNoParts = inputOptions.KeepCacheNoParts,
SkipStorageCheck = inputOptions.SkipStorageCheck,
CropBeginning = inputOptions.CropBeginningTime > 0.0,
CropBeginningTime = inputOptions.CropBeginningTime,
CropEnding = inputOptions.CropEndingTime > 0.0,
Expand All @@ -78,7 +64,33 @@ private static VideoDownloadOptions GetDownloadOptions(VideoDownloadArgs inputOp
TempFolder = inputOptions.TempFolder
};

if (!string.IsNullOrWhiteSpace(inputOptions.OutputFile))
{
if (!Path.HasExtension(inputOptions.OutputFile) && inputOptions.Quality is { Length: > 0 })
{
if (inputOptions.Quality.Contains("audio", StringComparison.OrdinalIgnoreCase))
inputOptions.OutputFile += ".m4a";
else if (char.IsDigit(inputOptions.Quality[0])
|| inputOptions.Quality.Contains("source", StringComparison.OrdinalIgnoreCase)
|| inputOptions.Quality.Contains("chunked", StringComparison.OrdinalIgnoreCase))
inputOptions.OutputFile += ".mp4";
}

downloadOptions.Filename = inputOptions.OutputFile;

downloadOptions.Quality = Path.GetExtension(inputOptions.OutputFile)!.ToLower() switch
{
".mp4" => inputOptions.Quality,
".m4a" => "Audio",
_ => throw new ArgumentException("Only MP4 and M4A audio files are supported.")
};
}
else if (inputOptions.Quality.Contains("audio", StringComparison.OrdinalIgnoreCase))
downloadOptions.Quality = "Audio";
else
downloadOptions.Quality = inputOptions.Quality;

return downloadOptions;
}
}
}
}
33 changes: 22 additions & 11 deletions TwitchDownloaderCLI/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,26 @@ Also can concatenate/combine/merge Transport Stream files, either those parts do
**-u / --id (REQUIRED)**
The ID or URL of the VOD to download.

**-o / --output (REQUIRED)**
File the program will output to. File extension will be used to determine download type. Valid extensions are: `.mp4` and `.m4a`.
**-o / --output**
File the program will output to. File extension will be used to determine download type if the extension is present. 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.

**-K / --cache**
Keep entire cache folder. Overrides "-k".

**-k / --cache-noparts**
Keep cache folder except .ts parts.

**-F / --skip-storagecheck**
Skip checking for free storage space.

**-b / --beginning**
Time in seconds to crop beginning. For example if I had a 10 second stream but only wanted the last 7 seconds of it I would use `-b 3` to skip the first 3 seconds.
Time in seconds where the crop begins. For example if I had a 10 second stream but only wanted the last 7 seconds of it I would use `-b 3` to skip the first 3 seconds.

**-e / --ending**
Time in seconds to crop ending. For example if I had a 10 second stream but only wanted the first 4 seconds of it I would use `-e 4` to end on the 4th second.
Time in seconds where the crop ends. For example if I had a 10 second stream but only wanted the first 4 seconds of it I would use `-e 4` to end on the 4th second.

Extra example, if I wanted only seconds 3-6 in a 10 second stream I would do `-b 3 -e 6`

Expand Down Expand Up @@ -94,10 +103,10 @@ File the program will output to. File extension will be used to determine downlo
(Default: `None`) Compresses an output json chat file using a specified compression, usually resulting in 40-90% size reductions. Valid values are: `None`, `Gzip`. More formats will be supported in the future.

**-b / --beginning**
Time in seconds to crop beginning. For example if I had a 10 second stream but only wanted the last 7 seconds of it I would use `-b 3` to skip the first 3 seconds.
Time in seconds where the crop begins. For example if I had a 10 second stream but only wanted the last 7 seconds of it I would use `-b 3` to skip the first 3 seconds.

**-e / --ending**
Time in seconds to crop ending. For example if I had a 10 second stream but only wanted the first 4 seconds of it I would use `-e 4` to end on the 4th second.
Time in seconds where the crop ends. For example if I had a 10 second stream but only wanted the first 4 seconds of it I would use `-e 4` to end on the 4th second.

**-E / --embed-images**
(Default: `false`) Embed first party emotes, badges, and cheermotes into the download file for offline rendering. Useful for archival purposes, file size will be larger.
Expand Down Expand Up @@ -145,10 +154,10 @@ Path to output file. File extension will be used to determine new chat type. Val
(Default: `false`) Replace all embedded emotes, badges, and cheermotes in the file. All embedded data will be overwritten!

**b / --beginning**
(Default: `-1`) New time in seconds for chat beginning. Comments may be added but not removed. -1 = No crop.
(Default: `-1`) New time in seconds where the chat begins. Comments may be added but not removed. -1 = No crop.

**-e / --ending**
(Default: `-1`) New time in seconds for chat beginning. Comments may be added but not removed. -1 = No crop.
(Default: `-1`) New time in seconds where chat ends. Comments may be added but not removed. -1 = No crop.

**--bttv**
(Default: `true`) Enable embedding BTTV emotes.
Expand Down Expand Up @@ -193,10 +202,10 @@ File the program will output to.
(Default: `600`) Height of chat render.

**-b / --beginning**
(Default: `-1`) Time in seconds to crop the beginning of the render.
(Default: `-1`) Time in seconds where the crop begins.

**-e / --ending**
(Default: `-1`) Time in seconds to crop the ending of the render.
(Default: `-1`) Time in seconds where the crop ends.

**--bttv**
(Default: `true`) Enable BTTV emotes.
Expand Down Expand Up @@ -434,5 +443,7 @@ For Linux users, ensure both `fontconfig` and `libfontconfig1` are installed. `a

Some distros, like Linux Alpine, lack fonts for some languages (Arabic, Persian, Thai, etc.) If this is the case for you, install additional fonts families such as [Noto](https://fonts.google.com/noto/specimen/Noto+Sans) or check your distro's wiki page on fonts as it may have an install command for this specific scenario, such as the [Linux Alpine](https://wiki.alpinelinux.org/wiki/Fonts) font page.

When cropping, the part of the file to be retained is the one after the crop starts and before the crop ends. The rest is discarded.

The list file for `tsmerge` may contain relative or absolute paths, with one path per line.
Alternatively, the list file may also be an M3U8 playlist file.
Alternatively, the list file may also be an M3U8 playlist file.
4 changes: 3 additions & 1 deletion TwitchDownloaderCore/ChatDownloader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -530,6 +530,8 @@ public async Task DownloadAsync(IProgress<ProgressReport> progress, Cancellation
default:
throw new NotSupportedException($"{downloadOptions.DownloadFormat} is not a supported output format.");
}

Console.WriteLine();
}
}
}
}
3 changes: 2 additions & 1 deletion TwitchDownloaderCore/ClipDownloader.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System;
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
Expand Down Expand Up @@ -82,6 +82,7 @@ void DownloadProgressHandler(StreamCopyProgress streamProgress)

_progress.Report(new ProgressReport(ReportType.SameLineStatus, "Encoding Clip Metadata 100%"));
_progress.Report(new ProgressReport(100));
Console.WriteLine();
}
finally
{
Expand Down
5 changes: 4 additions & 1 deletion TwitchDownloaderCore/Options/VideoDownloadOptions.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System;
using System;
using System.IO;

namespace TwitchDownloaderCore.Options
Expand All @@ -8,6 +8,9 @@ public class VideoDownloadOptions
public int Id { get; set; }
public string Quality { get; set; }
public string Filename { get; set; }
public bool KeepCache { get; set; }
public bool KeepCacheNoParts { get; set; }
public bool SkipStorageCheck { get; set; }
public bool CropBeginning { get; set; }
public double CropBeginningTime { get; set; }
public bool CropEnding { get; set; }
Expand Down
3 changes: 2 additions & 1 deletion TwitchDownloaderCore/TsMerger.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading;
Expand Down Expand Up @@ -57,6 +57,7 @@ public async Task MergeAsync(CancellationToken cancellationToken)
await CombineVideoParts(fileList, cancellationToken);

_progress.Report(new ProgressReport(100));
Console.WriteLine();
}

private async Task VerifyVideoParts(IReadOnlyCollection<string> fileList, CancellationToken cancellationToken)
Expand Down
Loading
Loading