mirror of
https://github.com/k4yt3x/video2x.git
synced 2025-09-26 22:10:59 +02:00
feat(video2x): improve the CLI help message structure and clarity
Signed-off-by: k4yt3x <i@k4yt3x.com>
This commit is contained in:
parent
3215c89870
commit
d3de1ded96
14
CHANGELOG.md
14
CHANGELOG.md
@ -10,9 +10,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
### Added
|
### Added
|
||||||
|
|
||||||
- Automatic selection of the most suitable pixel format for the output video.
|
- Automatic selection of the most suitable pixel format for the output video.
|
||||||
- Support for specifying arbitrary `AVOptions` for the encoder.
|
- Support for specifying arbitrary `AVOptions` for the encoder (#1232).
|
||||||
- More `AVCodecContext` options.
|
- More `AVCodecContext` options.
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Improve the CLI help message structure and clarity.
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Timestamp errors processing frames with PTS equal to 0 (#1222).
|
- Timestamp errors processing frames with PTS equal to 0 (#1222).
|
||||||
@ -38,16 +42,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
- Vulkan device selection for libplacebo.
|
- Vulkan device selection for libplacebo.
|
||||||
- Status bar and processing statistics. (Video2X Qt6)
|
- Status bar and processing statistics. (Video2X Qt6)
|
||||||
|
|
||||||
### Fixed
|
|
||||||
|
|
||||||
- Wide character string paths support on Windows systems without UTF-8 support enabled (#1201).
|
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
- Automatically detect if options `colorspace` and `range` are supported by the buffer filter.
|
- Automatically detect if options `colorspace` and `range` are supported by the buffer filter.
|
||||||
- Resource file missing error messages.
|
- Resource file missing error messages.
|
||||||
- Rewritten the CLI with C++.
|
- Rewritten the CLI with C++.
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Wide character string paths support on Windows systems without UTF-8 support enabled (#1201).
|
||||||
|
|
||||||
## [6.0.0] - 2024-10-29
|
## [6.0.0] - 2024-10-29
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
@ -56,14 +56,14 @@ std::mutex proc_ctx_mutex;
|
|||||||
|
|
||||||
// Structure to hold parsed arguments
|
// Structure to hold parsed arguments
|
||||||
struct Arguments {
|
struct Arguments {
|
||||||
StringType loglevel = STR("info");
|
StringType log_level = STR("info");
|
||||||
bool noprogress = false;
|
bool no_progress = false;
|
||||||
|
|
||||||
// General options
|
// General options
|
||||||
std::filesystem::path in_fname;
|
std::filesystem::path in_fname;
|
||||||
std::filesystem::path out_fname;
|
std::filesystem::path out_fname;
|
||||||
StringType filter_type;
|
StringType filter_type;
|
||||||
uint32_t gpuid = 0;
|
uint32_t gpu_id = 0;
|
||||||
StringType hwaccel = STR("none");
|
StringType hwaccel = STR("none");
|
||||||
bool no_copy_streams = false;
|
bool no_copy_streams = false;
|
||||||
bool benchmark = false;
|
bool benchmark = false;
|
||||||
@ -293,7 +293,7 @@ void process_video_thread(
|
|||||||
EncoderConfig *encoder_config,
|
EncoderConfig *encoder_config,
|
||||||
VideoProcessingContext *proc_ctx
|
VideoProcessingContext *proc_ctx
|
||||||
) {
|
) {
|
||||||
enum Libvideo2xLogLevel log_level = parse_log_level(arguments->loglevel);
|
enum Libvideo2xLogLevel log_level = parse_log_level(arguments->log_level);
|
||||||
|
|
||||||
StringType in_fname_string;
|
StringType in_fname_string;
|
||||||
StringType out_fname_string;
|
StringType out_fname_string;
|
||||||
@ -314,7 +314,7 @@ void process_video_thread(
|
|||||||
out_fname,
|
out_fname,
|
||||||
log_level,
|
log_level,
|
||||||
arguments->benchmark,
|
arguments->benchmark,
|
||||||
arguments->gpuid,
|
arguments->gpu_id,
|
||||||
hw_device_type,
|
hw_device_type,
|
||||||
filter_config,
|
filter_config,
|
||||||
encoder_config,
|
encoder_config,
|
||||||
@ -346,70 +346,84 @@ int main(int argc, char **argv) {
|
|||||||
|
|
||||||
// Parse command line arguments using Boost.Program_options
|
// Parse command line arguments using Boost.Program_options
|
||||||
try {
|
try {
|
||||||
po::options_description desc("Allowed options");
|
// clang-format off
|
||||||
|
po::options_description all_opts("General options");
|
||||||
desc.add_options()
|
all_opts.add_options()
|
||||||
("help", "Display this help page")
|
("help", "Display this help page")
|
||||||
("version,v", "Print program version")
|
("version,V", "Print program version and exit")
|
||||||
("loglevel", PO_STR_VALUE<StringType>(&arguments.loglevel)->default_value(STR("info"),
|
("verbose,v", PO_STR_VALUE<StringType>(&arguments.log_level)->default_value(STR("info"),
|
||||||
"info"), "Set log level (trace, debug, info, warn, error, critical, none)")
|
"info"), "Set verbosity level (trace, debug, info, warn, error, critical, none)")
|
||||||
("noprogress", po::bool_switch(&arguments.noprogress),
|
("no-progress", po::bool_switch(&arguments.no_progress),
|
||||||
"Do not display the progress bar")
|
"Do not display the progress bar")
|
||||||
("listgpus", "List the available GPUs")
|
("list-gpus,l", "List the available GPUs")
|
||||||
|
|
||||||
// General Processing Options
|
// General Processing Options
|
||||||
("input,i", PO_STR_VALUE<StringType>(), "Input video file path")
|
("input,i", PO_STR_VALUE<StringType>(), "Input video file path")
|
||||||
("output,o", PO_STR_VALUE<StringType>(), "Output video file path")
|
("output,o", PO_STR_VALUE<StringType>(), "Output video file path")
|
||||||
("filter,f", PO_STR_VALUE<StringType>(&arguments.filter_type),
|
("filter,f", PO_STR_VALUE<StringType>(&arguments.filter_type),
|
||||||
"Filter to use: 'libplacebo' or 'realesrgan'")
|
"Filter to use: 'libplacebo' or 'realesrgan'")
|
||||||
("gpuid,g", po::value<uint32_t>(&arguments.gpuid)->default_value(0), "Vulkan GPU ID")
|
("gpu,g", po::value<uint32_t>(&arguments.gpu_id)->default_value(0),
|
||||||
|
"GPU ID (Vulkan device index)")
|
||||||
("hwaccel,a", PO_STR_VALUE<StringType>(&arguments.hwaccel)->default_value(STR("none"),
|
("hwaccel,a", PO_STR_VALUE<StringType>(&arguments.hwaccel)->default_value(STR("none"),
|
||||||
"none"), "Hardware acceleration method")
|
"none"), "Hardware acceleration method (mostly for decoding)")
|
||||||
("benchmark", po::bool_switch(&arguments.benchmark),
|
("benchmark,b", po::bool_switch(&arguments.benchmark),
|
||||||
"Discard processed frames and calculate average FPS")
|
"Discard processed frames and calculate average FPS; "
|
||||||
|
"useful for detecting encoder bottlenecks")
|
||||||
|
;
|
||||||
|
|
||||||
|
po::options_description encoder_opts("Encoder options");
|
||||||
|
encoder_opts.add_options()
|
||||||
// Encoder options
|
// Encoder options
|
||||||
("codec,c", PO_STR_VALUE<StringType>(&arguments.codec)->default_value(STR("libx264"),
|
("codec,c", PO_STR_VALUE<StringType>(&arguments.codec)->default_value(STR("libx264"),
|
||||||
"libx264"), "Output codec")
|
"libx264"), "Output codec")
|
||||||
("no_copy_streams", po::bool_switch(&arguments.no_copy_streams),
|
("no-copy-streams", po::bool_switch(&arguments.no_copy_streams),
|
||||||
"Do not copy audio and subtitle streams")
|
"Do not copy audio and subtitle streams")
|
||||||
("pix_fmt", PO_STR_VALUE<StringType>(&arguments.pix_fmt), "Output pixel format")
|
("pix-fmt", PO_STR_VALUE<StringType>(&arguments.pix_fmt), "Output pixel format")
|
||||||
("bit_rate", po::value<int64_t>(&arguments.bit_rate)->default_value(0),
|
("bit-rate", po::value<int64_t>(&arguments.bit_rate)->default_value(0),
|
||||||
"Bitrate in bits per second")
|
"Bitrate in bits per second")
|
||||||
("rc_buffer_size", po::value<int>(&arguments.rc_buffer_size)->default_value(0),
|
("rc-buffer-size", po::value<int>(&arguments.rc_buffer_size)->default_value(0),
|
||||||
"Rate control buffer size in bits")
|
"Rate control buffer size in bits")
|
||||||
("rc_min_rate", po::value<int>(&arguments.rc_min_rate)->default_value(0),
|
("rc-min-rate", po::value<int>(&arguments.rc_min_rate)->default_value(0),
|
||||||
"Minimum rate control")
|
"Minimum rate control")
|
||||||
("rc_max_rate", po::value<int>(&arguments.rc_max_rate)->default_value(0),
|
("rc-max-rate", po::value<int>(&arguments.rc_max_rate)->default_value(0),
|
||||||
"Maximum rate control")
|
"Maximum rate control")
|
||||||
("qmin", po::value<int>(&arguments.qmin)->default_value(-1), "Minimum quantizer")
|
("qmin", po::value<int>(&arguments.qmin)->default_value(-1), "Minimum quantizer")
|
||||||
("qmax", po::value<int>(&arguments.qmax)->default_value(-1), "Maximum quantizer")
|
("qmax", po::value<int>(&arguments.qmax)->default_value(-1), "Maximum quantizer")
|
||||||
("gop_size", po::value<int>(&arguments.gop_size)->default_value(-1),
|
("gop-size", po::value<int>(&arguments.gop_size)->default_value(-1),
|
||||||
"Group of pictures structure size")
|
"Group of pictures structure size")
|
||||||
("max_b_frames", po::value<int>(&arguments.max_b_frames)->default_value(-1),
|
("max-b-frames", po::value<int>(&arguments.max_b_frames)->default_value(-1),
|
||||||
"Maximum number of B-frames")
|
"Maximum number of B-frames")
|
||||||
("keyint_min", po::value<int>(&arguments.keyint_min)->default_value(-1),
|
("keyint-min", po::value<int>(&arguments.keyint_min)->default_value(-1),
|
||||||
"Minimum interval between keyframes")
|
"Minimum interval between keyframes")
|
||||||
("refs", po::value<int>(&arguments.refs)->default_value(-1),
|
("refs", po::value<int>(&arguments.refs)->default_value(-1),
|
||||||
"Number of reference frames")
|
"Number of reference frames")
|
||||||
("thread_count", po::value<int>(&arguments.thread_count)->default_value(0),
|
("thread-count", po::value<int>(&arguments.thread_count)->default_value(0),
|
||||||
"Number of threads for encoding")
|
"Number of threads for encoding")
|
||||||
("delay", po::value<int>(&arguments.delay)->default_value(0),
|
("delay", po::value<int>(&arguments.delay)->default_value(0),
|
||||||
"Delay in milliseconds for encoder")
|
"Delay in milliseconds for encoder")
|
||||||
|
|
||||||
// Extra encoder options (key-value pairs)
|
// Extra encoder options (key-value pairs)
|
||||||
("extra_option,e", PO_STR_VALUE<std::vector<StringType>>()->multitoken(),
|
("extra-encoder-option,e", PO_STR_VALUE<std::vector<StringType>>()->multitoken(),
|
||||||
"Additional AVOption(s) for codec settings (-e key=value)")
|
"Additional AVOption(s) for the encoder (format: -e key=value)")
|
||||||
|
;
|
||||||
|
|
||||||
// libplacebo options
|
po::options_description libplacebo_opts("libplacebo options");
|
||||||
("shader,s", PO_STR_VALUE<StringType>(), "Name or path of the GLSL shader file to use")
|
libplacebo_opts.add_options()
|
||||||
|
("shader,s", PO_STR_VALUE<StringType>(), "Name/path of the GLSL shader file to use")
|
||||||
("width,w", po::value<int>(&arguments.width), "Output width")
|
("width,w", po::value<int>(&arguments.width), "Output width")
|
||||||
("height,h", po::value<int>(&arguments.height), "Output height")
|
("height,h", po::value<int>(&arguments.height), "Output height")
|
||||||
|
;
|
||||||
|
|
||||||
// RealESRGAN options
|
// RealESRGAN options
|
||||||
|
po::options_description realesrgan_opts("RealESRGAN options");
|
||||||
|
realesrgan_opts.add_options()
|
||||||
("model,m", PO_STR_VALUE<StringType>(&arguments.model_name), "Name of the model to use")
|
("model,m", PO_STR_VALUE<StringType>(&arguments.model_name), "Name of the model to use")
|
||||||
("scale,r", po::value<int>(&arguments.scaling_factor), "Scaling factor (2, 3, or 4)")
|
("scale,r", po::value<int>(&arguments.scaling_factor), "Scaling factor (2, 3, or 4)")
|
||||||
;
|
;
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
|
// Combine all options
|
||||||
|
all_opts.add(encoder_opts).add(libplacebo_opts).add(realesrgan_opts);
|
||||||
|
|
||||||
// Positional arguments
|
// Positional arguments
|
||||||
po::positional_options_description p;
|
po::positional_options_description p;
|
||||||
@ -417,15 +431,27 @@ int main(int argc, char **argv) {
|
|||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
po::variables_map vm;
|
po::variables_map vm;
|
||||||
po::store(po::wcommand_line_parser(argc, argv).options(desc).positional(p).run(), vm);
|
po::store(po::wcommand_line_parser(argc, argv).options(all_opts).positional(p).run(), vm);
|
||||||
#else
|
#else
|
||||||
po::variables_map vm;
|
po::variables_map vm;
|
||||||
po::store(po::command_line_parser(argc, argv).options(desc).positional(p).run(), vm);
|
po::store(po::command_line_parser(argc, argv).options(all_opts).positional(p).run(), vm);
|
||||||
#endif
|
#endif
|
||||||
po::notify(vm);
|
po::notify(vm);
|
||||||
|
|
||||||
if (vm.count("help")) {
|
if (vm.count("help")) {
|
||||||
std::cout << desc << std::endl;
|
std::cout << all_opts << std::endl;
|
||||||
|
std::cout
|
||||||
|
<< "Examples:" << std::endl
|
||||||
|
<< " Upscale an anime video to 4K using libplacebo:" << std::endl
|
||||||
|
<< " video2x -i input.mp4 -o output.mp4 -f libplacebo -s anime4k-v4-a+a "
|
||||||
|
"-w 3840 -h 2160"
|
||||||
|
<< std::endl
|
||||||
|
<< std::endl
|
||||||
|
<< " Upscale a film video by 4x using RealESRGAN with custom encoder options"
|
||||||
|
<< std::endl
|
||||||
|
<< " video2x -i input.mkv -o output.mkv -f realesrgan -m realesrgan-plus -r 4 \\"
|
||||||
|
<< std::endl
|
||||||
|
<< " -c libx264rgb -e crf=17 -e preset=veryslow -e tune=film" << std::endl;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -434,7 +460,7 @@ int main(int argc, char **argv) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vm.count("listgpus")) {
|
if (vm.count("list-gpus")) {
|
||||||
return list_gpus();
|
return list_gpus();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -459,8 +485,8 @@ int main(int argc, char **argv) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Parse avoptions
|
// Parse avoptions
|
||||||
if (vm.count("extra_option")) {
|
if (vm.count("extra-encoder-option")) {
|
||||||
for (const auto &opt : vm["extra_option"].as<std::vector<StringType>>()) {
|
for (const auto &opt : vm["extra-encoder-option"].as<std::vector<StringType>>()) {
|
||||||
size_t eq_pos = opt.find('=');
|
size_t eq_pos = opt.find('=');
|
||||||
if (eq_pos != StringType::npos) {
|
if (eq_pos != StringType::npos) {
|
||||||
StringType key = opt.substr(0, eq_pos);
|
StringType key = opt.substr(0, eq_pos);
|
||||||
@ -519,10 +545,10 @@ int main(int argc, char **argv) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Validate GPU ID
|
// Validate GPU ID
|
||||||
int gpu_status = is_valid_gpu_id(arguments.gpuid);
|
int gpu_status = is_valid_gpu_id(arguments.gpu_id);
|
||||||
if (gpu_status < 0) {
|
if (gpu_status < 0) {
|
||||||
spdlog::warn("Unable to validate GPU ID.");
|
spdlog::warn("Unable to validate GPU ID.");
|
||||||
} else if (arguments.gpuid > 0 && gpu_status == 0) {
|
} else if (arguments.gpu_id > 0 && gpu_status == 0) {
|
||||||
spdlog::critical("Invalid GPU ID specified.");
|
spdlog::critical("Invalid GPU ID specified.");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -551,7 +577,7 @@ int main(int argc, char **argv) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Set spdlog log level
|
// Set spdlog log level
|
||||||
auto log_level = parse_log_level(arguments.loglevel);
|
auto log_level = parse_log_level(arguments.log_level);
|
||||||
switch (log_level) {
|
switch (log_level) {
|
||||||
case LIBVIDEO2X_LOG_LEVEL_TRACE:
|
case LIBVIDEO2X_LOG_LEVEL_TRACE:
|
||||||
spdlog::set_level(spdlog::level::trace);
|
spdlog::set_level(spdlog::level::trace);
|
||||||
@ -757,7 +783,7 @@ int main(int argc, char **argv) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Display progress
|
// Display progress
|
||||||
if (!arguments.noprogress) {
|
if (!arguments.no_progress) {
|
||||||
int64_t processed_frames, total_frames;
|
int64_t processed_frames, total_frames;
|
||||||
bool pause;
|
bool pause;
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user