@isaacthoman/pulpo 0.138.0 → 0.139.1
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/README.md +13 -18
- package/dist/index.js +5 -30
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -72,23 +72,18 @@ microdollars: `inputPriceMicros`/`outputPriceMicros` per million respective toke
|
|
|
72
72
|
audio minute. Token billing requires SSE usage support. Credentials remain in
|
|
73
73
|
the referenced provider connection.
|
|
74
74
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
unchanged voice IDs and remove clips for deleted voices. Model deletion removes
|
|
88
|
-
its clips. Listening to an uploaded sample does not generate speech or incur
|
|
89
|
-
generation charges.
|
|
90
|
-
|
|
91
|
-
Speech catalog and preview commands use `/api/management/v1/speech-models` and
|
|
75
|
+
Set each voice's `previewText` in the model document to customize generated
|
|
76
|
+
previews (up to 500 characters). Use `null` to reset to the shared default;
|
|
77
|
+
updates from older clients that omit this field preserve existing overrides.
|
|
78
|
+
Users generate previews from **Preview speech** at the bottom of speech settings,
|
|
79
|
+
using their selected controls and normal speech billing.
|
|
80
|
+
|
|
81
|
+
`speech-model test-voice <id> <voice> -o clip.mp3` defaults to the configured text;
|
|
82
|
+
`--text` supplies a one-off override. Admin tests incur provider costs without
|
|
83
|
+
charging a user balance. Saved-preview upload/download/delete commands and
|
|
84
|
+
`--save-preview` are retired.
|
|
85
|
+
|
|
86
|
+
Speech catalog and voice asset commands use `/api/management/v1/speech-models` and
|
|
92
87
|
require a current administrator with `catalog:read` for reads/downloads or
|
|
93
88
|
`catalog:write` for mutations. Older servers without the `speechModels`
|
|
94
89
|
capability report that an upgrade is required. User preferences continue to use
|
|
@@ -169,7 +164,7 @@ totals. Active or queued model work must finish before deletion can proceed.
|
|
|
169
164
|
Use `speech-model preset --adapter mistral` for the Voxtral preset. The
|
|
170
165
|
`provider-voices`, `provider-sample`, `clone`, `watermark`, `test-voice`, and
|
|
171
166
|
`cleanup` subcommands manage provider discovery, private reference uploads,
|
|
172
|
-
repair, looping watermark settings,
|
|
167
|
+
repair, looping watermark settings, speech tests, and retryable cleanup.
|
|
173
168
|
See [the speech administration guide](../../docs/speech.md) for complete commands,
|
|
174
169
|
upload limits, billing behavior, and FFmpeg setup.
|
|
175
170
|
|
package/dist/index.js
CHANGED
|
@@ -14615,11 +14615,13 @@ var imageGenerationInputSchema = external_exports.object({
|
|
|
14615
14615
|
// ../../packages/contracts/dist/speech.js
|
|
14616
14616
|
var SPEECH_REQUEST_MAX_INPUT_LENGTH = 16384;
|
|
14617
14617
|
var SPEECH_MAX_INSTRUCTIONS_LENGTH = 4096;
|
|
14618
|
+
var SPEECH_MAX_PREVIEW_TEXT_LENGTH = 500;
|
|
14618
14619
|
var SPEECH_ASSET_MAX_BYTES = 10 * 1024 * 1024;
|
|
14619
14620
|
var speechWatermarkSchema = external_exports.object({ enabled: external_exports.boolean().default(false), volume: external_exports.number().min(0.01).max(1).default(0.15) });
|
|
14620
14621
|
var speechVoiceSchema = external_exports.object({
|
|
14621
14622
|
id: external_exports.string().trim().min(1).max(200),
|
|
14622
14623
|
label: external_exports.string().trim().min(1).max(120),
|
|
14624
|
+
previewText: external_exports.string().trim().max(SPEECH_MAX_PREVIEW_TEXT_LENGTH).transform((text) => text || null).nullable().optional(),
|
|
14623
14625
|
kind: external_exports.enum(["provider", "cloned"]).optional(),
|
|
14624
14626
|
watermark: speechWatermarkSchema.optional()
|
|
14625
14627
|
});
|
|
@@ -20800,7 +20802,7 @@ async function runModelTest(input) {
|
|
|
20800
20802
|
}
|
|
20801
20803
|
|
|
20802
20804
|
// src/index.ts
|
|
20803
|
-
var CLI_VERSION = true ? "0.
|
|
20805
|
+
var CLI_VERSION = true ? "0.139.1" : "0.1.0";
|
|
20804
20806
|
var CLI_BUNDLED = true;
|
|
20805
20807
|
var commandIo = /* @__PURE__ */ new WeakMap();
|
|
20806
20808
|
var commandClientFactory = /* @__PURE__ */ new WeakMap();
|
|
@@ -21275,33 +21277,6 @@ function createProgram(io = processIo, dependencies = {}) {
|
|
|
21275
21277
|
speechModel.command("preset <id>").requiredOption("--provider <id>", "existing provider connection ID").option("--adapter <adapter>", "openai or mistral", "openai").description("Print an editable OpenAI or Voxtral model document without creating it").action((id, options2) => {
|
|
21276
21278
|
writeOutput(io, speechModelSchema.parse({ ...external_exports.enum(["openai", "mistral"]).parse(options2.adapter) === "mistral" ? VOXTRAL_SPEECH_PRESET : OPENAI_SPEECH_PRESET, id, providerConnectionId: options2.provider }), true);
|
|
21277
21279
|
});
|
|
21278
|
-
const speechPreview = speechModel.command("preview").description("Manage each voice\u2019s optional MP3/WAV preview");
|
|
21279
|
-
const speechPreviewPath = (id, voice) => `/api/management/v1/speech-models/${encodeURIComponent(id)}/voices/${encodeURIComponent(voice)}/preview`;
|
|
21280
|
-
speechPreview.command("upload <id> <voice> <path>").description("Upload or replace a voice preview (up to 30 seconds and 5 MiB)").action(async (id, voice, path, _options, command) => {
|
|
21281
|
-
const filename = basename(path);
|
|
21282
|
-
const extension = filename.split(".").at(-1)?.toLowerCase();
|
|
21283
|
-
const contentType = extension === "mp3" ? "audio/mpeg" : extension === "wav" ? "audio/wav" : null;
|
|
21284
|
-
if (!contentType) throw new Error("Speech previews must be MP3 or WAV files");
|
|
21285
|
-
const file2 = await stat(path);
|
|
21286
|
-
if (!file2.isFile() || !file2.size || file2.size > 5 * 1024 * 1024) throw new Error("Speech previews must be nonempty files of at most 5 MiB");
|
|
21287
|
-
const bytes = new Uint8Array(await readFile2(path));
|
|
21288
|
-
if (!bytes.length || bytes.length > 5 * 1024 * 1024) throw new Error("Speech previews must be nonempty and at most 5 MiB");
|
|
21289
|
-
const { client } = await clientFor(command);
|
|
21290
|
-
emit(io, command, await client.upload(speechPreviewPath(id, voice), { bytes, filename, contentType }));
|
|
21291
|
-
});
|
|
21292
|
-
speechPreview.command("download <id> <voice>").requiredOption("-o, --output <path>", "destination audio file").action(async (id, voice, options2, command) => {
|
|
21293
|
-
const { client } = await clientFor(command);
|
|
21294
|
-
const result = await client.download(speechPreviewPath(id, voice));
|
|
21295
|
-
await writeFile2(options2.output, result.bytes, { mode: 384 });
|
|
21296
|
-
emit(io, command, { id, voice, output: options2.output });
|
|
21297
|
-
});
|
|
21298
|
-
speechPreview.command("delete <id> <voice>").description("Remove a voice preview without deleting its voice").action(async (id, voice, _options, command) => {
|
|
21299
|
-
const options2 = globalOptions(command);
|
|
21300
|
-
await confirmExact(io, `${id}/${voice}`, Boolean(options2.yes), Boolean(options2.json));
|
|
21301
|
-
const { client } = await clientFor(command);
|
|
21302
|
-
await client.request(speechPreviewPath(id, voice), { method: "DELETE" });
|
|
21303
|
-
emit(io, command, { id, voice, deleted: true });
|
|
21304
|
-
});
|
|
21305
21280
|
const voicePath = (id, voice) => `/api/management/v1/speech-models/${encodeURIComponent(id)}/voices/${encodeURIComponent(voice)}`;
|
|
21306
21281
|
speechModel.command("provider-voices <id>").action(async (id, _options, command) => {
|
|
21307
21282
|
const { client } = await clientFor(command);
|
|
@@ -21348,9 +21323,9 @@ function createProgram(io = processIo, dependencies = {}) {
|
|
|
21348
21323
|
});
|
|
21349
21324
|
}
|
|
21350
21325
|
}
|
|
21351
|
-
speechModel.command("test-voice <id> <voice>").requiredOption("-o, --output <path>").option("--text <text>", "text to synthesize
|
|
21326
|
+
speechModel.command("test-voice <id> <voice>").requiredOption("-o, --output <path>").option("--text <text>", "text to synthesize (defaults to the voice preview text)").action(async (id, voice, options2, command) => {
|
|
21352
21327
|
const { client } = await clientFor(command);
|
|
21353
|
-
const result = await client.download(`${voicePath(id, voice)}/test`, 12e4, { method: "POST", body: { input: options2.text
|
|
21328
|
+
const result = await client.download(`${voicePath(id, voice)}/test`, 12e4, { method: "POST", body: { ...options2.text !== void 0 ? { input: options2.text } : {} } });
|
|
21354
21329
|
await writeFile2(options2.output, result.bytes, { mode: 384 });
|
|
21355
21330
|
emit(io, command, { output: options2.output });
|
|
21356
21331
|
});
|