sonilo 0.7.0 → 0.9.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/README.md +46 -2
- package/dist/index.cjs +23 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +79 -8
- package/dist/index.d.ts +79 -8
- package/dist/index.js +23 -6
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -11,7 +11,7 @@ npm install sonilo
|
|
|
11
11
|
|
|
12
12
|
## Authentication
|
|
13
13
|
|
|
14
|
-
Create an API key in your [Sonilo dashboard](https://platform.sonilo.com/dashboard/api-keys),
|
|
14
|
+
Create an API key in your [Sonilo dashboard](https://platform.sonilo.com/dashboard/api-keys?utm_source=sonilo_js&utm_medium=readme&utm_campaign=sdk_quickstart),
|
|
15
15
|
then give it to the client either as an environment variable (recommended) or
|
|
16
16
|
inline:
|
|
17
17
|
|
|
@@ -107,6 +107,46 @@ if (result.ducked) {
|
|
|
107
107
|
}
|
|
108
108
|
```
|
|
109
109
|
|
|
110
|
+
### Variants (async)
|
|
111
|
+
|
|
112
|
+
`variantsNum` generates several distinct music variants in one request (1-10,
|
|
113
|
+
default 1) — each is its own creative direction, with its own title. It's
|
|
114
|
+
available on `textToMusic`, `videoToMusic`, `videoToVideoMusic`,
|
|
115
|
+
`videoToSound` and `videoToVideoSound`. Cost scales linearly with the count,
|
|
116
|
+
and **values above 1 are never covered by the free trial**.
|
|
117
|
+
|
|
118
|
+
On `textToMusic`/`videoToMusic`, `variantsNum` above 1 requires the async task
|
|
119
|
+
API — same as `preserveSpeech` above — so it implies `mode: "async"` if you
|
|
120
|
+
don't set `mode` yourself; `stream()`/`generate()` never send it, since they
|
|
121
|
+
always request a plain stream. `videoToVideoMusic`, `videoToSound` and
|
|
122
|
+
`videoToVideoSound` are already async-only, so no extra `mode` handling is
|
|
123
|
+
needed there.
|
|
124
|
+
|
|
125
|
+
```ts
|
|
126
|
+
const task = await client.textToMusic.submit({
|
|
127
|
+
prompt: "warm lo-fi piano",
|
|
128
|
+
duration: 30,
|
|
129
|
+
variantsNum: 3,
|
|
130
|
+
});
|
|
131
|
+
const result = await client.tasks.wait<MusicTaskResult>(task.task_id);
|
|
132
|
+
|
|
133
|
+
// audio has one entry per variant; each entry may carry its own `title`.
|
|
134
|
+
for (const variant of result.audio ?? []) {
|
|
135
|
+
console.log(variant.title?.title, variant.url);
|
|
136
|
+
}
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
`videoToVideoMusic` returns one video per variant in `videos[]`, with `video`
|
|
140
|
+
kept as a permanent alias for `videos[0]`. `videoToSound`/`videoToVideoSound`
|
|
141
|
+
return one entry per variant in `outputs[]`, each shaped like the top-level
|
|
142
|
+
result (`output_url`, `output_type`, `output_bytes`, `music`,
|
|
143
|
+
`music_processed?`, `sfx`) — the top-level fields remain permanent aliases for
|
|
144
|
+
`outputs[0]`. All of these arrays are present even at the default
|
|
145
|
+
`variantsNum` of 1, as a single-entry array; every other field is unchanged.
|
|
146
|
+
|
|
147
|
+
`GET /v1/tasks/{id}` (`tasks.get`/`tasks.wait`) echoes the request's
|
|
148
|
+
`variantsNum` back as `variants_num`, but only when it was above 1.
|
|
149
|
+
|
|
110
150
|
## Video to video
|
|
111
151
|
|
|
112
152
|
Generate a soundtrack or sound effects and get back a **re-hosted video** with
|
|
@@ -215,7 +255,11 @@ const result = await client.dubbing.generate(
|
|
|
215
255
|
Params: exactly one of `video` / `videoUrl` (`videoUrl` must be **https** —
|
|
216
256
|
the dubbing pipeline fetches the source itself and rejects plain http). The
|
|
217
257
|
optional `languages` array defaults to `["zh_cn", "es", "fr"]`; supported
|
|
218
|
-
codes are `en, zh_cn, ja, ko, pt, es, de, fr, it, ru`.
|
|
258
|
+
codes are `en, zh_cn, ja, ko, pt, es, de, fr, it, ru`. The optional `ducking`
|
|
259
|
+
boolean (default off, free) ducks the background music/effects bed under the
|
|
260
|
+
dubbed voice while it speaks; when off the bed is kept at a constant level.
|
|
261
|
+
Note this default is the opposite of video-to-music's `ducking`, which is on
|
|
262
|
+
by default.
|
|
219
263
|
|
|
220
264
|
Dubbing is async-only, and the source video may be at most 180 seconds long.
|
|
221
265
|
You are billed per language. Dubbing has **no free trial allowance** — unlike
|
package/dist/index.cjs
CHANGED
|
@@ -347,7 +347,8 @@ var TextToMusic = class {
|
|
|
347
347
|
/**
|
|
348
348
|
* Submit an async text-to-music task; poll with
|
|
349
349
|
* `client.tasks.wait<MusicTaskResult>(task.task_id)`. Required for
|
|
350
|
-
* `outputFormat: "wav"
|
|
350
|
+
* `outputFormat: "wav"` and `variantsNum` above 1. `stream()`/`generate()`
|
|
351
|
+
* remain the streaming path.
|
|
351
352
|
*/
|
|
352
353
|
async submit(params) {
|
|
353
354
|
const mode = params.mode ?? "async";
|
|
@@ -364,6 +365,9 @@ var TextToMusic = class {
|
|
|
364
365
|
if (params.outputFormat !== void 0) {
|
|
365
366
|
form.set("output_format", params.outputFormat);
|
|
366
367
|
}
|
|
368
|
+
if (params.variantsNum !== void 0) {
|
|
369
|
+
form.set("variants_num", String(params.variantsNum));
|
|
370
|
+
}
|
|
367
371
|
const res = await this.client.request("/v1/text-to-music", {
|
|
368
372
|
method: "POST",
|
|
369
373
|
body: form
|
|
@@ -444,19 +448,20 @@ var VideoToMusic = class {
|
|
|
444
448
|
/**
|
|
445
449
|
* Submit an async video-to-music task; poll its result with
|
|
446
450
|
* `client.tasks.wait<MusicTaskResult>(task.task_id)`. Required for
|
|
447
|
-
* `isolateVocals`
|
|
448
|
-
*
|
|
451
|
+
* `isolateVocals`/`preserveSpeech`, `outputFormat: "wav"`, and
|
|
452
|
+
* `variantsNum` above 1 — the backend rejects all of these on the plain
|
|
453
|
+
* stream, and they only ever run in async mode.
|
|
449
454
|
*/
|
|
450
455
|
async submit(params) {
|
|
451
456
|
if (params.video === void 0 === (params.videoUrl === void 0)) {
|
|
452
457
|
throw new SoniloError("Provide exactly one of video or videoUrl");
|
|
453
458
|
}
|
|
454
459
|
let mode = params.mode;
|
|
455
|
-
const needsAsync = params.isolateVocals || params.preserveSpeech || params.ducking !== void 0 || params.outputFormat === "wav";
|
|
460
|
+
const needsAsync = params.isolateVocals || params.preserveSpeech || params.ducking !== void 0 || params.outputFormat === "wav" || params.variantsNum !== void 0 && params.variantsNum > 1;
|
|
456
461
|
if (mode === void 0) mode = "async";
|
|
457
462
|
if (needsAsync && mode !== "async") {
|
|
458
463
|
throw new SoniloError(
|
|
459
|
-
'isolateVocals/preserveSpeech/ducking/outputFormat "wav" require mode: "async"'
|
|
464
|
+
'isolateVocals/preserveSpeech/ducking/outputFormat "wav"/variantsNum > 1 require mode: "async"'
|
|
460
465
|
);
|
|
461
466
|
}
|
|
462
467
|
const form = new FormData();
|
|
@@ -483,6 +488,9 @@ var VideoToMusic = class {
|
|
|
483
488
|
if (params.ducking !== void 0) {
|
|
484
489
|
form.set("ducking", String(params.ducking));
|
|
485
490
|
}
|
|
491
|
+
if (params.variantsNum !== void 0) {
|
|
492
|
+
form.set("variants_num", String(params.variantsNum));
|
|
493
|
+
}
|
|
486
494
|
const res = await this.client.request("/v1/video-to-music", {
|
|
487
495
|
method: "POST",
|
|
488
496
|
body: form
|
|
@@ -569,6 +577,9 @@ var VideoToVideoMusic = class {
|
|
|
569
577
|
if (params.isolateVocals !== void 0) {
|
|
570
578
|
form.set("isolate_vocals", String(params.isolateVocals));
|
|
571
579
|
}
|
|
580
|
+
if (params.variantsNum !== void 0) {
|
|
581
|
+
form.set("variants_num", String(params.variantsNum));
|
|
582
|
+
}
|
|
572
583
|
const res = await this.client.request("/v1/video-to-video-music", {
|
|
573
584
|
method: "POST",
|
|
574
585
|
body: form
|
|
@@ -634,6 +645,9 @@ async function buildSoundForm(params) {
|
|
|
634
645
|
form.set("preserve_speech", String(params.preserveSpeech));
|
|
635
646
|
}
|
|
636
647
|
if (params.ducking !== void 0) form.set("ducking", String(params.ducking));
|
|
648
|
+
if (params.variantsNum !== void 0) {
|
|
649
|
+
form.set("variants_num", String(params.variantsNum));
|
|
650
|
+
}
|
|
637
651
|
return form;
|
|
638
652
|
}
|
|
639
653
|
|
|
@@ -694,6 +708,9 @@ async function buildDubbingForm(params) {
|
|
|
694
708
|
if (params.languages !== void 0) {
|
|
695
709
|
form.set("languages", JSON.stringify(params.languages));
|
|
696
710
|
}
|
|
711
|
+
if (params.ducking !== void 0) {
|
|
712
|
+
form.set("ducking", String(params.ducking));
|
|
713
|
+
}
|
|
697
714
|
return form;
|
|
698
715
|
}
|
|
699
716
|
var Dubbing = class {
|
|
@@ -714,7 +731,7 @@ var Dubbing = class {
|
|
|
714
731
|
};
|
|
715
732
|
|
|
716
733
|
// src/version.ts
|
|
717
|
-
var VERSION = "0.
|
|
734
|
+
var VERSION = "0.9.0";
|
|
718
735
|
|
|
719
736
|
// src/client.ts
|
|
720
737
|
var DEFAULT_BASE_URL = "https://api.sonilo.com";
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/errors.ts","../src/resources/account.ts","../src/resources/tasks.ts","../src/streaming.ts","../src/resources/textToMusic.ts","../src/upload.ts","../src/resources/videoToMusic.ts","../src/resources/textToSfx.ts","../src/resources/videoToSfx.ts","../src/resources/videoToVideoMusic.ts","../src/resources/videoToVideoSfx.ts","../src/resources/soundForm.ts","../src/resources/videoToSound.ts","../src/resources/videoToVideoSound.ts","../src/resources/dubbing.ts","../src/version.ts","../src/client.ts","../src/download.ts","../src/types.ts"],"sourcesContent":["export { DEFAULT_TIMEOUT_MS, SoniloClient, type SoniloClientOptions } from \"./client.js\";\nexport {\n APIError,\n AuthenticationError,\n BadRequestError,\n GenerationError,\n PaymentRequiredError,\n RateLimitError,\n RequestTimeoutError,\n SoniloError,\n TaskFailedError,\n TaskTimeoutError,\n TrialExhaustedError,\n} from \"./errors.js\";\nexport { download } from \"./download.js\";\nexport { VERSION } from \"./version.js\";\nexport type {\n AccountServices,\n AudioChunkEvent,\n BaseTaskResult,\n CompleteEvent,\n CostEvent,\n CostInfo,\n DailyUsage,\n DubbingLanguage,\n DubbingParams,\n DubbingResult,\n ErrorEvent,\n MusicMediaEntry,\n MusicMuxEntry,\n MusicTaskResult,\n MusicTitle,\n Segment,\n SegmentLabel,\n SfxAudioFormat,\n SfxError,\n SfxMedia,\n SfxResult,\n SfxSegment,\n SfxTask,\n SoundResult,\n StreamEvent,\n TextToMusicParams,\n TextToSfxParams,\n TitleEvent,\n Track,\n TrialQuota,\n UnknownEvent,\n UsageResponse,\n UsageSummary,\n VideoInput,\n VideoResult,\n VideoToMusicParams,\n VideoToSfxParams,\n VideoToSoundParams,\n VideoToVideoMusicParams,\n VideoToVideoSfxParams,\n WaitOptions,\n} from \"./types.js\";\nexport { isAudioChunkEvent, isErrorEvent } from \"./types.js\";\n","export class SoniloError extends Error {\n constructor(message: string) {\n super(message);\n this.name = new.target.name;\n }\n}\n\nexport class APIError extends SoniloError {\n readonly status: number;\n readonly body: unknown;\n /** The API's typed error code (e.g. \"rate_limit_exceeded\"), distinct from the HTTP status. */\n readonly code?: string;\n /** Per-field validation details, present on a 422. */\n readonly errors?: unknown[];\n\n constructor(message: string, status: number, body?: unknown) {\n super(message);\n this.status = status;\n this.body = body;\n const parsed = body as { code?: unknown; errors?: unknown } | undefined;\n this.code = typeof parsed?.code === \"string\" ? parsed.code : undefined;\n this.errors = Array.isArray(parsed?.errors) ? parsed.errors : undefined;\n }\n}\n\nexport class AuthenticationError extends APIError {}\n\nexport class PaymentRequiredError extends APIError {}\n\n/** The account's free trial for this service is spent and it has never been\n * funded — the caller should add a payment method rather than retry. A\n * subclass of `PaymentRequiredError`, so code that already catches every 402\n * keeps working; catch this first to tell \"you haven't paid us yet\" apart\n * from a funded wallet that ran dry (`PaymentRequiredError` with\n * `code === \"insufficient_balance\"`). */\nexport class TrialExhaustedError extends PaymentRequiredError {}\n\nexport class BadRequestError extends APIError {\n get detail(): string | undefined {\n const body = this.body as { message?: unknown; detail?: unknown } | undefined;\n if (typeof body?.message === \"string\" && body.message) {\n return body.message;\n }\n return typeof body?.detail === \"string\" ? body.detail : undefined;\n }\n}\n\nexport class RateLimitError extends APIError {\n readonly retryAfter?: number;\n\n constructor(message: string, status: number, body?: unknown, retryAfter?: number) {\n super(message, status, body);\n this.retryAfter = retryAfter;\n }\n}\n\n/** Raised by generate() when an `error` event arrives mid-stream. */\nexport class GenerationError extends SoniloError {\n readonly code?: string;\n\n constructor(message: string, code?: string) {\n super(message);\n this.code = code;\n }\n}\n\n/** Raised by tasks.wait()/generate() when an SFX task reaches `failed`. */\nexport class TaskFailedError extends SoniloError {\n readonly code?: string;\n readonly taskId: string;\n readonly refunded?: boolean;\n\n constructor(\n message: string,\n opts: { code?: string; taskId: string; refunded?: boolean },\n ) {\n super(message);\n this.code = opts.code;\n this.taskId = opts.taskId;\n this.refunded = opts.refunded;\n }\n}\n\n/** Poll deadline passed. The task may still finish server-side — resume with\n * tasks.wait(taskId) or tasks.get(taskId). */\nexport class TaskTimeoutError extends SoniloError {\n readonly taskId: string;\n\n constructor(message: string, taskId: string) {\n super(message);\n this.taskId = taskId;\n }\n}\n\n/** Raised when a one-shot request or download is aborted by its own timeout\n * signal (as opposed to a caller-supplied AbortSignal, which propagates\n * untouched). */\nexport class RequestTimeoutError extends SoniloError {}\n\n/**\n * True if `err` is the rejection produced when an `AbortSignal.timeout()`\n * we created fires. Used to distinguish \"our\" timeout aborts (which should be\n * rethrown as `RequestTimeoutError`) from a caller-supplied signal's abort\n * (which must propagate untouched).\n */\nexport function isTimeoutSignalError(err: unknown): boolean {\n return err instanceof Error && (err.name === \"TimeoutError\" || err.name === \"AbortError\");\n}\n\nexport async function errorFromResponse(res: Response): Promise<APIError> {\n const text = await res.text().catch(() => \"\");\n let body: unknown = text;\n try {\n body = JSON.parse(text);\n } catch {\n // keep raw text\n }\n const parsed = body as { message?: unknown; detail?: unknown } | undefined;\n const rawMessage = typeof parsed?.message === \"string\" && parsed.message ? parsed.message : undefined;\n const rawDetail = parsed?.detail;\n const isDetailAbsent = rawDetail === undefined || rawDetail === null || rawDetail === \"\";\n let reason: string;\n if (rawMessage !== undefined) {\n reason = rawMessage;\n } else if (isDetailAbsent) {\n reason = res.statusText || \"request failed\";\n } else if (typeof rawDetail === \"string\") {\n reason = rawDetail;\n } else {\n try {\n reason = JSON.stringify(rawDetail);\n } catch {\n reason = res.statusText || \"request failed\";\n }\n }\n const message = `HTTP ${res.status}: ${reason}`;\n\n switch (res.status) {\n case 401:\n return new AuthenticationError(message, res.status, body);\n case 402: {\n // Branch on the API's `code`, never on the message text — the wording\n // is product copy and changes; the code is the contract.\n const code = (body as { code?: unknown } | undefined)?.code;\n if (code === \"trial_exhausted\") {\n return new TrialExhaustedError(message, res.status, body);\n }\n return new PaymentRequiredError(message, res.status, body);\n }\n case 429: {\n const ra = res.headers.get(\"retry-after\");\n const retryAfter = ra !== null && ra !== \"\" && !Number.isNaN(Number(ra)) ? Number(ra) : undefined;\n return new RateLimitError(message, res.status, body, retryAfter);\n }\n case 400:\n case 413:\n case 422:\n return new BadRequestError(message, res.status, body);\n default:\n return new APIError(message, res.status, body);\n }\n}\n","import type { SoniloClient } from \"../client.js\";\nimport type { AccountServices, UsageResponse } from \"../types.js\";\n\nexport class Account {\n constructor(private readonly client: SoniloClient) {}\n\n async services(): Promise<AccountServices> {\n const res = await this.client.request(\"/v1/account/services\");\n return (await res.json()) as AccountServices;\n }\n\n async usage(params: { days?: number } = {}): Promise<UsageResponse> {\n const query = params.days !== undefined ? `?days=${params.days}` : \"\";\n const res = await this.client.request(`/v1/account/usage${query}`);\n return (await res.json()) as UsageResponse;\n }\n}\n","import type { SoniloClient } from \"../client.js\";\nimport { SoniloError, TaskFailedError, TaskTimeoutError } from \"../errors.js\";\nimport type { BaseTaskResult, SfxResult, WaitOptions } from \"../types.js\";\n\nexport const DEFAULT_POLL_INTERVAL_MS = 2000;\nexport const DEFAULT_WAIT_TIMEOUT_MS = 600_000;\n\nconst sleep = (ms: number) => new Promise<void>((resolve) => setTimeout(resolve, ms));\n\n/** A negative delay is clamped to 0 by setTimeout, which would turn the poll\n * loop into a busy loop hammering the API until the deadline. */\nfunction validateWaitArgs(pollInterval: number, timeout: number): void {\n if (pollInterval < 0) {\n throw new SoniloError(`pollInterval must be >= 0, got ${pollInterval}`);\n }\n if (timeout < 0) {\n throw new SoniloError(`timeout must be >= 0, got ${timeout}`);\n }\n}\n\nexport class Tasks {\n constructor(private readonly client: SoniloClient) {}\n\n /**\n * Fetch current task state. Never throws on a failed status.\n *\n * Generic over the result shape so callers can request the endpoint-\n * specific type, e.g. `client.tasks.get<MusicTaskResult>(taskId)`.\n * Defaults to `SfxResult` for back-compat.\n */\n async get<T extends BaseTaskResult = SfxResult>(taskId: string): Promise<T> {\n const res = await this.client.request(`/v1/tasks/${encodeURIComponent(taskId)}`);\n return (await res.json()) as T;\n }\n\n /**\n * Poll until the task is terminal; throw on failure or deadline.\n *\n * Generic over the result shape, e.g.\n * `client.tasks.wait<MusicTaskResult>(taskId)`. Defaults to `SfxResult`\n * for back-compat.\n */\n async wait<T extends BaseTaskResult = SfxResult>(\n taskId: string,\n opts: WaitOptions = {},\n ): Promise<T> {\n const pollInterval = opts.pollInterval ?? DEFAULT_POLL_INTERVAL_MS;\n const timeout = opts.timeout ?? DEFAULT_WAIT_TIMEOUT_MS;\n validateWaitArgs(pollInterval, timeout);\n const deadline = performance.now() + timeout;\n for (;;) {\n const result = await this.get<T>(taskId);\n if (result.status === \"succeeded\") return result;\n if (result.status === \"failed\") {\n const message = result.error?.message || \"Generation failed\";\n throw new TaskFailedError(`Task ${taskId} failed: ${message}`, {\n code: result.error?.code,\n taskId,\n refunded: result.refunded,\n });\n }\n const remaining = deadline - performance.now();\n if (remaining <= 0) {\n throw new TaskTimeoutError(\n `Task ${taskId} still processing after ${timeout}ms; ` +\n \"it may finish later — resume with tasks.wait or tasks.get\",\n taskId,\n );\n }\n await sleep(Math.min(pollInterval, remaining));\n }\n }\n}\n","import { GenerationError } from \"./errors.js\";\nimport type { CostInfo, StreamEvent, Track } from \"./types.js\";\n\nexport function decodeBase64(b64: string): Uint8Array {\n const bin = atob(b64);\n const out = new Uint8Array(bin.length);\n for (let i = 0; i < bin.length; i++) out[i] = bin.charCodeAt(i);\n return out;\n}\n\n/** Returns `null` for a valid-JSON-but-non-object line (e.g. a bare `null`\n * or a number/string), which carries no event `type` and is skipped like any\n * other junk line rather than crashing on a `.type` read off `null`. */\nfunction toEvent(line: string): StreamEvent | null {\n const parsed: unknown = JSON.parse(line);\n if (typeof parsed !== \"object\" || parsed === null) return null;\n const raw = parsed as { type: string; [key: string]: unknown };\n if (raw.type === \"audio_chunk\" && typeof raw.data === \"string\") {\n try {\n return { ...raw, type: \"audio_chunk\", data: decodeBase64(raw.data) };\n } catch {\n // Don't raise here: this must reach collectTrack's malformed-chunk\n // check, which turns undecodable data into a typed GenerationError.\n // Raising in place would let a raw DOMException escape\n // stream()/generate(), breaking the SDK's \"all errors extend\n // SoniloError\" contract.\n }\n }\n return raw as StreamEvent;\n}\n\nexport async function* parseNdjson(\n body: ReadableStream<Uint8Array>,\n): AsyncGenerator<StreamEvent, void, undefined> {\n const reader = body.getReader();\n const decoder = new TextDecoder();\n let buffer = \"\";\n try {\n for (;;) {\n const { done, value } = await reader.read();\n if (done) break;\n buffer += decoder.decode(value, { stream: true });\n let nl: number;\n while ((nl = buffer.indexOf(\"\\n\")) !== -1) {\n const line = buffer.slice(0, nl).trim();\n buffer = buffer.slice(nl + 1);\n if (line) {\n const ev = toEvent(line);\n if (ev !== null) yield ev;\n }\n }\n }\n buffer += decoder.decode();\n const tail = buffer.trim();\n if (tail) {\n const ev = toEvent(tail);\n if (ev !== null) yield ev;\n }\n } finally {\n await reader.cancel().catch(() => {});\n }\n}\n\nexport async function collectTrack(events: AsyncIterable<StreamEvent>): Promise<Track> {\n const chunks: Uint8Array[] = [];\n let title: string | undefined;\n let cost: CostInfo | undefined;\n let sawComplete = false;\n\n for await (const ev of events) {\n if (ev.type === \"audio_chunk\") {\n // A malformed chunk (missing/non-decodable `data`) must not be\n // silently dropped: that would hand back a \"successful\" Track with\n // empty or truncated audio and no indication anything went wrong.\n if (!(ev.data instanceof Uint8Array)) {\n throw new GenerationError(\n \"received a malformed audio_chunk event (missing or non-decodable data)\",\n );\n }\n chunks.push(ev.data);\n } else if (ev.type === \"title\" && typeof ev.title === \"string\") {\n title = ev.title;\n } else if (ev.type === \"cost\") {\n const { type: _type, ...rest } = ev;\n cost = rest as CostInfo;\n } else if (ev.type === \"error\") {\n const message = typeof ev.message === \"string\" && ev.message !== \"\" ? ev.message : \"generation failed\";\n const code = typeof ev.code === \"string\" ? ev.code : undefined;\n throw new GenerationError(message, code);\n } else if (ev.type === \"complete\") {\n sawComplete = true;\n }\n // unknown event types: ignored\n }\n\n if (!sawComplete) {\n throw new GenerationError(\"stream ended before a 'complete' event (truncated response)\");\n }\n\n const total = chunks.reduce((n, c) => n + c.length, 0);\n const audio = new Uint8Array(total);\n let offset = 0;\n for (const c of chunks) {\n audio.set(c, offset);\n offset += c.length;\n }\n return { audio, title, cost };\n}\n","import type { SoniloClient } from \"../client.js\";\nimport { SoniloError } from \"../errors.js\";\nimport { collectTrack, parseNdjson } from \"../streaming.js\";\nimport type { SfxTask, StreamEvent, TextToMusicParams, Track } from \"../types.js\";\n\nexport class TextToMusic {\n constructor(private readonly client: SoniloClient) {}\n\n /** Stream raw generation events (audio chunks pre-decoded to bytes). */\n async *stream(params: TextToMusicParams): AsyncGenerator<StreamEvent, void, undefined> {\n const form = new FormData();\n form.set(\"prompt\", params.prompt);\n form.set(\"duration\", String(params.duration));\n if (params.segments !== undefined) {\n form.set(\"segments\", JSON.stringify(params.segments));\n }\n // Opt out of the client's absolute request timeout: this holds the\n // response body open and reads NDJSON chunks for as long as generation\n // takes, so an AbortSignal keyed to elapsed time would kill a healthy,\n // still-streaming, long-duration track. Pass `params.signal` yourself to\n // bound or cancel the stream instead — it is forwarded to `fetch` as-is.\n const res = await this.client.request(\n \"/v1/text-to-music\",\n { method: \"POST\", body: form, signal: params.signal },\n { timeout: null },\n );\n if (!res.body) throw new SoniloError(\"Response has no body\");\n yield* parseNdjson(res.body);\n }\n\n /** Generate and buffer the whole track; throws GenerationError on stream errors. */\n generate(params: TextToMusicParams): Promise<Track> {\n return collectTrack(this.stream(params));\n }\n\n /**\n * Submit an async text-to-music task; poll with\n * `client.tasks.wait<MusicTaskResult>(task.task_id)`. Required for\n * `outputFormat: \"wav\"`. `stream()`/`generate()` remain the streaming path.\n */\n async submit(params: TextToMusicParams): Promise<SfxTask> {\n const mode = params.mode ?? \"async\";\n if (mode !== \"async\") {\n throw new SoniloError('submit() requires mode: \"async\"');\n }\n const form = new FormData();\n form.set(\"prompt\", params.prompt);\n form.set(\"duration\", String(params.duration));\n if (params.segments !== undefined) {\n form.set(\"segments\", JSON.stringify(params.segments));\n }\n form.set(\"mode\", mode);\n if (params.outputFormat !== undefined) {\n form.set(\"output_format\", params.outputFormat);\n }\n const res = await this.client.request(\"/v1/text-to-music\", {\n method: \"POST\",\n body: form,\n });\n return (await res.json()) as SfxTask;\n }\n}\n","import { SoniloError } from \"./errors.js\";\nimport type { VideoInput } from \"./types.js\";\n\nconst DEFAULT_FILENAME = \"video.mp4\";\n\n/**\n * Normalize every accepted video input into a FormData-ready Blob.\n * String inputs are file paths and work only in Node.js; browsers must\n * pass File/Blob/bytes/streams.\n */\nexport async function toUploadBlob(\n video: VideoInput,\n): Promise<{ blob: Blob; filename: string }> {\n if (typeof video === \"string\") {\n const isNode =\n typeof process !== \"undefined\" && Boolean((process as { versions?: { node?: string } }).versions?.node);\n if (!isNode) {\n throw new SoniloError(\n \"File paths are only supported in Node.js; pass a File or Blob in the browser\",\n );\n }\n const fsModule = \"node:fs/promises\";\n const { readFile } = (await import(\n /* webpackIgnore: true */ /* @vite-ignore */ fsModule\n )) as typeof import(\"node:fs/promises\");\n const data = await readFile(video);\n const filename = video.split(/[\\\\/]/).pop() || DEFAULT_FILENAME;\n return { blob: new Blob([data]), filename };\n }\n if (typeof File !== \"undefined\" && video instanceof File) {\n return { blob: video, filename: video.name || DEFAULT_FILENAME };\n }\n if (video instanceof Blob) {\n return { blob: video, filename: DEFAULT_FILENAME };\n }\n if (video instanceof Uint8Array) {\n return { blob: new Blob([video as unknown as BlobPart]), filename: DEFAULT_FILENAME };\n }\n if (video instanceof ArrayBuffer) {\n return { blob: new Blob([video]), filename: DEFAULT_FILENAME };\n }\n if (video instanceof ReadableStream) {\n return { blob: await new Response(video).blob(), filename: DEFAULT_FILENAME };\n }\n throw new SoniloError(\"Unsupported video input type\");\n}\n","import type { SoniloClient } from \"../client.js\";\nimport { SoniloError } from \"../errors.js\";\nimport { collectTrack, parseNdjson } from \"../streaming.js\";\nimport { toUploadBlob } from \"../upload.js\";\nimport type { SfxTask, StreamEvent, Track, VideoToMusicParams } from \"../types.js\";\n\nexport class VideoToMusic {\n constructor(private readonly client: SoniloClient) {}\n\n async *stream(params: VideoToMusicParams): AsyncGenerator<StreamEvent, void, undefined> {\n if ((params.video === undefined) === (params.videoUrl === undefined)) {\n throw new SoniloError(\"Provide exactly one of video or videoUrl\");\n }\n const form = new FormData();\n if (params.video !== undefined) {\n const { blob, filename } = await toUploadBlob(params.video);\n form.set(\"video\", blob, filename);\n } else {\n form.set(\"video_url\", params.videoUrl as string);\n }\n if (params.prompt !== undefined) form.set(\"prompt\", params.prompt);\n if (params.segments !== undefined) {\n form.set(\"segments\", JSON.stringify(params.segments));\n }\n // Opt out of the client's absolute request timeout: this holds the\n // response body open and reads NDJSON chunks for as long as generation\n // takes, so an AbortSignal keyed to elapsed time would kill a healthy,\n // still-streaming request (e.g. a slow video upload or long track). Pass\n // `params.signal` yourself to bound or cancel the stream instead — it is\n // forwarded to `fetch` as-is.\n const res = await this.client.request(\n \"/v1/video-to-music\",\n { method: \"POST\", body: form, signal: params.signal },\n { timeout: null },\n );\n if (!res.body) throw new SoniloError(\"Response has no body\");\n yield* parseNdjson(res.body);\n }\n\n generate(params: VideoToMusicParams): Promise<Track> {\n return collectTrack(this.stream(params));\n }\n\n /**\n * Submit an async video-to-music task; poll its result with\n * `client.tasks.wait<MusicTaskResult>(task.task_id)`. Required for\n * `isolateVocals` — the backend rejects vocal isolation on the plain\n * stream, and it only ever runs in async mode.\n */\n async submit(params: VideoToMusicParams): Promise<SfxTask> {\n if ((params.video === undefined) === (params.videoUrl === undefined)) {\n throw new SoniloError(\"Provide exactly one of video or videoUrl\");\n }\n let mode = params.mode;\n const needsAsync =\n params.isolateVocals ||\n params.preserveSpeech ||\n params.ducking !== undefined ||\n params.outputFormat === \"wav\";\n // submit() always wants an async task ack, never a stream. Default to\n // async; only object if the caller explicitly asked for stream while\n // also requesting an async-only feature.\n if (mode === undefined) mode = \"async\";\n if (needsAsync && mode !== \"async\") {\n throw new SoniloError(\n 'isolateVocals/preserveSpeech/ducking/outputFormat \"wav\" require mode: \"async\"',\n );\n }\n const form = new FormData();\n if (params.video !== undefined) {\n const { blob, filename } = await toUploadBlob(params.video);\n form.set(\"video\", blob, filename);\n } else {\n form.set(\"video_url\", params.videoUrl as string);\n }\n if (params.prompt !== undefined) form.set(\"prompt\", params.prompt);\n if (params.segments !== undefined) {\n form.set(\"segments\", JSON.stringify(params.segments));\n }\n form.set(\"mode\", mode);\n if (params.preserveSpeech !== undefined) {\n form.set(\"preserve_speech\", String(params.preserveSpeech));\n }\n if (params.isolateVocals !== undefined) {\n form.set(\"isolate_vocals\", String(params.isolateVocals));\n }\n if (params.outputFormat !== undefined) {\n form.set(\"output_format\", params.outputFormat);\n }\n if (params.ducking !== undefined) {\n form.set(\"ducking\", String(params.ducking));\n }\n const res = await this.client.request(\"/v1/video-to-music\", {\n method: \"POST\",\n body: form,\n });\n return (await res.json()) as SfxTask;\n }\n}\n","import type { SoniloClient } from \"../client.js\";\nimport type { SfxResult, SfxTask, TextToSfxParams, WaitOptions } from \"../types.js\";\n\nexport class TextToSfx {\n constructor(private readonly client: SoniloClient) {}\n\n async submit(params: TextToSfxParams): Promise<SfxTask> {\n const form = new FormData();\n form.set(\"prompt\", params.prompt);\n form.set(\"duration\", String(params.duration));\n if (params.audioFormat !== undefined) form.set(\"audio_format\", params.audioFormat);\n const res = await this.client.request(\"/v1/text-to-sfx\", {\n method: \"POST\",\n body: form,\n });\n return (await res.json()) as SfxTask;\n }\n\n async generate(params: TextToSfxParams, opts?: WaitOptions): Promise<SfxResult> {\n const task = await this.submit(params);\n return this.client.tasks.wait(task.task_id, opts);\n }\n}\n","import type { SoniloClient } from \"../client.js\";\nimport { SoniloError } from \"../errors.js\";\nimport { toUploadBlob } from \"../upload.js\";\nimport type { SfxResult, SfxTask, VideoToSfxParams, WaitOptions } from \"../types.js\";\n\nexport class VideoToSfx {\n constructor(private readonly client: SoniloClient) {}\n\n async submit(params: VideoToSfxParams): Promise<SfxTask> {\n if ((params.video === undefined) === (params.videoUrl === undefined)) {\n throw new SoniloError(\"Provide exactly one of video or videoUrl\");\n }\n const form = new FormData();\n if (params.video !== undefined) {\n const { blob, filename } = await toUploadBlob(params.video);\n form.set(\"video\", blob, filename);\n } else {\n form.set(\"video_url\", params.videoUrl as string);\n }\n if (params.prompt !== undefined) form.set(\"prompt\", params.prompt);\n if (params.segments !== undefined) {\n form.set(\"segments\", JSON.stringify(params.segments));\n }\n if (params.audioFormat !== undefined) form.set(\"audio_format\", params.audioFormat);\n const res = await this.client.request(\"/v1/video-to-sfx\", {\n method: \"POST\",\n body: form,\n });\n return (await res.json()) as SfxTask;\n }\n\n async generate(params: VideoToSfxParams, opts?: WaitOptions): Promise<SfxResult> {\n const task = await this.submit(params);\n return this.client.tasks.wait(task.task_id, opts);\n }\n}\n","import type { SoniloClient } from \"../client.js\";\nimport { SoniloError } from \"../errors.js\";\nimport { toUploadBlob } from \"../upload.js\";\nimport type { SfxTask, VideoResult, VideoToVideoMusicParams, WaitOptions } from \"../types.js\";\n\n/** Generate an original score for a video and get back a re-hosted video with\n * the music muxed in. Async only: `submit()` returns a task ack; poll with\n * `client.tasks.wait<VideoResult>(id)`, or use `generate()` to do both. */\nexport class VideoToVideoMusic {\n constructor(private readonly client: SoniloClient) {}\n\n async submit(params: VideoToVideoMusicParams): Promise<SfxTask> {\n if ((params.video === undefined) === (params.videoUrl === undefined)) {\n throw new SoniloError(\"Provide exactly one of video or videoUrl\");\n }\n const form = new FormData();\n if (params.video !== undefined) {\n const { blob, filename } = await toUploadBlob(params.video);\n form.set(\"video\", blob, filename);\n } else {\n form.set(\"video_url\", params.videoUrl as string);\n }\n if (params.prompt !== undefined) form.set(\"prompt\", params.prompt);\n if (params.preserveSpeech !== undefined) {\n form.set(\"preserve_speech\", String(params.preserveSpeech));\n }\n if (params.isolateVocals !== undefined) {\n form.set(\"isolate_vocals\", String(params.isolateVocals));\n }\n const res = await this.client.request(\"/v1/video-to-video-music\", {\n method: \"POST\",\n body: form,\n });\n return (await res.json()) as SfxTask;\n }\n\n async generate(params: VideoToVideoMusicParams, opts?: WaitOptions): Promise<VideoResult> {\n const task = await this.submit(params);\n return this.client.tasks.wait<VideoResult>(task.task_id, opts);\n }\n}\n","import type { SoniloClient } from \"../client.js\";\nimport { SoniloError } from \"../errors.js\";\nimport { toUploadBlob } from \"../upload.js\";\nimport type { SfxTask, VideoResult, VideoToVideoSfxParams, WaitOptions } from \"../types.js\";\n\n/** Generate sound effects for a video and get back a re-hosted video with the\n * SFX muxed in. Async only. */\nexport class VideoToVideoSfx {\n constructor(private readonly client: SoniloClient) {}\n\n async submit(params: VideoToVideoSfxParams): Promise<SfxTask> {\n if ((params.video === undefined) === (params.videoUrl === undefined)) {\n throw new SoniloError(\"Provide exactly one of video or videoUrl\");\n }\n const form = new FormData();\n if (params.video !== undefined) {\n const { blob, filename } = await toUploadBlob(params.video);\n form.set(\"video\", blob, filename);\n } else {\n form.set(\"video_url\", params.videoUrl as string);\n }\n if (params.prompt !== undefined) form.set(\"prompt\", params.prompt);\n if (params.segments !== undefined) {\n form.set(\"segments\", JSON.stringify(params.segments));\n }\n const res = await this.client.request(\"/v1/video-to-video-sfx\", {\n method: \"POST\",\n body: form,\n });\n return (await res.json()) as SfxTask;\n }\n\n async generate(params: VideoToVideoSfxParams, opts?: WaitOptions): Promise<VideoResult> {\n const task = await this.submit(params);\n return this.client.tasks.wait<VideoResult>(task.task_id, opts);\n }\n}\n","import { SoniloError } from \"../errors.js\";\nimport { toUploadBlob } from \"../upload.js\";\nimport type { VideoToSoundParams } from \"../types.js\";\n\n/** Build the multipart body shared by /v1/video-to-sound and\n * /v1/video-to-video-sound — their form fields are identical, so the two\n * resources differ only in the path they POST to.\n *\n * Every optional field is omitted when unset rather than sent with a default:\n * `ducking` in particular is default-ON server-side, so an unset value must\n * not become an explicit \"false\" on the wire. */\nexport async function buildSoundForm(params: VideoToSoundParams): Promise<FormData> {\n if ((params.video === undefined) === (params.videoUrl === undefined)) {\n throw new SoniloError(\"Provide exactly one of video or videoUrl\");\n }\n const form = new FormData();\n if (params.video !== undefined) {\n const { blob, filename } = await toUploadBlob(params.video);\n form.set(\"video\", blob, filename);\n } else {\n form.set(\"video_url\", params.videoUrl as string);\n }\n if (params.musicPrompt !== undefined) form.set(\"music_prompt\", params.musicPrompt);\n if (params.sfxPrompt !== undefined) form.set(\"sfx_prompt\", params.sfxPrompt);\n if (params.segments !== undefined) {\n form.set(\"segments\", JSON.stringify(params.segments));\n }\n if (params.preserveSpeech !== undefined) {\n form.set(\"preserve_speech\", String(params.preserveSpeech));\n }\n if (params.ducking !== undefined) form.set(\"ducking\", String(params.ducking));\n return form;\n}\n","import type { SoniloClient } from \"../client.js\";\nimport { buildSoundForm } from \"./soundForm.js\";\nimport type { SfxTask, SoundResult, VideoToSoundParams, WaitOptions } from \"../types.js\";\n\n/** Generate a combined music + sound-effects track for a video and get back\n * the mixed audio. Async only. */\nexport class VideoToSound {\n constructor(private readonly client: SoniloClient) {}\n\n async submit(params: VideoToSoundParams): Promise<SfxTask> {\n const res = await this.client.request(\"/v1/video-to-sound\", {\n method: \"POST\",\n body: await buildSoundForm(params),\n });\n return (await res.json()) as SfxTask;\n }\n\n async generate(params: VideoToSoundParams, opts?: WaitOptions): Promise<SoundResult> {\n const task = await this.submit(params);\n return this.client.tasks.wait<SoundResult>(task.task_id, opts);\n }\n}\n","import type { SoniloClient } from \"../client.js\";\nimport { buildSoundForm } from \"./soundForm.js\";\nimport type { SfxTask, SoundResult, VideoToSoundParams, WaitOptions } from \"../types.js\";\n\n/** Generate a combined music + sound-effects track for a video and get back a\n * re-hosted video with that track muxed in. Async only. */\nexport class VideoToVideoSound {\n constructor(private readonly client: SoniloClient) {}\n\n async submit(params: VideoToSoundParams): Promise<SfxTask> {\n const res = await this.client.request(\"/v1/video-to-video-sound\", {\n method: \"POST\",\n body: await buildSoundForm(params),\n });\n return (await res.json()) as SfxTask;\n }\n\n async generate(params: VideoToSoundParams, opts?: WaitOptions): Promise<SoundResult> {\n const task = await this.submit(params);\n return this.client.tasks.wait<SoundResult>(task.task_id, opts);\n }\n}\n","import type { SoniloClient } from \"../client.js\";\nimport { SoniloError } from \"../errors.js\";\nimport { toUploadBlob } from \"../upload.js\";\nimport type { DubbingParams, DubbingResult, SfxTask, WaitOptions } from \"../types.js\";\n\n/** Build the multipart body for /v1/dubbing.\n *\n * `languages` travels as one opaque form field holding a JSON array string —\n * that is the shape the backend parses. It is omitted entirely when unset so\n * the server default ([\"zh_cn\", \"es\", \"fr\"]) applies; sending an empty array\n * instead would be rejected as a malformed payload.\n *\n * The https check is local because it is a guaranteed server-side 422: the\n * dubbing pipeline fetches the source URL itself and requires https\n * specifically, unlike the fal-backed endpoints, which accept plain http.\n * Language codes are deliberately NOT checked here — the backend owns that\n * list, and a hardcoded copy would make this SDK reject codes added later. */\nexport async function buildDubbingForm(params: DubbingParams): Promise<FormData> {\n if ((params.video === undefined) === (params.videoUrl === undefined)) {\n throw new SoniloError(\"Provide exactly one of video or videoUrl\");\n }\n const form = new FormData();\n if (params.video !== undefined) {\n const { blob, filename } = await toUploadBlob(params.video);\n form.set(\"video\", blob, filename);\n } else {\n const url = params.videoUrl as string;\n if (!url.toLowerCase().startsWith(\"https://\")) {\n throw new SoniloError(\n \"videoUrl must use https — the dubbing pipeline requires an https URL\",\n );\n }\n form.set(\"video_url\", url);\n }\n if (params.languages !== undefined) {\n form.set(\"languages\", JSON.stringify(params.languages));\n }\n return form;\n}\n\n/** Dub a video into one or more target languages. Async only; the result\n * carries a language → dubbed-video-URL map under `outputs`. */\nexport class Dubbing {\n constructor(private readonly client: SoniloClient) {}\n\n async submit(params: DubbingParams): Promise<SfxTask> {\n const res = await this.client.request(\"/v1/dubbing\", {\n method: \"POST\",\n body: await buildDubbingForm(params),\n });\n return (await res.json()) as SfxTask;\n }\n\n async generate(params: DubbingParams, opts?: WaitOptions): Promise<DubbingResult> {\n const task = await this.submit(params);\n return this.client.tasks.wait<DubbingResult>(task.task_id, opts);\n }\n}\n","/** The SDK's own version. Generated by scripts/sync-versions.mjs — do not edit. */\nexport const VERSION = \"0.7.0\";\n","import { RequestTimeoutError, SoniloError, errorFromResponse, isTimeoutSignalError } from \"./errors.js\";\nimport { Account } from \"./resources/account.js\";\nimport { Tasks } from \"./resources/tasks.js\";\nimport { TextToMusic } from \"./resources/textToMusic.js\";\nimport { VideoToMusic } from \"./resources/videoToMusic.js\";\nimport { TextToSfx } from \"./resources/textToSfx.js\";\nimport { VideoToSfx } from \"./resources/videoToSfx.js\";\nimport { VideoToVideoMusic } from \"./resources/videoToVideoMusic.js\";\nimport { VideoToVideoSfx } from \"./resources/videoToVideoSfx.js\";\nimport { VideoToSound } from \"./resources/videoToSound.js\";\nimport { VideoToVideoSound } from \"./resources/videoToVideoSound.js\";\nimport { Dubbing } from \"./resources/dubbing.js\";\nimport { VERSION } from \"./version.js\";\n\nexport interface SoniloClientOptions {\n /** Defaults to the SONILO_API_KEY environment variable (Node.js only). */\n apiKey?: string;\n /** Defaults to https://api.sonilo.com */\n baseUrl?: string;\n /** Injection point for tests and custom transports. */\n fetch?: typeof globalThis.fetch;\n /** Milliseconds before an in-flight request is aborted. Default 600000. */\n timeout?: number;\n /**\n * Identifies a wrapper built on this SDK (the CLI, the video kit) in the\n * `X-Sonilo-Client` header. Leave unset for direct SDK use — without an\n * override a wrapper's traffic is indistinguishable from the SDK's own.\n */\n clientName?: string;\n /** Version reported alongside `clientName`. Defaults to the SDK's version. */\n clientVersion?: string;\n}\n\nconst DEFAULT_BASE_URL = \"https://api.sonilo.com\";\n\n/**\n * Reported in `X-Sonilo-Client` unless a wrapper overrides it. First-party\n * wrappers (the CLI, the video kit) pass their own name so their traffic stays\n * distinguishable from direct SDK use in server-side analytics.\n */\nexport const DEFAULT_CLIENT_NAME = \"sdk-js\";\n\n/** Milliseconds before an in-flight request is aborted, unless overridden. */\nexport const DEFAULT_TIMEOUT_MS = 600_000;\n\nexport class SoniloClient {\n readonly baseUrl: string;\n private readonly apiKey: string;\n private readonly fetchFn: typeof globalThis.fetch;\n private readonly timeout: number;\n private readonly clientName: string;\n private readonly clientVersion: string;\n readonly account: Account;\n readonly tasks: Tasks;\n readonly textToMusic: TextToMusic;\n readonly videoToMusic: VideoToMusic;\n readonly textToSfx: TextToSfx;\n readonly videoToSfx: VideoToSfx;\n readonly videoToVideoMusic: VideoToVideoMusic;\n readonly videoToVideoSfx: VideoToVideoSfx;\n readonly videoToSound: VideoToSound;\n readonly videoToVideoSound: VideoToVideoSound;\n readonly dubbing: Dubbing;\n\n constructor(options: SoniloClientOptions = {}) {\n const envKey =\n typeof process !== \"undefined\" ? process.env?.SONILO_API_KEY : undefined;\n const apiKey = options.apiKey ?? envKey;\n if (!apiKey) {\n throw new SoniloError(\n \"Missing API key: pass { apiKey } or set the SONILO_API_KEY environment variable\",\n );\n }\n this.apiKey = apiKey;\n this.baseUrl = (options.baseUrl ?? DEFAULT_BASE_URL).replace(/\\/+$/, \"\");\n this.fetchFn = (options.fetch ?? globalThis.fetch).bind(globalThis);\n this.timeout = options.timeout ?? DEFAULT_TIMEOUT_MS;\n this.clientName = options.clientName ?? DEFAULT_CLIENT_NAME;\n this.clientVersion = options.clientVersion ?? VERSION;\n this.account = new Account(this);\n this.tasks = new Tasks(this);\n this.textToMusic = new TextToMusic(this);\n this.videoToMusic = new VideoToMusic(this);\n this.textToSfx = new TextToSfx(this);\n this.videoToSfx = new VideoToSfx(this);\n this.videoToVideoMusic = new VideoToVideoMusic(this);\n this.videoToVideoSfx = new VideoToVideoSfx(this);\n this.videoToSound = new VideoToSound(this);\n this.videoToVideoSound = new VideoToVideoSound(this);\n this.dubbing = new Dubbing(this);\n }\n\n /**\n * Perform an authenticated request; throws a typed error on non-2xx.\n *\n * `opts.timeout` overrides the client's default timeout for this call;\n * pass `null` to disable the abort-on-timeout behavior entirely (used by\n * the streaming music endpoints — see textToMusic.ts / videoToMusic.ts).\n * A caller-supplied `init.signal` always wins over any timeout signal.\n */\n async request(\n path: string,\n init: RequestInit = {},\n opts: { timeout?: number | null } = {},\n ): Promise<Response> {\n const headers = new Headers(init.headers);\n headers.set(\"Authorization\", `Bearer ${this.apiKey}`);\n headers.set(\"X-Sonilo-Client\", this.clientName);\n headers.set(\"X-Sonilo-Client-Version\", this.clientVersion);\n const timeout = opts.timeout === undefined ? this.timeout : opts.timeout;\n // We only \"own\" the signal (and may later rewrap its abort as a\n // RequestTimeoutError) when the caller didn't supply one and a timeout\n // is actually enabled.\n const ownsSignal = init.signal == null && timeout !== null;\n const signal = init.signal ?? (timeout === null ? undefined : AbortSignal.timeout(timeout));\n try {\n const res = await this.fetchFn(`${this.baseUrl}${path}`, { ...init, headers, signal });\n if (!res.ok) throw await errorFromResponse(res);\n return res;\n } catch (err) {\n if (ownsSignal && isTimeoutSignalError(err)) {\n throw new RequestTimeoutError(`Request to ${path} timed out after ${timeout}ms`);\n }\n throw err;\n }\n }\n}\n","import { DEFAULT_TIMEOUT_MS } from \"./client.js\";\nimport { RequestTimeoutError, SoniloError, isTimeoutSignalError } from \"./errors.js\";\nimport type { SfxMedia } from \"./types.js\";\n\n/** Fetch a result media file. The URL is presigned — no API key is sent.\n *\n * Accepts either a media object (`result.audio`, `result.music`, …) or a bare\n * URL string, which is what the combined video-to-sound endpoints return as\n * `output_url`. */\nexport async function download(\n media: SfxMedia | string | undefined,\n fetchFn: typeof globalThis.fetch = globalThis.fetch,\n timeout: number = DEFAULT_TIMEOUT_MS,\n): Promise<Uint8Array> {\n const url = typeof media === \"string\" ? media : media?.url;\n if (!url) {\n throw new SoniloError(\"No media to download\");\n }\n let res: Response;\n try {\n res = await fetchFn(url, { signal: AbortSignal.timeout(timeout) });\n } catch (err) {\n if (isTimeoutSignalError(err)) {\n throw new RequestTimeoutError(`Download of ${url} timed out after ${timeout}ms`);\n }\n throw err;\n }\n if (!res.ok) {\n throw new SoniloError(`Download failed: HTTP ${res.status}`);\n }\n return new Uint8Array(await res.arrayBuffer());\n}\n","export type SegmentLabel =\n | \"intro\"\n | \"verse\"\n | \"pre-chorus\"\n | \"chorus\"\n | \"bridge\"\n | \"break\"\n | \"silence\"\n | \"outro\"\n | \"none\";\n\nexport interface Segment {\n start: number;\n prompt: string;\n label?: SegmentLabel;\n}\n\n/** Monetary fields are strings, exactly as the backend serializes them. */\nexport interface CostInfo {\n billing_rate_per_sec: string;\n billing_before_discount: string;\n billing_after_discount: string;\n discount_factor: string;\n}\n\nexport interface AudioChunkEvent {\n type: \"audio_chunk\";\n /** Decoded from the wire's base64 by the SDK. */\n data: Uint8Array;\n}\n\nexport interface TitleEvent {\n type: \"title\";\n title: string;\n summary?: string;\n display_tags?: string[];\n [key: string]: unknown;\n}\n\nexport interface CompleteEvent {\n type: \"complete\";\n [key: string]: unknown;\n}\n\nexport interface ErrorEvent {\n type: \"error\";\n code?: string;\n message?: string;\n [key: string]: unknown;\n}\n\nexport interface CostEvent extends CostInfo {\n type: \"cost\";\n}\n\n/** Forward-compatibility: unrecognized event types are passed through. */\nexport interface UnknownEvent {\n type: string;\n [key: string]: unknown;\n}\n\nexport type StreamEvent =\n | AudioChunkEvent\n | TitleEvent\n | CompleteEvent\n | ErrorEvent\n | CostEvent\n | UnknownEvent;\n\nexport interface Track {\n audio: Uint8Array;\n title?: string;\n cost?: CostInfo;\n}\n\nexport interface TextToMusicParams {\n prompt: string;\n duration: number;\n segments?: Segment[];\n /** \"stream\" (default) or \"async\" (required by `submit()` and `output_format: \"wav\"`). */\n mode?: \"stream\" | \"async\";\n /** Container for the async result. `wav` requires `mode: \"async\"`. Defaults to m4a server-side. */\n outputFormat?: \"m4a\" | \"wav\";\n /** Bounds the stream: aborting this cancels the in-flight generation.\n * Passed straight through to `fetch` — it is never rewrapped as\n * RequestTimeoutError, since the client's own absolute timeout does not\n * apply to streaming music generation. */\n signal?: AbortSignal;\n}\n\n/** string = file path (Node.js only). */\nexport type VideoInput =\n | File\n | Blob\n | Uint8Array\n | ArrayBuffer\n | ReadableStream<Uint8Array>\n | string;\n\nexport interface VideoToMusicParams {\n video?: VideoInput;\n videoUrl?: string;\n prompt?: string;\n segments?: Segment[];\n /** Bounds the stream: aborting this cancels the in-flight generation.\n * Passed straight through to `fetch` — it is never rewrapped as\n * RequestTimeoutError, since the client's own absolute timeout does not\n * apply to streaming music generation. Only meaningful for `stream()`/\n * `generate()`; `submit()` ignores it. */\n signal?: AbortSignal;\n /** \"stream\" (the default, used by `stream()`/`generate()`) or \"async\"\n * (required for `submit()`, and for `isolateVocals`). Only consulted by\n * `submit()` — `stream()`/`generate()` always request a stream. */\n mode?: \"stream\" | \"async\";\n /** Split the generated track into a vocals-only stem alongside the mix.\n * Requires `mode: \"async\"`; if `mode` is left unset it defaults to\n * \"async\" automatically. Only usable via `submit()` — the backend\n * rejects it on the plain stream. */\n isolateVocals?: boolean;\n /** Keep the source speech/vocals in the async result. Current name for\n * `isolateVocals`; both are accepted and OR'd server-side. Requires\n * `mode: \"async\"` (auto-selected by `submit()`). */\n preserveSpeech?: boolean;\n /** Container for the async result. `wav` requires async. Defaults to m4a. */\n outputFormat?: \"m4a\" | \"wav\";\n /** Duck the generated music under the source voice at finalize time.\n * Default-ON server-side in async mode: leave unset to keep it on, pass\n * `false` to opt out. Free, best-effort; only valid on `submit()`. */\n ducking?: boolean;\n}\n\n/** One service's free-trial allowance. `remaining` is already floored at 0,\n * so it is safe to compare directly. */\nexport interface TrialQuota {\n granted: number;\n used: number;\n remaining: number;\n}\n\nexport interface AccountServices {\n available_services: string[];\n rpm_limit: number;\n concurrency_limit: number;\n discount_factor: number | string;\n max_upload_size_mb: number | null;\n /** Free-trial allowance keyed by service (`granted` / `used` /\n * `remaining`). Present only for self-serve accounts — always treat it as\n * possibly absent, and treat a service missing from the map as \"no trial\n * allowance\", not as an error. */\n trial?: Record<string, TrialQuota>;\n}\n\nexport interface UsageSummary {\n total_requests: number;\n total_duration_seconds: number;\n total_cost: number | string;\n period_start: string;\n period_end: string;\n [key: string]: unknown;\n}\n\nexport interface DailyUsage {\n date: string;\n requests: number;\n duration_seconds: number;\n cost: number | string;\n}\n\nexport interface UsageResponse {\n summary: UsageSummary;\n daily: DailyUsage[];\n}\n\nexport function isAudioChunkEvent(event: StreamEvent): event is AudioChunkEvent {\n return event.type === \"audio_chunk\" && (event as AudioChunkEvent).data instanceof Uint8Array;\n}\n\nexport function isErrorEvent(event: StreamEvent): event is ErrorEvent {\n return event.type === \"error\";\n}\n\n/** SFX segments (unlike music `Segment`) require `end`, must start at 0,\n * and be contiguous; validated server-side. */\nexport interface SfxSegment {\n start: number;\n end: number;\n prompt: string;\n}\n\nexport type SfxAudioFormat = \"wav\" | \"mp3\" | \"aac\" | \"flac\";\n\n/** Submission ack for the async SFX endpoints. */\nexport interface SfxTask {\n task_id: string;\n status: string;\n}\n\n/** A generated file re-hosted on R2 behind a presigned URL. */\nexport interface SfxMedia {\n url: string;\n content_type?: string;\n file_size?: number;\n}\n\nexport interface SfxError {\n code?: string;\n message?: string;\n}\n\n/**\n * Common shape of any polled task (`tasks.get`/`tasks.wait`), regardless of\n * which endpoint created it. `Tasks.get`/`Tasks.wait` are generic over this so\n * each endpoint's result type (e.g. `SfxResult`, `MusicTaskResult`) can add\n * its own `audio`/media fields while sharing the status/error/refund\n * bookkeeping the poller relies on.\n */\nexport interface BaseTaskResult {\n task_id: string;\n type?: string;\n status: \"processing\" | \"succeeded\" | \"failed\" | (string & {});\n /** Only present when the account's task-field whitelist enables cost. */\n cost?: number;\n error?: SfxError;\n refunded?: boolean;\n [key: string]: unknown;\n}\n\n/** State of an SFX task (`tasks.get`) or its final result (`wait`/`generate`). */\nexport interface SfxResult extends BaseTaskResult {\n audio?: SfxMedia;\n /** Kept for backward compatibility; no longer populated — video-to-sfx returns audio only. */\n video?: SfxMedia;\n}\n\nexport interface TextToSfxParams {\n prompt: string;\n duration: number;\n audioFormat?: SfxAudioFormat;\n}\n\nexport interface VideoToSfxParams {\n video?: VideoInput;\n videoUrl?: string;\n prompt?: string;\n segments?: SfxSegment[];\n audioFormat?: SfxAudioFormat;\n}\n\n/** One decoded audio stream of an async video-to-music result. Unlike SFX,\n * `audio` on a music task is always an array — even without `isolateVocals` —\n * since a music generation can carry more than one output stream. */\nexport interface MusicMediaEntry extends SfxMedia {\n stream_index: number;\n sample_rate?: number;\n channels?: number;\n}\n\n/** One muxed audio+video-aligned output, present only when `isolateVocals`\n * is set. */\nexport interface MusicMuxEntry extends SfxMedia {\n stream_index: number;\n}\n\nexport interface MusicTitle {\n title: string;\n summary?: string;\n display_tags?: string[];\n}\n\n/** State of an async video-to-music task (`tasks.get`) or its final result\n * (`tasks.wait<MusicTaskResult>()`). Only reachable via `videoToMusic.submit()`\n * with `mode: \"async\"`. */\nexport interface MusicTaskResult extends BaseTaskResult {\n audio?: MusicMediaEntry[];\n /** Vocals-only stem; present only when `isolateVocals` was requested. */\n vocals?: SfxMedia;\n /** Muxed output per stream; present only when `isolateVocals` was requested. */\n mux?: MusicMuxEntry[];\n /** Music ducked under the source voice; present only when `ducking` ran. */\n ducked?: MusicMediaEntry[];\n title?: MusicTitle;\n duration_seconds?: number;\n}\n\nexport interface WaitOptions {\n /** Milliseconds between polls. Default 2000. */\n pollInterval?: number;\n /** Overall deadline in milliseconds. Default 600000. */\n timeout?: number;\n}\n\n/** Result of an async video-to-video task (`videoToVideoMusic`/`videoToVideoSfx`):\n * a re-hosted video with generated music or SFX muxed in. */\nexport interface VideoResult extends BaseTaskResult {\n video?: SfxMedia;\n duration_seconds?: number;\n}\n\nexport interface VideoToVideoMusicParams {\n video?: VideoInput;\n videoUrl?: string;\n prompt?: string;\n /** Keep the source speech/vocals in the output. Both this and the legacy\n * `isolateVocals` are accepted and OR'd server-side. */\n preserveSpeech?: boolean;\n /** @deprecated Legacy alias for `preserveSpeech`. */\n isolateVocals?: boolean;\n}\n\nexport interface VideoToVideoSfxParams {\n video?: VideoInput;\n videoUrl?: string;\n prompt?: string;\n segments?: SfxSegment[];\n}\n\n/** Params for `videoToSound` and `videoToVideoSound`. Both endpoints take the\n * identical form, so they share one params type. */\nexport interface VideoToSoundParams {\n video?: VideoInput;\n videoUrl?: string;\n /** Style hint for the generated music bed. */\n musicPrompt?: string;\n /** Description of the sound effects layered over the music. */\n sfxPrompt?: string;\n /** Per-segment SFX descriptions; must start at 0 and be contiguous. */\n segments?: SfxSegment[];\n /** Keep the source speech in the result. */\n preserveSpeech?: boolean;\n /** Duck the generated music under the source speech. Default-ON\n * server-side: leave unset to keep it on, pass `false` to opt out. */\n ducking?: boolean;\n}\n\n/** Result of a `videoToSound` / `videoToVideoSound` task (`tasks.get`) or its\n * final state (`generate`).\n *\n * The combined music+SFX result is `output_url` — a bare presigned URL rather\n * than a media object, since these endpoints render one artifact whose kind is\n * announced by `output_type` (\"audio\" for video-to-sound, \"video\" for\n * video-to-video-sound). `music`, `music_processed` and `sfx` are the\n * individual stems; pass any of them, or `output_url` itself, to `download()`. */\nexport interface SoundResult extends BaseTaskResult {\n output_url?: string;\n output_type?: \"audio\" | \"video\";\n output_bytes?: number;\n music?: SfxMedia;\n /** Present only when `preserveSpeech`/`ducking` altered the music bed. */\n music_processed?: SfxMedia;\n sfx?: SfxMedia;\n duration_seconds?: number;\n}\n\n/**\n * A target language for /v1/dubbing. The union stays open (`string & {}`) so a\n * language added server-side still type-checks against an older SDK — the\n * backend, not this list, is the authority on what is supported.\n */\nexport type DubbingLanguage =\n | \"en\"\n | \"zh_cn\"\n | \"ja\"\n | \"ko\"\n | \"pt\"\n | \"es\"\n | \"de\"\n | \"fr\"\n | \"it\"\n | \"ru\"\n | (string & {});\n\nexport interface DubbingParams {\n /** Exactly one of `video` / `videoUrl`. */\n video?: VideoInput;\n /**\n * Exactly one of `video` / `videoUrl`. Must be an `https://` URL — the\n * dubbing pipeline fetches the source itself and rejects plain http.\n */\n videoUrl?: string;\n /** Omit to get the server default, `[\"zh_cn\", \"es\", \"fr\"]`. */\n languages?: DubbingLanguage[];\n}\n\nexport interface DubbingResult extends BaseTaskResult {\n /**\n * One dubbed video URL per requested language, keyed by language code.\n * Unlike every other endpoint's envelope this is a map, not an `audio`/\n * `video` slot — a dubbing task renders N artifacts, one per language.\n */\n outputs?: Record<string, string>;\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/errors.ts","../src/resources/account.ts","../src/resources/tasks.ts","../src/streaming.ts","../src/resources/textToMusic.ts","../src/upload.ts","../src/resources/videoToMusic.ts","../src/resources/textToSfx.ts","../src/resources/videoToSfx.ts","../src/resources/videoToVideoMusic.ts","../src/resources/videoToVideoSfx.ts","../src/resources/soundForm.ts","../src/resources/videoToSound.ts","../src/resources/videoToVideoSound.ts","../src/resources/dubbing.ts","../src/version.ts","../src/client.ts","../src/download.ts","../src/types.ts"],"sourcesContent":["export { DEFAULT_TIMEOUT_MS, SoniloClient, type SoniloClientOptions } from \"./client.js\";\nexport {\n APIError,\n AuthenticationError,\n BadRequestError,\n GenerationError,\n PaymentRequiredError,\n RateLimitError,\n RequestTimeoutError,\n SoniloError,\n TaskFailedError,\n TaskTimeoutError,\n TrialExhaustedError,\n} from \"./errors.js\";\nexport { download } from \"./download.js\";\nexport { VERSION } from \"./version.js\";\nexport type {\n AccountServices,\n AudioChunkEvent,\n BaseTaskResult,\n CompleteEvent,\n CostEvent,\n CostInfo,\n DailyUsage,\n DubbingLanguage,\n DubbingParams,\n DubbingResult,\n ErrorEvent,\n MusicMediaEntry,\n MusicMuxEntry,\n MusicTaskResult,\n MusicTitle,\n Segment,\n SegmentLabel,\n SfxAudioFormat,\n SfxError,\n SfxMedia,\n SfxResult,\n SfxSegment,\n SfxTask,\n SoundOutputEntry,\n SoundResult,\n StreamEvent,\n TextToMusicParams,\n TextToSfxParams,\n TitleEvent,\n Track,\n TrialQuota,\n UnknownEvent,\n UsageResponse,\n UsageSummary,\n VideoInput,\n VideoResult,\n VideoToMusicParams,\n VideoToSfxParams,\n VideoToSoundParams,\n VideoToVideoMusicParams,\n VideoToVideoSfxParams,\n WaitOptions,\n} from \"./types.js\";\nexport { isAudioChunkEvent, isErrorEvent } from \"./types.js\";\n","export class SoniloError extends Error {\n constructor(message: string) {\n super(message);\n this.name = new.target.name;\n }\n}\n\nexport class APIError extends SoniloError {\n readonly status: number;\n readonly body: unknown;\n /** The API's typed error code (e.g. \"rate_limit_exceeded\"), distinct from the HTTP status. */\n readonly code?: string;\n /** Per-field validation details, present on a 422. */\n readonly errors?: unknown[];\n\n constructor(message: string, status: number, body?: unknown) {\n super(message);\n this.status = status;\n this.body = body;\n const parsed = body as { code?: unknown; errors?: unknown } | undefined;\n this.code = typeof parsed?.code === \"string\" ? parsed.code : undefined;\n this.errors = Array.isArray(parsed?.errors) ? parsed.errors : undefined;\n }\n}\n\nexport class AuthenticationError extends APIError {}\n\nexport class PaymentRequiredError extends APIError {}\n\n/** The account's free trial for this service is spent and it has never been\n * funded — the caller should add a payment method rather than retry. A\n * subclass of `PaymentRequiredError`, so code that already catches every 402\n * keeps working; catch this first to tell \"you haven't paid us yet\" apart\n * from a funded wallet that ran dry (`PaymentRequiredError` with\n * `code === \"insufficient_balance\"`). */\nexport class TrialExhaustedError extends PaymentRequiredError {}\n\nexport class BadRequestError extends APIError {\n get detail(): string | undefined {\n const body = this.body as { message?: unknown; detail?: unknown } | undefined;\n if (typeof body?.message === \"string\" && body.message) {\n return body.message;\n }\n return typeof body?.detail === \"string\" ? body.detail : undefined;\n }\n}\n\nexport class RateLimitError extends APIError {\n readonly retryAfter?: number;\n\n constructor(message: string, status: number, body?: unknown, retryAfter?: number) {\n super(message, status, body);\n this.retryAfter = retryAfter;\n }\n}\n\n/** Raised by generate() when an `error` event arrives mid-stream. */\nexport class GenerationError extends SoniloError {\n readonly code?: string;\n\n constructor(message: string, code?: string) {\n super(message);\n this.code = code;\n }\n}\n\n/** Raised by tasks.wait()/generate() when an SFX task reaches `failed`. */\nexport class TaskFailedError extends SoniloError {\n readonly code?: string;\n readonly taskId: string;\n readonly refunded?: boolean;\n\n constructor(\n message: string,\n opts: { code?: string; taskId: string; refunded?: boolean },\n ) {\n super(message);\n this.code = opts.code;\n this.taskId = opts.taskId;\n this.refunded = opts.refunded;\n }\n}\n\n/** Poll deadline passed. The task may still finish server-side — resume with\n * tasks.wait(taskId) or tasks.get(taskId). */\nexport class TaskTimeoutError extends SoniloError {\n readonly taskId: string;\n\n constructor(message: string, taskId: string) {\n super(message);\n this.taskId = taskId;\n }\n}\n\n/** Raised when a one-shot request or download is aborted by its own timeout\n * signal (as opposed to a caller-supplied AbortSignal, which propagates\n * untouched). */\nexport class RequestTimeoutError extends SoniloError {}\n\n/**\n * True if `err` is the rejection produced when an `AbortSignal.timeout()`\n * we created fires. Used to distinguish \"our\" timeout aborts (which should be\n * rethrown as `RequestTimeoutError`) from a caller-supplied signal's abort\n * (which must propagate untouched).\n */\nexport function isTimeoutSignalError(err: unknown): boolean {\n return err instanceof Error && (err.name === \"TimeoutError\" || err.name === \"AbortError\");\n}\n\nexport async function errorFromResponse(res: Response): Promise<APIError> {\n const text = await res.text().catch(() => \"\");\n let body: unknown = text;\n try {\n body = JSON.parse(text);\n } catch {\n // keep raw text\n }\n const parsed = body as { message?: unknown; detail?: unknown } | undefined;\n const rawMessage = typeof parsed?.message === \"string\" && parsed.message ? parsed.message : undefined;\n const rawDetail = parsed?.detail;\n const isDetailAbsent = rawDetail === undefined || rawDetail === null || rawDetail === \"\";\n let reason: string;\n if (rawMessage !== undefined) {\n reason = rawMessage;\n } else if (isDetailAbsent) {\n reason = res.statusText || \"request failed\";\n } else if (typeof rawDetail === \"string\") {\n reason = rawDetail;\n } else {\n try {\n reason = JSON.stringify(rawDetail);\n } catch {\n reason = res.statusText || \"request failed\";\n }\n }\n const message = `HTTP ${res.status}: ${reason}`;\n\n switch (res.status) {\n case 401:\n return new AuthenticationError(message, res.status, body);\n case 402: {\n // Branch on the API's `code`, never on the message text — the wording\n // is product copy and changes; the code is the contract.\n const code = (body as { code?: unknown } | undefined)?.code;\n if (code === \"trial_exhausted\") {\n return new TrialExhaustedError(message, res.status, body);\n }\n return new PaymentRequiredError(message, res.status, body);\n }\n case 429: {\n const ra = res.headers.get(\"retry-after\");\n const retryAfter = ra !== null && ra !== \"\" && !Number.isNaN(Number(ra)) ? Number(ra) : undefined;\n return new RateLimitError(message, res.status, body, retryAfter);\n }\n case 400:\n case 413:\n case 422:\n return new BadRequestError(message, res.status, body);\n default:\n return new APIError(message, res.status, body);\n }\n}\n","import type { SoniloClient } from \"../client.js\";\nimport type { AccountServices, UsageResponse } from \"../types.js\";\n\nexport class Account {\n constructor(private readonly client: SoniloClient) {}\n\n async services(): Promise<AccountServices> {\n const res = await this.client.request(\"/v1/account/services\");\n return (await res.json()) as AccountServices;\n }\n\n async usage(params: { days?: number } = {}): Promise<UsageResponse> {\n const query = params.days !== undefined ? `?days=${params.days}` : \"\";\n const res = await this.client.request(`/v1/account/usage${query}`);\n return (await res.json()) as UsageResponse;\n }\n}\n","import type { SoniloClient } from \"../client.js\";\nimport { SoniloError, TaskFailedError, TaskTimeoutError } from \"../errors.js\";\nimport type { BaseTaskResult, SfxResult, WaitOptions } from \"../types.js\";\n\nexport const DEFAULT_POLL_INTERVAL_MS = 2000;\nexport const DEFAULT_WAIT_TIMEOUT_MS = 600_000;\n\nconst sleep = (ms: number) => new Promise<void>((resolve) => setTimeout(resolve, ms));\n\n/** A negative delay is clamped to 0 by setTimeout, which would turn the poll\n * loop into a busy loop hammering the API until the deadline. */\nfunction validateWaitArgs(pollInterval: number, timeout: number): void {\n if (pollInterval < 0) {\n throw new SoniloError(`pollInterval must be >= 0, got ${pollInterval}`);\n }\n if (timeout < 0) {\n throw new SoniloError(`timeout must be >= 0, got ${timeout}`);\n }\n}\n\nexport class Tasks {\n constructor(private readonly client: SoniloClient) {}\n\n /**\n * Fetch current task state. Never throws on a failed status.\n *\n * Generic over the result shape so callers can request the endpoint-\n * specific type, e.g. `client.tasks.get<MusicTaskResult>(taskId)`.\n * Defaults to `SfxResult` for back-compat.\n */\n async get<T extends BaseTaskResult = SfxResult>(taskId: string): Promise<T> {\n const res = await this.client.request(`/v1/tasks/${encodeURIComponent(taskId)}`);\n return (await res.json()) as T;\n }\n\n /**\n * Poll until the task is terminal; throw on failure or deadline.\n *\n * Generic over the result shape, e.g.\n * `client.tasks.wait<MusicTaskResult>(taskId)`. Defaults to `SfxResult`\n * for back-compat.\n */\n async wait<T extends BaseTaskResult = SfxResult>(\n taskId: string,\n opts: WaitOptions = {},\n ): Promise<T> {\n const pollInterval = opts.pollInterval ?? DEFAULT_POLL_INTERVAL_MS;\n const timeout = opts.timeout ?? DEFAULT_WAIT_TIMEOUT_MS;\n validateWaitArgs(pollInterval, timeout);\n const deadline = performance.now() + timeout;\n for (;;) {\n const result = await this.get<T>(taskId);\n if (result.status === \"succeeded\") return result;\n if (result.status === \"failed\") {\n const message = result.error?.message || \"Generation failed\";\n throw new TaskFailedError(`Task ${taskId} failed: ${message}`, {\n code: result.error?.code,\n taskId,\n refunded: result.refunded,\n });\n }\n const remaining = deadline - performance.now();\n if (remaining <= 0) {\n throw new TaskTimeoutError(\n `Task ${taskId} still processing after ${timeout}ms; ` +\n \"it may finish later — resume with tasks.wait or tasks.get\",\n taskId,\n );\n }\n await sleep(Math.min(pollInterval, remaining));\n }\n }\n}\n","import { GenerationError } from \"./errors.js\";\nimport type { CostInfo, StreamEvent, Track } from \"./types.js\";\n\nexport function decodeBase64(b64: string): Uint8Array {\n const bin = atob(b64);\n const out = new Uint8Array(bin.length);\n for (let i = 0; i < bin.length; i++) out[i] = bin.charCodeAt(i);\n return out;\n}\n\n/** Returns `null` for a valid-JSON-but-non-object line (e.g. a bare `null`\n * or a number/string), which carries no event `type` and is skipped like any\n * other junk line rather than crashing on a `.type` read off `null`. */\nfunction toEvent(line: string): StreamEvent | null {\n const parsed: unknown = JSON.parse(line);\n if (typeof parsed !== \"object\" || parsed === null) return null;\n const raw = parsed as { type: string; [key: string]: unknown };\n if (raw.type === \"audio_chunk\" && typeof raw.data === \"string\") {\n try {\n return { ...raw, type: \"audio_chunk\", data: decodeBase64(raw.data) };\n } catch {\n // Don't raise here: this must reach collectTrack's malformed-chunk\n // check, which turns undecodable data into a typed GenerationError.\n // Raising in place would let a raw DOMException escape\n // stream()/generate(), breaking the SDK's \"all errors extend\n // SoniloError\" contract.\n }\n }\n return raw as StreamEvent;\n}\n\nexport async function* parseNdjson(\n body: ReadableStream<Uint8Array>,\n): AsyncGenerator<StreamEvent, void, undefined> {\n const reader = body.getReader();\n const decoder = new TextDecoder();\n let buffer = \"\";\n try {\n for (;;) {\n const { done, value } = await reader.read();\n if (done) break;\n buffer += decoder.decode(value, { stream: true });\n let nl: number;\n while ((nl = buffer.indexOf(\"\\n\")) !== -1) {\n const line = buffer.slice(0, nl).trim();\n buffer = buffer.slice(nl + 1);\n if (line) {\n const ev = toEvent(line);\n if (ev !== null) yield ev;\n }\n }\n }\n buffer += decoder.decode();\n const tail = buffer.trim();\n if (tail) {\n const ev = toEvent(tail);\n if (ev !== null) yield ev;\n }\n } finally {\n await reader.cancel().catch(() => {});\n }\n}\n\nexport async function collectTrack(events: AsyncIterable<StreamEvent>): Promise<Track> {\n const chunks: Uint8Array[] = [];\n let title: string | undefined;\n let cost: CostInfo | undefined;\n let sawComplete = false;\n\n for await (const ev of events) {\n if (ev.type === \"audio_chunk\") {\n // A malformed chunk (missing/non-decodable `data`) must not be\n // silently dropped: that would hand back a \"successful\" Track with\n // empty or truncated audio and no indication anything went wrong.\n if (!(ev.data instanceof Uint8Array)) {\n throw new GenerationError(\n \"received a malformed audio_chunk event (missing or non-decodable data)\",\n );\n }\n chunks.push(ev.data);\n } else if (ev.type === \"title\" && typeof ev.title === \"string\") {\n title = ev.title;\n } else if (ev.type === \"cost\") {\n const { type: _type, ...rest } = ev;\n cost = rest as CostInfo;\n } else if (ev.type === \"error\") {\n const message = typeof ev.message === \"string\" && ev.message !== \"\" ? ev.message : \"generation failed\";\n const code = typeof ev.code === \"string\" ? ev.code : undefined;\n throw new GenerationError(message, code);\n } else if (ev.type === \"complete\") {\n sawComplete = true;\n }\n // unknown event types: ignored\n }\n\n if (!sawComplete) {\n throw new GenerationError(\"stream ended before a 'complete' event (truncated response)\");\n }\n\n const total = chunks.reduce((n, c) => n + c.length, 0);\n const audio = new Uint8Array(total);\n let offset = 0;\n for (const c of chunks) {\n audio.set(c, offset);\n offset += c.length;\n }\n return { audio, title, cost };\n}\n","import type { SoniloClient } from \"../client.js\";\nimport { SoniloError } from \"../errors.js\";\nimport { collectTrack, parseNdjson } from \"../streaming.js\";\nimport type { SfxTask, StreamEvent, TextToMusicParams, Track } from \"../types.js\";\n\nexport class TextToMusic {\n constructor(private readonly client: SoniloClient) {}\n\n /** Stream raw generation events (audio chunks pre-decoded to bytes). */\n async *stream(params: TextToMusicParams): AsyncGenerator<StreamEvent, void, undefined> {\n const form = new FormData();\n form.set(\"prompt\", params.prompt);\n form.set(\"duration\", String(params.duration));\n if (params.segments !== undefined) {\n form.set(\"segments\", JSON.stringify(params.segments));\n }\n // Opt out of the client's absolute request timeout: this holds the\n // response body open and reads NDJSON chunks for as long as generation\n // takes, so an AbortSignal keyed to elapsed time would kill a healthy,\n // still-streaming, long-duration track. Pass `params.signal` yourself to\n // bound or cancel the stream instead — it is forwarded to `fetch` as-is.\n const res = await this.client.request(\n \"/v1/text-to-music\",\n { method: \"POST\", body: form, signal: params.signal },\n { timeout: null },\n );\n if (!res.body) throw new SoniloError(\"Response has no body\");\n yield* parseNdjson(res.body);\n }\n\n /** Generate and buffer the whole track; throws GenerationError on stream errors. */\n generate(params: TextToMusicParams): Promise<Track> {\n return collectTrack(this.stream(params));\n }\n\n /**\n * Submit an async text-to-music task; poll with\n * `client.tasks.wait<MusicTaskResult>(task.task_id)`. Required for\n * `outputFormat: \"wav\"` and `variantsNum` above 1. `stream()`/`generate()`\n * remain the streaming path.\n */\n async submit(params: TextToMusicParams): Promise<SfxTask> {\n const mode = params.mode ?? \"async\";\n if (mode !== \"async\") {\n throw new SoniloError('submit() requires mode: \"async\"');\n }\n const form = new FormData();\n form.set(\"prompt\", params.prompt);\n form.set(\"duration\", String(params.duration));\n if (params.segments !== undefined) {\n form.set(\"segments\", JSON.stringify(params.segments));\n }\n form.set(\"mode\", mode);\n if (params.outputFormat !== undefined) {\n form.set(\"output_format\", params.outputFormat);\n }\n if (params.variantsNum !== undefined) {\n form.set(\"variants_num\", String(params.variantsNum));\n }\n const res = await this.client.request(\"/v1/text-to-music\", {\n method: \"POST\",\n body: form,\n });\n return (await res.json()) as SfxTask;\n }\n}\n","import { SoniloError } from \"./errors.js\";\nimport type { VideoInput } from \"./types.js\";\n\nconst DEFAULT_FILENAME = \"video.mp4\";\n\n/**\n * Normalize every accepted video input into a FormData-ready Blob.\n * String inputs are file paths and work only in Node.js; browsers must\n * pass File/Blob/bytes/streams.\n */\nexport async function toUploadBlob(\n video: VideoInput,\n): Promise<{ blob: Blob; filename: string }> {\n if (typeof video === \"string\") {\n const isNode =\n typeof process !== \"undefined\" && Boolean((process as { versions?: { node?: string } }).versions?.node);\n if (!isNode) {\n throw new SoniloError(\n \"File paths are only supported in Node.js; pass a File or Blob in the browser\",\n );\n }\n const fsModule = \"node:fs/promises\";\n const { readFile } = (await import(\n /* webpackIgnore: true */ /* @vite-ignore */ fsModule\n )) as typeof import(\"node:fs/promises\");\n const data = await readFile(video);\n const filename = video.split(/[\\\\/]/).pop() || DEFAULT_FILENAME;\n return { blob: new Blob([data]), filename };\n }\n if (typeof File !== \"undefined\" && video instanceof File) {\n return { blob: video, filename: video.name || DEFAULT_FILENAME };\n }\n if (video instanceof Blob) {\n return { blob: video, filename: DEFAULT_FILENAME };\n }\n if (video instanceof Uint8Array) {\n return { blob: new Blob([video as unknown as BlobPart]), filename: DEFAULT_FILENAME };\n }\n if (video instanceof ArrayBuffer) {\n return { blob: new Blob([video]), filename: DEFAULT_FILENAME };\n }\n if (video instanceof ReadableStream) {\n return { blob: await new Response(video).blob(), filename: DEFAULT_FILENAME };\n }\n throw new SoniloError(\"Unsupported video input type\");\n}\n","import type { SoniloClient } from \"../client.js\";\nimport { SoniloError } from \"../errors.js\";\nimport { collectTrack, parseNdjson } from \"../streaming.js\";\nimport { toUploadBlob } from \"../upload.js\";\nimport type { SfxTask, StreamEvent, Track, VideoToMusicParams } from \"../types.js\";\n\nexport class VideoToMusic {\n constructor(private readonly client: SoniloClient) {}\n\n async *stream(params: VideoToMusicParams): AsyncGenerator<StreamEvent, void, undefined> {\n if ((params.video === undefined) === (params.videoUrl === undefined)) {\n throw new SoniloError(\"Provide exactly one of video or videoUrl\");\n }\n const form = new FormData();\n if (params.video !== undefined) {\n const { blob, filename } = await toUploadBlob(params.video);\n form.set(\"video\", blob, filename);\n } else {\n form.set(\"video_url\", params.videoUrl as string);\n }\n if (params.prompt !== undefined) form.set(\"prompt\", params.prompt);\n if (params.segments !== undefined) {\n form.set(\"segments\", JSON.stringify(params.segments));\n }\n // Opt out of the client's absolute request timeout: this holds the\n // response body open and reads NDJSON chunks for as long as generation\n // takes, so an AbortSignal keyed to elapsed time would kill a healthy,\n // still-streaming request (e.g. a slow video upload or long track). Pass\n // `params.signal` yourself to bound or cancel the stream instead — it is\n // forwarded to `fetch` as-is.\n const res = await this.client.request(\n \"/v1/video-to-music\",\n { method: \"POST\", body: form, signal: params.signal },\n { timeout: null },\n );\n if (!res.body) throw new SoniloError(\"Response has no body\");\n yield* parseNdjson(res.body);\n }\n\n generate(params: VideoToMusicParams): Promise<Track> {\n return collectTrack(this.stream(params));\n }\n\n /**\n * Submit an async video-to-music task; poll its result with\n * `client.tasks.wait<MusicTaskResult>(task.task_id)`. Required for\n * `isolateVocals`/`preserveSpeech`, `outputFormat: \"wav\"`, and\n * `variantsNum` above 1 — the backend rejects all of these on the plain\n * stream, and they only ever run in async mode.\n */\n async submit(params: VideoToMusicParams): Promise<SfxTask> {\n if ((params.video === undefined) === (params.videoUrl === undefined)) {\n throw new SoniloError(\"Provide exactly one of video or videoUrl\");\n }\n let mode = params.mode;\n const needsAsync =\n params.isolateVocals ||\n params.preserveSpeech ||\n params.ducking !== undefined ||\n params.outputFormat === \"wav\" ||\n (params.variantsNum !== undefined && params.variantsNum > 1);\n // submit() always wants an async task ack, never a stream. Default to\n // async; only object if the caller explicitly asked for stream while\n // also requesting an async-only feature.\n if (mode === undefined) mode = \"async\";\n if (needsAsync && mode !== \"async\") {\n throw new SoniloError(\n 'isolateVocals/preserveSpeech/ducking/outputFormat \"wav\"/variantsNum > 1 require mode: \"async\"',\n );\n }\n const form = new FormData();\n if (params.video !== undefined) {\n const { blob, filename } = await toUploadBlob(params.video);\n form.set(\"video\", blob, filename);\n } else {\n form.set(\"video_url\", params.videoUrl as string);\n }\n if (params.prompt !== undefined) form.set(\"prompt\", params.prompt);\n if (params.segments !== undefined) {\n form.set(\"segments\", JSON.stringify(params.segments));\n }\n form.set(\"mode\", mode);\n if (params.preserveSpeech !== undefined) {\n form.set(\"preserve_speech\", String(params.preserveSpeech));\n }\n if (params.isolateVocals !== undefined) {\n form.set(\"isolate_vocals\", String(params.isolateVocals));\n }\n if (params.outputFormat !== undefined) {\n form.set(\"output_format\", params.outputFormat);\n }\n if (params.ducking !== undefined) {\n form.set(\"ducking\", String(params.ducking));\n }\n if (params.variantsNum !== undefined) {\n form.set(\"variants_num\", String(params.variantsNum));\n }\n const res = await this.client.request(\"/v1/video-to-music\", {\n method: \"POST\",\n body: form,\n });\n return (await res.json()) as SfxTask;\n }\n}\n","import type { SoniloClient } from \"../client.js\";\nimport type { SfxResult, SfxTask, TextToSfxParams, WaitOptions } from \"../types.js\";\n\nexport class TextToSfx {\n constructor(private readonly client: SoniloClient) {}\n\n async submit(params: TextToSfxParams): Promise<SfxTask> {\n const form = new FormData();\n form.set(\"prompt\", params.prompt);\n form.set(\"duration\", String(params.duration));\n if (params.audioFormat !== undefined) form.set(\"audio_format\", params.audioFormat);\n const res = await this.client.request(\"/v1/text-to-sfx\", {\n method: \"POST\",\n body: form,\n });\n return (await res.json()) as SfxTask;\n }\n\n async generate(params: TextToSfxParams, opts?: WaitOptions): Promise<SfxResult> {\n const task = await this.submit(params);\n return this.client.tasks.wait(task.task_id, opts);\n }\n}\n","import type { SoniloClient } from \"../client.js\";\nimport { SoniloError } from \"../errors.js\";\nimport { toUploadBlob } from \"../upload.js\";\nimport type { SfxResult, SfxTask, VideoToSfxParams, WaitOptions } from \"../types.js\";\n\nexport class VideoToSfx {\n constructor(private readonly client: SoniloClient) {}\n\n async submit(params: VideoToSfxParams): Promise<SfxTask> {\n if ((params.video === undefined) === (params.videoUrl === undefined)) {\n throw new SoniloError(\"Provide exactly one of video or videoUrl\");\n }\n const form = new FormData();\n if (params.video !== undefined) {\n const { blob, filename } = await toUploadBlob(params.video);\n form.set(\"video\", blob, filename);\n } else {\n form.set(\"video_url\", params.videoUrl as string);\n }\n if (params.prompt !== undefined) form.set(\"prompt\", params.prompt);\n if (params.segments !== undefined) {\n form.set(\"segments\", JSON.stringify(params.segments));\n }\n if (params.audioFormat !== undefined) form.set(\"audio_format\", params.audioFormat);\n const res = await this.client.request(\"/v1/video-to-sfx\", {\n method: \"POST\",\n body: form,\n });\n return (await res.json()) as SfxTask;\n }\n\n async generate(params: VideoToSfxParams, opts?: WaitOptions): Promise<SfxResult> {\n const task = await this.submit(params);\n return this.client.tasks.wait(task.task_id, opts);\n }\n}\n","import type { SoniloClient } from \"../client.js\";\nimport { SoniloError } from \"../errors.js\";\nimport { toUploadBlob } from \"../upload.js\";\nimport type { SfxTask, VideoResult, VideoToVideoMusicParams, WaitOptions } from \"../types.js\";\n\n/** Generate an original score for a video and get back a re-hosted video with\n * the music muxed in. Async only: `submit()` returns a task ack; poll with\n * `client.tasks.wait<VideoResult>(id)`, or use `generate()` to do both. */\nexport class VideoToVideoMusic {\n constructor(private readonly client: SoniloClient) {}\n\n async submit(params: VideoToVideoMusicParams): Promise<SfxTask> {\n if ((params.video === undefined) === (params.videoUrl === undefined)) {\n throw new SoniloError(\"Provide exactly one of video or videoUrl\");\n }\n const form = new FormData();\n if (params.video !== undefined) {\n const { blob, filename } = await toUploadBlob(params.video);\n form.set(\"video\", blob, filename);\n } else {\n form.set(\"video_url\", params.videoUrl as string);\n }\n if (params.prompt !== undefined) form.set(\"prompt\", params.prompt);\n if (params.preserveSpeech !== undefined) {\n form.set(\"preserve_speech\", String(params.preserveSpeech));\n }\n if (params.isolateVocals !== undefined) {\n form.set(\"isolate_vocals\", String(params.isolateVocals));\n }\n if (params.variantsNum !== undefined) {\n form.set(\"variants_num\", String(params.variantsNum));\n }\n const res = await this.client.request(\"/v1/video-to-video-music\", {\n method: \"POST\",\n body: form,\n });\n return (await res.json()) as SfxTask;\n }\n\n async generate(params: VideoToVideoMusicParams, opts?: WaitOptions): Promise<VideoResult> {\n const task = await this.submit(params);\n return this.client.tasks.wait<VideoResult>(task.task_id, opts);\n }\n}\n","import type { SoniloClient } from \"../client.js\";\nimport { SoniloError } from \"../errors.js\";\nimport { toUploadBlob } from \"../upload.js\";\nimport type { SfxTask, VideoResult, VideoToVideoSfxParams, WaitOptions } from \"../types.js\";\n\n/** Generate sound effects for a video and get back a re-hosted video with the\n * SFX muxed in. Async only. */\nexport class VideoToVideoSfx {\n constructor(private readonly client: SoniloClient) {}\n\n async submit(params: VideoToVideoSfxParams): Promise<SfxTask> {\n if ((params.video === undefined) === (params.videoUrl === undefined)) {\n throw new SoniloError(\"Provide exactly one of video or videoUrl\");\n }\n const form = new FormData();\n if (params.video !== undefined) {\n const { blob, filename } = await toUploadBlob(params.video);\n form.set(\"video\", blob, filename);\n } else {\n form.set(\"video_url\", params.videoUrl as string);\n }\n if (params.prompt !== undefined) form.set(\"prompt\", params.prompt);\n if (params.segments !== undefined) {\n form.set(\"segments\", JSON.stringify(params.segments));\n }\n const res = await this.client.request(\"/v1/video-to-video-sfx\", {\n method: \"POST\",\n body: form,\n });\n return (await res.json()) as SfxTask;\n }\n\n async generate(params: VideoToVideoSfxParams, opts?: WaitOptions): Promise<VideoResult> {\n const task = await this.submit(params);\n return this.client.tasks.wait<VideoResult>(task.task_id, opts);\n }\n}\n","import { SoniloError } from \"../errors.js\";\nimport { toUploadBlob } from \"../upload.js\";\nimport type { VideoToSoundParams } from \"../types.js\";\n\n/** Build the multipart body shared by /v1/video-to-sound and\n * /v1/video-to-video-sound — their form fields are identical, so the two\n * resources differ only in the path they POST to.\n *\n * Every optional field is omitted when unset rather than sent with a default:\n * `ducking` in particular is default-ON server-side, so an unset value must\n * not become an explicit \"false\" on the wire. */\nexport async function buildSoundForm(params: VideoToSoundParams): Promise<FormData> {\n if ((params.video === undefined) === (params.videoUrl === undefined)) {\n throw new SoniloError(\"Provide exactly one of video or videoUrl\");\n }\n const form = new FormData();\n if (params.video !== undefined) {\n const { blob, filename } = await toUploadBlob(params.video);\n form.set(\"video\", blob, filename);\n } else {\n form.set(\"video_url\", params.videoUrl as string);\n }\n if (params.musicPrompt !== undefined) form.set(\"music_prompt\", params.musicPrompt);\n if (params.sfxPrompt !== undefined) form.set(\"sfx_prompt\", params.sfxPrompt);\n if (params.segments !== undefined) {\n form.set(\"segments\", JSON.stringify(params.segments));\n }\n if (params.preserveSpeech !== undefined) {\n form.set(\"preserve_speech\", String(params.preserveSpeech));\n }\n if (params.ducking !== undefined) form.set(\"ducking\", String(params.ducking));\n if (params.variantsNum !== undefined) {\n form.set(\"variants_num\", String(params.variantsNum));\n }\n return form;\n}\n","import type { SoniloClient } from \"../client.js\";\nimport { buildSoundForm } from \"./soundForm.js\";\nimport type { SfxTask, SoundResult, VideoToSoundParams, WaitOptions } from \"../types.js\";\n\n/** Generate a combined music + sound-effects track for a video and get back\n * the mixed audio. Async only. */\nexport class VideoToSound {\n constructor(private readonly client: SoniloClient) {}\n\n async submit(params: VideoToSoundParams): Promise<SfxTask> {\n const res = await this.client.request(\"/v1/video-to-sound\", {\n method: \"POST\",\n body: await buildSoundForm(params),\n });\n return (await res.json()) as SfxTask;\n }\n\n async generate(params: VideoToSoundParams, opts?: WaitOptions): Promise<SoundResult> {\n const task = await this.submit(params);\n return this.client.tasks.wait<SoundResult>(task.task_id, opts);\n }\n}\n","import type { SoniloClient } from \"../client.js\";\nimport { buildSoundForm } from \"./soundForm.js\";\nimport type { SfxTask, SoundResult, VideoToSoundParams, WaitOptions } from \"../types.js\";\n\n/** Generate a combined music + sound-effects track for a video and get back a\n * re-hosted video with that track muxed in. Async only. */\nexport class VideoToVideoSound {\n constructor(private readonly client: SoniloClient) {}\n\n async submit(params: VideoToSoundParams): Promise<SfxTask> {\n const res = await this.client.request(\"/v1/video-to-video-sound\", {\n method: \"POST\",\n body: await buildSoundForm(params),\n });\n return (await res.json()) as SfxTask;\n }\n\n async generate(params: VideoToSoundParams, opts?: WaitOptions): Promise<SoundResult> {\n const task = await this.submit(params);\n return this.client.tasks.wait<SoundResult>(task.task_id, opts);\n }\n}\n","import type { SoniloClient } from \"../client.js\";\nimport { SoniloError } from \"../errors.js\";\nimport { toUploadBlob } from \"../upload.js\";\nimport type { DubbingParams, DubbingResult, SfxTask, WaitOptions } from \"../types.js\";\n\n/** Build the multipart body for /v1/dubbing.\n *\n * `languages` travels as one opaque form field holding a JSON array string —\n * that is the shape the backend parses. It is omitted entirely when unset so\n * the server default ([\"zh_cn\", \"es\", \"fr\"]) applies; sending an empty array\n * instead would be rejected as a malformed payload.\n *\n * The https check is local because it is a guaranteed server-side 422: the\n * dubbing pipeline fetches the source URL itself and requires https\n * specifically, unlike the fal-backed endpoints, which accept plain http.\n * Language codes are deliberately NOT checked here — the backend owns that\n * list, and a hardcoded copy would make this SDK reject codes added later. */\nexport async function buildDubbingForm(params: DubbingParams): Promise<FormData> {\n if ((params.video === undefined) === (params.videoUrl === undefined)) {\n throw new SoniloError(\"Provide exactly one of video or videoUrl\");\n }\n const form = new FormData();\n if (params.video !== undefined) {\n const { blob, filename } = await toUploadBlob(params.video);\n form.set(\"video\", blob, filename);\n } else {\n const url = params.videoUrl as string;\n if (!url.toLowerCase().startsWith(\"https://\")) {\n throw new SoniloError(\n \"videoUrl must use https — the dubbing pipeline requires an https URL\",\n );\n }\n form.set(\"video_url\", url);\n }\n if (params.languages !== undefined) {\n form.set(\"languages\", JSON.stringify(params.languages));\n }\n if (params.ducking !== undefined) {\n form.set(\"ducking\", String(params.ducking));\n }\n return form;\n}\n\n/** Dub a video into one or more target languages. Async only; the result\n * carries a language → dubbed-video-URL map under `outputs`. */\nexport class Dubbing {\n constructor(private readonly client: SoniloClient) {}\n\n async submit(params: DubbingParams): Promise<SfxTask> {\n const res = await this.client.request(\"/v1/dubbing\", {\n method: \"POST\",\n body: await buildDubbingForm(params),\n });\n return (await res.json()) as SfxTask;\n }\n\n async generate(params: DubbingParams, opts?: WaitOptions): Promise<DubbingResult> {\n const task = await this.submit(params);\n return this.client.tasks.wait<DubbingResult>(task.task_id, opts);\n }\n}\n","/** The SDK's own version. Generated by scripts/sync-versions.mjs — do not edit. */\nexport const VERSION = \"0.9.0\";\n","import { RequestTimeoutError, SoniloError, errorFromResponse, isTimeoutSignalError } from \"./errors.js\";\nimport { Account } from \"./resources/account.js\";\nimport { Tasks } from \"./resources/tasks.js\";\nimport { TextToMusic } from \"./resources/textToMusic.js\";\nimport { VideoToMusic } from \"./resources/videoToMusic.js\";\nimport { TextToSfx } from \"./resources/textToSfx.js\";\nimport { VideoToSfx } from \"./resources/videoToSfx.js\";\nimport { VideoToVideoMusic } from \"./resources/videoToVideoMusic.js\";\nimport { VideoToVideoSfx } from \"./resources/videoToVideoSfx.js\";\nimport { VideoToSound } from \"./resources/videoToSound.js\";\nimport { VideoToVideoSound } from \"./resources/videoToVideoSound.js\";\nimport { Dubbing } from \"./resources/dubbing.js\";\nimport { VERSION } from \"./version.js\";\n\nexport interface SoniloClientOptions {\n /** Defaults to the SONILO_API_KEY environment variable (Node.js only). */\n apiKey?: string;\n /** Defaults to https://api.sonilo.com */\n baseUrl?: string;\n /** Injection point for tests and custom transports. */\n fetch?: typeof globalThis.fetch;\n /** Milliseconds before an in-flight request is aborted. Default 600000. */\n timeout?: number;\n /**\n * Identifies a wrapper built on this SDK (the CLI, the video kit) in the\n * `X-Sonilo-Client` header. Leave unset for direct SDK use — without an\n * override a wrapper's traffic is indistinguishable from the SDK's own.\n */\n clientName?: string;\n /** Version reported alongside `clientName`. Defaults to the SDK's version. */\n clientVersion?: string;\n}\n\nconst DEFAULT_BASE_URL = \"https://api.sonilo.com\";\n\n/**\n * Reported in `X-Sonilo-Client` unless a wrapper overrides it. First-party\n * wrappers (the CLI, the video kit) pass their own name so their traffic stays\n * distinguishable from direct SDK use in server-side analytics.\n */\nexport const DEFAULT_CLIENT_NAME = \"sdk-js\";\n\n/** Milliseconds before an in-flight request is aborted, unless overridden. */\nexport const DEFAULT_TIMEOUT_MS = 600_000;\n\nexport class SoniloClient {\n readonly baseUrl: string;\n private readonly apiKey: string;\n private readonly fetchFn: typeof globalThis.fetch;\n private readonly timeout: number;\n private readonly clientName: string;\n private readonly clientVersion: string;\n readonly account: Account;\n readonly tasks: Tasks;\n readonly textToMusic: TextToMusic;\n readonly videoToMusic: VideoToMusic;\n readonly textToSfx: TextToSfx;\n readonly videoToSfx: VideoToSfx;\n readonly videoToVideoMusic: VideoToVideoMusic;\n readonly videoToVideoSfx: VideoToVideoSfx;\n readonly videoToSound: VideoToSound;\n readonly videoToVideoSound: VideoToVideoSound;\n readonly dubbing: Dubbing;\n\n constructor(options: SoniloClientOptions = {}) {\n const envKey =\n typeof process !== \"undefined\" ? process.env?.SONILO_API_KEY : undefined;\n const apiKey = options.apiKey ?? envKey;\n if (!apiKey) {\n throw new SoniloError(\n \"Missing API key: pass { apiKey } or set the SONILO_API_KEY environment variable\",\n );\n }\n this.apiKey = apiKey;\n this.baseUrl = (options.baseUrl ?? DEFAULT_BASE_URL).replace(/\\/+$/, \"\");\n this.fetchFn = (options.fetch ?? globalThis.fetch).bind(globalThis);\n this.timeout = options.timeout ?? DEFAULT_TIMEOUT_MS;\n this.clientName = options.clientName ?? DEFAULT_CLIENT_NAME;\n this.clientVersion = options.clientVersion ?? VERSION;\n this.account = new Account(this);\n this.tasks = new Tasks(this);\n this.textToMusic = new TextToMusic(this);\n this.videoToMusic = new VideoToMusic(this);\n this.textToSfx = new TextToSfx(this);\n this.videoToSfx = new VideoToSfx(this);\n this.videoToVideoMusic = new VideoToVideoMusic(this);\n this.videoToVideoSfx = new VideoToVideoSfx(this);\n this.videoToSound = new VideoToSound(this);\n this.videoToVideoSound = new VideoToVideoSound(this);\n this.dubbing = new Dubbing(this);\n }\n\n /**\n * Perform an authenticated request; throws a typed error on non-2xx.\n *\n * `opts.timeout` overrides the client's default timeout for this call;\n * pass `null` to disable the abort-on-timeout behavior entirely (used by\n * the streaming music endpoints — see textToMusic.ts / videoToMusic.ts).\n * A caller-supplied `init.signal` always wins over any timeout signal.\n */\n async request(\n path: string,\n init: RequestInit = {},\n opts: { timeout?: number | null } = {},\n ): Promise<Response> {\n const headers = new Headers(init.headers);\n headers.set(\"Authorization\", `Bearer ${this.apiKey}`);\n headers.set(\"X-Sonilo-Client\", this.clientName);\n headers.set(\"X-Sonilo-Client-Version\", this.clientVersion);\n const timeout = opts.timeout === undefined ? this.timeout : opts.timeout;\n // We only \"own\" the signal (and may later rewrap its abort as a\n // RequestTimeoutError) when the caller didn't supply one and a timeout\n // is actually enabled.\n const ownsSignal = init.signal == null && timeout !== null;\n const signal = init.signal ?? (timeout === null ? undefined : AbortSignal.timeout(timeout));\n try {\n const res = await this.fetchFn(`${this.baseUrl}${path}`, { ...init, headers, signal });\n if (!res.ok) throw await errorFromResponse(res);\n return res;\n } catch (err) {\n if (ownsSignal && isTimeoutSignalError(err)) {\n throw new RequestTimeoutError(`Request to ${path} timed out after ${timeout}ms`);\n }\n throw err;\n }\n }\n}\n","import { DEFAULT_TIMEOUT_MS } from \"./client.js\";\nimport { RequestTimeoutError, SoniloError, isTimeoutSignalError } from \"./errors.js\";\nimport type { SfxMedia } from \"./types.js\";\n\n/** Fetch a result media file. The URL is presigned — no API key is sent.\n *\n * Accepts either a media object (`result.audio`, `result.music`, …) or a bare\n * URL string, which is what the combined video-to-sound endpoints return as\n * `output_url`. */\nexport async function download(\n media: SfxMedia | string | undefined,\n fetchFn: typeof globalThis.fetch = globalThis.fetch,\n timeout: number = DEFAULT_TIMEOUT_MS,\n): Promise<Uint8Array> {\n const url = typeof media === \"string\" ? media : media?.url;\n if (!url) {\n throw new SoniloError(\"No media to download\");\n }\n let res: Response;\n try {\n res = await fetchFn(url, { signal: AbortSignal.timeout(timeout) });\n } catch (err) {\n if (isTimeoutSignalError(err)) {\n throw new RequestTimeoutError(`Download of ${url} timed out after ${timeout}ms`);\n }\n throw err;\n }\n if (!res.ok) {\n throw new SoniloError(`Download failed: HTTP ${res.status}`);\n }\n return new Uint8Array(await res.arrayBuffer());\n}\n","export type SegmentLabel =\n | \"intro\"\n | \"verse\"\n | \"pre-chorus\"\n | \"chorus\"\n | \"bridge\"\n | \"break\"\n | \"silence\"\n | \"outro\"\n | \"none\";\n\nexport interface Segment {\n start: number;\n prompt: string;\n label?: SegmentLabel;\n}\n\n/** Monetary fields are strings, exactly as the backend serializes them. */\nexport interface CostInfo {\n billing_rate_per_sec: string;\n billing_before_discount: string;\n billing_after_discount: string;\n discount_factor: string;\n}\n\nexport interface AudioChunkEvent {\n type: \"audio_chunk\";\n /** Decoded from the wire's base64 by the SDK. */\n data: Uint8Array;\n}\n\nexport interface TitleEvent {\n type: \"title\";\n title: string;\n summary?: string;\n display_tags?: string[];\n [key: string]: unknown;\n}\n\nexport interface CompleteEvent {\n type: \"complete\";\n [key: string]: unknown;\n}\n\nexport interface ErrorEvent {\n type: \"error\";\n code?: string;\n message?: string;\n [key: string]: unknown;\n}\n\nexport interface CostEvent extends CostInfo {\n type: \"cost\";\n}\n\n/** Forward-compatibility: unrecognized event types are passed through. */\nexport interface UnknownEvent {\n type: string;\n [key: string]: unknown;\n}\n\nexport type StreamEvent =\n | AudioChunkEvent\n | TitleEvent\n | CompleteEvent\n | ErrorEvent\n | CostEvent\n | UnknownEvent;\n\nexport interface Track {\n audio: Uint8Array;\n title?: string;\n cost?: CostInfo;\n}\n\nexport interface TextToMusicParams {\n prompt: string;\n duration: number;\n segments?: Segment[];\n /** \"stream\" (default) or \"async\" (required by `submit()` and `output_format: \"wav\"`). */\n mode?: \"stream\" | \"async\";\n /** Container for the async result. `wav` requires `mode: \"async\"`. Defaults to m4a server-side. */\n outputFormat?: \"m4a\" | \"wav\";\n /** How many distinct music variants to generate in one request (1-10,\n * default 1). Cost scales linearly, and values above 1 are never covered\n * by the free trial. Values above 1 require `mode: \"async\"` — only\n * meaningful via `submit()`; `stream()`/`generate()` never send it, since\n * they always request a plain stream. */\n variantsNum?: number;\n /** Bounds the stream: aborting this cancels the in-flight generation.\n * Passed straight through to `fetch` — it is never rewrapped as\n * RequestTimeoutError, since the client's own absolute timeout does not\n * apply to streaming music generation. */\n signal?: AbortSignal;\n}\n\n/** string = file path (Node.js only). */\nexport type VideoInput =\n | File\n | Blob\n | Uint8Array\n | ArrayBuffer\n | ReadableStream<Uint8Array>\n | string;\n\nexport interface VideoToMusicParams {\n video?: VideoInput;\n videoUrl?: string;\n prompt?: string;\n segments?: Segment[];\n /** Bounds the stream: aborting this cancels the in-flight generation.\n * Passed straight through to `fetch` — it is never rewrapped as\n * RequestTimeoutError, since the client's own absolute timeout does not\n * apply to streaming music generation. Only meaningful for `stream()`/\n * `generate()`; `submit()` ignores it. */\n signal?: AbortSignal;\n /** \"stream\" (the default, used by `stream()`/`generate()`) or \"async\"\n * (required for `submit()`, and for `isolateVocals`). Only consulted by\n * `submit()` — `stream()`/`generate()` always request a stream. */\n mode?: \"stream\" | \"async\";\n /** Split the generated track into a vocals-only stem alongside the mix.\n * Requires `mode: \"async\"`; if `mode` is left unset it defaults to\n * \"async\" automatically. Only usable via `submit()` — the backend\n * rejects it on the plain stream. */\n isolateVocals?: boolean;\n /** Keep the source speech/vocals in the async result. Current name for\n * `isolateVocals`; both are accepted and OR'd server-side. Requires\n * `mode: \"async\"` (auto-selected by `submit()`). */\n preserveSpeech?: boolean;\n /** Container for the async result. `wav` requires async. Defaults to m4a. */\n outputFormat?: \"m4a\" | \"wav\";\n /** Duck the generated music under the source voice at finalize time.\n * Default-ON server-side in async mode: leave unset to keep it on, pass\n * `false` to opt out. Free, best-effort; only valid on `submit()`. */\n ducking?: boolean;\n /** How many distinct music variants to generate in one request (1-10,\n * default 1). Cost scales linearly, and values above 1 are never covered\n * by the free trial. Values above 1 require `mode: \"async\"` (auto-selected\n * by `submit()`) — only meaningful via `submit()`; `stream()`/`generate()`\n * never send it, since they always request a plain stream. */\n variantsNum?: number;\n}\n\n/** One service's free-trial allowance. `remaining` is already floored at 0,\n * so it is safe to compare directly. */\nexport interface TrialQuota {\n granted: number;\n used: number;\n remaining: number;\n}\n\nexport interface AccountServices {\n available_services: string[];\n rpm_limit: number;\n concurrency_limit: number;\n discount_factor: number | string;\n max_upload_size_mb: number | null;\n /** Free-trial allowance keyed by service (`granted` / `used` /\n * `remaining`). Present only for self-serve accounts — always treat it as\n * possibly absent, and treat a service missing from the map as \"no trial\n * allowance\", not as an error. */\n trial?: Record<string, TrialQuota>;\n}\n\nexport interface UsageSummary {\n total_requests: number;\n total_duration_seconds: number;\n total_cost: number | string;\n period_start: string;\n period_end: string;\n [key: string]: unknown;\n}\n\nexport interface DailyUsage {\n date: string;\n requests: number;\n duration_seconds: number;\n cost: number | string;\n}\n\nexport interface UsageResponse {\n summary: UsageSummary;\n daily: DailyUsage[];\n}\n\nexport function isAudioChunkEvent(event: StreamEvent): event is AudioChunkEvent {\n return event.type === \"audio_chunk\" && (event as AudioChunkEvent).data instanceof Uint8Array;\n}\n\nexport function isErrorEvent(event: StreamEvent): event is ErrorEvent {\n return event.type === \"error\";\n}\n\n/** SFX segments (unlike music `Segment`) require `end`, must start at 0,\n * and be contiguous; validated server-side. */\nexport interface SfxSegment {\n start: number;\n end: number;\n prompt: string;\n}\n\nexport type SfxAudioFormat = \"wav\" | \"mp3\" | \"aac\" | \"flac\";\n\n/** Submission ack for the async SFX endpoints. */\nexport interface SfxTask {\n task_id: string;\n status: string;\n}\n\n/** A generated file re-hosted on R2 behind a presigned URL. */\nexport interface SfxMedia {\n url: string;\n content_type?: string;\n file_size?: number;\n}\n\nexport interface SfxError {\n code?: string;\n message?: string;\n}\n\n/**\n * Common shape of any polled task (`tasks.get`/`tasks.wait`), regardless of\n * which endpoint created it. `Tasks.get`/`Tasks.wait` are generic over this so\n * each endpoint's result type (e.g. `SfxResult`, `MusicTaskResult`) can add\n * its own `audio`/media fields while sharing the status/error/refund\n * bookkeeping the poller relies on.\n */\nexport interface BaseTaskResult {\n task_id: string;\n type?: string;\n status: \"processing\" | \"succeeded\" | \"failed\" | (string & {});\n /** Only present when the account's task-field whitelist enables cost. */\n cost?: number;\n error?: SfxError;\n refunded?: boolean;\n /** Echoes the request's `variantsNum`. Present regardless of task status\n * (so a `processing`/`failed` poll explains the charge too), but only\n * when it was above 1 — a default (single-variant) request sees the same\n * shape it always has. */\n variants_num?: number;\n [key: string]: unknown;\n}\n\n/** State of an SFX task (`tasks.get`) or its final result (`wait`/`generate`). */\nexport interface SfxResult extends BaseTaskResult {\n audio?: SfxMedia;\n /** Kept for backward compatibility; no longer populated — video-to-sfx returns audio only. */\n video?: SfxMedia;\n}\n\nexport interface TextToSfxParams {\n prompt: string;\n duration: number;\n audioFormat?: SfxAudioFormat;\n}\n\nexport interface VideoToSfxParams {\n video?: VideoInput;\n videoUrl?: string;\n prompt?: string;\n segments?: SfxSegment[];\n audioFormat?: SfxAudioFormat;\n}\n\n/** One decoded audio stream of an async video-to-music result. Unlike SFX,\n * `audio` on a music task is always an array — even without `isolateVocals` —\n * since a music generation can carry more than one output stream. */\nexport interface MusicMediaEntry extends SfxMedia {\n stream_index: number;\n sample_rate?: number;\n channels?: number;\n /** This entry's own title, present when `variantsNum` was above 1 (and\n * titles are visible on the account). Each variant is a distinct creative\n * direction, so it can carry its own title rather than sharing the\n * top-level `MusicTaskResult.title`, which always names variant 0. */\n title?: MusicTitle;\n}\n\n/** One muxed audio+video-aligned output, present only when `isolateVocals`\n * is set. */\nexport interface MusicMuxEntry extends SfxMedia {\n stream_index: number;\n}\n\nexport interface MusicTitle {\n title: string;\n summary?: string;\n display_tags?: string[];\n}\n\n/** State of an async video-to-music task (`tasks.get`) or its final result\n * (`tasks.wait<MusicTaskResult>()`). Only reachable via `videoToMusic.submit()`\n * with `mode: \"async\"`. */\nexport interface MusicTaskResult extends BaseTaskResult {\n /** One entry per stream, or one entry per variant when `variantsNum` was\n * greater than 1 — each variant entry may carry its own `title`. */\n audio?: MusicMediaEntry[];\n /** Vocals-only stem; present only when `isolateVocals` was requested. */\n vocals?: SfxMedia;\n /** Muxed output per stream (or per variant); present only when\n * `isolateVocals` was requested. */\n mux?: MusicMuxEntry[];\n /** Music ducked under the source voice (per variant when `variantsNum` is\n * above 1); present only when `ducking` ran. */\n ducked?: MusicMediaEntry[];\n /** Variant 0's title — the top-level field always names the first variant,\n * even when `variantsNum` produced others with their own titles on\n * `audio[]`. */\n title?: MusicTitle;\n duration_seconds?: number;\n}\n\nexport interface WaitOptions {\n /** Milliseconds between polls. Default 2000. */\n pollInterval?: number;\n /** Overall deadline in milliseconds. Default 600000. */\n timeout?: number;\n}\n\n/** Result of an async video-to-video task (`videoToVideoMusic`/`videoToVideoSfx`):\n * a re-hosted video with generated music or SFX muxed in. */\nexport interface VideoResult extends BaseTaskResult {\n /** One re-hosted video per variant. On `videoToVideoMusic` this is\n * populated even at the default `variantsNum` of 1 (as a single-entry\n * array); `videoToVideoSfx` has no variants knob and always sends one. */\n videos?: SfxMedia[];\n /** Permanent alias for `videos[0]`. */\n video?: SfxMedia;\n duration_seconds?: number;\n}\n\nexport interface VideoToVideoMusicParams {\n video?: VideoInput;\n videoUrl?: string;\n prompt?: string;\n /** Keep the source speech/vocals in the output. Both this and the legacy\n * `isolateVocals` are accepted and OR'd server-side. */\n preserveSpeech?: boolean;\n /** @deprecated Legacy alias for `preserveSpeech`. */\n isolateVocals?: boolean;\n /** How many distinct music variants to generate in one request (1-10,\n * default 1). Cost scales linearly, and values above 1 are never covered\n * by the free trial. This endpoint is always async, so no extra `mode`\n * gating applies. The result's `videos[]` gets one entry per variant. */\n variantsNum?: number;\n}\n\nexport interface VideoToVideoSfxParams {\n video?: VideoInput;\n videoUrl?: string;\n prompt?: string;\n segments?: SfxSegment[];\n}\n\n/** Params for `videoToSound` and `videoToVideoSound`. Both endpoints take the\n * identical form, so they share one params type. */\nexport interface VideoToSoundParams {\n video?: VideoInput;\n videoUrl?: string;\n /** Style hint for the generated music bed. */\n musicPrompt?: string;\n /** Description of the sound effects layered over the music. */\n sfxPrompt?: string;\n /** Per-segment SFX descriptions; must start at 0 and be contiguous. */\n segments?: SfxSegment[];\n /** Keep the source speech in the result. */\n preserveSpeech?: boolean;\n /** Duck the generated music under the source speech. Default-ON\n * server-side: leave unset to keep it on, pass `false` to opt out. */\n ducking?: boolean;\n /** How many distinct variants to generate in one request (1-10, default\n * 1). Cost scales linearly, and values above 1 are never covered by the\n * free trial. Both `videoToSound` and `videoToVideoSound` are always\n * async, so no extra `mode` gating applies. The result's `outputs[]` gets\n * one entry per variant. */\n variantsNum?: number;\n}\n\n/** One variant's outputs on a `videoToSound` / `videoToVideoSound` result.\n * Present even at the default `variantsNum` of 1, as a single-entry array. */\nexport interface SoundOutputEntry {\n variant_index: number;\n output_url: string;\n output_type: \"audio\" | \"video\";\n output_bytes: number;\n music?: SfxMedia;\n /** Present only when `preserveSpeech`/`ducking` altered this variant's music bed. */\n music_processed?: SfxMedia;\n sfx?: SfxMedia;\n}\n\n/** Result of a `videoToSound` / `videoToVideoSound` task (`tasks.get`) or its\n * final state (`generate`).\n *\n * The combined music+SFX result is `output_url` — a bare presigned URL rather\n * than a media object, since these endpoints render one artifact whose kind is\n * announced by `output_type` (\"audio\" for video-to-sound, \"video\" for\n * video-to-video-sound). `music`, `music_processed` and `sfx` are the\n * individual stems; pass any of them, or `output_url` itself, to `download()`.\n *\n * `outputs` carries the same fields per variant when `variantsNum` was\n * greater than 1; `output_url`/`output_type`/`output_bytes`/`music`/\n * `music_processed`/`sfx` remain permanent aliases for `outputs[0]`. */\nexport interface SoundResult extends BaseTaskResult {\n output_url?: string;\n output_type?: \"audio\" | \"video\";\n output_bytes?: number;\n music?: SfxMedia;\n /** Present only when `preserveSpeech`/`ducking` altered the music bed. */\n music_processed?: SfxMedia;\n sfx?: SfxMedia;\n duration_seconds?: number;\n /** One entry per variant; see `SoundOutputEntry`. */\n outputs?: SoundOutputEntry[];\n}\n\n/**\n * A target language for /v1/dubbing. The union stays open (`string & {}`) so a\n * language added server-side still type-checks against an older SDK — the\n * backend, not this list, is the authority on what is supported.\n */\nexport type DubbingLanguage =\n | \"en\"\n | \"zh_cn\"\n | \"ja\"\n | \"ko\"\n | \"pt\"\n | \"es\"\n | \"de\"\n | \"fr\"\n | \"it\"\n | \"ru\"\n | (string & {});\n\nexport interface DubbingParams {\n /** Exactly one of `video` / `videoUrl`. */\n video?: VideoInput;\n /**\n * Exactly one of `video` / `videoUrl`. Must be an `https://` URL — the\n * dubbing pipeline fetches the source itself and rejects plain http.\n */\n videoUrl?: string;\n /** Omit to get the server default, `[\"zh_cn\", \"es\", \"fr\"]`. */\n languages?: DubbingLanguage[];\n /**\n * Duck the background music/effects bed under the dubbed voice. Default\n * OFF server-side (the opposite of video-to-music's `ducking`): the bed\n * is always kept, at a constant level unless this is `true`. Free.\n */\n ducking?: boolean;\n}\n\nexport interface DubbingResult extends BaseTaskResult {\n /**\n * One dubbed video URL per requested language, keyed by language code.\n * Unlike every other endpoint's envelope this is a map, not an `audio`/\n * `video` slot — a dubbing task renders N artifacts, one per language.\n */\n outputs?: Record<string, string>;\n}\n"],"mappings":"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","names":[]}
|