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

[CLI] New options, fixes, update README #1002

Closed
wants to merge 20 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
7 changes: 5 additions & 2 deletions TwitchDownloaderCLI/Modes/Arguments/ClipDownloadArgs.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 @@ -20,6 +20,9 @@ public class ClipDownloadArgs : ITwitchDownloaderArgs
[Option("encode-metadata", Default = true, HelpText = "Uses FFmpeg to add metadata to the clip output file.")]
public bool? EncodeMetadata { get; set; }

[Option("tbn", HelpText = "Set specific TBN (time base in AVStream) for output.")]
public int SetTbnValue { get; set; }

[Option("ffmpeg-path", HelpText = "Path to FFmpeg executable.")]
public string FfmpegPath { get; set; }

Expand All @@ -29,4 +32,4 @@ public class ClipDownloadArgs : ITwitchDownloaderArgs
[Option("banner", Default = true, HelpText = "Displays a banner containing version and copyright information.")]
public bool? ShowBanner { get; set; }
}
}
}
5 changes: 4 additions & 1 deletion TwitchDownloaderCLI/Modes/Arguments/TsMergeArgs.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 @@ -11,6 +11,9 @@ public class TsMergeArgs : ITwitchDownloaderArgs
[Option('o', "output", Required = true, HelpText = "Path to output file.")]
public string OutputFile { get; set; }

[Option('f', "ignore-missing", HelpText = "Ignore missing files listed inside input. Useful when the stream was trimmed.")]
public bool IgnoreMissingParts { get; set; }

[Option("banner", Default = true, HelpText = "Displays a banner containing version and copyright information.")]
public bool? ShowBanner { get; set; }
}
Expand Down
31 changes: 23 additions & 8 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,31 +8,46 @@ 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", HelpText = "Path to output file. File extension will be used to determine download type. Valid extensions are: .mp4, .m4a.")]
public string OutputFile { get; set; }

[Option('q', "quality", HelpText = "The quality the program will attempt to download.")]
[Option('q', "quality", HelpText = "The quality the program will attempt to download, like '1080p60'. If '-o' and '-q' are missing will be 'best'.")]
public string Quality { get; set; }

[Option('b', "beginning", HelpText = "Time in seconds to crop beginning.")]
[Option('p', "parts", HelpText = "Only download playlist.m3u8, metadata.txt and .ts parts to cache folder, and exit. Overrides '-k', '-K', '-o'.")]
public bool TsPartsOnly { get; set; }

[Option('K', "cache", HelpText = "Keep entire cache folder. Overrides '-k'.")]
public bool KeepCache { get; set; }

[Option('k', "cache-noparts", HelpText = "Keep cache folder except .ts parts. Merged 'output.ts' is not considered a part.")]
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 of the ID begins. May break first GOP.")]
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 of the ID ends. May break last GOP.")]
public int CropEndingTime { get; set; }

[Option('t', "threads", Default = 4, HelpText = "Number of download threads.")]
[Option("tbn", HelpText = "Set specific TBN (time base in AVStream) for output.")]
public int SetTbnValue { get; set; }

[Option('t', "threads", Default = 4, HelpText = "Number of simultaneous download threads.")]
public int DownloadThreads { get; set; }

[Option("bandwidth", Default = -1, HelpText = "The maximum bandwidth a thread will be allowed to use in kibibytes per second (KiB/s), or -1 for no maximum.")]
public int ThrottleKib { get; set; }

[Option("oauth", HelpText = "OAuth access token to download subscriber only VODs. DO NOT SHARE THIS WITH ANYONE.")]
[Option('a', "oauth", HelpText = "OAuth access token to download subscriber only VODs. DO NOT SHARE THIS WITH ANYONE.")]
public string Oauth { 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.")]
[Option('c', "temp-path", Default = "", HelpText = "Set custom path to temp/cache folder instead of provided by system. Recommended for '-k', '-K', '-p'.")]
public string TempFolder { get; set; }

[Option("banner", Default = true, HelpText = "Displays a banner containing version and copyright information.")]
Expand Down
4 changes: 3 additions & 1 deletion TwitchDownloaderCLI/Modes/DownloadClip.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 @@ -50,6 +50,8 @@ private static ClipDownloadOptions GetDownloadOptions(ClipDownloadArgs inputOpti
ThrottleKib = inputOptions.ThrottleKib,
FfmpegPath = string.IsNullOrWhiteSpace(inputOptions.FfmpegPath) ? FfmpegHandler.FfmpegExecutableName : Path.GetFullPath(inputOptions.FfmpegPath),
EncodeMetadata = inputOptions.EncodeMetadata!.Value,
SetTbn = inputOptions.SetTbnValue > 0.0,
SetTbnValue = inputOptions.SetTbnValue,
TempFolder = inputOptions.TempFolder
};

Expand Down
55 changes: 36 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,38 +47,55 @@ 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.")
},
TsPartsOnly = inputOptions.TsPartsOnly,
KeepCache = inputOptions.KeepCache,
KeepCacheNoParts = inputOptions.KeepCacheNoParts,
SkipStorageCheck = inputOptions.SkipStorageCheck,
CropBeginning = inputOptions.CropBeginningTime > 0.0,
CropBeginningTime = inputOptions.CropBeginningTime,
CropEnding = inputOptions.CropEndingTime > 0.0,
CropEndingTime = inputOptions.CropEndingTime,
SetTbn = inputOptions.SetTbnValue > 0.0,
SetTbnValue = inputOptions.SetTbnValue,
FfmpegPath = string.IsNullOrWhiteSpace(inputOptions.FfmpegPath) ? FfmpegHandler.FfmpegExecutableName : Path.GetFullPath(inputOptions.FfmpegPath),
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 (string.IsNullOrWhiteSpace(inputOptions.Quality))
downloadOptions.Quality = "best";
else if (inputOptions.Quality.Contains("audio", StringComparison.OrdinalIgnoreCase))
downloadOptions.Quality = "Audio";
else
downloadOptions.Quality = inputOptions.Quality;

return downloadOptions;
}
}
}
}
5 changes: 3 additions & 2 deletions TwitchDownloaderCLI/Modes/MergeTs.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System;
using System;
using System.Threading;
using TwitchDownloaderCLI.Modes.Arguments;
using TwitchDownloaderCLI.Tools;
Expand Down Expand Up @@ -26,7 +26,8 @@ private static TsMergeOptions GetMergeOptions(TsMergeArgs inputOptions)
TsMergeOptions mergeOptions = new()
{
OutputFile = inputOptions.OutputFile,
InputFile = inputOptions.InputList
InputFile = inputOptions.InputList,
IgnoreMissingParts = inputOptions.IgnoreMissingParts
};

return mergeOptions;
Expand Down
Loading