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.
- package/LICENSE +21 -0
- package/README.md +90 -0
- package/README.zh-CN.md +88 -0
- package/package.json +54 -0
- package/packages/cli/dist/index.d.ts +2 -0
- package/packages/cli/dist/index.js +171 -0
- package/packages/cli/dist/index.js.map +1 -0
- package/packages/doubao/dist/cli.d.ts +38 -0
- package/packages/doubao/dist/cli.d.ts.map +1 -0
- package/packages/doubao/dist/cli.js +206 -0
- package/packages/gcli/dist/cli.d.ts +465 -0
- package/packages/gcli/dist/cli.js +2017 -0
- package/packages/gcli/dist/cli.js.map +1 -0
- package/packages/lmedia/dist/index.d.ts +1 -0
- package/packages/lmedia/dist/index.js +1594 -0
- package/packages/lmedia/python/edit.py +107 -0
- package/packages/lmedia/python/esrgan_path.py +16 -0
- package/packages/lmedia/python/gen.py +131 -0
- package/packages/lmedia/python/serve.py +352 -0
- package/packages/lmedia/python/sfx.py +527 -0
- package/packages/lmedia/python/teacache.py +255 -0
- package/packages/lmedia/python/upscale.py +41 -0
- package/packages/minimax/dist/cli.d.ts +51 -0
- package/packages/minimax/dist/cli.js +307 -0
- package/packages/minimax/dist/cli.js.map +1 -0
- package/packages/minimax/dist/client.d.ts +20 -0
- package/packages/minimax/dist/client.js +55 -0
- package/packages/minimax/dist/client.js.map +1 -0
- package/packages/minimax/dist/tts.d.ts +33 -0
- package/packages/minimax/dist/tts.js +64 -0
- package/packages/minimax/dist/tts.js.map +1 -0
- package/packages/minimax/dist/validate.d.ts +29 -0
- package/packages/minimax/dist/validate.js +122 -0
- package/packages/minimax/dist/validate.js.map +1 -0
- package/packages/minimax/dist/voice-clone.d.ts +17 -0
- package/packages/minimax/dist/voice-clone.js +47 -0
- package/packages/minimax/dist/voice-clone.js.map +1 -0
- package/packages/minimax/dist/voices.d.ts +17 -0
- package/packages/minimax/dist/voices.js +20 -0
- package/packages/minimax/dist/voices.js.map +1 -0
- package/packages/qwen/dist/index.d.ts +1 -0
- package/packages/qwen/dist/index.js +311 -0
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Minimal MiniMax API client: fetch + Bearer auth + base URL.
|
|
3
|
+
* Zero runtime deps. `post` sends JSON; `postMultipart` sends a FormData
|
|
4
|
+
* (fetch sets the multipart boundary — do not set Content-Type manually).
|
|
5
|
+
*/
|
|
6
|
+
export interface ClientOptions {
|
|
7
|
+
apiKey: string;
|
|
8
|
+
host: string;
|
|
9
|
+
}
|
|
10
|
+
export interface MiniMaxClient {
|
|
11
|
+
post<T = unknown>(path: string, data: unknown): Promise<T>;
|
|
12
|
+
postMultipart<T = unknown>(path: string, formData: FormData): Promise<T>;
|
|
13
|
+
}
|
|
14
|
+
export declare class MiniMaxApiError extends Error {
|
|
15
|
+
status: number;
|
|
16
|
+
statusText: string;
|
|
17
|
+
body: unknown;
|
|
18
|
+
constructor(status: number, statusText: string, body: unknown);
|
|
19
|
+
}
|
|
20
|
+
export declare function createClient(opts: ClientOptions): MiniMaxClient;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Minimal MiniMax API client: fetch + Bearer auth + base URL.
|
|
3
|
+
* Zero runtime deps. `post` sends JSON; `postMultipart` sends a FormData
|
|
4
|
+
* (fetch sets the multipart boundary — do not set Content-Type manually).
|
|
5
|
+
*/
|
|
6
|
+
export class MiniMaxApiError extends Error {
|
|
7
|
+
status;
|
|
8
|
+
statusText;
|
|
9
|
+
body;
|
|
10
|
+
constructor(status, statusText, body) {
|
|
11
|
+
const bodyText = typeof body === "string" ? body : JSON.stringify(body);
|
|
12
|
+
super(`MiniMax API error: ${status} ${statusText} - ${bodyText}`);
|
|
13
|
+
this.status = status;
|
|
14
|
+
this.statusText = statusText;
|
|
15
|
+
this.body = body;
|
|
16
|
+
this.name = "MiniMaxApiError";
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
export function createClient(opts) {
|
|
20
|
+
const base = opts.host.replace(/\/+$/, "");
|
|
21
|
+
async function request(path, init) {
|
|
22
|
+
const res = await fetch(`${base}${path}`, {
|
|
23
|
+
...init,
|
|
24
|
+
headers: {
|
|
25
|
+
Authorization: `Bearer ${opts.apiKey}`,
|
|
26
|
+
...(init.headers || {}),
|
|
27
|
+
},
|
|
28
|
+
});
|
|
29
|
+
const text = await res.text();
|
|
30
|
+
let body;
|
|
31
|
+
try {
|
|
32
|
+
body = text ? JSON.parse(text) : "";
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
body = text;
|
|
36
|
+
}
|
|
37
|
+
if (!res.ok) {
|
|
38
|
+
throw new MiniMaxApiError(res.status, res.statusText, body);
|
|
39
|
+
}
|
|
40
|
+
return body;
|
|
41
|
+
}
|
|
42
|
+
return {
|
|
43
|
+
post(path, data) {
|
|
44
|
+
return request(path, {
|
|
45
|
+
method: "POST",
|
|
46
|
+
headers: { "Content-Type": "application/json" },
|
|
47
|
+
body: JSON.stringify(data),
|
|
48
|
+
});
|
|
49
|
+
},
|
|
50
|
+
postMultipart(path, formData) {
|
|
51
|
+
return request(path, { method: "POST", body: formData });
|
|
52
|
+
},
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAYH,MAAM,OAAO,eAAgB,SAAQ,KAAK;IAE/B;IACA;IACA;IAHT,YACS,MAAc,EACd,UAAkB,EAClB,IAAa;QAEpB,MAAM,QAAQ,GACZ,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;QACzD,KAAK,CAAC,sBAAsB,MAAM,IAAI,UAAU,MAAM,QAAQ,EAAE,CAAC,CAAC;QAN3D,WAAM,GAAN,MAAM,CAAQ;QACd,eAAU,GAAV,UAAU,CAAQ;QAClB,SAAI,GAAJ,IAAI,CAAS;QAKpB,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAC;IAChC,CAAC;CACF;AAED,MAAM,UAAU,YAAY,CAAC,IAAmB;IAC9C,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IAE3C,KAAK,UAAU,OAAO,CAAI,IAAY,EAAE,IAAiB;QACvD,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,IAAI,GAAG,IAAI,EAAE,EAAE;YACxC,GAAG,IAAI;YACP,OAAO,EAAE;gBACP,aAAa,EAAE,UAAU,IAAI,CAAC,MAAM,EAAE;gBACtC,GAAG,CAAC,IAAI,CAAC,OAAO,IAAI,EAAE,CAAC;aACxB;SACF,CAAC,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;QAC9B,IAAI,IAAa,CAAC;QAClB,IAAI,CAAC;YACH,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACtC,CAAC;QAAC,MAAM,CAAC;YACP,IAAI,GAAG,IAAI,CAAC;QACd,CAAC;QACD,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACZ,MAAM,IAAI,eAAe,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;QAC9D,CAAC;QACD,OAAO,IAAS,CAAC;IACnB,CAAC;IAED,OAAO;QACL,IAAI,CAAC,IAAI,EAAE,IAAI;YACb,OAAO,OAAO,CAAC,IAAI,EAAE;gBACnB,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;gBAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;aAC3B,CAAC,CAAC;QACL,CAAC;QACD,aAAa,CAAC,IAAI,EAAE,QAAQ;YAC1B,OAAO,OAAO,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC;QAC3D,CAAC;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { MiniMaxClient } from "./client.js";
|
|
2
|
+
export interface TtsRequest {
|
|
3
|
+
text: string;
|
|
4
|
+
voiceId?: string;
|
|
5
|
+
model?: string;
|
|
6
|
+
speed?: number;
|
|
7
|
+
vol?: number;
|
|
8
|
+
pitch?: number;
|
|
9
|
+
emotion?: string;
|
|
10
|
+
format?: string;
|
|
11
|
+
sampleRate?: number;
|
|
12
|
+
bitrate?: number;
|
|
13
|
+
channel?: number;
|
|
14
|
+
languageBoost?: string;
|
|
15
|
+
/**
|
|
16
|
+
* 字幕开关(R1 karaoke 字级时间戳用)。
|
|
17
|
+
* 开启后 MiniMax 在响应中返回 `data.subtitle_file`(OSS 临时 URL,~24h 有效),
|
|
18
|
+
* `generateSpeech` 会即时下载并写盘 `{output}.timings.json`。
|
|
19
|
+
*/
|
|
20
|
+
subtitleEnable?: boolean;
|
|
21
|
+
/** 字幕粒度:'word'(字级,T9 实测中文每条 1 字)| 'sentence'(句级) */
|
|
22
|
+
subtitleType?: "word" | "sentence";
|
|
23
|
+
}
|
|
24
|
+
/** Build the /v1/t2a_v2 request body (pure — unit-tested). */
|
|
25
|
+
export declare function buildTtsRequestData(req: TtsRequest): Record<string, unknown>;
|
|
26
|
+
export interface TtsResult {
|
|
27
|
+
filePath: string;
|
|
28
|
+
format: string;
|
|
29
|
+
/** 字幕时间戳 JSON 落盘路径(仅 subtitleEnable=true 且响应含 subtitle_file 时存在) */
|
|
30
|
+
timingsPath?: string;
|
|
31
|
+
}
|
|
32
|
+
/** Call /v1/t2a_v2, decode the hex-encoded audio, and write it to disk. */
|
|
33
|
+
export declare function generateSpeech(client: MiniMaxClient, req: TtsRequest, outputFile: string): Promise<TtsResult>;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { mkdir, writeFile } from "node:fs/promises";
|
|
2
|
+
import { dirname, resolve } from "node:path";
|
|
3
|
+
import { DEFAULTS, ensureValidBitrate, ensureValidChannel, ensureValidEmotion, ensureValidFormat, ensureValidModel, ensureValidSampleRate, removeUndefined, } from "./validate.js";
|
|
4
|
+
/** Build the /v1/t2a_v2 request body (pure — unit-tested). */
|
|
5
|
+
export function buildTtsRequestData(req) {
|
|
6
|
+
const model = ensureValidModel(req.model);
|
|
7
|
+
return removeUndefined({
|
|
8
|
+
model,
|
|
9
|
+
text: req.text,
|
|
10
|
+
voice_setting: {
|
|
11
|
+
voice_id: req.voiceId || DEFAULTS.voiceId,
|
|
12
|
+
speed: req.speed ?? DEFAULTS.speed,
|
|
13
|
+
vol: req.vol ?? DEFAULTS.vol,
|
|
14
|
+
pitch: req.pitch ?? DEFAULTS.pitch,
|
|
15
|
+
emotion: ensureValidEmotion(req.emotion, model),
|
|
16
|
+
},
|
|
17
|
+
audio_setting: {
|
|
18
|
+
sample_rate: ensureValidSampleRate(req.sampleRate),
|
|
19
|
+
bitrate: ensureValidBitrate(req.bitrate),
|
|
20
|
+
format: ensureValidFormat(req.format),
|
|
21
|
+
channel: ensureValidChannel(req.channel),
|
|
22
|
+
},
|
|
23
|
+
language_boost: req.languageBoost || DEFAULTS.languageBoost,
|
|
24
|
+
stream: false,
|
|
25
|
+
// R1 karaoke: 顶层 subtitle_enable/subtitle_type(T9 实测顶层路径生效)
|
|
26
|
+
subtitle_enable: req.subtitleEnable ? true : undefined,
|
|
27
|
+
subtitle_type: req.subtitleEnable ? (req.subtitleType ?? "word") : undefined,
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
/** Call /v1/t2a_v2, decode the hex-encoded audio, and write it to disk. */
|
|
31
|
+
export async function generateSpeech(client, req, outputFile) {
|
|
32
|
+
const data = buildTtsRequestData(req);
|
|
33
|
+
const format = ensureValidFormat(req.format);
|
|
34
|
+
const response = await client.post("/v1/t2a_v2", data);
|
|
35
|
+
const audioHex = response?.data?.audio;
|
|
36
|
+
if (!audioHex) {
|
|
37
|
+
throw new Error("MiniMax T2A returned no audio data");
|
|
38
|
+
}
|
|
39
|
+
const audioBuffer = Buffer.from(audioHex, "hex");
|
|
40
|
+
const filePath = resolve(outputFile);
|
|
41
|
+
await mkdir(dirname(filePath), { recursive: true });
|
|
42
|
+
await writeFile(filePath, audioBuffer);
|
|
43
|
+
// R1 karaoke: subtitle_file 即时下载落盘(OSS URL ~24h 时效,必须现在取)
|
|
44
|
+
let timingsPath;
|
|
45
|
+
if (req.subtitleEnable && response?.data?.subtitle_file) {
|
|
46
|
+
try {
|
|
47
|
+
const subtitleResp = await fetch(response.data.subtitle_file);
|
|
48
|
+
if (subtitleResp.ok) {
|
|
49
|
+
const subtitleText = await subtitleResp.text();
|
|
50
|
+
timingsPath = resolve(`${outputFile}.timings.json`);
|
|
51
|
+
await writeFile(timingsPath, subtitleText, "utf8");
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
// 下载失败不阻断音频生成(音频已写盘),仅 warn
|
|
55
|
+
process.stderr.write(`minimax: subtitle_file download failed: ${subtitleResp.status} ${subtitleResp.statusText}\n`);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
catch (err) {
|
|
59
|
+
process.stderr.write(`minimax: subtitle_file download error: ${err instanceof Error ? err.message : String(err)}\n`);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return { filePath, format, timingsPath };
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=tts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tts.js","sourceRoot":"","sources":["../src/tts.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure validation helpers for MiniMax API parameters.
|
|
3
|
+
*
|
|
4
|
+
* Each `ensureValid*` returns the value if it is in the API's allow-list,
|
|
5
|
+
* otherwise falls back to the default (invalid input never throws — the API's
|
|
6
|
+
* own enum validation is the final authority, but we avoid obvious rejections).
|
|
7
|
+
*/
|
|
8
|
+
export declare const DEFAULTS: {
|
|
9
|
+
readonly model: "speech-02-hd";
|
|
10
|
+
readonly format: "mp3";
|
|
11
|
+
readonly emotion: "happy";
|
|
12
|
+
readonly sampleRate: 32000;
|
|
13
|
+
readonly bitrate: 128000;
|
|
14
|
+
readonly channel: 1;
|
|
15
|
+
readonly voiceId: "male-qn-qingse";
|
|
16
|
+
readonly speed: 1;
|
|
17
|
+
readonly vol: 1;
|
|
18
|
+
readonly pitch: 0;
|
|
19
|
+
readonly languageBoost: "auto";
|
|
20
|
+
};
|
|
21
|
+
export declare function ensureValidModel(model?: string): string;
|
|
22
|
+
export declare function ensureValidFormat(format?: string): string;
|
|
23
|
+
/** Returns undefined when the model does not support emotion (caller omits it). */
|
|
24
|
+
export declare function ensureValidEmotion(emotion?: string, model?: string): string | undefined;
|
|
25
|
+
export declare function ensureValidSampleRate(sampleRate?: number): number;
|
|
26
|
+
export declare function ensureValidBitrate(bitrate?: number): number;
|
|
27
|
+
export declare function ensureValidChannel(channel?: number): number;
|
|
28
|
+
/** Recursively drop undefined fields and empty objects (MiniMax rejects them). */
|
|
29
|
+
export declare function removeUndefined<T>(obj: T): T;
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure validation helpers for MiniMax API parameters.
|
|
3
|
+
*
|
|
4
|
+
* Each `ensureValid*` returns the value if it is in the API's allow-list,
|
|
5
|
+
* otherwise falls back to the default (invalid input never throws — the API's
|
|
6
|
+
* own enum validation is the final authority, but we avoid obvious rejections).
|
|
7
|
+
*/
|
|
8
|
+
const VALID_MODELS = [
|
|
9
|
+
"speech-02-hd",
|
|
10
|
+
"speech-02-turbo",
|
|
11
|
+
"speech-01-hd",
|
|
12
|
+
"speech-01-turbo",
|
|
13
|
+
"speech-01-240228",
|
|
14
|
+
"speech-01-turbo-240228",
|
|
15
|
+
];
|
|
16
|
+
const VALID_FORMATS = ["mp3", "pcm", "flac", "wav"];
|
|
17
|
+
const VALID_EMOTIONS = [
|
|
18
|
+
"happy",
|
|
19
|
+
"sad",
|
|
20
|
+
"angry",
|
|
21
|
+
"fearful",
|
|
22
|
+
"disgusted",
|
|
23
|
+
"surprised",
|
|
24
|
+
"neutral",
|
|
25
|
+
];
|
|
26
|
+
// Models that accept the `emotion` parameter at all.
|
|
27
|
+
const EMOTION_SUPPORTED_MODELS = [
|
|
28
|
+
"speech-02-hd",
|
|
29
|
+
"speech-02-turbo",
|
|
30
|
+
"speech-01-turbo",
|
|
31
|
+
"speech-01-hd",
|
|
32
|
+
];
|
|
33
|
+
const VALID_SAMPLE_RATES = [8000, 16000, 22050, 24000, 32000, 44100];
|
|
34
|
+
const VALID_BITRATES = [
|
|
35
|
+
64000,
|
|
36
|
+
96000,
|
|
37
|
+
128000,
|
|
38
|
+
160000,
|
|
39
|
+
192000,
|
|
40
|
+
224000,
|
|
41
|
+
256000,
|
|
42
|
+
320000,
|
|
43
|
+
];
|
|
44
|
+
const VALID_CHANNELS = [1, 2];
|
|
45
|
+
export const DEFAULTS = {
|
|
46
|
+
model: "speech-02-hd",
|
|
47
|
+
format: "mp3",
|
|
48
|
+
emotion: "happy",
|
|
49
|
+
sampleRate: 32000,
|
|
50
|
+
bitrate: 128000,
|
|
51
|
+
channel: 1,
|
|
52
|
+
voiceId: "male-qn-qingse",
|
|
53
|
+
speed: 1.0,
|
|
54
|
+
vol: 1.0,
|
|
55
|
+
pitch: 0,
|
|
56
|
+
languageBoost: "auto",
|
|
57
|
+
};
|
|
58
|
+
function closest(value, valid) {
|
|
59
|
+
return valid.reduce((prev, curr) => Math.abs(curr - value) < Math.abs(prev - value) ? curr : prev);
|
|
60
|
+
}
|
|
61
|
+
export function ensureValidModel(model) {
|
|
62
|
+
if (!model)
|
|
63
|
+
return DEFAULTS.model;
|
|
64
|
+
return VALID_MODELS.includes(model) ? model : DEFAULTS.model;
|
|
65
|
+
}
|
|
66
|
+
export function ensureValidFormat(format) {
|
|
67
|
+
if (!format)
|
|
68
|
+
return DEFAULTS.format;
|
|
69
|
+
return VALID_FORMATS.includes(format) ? format : DEFAULTS.format;
|
|
70
|
+
}
|
|
71
|
+
/** Returns undefined when the model does not support emotion (caller omits it). */
|
|
72
|
+
export function ensureValidEmotion(emotion, model) {
|
|
73
|
+
if (model && !EMOTION_SUPPORTED_MODELS.includes(model))
|
|
74
|
+
return undefined;
|
|
75
|
+
if (!emotion)
|
|
76
|
+
return DEFAULTS.emotion;
|
|
77
|
+
return VALID_EMOTIONS.includes(emotion) ? emotion : DEFAULTS.emotion;
|
|
78
|
+
}
|
|
79
|
+
export function ensureValidSampleRate(sampleRate) {
|
|
80
|
+
if (sampleRate === undefined)
|
|
81
|
+
return DEFAULTS.sampleRate;
|
|
82
|
+
return VALID_SAMPLE_RATES.includes(sampleRate)
|
|
83
|
+
? sampleRate
|
|
84
|
+
: closest(sampleRate, VALID_SAMPLE_RATES);
|
|
85
|
+
}
|
|
86
|
+
export function ensureValidBitrate(bitrate) {
|
|
87
|
+
if (bitrate === undefined)
|
|
88
|
+
return DEFAULTS.bitrate;
|
|
89
|
+
return VALID_BITRATES.includes(bitrate) ? bitrate : closest(bitrate, VALID_BITRATES);
|
|
90
|
+
}
|
|
91
|
+
export function ensureValidChannel(channel) {
|
|
92
|
+
if (channel === undefined)
|
|
93
|
+
return DEFAULTS.channel;
|
|
94
|
+
return VALID_CHANNELS.includes(channel) ? channel : closest(channel, VALID_CHANNELS);
|
|
95
|
+
}
|
|
96
|
+
/** Recursively drop undefined fields and empty objects (MiniMax rejects them). */
|
|
97
|
+
export function removeUndefined(obj) {
|
|
98
|
+
if (typeof obj !== "object" || obj === null)
|
|
99
|
+
return obj;
|
|
100
|
+
if (Array.isArray(obj)) {
|
|
101
|
+
return obj.map((item) => removeUndefined(item)).filter((item) => item !== undefined);
|
|
102
|
+
}
|
|
103
|
+
const result = {};
|
|
104
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
105
|
+
if (value === undefined)
|
|
106
|
+
continue;
|
|
107
|
+
if (typeof value === "object" && value !== null) {
|
|
108
|
+
const filtered = removeUndefined(value);
|
|
109
|
+
if (typeof filtered === "object" &&
|
|
110
|
+
!Array.isArray(filtered) &&
|
|
111
|
+
Object.keys(filtered).length === 0) {
|
|
112
|
+
continue;
|
|
113
|
+
}
|
|
114
|
+
result[key] = filtered;
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
result[key] = value;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
return result;
|
|
121
|
+
}
|
|
122
|
+
//# sourceMappingURL=validate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate.js","sourceRoot":"","sources":["../src/validate.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { MiniMaxClient } from "./client.js";
|
|
2
|
+
export interface VoiceCloneRequest {
|
|
3
|
+
voiceId: string;
|
|
4
|
+
audioFile: string;
|
|
5
|
+
text?: string;
|
|
6
|
+
}
|
|
7
|
+
/** Build the /v1/voice_clone payload from an uploaded file_id (pure). */
|
|
8
|
+
export declare function buildClonePayload(fileId: string, req: VoiceCloneRequest): Record<string, unknown>;
|
|
9
|
+
export interface VoiceCloneResult {
|
|
10
|
+
voiceId: string;
|
|
11
|
+
demoPath?: string;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Upload the audio (multipart, purpose=voice_clone), clone it, then download
|
|
15
|
+
* the demo audio if one is returned.
|
|
16
|
+
*/
|
|
17
|
+
export declare function cloneVoice(client: MiniMaxClient, req: VoiceCloneRequest, outputDir: string): Promise<VoiceCloneResult>;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
2
|
+
import { basename, resolve } from "node:path";
|
|
3
|
+
import { DEFAULTS } from "./validate.js";
|
|
4
|
+
/** Build the /v1/voice_clone payload from an uploaded file_id (pure). */
|
|
5
|
+
export function buildClonePayload(fileId, req) {
|
|
6
|
+
const payload = {
|
|
7
|
+
file_id: fileId,
|
|
8
|
+
voice_id: req.voiceId,
|
|
9
|
+
};
|
|
10
|
+
if (req.text) {
|
|
11
|
+
payload.text = req.text;
|
|
12
|
+
payload.model = DEFAULTS.model;
|
|
13
|
+
}
|
|
14
|
+
return payload;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Upload the audio (multipart, purpose=voice_clone), clone it, then download
|
|
18
|
+
* the demo audio if one is returned.
|
|
19
|
+
*/
|
|
20
|
+
export async function cloneVoice(client, req, outputDir) {
|
|
21
|
+
const absAudio = resolve(req.audioFile);
|
|
22
|
+
const buffer = await readFile(absAudio);
|
|
23
|
+
const form = new FormData();
|
|
24
|
+
form.append("file", new Blob([buffer]), basename(absAudio));
|
|
25
|
+
form.append("purpose", "voice_clone");
|
|
26
|
+
const upload = await client.postMultipart("/v1/files/upload", form);
|
|
27
|
+
const fileId = upload?.file?.file_id;
|
|
28
|
+
if (!fileId) {
|
|
29
|
+
throw new Error("MiniMax upload returned no file_id");
|
|
30
|
+
}
|
|
31
|
+
const cloneResp = await client.post("/v1/voice_clone", buildClonePayload(fileId, req));
|
|
32
|
+
const demoAudio = cloneResp?.demo_audio;
|
|
33
|
+
if (!demoAudio) {
|
|
34
|
+
return { voiceId: req.voiceId };
|
|
35
|
+
}
|
|
36
|
+
const demoResp = await fetch(demoAudio);
|
|
37
|
+
if (!demoResp.ok) {
|
|
38
|
+
return { voiceId: req.voiceId };
|
|
39
|
+
}
|
|
40
|
+
const demoBuffer = Buffer.from(await demoResp.arrayBuffer());
|
|
41
|
+
const outDir = resolve(outputDir);
|
|
42
|
+
await mkdir(outDir, { recursive: true });
|
|
43
|
+
const demoPath = resolve(outDir, `${req.voiceId}-demo.wav`);
|
|
44
|
+
await writeFile(demoPath, demoBuffer);
|
|
45
|
+
return { voiceId: req.voiceId, demoPath };
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=voice-clone.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"voice-clone.js","sourceRoot":"","sources":["../src/voice-clone.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC9D,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAE9C,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAQzC,yEAAyE;AACzE,MAAM,UAAU,iBAAiB,CAC/B,MAAc,EACd,GAAsB;IAEtB,MAAM,OAAO,GAA4B;QACvC,OAAO,EAAE,MAAM;QACf,QAAQ,EAAE,GAAG,CAAC,OAAO;KACtB,CAAC;IACF,IAAI,GAAG,CAAC,IAAI,EAAE,CAAC;QACb,OAAO,CAAC,IAAI,GAAG,GAAG,CAAC,IAAI,CAAC;QACxB,OAAO,CAAC,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC;IACjC,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAgBD;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAC9B,MAAqB,EACrB,GAAsB,EACtB,SAAiB;IAEjB,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IACxC,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,QAAQ,CAAC,CAAC;IAExC,MAAM,IAAI,GAAG,IAAI,QAAQ,EAAE,CAAC;IAC5B,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC;IAC5D,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,aAAa,CAAC,CAAC;IAEtC,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,aAAa,CACvC,kBAAkB,EAClB,IAAI,CACL,CAAC;IACF,MAAM,MAAM,GAAG,MAAM,EAAE,IAAI,EAAE,OAAO,CAAC;IACrC,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;IACxD,CAAC;IAED,MAAM,SAAS,GAAG,MAAM,MAAM,CAAC,IAAI,CACjC,iBAAiB,EACjB,iBAAiB,CAAC,MAAM,EAAE,GAAG,CAAC,CAC/B,CAAC;IAEF,MAAM,SAAS,GAAG,SAAS,EAAE,UAAU,CAAC;IACxC,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,OAAO,EAAE,OAAO,EAAE,GAAG,CAAC,OAAO,EAAE,CAAC;IAClC,CAAC;IAED,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,SAAS,CAAC,CAAC;IACxC,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,OAAO,EAAE,OAAO,EAAE,GAAG,CAAC,OAAO,EAAE,CAAC;IAClC,CAAC;IACD,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,QAAQ,CAAC,WAAW,EAAE,CAAC,CAAC;IAC7D,MAAM,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;IAClC,MAAM,KAAK,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACzC,MAAM,QAAQ,GAAG,OAAO,CAAC,MAAM,EAAE,GAAG,GAAG,CAAC,OAAO,WAAW,CAAC,CAAC;IAC5D,MAAM,SAAS,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;IACtC,OAAO,EAAE,OAAO,EAAE,GAAG,CAAC,OAAO,EAAE,QAAQ,EAAE,CAAC;AAC5C,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { MiniMaxClient } from "./client.js";
|
|
2
|
+
export type VoiceType = "all" | "system" | "voice_cloning";
|
|
3
|
+
export interface VoiceListResult {
|
|
4
|
+
system: Array<{
|
|
5
|
+
voice_id: string;
|
|
6
|
+
voice_name: string;
|
|
7
|
+
}>;
|
|
8
|
+
cloned: Array<{
|
|
9
|
+
voice_id: string;
|
|
10
|
+
voice_name: string;
|
|
11
|
+
}>;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* List available voices. Returns a structured { system, cloned } shape
|
|
15
|
+
* (stable schema for scripting) rather than the raw API field names.
|
|
16
|
+
*/
|
|
17
|
+
export declare function listVoices(client: MiniMaxClient, voiceType?: VoiceType): Promise<VoiceListResult>;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
function normalize(list) {
|
|
2
|
+
return (list ?? []).map((v) => ({
|
|
3
|
+
voice_id: v.voice_id ?? "",
|
|
4
|
+
voice_name: v.voice_name ?? "",
|
|
5
|
+
}));
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* List available voices. Returns a structured { system, cloned } shape
|
|
9
|
+
* (stable schema for scripting) rather than the raw API field names.
|
|
10
|
+
*/
|
|
11
|
+
export async function listVoices(client, voiceType = "all") {
|
|
12
|
+
const resp = await client.post("/v1/get_voice", {
|
|
13
|
+
voice_type: voiceType,
|
|
14
|
+
});
|
|
15
|
+
return {
|
|
16
|
+
system: normalize(resp?.system_voice),
|
|
17
|
+
cloned: normalize(resp?.voice_cloning),
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=voices.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"voices.js","sourceRoot":"","sources":["../src/voices.ts"],"names":[],"mappings":"AAmBA,SAAS,SAAS,CAChB,IAA8B;IAE9B,OAAO,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QAC9B,QAAQ,EAAE,CAAC,CAAC,QAAQ,IAAI,EAAE;QAC1B,UAAU,EAAE,CAAC,CAAC,UAAU,IAAI,EAAE;KAC/B,CAAC,CAAC,CAAC;AACN,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAC9B,MAAqB,EACrB,YAAuB,KAAK;IAE5B,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,IAAI,CAAmB,eAAe,EAAE;QAChE,UAAU,EAAE,SAAS;KACtB,CAAC,CAAC;IACH,OAAO;QACL,MAAM,EAAE,SAAS,CAAC,IAAI,EAAE,YAAY,CAAC;QACrC,MAAM,EAAE,SAAS,CAAC,IAAI,EAAE,aAAa,CAAC;KACvC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
#!/usr/bin/env node
|