honeydo 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +90 -0
  3. package/README.zh-CN.md +88 -0
  4. package/package.json +54 -0
  5. package/packages/cli/dist/index.d.ts +2 -0
  6. package/packages/cli/dist/index.js +171 -0
  7. package/packages/cli/dist/index.js.map +1 -0
  8. package/packages/doubao/dist/cli.d.ts +38 -0
  9. package/packages/doubao/dist/cli.d.ts.map +1 -0
  10. package/packages/doubao/dist/cli.js +206 -0
  11. package/packages/gcli/dist/cli.d.ts +465 -0
  12. package/packages/gcli/dist/cli.js +2017 -0
  13. package/packages/gcli/dist/cli.js.map +1 -0
  14. package/packages/lmedia/dist/index.d.ts +1 -0
  15. package/packages/lmedia/dist/index.js +1594 -0
  16. package/packages/lmedia/python/edit.py +107 -0
  17. package/packages/lmedia/python/esrgan_path.py +16 -0
  18. package/packages/lmedia/python/gen.py +131 -0
  19. package/packages/lmedia/python/serve.py +352 -0
  20. package/packages/lmedia/python/sfx.py +527 -0
  21. package/packages/lmedia/python/teacache.py +255 -0
  22. package/packages/lmedia/python/upscale.py +41 -0
  23. package/packages/minimax/dist/cli.d.ts +51 -0
  24. package/packages/minimax/dist/cli.js +307 -0
  25. package/packages/minimax/dist/cli.js.map +1 -0
  26. package/packages/minimax/dist/client.d.ts +20 -0
  27. package/packages/minimax/dist/client.js +55 -0
  28. package/packages/minimax/dist/client.js.map +1 -0
  29. package/packages/minimax/dist/tts.d.ts +33 -0
  30. package/packages/minimax/dist/tts.js +64 -0
  31. package/packages/minimax/dist/tts.js.map +1 -0
  32. package/packages/minimax/dist/validate.d.ts +29 -0
  33. package/packages/minimax/dist/validate.js +122 -0
  34. package/packages/minimax/dist/validate.js.map +1 -0
  35. package/packages/minimax/dist/voice-clone.d.ts +17 -0
  36. package/packages/minimax/dist/voice-clone.js +47 -0
  37. package/packages/minimax/dist/voice-clone.js.map +1 -0
  38. package/packages/minimax/dist/voices.d.ts +17 -0
  39. package/packages/minimax/dist/voices.js +20 -0
  40. package/packages/minimax/dist/voices.js.map +1 -0
  41. package/packages/qwen/dist/index.d.ts +1 -0
  42. package/packages/qwen/dist/index.js +311 -0
@@ -0,0 +1,255 @@
1
+ """teacache.py — TeaCache 步缓存(Qwen-Image 系专用,纯 PyTorch,MPS 兼容)。
2
+ * 算法:相邻去噪步 block0 调制输入(信号 A)的 rel-L1 → 标定多项式 → 累计值 < 阈值则
3
+ * 跳过 60 个 transformer block(body),用「当前 img_in 输出 + 上次 body 残差」过 tail
4
+ * (norm_out+proj_out 很便宜)。不动权重/步数/CFG/调度器。
5
+ * 系数:mlx-teacache 在 Apple Silicon 的实测标定值(Signal A 原点约束拟合,R²=0.85;
6
+ * 阈值 0.30 → 24/48 步跳过、SSIM 0.987 视觉无损;SSIM 随阈值无悬崖衰减)。
7
+ * ⚠️ 不要用 ComfyUI/vllm 的 [-450,280,-45,3.2,-0.02]:标定域不同且常数项为负,
8
+ * 我们的 rel 尺度下 acc 一路负漂 → 无限跳过 → 输出浆糊(2026-08-29 实录)。
9
+ * CFG:diffusers Qwen 管线每步正/负两次调用、hidden_states 完全相同 → 每步共享一次
10
+ * 门控决策(与 mlx-teacache「shared CFG gate」一致),残差缓存按流分开。
11
+ * 绕行:batch>1(--num>1 或未来 CFG 合批)直接 passthrough,不缓存。
12
+ * 重置:scheduler 时间步单调递减,t 回升 = 新生成 → 全部重置(daemon 跨任务安全)。
13
+ * 实现:forward 拆 prelude/body/tail 三段复刻(与 diffusers 0.36 transformer_qwenimage.py
14
+ * 逐行对齐);skip 也要跑 prelude/tail(<2% 前向耗时)。
15
+ * 参考:TeaCache(CVPR2025, arXiv 2411.19108);github.com/IonDen/mlx-teacache(Qwen 标定)。
16
+ """
17
+ import math
18
+ import os
19
+ import sys
20
+
21
+ import torch
22
+ from diffusers.models.modeling_outputs import Transformer2DModelOutput
23
+ from diffusers.models.transformers.transformer_qwenimage import compute_text_seq_len_from_mask
24
+
25
+ TRACE = os.environ.get("LMEDIA_TEACACHE_TRACE") == "1"
26
+
27
+ # mlx-teacache Signal A 原点约束拟合(scripts/_calibration_qwen.json,2026-06 标定;c4..c0,c0=0)
28
+ QWEN_COEFFS = (-12.954226906135869, 8.883805167578382, -0.9363839862290331, 1.4538816050570036, 0.0)
29
+
30
+ DEFAULT_THRESHOLD = 0.30 # mlx-teacache 阈值扫描:SSIM 0.995@0.20 / 0.987@0.30 / 0.981@0.40
31
+ DEFAULT_WARMUP_STEPS = 4 # 前 N 步(每流前 N 次调用)强制 compute——结构形成期禁缓存
32
+ #(cache-dit 对 Qwen 默认 warmup=8;2048 大图均值信号对构图大改不敏感,
33
+ # 无 warmup 时早期误跳 → 轨迹锁死在错误构图,2026-08-30 实录)
34
+
35
+
36
+ def _rescale(x: float) -> float:
37
+ c = QWEN_COEFFS
38
+ return c[0] * x**4 + c[1] * x**3 + c[2] * x**2 + c[3] * x + c[4]
39
+
40
+
41
+ class TeaCache:
42
+ """transformer.forward 级钩子。attach 后按 enabled/thresh 动态开关,per-job 复用。"""
43
+
44
+ def __init__(self, thresh: float = DEFAULT_THRESHOLD, warmup: int = DEFAULT_WARMUP_STEPS):
45
+ self.thresh = float(thresh)
46
+ self.warmup = int(warmup) # 每流前 warmup 次调用强制 compute
47
+ self.enabled = True
48
+ # 双流(0=正 1=负)各自的残差缓存;信号/决策按步共享
49
+ self._streams = [self._stream(), self._stream()]
50
+ self._prev_signal: torch.Tensor | None = None
51
+ self._acc = 0.0
52
+ self._step_t: float | None = None
53
+ self._step_count = 0
54
+ self._pending: tuple[bool, torch.Tensor] | None = None # (skip?, signal) 给本步第二次调用
55
+ self._last_t: float | None = None
56
+ self.calls = 0
57
+ self.skips = 0
58
+
59
+ @staticmethod
60
+ def _stream() -> dict:
61
+ return {"res_img": None, "res_enc": None}
62
+
63
+ def reset(self) -> None:
64
+ self._streams = [self._stream(), self._stream()]
65
+ self._prev_signal = None
66
+ self._acc = 0.0
67
+ self._step_t = None
68
+ self._step_count = 0
69
+ self._pending = None
70
+ self._last_t = None
71
+
72
+ def begin_job(self) -> None:
73
+ """每个生成任务开始:清零统计(缓存状态靠时间步回升自动重置)。"""
74
+ self.calls = 0
75
+ self.skips = 0
76
+
77
+ def stats(self) -> dict:
78
+ return {"calls": self.calls, "skips": self.skips, "thresh": self.thresh}
79
+
80
+ # ---- forward 三段复刻(diffusers 0.36 QwenImageTransformer2DModel)----
81
+
82
+ @staticmethod
83
+ def _prelude(m, hidden_states, encoder_hidden_states, encoder_hidden_states_mask,
84
+ timestep, img_shapes, guidance, additional_t_cond):
85
+ hs = m.img_in(hidden_states)
86
+ t = timestep.to(hs.dtype)
87
+ modulate_index = None
88
+ if m.zero_cond_t:
89
+ t = torch.cat([t, t * 0], dim=0)
90
+ modulate_index = torch.tensor(
91
+ [[0] * math.prod(s[0]) + [1] * sum(math.prod(x) for x in s[1:]) for s in img_shapes],
92
+ device=t.device, dtype=torch.int,
93
+ )
94
+ enc = m.txt_in(m.txt_norm(encoder_hidden_states))
95
+ text_seq_len, _, enc_mask = compute_text_seq_len_from_mask(enc, encoder_hidden_states_mask)
96
+ if guidance is not None:
97
+ guidance = guidance.to(hs.dtype) * 1000
98
+ temb = (
99
+ m.time_text_embed(t, hs, additional_t_cond)
100
+ if guidance is None
101
+ else m.time_text_embed(t, guidance, hs, additional_t_cond)
102
+ )
103
+ rope = m.pos_embed(img_shapes, max_txt_seq_len=text_seq_len, device=hs.device)
104
+ return hs, enc, enc_mask, t, temb, rope, modulate_index
105
+
106
+ @staticmethod
107
+ def _signal(m, hs, temb, modulate_index, img_shapes):
108
+ """信号 A:block0 img 流调制输入的「主图 token」部分(条件图 token 恒定,会稀释 rel-L1
109
+ 导致过度跳过——2026-08-29 实录 4ref 全序列信号把 57% 调用错误跳过)。"""
110
+ with torch.no_grad():
111
+ block = m.transformer_blocks[0]
112
+ img_mod1, _ = block.img_mod(temb).chunk(2, dim=-1)
113
+ modulated, _ = block._modulate(block.img_norm1(hs), img_mod1, modulate_index)
114
+ main_lens = [math.prod(s[0]) for s in img_shapes]
115
+ return torch.cat([modulated[b, : main_lens[b]].reshape(-1) for b in range(len(main_lens))])
116
+
117
+ @staticmethod
118
+ def _run_body(m, hs, enc, enc_mask, temb, rope, modulate_index, attention_kwargs, controlnet_block_samples):
119
+ for index_block, block in enumerate(m.transformer_blocks):
120
+ enc, hs = block(
121
+ hidden_states=hs,
122
+ encoder_hidden_states=enc,
123
+ encoder_hidden_states_mask=enc_mask,
124
+ temb=temb,
125
+ image_rotary_emb=rope,
126
+ joint_attention_kwargs=attention_kwargs,
127
+ modulate_index=modulate_index,
128
+ )
129
+ if controlnet_block_samples is not None:
130
+ import numpy as np
131
+
132
+ interval = int(np.ceil(len(m.transformer_blocks) / len(controlnet_block_samples)))
133
+ hs = hs + controlnet_block_samples[index_block // interval]
134
+ return enc, hs
135
+
136
+ @staticmethod
137
+ def _tail(m, hs, temb):
138
+ t = temb.chunk(2, dim=0)[0] if m.zero_cond_t else temb
139
+ return m.proj_out(m.norm_out(hs, t))
140
+
141
+ def attach(self, transformer) -> None:
142
+ tc = self
143
+ m = transformer
144
+
145
+ def forward(
146
+ hidden_states,
147
+ encoder_hidden_states=None,
148
+ encoder_hidden_states_mask=None,
149
+ timestep=None,
150
+ img_shapes=None,
151
+ guidance=None,
152
+ attention_kwargs=None,
153
+ controlnet_block_samples=None,
154
+ additional_t_cond=None,
155
+ return_dict=True,
156
+ ):
157
+ # batch>1(--num 或 CFG 合批)绕行:残差按整批缓存语义不安全
158
+ if not tc.enabled or hidden_states.size(0) != 1:
159
+ return _full()
160
+
161
+ t_val = float(timestep.reshape(-1)[0].item())
162
+ if tc._last_t is None or t_val > tc._last_t: # 时间步回升 = 新生成
163
+ tc.reset()
164
+ new_step = t_val != tc._step_t
165
+ tc._last_t = t_val
166
+ tc._step_t = t_val
167
+ tc.calls += 1
168
+
169
+ hs, enc, enc_mask, t, temb, rope, modulate_index = self._prelude(
170
+ m, hidden_states, encoder_hidden_states, encoder_hidden_states_mask,
171
+ timestep, img_shapes, guidance, additional_t_cond,
172
+ )
173
+
174
+ if new_step:
175
+ signal = self._signal(m, hs, temb, modulate_index, img_shapes)
176
+ tc._step_count += 1
177
+ skip = False
178
+ if tc._step_count <= tc.warmup:
179
+ pass # 结构形成期强制 compute(大图均值信号对构图大改不敏感,禁跳)
180
+ elif tc._prev_signal is not None:
181
+ rel = ((signal - tc._prev_signal).abs().mean()
182
+ / (tc._prev_signal.abs().mean() + 1e-9)).item()
183
+ tc._acc += _rescale(rel)
184
+ skip = tc._acc < tc.thresh
185
+ if TRACE:
186
+ print(f"[teacache] t={t_val:.1f} rel={rel:.4f} acc={tc._acc:.3f} "
187
+ f"{'SKIP' if skip else 'compute'}", file=sys.stderr)
188
+ tc._pending = (skip, signal)
189
+ stream = 0
190
+ else:
191
+ skip, signal = tc._pending
192
+ stream = 1
193
+ if TRACE:
194
+ print(f"[teacache] t={t_val:.1f} 负流共享决策 {'SKIP' if skip else 'compute'}",
195
+ file=sys.stderr)
196
+
197
+ st = tc._streams[stream]
198
+ if skip and st["res_img"] is not None:
199
+ tc.skips += 1
200
+ out = self._tail(m, hs + st["res_img"], temb)
201
+ return Transformer2DModelOutput(sample=out) if return_dict else (out,)
202
+
203
+ enc_in, hs_in = enc, hs
204
+ enc, hs = self._run_body(m, hs, enc, enc_mask, temb, rope, modulate_index,
205
+ attention_kwargs, controlnet_block_samples)
206
+ st["res_img"] = hs - hs_in
207
+ st["res_enc"] = enc - enc_in
208
+ if new_step:
209
+ tc._prev_signal = signal
210
+ tc._acc = 0.0
211
+ out = self._tail(m, hs, temb)
212
+ return Transformer2DModelOutput(sample=out) if return_dict else (out,)
213
+
214
+ def _full():
215
+ return TeaCache._orig_forward(
216
+ m,
217
+ hidden_states, encoder_hidden_states, encoder_hidden_states_mask, timestep,
218
+ img_shapes, guidance, attention_kwargs, controlnet_block_samples,
219
+ additional_t_cond, return_dict,
220
+ )
221
+
222
+ forward._orig = m.forward # 保留引用防 GC 歧义
223
+ m.forward = forward
224
+
225
+ # 由 attach 时填充
226
+ _orig_forward = None
227
+
228
+
229
+ def attach_teacache(transformer, thresh: float = DEFAULT_THRESHOLD, warmup: int = DEFAULT_WARMUP_STEPS) -> TeaCache:
230
+ tc = TeaCache(thresh=thresh, warmup=warmup)
231
+ TeaCache._orig_forward = transformer.forward
232
+ tc.attach(transformer)
233
+ return tc
234
+
235
+
236
+ def apply_teacache(pipe, cfg: dict) -> TeaCache | None:
237
+ """per-job 开关:cfg['teaCache'] 为 {thresh?, warmup?} 或 true 时启用;否则挂起(零开销 passthrough)。
238
+ 在 gen.py/edit.py 的 run() 开头调用——直跑与 daemon(serve.py run_job → run)两条路同时覆盖。"""
239
+ tc_cfg = cfg.get("teaCache")
240
+ tc: TeaCache | None = getattr(pipe, "_teacache", None)
241
+ if tc_cfg:
242
+ thresh = tc_cfg.get("thresh", DEFAULT_THRESHOLD) if isinstance(tc_cfg, dict) else DEFAULT_THRESHOLD
243
+ warmup = tc_cfg.get("warmup", DEFAULT_WARMUP_STEPS) if isinstance(tc_cfg, dict) else DEFAULT_WARMUP_STEPS
244
+ if tc is None:
245
+ tc = attach_teacache(pipe.transformer, thresh, warmup)
246
+ pipe._teacache = tc
247
+ else:
248
+ tc.thresh = float(thresh)
249
+ tc.warmup = int(warmup)
250
+ tc.enabled = True
251
+ tc.begin_job()
252
+ return tc
253
+ if tc is not None:
254
+ tc.enabled = False
255
+ return None
@@ -0,0 +1,41 @@
1
+ """upscale.py - Real-ESRGAN x2 超分(spandrel + MPS)。
2
+ * 直跑:argv[1] = JSON {in, out, finalSize?: [w,h], model?}
3
+ * serve.py 复用:load_model / run(daemon 内懒加载常驻,二次超分秒级)
4
+ """
5
+ import json
6
+ from esrgan_path import resolve_esrgan_path
7
+ import sys
8
+ import time
9
+
10
+ import numpy as np
11
+ import torch
12
+ from PIL import Image
13
+ from spandrel import ModelLoader
14
+
15
+
16
+ def load_model(path: str | None = None):
17
+ device = "mps" if torch.backends.mps.is_available() else "cpu"
18
+ return ModelLoader().load_from_file(path or resolve_esrgan_path()).to(device).eval()
19
+
20
+
21
+ def run(model, cfg: dict) -> dict:
22
+ t0 = time.time()
23
+ device = "mps" if torch.backends.mps.is_available() else "cpu"
24
+ img = np.array(Image.open(cfg["in"]).convert("RGB")).astype(np.float32) / 255.0
25
+ t = torch.from_numpy(img).permute(2, 0, 1).unsqueeze(0).to(device)
26
+ with torch.no_grad():
27
+ out = model(t)
28
+ up = Image.fromarray((out.squeeze(0).permute(1, 2, 0).clamp(0, 1).cpu().numpy() * 255).astype("uint8"))
29
+ if cfg.get("finalSize"):
30
+ up = up.resize(tuple(cfg["finalSize"]), Image.LANCZOS)
31
+ up.save(cfg["out"])
32
+ return {"out": cfg["out"], "size": up.size, "seconds": round(time.time() - t0, 1)}
33
+
34
+
35
+ def main() -> None:
36
+ cfg = json.loads(sys.argv[1])
37
+ print(json.dumps(run(load_model(cfg.get("model")), cfg), ensure_ascii=False))
38
+
39
+
40
+ if __name__ == "__main__":
41
+ main()
@@ -0,0 +1,51 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * minimax — CLI for the MiniMax API.
4
+ *
5
+ * Subcommands (intentionally minimal — the official MCP exposes 10 tools but
6
+ * its schema costs agent context on every call; add more on demand):
7
+ * tts <text> text-to-audio (POST /v1/t2a_v2)
8
+ * voice-clone clone a voice from audio (POST /v1/files/upload + /v1/voice_clone)
9
+ * voices list voices as JSON (POST /v1/get_voice)
10
+ */
11
+ import { type VoiceType } from "./voices.js";
12
+ export interface TtsCliArgs {
13
+ text?: string;
14
+ voiceId?: string;
15
+ model?: string;
16
+ output?: string;
17
+ speed?: number;
18
+ vol?: number;
19
+ pitch?: number;
20
+ emotion?: string;
21
+ format?: string;
22
+ sampleRate?: number;
23
+ bitrate?: number;
24
+ channel?: number;
25
+ languageBoost?: string;
26
+ /** R1 karaoke: 字幕开关 */
27
+ subtitleEnable?: boolean;
28
+ /** R1 karaoke: 字幕粒度(默认 'word') */
29
+ subtitleType?: "word" | "sentence";
30
+ }
31
+ export type TtsParse = TtsCliArgs | {
32
+ error: string;
33
+ };
34
+ export declare function parseTtsArgs(argv: string[]): TtsParse;
35
+ export interface VoiceCloneCliArgs {
36
+ voiceId?: string;
37
+ audioFile?: string;
38
+ text?: string;
39
+ output?: string;
40
+ }
41
+ export type VoiceCloneParse = VoiceCloneCliArgs | {
42
+ error: string;
43
+ };
44
+ export declare function parseVoiceCloneArgs(argv: string[]): VoiceCloneParse;
45
+ export interface VoicesCliArgs {
46
+ type: VoiceType;
47
+ }
48
+ export type VoicesParse = VoicesCliArgs | {
49
+ error: string;
50
+ };
51
+ export declare function parseVoicesArgs(argv: string[]): VoicesParse;
@@ -0,0 +1,307 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * minimax — CLI for the MiniMax API.
4
+ *
5
+ * Subcommands (intentionally minimal — the official MCP exposes 10 tools but
6
+ * its schema costs agent context on every call; add more on demand):
7
+ * tts <text> text-to-audio (POST /v1/t2a_v2)
8
+ * voice-clone clone a voice from audio (POST /v1/files/upload + /v1/voice_clone)
9
+ * voices list voices as JSON (POST /v1/get_voice)
10
+ */
11
+ import { realpathSync } from "node:fs";
12
+ import { fileURLToPath } from "node:url";
13
+ import { parseArgs } from "node:util";
14
+ import { createClient } from "./client.js";
15
+ import { generateSpeech } from "./tts.js";
16
+ import { cloneVoice } from "./voice-clone.js";
17
+ import { listVoices } from "./voices.js";
18
+ const DEFAULT_HOST = "https://api.minimax.chat";
19
+ // ---------------------------------------------------------------------------
20
+ // arg parsing (pure, unit-tested)
21
+ // ---------------------------------------------------------------------------
22
+ function num(v, name) {
23
+ if (v === undefined)
24
+ return undefined;
25
+ const n = Number(v);
26
+ if (!Number.isFinite(n)) {
27
+ throw new Error(`--${name} must be a number, got "${v}"`);
28
+ }
29
+ return n;
30
+ }
31
+ export function parseTtsArgs(argv) {
32
+ try {
33
+ const { values, positionals } = parseArgs({
34
+ args: argv,
35
+ options: {
36
+ voice: { type: "string" },
37
+ model: { type: "string" },
38
+ output: { type: "string" },
39
+ speed: { type: "string" },
40
+ vol: { type: "string" },
41
+ pitch: { type: "string" },
42
+ emotion: { type: "string" },
43
+ format: { type: "string" },
44
+ "sample-rate": { type: "string" },
45
+ bitrate: { type: "string" },
46
+ channel: { type: "string" },
47
+ "language-boost": { type: "string" },
48
+ subtitle: { type: "boolean", default: false },
49
+ "subtitle-type": { type: "string" },
50
+ },
51
+ allowPositionals: true,
52
+ allowNegative: true,
53
+ });
54
+ const subtitleTypeRaw = values["subtitle-type"];
55
+ const subtitleType = subtitleTypeRaw === "sentence" ? "sentence" : subtitleTypeRaw === "word" ? "word" : undefined;
56
+ return {
57
+ text: positionals[0],
58
+ voiceId: values.voice,
59
+ model: values.model,
60
+ output: values.output,
61
+ speed: num(values.speed, "speed"),
62
+ vol: num(values.vol, "vol"),
63
+ pitch: num(values.pitch, "pitch"),
64
+ emotion: values.emotion,
65
+ format: values.format,
66
+ sampleRate: num(values["sample-rate"], "sample-rate"),
67
+ bitrate: num(values.bitrate, "bitrate"),
68
+ channel: num(values.channel, "channel"),
69
+ languageBoost: values["language-boost"],
70
+ subtitleEnable: values.subtitle === true,
71
+ subtitleType,
72
+ };
73
+ }
74
+ catch (err) {
75
+ return { error: err instanceof Error ? err.message : String(err) };
76
+ }
77
+ }
78
+ export function parseVoiceCloneArgs(argv) {
79
+ try {
80
+ const { values } = parseArgs({
81
+ args: argv,
82
+ options: {
83
+ voice: { type: "string" },
84
+ audio: { type: "string" },
85
+ text: { type: "string" },
86
+ output: { type: "string" },
87
+ },
88
+ allowPositionals: false,
89
+ });
90
+ return {
91
+ voiceId: values.voice,
92
+ audioFile: values.audio,
93
+ text: values.text,
94
+ output: values.output,
95
+ };
96
+ }
97
+ catch (err) {
98
+ return { error: err instanceof Error ? err.message : String(err) };
99
+ }
100
+ }
101
+ const VOICE_TYPES = ["all", "system", "voice_cloning"];
102
+ export function parseVoicesArgs(argv) {
103
+ try {
104
+ const { values } = parseArgs({
105
+ args: argv,
106
+ options: { type: { type: "string" } },
107
+ allowPositionals: false,
108
+ });
109
+ const t = (values.type ?? "all");
110
+ if (!VOICE_TYPES.includes(t)) {
111
+ return {
112
+ error: `--type must be one of ${VOICE_TYPES.join(", ")}, got "${t}"`,
113
+ };
114
+ }
115
+ return { type: t };
116
+ }
117
+ catch (err) {
118
+ return { error: err instanceof Error ? err.message : String(err) };
119
+ }
120
+ }
121
+ // ---------------------------------------------------------------------------
122
+ // help
123
+ // ---------------------------------------------------------------------------
124
+ const HELP = `Usage: minimax <command> [options]
125
+
126
+ Commands:
127
+ tts <text> Text-to-audio (POST /v1/t2a_v2)
128
+ voice-clone Clone a voice from audio (upload + /v1/voice_clone)
129
+ voices List voices as JSON (POST /v1/get_voice)
130
+
131
+ Options:
132
+ --help Show this help (per-command: minimax <command> --help)
133
+
134
+ Env:
135
+ MINIMAX_API_KEY (required) API key
136
+ MINIMAX_API_HOST default ${DEFAULT_HOST}
137
+
138
+ Exit codes: 0 success | 1 API error / missing key | 2 bad args
139
+ On file output, last stdout line is the saved path.`;
140
+ const TTS_HELP = `Usage: minimax tts "<text>" [options]
141
+
142
+ Options:
143
+ --voice <id> Voice ID (default male-qn-qingse)
144
+ --model <name> speech-02-hd (default) | speech-02-turbo | speech-01-*
145
+ --output <path> Output file (default: ./<voice>_<ts>.mp3)
146
+ --speed <n> 0.5-2.0 (default 1.0)
147
+ --vol <n> 0.1-10.0 (default 1.0)
148
+ --pitch <n> -12 to 12 (default 0; negatives need --pitch=-N)
149
+ --emotion <name> happy|sad|angry|fearful|disgusted|surprised|neutral
150
+ --format <f> mp3 (default) | pcm | flac | wav
151
+ --sample-rate <hz> 8000|16000|22050|24000|32000|44100
152
+ --bitrate <bps> 64000...320000
153
+ --channel <n> 1|2
154
+ --language-boost <l> auto (default) | Chinese | English | ...
155
+ --subtitle Enable subtitle (word-level timestamps; R1 karaoke)
156
+ --subtitle-type <t> word (default) | sentence`;
157
+ const VC_HELP = `Usage: minimax voice-clone --voice <id> --audio <file> [options]
158
+
159
+ Options:
160
+ --voice <id> (required) Voice ID to create
161
+ --audio <file> (required) Source audio file (mp3/m4a/wav)
162
+ --text <demo> Demo text (also synthesized to a demo wav)
163
+ --output <dir> Directory for the demo wav (default: current dir)`;
164
+ const VOICES_HELP = `Usage: minimax voices [--type <t>]
165
+
166
+ Options:
167
+ --type <t> all (default) | system | voice_cloning
168
+ Outputs JSON: { system: [{voice_id,voice_name}], cloned: [...] }`;
169
+ // ---------------------------------------------------------------------------
170
+ // main
171
+ // ---------------------------------------------------------------------------
172
+ function fail(msg, code) {
173
+ process.stderr.write(`minimax: ${msg}\n`);
174
+ process.exit(code);
175
+ }
176
+ function envOrError() {
177
+ const apiKey = process.env.MINIMAX_API_KEY;
178
+ if (!apiKey) {
179
+ return { error: "MINIMAX_API_KEY environment variable is not set" };
180
+ }
181
+ return { apiKey, host: process.env.MINIMAX_API_HOST || DEFAULT_HOST };
182
+ }
183
+ function wantsHelp(rest) {
184
+ return rest.includes("--help") || rest.includes("-h");
185
+ }
186
+ async function runTts(rest) {
187
+ if (wantsHelp(rest)) {
188
+ process.stdout.write(`${TTS_HELP}\n`);
189
+ process.exit(0);
190
+ }
191
+ const parsed = parseTtsArgs(rest);
192
+ if ("error" in parsed)
193
+ fail(parsed.error, 2);
194
+ if (!parsed.text)
195
+ fail('tts requires <text> as the first argument', 2);
196
+ const env = envOrError();
197
+ if ("error" in env)
198
+ fail(env.error, 1);
199
+ const client = createClient(env);
200
+ const format = parsed.format || "mp3";
201
+ const output = parsed.output || `./${parsed.voiceId ?? "voice"}_${Date.now()}.${format}`;
202
+ try {
203
+ const r = await generateSpeech(client, {
204
+ text: parsed.text,
205
+ voiceId: parsed.voiceId,
206
+ model: parsed.model,
207
+ speed: parsed.speed,
208
+ vol: parsed.vol,
209
+ pitch: parsed.pitch,
210
+ emotion: parsed.emotion,
211
+ format: parsed.format,
212
+ sampleRate: parsed.sampleRate,
213
+ bitrate: parsed.bitrate,
214
+ channel: parsed.channel,
215
+ languageBoost: parsed.languageBoost,
216
+ subtitleEnable: parsed.subtitleEnable,
217
+ subtitleType: parsed.subtitleType,
218
+ }, output);
219
+ process.stdout.write(`Saved to: ${r.filePath}\n`);
220
+ if (r.timingsPath) {
221
+ process.stdout.write(`Timings: ${r.timingsPath}\n`);
222
+ }
223
+ process.exit(0);
224
+ }
225
+ catch (err) {
226
+ fail(`tts failed: ${err instanceof Error ? err.message : String(err)}`, 1);
227
+ }
228
+ }
229
+ async function runVoiceClone(rest) {
230
+ if (wantsHelp(rest)) {
231
+ process.stdout.write(`${VC_HELP}\n`);
232
+ process.exit(0);
233
+ }
234
+ const parsed = parseVoiceCloneArgs(rest);
235
+ if ("error" in parsed)
236
+ fail(parsed.error, 2);
237
+ if (!parsed.voiceId)
238
+ fail("voice-clone requires --voice <id>", 2);
239
+ if (!parsed.audioFile)
240
+ fail("voice-clone requires --audio <file>", 2);
241
+ const env = envOrError();
242
+ if ("error" in env)
243
+ fail(env.error, 1);
244
+ const client = createClient(env);
245
+ try {
246
+ const r = await cloneVoice(client, {
247
+ voiceId: parsed.voiceId,
248
+ audioFile: parsed.audioFile,
249
+ text: parsed.text,
250
+ }, parsed.output || ".");
251
+ process.stdout.write(r.demoPath
252
+ ? `Voice cloned: ${r.voiceId} (demo: ${r.demoPath})\n`
253
+ : `Voice cloned: ${r.voiceId}\n`);
254
+ process.exit(0);
255
+ }
256
+ catch (err) {
257
+ fail(`voice-clone failed: ${err instanceof Error ? err.message : String(err)}`, 1);
258
+ }
259
+ }
260
+ async function runVoices(rest) {
261
+ if (wantsHelp(rest)) {
262
+ process.stdout.write(`${VOICES_HELP}\n`);
263
+ process.exit(0);
264
+ }
265
+ const parsed = parseVoicesArgs(rest);
266
+ if ("error" in parsed)
267
+ fail(parsed.error, 2);
268
+ const env = envOrError();
269
+ if ("error" in env)
270
+ fail(env.error, 1);
271
+ const client = createClient(env);
272
+ try {
273
+ const result = await listVoices(client, parsed.type);
274
+ process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
275
+ process.exit(0);
276
+ }
277
+ catch (err) {
278
+ fail(`voices failed: ${err instanceof Error ? err.message : String(err)}`, 1);
279
+ }
280
+ }
281
+ async function main() {
282
+ const [cmd, ...rest] = process.argv.slice(2);
283
+ switch (cmd) {
284
+ case "tts":
285
+ return runTts(rest);
286
+ case "voice-clone":
287
+ return runVoiceClone(rest);
288
+ case "voices":
289
+ return runVoices(rest);
290
+ case "--help":
291
+ case "-h":
292
+ case undefined:
293
+ process.stdout.write(`${HELP}\n`);
294
+ process.exit(0);
295
+ default:
296
+ fail(`unknown command "${cmd}". Run "minimax --help".`, 2);
297
+ }
298
+ }
299
+ const invokedDirectly = process.argv[1] !== undefined &&
300
+ realpathSync(process.argv[1]) === fileURLToPath(import.meta.url);
301
+ if (invokedDirectly) {
302
+ main().catch((err) => {
303
+ process.stderr.write(`minimax: fatal ${err instanceof Error ? err.message : String(err)}\n`);
304
+ process.exit(1);
305
+ });
306
+ }
307
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}