sonilo 0.16.0 → 0.16.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -376,7 +376,7 @@ boolean (default off, free) ducks the background music/effects bed under the
|
|
|
376
376
|
dubbed voice while it speaks; when off the bed is kept at a constant level.
|
|
377
377
|
Every endpoint's `ducking` is default-off, so this one is no exception.
|
|
378
378
|
|
|
379
|
-
Dubbing is async-only, and the source video may be at most
|
|
379
|
+
Dubbing is async-only, and the source video may be at most 300 seconds long.
|
|
380
380
|
You are billed per language. Dubbing has **no free trial allowance** — unlike
|
|
381
381
|
every other endpoint, every call bills from the first one (see
|
|
382
382
|
[Free trial](#free-trial)).
|
package/dist/index.cjs
CHANGED
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/audioDucking.ts","../src/resources/dubbing.ts","../src/resources/videoAnalysis.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 AnalysisSegment,\n AnalysisVariation,\n AudioChunkEvent,\n AudioDuckingParams,\n BaseTaskResult,\n CompleteEvent,\n CostEvent,\n CostInfo,\n DailyUsage,\n DubbingLanguage,\n DubbingParams,\n DubbingResult,\n DuckingResult,\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 StemsEntry,\n StreamEvent,\n TextToMusicParams,\n TextToSfxParams,\n TitleEvent,\n Track,\n TrialQuota,\n UnknownEvent,\n UsageResponse,\n UsageSummary,\n VideoAnalysisParams,\n VideoAnalysisResult,\n VideoInput,\n VideoResult,\n VideoToMusicParams,\n VideoToSfxParams,\n VideoToSoundParams,\n VideoToVideoSoundParams,\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 * a non-m4a `outputFormat`, `variantsNum` above 1, and `stems`.\n * `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 if (params.variantsNum !== undefined) {\n form.set(\"variants_num\", String(params.variantsNum));\n }\n if (params.stems !== undefined) {\n form.set(\"stems\", String(params.stems));\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 // A generation-time knob, valid on the plain stream as well as async —\n // unlike the finalize-time params, which submit() alone sends. The\n // explicit undefined check matters: 0 is a meaningful value.\n if (params.promptInfluence !== undefined) {\n form.set(\"prompt_influence\", String(params.promptInfluence));\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`, a non-m4a `outputFormat`,\n * `variantsNum` above 1, and `stems` — the backend rejects all of these on\n * the plain 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 // Any non-m4a container is a finalize-time transcode, so it needs\n // async. Checking != \"m4a\" rather than == \"wav\" keeps this correct\n // as formats are added (mp3 landed after the original check).\n (params.outputFormat !== undefined && params.outputFormat !== \"m4a\") ||\n (params.variantsNum !== undefined && params.variantsNum > 1) ||\n params.stems !== undefined;\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/stems/outputFormat other than \"m4a\"/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 if (params.stems !== undefined) {\n form.set(\"stems\", String(params.stems));\n }\n // Explicit undefined check: 0 is a meaningful value and must go out.\n if (params.promptInfluence !== undefined) {\n form.set(\"prompt_influence\", String(params.promptInfluence));\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.segments !== undefined) {\n form.set(\"segments\", JSON.stringify(params.segments));\n }\n // Omitted when unset rather than sent with a default, so the server's own\n // default decides — `ducking` and `keepOriginalSound` are both default-OFF\n // server-side today, and neither is hardcoded here (same rule as\n // buildSoundForm's).\n if (params.keepOriginalSound !== undefined) {\n form.set(\"keep_original_sound\", String(params.keepOriginalSound));\n }\n if (params.ducking !== undefined) form.set(\"ducking\", String(params.ducking));\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 // Explicit undefined check: 0 is a meaningful value and must go out.\n if (params.promptInfluence !== undefined) {\n form.set(\"prompt_influence\", String(params.promptInfluence));\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, VideoToVideoSoundParams } from \"../types.js\";\n\n/** The widest shape either endpoint can send. Neither public param type can\n * serve as the parameter here, because the two now differ in opposite\n * directions: `outputFormat` exists only on `VideoToSoundParams` (audio),\n * while `keepOriginalSound` is video-only and is therefore typed `never` on\n * `VideoToSoundParams`. That makes each public type unassignable to the other,\n * so the shared builder takes their union and each endpoint's own param type\n * stays the thing that rejects the wrong field at compile time. */\ntype SoundFormParams = VideoToVideoSoundParams & Pick<VideoToSoundParams, \"outputFormat\">;\n\n/** Build the multipart body shared by /v1/video-to-sound and\n * /v1/video-to-video-sound. The two differ only in the path they POST to and\n * in the two endpoint-specific fields described on `SoundFormParams`.\n *\n * Every optional field is omitted when unset rather than sent with a default,\n * so the server's own default decides. `ducking` and `keepOriginalSound` are\n * both default-OFF server-side today, but neither is hardcoded here — pinning\n * either one on the wire is what would have to change the next time a server\n * default moves, and this builder deliberately does not. */\nexport async function buildSoundForm(params: SoundFormParams): 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.keepOriginalSound !== undefined) {\n form.set(\"keep_original_sound\", String(params.keepOriginalSound));\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.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 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 {\n SfxTask,\n SoundResult,\n VideoToVideoSoundParams,\n WaitOptions,\n} 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: VideoToVideoSoundParams): 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: VideoToVideoSoundParams, 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 { AudioDuckingParams, DuckingResult, SfxTask, WaitOptions } from \"../types.js\";\n\n/** Duck an existing music bed under a voice track. Async only (202 + poll).\n *\n * Both inputs are user-supplied — nothing is generated here. The voice may be\n * audio OR a video: the backend extracts a video's audio track, ducks the\n * music under it, and re-muxes the ducked mix back into a new video (the\n * result's `output_type` announces which came back). The music must be audio —\n * the backend never probes it for a video stream, so a video there would be\n * silently mishandled. */\nexport class AudioDucking {\n constructor(private readonly client: SoniloClient) {}\n\n async submit(params: AudioDuckingParams): Promise<SfxTask> {\n // Both pairs are validated before any upload I/O, so a missing music\n // input is reported even when the voice side alone looks fine.\n if ((params.voice === undefined) === (params.voiceUrl === undefined)) {\n throw new SoniloError(\"Provide exactly one of voice or voiceUrl\");\n }\n if ((params.music === undefined) === (params.musicUrl === undefined)) {\n throw new SoniloError(\"Provide exactly one of music or musicUrl\");\n }\n const form = new FormData();\n if (params.voice !== undefined) {\n const { blob, filename } = await toUploadBlob(params.voice);\n form.set(\"voice_file\", blob, filename);\n } else {\n form.set(\"voice_url\", params.voiceUrl as string);\n }\n if (params.music !== undefined) {\n const { blob, filename } = await toUploadBlob(params.music);\n form.set(\"music_file\", blob, filename);\n } else {\n form.set(\"music_url\", params.musicUrl as string);\n }\n const res = await this.client.request(\"/v1/audio-ducking\", {\n method: \"POST\",\n body: form,\n });\n return (await res.json()) as SfxTask;\n }\n\n async generate(params: AudioDuckingParams, opts?: WaitOptions): Promise<DuckingResult> {\n const task = await this.submit(params);\n return this.client.tasks.wait<DuckingResult>(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","import type { SoniloClient } from \"../client.js\";\nimport { SoniloError } from \"../errors.js\";\nimport { toUploadBlob } from \"../upload.js\";\nimport type {\n SfxTask,\n VideoAnalysisParams,\n VideoAnalysisResult,\n WaitOptions,\n} from \"../types.js\";\n\n/** Analyze a video and get back a creative brief for scoring it. Async only.\n *\n * This endpoint generates nothing — no audio, no video, no artifact to\n * download. The result is the work order: `segments` (a time-aligned section\n * plan) plus one `prompt` per requested variation, each ready to hand\n * straight to videoToMusic, videoToSfx, videoToSound or their\n * video-to-video counterparts.\n *\n * The method is `analyze`, not `generate`, for that reason: every other\n * resource's `generate` returns something you download, and this one never\n * does.\n *\n * The 1-5 bound on `variantsNum` and the 2000-character bound on `prompt`\n * are deliberately not checked here — the backend owns them, and a hardcoded\n * copy would make this SDK reject values a later API widens. */\nexport class VideoAnalysis {\n constructor(private readonly client: SoniloClient) {}\n\n async submit(params: VideoAnalysisParams): 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.variantsNum !== undefined) {\n form.set(\"variants_num\", String(params.variantsNum));\n }\n const res = await this.client.request(\"/v1/video-analysis\", {\n method: \"POST\",\n body: form,\n });\n return (await res.json()) as SfxTask;\n }\n\n async analyze(\n params: VideoAnalysisParams,\n opts?: WaitOptions,\n ): Promise<VideoAnalysisResult> {\n const task = await this.submit(params);\n return this.client.tasks.wait<VideoAnalysisResult>(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.16.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 { AudioDucking } from \"./resources/audioDucking.js\";\nimport { Dubbing } from \"./resources/dubbing.js\";\nimport { VideoAnalysis } from \"./resources/videoAnalysis.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 audioDucking: AudioDucking;\n readonly dubbing: Dubbing;\n readonly videoAnalysis: VideoAnalysis;\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.audioDucking = new AudioDucking(this);\n this.dubbing = new Dubbing(this);\n this.videoAnalysis = new VideoAnalysis(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 by any\n * `outputFormat` other than the m4a default). */\n mode?: \"stream\" | \"async\";\n /** Container for the async result. `wav` and `mp3` (320 kbps) are\n * finalize-time transcodes and require `mode: \"async\"`; m4a is what the\n * stream itself carries. Defaults to m4a server-side. */\n outputFormat?: \"m4a\" | \"wav\" | \"mp3\";\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 /** Also split the generated track into four separated stems — `drums`,\n * `bass`, `vocals`, `other` — delivered on the task result's `stems`\n * array. Free of charge. Requires `mode: \"async\"` (the backend rejects it\n * on the plain stream with a 400), so it is only meaningful via\n * `submit()`; `stream()`/`generate()` never send it. Separation runs after\n * generation and typically adds 2-6 minutes to the wait (it gives up after\n * 30), so raise `tasks.wait`'s `timeout` accordingly. See `StemsEntry` for\n * the result shape, and `MusicTaskResult.stems_error` for how failures are\n * reported. */\n stems?: boolean;\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` and `mp3` (320 kbps) are\n * finalize-time transcodes and require async. Defaults to m4a. */\n outputFormat?: \"m4a\" | \"wav\" | \"mp3\";\n /** Duck the generated music under the source voice at finalize time.\n * Default-OFF server-side: leave unset to skip it, pass `true` to run it,\n * which adds a `ducked` track alongside the unchanged clean `audio`. Free,\n * 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 /** How strongly the generated music follows the prompt (0-1, API default\n * 0.5). Lower values let the video lead; higher values follow the prompt\n * more literally. Free of charge. A generation-time knob, not a\n * finalize-time one, so it works on the plain stream as well as async —\n * no `mode` gating. Omitted from the wire when unset so the server\n * default applies; `0` is a meaningful value and is sent. Out-of-range\n * values are rejected server-side with a 422. */\n promptInfluence?: number;\n /** Also split the generated music into four separated stems — `drums`,\n * `bass`, `vocals`, `other` — delivered on the task result's `stems`\n * array. It splits the GENERATED music, never the source video's own\n * audio. Free of charge. Requires `mode: \"async\"` (auto-selected by\n * `submit()`; the backend rejects it on the plain stream with a 400), so\n * it is only meaningful via `submit()` — `stream()`/`generate()` never\n * send it. Separation runs after generation and typically adds 2-6\n * minutes to the wait (it gives up after 30), so raise `tasks.wait`'s\n * `timeout` accordingly. See `StemsEntry` for the result shape, and\n * `MusicTaskResult.stems_error` for how failures are reported. */\n stems?: 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 /** 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/** The four separated stems of one generated stream, present when the\n * request set `stems: true`. Each stem is an ordinary media object\n * (`url` / `content_type` / `file_size`), so any of them can be passed to\n * `download()`. The stems normally follow the request's `outputFormat`;\n * each stem's own `content_type` reports what was actually delivered. */\nexport interface StemsEntry {\n /** Which `audio` entry this stems set belongs to. Match on this field,\n * never on array position — `stems` carries only the streams that\n * separated successfully, so it can be shorter than `audio`. */\n stream_index: number;\n drums: SfxMedia;\n bass: SfxMedia;\n vocals: SfxMedia;\n other: SfxMedia;\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 /** Separated stems, one entry per stream that separated successfully;\n * only appears when the request set `stems: true`. Look entries up by\n * `stream_index`, never by array position — the array can be shorter than\n * `audio` when separation failed for some streams (see `stems_error`). */\n stems?: StemsEntry[];\n /** Why stem separation failed wholly or in part, or was skipped. It can\n * appear ALONGSIDE a partial `stems` array, so never treat its presence as\n * \"no stems\" — check `stems` itself for what did arrive. Independent of\n * the task's own `status`/`error`: the generation is intact either way. */\n stems_error?: string;\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\n/** Params for `videoToVideoMusic`.\n *\n * The delivered video's audio is decided by two independent knobs:\n * `keepOriginalSound` picks the **voice source**, `ducking` picks how that\n * voice and the generated music are **combined**.\n *\n * | Request | Audio in the returned video |\n * | --- | --- |\n * | neither set | generated music only — the source's own audio is removed |\n * | `keepOriginalSound: true` | full original sound + static music mix |\n * | `keepOriginalSound: true, ducking: true` | full original sound + music ducked under it |\n * | `preserveSpeech: true` | static vocal-forward mix of vocals + music |\n * | `preserveSpeech: true, ducking: true` | isolated vocals + music ducked under them |\n *\n * `keepOriginalSound` supersedes `preserveSpeech` — the voice source is a\n * single choice, and keeping the whole track subsumes keeping only the\n * isolated speech. No combination is rejected.\n *\n * The source picture is copied without re-encoding, so the input must carry\n * H.264, H.265/HEVC, VP9 or AV1 video in an mp4, mov, m4v or webm container —\n * animated gif and VP8 webm are rejected. Maximum input duration is 360\n * seconds. */\nexport interface VideoToVideoMusicParams {\n video?: VideoInput;\n videoUrl?: string;\n prompt?: string;\n /** How the music should develop over time. Same shape as\n * `videoToMusic`'s: the first `start` must be 0. Supplying these skips the\n * prompt-service plan the server would otherwise derive from `prompt`. */\n segments?: Segment[];\n /** Keep the source video's whole original audio track in the result, with\n * the generated music combined under it. Defaults to `false`, so by\n * default the returned video's audio is the generated music ALONE and the\n * source's own audio is removed. Supersedes `preserveSpeech`. */\n keepOriginalSound?: boolean;\n /** How the voice and the generated music are combined — not whether a\n * voice is kept. Default-OFF server-side: leave unset for a static\n * voice-forward mix at a fixed offset, pass `true` for the dynamic duck\n * (music dips only while the voice is present). Has no effect when there\n * is no voice source, i.e. neither `keepOriginalSound` nor `preserveSpeech`\n * is set. Free and best-effort; silently falls back to\n * generated-audio-only if the source has no usable audio track, voice\n * isolation fails, or the mix fails. */\n ducking?: boolean;\n /** Keep only the source's isolated speech (not the whole track) in the\n * output. Both this and the legacy `isolateVocals` are accepted and OR'd\n * server-side. Superseded by `keepOriginalSound`. */\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 /** How strongly the generated music follows the prompt (0-1, API default\n * 0.5). Lower values let the video lead; higher values follow the prompt\n * more literally. Free of charge. Omitted from the wire when unset so the\n * server default applies; `0` is a meaningful value and is sent.\n * Out-of-range values are rejected server-side with a 422. */\n promptInfluence?: number;\n}\n\nexport interface VideoToVideoSfxParams {\n video?: VideoInput;\n videoUrl?: string;\n prompt?: string;\n segments?: SfxSegment[];\n}\n\n/** Params for `videoToVideoSound`, and the base every `videoToSound` param\n * also has. The two endpoints differ in exactly two fields, one in each\n * direction, and both are enforced at the type level rather than left to the\n * server to silently ignore:\n *\n * - `outputFormat` is **audio-only** — added by `VideoToSoundParams` below, so\n * it simply does not exist on this type.\n * - `keepOriginalSound` is **video-only** — declared here, so\n * `VideoToSoundParams` inherits it and has to forbid it explicitly with\n * `?: never` (the inheritance runs the other way, so it cannot just be\n * omitted the way `outputFormat` is).\n *\n * Passing either field to the wrong endpoint is therefore a compile error. */\nexport interface VideoToVideoSoundParams {\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 video's whole original audio track in the result, with\n * the generated music + SFX combined under it. Defaults to `false`, so by\n * default the returned video's audio is the generated music and sound\n * effects ALONE and the source's own audio is removed — and the result\n * carries no `music_processed` stem, since with no voice source there is no\n * processed track. Supersedes `preserveSpeech`. Video endpoint only. */\n keepOriginalSound?: boolean;\n /** Keep only the source's isolated speech (not the whole track) in the\n * result. Superseded by `keepOriginalSound`. */\n preserveSpeech?: boolean;\n /** On `videoToVideoSound`, how the voice and the generated bed are\n * combined — not whether a voice is kept: default-OFF server-side, so an\n * unset value gives a static voice-forward mix and `true` gives the dynamic\n * duck, and either way it has no effect without a voice source.\n *\n * On `videoToSound` it decides BOTH, because that endpoint has no\n * `keepOriginalSound`: unset means the source's own speech is left out of\n * the deliverable entirely, and `true` is what pulls the original track in\n * and ducks the bed under it. Pass `preserveSpeech` instead to bring in the\n * isolated vocals rather than the whole track. */\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/** Params for `videoToSound`. Everything `videoToVideoSound` takes, plus the\n * delivery container for the combined track. */\nexport interface VideoToSoundParams extends VideoToVideoSoundParams {\n /** Container for the combined music + SFX track. Defaults to `wav`;\n * `mp3` is 320 kbps. Applies to the combined output only — the `music`\n * and `sfx` stems keep their native formats. Not available on\n * `videoToVideoSound`, which always returns an mp4. */\n outputFormat?: \"wav\" | \"m4a\" | \"mp3\";\n /** Not available on this endpoint. `keepOriginalSound` only means something\n * when the deliverable is a video whose own audio could be preserved;\n * `videoToSound` returns generated audio, and reaches the original track\n * through `ducking: true` instead. Typed `never` so passing it is a compile\n * error rather than a field the server silently drops — the mirror of how\n * `outputFormat` is kept off `videoToVideoSound`. */\n keepOriginalSound?: never;\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/** Params for `audioDucking`: mix an existing music bed under an existing\n * voice track, ducking the music wherever the voice speaks. Exactly one of\n * `voice`/`voiceUrl` and exactly one of `music`/`musicUrl`; a local input and\n * a URL may be mixed across the two.\n *\n * The voice may be audio or video (`VideoInput` is the SDK's generic media\n * input union) — a video's own audio track becomes the voice, and the ducked\n * mix is re-muxed back into a new video. The music must be audio: the backend\n * never probes it for a video stream, so a video there would be silently\n * mishandled. Each input is capped at 360 seconds server-side. */\nexport interface AudioDuckingParams {\n voice?: VideoInput;\n voiceUrl?: string;\n music?: VideoInput;\n musicUrl?: string;\n}\n\n/** Result of an `audioDucking` task (`tasks.get`) or its final state\n * (`generate`). Same flat envelope as `SoundResult`, but a ducking task\n * renders exactly one artifact and no stems: a `.wav` (`output_type`\n * \"audio\"), or a `.mp4` with the ducked mix re-muxed in (`output_type`\n * \"video\") when the voice input was a video. Pass `output_url` to\n * `download()`. */\nexport interface DuckingResult extends BaseTaskResult {\n output_url?: string;\n output_type?: \"audio\" | \"video\";\n output_bytes?: number;\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 * Duck the background music/effects bed under the dubbed voice. Default\n * OFF server-side, like every other endpoint's `ducking`: the bed is\n * 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\nexport interface VideoAnalysisParams {\n /** Exactly one of `video` / `videoUrl`. */\n video?: VideoInput;\n /** Exactly one of `video` / `videoUrl`. */\n videoUrl?: string;\n /** Optional guidance for the analysis, at most 2000 characters. */\n prompt?: string;\n /**\n * How many independent creative briefs to author for the same video\n * (1-5, default 1). Billed per brief.\n */\n variantsNum?: number;\n}\n\n/** One time-aligned section of the analyzed video, with the scoring\n * direction for that stretch. Bounds are whole seconds — the backend\n * truncates any fractional upstream bound before it reaches the envelope. */\nexport interface AnalysisSegment {\n start: number;\n end: number;\n /** The backend always emits one, defaulting to the string `\"none\"`. */\n label: string;\n prompt: string;\n}\n\n/** One independent creative brief for the whole video. Only the generation\n * prompt is public — the upstream's title/summary/tags are internal display\n * copy the API deliberately does not resell. */\nexport interface AnalysisVariation {\n prompt: string;\n}\n\n/**\n * The only Sonilo result with no media artifact at all: video-analysis\n * generates nothing and there is nothing to download. The payload is the\n * work order — `segments` for a time-aligned plan, and one `prompt` per\n * requested variation, each ready to pass to videoToMusic, videoToSfx,\n * videoToSound or their video-to-video counterparts.\n *\n * Both lists are optional because a `processing` or `failed` poll carries\n * neither.\n */\nexport interface VideoAnalysisResult extends BaseTaskResult {\n segments?: AnalysisSegment[];\n variations?: AnalysisVariation[];\n duration_seconds?: number;\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/audioDucking.ts","../src/resources/dubbing.ts","../src/resources/videoAnalysis.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 AnalysisSegment,\n AnalysisVariation,\n AudioChunkEvent,\n AudioDuckingParams,\n BaseTaskResult,\n CompleteEvent,\n CostEvent,\n CostInfo,\n DailyUsage,\n DubbingLanguage,\n DubbingParams,\n DubbingResult,\n DuckingResult,\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 StemsEntry,\n StreamEvent,\n TextToMusicParams,\n TextToSfxParams,\n TitleEvent,\n Track,\n TrialQuota,\n UnknownEvent,\n UsageResponse,\n UsageSummary,\n VideoAnalysisParams,\n VideoAnalysisResult,\n VideoInput,\n VideoResult,\n VideoToMusicParams,\n VideoToSfxParams,\n VideoToSoundParams,\n VideoToVideoSoundParams,\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 * a non-m4a `outputFormat`, `variantsNum` above 1, and `stems`.\n * `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 if (params.variantsNum !== undefined) {\n form.set(\"variants_num\", String(params.variantsNum));\n }\n if (params.stems !== undefined) {\n form.set(\"stems\", String(params.stems));\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 // A generation-time knob, valid on the plain stream as well as async —\n // unlike the finalize-time params, which submit() alone sends. The\n // explicit undefined check matters: 0 is a meaningful value.\n if (params.promptInfluence !== undefined) {\n form.set(\"prompt_influence\", String(params.promptInfluence));\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`, a non-m4a `outputFormat`,\n * `variantsNum` above 1, and `stems` — the backend rejects all of these on\n * the plain 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 // Any non-m4a container is a finalize-time transcode, so it needs\n // async. Checking != \"m4a\" rather than == \"wav\" keeps this correct\n // as formats are added (mp3 landed after the original check).\n (params.outputFormat !== undefined && params.outputFormat !== \"m4a\") ||\n (params.variantsNum !== undefined && params.variantsNum > 1) ||\n params.stems !== undefined;\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/stems/outputFormat other than \"m4a\"/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 if (params.stems !== undefined) {\n form.set(\"stems\", String(params.stems));\n }\n // Explicit undefined check: 0 is a meaningful value and must go out.\n if (params.promptInfluence !== undefined) {\n form.set(\"prompt_influence\", String(params.promptInfluence));\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.segments !== undefined) {\n form.set(\"segments\", JSON.stringify(params.segments));\n }\n // Omitted when unset rather than sent with a default, so the server's own\n // default decides — `ducking` and `keepOriginalSound` are both default-OFF\n // server-side today, and neither is hardcoded here (same rule as\n // buildSoundForm's).\n if (params.keepOriginalSound !== undefined) {\n form.set(\"keep_original_sound\", String(params.keepOriginalSound));\n }\n if (params.ducking !== undefined) form.set(\"ducking\", String(params.ducking));\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 // Explicit undefined check: 0 is a meaningful value and must go out.\n if (params.promptInfluence !== undefined) {\n form.set(\"prompt_influence\", String(params.promptInfluence));\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, VideoToVideoSoundParams } from \"../types.js\";\n\n/** The widest shape either endpoint can send. Neither public param type can\n * serve as the parameter here, because the two now differ in opposite\n * directions: `outputFormat` exists only on `VideoToSoundParams` (audio),\n * while `keepOriginalSound` is video-only and is therefore typed `never` on\n * `VideoToSoundParams`. That makes each public type unassignable to the other,\n * so the shared builder takes their union and each endpoint's own param type\n * stays the thing that rejects the wrong field at compile time. */\ntype SoundFormParams = VideoToVideoSoundParams & Pick<VideoToSoundParams, \"outputFormat\">;\n\n/** Build the multipart body shared by /v1/video-to-sound and\n * /v1/video-to-video-sound. The two differ only in the path they POST to and\n * in the two endpoint-specific fields described on `SoundFormParams`.\n *\n * Every optional field is omitted when unset rather than sent with a default,\n * so the server's own default decides. `ducking` and `keepOriginalSound` are\n * both default-OFF server-side today, but neither is hardcoded here — pinning\n * either one on the wire is what would have to change the next time a server\n * default moves, and this builder deliberately does not. */\nexport async function buildSoundForm(params: SoundFormParams): 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.keepOriginalSound !== undefined) {\n form.set(\"keep_original_sound\", String(params.keepOriginalSound));\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.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 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 {\n SfxTask,\n SoundResult,\n VideoToVideoSoundParams,\n WaitOptions,\n} 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: VideoToVideoSoundParams): 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: VideoToVideoSoundParams, 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 { AudioDuckingParams, DuckingResult, SfxTask, WaitOptions } from \"../types.js\";\n\n/** Duck an existing music bed under a voice track. Async only (202 + poll).\n *\n * Both inputs are user-supplied — nothing is generated here. The voice may be\n * audio OR a video: the backend extracts a video's audio track, ducks the\n * music under it, and re-muxes the ducked mix back into a new video (the\n * result's `output_type` announces which came back). The music must be audio —\n * the backend never probes it for a video stream, so a video there would be\n * silently mishandled. */\nexport class AudioDucking {\n constructor(private readonly client: SoniloClient) {}\n\n async submit(params: AudioDuckingParams): Promise<SfxTask> {\n // Both pairs are validated before any upload I/O, so a missing music\n // input is reported even when the voice side alone looks fine.\n if ((params.voice === undefined) === (params.voiceUrl === undefined)) {\n throw new SoniloError(\"Provide exactly one of voice or voiceUrl\");\n }\n if ((params.music === undefined) === (params.musicUrl === undefined)) {\n throw new SoniloError(\"Provide exactly one of music or musicUrl\");\n }\n const form = new FormData();\n if (params.voice !== undefined) {\n const { blob, filename } = await toUploadBlob(params.voice);\n form.set(\"voice_file\", blob, filename);\n } else {\n form.set(\"voice_url\", params.voiceUrl as string);\n }\n if (params.music !== undefined) {\n const { blob, filename } = await toUploadBlob(params.music);\n form.set(\"music_file\", blob, filename);\n } else {\n form.set(\"music_url\", params.musicUrl as string);\n }\n const res = await this.client.request(\"/v1/audio-ducking\", {\n method: \"POST\",\n body: form,\n });\n return (await res.json()) as SfxTask;\n }\n\n async generate(params: AudioDuckingParams, opts?: WaitOptions): Promise<DuckingResult> {\n const task = await this.submit(params);\n return this.client.tasks.wait<DuckingResult>(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","import type { SoniloClient } from \"../client.js\";\nimport { SoniloError } from \"../errors.js\";\nimport { toUploadBlob } from \"../upload.js\";\nimport type {\n SfxTask,\n VideoAnalysisParams,\n VideoAnalysisResult,\n WaitOptions,\n} from \"../types.js\";\n\n/** Analyze a video and get back a creative brief for scoring it. Async only.\n *\n * This endpoint generates nothing — no audio, no video, no artifact to\n * download. The result is the work order: `segments` (a time-aligned section\n * plan) plus one `prompt` per requested variation, each ready to hand\n * straight to videoToMusic, videoToSfx, videoToSound or their\n * video-to-video counterparts.\n *\n * The method is `analyze`, not `generate`, for that reason: every other\n * resource's `generate` returns something you download, and this one never\n * does.\n *\n * The 1-5 bound on `variantsNum` and the 2000-character bound on `prompt`\n * are deliberately not checked here — the backend owns them, and a hardcoded\n * copy would make this SDK reject values a later API widens. */\nexport class VideoAnalysis {\n constructor(private readonly client: SoniloClient) {}\n\n async submit(params: VideoAnalysisParams): 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.variantsNum !== undefined) {\n form.set(\"variants_num\", String(params.variantsNum));\n }\n const res = await this.client.request(\"/v1/video-analysis\", {\n method: \"POST\",\n body: form,\n });\n return (await res.json()) as SfxTask;\n }\n\n async analyze(\n params: VideoAnalysisParams,\n opts?: WaitOptions,\n ): Promise<VideoAnalysisResult> {\n const task = await this.submit(params);\n return this.client.tasks.wait<VideoAnalysisResult>(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.16.1\";\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 { AudioDucking } from \"./resources/audioDucking.js\";\nimport { Dubbing } from \"./resources/dubbing.js\";\nimport { VideoAnalysis } from \"./resources/videoAnalysis.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 audioDucking: AudioDucking;\n readonly dubbing: Dubbing;\n readonly videoAnalysis: VideoAnalysis;\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.audioDucking = new AudioDucking(this);\n this.dubbing = new Dubbing(this);\n this.videoAnalysis = new VideoAnalysis(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 by any\n * `outputFormat` other than the m4a default). */\n mode?: \"stream\" | \"async\";\n /** Container for the async result. `wav` and `mp3` (320 kbps) are\n * finalize-time transcodes and require `mode: \"async\"`; m4a is what the\n * stream itself carries. Defaults to m4a server-side. */\n outputFormat?: \"m4a\" | \"wav\" | \"mp3\";\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 /** Also split the generated track into four separated stems — `drums`,\n * `bass`, `vocals`, `other` — delivered on the task result's `stems`\n * array. Free of charge. Requires `mode: \"async\"` (the backend rejects it\n * on the plain stream with a 400), so it is only meaningful via\n * `submit()`; `stream()`/`generate()` never send it. Separation runs after\n * generation and typically adds 2-6 minutes to the wait (it gives up after\n * 30), so raise `tasks.wait`'s `timeout` accordingly. See `StemsEntry` for\n * the result shape, and `MusicTaskResult.stems_error` for how failures are\n * reported. */\n stems?: boolean;\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` and `mp3` (320 kbps) are\n * finalize-time transcodes and require async. Defaults to m4a. */\n outputFormat?: \"m4a\" | \"wav\" | \"mp3\";\n /** Duck the generated music under the source voice at finalize time.\n * Default-OFF server-side: leave unset to skip it, pass `true` to run it,\n * which adds a `ducked` track alongside the unchanged clean `audio`. Free,\n * 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 /** How strongly the generated music follows the prompt (0-1, API default\n * 0.5). Lower values let the video lead; higher values follow the prompt\n * more literally. Free of charge. A generation-time knob, not a\n * finalize-time one, so it works on the plain stream as well as async —\n * no `mode` gating. Omitted from the wire when unset so the server\n * default applies; `0` is a meaningful value and is sent. Out-of-range\n * values are rejected server-side with a 422. */\n promptInfluence?: number;\n /** Also split the generated music into four separated stems — `drums`,\n * `bass`, `vocals`, `other` — delivered on the task result's `stems`\n * array. It splits the GENERATED music, never the source video's own\n * audio. Free of charge. Requires `mode: \"async\"` (auto-selected by\n * `submit()`; the backend rejects it on the plain stream with a 400), so\n * it is only meaningful via `submit()` — `stream()`/`generate()` never\n * send it. Separation runs after generation and typically adds 2-6\n * minutes to the wait (it gives up after 30), so raise `tasks.wait`'s\n * `timeout` accordingly. See `StemsEntry` for the result shape, and\n * `MusicTaskResult.stems_error` for how failures are reported. */\n stems?: 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 /** 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/** The four separated stems of one generated stream, present when the\n * request set `stems: true`. Each stem is an ordinary media object\n * (`url` / `content_type` / `file_size`), so any of them can be passed to\n * `download()`. The stems normally follow the request's `outputFormat`;\n * each stem's own `content_type` reports what was actually delivered. */\nexport interface StemsEntry {\n /** Which `audio` entry this stems set belongs to. Match on this field,\n * never on array position — `stems` carries only the streams that\n * separated successfully, so it can be shorter than `audio`. */\n stream_index: number;\n drums: SfxMedia;\n bass: SfxMedia;\n vocals: SfxMedia;\n other: SfxMedia;\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 /** Separated stems, one entry per stream that separated successfully;\n * only appears when the request set `stems: true`. Look entries up by\n * `stream_index`, never by array position — the array can be shorter than\n * `audio` when separation failed for some streams (see `stems_error`). */\n stems?: StemsEntry[];\n /** Why stem separation failed wholly or in part, or was skipped. It can\n * appear ALONGSIDE a partial `stems` array, so never treat its presence as\n * \"no stems\" — check `stems` itself for what did arrive. Independent of\n * the task's own `status`/`error`: the generation is intact either way. */\n stems_error?: string;\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\n/** Params for `videoToVideoMusic`.\n *\n * The delivered video's audio is decided by two independent knobs:\n * `keepOriginalSound` picks the **voice source**, `ducking` picks how that\n * voice and the generated music are **combined**.\n *\n * | Request | Audio in the returned video |\n * | --- | --- |\n * | neither set | generated music only — the source's own audio is removed |\n * | `keepOriginalSound: true` | full original sound + static music mix |\n * | `keepOriginalSound: true, ducking: true` | full original sound + music ducked under it |\n * | `preserveSpeech: true` | static vocal-forward mix of vocals + music |\n * | `preserveSpeech: true, ducking: true` | isolated vocals + music ducked under them |\n *\n * `keepOriginalSound` supersedes `preserveSpeech` — the voice source is a\n * single choice, and keeping the whole track subsumes keeping only the\n * isolated speech. No combination is rejected.\n *\n * The source picture is copied without re-encoding, so the input must carry\n * H.264, H.265/HEVC, VP9 or AV1 video in an mp4, mov, m4v or webm container —\n * animated gif and VP8 webm are rejected. Maximum input duration is 360\n * seconds. */\nexport interface VideoToVideoMusicParams {\n video?: VideoInput;\n videoUrl?: string;\n prompt?: string;\n /** How the music should develop over time. Same shape as\n * `videoToMusic`'s: the first `start` must be 0. Supplying these skips the\n * prompt-service plan the server would otherwise derive from `prompt`. */\n segments?: Segment[];\n /** Keep the source video's whole original audio track in the result, with\n * the generated music combined under it. Defaults to `false`, so by\n * default the returned video's audio is the generated music ALONE and the\n * source's own audio is removed. Supersedes `preserveSpeech`. */\n keepOriginalSound?: boolean;\n /** How the voice and the generated music are combined — not whether a\n * voice is kept. Default-OFF server-side: leave unset for a static\n * voice-forward mix at a fixed offset, pass `true` for the dynamic duck\n * (music dips only while the voice is present). Has no effect when there\n * is no voice source, i.e. neither `keepOriginalSound` nor `preserveSpeech`\n * is set. Free and best-effort; silently falls back to\n * generated-audio-only if the source has no usable audio track, voice\n * isolation fails, or the mix fails. */\n ducking?: boolean;\n /** Keep only the source's isolated speech (not the whole track) in the\n * output. Both this and the legacy `isolateVocals` are accepted and OR'd\n * server-side. Superseded by `keepOriginalSound`. */\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 /** How strongly the generated music follows the prompt (0-1, API default\n * 0.5). Lower values let the video lead; higher values follow the prompt\n * more literally. Free of charge. Omitted from the wire when unset so the\n * server default applies; `0` is a meaningful value and is sent.\n * Out-of-range values are rejected server-side with a 422. */\n promptInfluence?: number;\n}\n\nexport interface VideoToVideoSfxParams {\n video?: VideoInput;\n videoUrl?: string;\n prompt?: string;\n segments?: SfxSegment[];\n}\n\n/** Params for `videoToVideoSound`, and the base every `videoToSound` param\n * also has. The two endpoints differ in exactly two fields, one in each\n * direction, and both are enforced at the type level rather than left to the\n * server to silently ignore:\n *\n * - `outputFormat` is **audio-only** — added by `VideoToSoundParams` below, so\n * it simply does not exist on this type.\n * - `keepOriginalSound` is **video-only** — declared here, so\n * `VideoToSoundParams` inherits it and has to forbid it explicitly with\n * `?: never` (the inheritance runs the other way, so it cannot just be\n * omitted the way `outputFormat` is).\n *\n * Passing either field to the wrong endpoint is therefore a compile error. */\nexport interface VideoToVideoSoundParams {\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 video's whole original audio track in the result, with\n * the generated music + SFX combined under it. Defaults to `false`, so by\n * default the returned video's audio is the generated music and sound\n * effects ALONE and the source's own audio is removed — and the result\n * carries no `music_processed` stem, since with no voice source there is no\n * processed track. Supersedes `preserveSpeech`. Video endpoint only. */\n keepOriginalSound?: boolean;\n /** Keep only the source's isolated speech (not the whole track) in the\n * result. Superseded by `keepOriginalSound`. */\n preserveSpeech?: boolean;\n /** On `videoToVideoSound`, how the voice and the generated bed are\n * combined — not whether a voice is kept: default-OFF server-side, so an\n * unset value gives a static voice-forward mix and `true` gives the dynamic\n * duck, and either way it has no effect without a voice source.\n *\n * On `videoToSound` it decides BOTH, because that endpoint has no\n * `keepOriginalSound`: unset means the source's own speech is left out of\n * the deliverable entirely, and `true` is what pulls the original track in\n * and ducks the bed under it. Pass `preserveSpeech` instead to bring in the\n * isolated vocals rather than the whole track. */\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/** Params for `videoToSound`. Everything `videoToVideoSound` takes, plus the\n * delivery container for the combined track. */\nexport interface VideoToSoundParams extends VideoToVideoSoundParams {\n /** Container for the combined music + SFX track. Defaults to `wav`;\n * `mp3` is 320 kbps. Applies to the combined output only — the `music`\n * and `sfx` stems keep their native formats. Not available on\n * `videoToVideoSound`, which always returns an mp4. */\n outputFormat?: \"wav\" | \"m4a\" | \"mp3\";\n /** Not available on this endpoint. `keepOriginalSound` only means something\n * when the deliverable is a video whose own audio could be preserved;\n * `videoToSound` returns generated audio, and reaches the original track\n * through `ducking: true` instead. Typed `never` so passing it is a compile\n * error rather than a field the server silently drops — the mirror of how\n * `outputFormat` is kept off `videoToVideoSound`. */\n keepOriginalSound?: never;\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/** Params for `audioDucking`: mix an existing music bed under an existing\n * voice track, ducking the music wherever the voice speaks. Exactly one of\n * `voice`/`voiceUrl` and exactly one of `music`/`musicUrl`; a local input and\n * a URL may be mixed across the two.\n *\n * The voice may be audio or video (`VideoInput` is the SDK's generic media\n * input union) — a video's own audio track becomes the voice, and the ducked\n * mix is re-muxed back into a new video. The music must be audio: the backend\n * never probes it for a video stream, so a video there would be silently\n * mishandled. Each input is capped at 360 seconds server-side. */\nexport interface AudioDuckingParams {\n voice?: VideoInput;\n voiceUrl?: string;\n music?: VideoInput;\n musicUrl?: string;\n}\n\n/** Result of an `audioDucking` task (`tasks.get`) or its final state\n * (`generate`). Same flat envelope as `SoundResult`, but a ducking task\n * renders exactly one artifact and no stems: a `.wav` (`output_type`\n * \"audio\"), or a `.mp4` with the ducked mix re-muxed in (`output_type`\n * \"video\") when the voice input was a video. Pass `output_url` to\n * `download()`. */\nexport interface DuckingResult extends BaseTaskResult {\n output_url?: string;\n output_type?: \"audio\" | \"video\";\n output_bytes?: number;\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 * Duck the background music/effects bed under the dubbed voice. Default\n * OFF server-side, like every other endpoint's `ducking`: the bed is\n * 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\nexport interface VideoAnalysisParams {\n /** Exactly one of `video` / `videoUrl`. */\n video?: VideoInput;\n /** Exactly one of `video` / `videoUrl`. */\n videoUrl?: string;\n /** Optional guidance for the analysis, at most 2000 characters. */\n prompt?: string;\n /**\n * How many independent creative briefs to author for the same video\n * (1-5, default 1). Billed per brief.\n */\n variantsNum?: number;\n}\n\n/** One time-aligned section of the analyzed video, with the scoring\n * direction for that stretch. Bounds are whole seconds — the backend\n * truncates any fractional upstream bound before it reaches the envelope. */\nexport interface AnalysisSegment {\n start: number;\n end: number;\n /** The backend always emits one, defaulting to the string `\"none\"`. */\n label: string;\n prompt: string;\n}\n\n/** One independent creative brief for the whole video. Only the generation\n * prompt is public — the upstream's title/summary/tags are internal display\n * copy the API deliberately does not resell. */\nexport interface AnalysisVariation {\n prompt: string;\n}\n\n/**\n * The only Sonilo result with no media artifact at all: video-analysis\n * generates nothing and there is nothing to download. The payload is the\n * work order — `segments` for a time-aligned plan, and one `prompt` per\n * requested variation, each ready to pass to videoToMusic, videoToSfx,\n * videoToSound or their video-to-video counterparts.\n *\n * Both lists are optional because a `processing` or `failed` poll carries\n * neither.\n */\nexport interface VideoAnalysisResult extends BaseTaskResult {\n segments?: AnalysisSegment[];\n variations?: AnalysisVariation[];\n duration_seconds?: number;\n}\n"],"mappings":"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","names":[]}
|
package/dist/index.d.cts
CHANGED
|
@@ -881,6 +881,6 @@ declare class RequestTimeoutError extends SoniloError {
|
|
|
881
881
|
declare function download(media: SfxMedia | string | undefined, fetchFn?: typeof globalThis.fetch, timeout?: number): Promise<Uint8Array>;
|
|
882
882
|
|
|
883
883
|
/** The SDK's own version. Generated by scripts/sync-versions.mjs — do not edit. */
|
|
884
|
-
declare const VERSION = "0.16.
|
|
884
|
+
declare const VERSION = "0.16.1";
|
|
885
885
|
|
|
886
886
|
export { APIError, type AccountServices, type AnalysisSegment, type AnalysisVariation, type AudioChunkEvent, type AudioDuckingParams, AuthenticationError, BadRequestError, type BaseTaskResult, type CompleteEvent, type CostEvent, type CostInfo, DEFAULT_TIMEOUT_MS, type DailyUsage, type DubbingLanguage, type DubbingParams, type DubbingResult, type DuckingResult, type ErrorEvent, GenerationError, type MusicMediaEntry, type MusicMuxEntry, type MusicTaskResult, type MusicTitle, PaymentRequiredError, RateLimitError, RequestTimeoutError, type Segment, type SegmentLabel, type SfxAudioFormat, type SfxError, type SfxMedia, type SfxResult, type SfxSegment, type SfxTask, SoniloClient, type SoniloClientOptions, SoniloError, type SoundOutputEntry, type SoundResult, type StemsEntry, type StreamEvent, TaskFailedError, TaskTimeoutError, type TextToMusicParams, type TextToSfxParams, type TitleEvent, type Track, TrialExhaustedError, type TrialQuota, type UnknownEvent, type UsageResponse, type UsageSummary, VERSION, type VideoAnalysisParams, type VideoAnalysisResult, type VideoInput, type VideoResult, type VideoToMusicParams, type VideoToSfxParams, type VideoToSoundParams, type VideoToVideoMusicParams, type VideoToVideoSfxParams, type VideoToVideoSoundParams, type WaitOptions, download, isAudioChunkEvent, isErrorEvent };
|
package/dist/index.d.ts
CHANGED
|
@@ -881,6 +881,6 @@ declare class RequestTimeoutError extends SoniloError {
|
|
|
881
881
|
declare function download(media: SfxMedia | string | undefined, fetchFn?: typeof globalThis.fetch, timeout?: number): Promise<Uint8Array>;
|
|
882
882
|
|
|
883
883
|
/** The SDK's own version. Generated by scripts/sync-versions.mjs — do not edit. */
|
|
884
|
-
declare const VERSION = "0.16.
|
|
884
|
+
declare const VERSION = "0.16.1";
|
|
885
885
|
|
|
886
886
|
export { APIError, type AccountServices, type AnalysisSegment, type AnalysisVariation, type AudioChunkEvent, type AudioDuckingParams, AuthenticationError, BadRequestError, type BaseTaskResult, type CompleteEvent, type CostEvent, type CostInfo, DEFAULT_TIMEOUT_MS, type DailyUsage, type DubbingLanguage, type DubbingParams, type DubbingResult, type DuckingResult, type ErrorEvent, GenerationError, type MusicMediaEntry, type MusicMuxEntry, type MusicTaskResult, type MusicTitle, PaymentRequiredError, RateLimitError, RequestTimeoutError, type Segment, type SegmentLabel, type SfxAudioFormat, type SfxError, type SfxMedia, type SfxResult, type SfxSegment, type SfxTask, SoniloClient, type SoniloClientOptions, SoniloError, type SoundOutputEntry, type SoundResult, type StemsEntry, type StreamEvent, TaskFailedError, TaskTimeoutError, type TextToMusicParams, type TextToSfxParams, type TitleEvent, type Track, TrialExhaustedError, type TrialQuota, type UnknownEvent, type UsageResponse, type UsageSummary, VERSION, type VideoAnalysisParams, type VideoAnalysisResult, type VideoInput, type VideoResult, type VideoToMusicParams, type VideoToSfxParams, type VideoToSoundParams, type VideoToVideoMusicParams, type VideoToVideoSfxParams, type VideoToVideoSoundParams, type WaitOptions, download, isAudioChunkEvent, isErrorEvent };
|
package/dist/index.js
CHANGED
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../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/audioDucking.ts","../src/resources/dubbing.ts","../src/resources/videoAnalysis.ts","../src/version.ts","../src/client.ts","../src/download.ts","../src/types.ts"],"sourcesContent":["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 * a non-m4a `outputFormat`, `variantsNum` above 1, and `stems`.\n * `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 if (params.variantsNum !== undefined) {\n form.set(\"variants_num\", String(params.variantsNum));\n }\n if (params.stems !== undefined) {\n form.set(\"stems\", String(params.stems));\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 // A generation-time knob, valid on the plain stream as well as async —\n // unlike the finalize-time params, which submit() alone sends. The\n // explicit undefined check matters: 0 is a meaningful value.\n if (params.promptInfluence !== undefined) {\n form.set(\"prompt_influence\", String(params.promptInfluence));\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`, a non-m4a `outputFormat`,\n * `variantsNum` above 1, and `stems` — the backend rejects all of these on\n * the plain 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 // Any non-m4a container is a finalize-time transcode, so it needs\n // async. Checking != \"m4a\" rather than == \"wav\" keeps this correct\n // as formats are added (mp3 landed after the original check).\n (params.outputFormat !== undefined && params.outputFormat !== \"m4a\") ||\n (params.variantsNum !== undefined && params.variantsNum > 1) ||\n params.stems !== undefined;\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/stems/outputFormat other than \"m4a\"/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 if (params.stems !== undefined) {\n form.set(\"stems\", String(params.stems));\n }\n // Explicit undefined check: 0 is a meaningful value and must go out.\n if (params.promptInfluence !== undefined) {\n form.set(\"prompt_influence\", String(params.promptInfluence));\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.segments !== undefined) {\n form.set(\"segments\", JSON.stringify(params.segments));\n }\n // Omitted when unset rather than sent with a default, so the server's own\n // default decides — `ducking` and `keepOriginalSound` are both default-OFF\n // server-side today, and neither is hardcoded here (same rule as\n // buildSoundForm's).\n if (params.keepOriginalSound !== undefined) {\n form.set(\"keep_original_sound\", String(params.keepOriginalSound));\n }\n if (params.ducking !== undefined) form.set(\"ducking\", String(params.ducking));\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 // Explicit undefined check: 0 is a meaningful value and must go out.\n if (params.promptInfluence !== undefined) {\n form.set(\"prompt_influence\", String(params.promptInfluence));\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, VideoToVideoSoundParams } from \"../types.js\";\n\n/** The widest shape either endpoint can send. Neither public param type can\n * serve as the parameter here, because the two now differ in opposite\n * directions: `outputFormat` exists only on `VideoToSoundParams` (audio),\n * while `keepOriginalSound` is video-only and is therefore typed `never` on\n * `VideoToSoundParams`. That makes each public type unassignable to the other,\n * so the shared builder takes their union and each endpoint's own param type\n * stays the thing that rejects the wrong field at compile time. */\ntype SoundFormParams = VideoToVideoSoundParams & Pick<VideoToSoundParams, \"outputFormat\">;\n\n/** Build the multipart body shared by /v1/video-to-sound and\n * /v1/video-to-video-sound. The two differ only in the path they POST to and\n * in the two endpoint-specific fields described on `SoundFormParams`.\n *\n * Every optional field is omitted when unset rather than sent with a default,\n * so the server's own default decides. `ducking` and `keepOriginalSound` are\n * both default-OFF server-side today, but neither is hardcoded here — pinning\n * either one on the wire is what would have to change the next time a server\n * default moves, and this builder deliberately does not. */\nexport async function buildSoundForm(params: SoundFormParams): 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.keepOriginalSound !== undefined) {\n form.set(\"keep_original_sound\", String(params.keepOriginalSound));\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.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 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 {\n SfxTask,\n SoundResult,\n VideoToVideoSoundParams,\n WaitOptions,\n} 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: VideoToVideoSoundParams): 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: VideoToVideoSoundParams, 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 { AudioDuckingParams, DuckingResult, SfxTask, WaitOptions } from \"../types.js\";\n\n/** Duck an existing music bed under a voice track. Async only (202 + poll).\n *\n * Both inputs are user-supplied — nothing is generated here. The voice may be\n * audio OR a video: the backend extracts a video's audio track, ducks the\n * music under it, and re-muxes the ducked mix back into a new video (the\n * result's `output_type` announces which came back). The music must be audio —\n * the backend never probes it for a video stream, so a video there would be\n * silently mishandled. */\nexport class AudioDucking {\n constructor(private readonly client: SoniloClient) {}\n\n async submit(params: AudioDuckingParams): Promise<SfxTask> {\n // Both pairs are validated before any upload I/O, so a missing music\n // input is reported even when the voice side alone looks fine.\n if ((params.voice === undefined) === (params.voiceUrl === undefined)) {\n throw new SoniloError(\"Provide exactly one of voice or voiceUrl\");\n }\n if ((params.music === undefined) === (params.musicUrl === undefined)) {\n throw new SoniloError(\"Provide exactly one of music or musicUrl\");\n }\n const form = new FormData();\n if (params.voice !== undefined) {\n const { blob, filename } = await toUploadBlob(params.voice);\n form.set(\"voice_file\", blob, filename);\n } else {\n form.set(\"voice_url\", params.voiceUrl as string);\n }\n if (params.music !== undefined) {\n const { blob, filename } = await toUploadBlob(params.music);\n form.set(\"music_file\", blob, filename);\n } else {\n form.set(\"music_url\", params.musicUrl as string);\n }\n const res = await this.client.request(\"/v1/audio-ducking\", {\n method: \"POST\",\n body: form,\n });\n return (await res.json()) as SfxTask;\n }\n\n async generate(params: AudioDuckingParams, opts?: WaitOptions): Promise<DuckingResult> {\n const task = await this.submit(params);\n return this.client.tasks.wait<DuckingResult>(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","import type { SoniloClient } from \"../client.js\";\nimport { SoniloError } from \"../errors.js\";\nimport { toUploadBlob } from \"../upload.js\";\nimport type {\n SfxTask,\n VideoAnalysisParams,\n VideoAnalysisResult,\n WaitOptions,\n} from \"../types.js\";\n\n/** Analyze a video and get back a creative brief for scoring it. Async only.\n *\n * This endpoint generates nothing — no audio, no video, no artifact to\n * download. The result is the work order: `segments` (a time-aligned section\n * plan) plus one `prompt` per requested variation, each ready to hand\n * straight to videoToMusic, videoToSfx, videoToSound or their\n * video-to-video counterparts.\n *\n * The method is `analyze`, not `generate`, for that reason: every other\n * resource's `generate` returns something you download, and this one never\n * does.\n *\n * The 1-5 bound on `variantsNum` and the 2000-character bound on `prompt`\n * are deliberately not checked here — the backend owns them, and a hardcoded\n * copy would make this SDK reject values a later API widens. */\nexport class VideoAnalysis {\n constructor(private readonly client: SoniloClient) {}\n\n async submit(params: VideoAnalysisParams): 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.variantsNum !== undefined) {\n form.set(\"variants_num\", String(params.variantsNum));\n }\n const res = await this.client.request(\"/v1/video-analysis\", {\n method: \"POST\",\n body: form,\n });\n return (await res.json()) as SfxTask;\n }\n\n async analyze(\n params: VideoAnalysisParams,\n opts?: WaitOptions,\n ): Promise<VideoAnalysisResult> {\n const task = await this.submit(params);\n return this.client.tasks.wait<VideoAnalysisResult>(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.16.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 { AudioDucking } from \"./resources/audioDucking.js\";\nimport { Dubbing } from \"./resources/dubbing.js\";\nimport { VideoAnalysis } from \"./resources/videoAnalysis.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 audioDucking: AudioDucking;\n readonly dubbing: Dubbing;\n readonly videoAnalysis: VideoAnalysis;\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.audioDucking = new AudioDucking(this);\n this.dubbing = new Dubbing(this);\n this.videoAnalysis = new VideoAnalysis(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 by any\n * `outputFormat` other than the m4a default). */\n mode?: \"stream\" | \"async\";\n /** Container for the async result. `wav` and `mp3` (320 kbps) are\n * finalize-time transcodes and require `mode: \"async\"`; m4a is what the\n * stream itself carries. Defaults to m4a server-side. */\n outputFormat?: \"m4a\" | \"wav\" | \"mp3\";\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 /** Also split the generated track into four separated stems — `drums`,\n * `bass`, `vocals`, `other` — delivered on the task result's `stems`\n * array. Free of charge. Requires `mode: \"async\"` (the backend rejects it\n * on the plain stream with a 400), so it is only meaningful via\n * `submit()`; `stream()`/`generate()` never send it. Separation runs after\n * generation and typically adds 2-6 minutes to the wait (it gives up after\n * 30), so raise `tasks.wait`'s `timeout` accordingly. See `StemsEntry` for\n * the result shape, and `MusicTaskResult.stems_error` for how failures are\n * reported. */\n stems?: boolean;\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` and `mp3` (320 kbps) are\n * finalize-time transcodes and require async. Defaults to m4a. */\n outputFormat?: \"m4a\" | \"wav\" | \"mp3\";\n /** Duck the generated music under the source voice at finalize time.\n * Default-OFF server-side: leave unset to skip it, pass `true` to run it,\n * which adds a `ducked` track alongside the unchanged clean `audio`. Free,\n * 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 /** How strongly the generated music follows the prompt (0-1, API default\n * 0.5). Lower values let the video lead; higher values follow the prompt\n * more literally. Free of charge. A generation-time knob, not a\n * finalize-time one, so it works on the plain stream as well as async —\n * no `mode` gating. Omitted from the wire when unset so the server\n * default applies; `0` is a meaningful value and is sent. Out-of-range\n * values are rejected server-side with a 422. */\n promptInfluence?: number;\n /** Also split the generated music into four separated stems — `drums`,\n * `bass`, `vocals`, `other` — delivered on the task result's `stems`\n * array. It splits the GENERATED music, never the source video's own\n * audio. Free of charge. Requires `mode: \"async\"` (auto-selected by\n * `submit()`; the backend rejects it on the plain stream with a 400), so\n * it is only meaningful via `submit()` — `stream()`/`generate()` never\n * send it. Separation runs after generation and typically adds 2-6\n * minutes to the wait (it gives up after 30), so raise `tasks.wait`'s\n * `timeout` accordingly. See `StemsEntry` for the result shape, and\n * `MusicTaskResult.stems_error` for how failures are reported. */\n stems?: 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 /** 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/** The four separated stems of one generated stream, present when the\n * request set `stems: true`. Each stem is an ordinary media object\n * (`url` / `content_type` / `file_size`), so any of them can be passed to\n * `download()`. The stems normally follow the request's `outputFormat`;\n * each stem's own `content_type` reports what was actually delivered. */\nexport interface StemsEntry {\n /** Which `audio` entry this stems set belongs to. Match on this field,\n * never on array position — `stems` carries only the streams that\n * separated successfully, so it can be shorter than `audio`. */\n stream_index: number;\n drums: SfxMedia;\n bass: SfxMedia;\n vocals: SfxMedia;\n other: SfxMedia;\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 /** Separated stems, one entry per stream that separated successfully;\n * only appears when the request set `stems: true`. Look entries up by\n * `stream_index`, never by array position — the array can be shorter than\n * `audio` when separation failed for some streams (see `stems_error`). */\n stems?: StemsEntry[];\n /** Why stem separation failed wholly or in part, or was skipped. It can\n * appear ALONGSIDE a partial `stems` array, so never treat its presence as\n * \"no stems\" — check `stems` itself for what did arrive. Independent of\n * the task's own `status`/`error`: the generation is intact either way. */\n stems_error?: string;\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\n/** Params for `videoToVideoMusic`.\n *\n * The delivered video's audio is decided by two independent knobs:\n * `keepOriginalSound` picks the **voice source**, `ducking` picks how that\n * voice and the generated music are **combined**.\n *\n * | Request | Audio in the returned video |\n * | --- | --- |\n * | neither set | generated music only — the source's own audio is removed |\n * | `keepOriginalSound: true` | full original sound + static music mix |\n * | `keepOriginalSound: true, ducking: true` | full original sound + music ducked under it |\n * | `preserveSpeech: true` | static vocal-forward mix of vocals + music |\n * | `preserveSpeech: true, ducking: true` | isolated vocals + music ducked under them |\n *\n * `keepOriginalSound` supersedes `preserveSpeech` — the voice source is a\n * single choice, and keeping the whole track subsumes keeping only the\n * isolated speech. No combination is rejected.\n *\n * The source picture is copied without re-encoding, so the input must carry\n * H.264, H.265/HEVC, VP9 or AV1 video in an mp4, mov, m4v or webm container —\n * animated gif and VP8 webm are rejected. Maximum input duration is 360\n * seconds. */\nexport interface VideoToVideoMusicParams {\n video?: VideoInput;\n videoUrl?: string;\n prompt?: string;\n /** How the music should develop over time. Same shape as\n * `videoToMusic`'s: the first `start` must be 0. Supplying these skips the\n * prompt-service plan the server would otherwise derive from `prompt`. */\n segments?: Segment[];\n /** Keep the source video's whole original audio track in the result, with\n * the generated music combined under it. Defaults to `false`, so by\n * default the returned video's audio is the generated music ALONE and the\n * source's own audio is removed. Supersedes `preserveSpeech`. */\n keepOriginalSound?: boolean;\n /** How the voice and the generated music are combined — not whether a\n * voice is kept. Default-OFF server-side: leave unset for a static\n * voice-forward mix at a fixed offset, pass `true` for the dynamic duck\n * (music dips only while the voice is present). Has no effect when there\n * is no voice source, i.e. neither `keepOriginalSound` nor `preserveSpeech`\n * is set. Free and best-effort; silently falls back to\n * generated-audio-only if the source has no usable audio track, voice\n * isolation fails, or the mix fails. */\n ducking?: boolean;\n /** Keep only the source's isolated speech (not the whole track) in the\n * output. Both this and the legacy `isolateVocals` are accepted and OR'd\n * server-side. Superseded by `keepOriginalSound`. */\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 /** How strongly the generated music follows the prompt (0-1, API default\n * 0.5). Lower values let the video lead; higher values follow the prompt\n * more literally. Free of charge. Omitted from the wire when unset so the\n * server default applies; `0` is a meaningful value and is sent.\n * Out-of-range values are rejected server-side with a 422. */\n promptInfluence?: number;\n}\n\nexport interface VideoToVideoSfxParams {\n video?: VideoInput;\n videoUrl?: string;\n prompt?: string;\n segments?: SfxSegment[];\n}\n\n/** Params for `videoToVideoSound`, and the base every `videoToSound` param\n * also has. The two endpoints differ in exactly two fields, one in each\n * direction, and both are enforced at the type level rather than left to the\n * server to silently ignore:\n *\n * - `outputFormat` is **audio-only** — added by `VideoToSoundParams` below, so\n * it simply does not exist on this type.\n * - `keepOriginalSound` is **video-only** — declared here, so\n * `VideoToSoundParams` inherits it and has to forbid it explicitly with\n * `?: never` (the inheritance runs the other way, so it cannot just be\n * omitted the way `outputFormat` is).\n *\n * Passing either field to the wrong endpoint is therefore a compile error. */\nexport interface VideoToVideoSoundParams {\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 video's whole original audio track in the result, with\n * the generated music + SFX combined under it. Defaults to `false`, so by\n * default the returned video's audio is the generated music and sound\n * effects ALONE and the source's own audio is removed — and the result\n * carries no `music_processed` stem, since with no voice source there is no\n * processed track. Supersedes `preserveSpeech`. Video endpoint only. */\n keepOriginalSound?: boolean;\n /** Keep only the source's isolated speech (not the whole track) in the\n * result. Superseded by `keepOriginalSound`. */\n preserveSpeech?: boolean;\n /** On `videoToVideoSound`, how the voice and the generated bed are\n * combined — not whether a voice is kept: default-OFF server-side, so an\n * unset value gives a static voice-forward mix and `true` gives the dynamic\n * duck, and either way it has no effect without a voice source.\n *\n * On `videoToSound` it decides BOTH, because that endpoint has no\n * `keepOriginalSound`: unset means the source's own speech is left out of\n * the deliverable entirely, and `true` is what pulls the original track in\n * and ducks the bed under it. Pass `preserveSpeech` instead to bring in the\n * isolated vocals rather than the whole track. */\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/** Params for `videoToSound`. Everything `videoToVideoSound` takes, plus the\n * delivery container for the combined track. */\nexport interface VideoToSoundParams extends VideoToVideoSoundParams {\n /** Container for the combined music + SFX track. Defaults to `wav`;\n * `mp3` is 320 kbps. Applies to the combined output only — the `music`\n * and `sfx` stems keep their native formats. Not available on\n * `videoToVideoSound`, which always returns an mp4. */\n outputFormat?: \"wav\" | \"m4a\" | \"mp3\";\n /** Not available on this endpoint. `keepOriginalSound` only means something\n * when the deliverable is a video whose own audio could be preserved;\n * `videoToSound` returns generated audio, and reaches the original track\n * through `ducking: true` instead. Typed `never` so passing it is a compile\n * error rather than a field the server silently drops — the mirror of how\n * `outputFormat` is kept off `videoToVideoSound`. */\n keepOriginalSound?: never;\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/** Params for `audioDucking`: mix an existing music bed under an existing\n * voice track, ducking the music wherever the voice speaks. Exactly one of\n * `voice`/`voiceUrl` and exactly one of `music`/`musicUrl`; a local input and\n * a URL may be mixed across the two.\n *\n * The voice may be audio or video (`VideoInput` is the SDK's generic media\n * input union) — a video's own audio track becomes the voice, and the ducked\n * mix is re-muxed back into a new video. The music must be audio: the backend\n * never probes it for a video stream, so a video there would be silently\n * mishandled. Each input is capped at 360 seconds server-side. */\nexport interface AudioDuckingParams {\n voice?: VideoInput;\n voiceUrl?: string;\n music?: VideoInput;\n musicUrl?: string;\n}\n\n/** Result of an `audioDucking` task (`tasks.get`) or its final state\n * (`generate`). Same flat envelope as `SoundResult`, but a ducking task\n * renders exactly one artifact and no stems: a `.wav` (`output_type`\n * \"audio\"), or a `.mp4` with the ducked mix re-muxed in (`output_type`\n * \"video\") when the voice input was a video. Pass `output_url` to\n * `download()`. */\nexport interface DuckingResult extends BaseTaskResult {\n output_url?: string;\n output_type?: \"audio\" | \"video\";\n output_bytes?: number;\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 * Duck the background music/effects bed under the dubbed voice. Default\n * OFF server-side, like every other endpoint's `ducking`: the bed is\n * 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\nexport interface VideoAnalysisParams {\n /** Exactly one of `video` / `videoUrl`. */\n video?: VideoInput;\n /** Exactly one of `video` / `videoUrl`. */\n videoUrl?: string;\n /** Optional guidance for the analysis, at most 2000 characters. */\n prompt?: string;\n /**\n * How many independent creative briefs to author for the same video\n * (1-5, default 1). Billed per brief.\n */\n variantsNum?: number;\n}\n\n/** One time-aligned section of the analyzed video, with the scoring\n * direction for that stretch. Bounds are whole seconds — the backend\n * truncates any fractional upstream bound before it reaches the envelope. */\nexport interface AnalysisSegment {\n start: number;\n end: number;\n /** The backend always emits one, defaulting to the string `\"none\"`. */\n label: string;\n prompt: string;\n}\n\n/** One independent creative brief for the whole video. Only the generation\n * prompt is public — the upstream's title/summary/tags are internal display\n * copy the API deliberately does not resell. */\nexport interface AnalysisVariation {\n prompt: string;\n}\n\n/**\n * The only Sonilo result with no media artifact at all: video-analysis\n * generates nothing and there is nothing to download. The payload is the\n * work order — `segments` for a time-aligned plan, and one `prompt` per\n * requested variation, each ready to pass to videoToMusic, videoToSfx,\n * videoToSound or their video-to-video counterparts.\n *\n * Both lists are optional because a `processing` or `failed` poll carries\n * neither.\n */\nexport interface VideoAnalysisResult extends BaseTaskResult {\n segments?: AnalysisSegment[];\n variations?: AnalysisVariation[];\n duration_seconds?: number;\n}\n"],"mappings":";AAAO,IAAM,cAAN,cAA0B,MAAM;AAAA,EACrC,YAAY,SAAiB;AAC3B,UAAM,OAAO;AACb,SAAK,OAAO,WAAW;AAAA,EACzB;AACF;AAEO,IAAM,WAAN,cAAuB,YAAY;AAAA,EAQxC,YAAY,SAAiB,QAAgB,MAAgB;AAC3D,UAAM,OAAO;AACb,SAAK,SAAS;AACd,SAAK,OAAO;AACZ,UAAM,SAAS;AACf,SAAK,OAAO,OAAO,QAAQ,SAAS,WAAW,OAAO,OAAO;AAC7D,SAAK,SAAS,MAAM,QAAQ,QAAQ,MAAM,IAAI,OAAO,SAAS;AAAA,EAChE;AACF;AAEO,IAAM,sBAAN,cAAkC,SAAS;AAAC;AAE5C,IAAM,uBAAN,cAAmC,SAAS;AAAC;AAQ7C,IAAM,sBAAN,cAAkC,qBAAqB;AAAC;AAExD,IAAM,kBAAN,cAA8B,SAAS;AAAA,EAC5C,IAAI,SAA6B;AAC/B,UAAM,OAAO,KAAK;AAClB,QAAI,OAAO,MAAM,YAAY,YAAY,KAAK,SAAS;AACrD,aAAO,KAAK;AAAA,IACd;AACA,WAAO,OAAO,MAAM,WAAW,WAAW,KAAK,SAAS;AAAA,EAC1D;AACF;AAEO,IAAM,iBAAN,cAA6B,SAAS;AAAA,EAG3C,YAAY,SAAiB,QAAgB,MAAgB,YAAqB;AAChF,UAAM,SAAS,QAAQ,IAAI;AAC3B,SAAK,aAAa;AAAA,EACpB;AACF;AAGO,IAAM,kBAAN,cAA8B,YAAY;AAAA,EAG/C,YAAY,SAAiB,MAAe;AAC1C,UAAM,OAAO;AACb,SAAK,OAAO;AAAA,EACd;AACF;AAGO,IAAM,kBAAN,cAA8B,YAAY;AAAA,EAK/C,YACE,SACA,MACA;AACA,UAAM,OAAO;AACb,SAAK,OAAO,KAAK;AACjB,SAAK,SAAS,KAAK;AACnB,SAAK,WAAW,KAAK;AAAA,EACvB;AACF;AAIO,IAAM,mBAAN,cAA+B,YAAY;AAAA,EAGhD,YAAY,SAAiB,QAAgB;AAC3C,UAAM,OAAO;AACb,SAAK,SAAS;AAAA,EAChB;AACF;AAKO,IAAM,sBAAN,cAAkC,YAAY;AAAC;AAQ/C,SAAS,qBAAqB,KAAuB;AAC1D,SAAO,eAAe,UAAU,IAAI,SAAS,kBAAkB,IAAI,SAAS;AAC9E;AAEA,eAAsB,kBAAkB,KAAkC;AACxE,QAAM,OAAO,MAAM,IAAI,KAAK,EAAE,MAAM,MAAM,EAAE;AAC5C,MAAI,OAAgB;AACpB,MAAI;AACF,WAAO,KAAK,MAAM,IAAI;AAAA,EACxB,QAAQ;AAAA,EAER;AACA,QAAM,SAAS;AACf,QAAM,aAAa,OAAO,QAAQ,YAAY,YAAY,OAAO,UAAU,OAAO,UAAU;AAC5F,QAAM,YAAY,QAAQ;AAC1B,QAAM,iBAAiB,cAAc,UAAa,cAAc,QAAQ,cAAc;AACtF,MAAI;AACJ,MAAI,eAAe,QAAW;AAC5B,aAAS;AAAA,EACX,WAAW,gBAAgB;AACzB,aAAS,IAAI,cAAc;AAAA,EAC7B,WAAW,OAAO,cAAc,UAAU;AACxC,aAAS;AAAA,EACX,OAAO;AACL,QAAI;AACF,eAAS,KAAK,UAAU,SAAS;AAAA,IACnC,QAAQ;AACN,eAAS,IAAI,cAAc;AAAA,IAC7B;AAAA,EACF;AACA,QAAM,UAAU,QAAQ,IAAI,MAAM,KAAK,MAAM;AAE7C,UAAQ,IAAI,QAAQ;AAAA,IAClB,KAAK;AACH,aAAO,IAAI,oBAAoB,SAAS,IAAI,QAAQ,IAAI;AAAA,IAC1D,KAAK,KAAK;AAGR,YAAM,OAAQ,MAAyC;AACvD,UAAI,SAAS,mBAAmB;AAC9B,eAAO,IAAI,oBAAoB,SAAS,IAAI,QAAQ,IAAI;AAAA,MAC1D;AACA,aAAO,IAAI,qBAAqB,SAAS,IAAI,QAAQ,IAAI;AAAA,IAC3D;AAAA,IACA,KAAK,KAAK;AACR,YAAM,KAAK,IAAI,QAAQ,IAAI,aAAa;AACxC,YAAM,aAAa,OAAO,QAAQ,OAAO,MAAM,CAAC,OAAO,MAAM,OAAO,EAAE,CAAC,IAAI,OAAO,EAAE,IAAI;AACxF,aAAO,IAAI,eAAe,SAAS,IAAI,QAAQ,MAAM,UAAU;AAAA,IACjE;AAAA,IACA,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AACH,aAAO,IAAI,gBAAgB,SAAS,IAAI,QAAQ,IAAI;AAAA,IACtD;AACE,aAAO,IAAI,SAAS,SAAS,IAAI,QAAQ,IAAI;AAAA,EACjD;AACF;;;AC9JO,IAAM,UAAN,MAAc;AAAA,EACnB,YAA6B,QAAsB;AAAtB;AAAA,EAAuB;AAAA,EAEpD,MAAM,WAAqC;AACzC,UAAM,MAAM,MAAM,KAAK,OAAO,QAAQ,sBAAsB;AAC5D,WAAQ,MAAM,IAAI,KAAK;AAAA,EACzB;AAAA,EAEA,MAAM,MAAM,SAA4B,CAAC,GAA2B;AAClE,UAAM,QAAQ,OAAO,SAAS,SAAY,SAAS,OAAO,IAAI,KAAK;AACnE,UAAM,MAAM,MAAM,KAAK,OAAO,QAAQ,oBAAoB,KAAK,EAAE;AACjE,WAAQ,MAAM,IAAI,KAAK;AAAA,EACzB;AACF;;;ACZO,IAAM,2BAA2B;AACjC,IAAM,0BAA0B;AAEvC,IAAM,QAAQ,CAAC,OAAe,IAAI,QAAc,CAAC,YAAY,WAAW,SAAS,EAAE,CAAC;AAIpF,SAAS,iBAAiB,cAAsB,SAAuB;AACrE,MAAI,eAAe,GAAG;AACpB,UAAM,IAAI,YAAY,kCAAkC,YAAY,EAAE;AAAA,EACxE;AACA,MAAI,UAAU,GAAG;AACf,UAAM,IAAI,YAAY,6BAA6B,OAAO,EAAE;AAAA,EAC9D;AACF;AAEO,IAAM,QAAN,MAAY;AAAA,EACjB,YAA6B,QAAsB;AAAtB;AAAA,EAAuB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASpD,MAAM,IAA0C,QAA4B;AAC1E,UAAM,MAAM,MAAM,KAAK,OAAO,QAAQ,aAAa,mBAAmB,MAAM,CAAC,EAAE;AAC/E,WAAQ,MAAM,IAAI,KAAK;AAAA,EACzB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,KACJ,QACA,OAAoB,CAAC,GACT;AACZ,UAAM,eAAe,KAAK,gBAAgB;AAC1C,UAAM,UAAU,KAAK,WAAW;AAChC,qBAAiB,cAAc,OAAO;AACtC,UAAM,WAAW,YAAY,IAAI,IAAI;AACrC,eAAS;AACP,YAAM,SAAS,MAAM,KAAK,IAAO,MAAM;AACvC,UAAI,OAAO,WAAW,YAAa,QAAO;AAC1C,UAAI,OAAO,WAAW,UAAU;AAC9B,cAAM,UAAU,OAAO,OAAO,WAAW;AACzC,cAAM,IAAI,gBAAgB,QAAQ,MAAM,YAAY,OAAO,IAAI;AAAA,UAC7D,MAAM,OAAO,OAAO;AAAA,UACpB;AAAA,UACA,UAAU,OAAO;AAAA,QACnB,CAAC;AAAA,MACH;AACA,YAAM,YAAY,WAAW,YAAY,IAAI;AAC7C,UAAI,aAAa,GAAG;AAClB,cAAM,IAAI;AAAA,UACR,QAAQ,MAAM,2BAA2B,OAAO;AAAA,UAEhD;AAAA,QACF;AAAA,MACF;AACA,YAAM,MAAM,KAAK,IAAI,cAAc,SAAS,CAAC;AAAA,IAC/C;AAAA,EACF;AACF;;;ACrEO,SAAS,aAAa,KAAyB;AACpD,QAAM,MAAM,KAAK,GAAG;AACpB,QAAM,MAAM,IAAI,WAAW,IAAI,MAAM;AACrC,WAAS,IAAI,GAAG,IAAI,IAAI,QAAQ,IAAK,KAAI,CAAC,IAAI,IAAI,WAAW,CAAC;AAC9D,SAAO;AACT;AAKA,SAAS,QAAQ,MAAkC;AACjD,QAAM,SAAkB,KAAK,MAAM,IAAI;AACvC,MAAI,OAAO,WAAW,YAAY,WAAW,KAAM,QAAO;AAC1D,QAAM,MAAM;AACZ,MAAI,IAAI,SAAS,iBAAiB,OAAO,IAAI,SAAS,UAAU;AAC9D,QAAI;AACF,aAAO,EAAE,GAAG,KAAK,MAAM,eAAe,MAAM,aAAa,IAAI,IAAI,EAAE;AAAA,IACrE,QAAQ;AAAA,IAMR;AAAA,EACF;AACA,SAAO;AACT;AAEA,gBAAuB,YACrB,MAC8C;AAC9C,QAAM,SAAS,KAAK,UAAU;AAC9B,QAAM,UAAU,IAAI,YAAY;AAChC,MAAI,SAAS;AACb,MAAI;AACF,eAAS;AACP,YAAM,EAAE,MAAM,MAAM,IAAI,MAAM,OAAO,KAAK;AAC1C,UAAI,KAAM;AACV,gBAAU,QAAQ,OAAO,OAAO,EAAE,QAAQ,KAAK,CAAC;AAChD,UAAI;AACJ,cAAQ,KAAK,OAAO,QAAQ,IAAI,OAAO,IAAI;AACzC,cAAM,OAAO,OAAO,MAAM,GAAG,EAAE,EAAE,KAAK;AACtC,iBAAS,OAAO,MAAM,KAAK,CAAC;AAC5B,YAAI,MAAM;AACR,gBAAM,KAAK,QAAQ,IAAI;AACvB,cAAI,OAAO,KAAM,OAAM;AAAA,QACzB;AAAA,MACF;AAAA,IACF;AACA,cAAU,QAAQ,OAAO;AACzB,UAAM,OAAO,OAAO,KAAK;AACzB,QAAI,MAAM;AACR,YAAM,KAAK,QAAQ,IAAI;AACvB,UAAI,OAAO,KAAM,OAAM;AAAA,IACzB;AAAA,EACF,UAAE;AACA,UAAM,OAAO,OAAO,EAAE,MAAM,MAAM;AAAA,IAAC,CAAC;AAAA,EACtC;AACF;AAEA,eAAsB,aAAa,QAAoD;AACrF,QAAM,SAAuB,CAAC;AAC9B,MAAI;AACJ,MAAI;AACJ,MAAI,cAAc;AAElB,mBAAiB,MAAM,QAAQ;AAC7B,QAAI,GAAG,SAAS,eAAe;AAI7B,UAAI,EAAE,GAAG,gBAAgB,aAAa;AACpC,cAAM,IAAI;AAAA,UACR;AAAA,QACF;AAAA,MACF;AACA,aAAO,KAAK,GAAG,IAAI;AAAA,IACrB,WAAW,GAAG,SAAS,WAAW,OAAO,GAAG,UAAU,UAAU;AAC9D,cAAQ,GAAG;AAAA,IACb,WAAW,GAAG,SAAS,QAAQ;AAC7B,YAAM,EAAE,MAAM,OAAO,GAAG,KAAK,IAAI;AACjC,aAAO;AAAA,IACT,WAAW,GAAG,SAAS,SAAS;AAC9B,YAAM,UAAU,OAAO,GAAG,YAAY,YAAY,GAAG,YAAY,KAAK,GAAG,UAAU;AACnF,YAAM,OAAO,OAAO,GAAG,SAAS,WAAW,GAAG,OAAO;AACrD,YAAM,IAAI,gBAAgB,SAAS,IAAI;AAAA,IACzC,WAAW,GAAG,SAAS,YAAY;AACjC,oBAAc;AAAA,IAChB;AAAA,EAEF;AAEA,MAAI,CAAC,aAAa;AAChB,UAAM,IAAI,gBAAgB,6DAA6D;AAAA,EACzF;AAEA,QAAM,QAAQ,OAAO,OAAO,CAAC,GAAG,MAAM,IAAI,EAAE,QAAQ,CAAC;AACrD,QAAM,QAAQ,IAAI,WAAW,KAAK;AAClC,MAAI,SAAS;AACb,aAAW,KAAK,QAAQ;AACtB,UAAM,IAAI,GAAG,MAAM;AACnB,cAAU,EAAE;AAAA,EACd;AACA,SAAO,EAAE,OAAO,OAAO,KAAK;AAC9B;;;ACtGO,IAAM,cAAN,MAAkB;AAAA,EACvB,YAA6B,QAAsB;AAAtB;AAAA,EAAuB;AAAA;AAAA,EAGpD,OAAO,OAAO,QAAyE;AACrF,UAAM,OAAO,IAAI,SAAS;AAC1B,SAAK,IAAI,UAAU,OAAO,MAAM;AAChC,SAAK,IAAI,YAAY,OAAO,OAAO,QAAQ,CAAC;AAC5C,QAAI,OAAO,aAAa,QAAW;AACjC,WAAK,IAAI,YAAY,KAAK,UAAU,OAAO,QAAQ,CAAC;AAAA,IACtD;AAMA,UAAM,MAAM,MAAM,KAAK,OAAO;AAAA,MAC5B;AAAA,MACA,EAAE,QAAQ,QAAQ,MAAM,MAAM,QAAQ,OAAO,OAAO;AAAA,MACpD,EAAE,SAAS,KAAK;AAAA,IAClB;AACA,QAAI,CAAC,IAAI,KAAM,OAAM,IAAI,YAAY,sBAAsB;AAC3D,WAAO,YAAY,IAAI,IAAI;AAAA,EAC7B;AAAA;AAAA,EAGA,SAAS,QAA2C;AAClD,WAAO,aAAa,KAAK,OAAO,MAAM,CAAC;AAAA,EACzC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,OAAO,QAA6C;AACxD,UAAM,OAAO,OAAO,QAAQ;AAC5B,QAAI,SAAS,SAAS;AACpB,YAAM,IAAI,YAAY,iCAAiC;AAAA,IACzD;AACA,UAAM,OAAO,IAAI,SAAS;AAC1B,SAAK,IAAI,UAAU,OAAO,MAAM;AAChC,SAAK,IAAI,YAAY,OAAO,OAAO,QAAQ,CAAC;AAC5C,QAAI,OAAO,aAAa,QAAW;AACjC,WAAK,IAAI,YAAY,KAAK,UAAU,OAAO,QAAQ,CAAC;AAAA,IACtD;AACA,SAAK,IAAI,QAAQ,IAAI;AACrB,QAAI,OAAO,iBAAiB,QAAW;AACrC,WAAK,IAAI,iBAAiB,OAAO,YAAY;AAAA,IAC/C;AACA,QAAI,OAAO,gBAAgB,QAAW;AACpC,WAAK,IAAI,gBAAgB,OAAO,OAAO,WAAW,CAAC;AAAA,IACrD;AACA,QAAI,OAAO,UAAU,QAAW;AAC9B,WAAK,IAAI,SAAS,OAAO,OAAO,KAAK,CAAC;AAAA,IACxC;AACA,UAAM,MAAM,MAAM,KAAK,OAAO,QAAQ,qBAAqB;AAAA,MACzD,QAAQ;AAAA,MACR,MAAM;AAAA,IACR,CAAC;AACD,WAAQ,MAAM,IAAI,KAAK;AAAA,EACzB;AACF;;;ACjEA,IAAM,mBAAmB;AAOzB,eAAsB,aACpB,OAC2C;AAC3C,MAAI,OAAO,UAAU,UAAU;AAC7B,UAAM,SACJ,OAAO,YAAY,eAAe,QAAS,QAA6C,UAAU,IAAI;AACxG,QAAI,CAAC,QAAQ;AACX,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AACA,UAAM,WAAW;AACjB,UAAM,EAAE,SAAS,IAAK,MAAM;AAAA;AAAA;AAAA,MACmB;AAAA;AAE/C,UAAM,OAAO,MAAM,SAAS,KAAK;AACjC,UAAM,WAAW,MAAM,MAAM,OAAO,EAAE,IAAI,KAAK;AAC/C,WAAO,EAAE,MAAM,IAAI,KAAK,CAAC,IAAI,CAAC,GAAG,SAAS;AAAA,EAC5C;AACA,MAAI,OAAO,SAAS,eAAe,iBAAiB,MAAM;AACxD,WAAO,EAAE,MAAM,OAAO,UAAU,MAAM,QAAQ,iBAAiB;AAAA,EACjE;AACA,MAAI,iBAAiB,MAAM;AACzB,WAAO,EAAE,MAAM,OAAO,UAAU,iBAAiB;AAAA,EACnD;AACA,MAAI,iBAAiB,YAAY;AAC/B,WAAO,EAAE,MAAM,IAAI,KAAK,CAAC,KAA4B,CAAC,GAAG,UAAU,iBAAiB;AAAA,EACtF;AACA,MAAI,iBAAiB,aAAa;AAChC,WAAO,EAAE,MAAM,IAAI,KAAK,CAAC,KAAK,CAAC,GAAG,UAAU,iBAAiB;AAAA,EAC/D;AACA,MAAI,iBAAiB,gBAAgB;AACnC,WAAO,EAAE,MAAM,MAAM,IAAI,SAAS,KAAK,EAAE,KAAK,GAAG,UAAU,iBAAiB;AAAA,EAC9E;AACA,QAAM,IAAI,YAAY,8BAA8B;AACtD;;;ACvCO,IAAM,eAAN,MAAmB;AAAA,EACxB,YAA6B,QAAsB;AAAtB;AAAA,EAAuB;AAAA,EAEpD,OAAO,OAAO,QAA0E;AACtF,QAAK,OAAO,UAAU,YAAgB,OAAO,aAAa,SAAY;AACpE,YAAM,IAAI,YAAY,0CAA0C;AAAA,IAClE;AACA,UAAM,OAAO,IAAI,SAAS;AAC1B,QAAI,OAAO,UAAU,QAAW;AAC9B,YAAM,EAAE,MAAM,SAAS,IAAI,MAAM,aAAa,OAAO,KAAK;AAC1D,WAAK,IAAI,SAAS,MAAM,QAAQ;AAAA,IAClC,OAAO;AACL,WAAK,IAAI,aAAa,OAAO,QAAkB;AAAA,IACjD;AACA,QAAI,OAAO,WAAW,OAAW,MAAK,IAAI,UAAU,OAAO,MAAM;AACjE,QAAI,OAAO,aAAa,QAAW;AACjC,WAAK,IAAI,YAAY,KAAK,UAAU,OAAO,QAAQ,CAAC;AAAA,IACtD;AAIA,QAAI,OAAO,oBAAoB,QAAW;AACxC,WAAK,IAAI,oBAAoB,OAAO,OAAO,eAAe,CAAC;AAAA,IAC7D;AAOA,UAAM,MAAM,MAAM,KAAK,OAAO;AAAA,MAC5B;AAAA,MACA,EAAE,QAAQ,QAAQ,MAAM,MAAM,QAAQ,OAAO,OAAO;AAAA,MACpD,EAAE,SAAS,KAAK;AAAA,IAClB;AACA,QAAI,CAAC,IAAI,KAAM,OAAM,IAAI,YAAY,sBAAsB;AAC3D,WAAO,YAAY,IAAI,IAAI;AAAA,EAC7B;AAAA,EAEA,SAAS,QAA4C;AACnD,WAAO,aAAa,KAAK,OAAO,MAAM,CAAC;AAAA,EACzC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,OAAO,QAA8C;AACzD,QAAK,OAAO,UAAU,YAAgB,OAAO,aAAa,SAAY;AACpE,YAAM,IAAI,YAAY,0CAA0C;AAAA,IAClE;AACA,QAAI,OAAO,OAAO;AAClB,UAAM,aACJ,OAAO,iBACP,OAAO,kBACP,OAAO,YAAY;AAAA;AAAA;AAAA,IAIlB,OAAO,iBAAiB,UAAa,OAAO,iBAAiB,SAC7D,OAAO,gBAAgB,UAAa,OAAO,cAAc,KAC1D,OAAO,UAAU;AAInB,QAAI,SAAS,OAAW,QAAO;AAC/B,QAAI,cAAc,SAAS,SAAS;AAClC,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AACA,UAAM,OAAO,IAAI,SAAS;AAC1B,QAAI,OAAO,UAAU,QAAW;AAC9B,YAAM,EAAE,MAAM,SAAS,IAAI,MAAM,aAAa,OAAO,KAAK;AAC1D,WAAK,IAAI,SAAS,MAAM,QAAQ;AAAA,IAClC,OAAO;AACL,WAAK,IAAI,aAAa,OAAO,QAAkB;AAAA,IACjD;AACA,QAAI,OAAO,WAAW,OAAW,MAAK,IAAI,UAAU,OAAO,MAAM;AACjE,QAAI,OAAO,aAAa,QAAW;AACjC,WAAK,IAAI,YAAY,KAAK,UAAU,OAAO,QAAQ,CAAC;AAAA,IACtD;AACA,SAAK,IAAI,QAAQ,IAAI;AACrB,QAAI,OAAO,mBAAmB,QAAW;AACvC,WAAK,IAAI,mBAAmB,OAAO,OAAO,cAAc,CAAC;AAAA,IAC3D;AACA,QAAI,OAAO,kBAAkB,QAAW;AACtC,WAAK,IAAI,kBAAkB,OAAO,OAAO,aAAa,CAAC;AAAA,IACzD;AACA,QAAI,OAAO,iBAAiB,QAAW;AACrC,WAAK,IAAI,iBAAiB,OAAO,YAAY;AAAA,IAC/C;AACA,QAAI,OAAO,YAAY,QAAW;AAChC,WAAK,IAAI,WAAW,OAAO,OAAO,OAAO,CAAC;AAAA,IAC5C;AACA,QAAI,OAAO,gBAAgB,QAAW;AACpC,WAAK,IAAI,gBAAgB,OAAO,OAAO,WAAW,CAAC;AAAA,IACrD;AACA,QAAI,OAAO,UAAU,QAAW;AAC9B,WAAK,IAAI,SAAS,OAAO,OAAO,KAAK,CAAC;AAAA,IACxC;AAEA,QAAI,OAAO,oBAAoB,QAAW;AACxC,WAAK,IAAI,oBAAoB,OAAO,OAAO,eAAe,CAAC;AAAA,IAC7D;AACA,UAAM,MAAM,MAAM,KAAK,OAAO,QAAQ,sBAAsB;AAAA,MAC1D,QAAQ;AAAA,MACR,MAAM;AAAA,IACR,CAAC;AACD,WAAQ,MAAM,IAAI,KAAK;AAAA,EACzB;AACF;;;ACrHO,IAAM,YAAN,MAAgB;AAAA,EACrB,YAA6B,QAAsB;AAAtB;AAAA,EAAuB;AAAA,EAEpD,MAAM,OAAO,QAA2C;AACtD,UAAM,OAAO,IAAI,SAAS;AAC1B,SAAK,IAAI,UAAU,OAAO,MAAM;AAChC,SAAK,IAAI,YAAY,OAAO,OAAO,QAAQ,CAAC;AAC5C,QAAI,OAAO,gBAAgB,OAAW,MAAK,IAAI,gBAAgB,OAAO,WAAW;AACjF,UAAM,MAAM,MAAM,KAAK,OAAO,QAAQ,mBAAmB;AAAA,MACvD,QAAQ;AAAA,MACR,MAAM;AAAA,IACR,CAAC;AACD,WAAQ,MAAM,IAAI,KAAK;AAAA,EACzB;AAAA,EAEA,MAAM,SAAS,QAAyB,MAAwC;AAC9E,UAAM,OAAO,MAAM,KAAK,OAAO,MAAM;AACrC,WAAO,KAAK,OAAO,MAAM,KAAK,KAAK,SAAS,IAAI;AAAA,EAClD;AACF;;;ACjBO,IAAM,aAAN,MAAiB;AAAA,EACtB,YAA6B,QAAsB;AAAtB;AAAA,EAAuB;AAAA,EAEpD,MAAM,OAAO,QAA4C;AACvD,QAAK,OAAO,UAAU,YAAgB,OAAO,aAAa,SAAY;AACpE,YAAM,IAAI,YAAY,0CAA0C;AAAA,IAClE;AACA,UAAM,OAAO,IAAI,SAAS;AAC1B,QAAI,OAAO,UAAU,QAAW;AAC9B,YAAM,EAAE,MAAM,SAAS,IAAI,MAAM,aAAa,OAAO,KAAK;AAC1D,WAAK,IAAI,SAAS,MAAM,QAAQ;AAAA,IAClC,OAAO;AACL,WAAK,IAAI,aAAa,OAAO,QAAkB;AAAA,IACjD;AACA,QAAI,OAAO,WAAW,OAAW,MAAK,IAAI,UAAU,OAAO,MAAM;AACjE,QAAI,OAAO,aAAa,QAAW;AACjC,WAAK,IAAI,YAAY,KAAK,UAAU,OAAO,QAAQ,CAAC;AAAA,IACtD;AACA,QAAI,OAAO,gBAAgB,OAAW,MAAK,IAAI,gBAAgB,OAAO,WAAW;AACjF,UAAM,MAAM,MAAM,KAAK,OAAO,QAAQ,oBAAoB;AAAA,MACxD,QAAQ;AAAA,MACR,MAAM;AAAA,IACR,CAAC;AACD,WAAQ,MAAM,IAAI,KAAK;AAAA,EACzB;AAAA,EAEA,MAAM,SAAS,QAA0B,MAAwC;AAC/E,UAAM,OAAO,MAAM,KAAK,OAAO,MAAM;AACrC,WAAO,KAAK,OAAO,MAAM,KAAK,KAAK,SAAS,IAAI;AAAA,EAClD;AACF;;;AC3BO,IAAM,oBAAN,MAAwB;AAAA,EAC7B,YAA6B,QAAsB;AAAtB;AAAA,EAAuB;AAAA,EAEpD,MAAM,OAAO,QAAmD;AAC9D,QAAK,OAAO,UAAU,YAAgB,OAAO,aAAa,SAAY;AACpE,YAAM,IAAI,YAAY,0CAA0C;AAAA,IAClE;AACA,UAAM,OAAO,IAAI,SAAS;AAC1B,QAAI,OAAO,UAAU,QAAW;AAC9B,YAAM,EAAE,MAAM,SAAS,IAAI,MAAM,aAAa,OAAO,KAAK;AAC1D,WAAK,IAAI,SAAS,MAAM,QAAQ;AAAA,IAClC,OAAO;AACL,WAAK,IAAI,aAAa,OAAO,QAAkB;AAAA,IACjD;AACA,QAAI,OAAO,WAAW,OAAW,MAAK,IAAI,UAAU,OAAO,MAAM;AACjE,QAAI,OAAO,aAAa,QAAW;AACjC,WAAK,IAAI,YAAY,KAAK,UAAU,OAAO,QAAQ,CAAC;AAAA,IACtD;AAKA,QAAI,OAAO,sBAAsB,QAAW;AAC1C,WAAK,IAAI,uBAAuB,OAAO,OAAO,iBAAiB,CAAC;AAAA,IAClE;AACA,QAAI,OAAO,YAAY,OAAW,MAAK,IAAI,WAAW,OAAO,OAAO,OAAO,CAAC;AAC5E,QAAI,OAAO,mBAAmB,QAAW;AACvC,WAAK,IAAI,mBAAmB,OAAO,OAAO,cAAc,CAAC;AAAA,IAC3D;AACA,QAAI,OAAO,kBAAkB,QAAW;AACtC,WAAK,IAAI,kBAAkB,OAAO,OAAO,aAAa,CAAC;AAAA,IACzD;AACA,QAAI,OAAO,gBAAgB,QAAW;AACpC,WAAK,IAAI,gBAAgB,OAAO,OAAO,WAAW,CAAC;AAAA,IACrD;AAEA,QAAI,OAAO,oBAAoB,QAAW;AACxC,WAAK,IAAI,oBAAoB,OAAO,OAAO,eAAe,CAAC;AAAA,IAC7D;AACA,UAAM,MAAM,MAAM,KAAK,OAAO,QAAQ,4BAA4B;AAAA,MAChE,QAAQ;AAAA,MACR,MAAM;AAAA,IACR,CAAC;AACD,WAAQ,MAAM,IAAI,KAAK;AAAA,EACzB;AAAA,EAEA,MAAM,SAAS,QAAiC,MAA0C;AACxF,UAAM,OAAO,MAAM,KAAK,OAAO,MAAM;AACrC,WAAO,KAAK,OAAO,MAAM,KAAkB,KAAK,SAAS,IAAI;AAAA,EAC/D;AACF;;;ACnDO,IAAM,kBAAN,MAAsB;AAAA,EAC3B,YAA6B,QAAsB;AAAtB;AAAA,EAAuB;AAAA,EAEpD,MAAM,OAAO,QAAiD;AAC5D,QAAK,OAAO,UAAU,YAAgB,OAAO,aAAa,SAAY;AACpE,YAAM,IAAI,YAAY,0CAA0C;AAAA,IAClE;AACA,UAAM,OAAO,IAAI,SAAS;AAC1B,QAAI,OAAO,UAAU,QAAW;AAC9B,YAAM,EAAE,MAAM,SAAS,IAAI,MAAM,aAAa,OAAO,KAAK;AAC1D,WAAK,IAAI,SAAS,MAAM,QAAQ;AAAA,IAClC,OAAO;AACL,WAAK,IAAI,aAAa,OAAO,QAAkB;AAAA,IACjD;AACA,QAAI,OAAO,WAAW,OAAW,MAAK,IAAI,UAAU,OAAO,MAAM;AACjE,QAAI,OAAO,aAAa,QAAW;AACjC,WAAK,IAAI,YAAY,KAAK,UAAU,OAAO,QAAQ,CAAC;AAAA,IACtD;AACA,UAAM,MAAM,MAAM,KAAK,OAAO,QAAQ,0BAA0B;AAAA,MAC9D,QAAQ;AAAA,MACR,MAAM;AAAA,IACR,CAAC;AACD,WAAQ,MAAM,IAAI,KAAK;AAAA,EACzB;AAAA,EAEA,MAAM,SAAS,QAA+B,MAA0C;AACtF,UAAM,OAAO,MAAM,KAAK,OAAO,MAAM;AACrC,WAAO,KAAK,OAAO,MAAM,KAAkB,KAAK,SAAS,IAAI;AAAA,EAC/D;AACF;;;ACdA,eAAsB,eAAe,QAA4C;AAC/E,MAAK,OAAO,UAAU,YAAgB,OAAO,aAAa,SAAY;AACpE,UAAM,IAAI,YAAY,0CAA0C;AAAA,EAClE;AACA,QAAM,OAAO,IAAI,SAAS;AAC1B,MAAI,OAAO,UAAU,QAAW;AAC9B,UAAM,EAAE,MAAM,SAAS,IAAI,MAAM,aAAa,OAAO,KAAK;AAC1D,SAAK,IAAI,SAAS,MAAM,QAAQ;AAAA,EAClC,OAAO;AACL,SAAK,IAAI,aAAa,OAAO,QAAkB;AAAA,EACjD;AACA,MAAI,OAAO,gBAAgB,OAAW,MAAK,IAAI,gBAAgB,OAAO,WAAW;AACjF,MAAI,OAAO,cAAc,OAAW,MAAK,IAAI,cAAc,OAAO,SAAS;AAC3E,MAAI,OAAO,aAAa,QAAW;AACjC,SAAK,IAAI,YAAY,KAAK,UAAU,OAAO,QAAQ,CAAC;AAAA,EACtD;AACA,MAAI,OAAO,sBAAsB,QAAW;AAC1C,SAAK,IAAI,uBAAuB,OAAO,OAAO,iBAAiB,CAAC;AAAA,EAClE;AACA,MAAI,OAAO,mBAAmB,QAAW;AACvC,SAAK,IAAI,mBAAmB,OAAO,OAAO,cAAc,CAAC;AAAA,EAC3D;AACA,MAAI,OAAO,YAAY,OAAW,MAAK,IAAI,WAAW,OAAO,OAAO,OAAO,CAAC;AAC5E,MAAI,OAAO,iBAAiB,QAAW;AACrC,SAAK,IAAI,iBAAiB,OAAO,YAAY;AAAA,EAC/C;AACA,MAAI,OAAO,gBAAgB,QAAW;AACpC,SAAK,IAAI,gBAAgB,OAAO,OAAO,WAAW,CAAC;AAAA,EACrD;AACA,SAAO;AACT;;;AC9CO,IAAM,eAAN,MAAmB;AAAA,EACxB,YAA6B,QAAsB;AAAtB;AAAA,EAAuB;AAAA,EAEpD,MAAM,OAAO,QAA8C;AACzD,UAAM,MAAM,MAAM,KAAK,OAAO,QAAQ,sBAAsB;AAAA,MAC1D,QAAQ;AAAA,MACR,MAAM,MAAM,eAAe,MAAM;AAAA,IACnC,CAAC;AACD,WAAQ,MAAM,IAAI,KAAK;AAAA,EACzB;AAAA,EAEA,MAAM,SAAS,QAA4B,MAA0C;AACnF,UAAM,OAAO,MAAM,KAAK,OAAO,MAAM;AACrC,WAAO,KAAK,OAAO,MAAM,KAAkB,KAAK,SAAS,IAAI;AAAA,EAC/D;AACF;;;ACVO,IAAM,oBAAN,MAAwB;AAAA,EAC7B,YAA6B,QAAsB;AAAtB;AAAA,EAAuB;AAAA,EAEpD,MAAM,OAAO,QAAmD;AAC9D,UAAM,MAAM,MAAM,KAAK,OAAO,QAAQ,4BAA4B;AAAA,MAChE,QAAQ;AAAA,MACR,MAAM,MAAM,eAAe,MAAM;AAAA,IACnC,CAAC;AACD,WAAQ,MAAM,IAAI,KAAK;AAAA,EACzB;AAAA,EAEA,MAAM,SAAS,QAAiC,MAA0C;AACxF,UAAM,OAAO,MAAM,KAAK,OAAO,MAAM;AACrC,WAAO,KAAK,OAAO,MAAM,KAAkB,KAAK,SAAS,IAAI;AAAA,EAC/D;AACF;;;ACbO,IAAM,eAAN,MAAmB;AAAA,EACxB,YAA6B,QAAsB;AAAtB;AAAA,EAAuB;AAAA,EAEpD,MAAM,OAAO,QAA8C;AAGzD,QAAK,OAAO,UAAU,YAAgB,OAAO,aAAa,SAAY;AACpE,YAAM,IAAI,YAAY,0CAA0C;AAAA,IAClE;AACA,QAAK,OAAO,UAAU,YAAgB,OAAO,aAAa,SAAY;AACpE,YAAM,IAAI,YAAY,0CAA0C;AAAA,IAClE;AACA,UAAM,OAAO,IAAI,SAAS;AAC1B,QAAI,OAAO,UAAU,QAAW;AAC9B,YAAM,EAAE,MAAM,SAAS,IAAI,MAAM,aAAa,OAAO,KAAK;AAC1D,WAAK,IAAI,cAAc,MAAM,QAAQ;AAAA,IACvC,OAAO;AACL,WAAK,IAAI,aAAa,OAAO,QAAkB;AAAA,IACjD;AACA,QAAI,OAAO,UAAU,QAAW;AAC9B,YAAM,EAAE,MAAM,SAAS,IAAI,MAAM,aAAa,OAAO,KAAK;AAC1D,WAAK,IAAI,cAAc,MAAM,QAAQ;AAAA,IACvC,OAAO;AACL,WAAK,IAAI,aAAa,OAAO,QAAkB;AAAA,IACjD;AACA,UAAM,MAAM,MAAM,KAAK,OAAO,QAAQ,qBAAqB;AAAA,MACzD,QAAQ;AAAA,MACR,MAAM;AAAA,IACR,CAAC;AACD,WAAQ,MAAM,IAAI,KAAK;AAAA,EACzB;AAAA,EAEA,MAAM,SAAS,QAA4B,MAA4C;AACrF,UAAM,OAAO,MAAM,KAAK,OAAO,MAAM;AACrC,WAAO,KAAK,OAAO,MAAM,KAAoB,KAAK,SAAS,IAAI;AAAA,EACjE;AACF;;;AChCA,eAAsB,iBAAiB,QAA0C;AAC/E,MAAK,OAAO,UAAU,YAAgB,OAAO,aAAa,SAAY;AACpE,UAAM,IAAI,YAAY,0CAA0C;AAAA,EAClE;AACA,QAAM,OAAO,IAAI,SAAS;AAC1B,MAAI,OAAO,UAAU,QAAW;AAC9B,UAAM,EAAE,MAAM,SAAS,IAAI,MAAM,aAAa,OAAO,KAAK;AAC1D,SAAK,IAAI,SAAS,MAAM,QAAQ;AAAA,EAClC,OAAO;AACL,UAAM,MAAM,OAAO;AACnB,QAAI,CAAC,IAAI,YAAY,EAAE,WAAW,UAAU,GAAG;AAC7C,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AACA,SAAK,IAAI,aAAa,GAAG;AAAA,EAC3B;AACA,MAAI,OAAO,cAAc,QAAW;AAClC,SAAK,IAAI,aAAa,KAAK,UAAU,OAAO,SAAS,CAAC;AAAA,EACxD;AACA,MAAI,OAAO,YAAY,QAAW;AAChC,SAAK,IAAI,WAAW,OAAO,OAAO,OAAO,CAAC;AAAA,EAC5C;AACA,SAAO;AACT;AAIO,IAAM,UAAN,MAAc;AAAA,EACnB,YAA6B,QAAsB;AAAtB;AAAA,EAAuB;AAAA,EAEpD,MAAM,OAAO,QAAyC;AACpD,UAAM,MAAM,MAAM,KAAK,OAAO,QAAQ,eAAe;AAAA,MACnD,QAAQ;AAAA,MACR,MAAM,MAAM,iBAAiB,MAAM;AAAA,IACrC,CAAC;AACD,WAAQ,MAAM,IAAI,KAAK;AAAA,EACzB;AAAA,EAEA,MAAM,SAAS,QAAuB,MAA4C;AAChF,UAAM,OAAO,MAAM,KAAK,OAAO,MAAM;AACrC,WAAO,KAAK,OAAO,MAAM,KAAoB,KAAK,SAAS,IAAI;AAAA,EACjE;AACF;;;ACnCO,IAAM,gBAAN,MAAoB;AAAA,EACzB,YAA6B,QAAsB;AAAtB;AAAA,EAAuB;AAAA,EAEpD,MAAM,OAAO,QAA+C;AAC1D,QAAK,OAAO,UAAU,YAAgB,OAAO,aAAa,SAAY;AACpE,YAAM,IAAI,YAAY,0CAA0C;AAAA,IAClE;AACA,UAAM,OAAO,IAAI,SAAS;AAC1B,QAAI,OAAO,UAAU,QAAW;AAC9B,YAAM,EAAE,MAAM,SAAS,IAAI,MAAM,aAAa,OAAO,KAAK;AAC1D,WAAK,IAAI,SAAS,MAAM,QAAQ;AAAA,IAClC,OAAO;AACL,WAAK,IAAI,aAAa,OAAO,QAAkB;AAAA,IACjD;AACA,QAAI,OAAO,WAAW,OAAW,MAAK,IAAI,UAAU,OAAO,MAAM;AACjE,QAAI,OAAO,gBAAgB,QAAW;AACpC,WAAK,IAAI,gBAAgB,OAAO,OAAO,WAAW,CAAC;AAAA,IACrD;AACA,UAAM,MAAM,MAAM,KAAK,OAAO,QAAQ,sBAAsB;AAAA,MAC1D,QAAQ;AAAA,MACR,MAAM;AAAA,IACR,CAAC;AACD,WAAQ,MAAM,IAAI,KAAK;AAAA,EACzB;AAAA,EAEA,MAAM,QACJ,QACA,MAC8B;AAC9B,UAAM,OAAO,MAAM,KAAK,OAAO,MAAM;AACrC,WAAO,KAAK,OAAO,MAAM,KAA0B,KAAK,SAAS,IAAI;AAAA,EACvE;AACF;;;ACxDO,IAAM,UAAU;;;ACkCvB,IAAM,mBAAmB;AAOlB,IAAM,sBAAsB;AAG5B,IAAM,qBAAqB;AAE3B,IAAM,eAAN,MAAmB;AAAA,EAqBxB,YAAY,UAA+B,CAAC,GAAG;AAC7C,UAAM,SACJ,OAAO,YAAY,cAAc,QAAQ,KAAK,iBAAiB;AACjE,UAAM,SAAS,QAAQ,UAAU;AACjC,QAAI,CAAC,QAAQ;AACX,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AACA,SAAK,SAAS;AACd,SAAK,WAAW,QAAQ,WAAW,kBAAkB,QAAQ,QAAQ,EAAE;AACvE,SAAK,WAAW,QAAQ,SAAS,WAAW,OAAO,KAAK,UAAU;AAClE,SAAK,UAAU,QAAQ,WAAW;AAClC,SAAK,aAAa,QAAQ,cAAc;AACxC,SAAK,gBAAgB,QAAQ,iBAAiB;AAC9C,SAAK,UAAU,IAAI,QAAQ,IAAI;AAC/B,SAAK,QAAQ,IAAI,MAAM,IAAI;AAC3B,SAAK,cAAc,IAAI,YAAY,IAAI;AACvC,SAAK,eAAe,IAAI,aAAa,IAAI;AACzC,SAAK,YAAY,IAAI,UAAU,IAAI;AACnC,SAAK,aAAa,IAAI,WAAW,IAAI;AACrC,SAAK,oBAAoB,IAAI,kBAAkB,IAAI;AACnD,SAAK,kBAAkB,IAAI,gBAAgB,IAAI;AAC/C,SAAK,eAAe,IAAI,aAAa,IAAI;AACzC,SAAK,oBAAoB,IAAI,kBAAkB,IAAI;AACnD,SAAK,eAAe,IAAI,aAAa,IAAI;AACzC,SAAK,UAAU,IAAI,QAAQ,IAAI;AAC/B,SAAK,gBAAgB,IAAI,cAAc,IAAI;AAAA,EAC7C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,QACJ,MACA,OAAoB,CAAC,GACrB,OAAoC,CAAC,GAClB;AACnB,UAAM,UAAU,IAAI,QAAQ,KAAK,OAAO;AACxC,YAAQ,IAAI,iBAAiB,UAAU,KAAK,MAAM,EAAE;AACpD,YAAQ,IAAI,mBAAmB,KAAK,UAAU;AAC9C,YAAQ,IAAI,2BAA2B,KAAK,aAAa;AACzD,UAAM,UAAU,KAAK,YAAY,SAAY,KAAK,UAAU,KAAK;AAIjE,UAAM,aAAa,KAAK,UAAU,QAAQ,YAAY;AACtD,UAAM,SAAS,KAAK,WAAW,YAAY,OAAO,SAAY,YAAY,QAAQ,OAAO;AACzF,QAAI;AACF,YAAM,MAAM,MAAM,KAAK,QAAQ,GAAG,KAAK,OAAO,GAAG,IAAI,IAAI,EAAE,GAAG,MAAM,SAAS,OAAO,CAAC;AACrF,UAAI,CAAC,IAAI,GAAI,OAAM,MAAM,kBAAkB,GAAG;AAC9C,aAAO;AAAA,IACT,SAAS,KAAK;AACZ,UAAI,cAAc,qBAAqB,GAAG,GAAG;AAC3C,cAAM,IAAI,oBAAoB,cAAc,IAAI,oBAAoB,OAAO,IAAI;AAAA,MACjF;AACA,YAAM;AAAA,IACR;AAAA,EACF;AACF;;;AC3HA,eAAsB,SACpB,OACA,UAAmC,WAAW,OAC9C,UAAkB,oBACG;AACrB,QAAM,MAAM,OAAO,UAAU,WAAW,QAAQ,OAAO;AACvD,MAAI,CAAC,KAAK;AACR,UAAM,IAAI,YAAY,sBAAsB;AAAA,EAC9C;AACA,MAAI;AACJ,MAAI;AACF,UAAM,MAAM,QAAQ,KAAK,EAAE,QAAQ,YAAY,QAAQ,OAAO,EAAE,CAAC;AAAA,EACnE,SAAS,KAAK;AACZ,QAAI,qBAAqB,GAAG,GAAG;AAC7B,YAAM,IAAI,oBAAoB,eAAe,GAAG,oBAAoB,OAAO,IAAI;AAAA,IACjF;AACA,UAAM;AAAA,EACR;AACA,MAAI,CAAC,IAAI,IAAI;AACX,UAAM,IAAI,YAAY,yBAAyB,IAAI,MAAM,EAAE;AAAA,EAC7D;AACA,SAAO,IAAI,WAAW,MAAM,IAAI,YAAY,CAAC;AAC/C;;;AC4LO,SAAS,kBAAkB,OAA8C;AAC9E,SAAO,MAAM,SAAS,iBAAkB,MAA0B,gBAAgB;AACpF;AAEO,SAAS,aAAa,OAAyC;AACpE,SAAO,MAAM,SAAS;AACxB;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../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/audioDucking.ts","../src/resources/dubbing.ts","../src/resources/videoAnalysis.ts","../src/version.ts","../src/client.ts","../src/download.ts","../src/types.ts"],"sourcesContent":["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 * a non-m4a `outputFormat`, `variantsNum` above 1, and `stems`.\n * `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 if (params.variantsNum !== undefined) {\n form.set(\"variants_num\", String(params.variantsNum));\n }\n if (params.stems !== undefined) {\n form.set(\"stems\", String(params.stems));\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 // A generation-time knob, valid on the plain stream as well as async —\n // unlike the finalize-time params, which submit() alone sends. The\n // explicit undefined check matters: 0 is a meaningful value.\n if (params.promptInfluence !== undefined) {\n form.set(\"prompt_influence\", String(params.promptInfluence));\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`, a non-m4a `outputFormat`,\n * `variantsNum` above 1, and `stems` — the backend rejects all of these on\n * the plain 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 // Any non-m4a container is a finalize-time transcode, so it needs\n // async. Checking != \"m4a\" rather than == \"wav\" keeps this correct\n // as formats are added (mp3 landed after the original check).\n (params.outputFormat !== undefined && params.outputFormat !== \"m4a\") ||\n (params.variantsNum !== undefined && params.variantsNum > 1) ||\n params.stems !== undefined;\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/stems/outputFormat other than \"m4a\"/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 if (params.stems !== undefined) {\n form.set(\"stems\", String(params.stems));\n }\n // Explicit undefined check: 0 is a meaningful value and must go out.\n if (params.promptInfluence !== undefined) {\n form.set(\"prompt_influence\", String(params.promptInfluence));\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.segments !== undefined) {\n form.set(\"segments\", JSON.stringify(params.segments));\n }\n // Omitted when unset rather than sent with a default, so the server's own\n // default decides — `ducking` and `keepOriginalSound` are both default-OFF\n // server-side today, and neither is hardcoded here (same rule as\n // buildSoundForm's).\n if (params.keepOriginalSound !== undefined) {\n form.set(\"keep_original_sound\", String(params.keepOriginalSound));\n }\n if (params.ducking !== undefined) form.set(\"ducking\", String(params.ducking));\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 // Explicit undefined check: 0 is a meaningful value and must go out.\n if (params.promptInfluence !== undefined) {\n form.set(\"prompt_influence\", String(params.promptInfluence));\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, VideoToVideoSoundParams } from \"../types.js\";\n\n/** The widest shape either endpoint can send. Neither public param type can\n * serve as the parameter here, because the two now differ in opposite\n * directions: `outputFormat` exists only on `VideoToSoundParams` (audio),\n * while `keepOriginalSound` is video-only and is therefore typed `never` on\n * `VideoToSoundParams`. That makes each public type unassignable to the other,\n * so the shared builder takes their union and each endpoint's own param type\n * stays the thing that rejects the wrong field at compile time. */\ntype SoundFormParams = VideoToVideoSoundParams & Pick<VideoToSoundParams, \"outputFormat\">;\n\n/** Build the multipart body shared by /v1/video-to-sound and\n * /v1/video-to-video-sound. The two differ only in the path they POST to and\n * in the two endpoint-specific fields described on `SoundFormParams`.\n *\n * Every optional field is omitted when unset rather than sent with a default,\n * so the server's own default decides. `ducking` and `keepOriginalSound` are\n * both default-OFF server-side today, but neither is hardcoded here — pinning\n * either one on the wire is what would have to change the next time a server\n * default moves, and this builder deliberately does not. */\nexport async function buildSoundForm(params: SoundFormParams): 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.keepOriginalSound !== undefined) {\n form.set(\"keep_original_sound\", String(params.keepOriginalSound));\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.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 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 {\n SfxTask,\n SoundResult,\n VideoToVideoSoundParams,\n WaitOptions,\n} 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: VideoToVideoSoundParams): 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: VideoToVideoSoundParams, 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 { AudioDuckingParams, DuckingResult, SfxTask, WaitOptions } from \"../types.js\";\n\n/** Duck an existing music bed under a voice track. Async only (202 + poll).\n *\n * Both inputs are user-supplied — nothing is generated here. The voice may be\n * audio OR a video: the backend extracts a video's audio track, ducks the\n * music under it, and re-muxes the ducked mix back into a new video (the\n * result's `output_type` announces which came back). The music must be audio —\n * the backend never probes it for a video stream, so a video there would be\n * silently mishandled. */\nexport class AudioDucking {\n constructor(private readonly client: SoniloClient) {}\n\n async submit(params: AudioDuckingParams): Promise<SfxTask> {\n // Both pairs are validated before any upload I/O, so a missing music\n // input is reported even when the voice side alone looks fine.\n if ((params.voice === undefined) === (params.voiceUrl === undefined)) {\n throw new SoniloError(\"Provide exactly one of voice or voiceUrl\");\n }\n if ((params.music === undefined) === (params.musicUrl === undefined)) {\n throw new SoniloError(\"Provide exactly one of music or musicUrl\");\n }\n const form = new FormData();\n if (params.voice !== undefined) {\n const { blob, filename } = await toUploadBlob(params.voice);\n form.set(\"voice_file\", blob, filename);\n } else {\n form.set(\"voice_url\", params.voiceUrl as string);\n }\n if (params.music !== undefined) {\n const { blob, filename } = await toUploadBlob(params.music);\n form.set(\"music_file\", blob, filename);\n } else {\n form.set(\"music_url\", params.musicUrl as string);\n }\n const res = await this.client.request(\"/v1/audio-ducking\", {\n method: \"POST\",\n body: form,\n });\n return (await res.json()) as SfxTask;\n }\n\n async generate(params: AudioDuckingParams, opts?: WaitOptions): Promise<DuckingResult> {\n const task = await this.submit(params);\n return this.client.tasks.wait<DuckingResult>(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","import type { SoniloClient } from \"../client.js\";\nimport { SoniloError } from \"../errors.js\";\nimport { toUploadBlob } from \"../upload.js\";\nimport type {\n SfxTask,\n VideoAnalysisParams,\n VideoAnalysisResult,\n WaitOptions,\n} from \"../types.js\";\n\n/** Analyze a video and get back a creative brief for scoring it. Async only.\n *\n * This endpoint generates nothing — no audio, no video, no artifact to\n * download. The result is the work order: `segments` (a time-aligned section\n * plan) plus one `prompt` per requested variation, each ready to hand\n * straight to videoToMusic, videoToSfx, videoToSound or their\n * video-to-video counterparts.\n *\n * The method is `analyze`, not `generate`, for that reason: every other\n * resource's `generate` returns something you download, and this one never\n * does.\n *\n * The 1-5 bound on `variantsNum` and the 2000-character bound on `prompt`\n * are deliberately not checked here — the backend owns them, and a hardcoded\n * copy would make this SDK reject values a later API widens. */\nexport class VideoAnalysis {\n constructor(private readonly client: SoniloClient) {}\n\n async submit(params: VideoAnalysisParams): 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.variantsNum !== undefined) {\n form.set(\"variants_num\", String(params.variantsNum));\n }\n const res = await this.client.request(\"/v1/video-analysis\", {\n method: \"POST\",\n body: form,\n });\n return (await res.json()) as SfxTask;\n }\n\n async analyze(\n params: VideoAnalysisParams,\n opts?: WaitOptions,\n ): Promise<VideoAnalysisResult> {\n const task = await this.submit(params);\n return this.client.tasks.wait<VideoAnalysisResult>(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.16.1\";\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 { AudioDucking } from \"./resources/audioDucking.js\";\nimport { Dubbing } from \"./resources/dubbing.js\";\nimport { VideoAnalysis } from \"./resources/videoAnalysis.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 audioDucking: AudioDucking;\n readonly dubbing: Dubbing;\n readonly videoAnalysis: VideoAnalysis;\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.audioDucking = new AudioDucking(this);\n this.dubbing = new Dubbing(this);\n this.videoAnalysis = new VideoAnalysis(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 by any\n * `outputFormat` other than the m4a default). */\n mode?: \"stream\" | \"async\";\n /** Container for the async result. `wav` and `mp3` (320 kbps) are\n * finalize-time transcodes and require `mode: \"async\"`; m4a is what the\n * stream itself carries. Defaults to m4a server-side. */\n outputFormat?: \"m4a\" | \"wav\" | \"mp3\";\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 /** Also split the generated track into four separated stems — `drums`,\n * `bass`, `vocals`, `other` — delivered on the task result's `stems`\n * array. Free of charge. Requires `mode: \"async\"` (the backend rejects it\n * on the plain stream with a 400), so it is only meaningful via\n * `submit()`; `stream()`/`generate()` never send it. Separation runs after\n * generation and typically adds 2-6 minutes to the wait (it gives up after\n * 30), so raise `tasks.wait`'s `timeout` accordingly. See `StemsEntry` for\n * the result shape, and `MusicTaskResult.stems_error` for how failures are\n * reported. */\n stems?: boolean;\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` and `mp3` (320 kbps) are\n * finalize-time transcodes and require async. Defaults to m4a. */\n outputFormat?: \"m4a\" | \"wav\" | \"mp3\";\n /** Duck the generated music under the source voice at finalize time.\n * Default-OFF server-side: leave unset to skip it, pass `true` to run it,\n * which adds a `ducked` track alongside the unchanged clean `audio`. Free,\n * 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 /** How strongly the generated music follows the prompt (0-1, API default\n * 0.5). Lower values let the video lead; higher values follow the prompt\n * more literally. Free of charge. A generation-time knob, not a\n * finalize-time one, so it works on the plain stream as well as async —\n * no `mode` gating. Omitted from the wire when unset so the server\n * default applies; `0` is a meaningful value and is sent. Out-of-range\n * values are rejected server-side with a 422. */\n promptInfluence?: number;\n /** Also split the generated music into four separated stems — `drums`,\n * `bass`, `vocals`, `other` — delivered on the task result's `stems`\n * array. It splits the GENERATED music, never the source video's own\n * audio. Free of charge. Requires `mode: \"async\"` (auto-selected by\n * `submit()`; the backend rejects it on the plain stream with a 400), so\n * it is only meaningful via `submit()` — `stream()`/`generate()` never\n * send it. Separation runs after generation and typically adds 2-6\n * minutes to the wait (it gives up after 30), so raise `tasks.wait`'s\n * `timeout` accordingly. See `StemsEntry` for the result shape, and\n * `MusicTaskResult.stems_error` for how failures are reported. */\n stems?: 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 /** 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/** The four separated stems of one generated stream, present when the\n * request set `stems: true`. Each stem is an ordinary media object\n * (`url` / `content_type` / `file_size`), so any of them can be passed to\n * `download()`. The stems normally follow the request's `outputFormat`;\n * each stem's own `content_type` reports what was actually delivered. */\nexport interface StemsEntry {\n /** Which `audio` entry this stems set belongs to. Match on this field,\n * never on array position — `stems` carries only the streams that\n * separated successfully, so it can be shorter than `audio`. */\n stream_index: number;\n drums: SfxMedia;\n bass: SfxMedia;\n vocals: SfxMedia;\n other: SfxMedia;\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 /** Separated stems, one entry per stream that separated successfully;\n * only appears when the request set `stems: true`. Look entries up by\n * `stream_index`, never by array position — the array can be shorter than\n * `audio` when separation failed for some streams (see `stems_error`). */\n stems?: StemsEntry[];\n /** Why stem separation failed wholly or in part, or was skipped. It can\n * appear ALONGSIDE a partial `stems` array, so never treat its presence as\n * \"no stems\" — check `stems` itself for what did arrive. Independent of\n * the task's own `status`/`error`: the generation is intact either way. */\n stems_error?: string;\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\n/** Params for `videoToVideoMusic`.\n *\n * The delivered video's audio is decided by two independent knobs:\n * `keepOriginalSound` picks the **voice source**, `ducking` picks how that\n * voice and the generated music are **combined**.\n *\n * | Request | Audio in the returned video |\n * | --- | --- |\n * | neither set | generated music only — the source's own audio is removed |\n * | `keepOriginalSound: true` | full original sound + static music mix |\n * | `keepOriginalSound: true, ducking: true` | full original sound + music ducked under it |\n * | `preserveSpeech: true` | static vocal-forward mix of vocals + music |\n * | `preserveSpeech: true, ducking: true` | isolated vocals + music ducked under them |\n *\n * `keepOriginalSound` supersedes `preserveSpeech` — the voice source is a\n * single choice, and keeping the whole track subsumes keeping only the\n * isolated speech. No combination is rejected.\n *\n * The source picture is copied without re-encoding, so the input must carry\n * H.264, H.265/HEVC, VP9 or AV1 video in an mp4, mov, m4v or webm container —\n * animated gif and VP8 webm are rejected. Maximum input duration is 360\n * seconds. */\nexport interface VideoToVideoMusicParams {\n video?: VideoInput;\n videoUrl?: string;\n prompt?: string;\n /** How the music should develop over time. Same shape as\n * `videoToMusic`'s: the first `start` must be 0. Supplying these skips the\n * prompt-service plan the server would otherwise derive from `prompt`. */\n segments?: Segment[];\n /** Keep the source video's whole original audio track in the result, with\n * the generated music combined under it. Defaults to `false`, so by\n * default the returned video's audio is the generated music ALONE and the\n * source's own audio is removed. Supersedes `preserveSpeech`. */\n keepOriginalSound?: boolean;\n /** How the voice and the generated music are combined — not whether a\n * voice is kept. Default-OFF server-side: leave unset for a static\n * voice-forward mix at a fixed offset, pass `true` for the dynamic duck\n * (music dips only while the voice is present). Has no effect when there\n * is no voice source, i.e. neither `keepOriginalSound` nor `preserveSpeech`\n * is set. Free and best-effort; silently falls back to\n * generated-audio-only if the source has no usable audio track, voice\n * isolation fails, or the mix fails. */\n ducking?: boolean;\n /** Keep only the source's isolated speech (not the whole track) in the\n * output. Both this and the legacy `isolateVocals` are accepted and OR'd\n * server-side. Superseded by `keepOriginalSound`. */\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 /** How strongly the generated music follows the prompt (0-1, API default\n * 0.5). Lower values let the video lead; higher values follow the prompt\n * more literally. Free of charge. Omitted from the wire when unset so the\n * server default applies; `0` is a meaningful value and is sent.\n * Out-of-range values are rejected server-side with a 422. */\n promptInfluence?: number;\n}\n\nexport interface VideoToVideoSfxParams {\n video?: VideoInput;\n videoUrl?: string;\n prompt?: string;\n segments?: SfxSegment[];\n}\n\n/** Params for `videoToVideoSound`, and the base every `videoToSound` param\n * also has. The two endpoints differ in exactly two fields, one in each\n * direction, and both are enforced at the type level rather than left to the\n * server to silently ignore:\n *\n * - `outputFormat` is **audio-only** — added by `VideoToSoundParams` below, so\n * it simply does not exist on this type.\n * - `keepOriginalSound` is **video-only** — declared here, so\n * `VideoToSoundParams` inherits it and has to forbid it explicitly with\n * `?: never` (the inheritance runs the other way, so it cannot just be\n * omitted the way `outputFormat` is).\n *\n * Passing either field to the wrong endpoint is therefore a compile error. */\nexport interface VideoToVideoSoundParams {\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 video's whole original audio track in the result, with\n * the generated music + SFX combined under it. Defaults to `false`, so by\n * default the returned video's audio is the generated music and sound\n * effects ALONE and the source's own audio is removed — and the result\n * carries no `music_processed` stem, since with no voice source there is no\n * processed track. Supersedes `preserveSpeech`. Video endpoint only. */\n keepOriginalSound?: boolean;\n /** Keep only the source's isolated speech (not the whole track) in the\n * result. Superseded by `keepOriginalSound`. */\n preserveSpeech?: boolean;\n /** On `videoToVideoSound`, how the voice and the generated bed are\n * combined — not whether a voice is kept: default-OFF server-side, so an\n * unset value gives a static voice-forward mix and `true` gives the dynamic\n * duck, and either way it has no effect without a voice source.\n *\n * On `videoToSound` it decides BOTH, because that endpoint has no\n * `keepOriginalSound`: unset means the source's own speech is left out of\n * the deliverable entirely, and `true` is what pulls the original track in\n * and ducks the bed under it. Pass `preserveSpeech` instead to bring in the\n * isolated vocals rather than the whole track. */\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/** Params for `videoToSound`. Everything `videoToVideoSound` takes, plus the\n * delivery container for the combined track. */\nexport interface VideoToSoundParams extends VideoToVideoSoundParams {\n /** Container for the combined music + SFX track. Defaults to `wav`;\n * `mp3` is 320 kbps. Applies to the combined output only — the `music`\n * and `sfx` stems keep their native formats. Not available on\n * `videoToVideoSound`, which always returns an mp4. */\n outputFormat?: \"wav\" | \"m4a\" | \"mp3\";\n /** Not available on this endpoint. `keepOriginalSound` only means something\n * when the deliverable is a video whose own audio could be preserved;\n * `videoToSound` returns generated audio, and reaches the original track\n * through `ducking: true` instead. Typed `never` so passing it is a compile\n * error rather than a field the server silently drops — the mirror of how\n * `outputFormat` is kept off `videoToVideoSound`. */\n keepOriginalSound?: never;\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/** Params for `audioDucking`: mix an existing music bed under an existing\n * voice track, ducking the music wherever the voice speaks. Exactly one of\n * `voice`/`voiceUrl` and exactly one of `music`/`musicUrl`; a local input and\n * a URL may be mixed across the two.\n *\n * The voice may be audio or video (`VideoInput` is the SDK's generic media\n * input union) — a video's own audio track becomes the voice, and the ducked\n * mix is re-muxed back into a new video. The music must be audio: the backend\n * never probes it for a video stream, so a video there would be silently\n * mishandled. Each input is capped at 360 seconds server-side. */\nexport interface AudioDuckingParams {\n voice?: VideoInput;\n voiceUrl?: string;\n music?: VideoInput;\n musicUrl?: string;\n}\n\n/** Result of an `audioDucking` task (`tasks.get`) or its final state\n * (`generate`). Same flat envelope as `SoundResult`, but a ducking task\n * renders exactly one artifact and no stems: a `.wav` (`output_type`\n * \"audio\"), or a `.mp4` with the ducked mix re-muxed in (`output_type`\n * \"video\") when the voice input was a video. Pass `output_url` to\n * `download()`. */\nexport interface DuckingResult extends BaseTaskResult {\n output_url?: string;\n output_type?: \"audio\" | \"video\";\n output_bytes?: number;\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 * Duck the background music/effects bed under the dubbed voice. Default\n * OFF server-side, like every other endpoint's `ducking`: the bed is\n * 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\nexport interface VideoAnalysisParams {\n /** Exactly one of `video` / `videoUrl`. */\n video?: VideoInput;\n /** Exactly one of `video` / `videoUrl`. */\n videoUrl?: string;\n /** Optional guidance for the analysis, at most 2000 characters. */\n prompt?: string;\n /**\n * How many independent creative briefs to author for the same video\n * (1-5, default 1). Billed per brief.\n */\n variantsNum?: number;\n}\n\n/** One time-aligned section of the analyzed video, with the scoring\n * direction for that stretch. Bounds are whole seconds — the backend\n * truncates any fractional upstream bound before it reaches the envelope. */\nexport interface AnalysisSegment {\n start: number;\n end: number;\n /** The backend always emits one, defaulting to the string `\"none\"`. */\n label: string;\n prompt: string;\n}\n\n/** One independent creative brief for the whole video. Only the generation\n * prompt is public — the upstream's title/summary/tags are internal display\n * copy the API deliberately does not resell. */\nexport interface AnalysisVariation {\n prompt: string;\n}\n\n/**\n * The only Sonilo result with no media artifact at all: video-analysis\n * generates nothing and there is nothing to download. The payload is the\n * work order — `segments` for a time-aligned plan, and one `prompt` per\n * requested variation, each ready to pass to videoToMusic, videoToSfx,\n * videoToSound or their video-to-video counterparts.\n *\n * Both lists are optional because a `processing` or `failed` poll carries\n * neither.\n */\nexport interface VideoAnalysisResult extends BaseTaskResult {\n segments?: AnalysisSegment[];\n variations?: AnalysisVariation[];\n duration_seconds?: number;\n}\n"],"mappings":"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","names":[]}
|