Skip to content

Commit 85e8c12

Browse files
committed
feat: cli usm2mp4
1 parent dff96cb commit 85e8c12

2 files changed

Lines changed: 162 additions & 0 deletions

File tree

Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
using MaiChartManager.Utils;
2+
using Spectre.Console;
3+
using Spectre.Console.Cli;
4+
using System.ComponentModel;
5+
using MaiChartManager.CLI.Utils;
6+
7+
namespace MaiChartManager.CLI.Commands;
8+
9+
public class MakeMp4Command : AsyncCommand<MakeMp4Command.Settings>
10+
{
11+
public class Settings : CommandSettings
12+
{
13+
[CommandArgument(0, "<sources>")]
14+
[Description("要转换的 USM/DAT 文件")]
15+
public string[] Sources { get; set; } = [];
16+
17+
[CommandOption("-O|--output")]
18+
[Description("输出文件路径(仅单文件时可用)")]
19+
public string? Output { get; set; }
20+
21+
public override ValidationResult Validate()
22+
{
23+
if (Sources.Length == 0)
24+
{
25+
return ValidationResult.Error("至少需要一个源文件");
26+
}
27+
28+
if (Sources.Length > 1 && !string.IsNullOrEmpty(Output))
29+
{
30+
return ValidationResult.Error("多文件转换时不能使用 -O 选项");
31+
}
32+
33+
foreach (var source in Sources)
34+
{
35+
if (!File.Exists(source))
36+
{
37+
return ValidationResult.Error($"源文件不存在: {source}");
38+
}
39+
}
40+
41+
return ValidationResult.Success();
42+
}
43+
}
44+
45+
public override async Task<int> ExecuteAsync(CommandContext context, Settings settings, CancellationToken cancellationToken)
46+
{
47+
try
48+
{
49+
if (settings.Sources.Length == 1)
50+
{
51+
var source = settings.Sources[0];
52+
var output = settings.Output ?? Path.ChangeExtension(source, ".mp4");
53+
await ConvertSingleFile(source, output);
54+
}
55+
else
56+
{
57+
await ConvertMultipleFiles(settings);
58+
}
59+
60+
AnsiConsole.MarkupLine("[green]✓ 所有转换已成功完成![/]");
61+
return 0;
62+
}
63+
catch (Exception ex)
64+
{
65+
SentrySdk.CaptureException(ex);
66+
AnsiConsole.MarkupLine($"[red]✗ 错误: {ex.Message}[/]");
67+
return 1;
68+
}
69+
}
70+
71+
private async Task ConvertSingleFile(string source, string output)
72+
{
73+
AnsiConsole.MarkupLine($"[yellow]正在转换:[/] {Path.GetFileName(source)}{Path.GetFileName(output)}");
74+
75+
await AnsiConsole.Progress()
76+
.AutoClear(false)
77+
.Columns(
78+
new TaskDescriptionColumn(),
79+
new ProgressBarColumn(),
80+
new PercentageColumn(),
81+
new SpinnerColumn())
82+
.StartAsync(async ctx =>
83+
{
84+
var task = ctx.AddTask($"[green]转换 {Path.GetFileName(source)}[/]");
85+
task.MaxValue = 100;
86+
TerminalProgress.Set(TerminalProgress.Status.Indeterminate);
87+
88+
await VideoConvert.ConvertUsmToMp4(
89+
source,
90+
output,
91+
onProgress: percent =>
92+
{
93+
TerminalProgress.Set(percent);
94+
task.Value = percent;
95+
});
96+
97+
TerminalProgress.Clear();
98+
task.Value = 100;
99+
});
100+
101+
AnsiConsole.MarkupLine($"[green]✓ 已保存到: {output}[/]");
102+
}
103+
104+
private async Task ConvertMultipleFiles(Settings settings)
105+
{
106+
AnsiConsole.MarkupLine($"[yellow]正在转换 {settings.Sources.Length} 个文件...[/]");
107+
108+
await AnsiConsole.Progress()
109+
.AutoClear(false)
110+
.Columns(
111+
new TaskDescriptionColumn(),
112+
new ProgressBarColumn(),
113+
new PercentageColumn(),
114+
new SpinnerColumn())
115+
.StartAsync(async ctx =>
116+
{
117+
int doneCount = 0, errorCount = 0;
118+
foreach (var source in settings.Sources)
119+
{
120+
var output = Path.ChangeExtension(source, ".mp4");
121+
var task = ctx.AddTask($"[green]{Path.GetFileName(source)}[/]");
122+
task.MaxValue = 100;
123+
124+
if (errorCount > 0)
125+
{
126+
TerminalProgress.Set(TerminalProgress.Status.Warning, (errorCount + doneCount) * 100 / settings.Sources.Length);
127+
}
128+
else
129+
{
130+
TerminalProgress.Set(doneCount * 100 / settings.Sources.Length);
131+
}
132+
133+
try
134+
{
135+
await VideoConvert.ConvertUsmToMp4(
136+
source,
137+
output,
138+
onProgress: percent => task.Value = percent
139+
);
140+
141+
doneCount++;
142+
task.Value = 100;
143+
}
144+
catch (Exception ex)
145+
{
146+
SentrySdk.CaptureException(ex);
147+
errorCount++;
148+
task.Description = $"[red]{Path.GetFileName(source)} - 失败[/]";
149+
task.Value = 100;
150+
task.StopTask();
151+
}
152+
}
153+
TerminalProgress.Clear();
154+
});
155+
}
156+
}

MaiChartManager.CLI/Program.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,12 @@
4444
.WithExample("makeusm", "video.mp4", "-O", "output.dat")
4545
.WithExample("makeusm", "video1.mp4", "video2.mp4", "video3.mp4");
4646

47+
config.AddCommand<MakeMp4Command>("makemp4")
48+
.WithDescription("将 USM/DAT 文件转换为 MP4 格式")
49+
.WithExample("makemp4", "movie.dat")
50+
.WithExample("makemp4", "movie.dat", "-O", "output.mp4")
51+
.WithExample("makemp4", "movie1.dat", "movie2.dat", "movie3.dat");
52+
4753
config.AddCommand<MakeAcbCommand>("makeacb")
4854
.WithDescription("将音频文件转换为 ACB 格式")
4955
.WithExample("makeacb", "audio.wav")

0 commit comments

Comments
 (0)