threenative-asset-mcp 0.9.1 → 0.9.3
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 +88 -0
- package/dist/audio/fsutil.d.ts +7 -0
- package/dist/audio/fsutil.d.ts.map +1 -0
- package/dist/audio/fsutil.js +37 -0
- package/dist/audio/fsutil.js.map +1 -0
- package/dist/audio/generate.d.ts +95 -0
- package/dist/audio/generate.d.ts.map +1 -0
- package/dist/audio/generate.js +405 -0
- package/dist/audio/generate.js.map +1 -0
- package/dist/audio/inspect.d.ts +123 -0
- package/dist/audio/inspect.d.ts.map +1 -0
- package/dist/audio/inspect.js +464 -0
- package/dist/audio/inspect.js.map +1 -0
- package/dist/audio/semantic.d.ts +66 -0
- package/dist/audio/semantic.d.ts.map +1 -0
- package/dist/audio/semantic.js +197 -0
- package/dist/audio/semantic.js.map +1 -0
- package/dist/fab/api-download.d.ts.map +1 -1
- package/dist/fab/api-download.js +18 -2
- package/dist/fab/api-download.js.map +1 -1
- package/dist/fab/fabcli.d.ts.map +1 -1
- package/dist/fab/fabcli.js +8 -1
- package/dist/fab/fabcli.js.map +1 -1
- package/dist/fab/normalize.d.ts.map +1 -1
- package/dist/fab/normalize.js +4 -0
- package/dist/fab/normalize.js.map +1 -1
- package/dist/polyhaven/pack.d.ts +53 -0
- package/dist/polyhaven/pack.d.ts.map +1 -0
- package/dist/polyhaven/pack.js +104 -0
- package/dist/polyhaven/pack.js.map +1 -0
- package/dist/server.d.ts +5 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +33 -1
- package/dist/server.js.map +1 -1
- package/dist/tools/audio.d.ts +622 -0
- package/dist/tools/audio.d.ts.map +1 -1
- package/dist/tools/audio.js +217 -1
- package/dist/tools/audio.js.map +1 -1
- package/dist/tools/polyhaven-import.d.ts +58 -0
- package/dist/tools/polyhaven-import.d.ts.map +1 -0
- package/dist/tools/polyhaven-import.js +121 -0
- package/dist/tools/polyhaven-import.js.map +1 -0
- package/dist/unreal/importer.d.ts +6 -1
- package/dist/unreal/importer.d.ts.map +1 -1
- package/dist/unreal/importer.js +61 -20
- package/dist/unreal/importer.js.map +1 -1
- package/dist/unreal/materials.d.ts.map +1 -1
- package/dist/unreal/materials.js +39 -7
- package/dist/unreal/materials.js.map +1 -1
- package/dist/unreal/provision.d.ts +6 -1
- package/dist/unreal/provision.d.ts.map +1 -1
- package/dist/unreal/provision.js +23 -6
- package/dist/unreal/provision.js.map +1 -1
- package/dist/unreal/psa.d.ts.map +1 -1
- package/dist/unreal/psa.js +27 -9
- package/dist/unreal/psa.js.map +1 -1
- package/package.json +3 -1
- package/scripts/audio-semantic.py +168 -0
package/README.md
CHANGED
|
@@ -35,6 +35,11 @@ dependency relationships with pagination and resolution/format filters.
|
|
|
35
35
|
- A local environment capable of running Playwright Chromium when Fab requests
|
|
36
36
|
browser verification
|
|
37
37
|
- No Epic or Fab login is required or automated
|
|
38
|
+
- **FFmpeg and FFprobe on `PATH`** for `audio_inspect_asset` and
|
|
39
|
+
`audio_generate_sound`. Without them nothing is decoded, and the tools report
|
|
40
|
+
that they could not check rather than reporting a pass.
|
|
41
|
+
- An **ElevenLabs API key of your own** for `audio_generate_sound` only. Every
|
|
42
|
+
other tool, including local audio inspection, works without one.
|
|
38
43
|
|
|
39
44
|
## Install
|
|
40
45
|
|
|
@@ -192,6 +197,83 @@ Game audio:
|
|
|
192
197
|
`acceptLicense: true`. It uses an HTTPS host allowlist, validates every
|
|
193
198
|
redirect, streams with a byte cap, writes atomically without overwrite, and
|
|
194
199
|
returns the local path, byte size, and SHA-256.
|
|
200
|
+
- `audio_inspect_asset` — measures one local WAV, Ogg, MP3, or FLAC with the
|
|
201
|
+
pinned `@threenative/playtest` inspector: decode integrity, silence floor,
|
|
202
|
+
peak ceiling, DC offset, a five-band spectrum, the loop seam of a **declared**
|
|
203
|
+
loop, and the requested duration, plus a spectrogram PNG. Needs no ElevenLabs
|
|
204
|
+
key and never modifies or repairs the file. Optionally compares prompt and
|
|
205
|
+
emotional tone when local CLAP is provisioned.
|
|
206
|
+
- `audio_generate_sound` — **spends ElevenLabs credits.** Generates one sound
|
|
207
|
+
effect or ambience from a prompt using *your own* `ELEVENLABS_API_KEY`, saves
|
|
208
|
+
the original response plus a PCM16 WAV, and runs the same inspection
|
|
209
|
+
automatically. Reusing a `requestId` returns the saved result instead of
|
|
210
|
+
charging again.
|
|
211
|
+
|
|
212
|
+
### Generating a sound
|
|
213
|
+
|
|
214
|
+
The loop is **generate once → inspect → revise the one property that failed →
|
|
215
|
+
explicitly generate again.** There is no best-of-N retry: every generation is a
|
|
216
|
+
separate billable invocation you ask for on purpose.
|
|
217
|
+
|
|
218
|
+
Describe source, action, material, distance, and timing. A useful brief:
|
|
219
|
+
|
|
220
|
+
> One short metal latch closing, close microphone, dry recording, single event
|
|
221
|
+
> with natural decay, no speech or music.
|
|
222
|
+
|
|
223
|
+
These are prompting conventions absorbed from ElevenLabs' own
|
|
224
|
+
[sound-effects skill](https://github.com/elevenlabs/skills/blob/9edcbd4b80ed57b8e07a3f86ea520333969fbc3c/sound-effects/SKILL.md)
|
|
225
|
+
(MIT, reviewed at commit `9edcbd4b`), which is linked and attributed rather than
|
|
226
|
+
installed. They are conventions, not guaranteed exclusion controls.
|
|
227
|
+
|
|
228
|
+
`audio_generate_sound` requires `ELEVENLABS_API_KEY` in the server environment.
|
|
229
|
+
It is never bundled, defaulted, or logged: without your own key the tool fails
|
|
230
|
+
with `AUDIO_GENERATE_NO_CREDENTIALS` and an instruction to set one, while the
|
|
231
|
+
catalog and inspection tools keep working normally.
|
|
232
|
+
|
|
233
|
+
What the inspection does and does not tell you:
|
|
234
|
+
|
|
235
|
+
| It answers | It does not answer |
|
|
236
|
+
| --- | --- |
|
|
237
|
+
| Is it broken, silent, clipped, DC-offset, or the wrong duration? | Is it a *good* sound? |
|
|
238
|
+
| Does a declared loop click at the wrap? | Does it suit this scene? |
|
|
239
|
+
| Is the frequency content inside bounds *you* supplied? | Is the mix right? |
|
|
240
|
+
|
|
241
|
+
`artisticQuality` is always `"unverified"`. There is no `soundsGood` flag and no
|
|
242
|
+
single quality score. `recommendation: "audition"` means the technical checks
|
|
243
|
+
passed and every requested check completed — it means *go listen to it*, not
|
|
244
|
+
*ship it*. A definite technical failure recommends `"reject"`; a warning, a
|
|
245
|
+
possible mismatch, or an incomplete requested check recommends `"review"`.
|
|
246
|
+
|
|
247
|
+
If asset compilation rewrites the bytes, inspect the compiled output before
|
|
248
|
+
describing that output as checked.
|
|
249
|
+
|
|
250
|
+
### Optional local CLAP setup
|
|
251
|
+
|
|
252
|
+
Prompt fit and emotion fit are **off by default** (`semantic: "off"`) and add no
|
|
253
|
+
dependency to `npm install`. To enable them:
|
|
254
|
+
|
|
255
|
+
```sh
|
|
256
|
+
python3 -m venv ~/.venvs/clap
|
|
257
|
+
~/.venvs/clap/bin/pip install "laion-clap==1.1.6" "torch==2.4.1" \
|
|
258
|
+
"torchaudio==2.4.1" "librosa==0.10.2.post1" "numpy<2"
|
|
259
|
+
# Download 630k-audioset-best.pt from the LAION-AI/CLAP releases and check its hash.
|
|
260
|
+
export AUDIO_CLAP_CHECKPOINT=/path/to/630k-audioset-best.pt
|
|
261
|
+
export AUDIO_CLAP_PYTHON=~/.venvs/clap/bin/python
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
Nothing is downloaded implicitly and no GPU is required. With `semantic: "clap"`
|
|
265
|
+
and no provisioned model, you get the technical result plus an explicit
|
|
266
|
+
unavailable semantic result and this instruction — never a semantic pass. A
|
|
267
|
+
generation that requests `semantic: "clap"` is refused in preflight, before
|
|
268
|
+
spending, when the model is missing.
|
|
269
|
+
|
|
270
|
+
Scores are cosine similarities used as **supporting evidence**, never
|
|
271
|
+
probabilities or quality grades. The emotion check builds otherwise identical
|
|
272
|
+
hypotheses — `The sound of {sourceDescription}, with a {mood} emotional tone.` —
|
|
273
|
+
so only the mood clause differs, and **this use of CLAP is a proposed heuristic,
|
|
274
|
+
not a demonstrated emotion-recognition capability**: mood status stays
|
|
275
|
+
`unverified` until the held-out emotion calibration qualifies your domain. Check
|
|
276
|
+
the CLAP code and checkpoint licensing separately before redistributing either.
|
|
195
277
|
|
|
196
278
|
Curated itch.io packs:
|
|
197
279
|
|
|
@@ -267,6 +349,7 @@ require manually installed tools instead.
|
|
|
267
349
|
| Cooked loose UE4 static meshes and textures | GLB geometry, LOD sections, embedded textures, and common PBR reconstruction |
|
|
268
350
|
| Cooked loose UE4 skeletal meshes and standalone animation packages | Standard skinned GLB; joints, weights, inverse-bind matrices, and existing clips are preserved; ActorX PSA clips are attached by case-insensitive bone name when at least 80% of tracks match, without duplicating an existing clip name |
|
|
269
351
|
| Uncooked UE4 `FMeshDescription` static meshes (object versions 517–522) | GLB geometry with centimetres converted to metres; verified on Fab Office Pack Vol.1 (47/47 meshes) |
|
|
352
|
+
| Uncooked UE4.0–4.20 static and skeletal meshes (object versions below 517) | Exported by UE Viewer from the editor source data, with materials, skins, and ActorX clips like cooked packages. Verified on Fab packs from UE4.10 to UE4.20: Modular Building Set (129 meshes), Animal Variety Pack (6 rigged animals, 146 clips), STF Landscape Pro 2.0 (61), Power Plant (65), and a UE4.19 fern pack (38) |
|
|
270
353
|
| Standalone `Texture2D` packages | Collision-free source-relative PNGs under `textures/`; duplicate Unreal basenames are exported independently instead of overwriting one another |
|
|
271
354
|
| `TextureCube` environment maps | Collision-free 2:1 equirectangular PNG or lossless Radiance HDR files under `cubemaps/`; CUE4Parse decodes cooked faces, while editor `TSF_BGRE8` source art retains its lighting range without Unreal Engine |
|
|
272
355
|
| `Texture2DArray`, `TextureCubeArray`, and `VolumeTexture` | Collision-free RGBA8 slice data plus JSON dimensions under `textures3d/`; use `DataArrayTexture` for arrays and `Data3DTexture` for volumes. Cube-array faces remain ordered in groups of six for custom shaders. Floating-point/HDR stacks are rejected rather than reduced to RGBA8 |
|
|
@@ -399,6 +482,11 @@ glTF's standard punctual-light extension has no area-light type.
|
|
|
399
482
|
| `AUDIO_DOWNLOAD_DIR` | `~/Downloads/threenative-asset-mcp/audio` | Dedicated directory for curated audio downloads. |
|
|
400
483
|
| `AUDIO_MAX_DOWNLOAD_BYTES` | `10737418240` | Maximum accepted bytes per audio archive (10 GiB). |
|
|
401
484
|
| `AUDIO_DOWNLOAD_TIMEOUT_MS` | `1800000` | Total timeout for one audio download (30 minutes). |
|
|
485
|
+
| `ELEVENLABS_API_KEY` | unset | **Your own** key; required only by `audio_generate_sound`. Never bundled or logged. |
|
|
486
|
+
| `AUDIO_INSPECT_ROOTS` | the audio dir plus the launch directory | Extra `:`-separated roots `audio_inspect_asset` may read. |
|
|
487
|
+
| `AUDIO_CLAP_PYTHON` | unset | Interpreter with LAION-CLAP installed; enables `semantic: "clap"`. |
|
|
488
|
+
| `AUDIO_CLAP_CHECKPOINT` | unset | Path to the `630k-audioset-best.pt` checkpoint. |
|
|
489
|
+
| `AUDIO_CLAP_CHECKPOINT_SHA256` | unset | Optional pin; a mismatched checkpoint is refused. |
|
|
402
490
|
| `ASSET_DOWNLOAD_DIR` | `~/Downloads/threenative-asset-mcp/assets` | Dedicated directory for direct provider downloads. |
|
|
403
491
|
| `ASSET_MAX_DOWNLOAD_BYTES` | `10737418240` | Maximum accepted bytes per provider file (10 GiB). |
|
|
404
492
|
| `ASSET_DOWNLOAD_TIMEOUT_MS` | `1800000` | Total timeout for one provider download (30 minutes). |
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/** True when `path` is `parent` itself or lies beneath it. Both must already be real paths. */
|
|
2
|
+
export declare function isInside(path: string, parent: string): boolean;
|
|
3
|
+
export declare function sha256File(path: string): Promise<string>;
|
|
4
|
+
export declare function sha256Bytes(value: Uint8Array): string;
|
|
5
|
+
/** Stable hash of a plain JSON value: object key order must not change the digest. */
|
|
6
|
+
export declare function sha256Json(value: unknown): string;
|
|
7
|
+
//# sourceMappingURL=fsutil.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fsutil.d.ts","sourceRoot":"","sources":["../../src/audio/fsutil.ts"],"names":[],"mappings":"AAIA,+FAA+F;AAC/F,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAG9D;AAED,wBAAsB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAS9D;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAErD;AAED,sFAAsF;AACtF,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAEjD"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { createReadStream } from "node:fs";
|
|
3
|
+
import { isAbsolute, relative } from "node:path";
|
|
4
|
+
/** True when `path` is `parent` itself or lies beneath it. Both must already be real paths. */
|
|
5
|
+
export function isInside(path, parent) {
|
|
6
|
+
const child = relative(parent, path);
|
|
7
|
+
return child === "" || (!child.startsWith("..") && !isAbsolute(child));
|
|
8
|
+
}
|
|
9
|
+
export async function sha256File(path) {
|
|
10
|
+
const hash = createHash("sha256");
|
|
11
|
+
await new Promise((done, fail) => {
|
|
12
|
+
const stream = createReadStream(path);
|
|
13
|
+
stream.on("data", (chunk) => hash.update(chunk));
|
|
14
|
+
stream.on("error", fail);
|
|
15
|
+
stream.on("end", done);
|
|
16
|
+
});
|
|
17
|
+
return hash.digest("hex");
|
|
18
|
+
}
|
|
19
|
+
export function sha256Bytes(value) {
|
|
20
|
+
return createHash("sha256").update(value).digest("hex");
|
|
21
|
+
}
|
|
22
|
+
/** Stable hash of a plain JSON value: object key order must not change the digest. */
|
|
23
|
+
export function sha256Json(value) {
|
|
24
|
+
return createHash("sha256").update(canonicalJson(value)).digest("hex");
|
|
25
|
+
}
|
|
26
|
+
function canonicalJson(value) {
|
|
27
|
+
if (value === null || typeof value !== "object")
|
|
28
|
+
return JSON.stringify(value) ?? "null";
|
|
29
|
+
if (Array.isArray(value))
|
|
30
|
+
return `[${value.map(canonicalJson).join(",")}]`;
|
|
31
|
+
const entries = Object.entries(value)
|
|
32
|
+
.filter(([, item]) => item !== undefined)
|
|
33
|
+
.sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0))
|
|
34
|
+
.map(([key, item]) => `${JSON.stringify(key)}:${canonicalJson(item)}`);
|
|
35
|
+
return `{${entries.join(",")}}`;
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=fsutil.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fsutil.js","sourceRoot":"","sources":["../../src/audio/fsutil.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAC3C,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAEjD,+FAA+F;AAC/F,MAAM,UAAU,QAAQ,CAAC,IAAY,EAAE,MAAc;IACnD,MAAM,KAAK,GAAG,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IACrC,OAAO,KAAK,KAAK,EAAE,IAAI,CAAC,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC;AACzE,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,IAAY;IAC3C,MAAM,IAAI,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC;IAClC,MAAM,IAAI,OAAO,CAAO,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE;QACrC,MAAM,MAAM,GAAG,gBAAgB,CAAC,IAAI,CAAC,CAAC;QACtC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;QACjD,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;QACzB,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IACzB,CAAC,CAAC,CAAC;IACH,OAAO,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAC5B,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,KAAiB;IAC3C,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAC1D,CAAC;AAED,sFAAsF;AACtF,MAAM,UAAU,UAAU,CAAC,KAAc;IACvC,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AACzE,CAAC;AAED,SAAS,aAAa,CAAC,KAAc;IACnC,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC;IACxF,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,IAAI,KAAK,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;IAC3E,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,KAAgC,CAAC;SAC7D,MAAM,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,IAAI,KAAK,SAAS,CAAC;SACxC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;SAChD,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,aAAa,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACzE,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;AAClC,CAAC"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { type AudioInspectRequest, type AudioInspectResult, type AudioInspectorOptions } from "./inspect.js";
|
|
2
|
+
/**
|
|
3
|
+
* One billed ElevenLabs sound-effect generation, saved and then inspected.
|
|
4
|
+
*
|
|
5
|
+
* The whole design here is about never charging twice. A `requestId` reserves a directory and a
|
|
6
|
+
* normalized-request hash *before* the POST, every durable step is written down as it completes, and
|
|
7
|
+
* a replay resumes from whichever verified bytes already exist. A submission whose outcome we never
|
|
8
|
+
* learned stays `outcome_unknown` forever: repeating that id never resubmits, because the provider
|
|
9
|
+
* may well have billed for it.
|
|
10
|
+
*/
|
|
11
|
+
export type AudioGenerateErrorCode = "AUDIO_GENERATE_NO_CREDENTIALS" | "AUDIO_GENERATE_INVALID_INPUT" | "AUDIO_GENERATE_REQUEST_CONFLICT" | "AUDIO_GENERATE_OUTCOME_UNKNOWN" | "AUDIO_GENERATE_PREREQUISITE_MISSING" | "AUDIO_GENERATE_AUTH_FAILED" | "AUDIO_GENERATE_RATE_LIMITED" | "AUDIO_GENERATE_REJECTED" | "AUDIO_GENERATE_UPSTREAM" | "AUDIO_GENERATE_TIMEOUT" | "AUDIO_GENERATE_TOO_LARGE" | "AUDIO_GENERATE_UNSAFE_REDIRECT" | "AUDIO_GENERATE_STORAGE" | "AUDIO_GENERATE_CONVERT_FAILED" | "AUDIO_GENERATE_HASH_MISMATCH";
|
|
12
|
+
export declare class AudioGenerateError extends Error {
|
|
13
|
+
readonly code: AudioGenerateErrorCode;
|
|
14
|
+
readonly retryable: boolean;
|
|
15
|
+
constructor(code: AudioGenerateErrorCode, message: string, retryable?: boolean);
|
|
16
|
+
}
|
|
17
|
+
export declare const GENERATE_LIMITS: {
|
|
18
|
+
/** Our policy cap, not a claimed provider maximum. */
|
|
19
|
+
readonly maxPromptChars: 2000;
|
|
20
|
+
readonly minDurationSeconds: 0.5;
|
|
21
|
+
readonly maxDurationSeconds: 30;
|
|
22
|
+
readonly maxResponseBytes: number;
|
|
23
|
+
readonly timeoutMs: 120000;
|
|
24
|
+
};
|
|
25
|
+
export interface AudioGenerateRequest {
|
|
26
|
+
requestId: string;
|
|
27
|
+
prompt: string;
|
|
28
|
+
durationSeconds?: number | undefined;
|
|
29
|
+
loop?: boolean | undefined;
|
|
30
|
+
promptInfluence?: number | undefined;
|
|
31
|
+
inspection?: Omit<AudioInspectRequest, "path" | "loop" | "expectedDurationSeconds" | "expectedPrompt"> | undefined;
|
|
32
|
+
}
|
|
33
|
+
interface NormalizedRequest {
|
|
34
|
+
text: string;
|
|
35
|
+
duration_seconds: number;
|
|
36
|
+
loop: boolean;
|
|
37
|
+
prompt_influence: number;
|
|
38
|
+
model_id: string;
|
|
39
|
+
output_format: string;
|
|
40
|
+
}
|
|
41
|
+
export interface AudioGenerateResult {
|
|
42
|
+
requestId: string;
|
|
43
|
+
provider: "elevenlabs";
|
|
44
|
+
model: string;
|
|
45
|
+
normalizedRequest: NormalizedRequest;
|
|
46
|
+
generatedAt: string;
|
|
47
|
+
generation: "saved";
|
|
48
|
+
sourcePath: string;
|
|
49
|
+
sourceSha256: string;
|
|
50
|
+
sourceSizeBytes: number;
|
|
51
|
+
wavPath: string;
|
|
52
|
+
wavSha256: string;
|
|
53
|
+
wavSizeBytes: number;
|
|
54
|
+
providerRequestId?: string;
|
|
55
|
+
billingUnits?: string;
|
|
56
|
+
commercialUse: "unverified";
|
|
57
|
+
providerTermsUrl: string;
|
|
58
|
+
receiptPath: string;
|
|
59
|
+
replayed: boolean;
|
|
60
|
+
inspection: AudioInspectResult;
|
|
61
|
+
}
|
|
62
|
+
export interface AudioGeneratorOptions extends AudioInspectorOptions {
|
|
63
|
+
fetch?: typeof globalThis.fetch;
|
|
64
|
+
apiKey?: string;
|
|
65
|
+
ffmpegPath?: string;
|
|
66
|
+
}
|
|
67
|
+
export declare class AudioGenerator {
|
|
68
|
+
private readonly fetch;
|
|
69
|
+
private readonly audioDir;
|
|
70
|
+
private readonly apiKeyOverride;
|
|
71
|
+
private readonly ffmpegPath;
|
|
72
|
+
private readonly inspector;
|
|
73
|
+
constructor(options?: AudioGeneratorOptions);
|
|
74
|
+
/**
|
|
75
|
+
* The key is the operator's, read from their environment at call time. It is never defaulted,
|
|
76
|
+
* never written to a receipt, never logged and never returned — a missing one is an error the
|
|
77
|
+
* agent is expected to relay to the person running the server.
|
|
78
|
+
*/
|
|
79
|
+
private apiKey;
|
|
80
|
+
generate(request: AudioGenerateRequest): Promise<AudioGenerateResult>;
|
|
81
|
+
/** Local-only completion: convert, inspect, finish. Never reaches the provider, never charges. */
|
|
82
|
+
private resume;
|
|
83
|
+
private preflight;
|
|
84
|
+
/** Exclusive reservation: two concurrent duplicates cannot both get past this. */
|
|
85
|
+
private reserve;
|
|
86
|
+
private submit;
|
|
87
|
+
/**
|
|
88
|
+
* Decode to PCM16 WAV with no resampling, no downmix, no normalization and no trimming. Turning
|
|
89
|
+
* MP3 into WAV does not restore what the encoder threw away, and pretending otherwise by
|
|
90
|
+
* "cleaning up" here would hide the defect the inspection exists to find.
|
|
91
|
+
*/
|
|
92
|
+
private toWav;
|
|
93
|
+
}
|
|
94
|
+
export {};
|
|
95
|
+
//# sourceMappingURL=generate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generate.d.ts","sourceRoot":"","sources":["../../src/audio/generate.ts"],"names":[],"mappings":"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"}
|