sonilo 0.6.0 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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/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} from \"./errors.js\";\nexport { download } from \"./download.js\";\nexport { VERSION } from \"./version.js\";\nexport type {\n AccountServices,\n AudioChunkEvent,\n BaseTaskResult,\n CompleteEvent,\n CostEvent,\n CostInfo,\n DailyUsage,\n ErrorEvent,\n MusicMediaEntry,\n MusicMuxEntry,\n MusicTaskResult,\n MusicTitle,\n Segment,\n SegmentLabel,\n SfxAudioFormat,\n SfxError,\n SfxMedia,\n SfxResult,\n SfxSegment,\n SfxTask,\n SoundResult,\n StreamEvent,\n TextToMusicParams,\n TextToSfxParams,\n TitleEvent,\n Track,\n TrialQuota,\n UnknownEvent,\n UsageResponse,\n UsageSummary,\n VideoInput,\n VideoResult,\n VideoToMusicParams,\n VideoToSfxParams,\n VideoToSoundParams,\n VideoToVideoMusicParams,\n VideoToVideoSfxParams,\n WaitOptions,\n} from \"./types.js\";\nexport { isAudioChunkEvent, isErrorEvent } from \"./types.js\";\n","export class SoniloError extends Error {\n constructor(message: string) {\n super(message);\n this.name = new.target.name;\n }\n}\n\nexport class APIError extends SoniloError {\n readonly status: number;\n readonly body: unknown;\n /** The API's typed error code (e.g. \"rate_limit_exceeded\"), distinct from the HTTP status. */\n readonly code?: string;\n /** Per-field validation details, present on a 422. */\n readonly errors?: unknown[];\n\n constructor(message: string, status: number, body?: unknown) {\n super(message);\n this.status = status;\n this.body = body;\n const parsed = body as { code?: unknown; errors?: unknown } | undefined;\n this.code = typeof parsed?.code === \"string\" ? parsed.code : undefined;\n this.errors = Array.isArray(parsed?.errors) ? parsed.errors : undefined;\n }\n}\n\nexport class AuthenticationError extends APIError {}\n\nexport class PaymentRequiredError extends APIError {}\n\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 return new PaymentRequiredError(message, res.status, body);\n case 429: {\n const ra = res.headers.get(\"retry-after\");\n const retryAfter = ra !== null && ra !== \"\" && !Number.isNaN(Number(ra)) ? Number(ra) : undefined;\n return new RateLimitError(message, res.status, body, retryAfter);\n }\n case 400:\n case 413:\n case 422:\n return new BadRequestError(message, res.status, body);\n default:\n return new APIError(message, res.status, body);\n }\n}\n","import type { SoniloClient } from \"../client.js\";\nimport type { AccountServices, UsageResponse } from \"../types.js\";\n\nexport class Account {\n constructor(private readonly client: SoniloClient) {}\n\n async services(): Promise<AccountServices> {\n const res = await this.client.request(\"/v1/account/services\");\n return (await res.json()) as AccountServices;\n }\n\n async usage(params: { days?: number } = {}): Promise<UsageResponse> {\n const query = params.days !== undefined ? `?days=${params.days}` : \"\";\n const res = await this.client.request(`/v1/account/usage${query}`);\n return (await res.json()) as UsageResponse;\n }\n}\n","import type { SoniloClient } from \"../client.js\";\nimport { SoniloError, TaskFailedError, TaskTimeoutError } from \"../errors.js\";\nimport type { BaseTaskResult, SfxResult, WaitOptions } from \"../types.js\";\n\nexport const DEFAULT_POLL_INTERVAL_MS = 2000;\nexport const DEFAULT_WAIT_TIMEOUT_MS = 600_000;\n\nconst sleep = (ms: number) => new Promise<void>((resolve) => setTimeout(resolve, ms));\n\n/** A negative delay is clamped to 0 by setTimeout, which would turn the poll\n * loop into a busy loop hammering the API until the deadline. */\nfunction validateWaitArgs(pollInterval: number, timeout: number): void {\n if (pollInterval < 0) {\n throw new SoniloError(`pollInterval must be >= 0, got ${pollInterval}`);\n }\n if (timeout < 0) {\n throw new SoniloError(`timeout must be >= 0, got ${timeout}`);\n }\n}\n\nexport class Tasks {\n constructor(private readonly client: SoniloClient) {}\n\n /**\n * Fetch current task state. Never throws on a failed status.\n *\n * Generic over the result shape so callers can request the endpoint-\n * specific type, e.g. `client.tasks.get<MusicTaskResult>(taskId)`.\n * Defaults to `SfxResult` for back-compat.\n */\n async get<T extends BaseTaskResult = SfxResult>(taskId: string): Promise<T> {\n const res = await this.client.request(`/v1/tasks/${encodeURIComponent(taskId)}`);\n return (await res.json()) as T;\n }\n\n /**\n * Poll until the task is terminal; throw on failure or deadline.\n *\n * Generic over the result shape, e.g.\n * `client.tasks.wait<MusicTaskResult>(taskId)`. Defaults to `SfxResult`\n * for back-compat.\n */\n async wait<T extends BaseTaskResult = SfxResult>(\n taskId: string,\n opts: WaitOptions = {},\n ): Promise<T> {\n const pollInterval = opts.pollInterval ?? DEFAULT_POLL_INTERVAL_MS;\n const timeout = opts.timeout ?? DEFAULT_WAIT_TIMEOUT_MS;\n validateWaitArgs(pollInterval, timeout);\n const deadline = performance.now() + timeout;\n for (;;) {\n const result = await this.get<T>(taskId);\n if (result.status === \"succeeded\") return result;\n if (result.status === \"failed\") {\n const message = result.error?.message || \"Generation failed\";\n throw new TaskFailedError(`Task ${taskId} failed: ${message}`, {\n code: result.error?.code,\n taskId,\n refunded: result.refunded,\n });\n }\n const remaining = deadline - performance.now();\n if (remaining <= 0) {\n throw new TaskTimeoutError(\n `Task ${taskId} still processing after ${timeout}ms; ` +\n \"it may finish later — resume with tasks.wait or tasks.get\",\n taskId,\n );\n }\n await sleep(Math.min(pollInterval, remaining));\n }\n }\n}\n","import { GenerationError } from \"./errors.js\";\nimport type { CostInfo, StreamEvent, Track } from \"./types.js\";\n\nexport function decodeBase64(b64: string): Uint8Array {\n const bin = atob(b64);\n const out = new Uint8Array(bin.length);\n for (let i = 0; i < bin.length; i++) out[i] = bin.charCodeAt(i);\n return out;\n}\n\n/** Returns `null` for a valid-JSON-but-non-object line (e.g. a bare `null`\n * or a number/string), which carries no event `type` and is skipped like any\n * other junk line rather than crashing on a `.type` read off `null`. */\nfunction toEvent(line: string): StreamEvent | null {\n const parsed: unknown = JSON.parse(line);\n if (typeof parsed !== \"object\" || parsed === null) return null;\n const raw = parsed as { type: string; [key: string]: unknown };\n if (raw.type === \"audio_chunk\" && typeof raw.data === \"string\") {\n try {\n return { ...raw, type: \"audio_chunk\", data: decodeBase64(raw.data) };\n } catch {\n // Don't raise here: this must reach collectTrack's malformed-chunk\n // check, which turns undecodable data into a typed GenerationError.\n // Raising in place would let a raw DOMException escape\n // stream()/generate(), breaking the SDK's \"all errors extend\n // SoniloError\" contract.\n }\n }\n return raw as StreamEvent;\n}\n\nexport async function* parseNdjson(\n body: ReadableStream<Uint8Array>,\n): AsyncGenerator<StreamEvent, void, undefined> {\n const reader = body.getReader();\n const decoder = new TextDecoder();\n let buffer = \"\";\n try {\n for (;;) {\n const { done, value } = await reader.read();\n if (done) break;\n buffer += decoder.decode(value, { stream: true });\n let nl: number;\n while ((nl = buffer.indexOf(\"\\n\")) !== -1) {\n const line = buffer.slice(0, nl).trim();\n buffer = buffer.slice(nl + 1);\n if (line) {\n const ev = toEvent(line);\n if (ev !== null) yield ev;\n }\n }\n }\n buffer += decoder.decode();\n const tail = buffer.trim();\n if (tail) {\n const ev = toEvent(tail);\n if (ev !== null) yield ev;\n }\n } finally {\n await reader.cancel().catch(() => {});\n }\n}\n\nexport async function collectTrack(events: AsyncIterable<StreamEvent>): Promise<Track> {\n const chunks: Uint8Array[] = [];\n let title: string | undefined;\n let cost: CostInfo | undefined;\n let sawComplete = false;\n\n for await (const ev of events) {\n if (ev.type === \"audio_chunk\") {\n // A malformed chunk (missing/non-decodable `data`) must not be\n // silently dropped: that would hand back a \"successful\" Track with\n // empty or truncated audio and no indication anything went wrong.\n if (!(ev.data instanceof Uint8Array)) {\n throw new GenerationError(\n \"received a malformed audio_chunk event (missing or non-decodable data)\",\n );\n }\n chunks.push(ev.data);\n } else if (ev.type === \"title\" && typeof ev.title === \"string\") {\n title = ev.title;\n } else if (ev.type === \"cost\") {\n const { type: _type, ...rest } = ev;\n cost = rest as CostInfo;\n } else if (ev.type === \"error\") {\n const message = typeof ev.message === \"string\" && ev.message !== \"\" ? ev.message : \"generation failed\";\n const code = typeof ev.code === \"string\" ? ev.code : undefined;\n throw new GenerationError(message, code);\n } else if (ev.type === \"complete\") {\n sawComplete = true;\n }\n // unknown event types: ignored\n }\n\n if (!sawComplete) {\n throw new GenerationError(\"stream ended before a 'complete' event (truncated response)\");\n }\n\n const total = chunks.reduce((n, c) => n + c.length, 0);\n const audio = new Uint8Array(total);\n let offset = 0;\n for (const c of chunks) {\n audio.set(c, offset);\n offset += c.length;\n }\n return { audio, title, cost };\n}\n","import type { SoniloClient } from \"../client.js\";\nimport { SoniloError } from \"../errors.js\";\nimport { collectTrack, parseNdjson } from \"../streaming.js\";\nimport type { SfxTask, StreamEvent, TextToMusicParams, Track } from \"../types.js\";\n\nexport class TextToMusic {\n constructor(private readonly client: SoniloClient) {}\n\n /** Stream raw generation events (audio chunks pre-decoded to bytes). */\n async *stream(params: TextToMusicParams): AsyncGenerator<StreamEvent, void, undefined> {\n const form = new FormData();\n form.set(\"prompt\", params.prompt);\n form.set(\"duration\", String(params.duration));\n if (params.segments !== undefined) {\n form.set(\"segments\", JSON.stringify(params.segments));\n }\n // Opt out of the client's absolute request timeout: this holds the\n // response body open and reads NDJSON chunks for as long as generation\n // takes, so an AbortSignal keyed to elapsed time would kill a healthy,\n // still-streaming, long-duration track. Pass `params.signal` yourself to\n // bound or cancel the stream instead — it is forwarded to `fetch` as-is.\n const res = await this.client.request(\n \"/v1/text-to-music\",\n { method: \"POST\", body: form, signal: params.signal },\n { timeout: null },\n );\n if (!res.body) throw new SoniloError(\"Response has no body\");\n yield* parseNdjson(res.body);\n }\n\n /** Generate and buffer the whole track; throws GenerationError on stream errors. */\n generate(params: TextToMusicParams): Promise<Track> {\n return collectTrack(this.stream(params));\n }\n\n /**\n * Submit an async text-to-music task; poll with\n * `client.tasks.wait<MusicTaskResult>(task.task_id)`. Required for\n * `outputFormat: \"wav\"`. `stream()`/`generate()` remain the streaming path.\n */\n async submit(params: TextToMusicParams): Promise<SfxTask> {\n const mode = params.mode ?? \"async\";\n if (mode !== \"async\") {\n throw new SoniloError('submit() requires mode: \"async\"');\n }\n const form = new FormData();\n form.set(\"prompt\", params.prompt);\n form.set(\"duration\", String(params.duration));\n if (params.segments !== undefined) {\n form.set(\"segments\", JSON.stringify(params.segments));\n }\n form.set(\"mode\", mode);\n if (params.outputFormat !== undefined) {\n form.set(\"output_format\", params.outputFormat);\n }\n const res = await this.client.request(\"/v1/text-to-music\", {\n method: \"POST\",\n body: form,\n });\n return (await res.json()) as SfxTask;\n }\n}\n","import { SoniloError } from \"./errors.js\";\nimport type { VideoInput } from \"./types.js\";\n\nconst DEFAULT_FILENAME = \"video.mp4\";\n\n/**\n * Normalize every accepted video input into a FormData-ready Blob.\n * String inputs are file paths and work only in Node.js; browsers must\n * pass File/Blob/bytes/streams.\n */\nexport async function toUploadBlob(\n video: VideoInput,\n): Promise<{ blob: Blob; filename: string }> {\n if (typeof video === \"string\") {\n const isNode =\n typeof process !== \"undefined\" && Boolean((process as { versions?: { node?: string } }).versions?.node);\n if (!isNode) {\n throw new SoniloError(\n \"File paths are only supported in Node.js; pass a File or Blob in the browser\",\n );\n }\n const fsModule = \"node:fs/promises\";\n const { readFile } = (await import(\n /* webpackIgnore: true */ /* @vite-ignore */ fsModule\n )) as typeof import(\"node:fs/promises\");\n const data = await readFile(video);\n const filename = video.split(/[\\\\/]/).pop() || DEFAULT_FILENAME;\n return { blob: new Blob([data]), filename };\n }\n if (typeof File !== \"undefined\" && video instanceof File) {\n return { blob: video, filename: video.name || DEFAULT_FILENAME };\n }\n if (video instanceof Blob) {\n return { blob: video, filename: DEFAULT_FILENAME };\n }\n if (video instanceof Uint8Array) {\n return { blob: new Blob([video as unknown as BlobPart]), filename: DEFAULT_FILENAME };\n }\n if (video instanceof ArrayBuffer) {\n return { blob: new Blob([video]), filename: DEFAULT_FILENAME };\n }\n if (video instanceof ReadableStream) {\n return { blob: await new Response(video).blob(), filename: DEFAULT_FILENAME };\n }\n throw new SoniloError(\"Unsupported video input type\");\n}\n","import type { SoniloClient } from \"../client.js\";\nimport { SoniloError } from \"../errors.js\";\nimport { collectTrack, parseNdjson } from \"../streaming.js\";\nimport { toUploadBlob } from \"../upload.js\";\nimport type { SfxTask, StreamEvent, Track, VideoToMusicParams } from \"../types.js\";\n\nexport class VideoToMusic {\n constructor(private readonly client: SoniloClient) {}\n\n async *stream(params: VideoToMusicParams): AsyncGenerator<StreamEvent, void, undefined> {\n if ((params.video === undefined) === (params.videoUrl === undefined)) {\n throw new SoniloError(\"Provide exactly one of video or videoUrl\");\n }\n const form = new FormData();\n if (params.video !== undefined) {\n const { blob, filename } = await toUploadBlob(params.video);\n form.set(\"video\", blob, filename);\n } else {\n form.set(\"video_url\", params.videoUrl as string);\n }\n if (params.prompt !== undefined) form.set(\"prompt\", params.prompt);\n if (params.segments !== undefined) {\n form.set(\"segments\", JSON.stringify(params.segments));\n }\n // Opt out of the client's absolute request timeout: this holds the\n // response body open and reads NDJSON chunks for as long as generation\n // takes, so an AbortSignal keyed to elapsed time would kill a healthy,\n // still-streaming request (e.g. a slow video upload or long track). Pass\n // `params.signal` yourself to bound or cancel the stream instead — it is\n // forwarded to `fetch` as-is.\n const res = await this.client.request(\n \"/v1/video-to-music\",\n { method: \"POST\", body: form, signal: params.signal },\n { timeout: null },\n );\n if (!res.body) throw new SoniloError(\"Response has no body\");\n yield* parseNdjson(res.body);\n }\n\n generate(params: VideoToMusicParams): Promise<Track> {\n return collectTrack(this.stream(params));\n }\n\n /**\n * Submit an async video-to-music task; poll its result with\n * `client.tasks.wait<MusicTaskResult>(task.task_id)`. Required for\n * `isolateVocals` — the backend rejects vocal isolation on the plain\n * stream, and it only ever runs in async mode.\n */\n async submit(params: VideoToMusicParams): Promise<SfxTask> {\n if ((params.video === undefined) === (params.videoUrl === undefined)) {\n throw new SoniloError(\"Provide exactly one of video or videoUrl\");\n }\n let mode = params.mode;\n const needsAsync =\n params.isolateVocals ||\n params.preserveSpeech ||\n params.ducking !== undefined ||\n params.outputFormat === \"wav\";\n // submit() always wants an async task ack, never a stream. Default to\n // async; only object if the caller explicitly asked for stream while\n // also requesting an async-only feature.\n if (mode === undefined) mode = \"async\";\n if (needsAsync && mode !== \"async\") {\n throw new SoniloError(\n 'isolateVocals/preserveSpeech/ducking/outputFormat \"wav\" require mode: \"async\"',\n );\n }\n const form = new FormData();\n if (params.video !== undefined) {\n const { blob, filename } = await toUploadBlob(params.video);\n form.set(\"video\", blob, filename);\n } else {\n form.set(\"video_url\", params.videoUrl as string);\n }\n if (params.prompt !== undefined) form.set(\"prompt\", params.prompt);\n if (params.segments !== undefined) {\n form.set(\"segments\", JSON.stringify(params.segments));\n }\n form.set(\"mode\", mode);\n if (params.preserveSpeech !== undefined) {\n form.set(\"preserve_speech\", String(params.preserveSpeech));\n }\n if (params.isolateVocals !== undefined) {\n form.set(\"isolate_vocals\", String(params.isolateVocals));\n }\n if (params.outputFormat !== undefined) {\n form.set(\"output_format\", params.outputFormat);\n }\n if (params.ducking !== undefined) {\n form.set(\"ducking\", String(params.ducking));\n }\n const res = await this.client.request(\"/v1/video-to-music\", {\n method: \"POST\",\n body: form,\n });\n return (await res.json()) as SfxTask;\n }\n}\n","import type { SoniloClient } from \"../client.js\";\nimport type { SfxResult, SfxTask, TextToSfxParams, WaitOptions } from \"../types.js\";\n\nexport class TextToSfx {\n constructor(private readonly client: SoniloClient) {}\n\n async submit(params: TextToSfxParams): Promise<SfxTask> {\n const form = new FormData();\n form.set(\"prompt\", params.prompt);\n form.set(\"duration\", String(params.duration));\n if (params.audioFormat !== undefined) form.set(\"audio_format\", params.audioFormat);\n const res = await this.client.request(\"/v1/text-to-sfx\", {\n method: \"POST\",\n body: form,\n });\n return (await res.json()) as SfxTask;\n }\n\n async generate(params: TextToSfxParams, opts?: WaitOptions): Promise<SfxResult> {\n const task = await this.submit(params);\n return this.client.tasks.wait(task.task_id, opts);\n }\n}\n","import type { SoniloClient } from \"../client.js\";\nimport { SoniloError } from \"../errors.js\";\nimport { toUploadBlob } from \"../upload.js\";\nimport type { SfxResult, SfxTask, VideoToSfxParams, WaitOptions } from \"../types.js\";\n\nexport class VideoToSfx {\n constructor(private readonly client: SoniloClient) {}\n\n async submit(params: VideoToSfxParams): Promise<SfxTask> {\n if ((params.video === undefined) === (params.videoUrl === undefined)) {\n throw new SoniloError(\"Provide exactly one of video or videoUrl\");\n }\n const form = new FormData();\n if (params.video !== undefined) {\n const { blob, filename } = await toUploadBlob(params.video);\n form.set(\"video\", blob, filename);\n } else {\n form.set(\"video_url\", params.videoUrl as string);\n }\n if (params.prompt !== undefined) form.set(\"prompt\", params.prompt);\n if (params.segments !== undefined) {\n form.set(\"segments\", JSON.stringify(params.segments));\n }\n if (params.audioFormat !== undefined) form.set(\"audio_format\", params.audioFormat);\n const res = await this.client.request(\"/v1/video-to-sfx\", {\n method: \"POST\",\n body: form,\n });\n return (await res.json()) as SfxTask;\n }\n\n async generate(params: VideoToSfxParams, opts?: WaitOptions): Promise<SfxResult> {\n const task = await this.submit(params);\n return this.client.tasks.wait(task.task_id, opts);\n }\n}\n","import type { SoniloClient } from \"../client.js\";\nimport { SoniloError } from \"../errors.js\";\nimport { toUploadBlob } from \"../upload.js\";\nimport type { SfxTask, VideoResult, VideoToVideoMusicParams, WaitOptions } from \"../types.js\";\n\n/** Generate an original score for a video and get back a re-hosted video with\n * the music muxed in. Async only: `submit()` returns a task ack; poll with\n * `client.tasks.wait<VideoResult>(id)`, or use `generate()` to do both. */\nexport class VideoToVideoMusic {\n constructor(private readonly client: SoniloClient) {}\n\n async submit(params: VideoToVideoMusicParams): Promise<SfxTask> {\n if ((params.video === undefined) === (params.videoUrl === undefined)) {\n throw new SoniloError(\"Provide exactly one of video or videoUrl\");\n }\n const form = new FormData();\n if (params.video !== undefined) {\n const { blob, filename } = await toUploadBlob(params.video);\n form.set(\"video\", blob, filename);\n } else {\n form.set(\"video_url\", params.videoUrl as string);\n }\n if (params.prompt !== undefined) form.set(\"prompt\", params.prompt);\n if (params.preserveSpeech !== undefined) {\n form.set(\"preserve_speech\", String(params.preserveSpeech));\n }\n if (params.isolateVocals !== undefined) {\n form.set(\"isolate_vocals\", String(params.isolateVocals));\n }\n const res = await this.client.request(\"/v1/video-to-video-music\", {\n method: \"POST\",\n body: form,\n });\n return (await res.json()) as SfxTask;\n }\n\n async generate(params: VideoToVideoMusicParams, opts?: WaitOptions): Promise<VideoResult> {\n const task = await this.submit(params);\n return this.client.tasks.wait<VideoResult>(task.task_id, opts);\n }\n}\n","import type { SoniloClient } from \"../client.js\";\nimport { SoniloError } from \"../errors.js\";\nimport { toUploadBlob } from \"../upload.js\";\nimport type { SfxTask, VideoResult, VideoToVideoSfxParams, WaitOptions } from \"../types.js\";\n\n/** Generate sound effects for a video and get back a re-hosted video with the\n * SFX muxed in. Async only. */\nexport class VideoToVideoSfx {\n constructor(private readonly client: SoniloClient) {}\n\n async submit(params: VideoToVideoSfxParams): Promise<SfxTask> {\n if ((params.video === undefined) === (params.videoUrl === undefined)) {\n throw new SoniloError(\"Provide exactly one of video or videoUrl\");\n }\n const form = new FormData();\n if (params.video !== undefined) {\n const { blob, filename } = await toUploadBlob(params.video);\n form.set(\"video\", blob, filename);\n } else {\n form.set(\"video_url\", params.videoUrl as string);\n }\n if (params.prompt !== undefined) form.set(\"prompt\", params.prompt);\n if (params.segments !== undefined) {\n form.set(\"segments\", JSON.stringify(params.segments));\n }\n const res = await this.client.request(\"/v1/video-to-video-sfx\", {\n method: \"POST\",\n body: form,\n });\n return (await res.json()) as SfxTask;\n }\n\n async generate(params: VideoToVideoSfxParams, opts?: WaitOptions): Promise<VideoResult> {\n const task = await this.submit(params);\n return this.client.tasks.wait<VideoResult>(task.task_id, opts);\n }\n}\n","import { SoniloError } from \"../errors.js\";\nimport { toUploadBlob } from \"../upload.js\";\nimport type { VideoToSoundParams } from \"../types.js\";\n\n/** Build the multipart body shared by /v1/video-to-sound and\n * /v1/video-to-video-sound — their form fields are identical, so the two\n * resources differ only in the path they POST to.\n *\n * Every optional field is omitted when unset rather than sent with a default:\n * `ducking` in particular is default-ON server-side, so an unset value must\n * not become an explicit \"false\" on the wire. */\nexport async function buildSoundForm(params: VideoToSoundParams): Promise<FormData> {\n if ((params.video === undefined) === (params.videoUrl === undefined)) {\n throw new SoniloError(\"Provide exactly one of video or videoUrl\");\n }\n const form = new FormData();\n if (params.video !== undefined) {\n const { blob, filename } = await toUploadBlob(params.video);\n form.set(\"video\", blob, filename);\n } else {\n form.set(\"video_url\", params.videoUrl as string);\n }\n if (params.musicPrompt !== undefined) form.set(\"music_prompt\", params.musicPrompt);\n if (params.sfxPrompt !== undefined) form.set(\"sfx_prompt\", params.sfxPrompt);\n if (params.segments !== undefined) {\n form.set(\"segments\", JSON.stringify(params.segments));\n }\n if (params.preserveSpeech !== undefined) {\n form.set(\"preserve_speech\", String(params.preserveSpeech));\n }\n if (params.ducking !== undefined) form.set(\"ducking\", String(params.ducking));\n return form;\n}\n","import type { SoniloClient } from \"../client.js\";\nimport { buildSoundForm } from \"./soundForm.js\";\nimport type { SfxTask, SoundResult, VideoToSoundParams, WaitOptions } from \"../types.js\";\n\n/** Generate a combined music + sound-effects track for a video and get back\n * the mixed audio. Async only. */\nexport class VideoToSound {\n constructor(private readonly client: SoniloClient) {}\n\n async submit(params: VideoToSoundParams): Promise<SfxTask> {\n const res = await this.client.request(\"/v1/video-to-sound\", {\n method: \"POST\",\n body: await buildSoundForm(params),\n });\n return (await res.json()) as SfxTask;\n }\n\n async generate(params: VideoToSoundParams, opts?: WaitOptions): Promise<SoundResult> {\n const task = await this.submit(params);\n return this.client.tasks.wait<SoundResult>(task.task_id, opts);\n }\n}\n","import type { SoniloClient } from \"../client.js\";\nimport { buildSoundForm } from \"./soundForm.js\";\nimport type { SfxTask, SoundResult, VideoToSoundParams, WaitOptions } from \"../types.js\";\n\n/** Generate a combined music + sound-effects track for a video and get back a\n * re-hosted video with that track muxed in. Async only. */\nexport class VideoToVideoSound {\n constructor(private readonly client: SoniloClient) {}\n\n async submit(params: VideoToSoundParams): Promise<SfxTask> {\n const res = await this.client.request(\"/v1/video-to-video-sound\", {\n method: \"POST\",\n body: await buildSoundForm(params),\n });\n return (await res.json()) as SfxTask;\n }\n\n async generate(params: VideoToSoundParams, opts?: WaitOptions): Promise<SoundResult> {\n const task = await this.submit(params);\n return this.client.tasks.wait<SoundResult>(task.task_id, opts);\n }\n}\n","/** The SDK's own version. Generated by scripts/sync-versions.mjs — do not edit. */\nexport const VERSION = \"0.6.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 { 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\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 }\n\n /**\n * Perform an authenticated request; throws a typed error on non-2xx.\n *\n * `opts.timeout` overrides the client's default timeout for this call;\n * pass `null` to disable the abort-on-timeout behavior entirely (used by\n * the streaming music endpoints — see textToMusic.ts / videoToMusic.ts).\n * A caller-supplied `init.signal` always wins over any timeout signal.\n */\n async request(\n path: string,\n init: RequestInit = {},\n opts: { timeout?: number | null } = {},\n ): Promise<Response> {\n const headers = new Headers(init.headers);\n headers.set(\"Authorization\", `Bearer ${this.apiKey}`);\n headers.set(\"X-Sonilo-Client\", this.clientName);\n headers.set(\"X-Sonilo-Client-Version\", this.clientVersion);\n const timeout = opts.timeout === undefined ? this.timeout : opts.timeout;\n // We only \"own\" the signal (and may later rewrap its abort as a\n // RequestTimeoutError) when the caller didn't supply one and a timeout\n // is actually enabled.\n const ownsSignal = init.signal == null && timeout !== null;\n const signal = init.signal ?? (timeout === null ? undefined : AbortSignal.timeout(timeout));\n try {\n const res = await this.fetchFn(`${this.baseUrl}${path}`, { ...init, headers, signal });\n if (!res.ok) throw await errorFromResponse(res);\n return res;\n } catch (err) {\n if (ownsSignal && isTimeoutSignalError(err)) {\n throw new RequestTimeoutError(`Request to ${path} timed out after ${timeout}ms`);\n }\n throw err;\n }\n }\n}\n","import { DEFAULT_TIMEOUT_MS } from \"./client.js\";\nimport { RequestTimeoutError, SoniloError, isTimeoutSignalError } from \"./errors.js\";\nimport type { SfxMedia } from \"./types.js\";\n\n/** Fetch a result media file. The URL is presigned — no API key is sent.\n *\n * Accepts either a media object (`result.audio`, `result.music`, …) or a bare\n * URL string, which is what the combined video-to-sound endpoints return as\n * `output_url`. */\nexport async function download(\n media: SfxMedia | string | undefined,\n fetchFn: typeof globalThis.fetch = globalThis.fetch,\n timeout: number = DEFAULT_TIMEOUT_MS,\n): Promise<Uint8Array> {\n const url = typeof media === \"string\" ? media : media?.url;\n if (!url) {\n throw new SoniloError(\"No media to download\");\n }\n let res: Response;\n try {\n res = await fetchFn(url, { signal: AbortSignal.timeout(timeout) });\n } catch (err) {\n if (isTimeoutSignalError(err)) {\n throw new RequestTimeoutError(`Download of ${url} timed out after ${timeout}ms`);\n }\n throw err;\n }\n if (!res.ok) {\n throw new SoniloError(`Download failed: HTTP ${res.status}`);\n }\n return new Uint8Array(await res.arrayBuffer());\n}\n","export type SegmentLabel =\n | \"intro\"\n | \"verse\"\n | \"pre-chorus\"\n | \"chorus\"\n | \"bridge\"\n | \"break\"\n | \"silence\"\n | \"outro\"\n | \"none\";\n\nexport interface Segment {\n start: number;\n prompt: string;\n label?: SegmentLabel;\n}\n\n/** Monetary fields are strings, exactly as the backend serializes them. */\nexport interface CostInfo {\n billing_rate_per_sec: string;\n billing_before_discount: string;\n billing_after_discount: string;\n discount_factor: string;\n}\n\nexport interface AudioChunkEvent {\n type: \"audio_chunk\";\n /** Decoded from the wire's base64 by the SDK. */\n data: Uint8Array;\n}\n\nexport interface TitleEvent {\n type: \"title\";\n title: string;\n summary?: string;\n display_tags?: string[];\n [key: string]: unknown;\n}\n\nexport interface CompleteEvent {\n type: \"complete\";\n [key: string]: unknown;\n}\n\nexport interface ErrorEvent {\n type: \"error\";\n code?: string;\n message?: string;\n [key: string]: unknown;\n}\n\nexport interface CostEvent extends CostInfo {\n type: \"cost\";\n}\n\n/** Forward-compatibility: unrecognized event types are passed through. */\nexport interface UnknownEvent {\n type: string;\n [key: string]: unknown;\n}\n\nexport type StreamEvent =\n | AudioChunkEvent\n | TitleEvent\n | CompleteEvent\n | ErrorEvent\n | CostEvent\n | UnknownEvent;\n\nexport interface Track {\n audio: Uint8Array;\n title?: string;\n cost?: CostInfo;\n}\n\nexport interface TextToMusicParams {\n prompt: string;\n duration: number;\n segments?: Segment[];\n /** \"stream\" (default) or \"async\" (required by `submit()` and `output_format: \"wav\"`). */\n mode?: \"stream\" | \"async\";\n /** Container for the async result. `wav` requires `mode: \"async\"`. Defaults to m4a server-side. */\n outputFormat?: \"m4a\" | \"wav\";\n /** Bounds the stream: aborting this cancels the in-flight generation.\n * Passed straight through to `fetch` — it is never rewrapped as\n * RequestTimeoutError, since the client's own absolute timeout does not\n * apply to streaming music generation. */\n signal?: AbortSignal;\n}\n\n/** string = file path (Node.js only). */\nexport type VideoInput =\n | File\n | Blob\n | Uint8Array\n | ArrayBuffer\n | ReadableStream<Uint8Array>\n | string;\n\nexport interface VideoToMusicParams {\n video?: VideoInput;\n videoUrl?: string;\n prompt?: string;\n segments?: Segment[];\n /** Bounds the stream: aborting this cancels the in-flight generation.\n * Passed straight through to `fetch` — it is never rewrapped as\n * RequestTimeoutError, since the client's own absolute timeout does not\n * apply to streaming music generation. Only meaningful for `stream()`/\n * `generate()`; `submit()` ignores it. */\n signal?: AbortSignal;\n /** \"stream\" (the default, used by `stream()`/`generate()`) or \"async\"\n * (required for `submit()`, and for `isolateVocals`). Only consulted by\n * `submit()` — `stream()`/`generate()` always request a stream. */\n mode?: \"stream\" | \"async\";\n /** Split the generated track into a vocals-only stem alongside the mix.\n * Requires `mode: \"async\"`; if `mode` is left unset it defaults to\n * \"async\" automatically. Only usable via `submit()` — the backend\n * rejects it on the plain stream. */\n isolateVocals?: boolean;\n /** Keep the source speech/vocals in the async result. Current name for\n * `isolateVocals`; both are accepted and OR'd server-side. Requires\n * `mode: \"async\"` (auto-selected by `submit()`). */\n preserveSpeech?: boolean;\n /** Container for the async result. `wav` requires async. Defaults to m4a. */\n outputFormat?: \"m4a\" | \"wav\";\n /** Duck the generated music under the source voice at finalize time.\n * Default-ON server-side in async mode: leave unset to keep it on, pass\n * `false` to opt out. Free, best-effort; only valid on `submit()`. */\n ducking?: boolean;\n}\n\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. Returned only for self-serve\n * accounts; absent entirely for invoiced accounts. */\n trial?: Record<string, TrialQuota>;\n}\n\nexport interface UsageSummary {\n total_requests: number;\n total_duration_seconds: number;\n total_cost: number | string;\n period_start: string;\n period_end: string;\n [key: string]: unknown;\n}\n\nexport interface DailyUsage {\n date: string;\n requests: number;\n duration_seconds: number;\n cost: number | string;\n}\n\nexport interface UsageResponse {\n summary: UsageSummary;\n daily: DailyUsage[];\n}\n\nexport function isAudioChunkEvent(event: StreamEvent): event is AudioChunkEvent {\n return event.type === \"audio_chunk\" && (event as AudioChunkEvent).data instanceof Uint8Array;\n}\n\nexport function isErrorEvent(event: StreamEvent): event is ErrorEvent {\n return event.type === \"error\";\n}\n\n/** SFX segments (unlike music `Segment`) require `end`, must start at 0,\n * and be contiguous; validated server-side. */\nexport interface SfxSegment {\n start: number;\n end: number;\n prompt: string;\n}\n\nexport type SfxAudioFormat = \"wav\" | \"mp3\" | \"aac\" | \"flac\";\n\n/** Submission ack for the async SFX endpoints. */\nexport interface SfxTask {\n task_id: string;\n status: string;\n}\n\n/** A generated file re-hosted on R2 behind a presigned URL. */\nexport interface SfxMedia {\n url: string;\n content_type?: string;\n file_size?: number;\n}\n\nexport interface SfxError {\n code?: string;\n message?: string;\n}\n\n/**\n * Common shape of any polled task (`tasks.get`/`tasks.wait`), regardless of\n * which endpoint created it. `Tasks.get`/`Tasks.wait` are generic over this so\n * each endpoint's result type (e.g. `SfxResult`, `MusicTaskResult`) can add\n * its own `audio`/media fields while sharing the status/error/refund\n * bookkeeping the poller relies on.\n */\nexport interface BaseTaskResult {\n task_id: string;\n type?: string;\n status: \"processing\" | \"succeeded\" | \"failed\" | (string & {});\n /** Only present when the account's task-field whitelist enables cost. */\n cost?: number;\n error?: SfxError;\n refunded?: boolean;\n [key: string]: unknown;\n}\n\n/** State of an SFX task (`tasks.get`) or its final result (`wait`/`generate`). */\nexport interface SfxResult extends BaseTaskResult {\n audio?: SfxMedia;\n /** Kept for backward compatibility; no longer populated — video-to-sfx returns audio only. */\n video?: SfxMedia;\n}\n\nexport interface TextToSfxParams {\n prompt: string;\n duration: number;\n audioFormat?: SfxAudioFormat;\n}\n\nexport interface VideoToSfxParams {\n video?: VideoInput;\n videoUrl?: string;\n prompt?: string;\n segments?: SfxSegment[];\n audioFormat?: SfxAudioFormat;\n}\n\n/** One decoded audio stream of an async video-to-music result. Unlike SFX,\n * `audio` on a music task is always an array — even without `isolateVocals` —\n * since a music generation can carry more than one output stream. */\nexport interface MusicMediaEntry extends SfxMedia {\n stream_index: number;\n sample_rate?: number;\n channels?: number;\n}\n\n/** One muxed audio+video-aligned output, present only when `isolateVocals`\n * is set. */\nexport interface MusicMuxEntry extends SfxMedia {\n stream_index: number;\n}\n\nexport interface MusicTitle {\n title: string;\n summary?: string;\n display_tags?: string[];\n}\n\n/** State of an async video-to-music task (`tasks.get`) or its final result\n * (`tasks.wait<MusicTaskResult>()`). Only reachable via `videoToMusic.submit()`\n * with `mode: \"async\"`. */\nexport interface MusicTaskResult extends BaseTaskResult {\n audio?: MusicMediaEntry[];\n /** Vocals-only stem; present only when `isolateVocals` was requested. */\n vocals?: SfxMedia;\n /** Muxed output per stream; present only when `isolateVocals` was requested. */\n mux?: MusicMuxEntry[];\n /** Music ducked under the source voice; present only when `ducking` ran. */\n ducked?: MusicMediaEntry[];\n title?: MusicTitle;\n duration_seconds?: number;\n}\n\nexport interface WaitOptions {\n /** Milliseconds between polls. Default 2000. */\n pollInterval?: number;\n /** Overall deadline in milliseconds. Default 600000. */\n timeout?: number;\n}\n\n/** Result of an async video-to-video task (`videoToVideoMusic`/`videoToVideoSfx`):\n * a re-hosted video with generated music or SFX muxed in. */\nexport interface VideoResult extends BaseTaskResult {\n video?: SfxMedia;\n duration_seconds?: number;\n}\n\nexport interface VideoToVideoMusicParams {\n video?: VideoInput;\n videoUrl?: string;\n prompt?: string;\n /** Keep the source speech/vocals in the output. Both this and the legacy\n * `isolateVocals` are accepted and OR'd server-side. */\n preserveSpeech?: boolean;\n /** @deprecated Legacy alias for `preserveSpeech`. */\n isolateVocals?: boolean;\n}\n\nexport interface VideoToVideoSfxParams {\n video?: VideoInput;\n videoUrl?: string;\n prompt?: string;\n segments?: SfxSegment[];\n}\n\n/** Params for `videoToSound` and `videoToVideoSound`. Both endpoints take the\n * identical form, so they share one params type. */\nexport interface VideoToSoundParams {\n video?: VideoInput;\n videoUrl?: string;\n /** Style hint for the generated music bed. */\n musicPrompt?: string;\n /** Description of the sound effects layered over the music. */\n sfxPrompt?: string;\n /** Per-segment SFX descriptions; must start at 0 and be contiguous. */\n segments?: SfxSegment[];\n /** Keep the source speech in the result. */\n preserveSpeech?: boolean;\n /** Duck the generated music under the source speech. Default-ON\n * server-side: leave unset to keep it on, pass `false` to opt out. */\n ducking?: boolean;\n}\n\n/** Result of a `videoToSound` / `videoToVideoSound` task (`tasks.get`) or its\n * final state (`generate`).\n *\n * The combined music+SFX result is `output_url` — a bare presigned URL rather\n * than a media object, since these endpoints render one artifact whose kind is\n * announced by `output_type` (\"audio\" for video-to-sound, \"video\" for\n * video-to-video-sound). `music`, `music_processed` and `sfx` are the\n * individual stems; pass any of them, or `output_url` itself, to `download()`. */\nexport interface SoundResult extends BaseTaskResult {\n output_url?: string;\n output_type?: \"audio\" | \"video\";\n output_bytes?: number;\n music?: SfxMedia;\n /** Present only when `preserveSpeech`/`ducking` altered the music bed. */\n music_processed?: SfxMedia;\n sfx?: SfxMedia;\n duration_seconds?: number;\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/index.ts","../src/errors.ts","../src/resources/account.ts","../src/resources/tasks.ts","../src/streaming.ts","../src/resources/textToMusic.ts","../src/upload.ts","../src/resources/videoToMusic.ts","../src/resources/textToSfx.ts","../src/resources/videoToSfx.ts","../src/resources/videoToVideoMusic.ts","../src/resources/videoToVideoSfx.ts","../src/resources/soundForm.ts","../src/resources/videoToSound.ts","../src/resources/videoToVideoSound.ts","../src/resources/dubbing.ts","../src/version.ts","../src/client.ts","../src/download.ts","../src/types.ts"],"sourcesContent":["export { DEFAULT_TIMEOUT_MS, SoniloClient, type SoniloClientOptions } from \"./client.js\";\nexport {\n APIError,\n AuthenticationError,\n BadRequestError,\n GenerationError,\n PaymentRequiredError,\n RateLimitError,\n RequestTimeoutError,\n SoniloError,\n TaskFailedError,\n TaskTimeoutError,\n TrialExhaustedError,\n} from \"./errors.js\";\nexport { download } from \"./download.js\";\nexport { VERSION } from \"./version.js\";\nexport type {\n AccountServices,\n AudioChunkEvent,\n BaseTaskResult,\n CompleteEvent,\n CostEvent,\n CostInfo,\n DailyUsage,\n DubbingLanguage,\n DubbingParams,\n DubbingResult,\n ErrorEvent,\n MusicMediaEntry,\n MusicMuxEntry,\n MusicTaskResult,\n MusicTitle,\n Segment,\n SegmentLabel,\n SfxAudioFormat,\n SfxError,\n SfxMedia,\n SfxResult,\n SfxSegment,\n SfxTask,\n SoundOutputEntry,\n SoundResult,\n StreamEvent,\n TextToMusicParams,\n TextToSfxParams,\n TitleEvent,\n Track,\n TrialQuota,\n UnknownEvent,\n UsageResponse,\n UsageSummary,\n VideoInput,\n VideoResult,\n VideoToMusicParams,\n VideoToSfxParams,\n VideoToSoundParams,\n VideoToVideoMusicParams,\n VideoToVideoSfxParams,\n WaitOptions,\n} from \"./types.js\";\nexport { isAudioChunkEvent, isErrorEvent } from \"./types.js\";\n","export class SoniloError extends Error {\n constructor(message: string) {\n super(message);\n this.name = new.target.name;\n }\n}\n\nexport class APIError extends SoniloError {\n readonly status: number;\n readonly body: unknown;\n /** The API's typed error code (e.g. \"rate_limit_exceeded\"), distinct from the HTTP status. */\n readonly code?: string;\n /** Per-field validation details, present on a 422. */\n readonly errors?: unknown[];\n\n constructor(message: string, status: number, body?: unknown) {\n super(message);\n this.status = status;\n this.body = body;\n const parsed = body as { code?: unknown; errors?: unknown } | undefined;\n this.code = typeof parsed?.code === \"string\" ? parsed.code : undefined;\n this.errors = Array.isArray(parsed?.errors) ? parsed.errors : undefined;\n }\n}\n\nexport class AuthenticationError extends APIError {}\n\nexport class PaymentRequiredError extends APIError {}\n\n/** The account's free trial for this service is spent and it has never been\n * funded — the caller should add a payment method rather than retry. A\n * subclass of `PaymentRequiredError`, so code that already catches every 402\n * keeps working; catch this first to tell \"you haven't paid us yet\" apart\n * from a funded wallet that ran dry (`PaymentRequiredError` with\n * `code === \"insufficient_balance\"`). */\nexport class TrialExhaustedError extends PaymentRequiredError {}\n\nexport class BadRequestError extends APIError {\n get detail(): string | undefined {\n const body = this.body as { message?: unknown; detail?: unknown } | undefined;\n if (typeof body?.message === \"string\" && body.message) {\n return body.message;\n }\n return typeof body?.detail === \"string\" ? body.detail : undefined;\n }\n}\n\nexport class RateLimitError extends APIError {\n readonly retryAfter?: number;\n\n constructor(message: string, status: number, body?: unknown, retryAfter?: number) {\n super(message, status, body);\n this.retryAfter = retryAfter;\n }\n}\n\n/** Raised by generate() when an `error` event arrives mid-stream. */\nexport class GenerationError extends SoniloError {\n readonly code?: string;\n\n constructor(message: string, code?: string) {\n super(message);\n this.code = code;\n }\n}\n\n/** Raised by tasks.wait()/generate() when an SFX task reaches `failed`. */\nexport class TaskFailedError extends SoniloError {\n readonly code?: string;\n readonly taskId: string;\n readonly refunded?: boolean;\n\n constructor(\n message: string,\n opts: { code?: string; taskId: string; refunded?: boolean },\n ) {\n super(message);\n this.code = opts.code;\n this.taskId = opts.taskId;\n this.refunded = opts.refunded;\n }\n}\n\n/** Poll deadline passed. The task may still finish server-side — resume with\n * tasks.wait(taskId) or tasks.get(taskId). */\nexport class TaskTimeoutError extends SoniloError {\n readonly taskId: string;\n\n constructor(message: string, taskId: string) {\n super(message);\n this.taskId = taskId;\n }\n}\n\n/** Raised when a one-shot request or download is aborted by its own timeout\n * signal (as opposed to a caller-supplied AbortSignal, which propagates\n * untouched). */\nexport class RequestTimeoutError extends SoniloError {}\n\n/**\n * True if `err` is the rejection produced when an `AbortSignal.timeout()`\n * we created fires. Used to distinguish \"our\" timeout aborts (which should be\n * rethrown as `RequestTimeoutError`) from a caller-supplied signal's abort\n * (which must propagate untouched).\n */\nexport function isTimeoutSignalError(err: unknown): boolean {\n return err instanceof Error && (err.name === \"TimeoutError\" || err.name === \"AbortError\");\n}\n\nexport async function errorFromResponse(res: Response): Promise<APIError> {\n const text = await res.text().catch(() => \"\");\n let body: unknown = text;\n try {\n body = JSON.parse(text);\n } catch {\n // keep raw text\n }\n const parsed = body as { message?: unknown; detail?: unknown } | undefined;\n const rawMessage = typeof parsed?.message === \"string\" && parsed.message ? parsed.message : undefined;\n const rawDetail = parsed?.detail;\n const isDetailAbsent = rawDetail === undefined || rawDetail === null || rawDetail === \"\";\n let reason: string;\n if (rawMessage !== undefined) {\n reason = rawMessage;\n } else if (isDetailAbsent) {\n reason = res.statusText || \"request failed\";\n } else if (typeof rawDetail === \"string\") {\n reason = rawDetail;\n } else {\n try {\n reason = JSON.stringify(rawDetail);\n } catch {\n reason = res.statusText || \"request failed\";\n }\n }\n const message = `HTTP ${res.status}: ${reason}`;\n\n switch (res.status) {\n case 401:\n return new AuthenticationError(message, res.status, body);\n case 402: {\n // Branch on the API's `code`, never on the message text — the wording\n // is product copy and changes; the code is the contract.\n const code = (body as { code?: unknown } | undefined)?.code;\n if (code === \"trial_exhausted\") {\n return new TrialExhaustedError(message, res.status, body);\n }\n return new PaymentRequiredError(message, res.status, body);\n }\n case 429: {\n const ra = res.headers.get(\"retry-after\");\n const retryAfter = ra !== null && ra !== \"\" && !Number.isNaN(Number(ra)) ? Number(ra) : undefined;\n return new RateLimitError(message, res.status, body, retryAfter);\n }\n case 400:\n case 413:\n case 422:\n return new BadRequestError(message, res.status, body);\n default:\n return new APIError(message, res.status, body);\n }\n}\n","import type { SoniloClient } from \"../client.js\";\nimport type { AccountServices, UsageResponse } from \"../types.js\";\n\nexport class Account {\n constructor(private readonly client: SoniloClient) {}\n\n async services(): Promise<AccountServices> {\n const res = await this.client.request(\"/v1/account/services\");\n return (await res.json()) as AccountServices;\n }\n\n async usage(params: { days?: number } = {}): Promise<UsageResponse> {\n const query = params.days !== undefined ? `?days=${params.days}` : \"\";\n const res = await this.client.request(`/v1/account/usage${query}`);\n return (await res.json()) as UsageResponse;\n }\n}\n","import type { SoniloClient } from \"../client.js\";\nimport { SoniloError, TaskFailedError, TaskTimeoutError } from \"../errors.js\";\nimport type { BaseTaskResult, SfxResult, WaitOptions } from \"../types.js\";\n\nexport const DEFAULT_POLL_INTERVAL_MS = 2000;\nexport const DEFAULT_WAIT_TIMEOUT_MS = 600_000;\n\nconst sleep = (ms: number) => new Promise<void>((resolve) => setTimeout(resolve, ms));\n\n/** A negative delay is clamped to 0 by setTimeout, which would turn the poll\n * loop into a busy loop hammering the API until the deadline. */\nfunction validateWaitArgs(pollInterval: number, timeout: number): void {\n if (pollInterval < 0) {\n throw new SoniloError(`pollInterval must be >= 0, got ${pollInterval}`);\n }\n if (timeout < 0) {\n throw new SoniloError(`timeout must be >= 0, got ${timeout}`);\n }\n}\n\nexport class Tasks {\n constructor(private readonly client: SoniloClient) {}\n\n /**\n * Fetch current task state. Never throws on a failed status.\n *\n * Generic over the result shape so callers can request the endpoint-\n * specific type, e.g. `client.tasks.get<MusicTaskResult>(taskId)`.\n * Defaults to `SfxResult` for back-compat.\n */\n async get<T extends BaseTaskResult = SfxResult>(taskId: string): Promise<T> {\n const res = await this.client.request(`/v1/tasks/${encodeURIComponent(taskId)}`);\n return (await res.json()) as T;\n }\n\n /**\n * Poll until the task is terminal; throw on failure or deadline.\n *\n * Generic over the result shape, e.g.\n * `client.tasks.wait<MusicTaskResult>(taskId)`. Defaults to `SfxResult`\n * for back-compat.\n */\n async wait<T extends BaseTaskResult = SfxResult>(\n taskId: string,\n opts: WaitOptions = {},\n ): Promise<T> {\n const pollInterval = opts.pollInterval ?? DEFAULT_POLL_INTERVAL_MS;\n const timeout = opts.timeout ?? DEFAULT_WAIT_TIMEOUT_MS;\n validateWaitArgs(pollInterval, timeout);\n const deadline = performance.now() + timeout;\n for (;;) {\n const result = await this.get<T>(taskId);\n if (result.status === \"succeeded\") return result;\n if (result.status === \"failed\") {\n const message = result.error?.message || \"Generation failed\";\n throw new TaskFailedError(`Task ${taskId} failed: ${message}`, {\n code: result.error?.code,\n taskId,\n refunded: result.refunded,\n });\n }\n const remaining = deadline - performance.now();\n if (remaining <= 0) {\n throw new TaskTimeoutError(\n `Task ${taskId} still processing after ${timeout}ms; ` +\n \"it may finish later — resume with tasks.wait or tasks.get\",\n taskId,\n );\n }\n await sleep(Math.min(pollInterval, remaining));\n }\n }\n}\n","import { GenerationError } from \"./errors.js\";\nimport type { CostInfo, StreamEvent, Track } from \"./types.js\";\n\nexport function decodeBase64(b64: string): Uint8Array {\n const bin = atob(b64);\n const out = new Uint8Array(bin.length);\n for (let i = 0; i < bin.length; i++) out[i] = bin.charCodeAt(i);\n return out;\n}\n\n/** Returns `null` for a valid-JSON-but-non-object line (e.g. a bare `null`\n * or a number/string), which carries no event `type` and is skipped like any\n * other junk line rather than crashing on a `.type` read off `null`. */\nfunction toEvent(line: string): StreamEvent | null {\n const parsed: unknown = JSON.parse(line);\n if (typeof parsed !== \"object\" || parsed === null) return null;\n const raw = parsed as { type: string; [key: string]: unknown };\n if (raw.type === \"audio_chunk\" && typeof raw.data === \"string\") {\n try {\n return { ...raw, type: \"audio_chunk\", data: decodeBase64(raw.data) };\n } catch {\n // Don't raise here: this must reach collectTrack's malformed-chunk\n // check, which turns undecodable data into a typed GenerationError.\n // Raising in place would let a raw DOMException escape\n // stream()/generate(), breaking the SDK's \"all errors extend\n // SoniloError\" contract.\n }\n }\n return raw as StreamEvent;\n}\n\nexport async function* parseNdjson(\n body: ReadableStream<Uint8Array>,\n): AsyncGenerator<StreamEvent, void, undefined> {\n const reader = body.getReader();\n const decoder = new TextDecoder();\n let buffer = \"\";\n try {\n for (;;) {\n const { done, value } = await reader.read();\n if (done) break;\n buffer += decoder.decode(value, { stream: true });\n let nl: number;\n while ((nl = buffer.indexOf(\"\\n\")) !== -1) {\n const line = buffer.slice(0, nl).trim();\n buffer = buffer.slice(nl + 1);\n if (line) {\n const ev = toEvent(line);\n if (ev !== null) yield ev;\n }\n }\n }\n buffer += decoder.decode();\n const tail = buffer.trim();\n if (tail) {\n const ev = toEvent(tail);\n if (ev !== null) yield ev;\n }\n } finally {\n await reader.cancel().catch(() => {});\n }\n}\n\nexport async function collectTrack(events: AsyncIterable<StreamEvent>): Promise<Track> {\n const chunks: Uint8Array[] = [];\n let title: string | undefined;\n let cost: CostInfo | undefined;\n let sawComplete = false;\n\n for await (const ev of events) {\n if (ev.type === \"audio_chunk\") {\n // A malformed chunk (missing/non-decodable `data`) must not be\n // silently dropped: that would hand back a \"successful\" Track with\n // empty or truncated audio and no indication anything went wrong.\n if (!(ev.data instanceof Uint8Array)) {\n throw new GenerationError(\n \"received a malformed audio_chunk event (missing or non-decodable data)\",\n );\n }\n chunks.push(ev.data);\n } else if (ev.type === \"title\" && typeof ev.title === \"string\") {\n title = ev.title;\n } else if (ev.type === \"cost\") {\n const { type: _type, ...rest } = ev;\n cost = rest as CostInfo;\n } else if (ev.type === \"error\") {\n const message = typeof ev.message === \"string\" && ev.message !== \"\" ? ev.message : \"generation failed\";\n const code = typeof ev.code === \"string\" ? ev.code : undefined;\n throw new GenerationError(message, code);\n } else if (ev.type === \"complete\") {\n sawComplete = true;\n }\n // unknown event types: ignored\n }\n\n if (!sawComplete) {\n throw new GenerationError(\"stream ended before a 'complete' event (truncated response)\");\n }\n\n const total = chunks.reduce((n, c) => n + c.length, 0);\n const audio = new Uint8Array(total);\n let offset = 0;\n for (const c of chunks) {\n audio.set(c, offset);\n offset += c.length;\n }\n return { audio, title, cost };\n}\n","import type { SoniloClient } from \"../client.js\";\nimport { SoniloError } from \"../errors.js\";\nimport { collectTrack, parseNdjson } from \"../streaming.js\";\nimport type { SfxTask, StreamEvent, TextToMusicParams, Track } from \"../types.js\";\n\nexport class TextToMusic {\n constructor(private readonly client: SoniloClient) {}\n\n /** Stream raw generation events (audio chunks pre-decoded to bytes). */\n async *stream(params: TextToMusicParams): AsyncGenerator<StreamEvent, void, undefined> {\n const form = new FormData();\n form.set(\"prompt\", params.prompt);\n form.set(\"duration\", String(params.duration));\n if (params.segments !== undefined) {\n form.set(\"segments\", JSON.stringify(params.segments));\n }\n // Opt out of the client's absolute request timeout: this holds the\n // response body open and reads NDJSON chunks for as long as generation\n // takes, so an AbortSignal keyed to elapsed time would kill a healthy,\n // still-streaming, long-duration track. Pass `params.signal` yourself to\n // bound or cancel the stream instead — it is forwarded to `fetch` as-is.\n const res = await this.client.request(\n \"/v1/text-to-music\",\n { method: \"POST\", body: form, signal: params.signal },\n { timeout: null },\n );\n if (!res.body) throw new SoniloError(\"Response has no body\");\n yield* parseNdjson(res.body);\n }\n\n /** Generate and buffer the whole track; throws GenerationError on stream errors. */\n generate(params: TextToMusicParams): Promise<Track> {\n return collectTrack(this.stream(params));\n }\n\n /**\n * Submit an async text-to-music task; poll with\n * `client.tasks.wait<MusicTaskResult>(task.task_id)`. Required for\n * `outputFormat: \"wav\"` and `variantsNum` above 1. `stream()`/`generate()`\n * remain the streaming path.\n */\n async submit(params: TextToMusicParams): Promise<SfxTask> {\n const mode = params.mode ?? \"async\";\n if (mode !== \"async\") {\n throw new SoniloError('submit() requires mode: \"async\"');\n }\n const form = new FormData();\n form.set(\"prompt\", params.prompt);\n form.set(\"duration\", String(params.duration));\n if (params.segments !== undefined) {\n form.set(\"segments\", JSON.stringify(params.segments));\n }\n form.set(\"mode\", mode);\n if (params.outputFormat !== undefined) {\n form.set(\"output_format\", params.outputFormat);\n }\n if (params.variantsNum !== undefined) {\n form.set(\"variants_num\", String(params.variantsNum));\n }\n const res = await this.client.request(\"/v1/text-to-music\", {\n method: \"POST\",\n body: form,\n });\n return (await res.json()) as SfxTask;\n }\n}\n","import { SoniloError } from \"./errors.js\";\nimport type { VideoInput } from \"./types.js\";\n\nconst DEFAULT_FILENAME = \"video.mp4\";\n\n/**\n * Normalize every accepted video input into a FormData-ready Blob.\n * String inputs are file paths and work only in Node.js; browsers must\n * pass File/Blob/bytes/streams.\n */\nexport async function toUploadBlob(\n video: VideoInput,\n): Promise<{ blob: Blob; filename: string }> {\n if (typeof video === \"string\") {\n const isNode =\n typeof process !== \"undefined\" && Boolean((process as { versions?: { node?: string } }).versions?.node);\n if (!isNode) {\n throw new SoniloError(\n \"File paths are only supported in Node.js; pass a File or Blob in the browser\",\n );\n }\n const fsModule = \"node:fs/promises\";\n const { readFile } = (await import(\n /* webpackIgnore: true */ /* @vite-ignore */ fsModule\n )) as typeof import(\"node:fs/promises\");\n const data = await readFile(video);\n const filename = video.split(/[\\\\/]/).pop() || DEFAULT_FILENAME;\n return { blob: new Blob([data]), filename };\n }\n if (typeof File !== \"undefined\" && video instanceof File) {\n return { blob: video, filename: video.name || DEFAULT_FILENAME };\n }\n if (video instanceof Blob) {\n return { blob: video, filename: DEFAULT_FILENAME };\n }\n if (video instanceof Uint8Array) {\n return { blob: new Blob([video as unknown as BlobPart]), filename: DEFAULT_FILENAME };\n }\n if (video instanceof ArrayBuffer) {\n return { blob: new Blob([video]), filename: DEFAULT_FILENAME };\n }\n if (video instanceof ReadableStream) {\n return { blob: await new Response(video).blob(), filename: DEFAULT_FILENAME };\n }\n throw new SoniloError(\"Unsupported video input type\");\n}\n","import type { SoniloClient } from \"../client.js\";\nimport { SoniloError } from \"../errors.js\";\nimport { collectTrack, parseNdjson } from \"../streaming.js\";\nimport { toUploadBlob } from \"../upload.js\";\nimport type { SfxTask, StreamEvent, Track, VideoToMusicParams } from \"../types.js\";\n\nexport class VideoToMusic {\n constructor(private readonly client: SoniloClient) {}\n\n async *stream(params: VideoToMusicParams): AsyncGenerator<StreamEvent, void, undefined> {\n if ((params.video === undefined) === (params.videoUrl === undefined)) {\n throw new SoniloError(\"Provide exactly one of video or videoUrl\");\n }\n const form = new FormData();\n if (params.video !== undefined) {\n const { blob, filename } = await toUploadBlob(params.video);\n form.set(\"video\", blob, filename);\n } else {\n form.set(\"video_url\", params.videoUrl as string);\n }\n if (params.prompt !== undefined) form.set(\"prompt\", params.prompt);\n if (params.segments !== undefined) {\n form.set(\"segments\", JSON.stringify(params.segments));\n }\n // Opt out of the client's absolute request timeout: this holds the\n // response body open and reads NDJSON chunks for as long as generation\n // takes, so an AbortSignal keyed to elapsed time would kill a healthy,\n // still-streaming request (e.g. a slow video upload or long track). Pass\n // `params.signal` yourself to bound or cancel the stream instead — it is\n // forwarded to `fetch` as-is.\n const res = await this.client.request(\n \"/v1/video-to-music\",\n { method: \"POST\", body: form, signal: params.signal },\n { timeout: null },\n );\n if (!res.body) throw new SoniloError(\"Response has no body\");\n yield* parseNdjson(res.body);\n }\n\n generate(params: VideoToMusicParams): Promise<Track> {\n return collectTrack(this.stream(params));\n }\n\n /**\n * Submit an async video-to-music task; poll its result with\n * `client.tasks.wait<MusicTaskResult>(task.task_id)`. Required for\n * `isolateVocals`/`preserveSpeech`, `outputFormat: \"wav\"`, and\n * `variantsNum` above 1 — the backend rejects all of these on the plain\n * stream, and they only ever run in async mode.\n */\n async submit(params: VideoToMusicParams): Promise<SfxTask> {\n if ((params.video === undefined) === (params.videoUrl === undefined)) {\n throw new SoniloError(\"Provide exactly one of video or videoUrl\");\n }\n let mode = params.mode;\n const needsAsync =\n params.isolateVocals ||\n params.preserveSpeech ||\n params.ducking !== undefined ||\n params.outputFormat === \"wav\" ||\n (params.variantsNum !== undefined && params.variantsNum > 1);\n // submit() always wants an async task ack, never a stream. Default to\n // async; only object if the caller explicitly asked for stream while\n // also requesting an async-only feature.\n if (mode === undefined) mode = \"async\";\n if (needsAsync && mode !== \"async\") {\n throw new SoniloError(\n 'isolateVocals/preserveSpeech/ducking/outputFormat \"wav\"/variantsNum > 1 require mode: \"async\"',\n );\n }\n const form = new FormData();\n if (params.video !== undefined) {\n const { blob, filename } = await toUploadBlob(params.video);\n form.set(\"video\", blob, filename);\n } else {\n form.set(\"video_url\", params.videoUrl as string);\n }\n if (params.prompt !== undefined) form.set(\"prompt\", params.prompt);\n if (params.segments !== undefined) {\n form.set(\"segments\", JSON.stringify(params.segments));\n }\n form.set(\"mode\", mode);\n if (params.preserveSpeech !== undefined) {\n form.set(\"preserve_speech\", String(params.preserveSpeech));\n }\n if (params.isolateVocals !== undefined) {\n form.set(\"isolate_vocals\", String(params.isolateVocals));\n }\n if (params.outputFormat !== undefined) {\n form.set(\"output_format\", params.outputFormat);\n }\n if (params.ducking !== undefined) {\n form.set(\"ducking\", String(params.ducking));\n }\n if (params.variantsNum !== undefined) {\n form.set(\"variants_num\", String(params.variantsNum));\n }\n const res = await this.client.request(\"/v1/video-to-music\", {\n method: \"POST\",\n body: form,\n });\n return (await res.json()) as SfxTask;\n }\n}\n","import type { SoniloClient } from \"../client.js\";\nimport type { SfxResult, SfxTask, TextToSfxParams, WaitOptions } from \"../types.js\";\n\nexport class TextToSfx {\n constructor(private readonly client: SoniloClient) {}\n\n async submit(params: TextToSfxParams): Promise<SfxTask> {\n const form = new FormData();\n form.set(\"prompt\", params.prompt);\n form.set(\"duration\", String(params.duration));\n if (params.audioFormat !== undefined) form.set(\"audio_format\", params.audioFormat);\n const res = await this.client.request(\"/v1/text-to-sfx\", {\n method: \"POST\",\n body: form,\n });\n return (await res.json()) as SfxTask;\n }\n\n async generate(params: TextToSfxParams, opts?: WaitOptions): Promise<SfxResult> {\n const task = await this.submit(params);\n return this.client.tasks.wait(task.task_id, opts);\n }\n}\n","import type { SoniloClient } from \"../client.js\";\nimport { SoniloError } from \"../errors.js\";\nimport { toUploadBlob } from \"../upload.js\";\nimport type { SfxResult, SfxTask, VideoToSfxParams, WaitOptions } from \"../types.js\";\n\nexport class VideoToSfx {\n constructor(private readonly client: SoniloClient) {}\n\n async submit(params: VideoToSfxParams): Promise<SfxTask> {\n if ((params.video === undefined) === (params.videoUrl === undefined)) {\n throw new SoniloError(\"Provide exactly one of video or videoUrl\");\n }\n const form = new FormData();\n if (params.video !== undefined) {\n const { blob, filename } = await toUploadBlob(params.video);\n form.set(\"video\", blob, filename);\n } else {\n form.set(\"video_url\", params.videoUrl as string);\n }\n if (params.prompt !== undefined) form.set(\"prompt\", params.prompt);\n if (params.segments !== undefined) {\n form.set(\"segments\", JSON.stringify(params.segments));\n }\n if (params.audioFormat !== undefined) form.set(\"audio_format\", params.audioFormat);\n const res = await this.client.request(\"/v1/video-to-sfx\", {\n method: \"POST\",\n body: form,\n });\n return (await res.json()) as SfxTask;\n }\n\n async generate(params: VideoToSfxParams, opts?: WaitOptions): Promise<SfxResult> {\n const task = await this.submit(params);\n return this.client.tasks.wait(task.task_id, opts);\n }\n}\n","import type { SoniloClient } from \"../client.js\";\nimport { SoniloError } from \"../errors.js\";\nimport { toUploadBlob } from \"../upload.js\";\nimport type { SfxTask, VideoResult, VideoToVideoMusicParams, WaitOptions } from \"../types.js\";\n\n/** Generate an original score for a video and get back a re-hosted video with\n * the music muxed in. Async only: `submit()` returns a task ack; poll with\n * `client.tasks.wait<VideoResult>(id)`, or use `generate()` to do both. */\nexport class VideoToVideoMusic {\n constructor(private readonly client: SoniloClient) {}\n\n async submit(params: VideoToVideoMusicParams): Promise<SfxTask> {\n if ((params.video === undefined) === (params.videoUrl === undefined)) {\n throw new SoniloError(\"Provide exactly one of video or videoUrl\");\n }\n const form = new FormData();\n if (params.video !== undefined) {\n const { blob, filename } = await toUploadBlob(params.video);\n form.set(\"video\", blob, filename);\n } else {\n form.set(\"video_url\", params.videoUrl as string);\n }\n if (params.prompt !== undefined) form.set(\"prompt\", params.prompt);\n if (params.preserveSpeech !== undefined) {\n form.set(\"preserve_speech\", String(params.preserveSpeech));\n }\n if (params.isolateVocals !== undefined) {\n form.set(\"isolate_vocals\", String(params.isolateVocals));\n }\n if (params.variantsNum !== undefined) {\n form.set(\"variants_num\", String(params.variantsNum));\n }\n const res = await this.client.request(\"/v1/video-to-video-music\", {\n method: \"POST\",\n body: form,\n });\n return (await res.json()) as SfxTask;\n }\n\n async generate(params: VideoToVideoMusicParams, opts?: WaitOptions): Promise<VideoResult> {\n const task = await this.submit(params);\n return this.client.tasks.wait<VideoResult>(task.task_id, opts);\n }\n}\n","import type { SoniloClient } from \"../client.js\";\nimport { SoniloError } from \"../errors.js\";\nimport { toUploadBlob } from \"../upload.js\";\nimport type { SfxTask, VideoResult, VideoToVideoSfxParams, WaitOptions } from \"../types.js\";\n\n/** Generate sound effects for a video and get back a re-hosted video with the\n * SFX muxed in. Async only. */\nexport class VideoToVideoSfx {\n constructor(private readonly client: SoniloClient) {}\n\n async submit(params: VideoToVideoSfxParams): Promise<SfxTask> {\n if ((params.video === undefined) === (params.videoUrl === undefined)) {\n throw new SoniloError(\"Provide exactly one of video or videoUrl\");\n }\n const form = new FormData();\n if (params.video !== undefined) {\n const { blob, filename } = await toUploadBlob(params.video);\n form.set(\"video\", blob, filename);\n } else {\n form.set(\"video_url\", params.videoUrl as string);\n }\n if (params.prompt !== undefined) form.set(\"prompt\", params.prompt);\n if (params.segments !== undefined) {\n form.set(\"segments\", JSON.stringify(params.segments));\n }\n const res = await this.client.request(\"/v1/video-to-video-sfx\", {\n method: \"POST\",\n body: form,\n });\n return (await res.json()) as SfxTask;\n }\n\n async generate(params: VideoToVideoSfxParams, opts?: WaitOptions): Promise<VideoResult> {\n const task = await this.submit(params);\n return this.client.tasks.wait<VideoResult>(task.task_id, opts);\n }\n}\n","import { SoniloError } from \"../errors.js\";\nimport { toUploadBlob } from \"../upload.js\";\nimport type { VideoToSoundParams } from \"../types.js\";\n\n/** Build the multipart body shared by /v1/video-to-sound and\n * /v1/video-to-video-sound — their form fields are identical, so the two\n * resources differ only in the path they POST to.\n *\n * Every optional field is omitted when unset rather than sent with a default:\n * `ducking` in particular is default-ON server-side, so an unset value must\n * not become an explicit \"false\" on the wire. */\nexport async function buildSoundForm(params: VideoToSoundParams): Promise<FormData> {\n if ((params.video === undefined) === (params.videoUrl === undefined)) {\n throw new SoniloError(\"Provide exactly one of video or videoUrl\");\n }\n const form = new FormData();\n if (params.video !== undefined) {\n const { blob, filename } = await toUploadBlob(params.video);\n form.set(\"video\", blob, filename);\n } else {\n form.set(\"video_url\", params.videoUrl as string);\n }\n if (params.musicPrompt !== undefined) form.set(\"music_prompt\", params.musicPrompt);\n if (params.sfxPrompt !== undefined) form.set(\"sfx_prompt\", params.sfxPrompt);\n if (params.segments !== undefined) {\n form.set(\"segments\", JSON.stringify(params.segments));\n }\n if (params.preserveSpeech !== undefined) {\n form.set(\"preserve_speech\", String(params.preserveSpeech));\n }\n if (params.ducking !== undefined) form.set(\"ducking\", String(params.ducking));\n if (params.variantsNum !== undefined) {\n form.set(\"variants_num\", String(params.variantsNum));\n }\n return form;\n}\n","import type { SoniloClient } from \"../client.js\";\nimport { buildSoundForm } from \"./soundForm.js\";\nimport type { SfxTask, SoundResult, VideoToSoundParams, WaitOptions } from \"../types.js\";\n\n/** Generate a combined music + sound-effects track for a video and get back\n * the mixed audio. Async only. */\nexport class VideoToSound {\n constructor(private readonly client: SoniloClient) {}\n\n async submit(params: VideoToSoundParams): Promise<SfxTask> {\n const res = await this.client.request(\"/v1/video-to-sound\", {\n method: \"POST\",\n body: await buildSoundForm(params),\n });\n return (await res.json()) as SfxTask;\n }\n\n async generate(params: VideoToSoundParams, opts?: WaitOptions): Promise<SoundResult> {\n const task = await this.submit(params);\n return this.client.tasks.wait<SoundResult>(task.task_id, opts);\n }\n}\n","import type { SoniloClient } from \"../client.js\";\nimport { buildSoundForm } from \"./soundForm.js\";\nimport type { SfxTask, SoundResult, VideoToSoundParams, WaitOptions } from \"../types.js\";\n\n/** Generate a combined music + sound-effects track for a video and get back a\n * re-hosted video with that track muxed in. Async only. */\nexport class VideoToVideoSound {\n constructor(private readonly client: SoniloClient) {}\n\n async submit(params: VideoToSoundParams): Promise<SfxTask> {\n const res = await this.client.request(\"/v1/video-to-video-sound\", {\n method: \"POST\",\n body: await buildSoundForm(params),\n });\n return (await res.json()) as SfxTask;\n }\n\n async generate(params: VideoToSoundParams, opts?: WaitOptions): Promise<SoundResult> {\n const task = await this.submit(params);\n return this.client.tasks.wait<SoundResult>(task.task_id, opts);\n }\n}\n","import type { SoniloClient } from \"../client.js\";\nimport { SoniloError } from \"../errors.js\";\nimport { toUploadBlob } from \"../upload.js\";\nimport type { DubbingParams, DubbingResult, SfxTask, WaitOptions } from \"../types.js\";\n\n/** Build the multipart body for /v1/dubbing.\n *\n * `languages` travels as one opaque form field holding a JSON array string —\n * that is the shape the backend parses. It is omitted entirely when unset so\n * the server default ([\"zh_cn\", \"es\", \"fr\"]) applies; sending an empty array\n * instead would be rejected as a malformed payload.\n *\n * The https check is local because it is a guaranteed server-side 422: the\n * dubbing pipeline fetches the source URL itself and requires https\n * specifically, unlike the fal-backed endpoints, which accept plain http.\n * Language codes are deliberately NOT checked here — the backend owns that\n * list, and a hardcoded copy would make this SDK reject codes added later. */\nexport async function buildDubbingForm(params: DubbingParams): Promise<FormData> {\n if ((params.video === undefined) === (params.videoUrl === undefined)) {\n throw new SoniloError(\"Provide exactly one of video or videoUrl\");\n }\n const form = new FormData();\n if (params.video !== undefined) {\n const { blob, filename } = await toUploadBlob(params.video);\n form.set(\"video\", blob, filename);\n } else {\n const url = params.videoUrl as string;\n if (!url.toLowerCase().startsWith(\"https://\")) {\n throw new SoniloError(\n \"videoUrl must use https — the dubbing pipeline requires an https URL\",\n );\n }\n form.set(\"video_url\", url);\n }\n if (params.languages !== undefined) {\n form.set(\"languages\", JSON.stringify(params.languages));\n }\n return form;\n}\n\n/** Dub a video into one or more target languages. Async only; the result\n * carries a language → dubbed-video-URL map under `outputs`. */\nexport class Dubbing {\n constructor(private readonly client: SoniloClient) {}\n\n async submit(params: DubbingParams): Promise<SfxTask> {\n const res = await this.client.request(\"/v1/dubbing\", {\n method: \"POST\",\n body: await buildDubbingForm(params),\n });\n return (await res.json()) as SfxTask;\n }\n\n async generate(params: DubbingParams, opts?: WaitOptions): Promise<DubbingResult> {\n const task = await this.submit(params);\n return this.client.tasks.wait<DubbingResult>(task.task_id, opts);\n }\n}\n","/** The SDK's own version. Generated by scripts/sync-versions.mjs — do not edit. */\nexport const VERSION = \"0.8.0\";\n","import { RequestTimeoutError, SoniloError, errorFromResponse, isTimeoutSignalError } from \"./errors.js\";\nimport { Account } from \"./resources/account.js\";\nimport { Tasks } from \"./resources/tasks.js\";\nimport { TextToMusic } from \"./resources/textToMusic.js\";\nimport { VideoToMusic } from \"./resources/videoToMusic.js\";\nimport { TextToSfx } from \"./resources/textToSfx.js\";\nimport { VideoToSfx } from \"./resources/videoToSfx.js\";\nimport { VideoToVideoMusic } from \"./resources/videoToVideoMusic.js\";\nimport { VideoToVideoSfx } from \"./resources/videoToVideoSfx.js\";\nimport { VideoToSound } from \"./resources/videoToSound.js\";\nimport { VideoToVideoSound } from \"./resources/videoToVideoSound.js\";\nimport { Dubbing } from \"./resources/dubbing.js\";\nimport { VERSION } from \"./version.js\";\n\nexport interface SoniloClientOptions {\n /** Defaults to the SONILO_API_KEY environment variable (Node.js only). */\n apiKey?: string;\n /** Defaults to https://api.sonilo.com */\n baseUrl?: string;\n /** Injection point for tests and custom transports. */\n fetch?: typeof globalThis.fetch;\n /** Milliseconds before an in-flight request is aborted. Default 600000. */\n timeout?: number;\n /**\n * Identifies a wrapper built on this SDK (the CLI, the video kit) in the\n * `X-Sonilo-Client` header. Leave unset for direct SDK use — without an\n * override a wrapper's traffic is indistinguishable from the SDK's own.\n */\n clientName?: string;\n /** Version reported alongside `clientName`. Defaults to the SDK's version. */\n clientVersion?: string;\n}\n\nconst DEFAULT_BASE_URL = \"https://api.sonilo.com\";\n\n/**\n * Reported in `X-Sonilo-Client` unless a wrapper overrides it. First-party\n * wrappers (the CLI, the video kit) pass their own name so their traffic stays\n * distinguishable from direct SDK use in server-side analytics.\n */\nexport const DEFAULT_CLIENT_NAME = \"sdk-js\";\n\n/** Milliseconds before an in-flight request is aborted, unless overridden. */\nexport const DEFAULT_TIMEOUT_MS = 600_000;\n\nexport class SoniloClient {\n readonly baseUrl: string;\n private readonly apiKey: string;\n private readonly fetchFn: typeof globalThis.fetch;\n private readonly timeout: number;\n private readonly clientName: string;\n private readonly clientVersion: string;\n readonly account: Account;\n readonly tasks: Tasks;\n readonly textToMusic: TextToMusic;\n readonly videoToMusic: VideoToMusic;\n readonly textToSfx: TextToSfx;\n readonly videoToSfx: VideoToSfx;\n readonly videoToVideoMusic: VideoToVideoMusic;\n readonly videoToVideoSfx: VideoToVideoSfx;\n readonly videoToSound: VideoToSound;\n readonly videoToVideoSound: VideoToVideoSound;\n readonly dubbing: Dubbing;\n\n constructor(options: SoniloClientOptions = {}) {\n const envKey =\n typeof process !== \"undefined\" ? process.env?.SONILO_API_KEY : undefined;\n const apiKey = options.apiKey ?? envKey;\n if (!apiKey) {\n throw new SoniloError(\n \"Missing API key: pass { apiKey } or set the SONILO_API_KEY environment variable\",\n );\n }\n this.apiKey = apiKey;\n this.baseUrl = (options.baseUrl ?? DEFAULT_BASE_URL).replace(/\\/+$/, \"\");\n this.fetchFn = (options.fetch ?? globalThis.fetch).bind(globalThis);\n this.timeout = options.timeout ?? DEFAULT_TIMEOUT_MS;\n this.clientName = options.clientName ?? DEFAULT_CLIENT_NAME;\n this.clientVersion = options.clientVersion ?? VERSION;\n this.account = new Account(this);\n this.tasks = new Tasks(this);\n this.textToMusic = new TextToMusic(this);\n this.videoToMusic = new VideoToMusic(this);\n this.textToSfx = new TextToSfx(this);\n this.videoToSfx = new VideoToSfx(this);\n this.videoToVideoMusic = new VideoToVideoMusic(this);\n this.videoToVideoSfx = new VideoToVideoSfx(this);\n this.videoToSound = new VideoToSound(this);\n this.videoToVideoSound = new VideoToVideoSound(this);\n this.dubbing = new Dubbing(this);\n }\n\n /**\n * Perform an authenticated request; throws a typed error on non-2xx.\n *\n * `opts.timeout` overrides the client's default timeout for this call;\n * pass `null` to disable the abort-on-timeout behavior entirely (used by\n * the streaming music endpoints — see textToMusic.ts / videoToMusic.ts).\n * A caller-supplied `init.signal` always wins over any timeout signal.\n */\n async request(\n path: string,\n init: RequestInit = {},\n opts: { timeout?: number | null } = {},\n ): Promise<Response> {\n const headers = new Headers(init.headers);\n headers.set(\"Authorization\", `Bearer ${this.apiKey}`);\n headers.set(\"X-Sonilo-Client\", this.clientName);\n headers.set(\"X-Sonilo-Client-Version\", this.clientVersion);\n const timeout = opts.timeout === undefined ? this.timeout : opts.timeout;\n // We only \"own\" the signal (and may later rewrap its abort as a\n // RequestTimeoutError) when the caller didn't supply one and a timeout\n // is actually enabled.\n const ownsSignal = init.signal == null && timeout !== null;\n const signal = init.signal ?? (timeout === null ? undefined : AbortSignal.timeout(timeout));\n try {\n const res = await this.fetchFn(`${this.baseUrl}${path}`, { ...init, headers, signal });\n if (!res.ok) throw await errorFromResponse(res);\n return res;\n } catch (err) {\n if (ownsSignal && isTimeoutSignalError(err)) {\n throw new RequestTimeoutError(`Request to ${path} timed out after ${timeout}ms`);\n }\n throw err;\n }\n }\n}\n","import { DEFAULT_TIMEOUT_MS } from \"./client.js\";\nimport { RequestTimeoutError, SoniloError, isTimeoutSignalError } from \"./errors.js\";\nimport type { SfxMedia } from \"./types.js\";\n\n/** Fetch a result media file. The URL is presigned — no API key is sent.\n *\n * Accepts either a media object (`result.audio`, `result.music`, …) or a bare\n * URL string, which is what the combined video-to-sound endpoints return as\n * `output_url`. */\nexport async function download(\n media: SfxMedia | string | undefined,\n fetchFn: typeof globalThis.fetch = globalThis.fetch,\n timeout: number = DEFAULT_TIMEOUT_MS,\n): Promise<Uint8Array> {\n const url = typeof media === \"string\" ? media : media?.url;\n if (!url) {\n throw new SoniloError(\"No media to download\");\n }\n let res: Response;\n try {\n res = await fetchFn(url, { signal: AbortSignal.timeout(timeout) });\n } catch (err) {\n if (isTimeoutSignalError(err)) {\n throw new RequestTimeoutError(`Download of ${url} timed out after ${timeout}ms`);\n }\n throw err;\n }\n if (!res.ok) {\n throw new SoniloError(`Download failed: HTTP ${res.status}`);\n }\n return new Uint8Array(await res.arrayBuffer());\n}\n","export type SegmentLabel =\n | \"intro\"\n | \"verse\"\n | \"pre-chorus\"\n | \"chorus\"\n | \"bridge\"\n | \"break\"\n | \"silence\"\n | \"outro\"\n | \"none\";\n\nexport interface Segment {\n start: number;\n prompt: string;\n label?: SegmentLabel;\n}\n\n/** Monetary fields are strings, exactly as the backend serializes them. */\nexport interface CostInfo {\n billing_rate_per_sec: string;\n billing_before_discount: string;\n billing_after_discount: string;\n discount_factor: string;\n}\n\nexport interface AudioChunkEvent {\n type: \"audio_chunk\";\n /** Decoded from the wire's base64 by the SDK. */\n data: Uint8Array;\n}\n\nexport interface TitleEvent {\n type: \"title\";\n title: string;\n summary?: string;\n display_tags?: string[];\n [key: string]: unknown;\n}\n\nexport interface CompleteEvent {\n type: \"complete\";\n [key: string]: unknown;\n}\n\nexport interface ErrorEvent {\n type: \"error\";\n code?: string;\n message?: string;\n [key: string]: unknown;\n}\n\nexport interface CostEvent extends CostInfo {\n type: \"cost\";\n}\n\n/** Forward-compatibility: unrecognized event types are passed through. */\nexport interface UnknownEvent {\n type: string;\n [key: string]: unknown;\n}\n\nexport type StreamEvent =\n | AudioChunkEvent\n | TitleEvent\n | CompleteEvent\n | ErrorEvent\n | CostEvent\n | UnknownEvent;\n\nexport interface Track {\n audio: Uint8Array;\n title?: string;\n cost?: CostInfo;\n}\n\nexport interface TextToMusicParams {\n prompt: string;\n duration: number;\n segments?: Segment[];\n /** \"stream\" (default) or \"async\" (required by `submit()` and `output_format: \"wav\"`). */\n mode?: \"stream\" | \"async\";\n /** Container for the async result. `wav` requires `mode: \"async\"`. Defaults to m4a server-side. */\n outputFormat?: \"m4a\" | \"wav\";\n /** How many distinct music variants to generate in one request (1-10,\n * default 1). Cost scales linearly, and values above 1 are never covered\n * by the free trial. Values above 1 require `mode: \"async\"` — only\n * meaningful via `submit()`; `stream()`/`generate()` never send it, since\n * they always request a plain stream. */\n variantsNum?: number;\n /** Bounds the stream: aborting this cancels the in-flight generation.\n * Passed straight through to `fetch` — it is never rewrapped as\n * RequestTimeoutError, since the client's own absolute timeout does not\n * apply to streaming music generation. */\n signal?: AbortSignal;\n}\n\n/** string = file path (Node.js only). */\nexport type VideoInput =\n | File\n | Blob\n | Uint8Array\n | ArrayBuffer\n | ReadableStream<Uint8Array>\n | string;\n\nexport interface VideoToMusicParams {\n video?: VideoInput;\n videoUrl?: string;\n prompt?: string;\n segments?: Segment[];\n /** Bounds the stream: aborting this cancels the in-flight generation.\n * Passed straight through to `fetch` — it is never rewrapped as\n * RequestTimeoutError, since the client's own absolute timeout does not\n * apply to streaming music generation. Only meaningful for `stream()`/\n * `generate()`; `submit()` ignores it. */\n signal?: AbortSignal;\n /** \"stream\" (the default, used by `stream()`/`generate()`) or \"async\"\n * (required for `submit()`, and for `isolateVocals`). Only consulted by\n * `submit()` — `stream()`/`generate()` always request a stream. */\n mode?: \"stream\" | \"async\";\n /** Split the generated track into a vocals-only stem alongside the mix.\n * Requires `mode: \"async\"`; if `mode` is left unset it defaults to\n * \"async\" automatically. Only usable via `submit()` — the backend\n * rejects it on the plain stream. */\n isolateVocals?: boolean;\n /** Keep the source speech/vocals in the async result. Current name for\n * `isolateVocals`; both are accepted and OR'd server-side. Requires\n * `mode: \"async\"` (auto-selected by `submit()`). */\n preserveSpeech?: boolean;\n /** Container for the async result. `wav` requires async. Defaults to m4a. */\n outputFormat?: \"m4a\" | \"wav\";\n /** Duck the generated music under the source voice at finalize time.\n * Default-ON server-side in async mode: leave unset to keep it on, pass\n * `false` to opt out. Free, best-effort; only valid on `submit()`. */\n ducking?: boolean;\n /** How many distinct music variants to generate in one request (1-10,\n * default 1). Cost scales linearly, and values above 1 are never covered\n * by the free trial. Values above 1 require `mode: \"async\"` (auto-selected\n * by `submit()`) — only meaningful via `submit()`; `stream()`/`generate()`\n * never send it, since they always request a plain stream. */\n variantsNum?: number;\n}\n\n/** One service's free-trial allowance. `remaining` is already floored at 0,\n * so it is safe to compare directly. */\nexport interface TrialQuota {\n granted: number;\n used: number;\n remaining: number;\n}\n\nexport interface AccountServices {\n available_services: string[];\n rpm_limit: number;\n concurrency_limit: number;\n discount_factor: number | string;\n max_upload_size_mb: number | null;\n /** Free-trial allowance keyed by service (`granted` / `used` /\n * `remaining`). Present only for self-serve accounts — always treat it as\n * possibly absent, and treat a service missing from the map as \"no trial\n * allowance\", not as an error. */\n trial?: Record<string, TrialQuota>;\n}\n\nexport interface UsageSummary {\n total_requests: number;\n total_duration_seconds: number;\n total_cost: number | string;\n period_start: string;\n period_end: string;\n [key: string]: unknown;\n}\n\nexport interface DailyUsage {\n date: string;\n requests: number;\n duration_seconds: number;\n cost: number | string;\n}\n\nexport interface UsageResponse {\n summary: UsageSummary;\n daily: DailyUsage[];\n}\n\nexport function isAudioChunkEvent(event: StreamEvent): event is AudioChunkEvent {\n return event.type === \"audio_chunk\" && (event as AudioChunkEvent).data instanceof Uint8Array;\n}\n\nexport function isErrorEvent(event: StreamEvent): event is ErrorEvent {\n return event.type === \"error\";\n}\n\n/** SFX segments (unlike music `Segment`) require `end`, must start at 0,\n * and be contiguous; validated server-side. */\nexport interface SfxSegment {\n start: number;\n end: number;\n prompt: string;\n}\n\nexport type SfxAudioFormat = \"wav\" | \"mp3\" | \"aac\" | \"flac\";\n\n/** Submission ack for the async SFX endpoints. */\nexport interface SfxTask {\n task_id: string;\n status: string;\n}\n\n/** A generated file re-hosted on R2 behind a presigned URL. */\nexport interface SfxMedia {\n url: string;\n content_type?: string;\n file_size?: number;\n}\n\nexport interface SfxError {\n code?: string;\n message?: string;\n}\n\n/**\n * Common shape of any polled task (`tasks.get`/`tasks.wait`), regardless of\n * which endpoint created it. `Tasks.get`/`Tasks.wait` are generic over this so\n * each endpoint's result type (e.g. `SfxResult`, `MusicTaskResult`) can add\n * its own `audio`/media fields while sharing the status/error/refund\n * bookkeeping the poller relies on.\n */\nexport interface BaseTaskResult {\n task_id: string;\n type?: string;\n status: \"processing\" | \"succeeded\" | \"failed\" | (string & {});\n /** Only present when the account's task-field whitelist enables cost. */\n cost?: number;\n error?: SfxError;\n refunded?: boolean;\n /** Echoes the request's `variantsNum`. Present regardless of task status\n * (so a `processing`/`failed` poll explains the charge too), but only\n * when it was above 1 — a default (single-variant) request sees the same\n * shape it always has. */\n variants_num?: number;\n [key: string]: unknown;\n}\n\n/** State of an SFX task (`tasks.get`) or its final result (`wait`/`generate`). */\nexport interface SfxResult extends BaseTaskResult {\n audio?: SfxMedia;\n /** Kept for backward compatibility; no longer populated — video-to-sfx returns audio only. */\n video?: SfxMedia;\n}\n\nexport interface TextToSfxParams {\n prompt: string;\n duration: number;\n audioFormat?: SfxAudioFormat;\n}\n\nexport interface VideoToSfxParams {\n video?: VideoInput;\n videoUrl?: string;\n prompt?: string;\n segments?: SfxSegment[];\n audioFormat?: SfxAudioFormat;\n}\n\n/** One decoded audio stream of an async video-to-music result. Unlike SFX,\n * `audio` on a music task is always an array — even without `isolateVocals` —\n * since a music generation can carry more than one output stream. */\nexport interface MusicMediaEntry extends SfxMedia {\n stream_index: number;\n sample_rate?: number;\n channels?: number;\n /** This entry's own title, present when `variantsNum` was above 1 (and\n * titles are visible on the account). Each variant is a distinct creative\n * direction, so it can carry its own title rather than sharing the\n * top-level `MusicTaskResult.title`, which always names variant 0. */\n title?: MusicTitle;\n}\n\n/** One muxed audio+video-aligned output, present only when `isolateVocals`\n * is set. */\nexport interface MusicMuxEntry extends SfxMedia {\n stream_index: number;\n}\n\nexport interface MusicTitle {\n title: string;\n summary?: string;\n display_tags?: string[];\n}\n\n/** State of an async video-to-music task (`tasks.get`) or its final result\n * (`tasks.wait<MusicTaskResult>()`). Only reachable via `videoToMusic.submit()`\n * with `mode: \"async\"`. */\nexport interface MusicTaskResult extends BaseTaskResult {\n /** One entry per stream, or one entry per variant when `variantsNum` was\n * greater than 1 — each variant entry may carry its own `title`. */\n audio?: MusicMediaEntry[];\n /** Vocals-only stem; present only when `isolateVocals` was requested. */\n vocals?: SfxMedia;\n /** Muxed output per stream (or per variant); present only when\n * `isolateVocals` was requested. */\n mux?: MusicMuxEntry[];\n /** Music ducked under the source voice (per variant when `variantsNum` is\n * above 1); present only when `ducking` ran. */\n ducked?: MusicMediaEntry[];\n /** Variant 0's title — the top-level field always names the first variant,\n * even when `variantsNum` produced others with their own titles on\n * `audio[]`. */\n title?: MusicTitle;\n duration_seconds?: number;\n}\n\nexport interface WaitOptions {\n /** Milliseconds between polls. Default 2000. */\n pollInterval?: number;\n /** Overall deadline in milliseconds. Default 600000. */\n timeout?: number;\n}\n\n/** Result of an async video-to-video task (`videoToVideoMusic`/`videoToVideoSfx`):\n * a re-hosted video with generated music or SFX muxed in. */\nexport interface VideoResult extends BaseTaskResult {\n /** One re-hosted video per variant. On `videoToVideoMusic` this is\n * populated even at the default `variantsNum` of 1 (as a single-entry\n * array); `videoToVideoSfx` has no variants knob and always sends one. */\n videos?: SfxMedia[];\n /** Permanent alias for `videos[0]`. */\n video?: SfxMedia;\n duration_seconds?: number;\n}\n\nexport interface VideoToVideoMusicParams {\n video?: VideoInput;\n videoUrl?: string;\n prompt?: string;\n /** Keep the source speech/vocals in the output. Both this and the legacy\n * `isolateVocals` are accepted and OR'd server-side. */\n preserveSpeech?: boolean;\n /** @deprecated Legacy alias for `preserveSpeech`. */\n isolateVocals?: boolean;\n /** How many distinct music variants to generate in one request (1-10,\n * default 1). Cost scales linearly, and values above 1 are never covered\n * by the free trial. This endpoint is always async, so no extra `mode`\n * gating applies. The result's `videos[]` gets one entry per variant. */\n variantsNum?: number;\n}\n\nexport interface VideoToVideoSfxParams {\n video?: VideoInput;\n videoUrl?: string;\n prompt?: string;\n segments?: SfxSegment[];\n}\n\n/** Params for `videoToSound` and `videoToVideoSound`. Both endpoints take the\n * identical form, so they share one params type. */\nexport interface VideoToSoundParams {\n video?: VideoInput;\n videoUrl?: string;\n /** Style hint for the generated music bed. */\n musicPrompt?: string;\n /** Description of the sound effects layered over the music. */\n sfxPrompt?: string;\n /** Per-segment SFX descriptions; must start at 0 and be contiguous. */\n segments?: SfxSegment[];\n /** Keep the source speech in the result. */\n preserveSpeech?: boolean;\n /** Duck the generated music under the source speech. Default-ON\n * server-side: leave unset to keep it on, pass `false` to opt out. */\n ducking?: boolean;\n /** How many distinct variants to generate in one request (1-10, default\n * 1). Cost scales linearly, and values above 1 are never covered by the\n * free trial. Both `videoToSound` and `videoToVideoSound` are always\n * async, so no extra `mode` gating applies. The result's `outputs[]` gets\n * one entry per variant. */\n variantsNum?: number;\n}\n\n/** One variant's outputs on a `videoToSound` / `videoToVideoSound` result.\n * Present even at the default `variantsNum` of 1, as a single-entry array. */\nexport interface SoundOutputEntry {\n variant_index: number;\n output_url: string;\n output_type: \"audio\" | \"video\";\n output_bytes: number;\n music?: SfxMedia;\n /** Present only when `preserveSpeech`/`ducking` altered this variant's music bed. */\n music_processed?: SfxMedia;\n sfx?: SfxMedia;\n}\n\n/** Result of a `videoToSound` / `videoToVideoSound` task (`tasks.get`) or its\n * final state (`generate`).\n *\n * The combined music+SFX result is `output_url` — a bare presigned URL rather\n * than a media object, since these endpoints render one artifact whose kind is\n * announced by `output_type` (\"audio\" for video-to-sound, \"video\" for\n * video-to-video-sound). `music`, `music_processed` and `sfx` are the\n * individual stems; pass any of them, or `output_url` itself, to `download()`.\n *\n * `outputs` carries the same fields per variant when `variantsNum` was\n * greater than 1; `output_url`/`output_type`/`output_bytes`/`music`/\n * `music_processed`/`sfx` remain permanent aliases for `outputs[0]`. */\nexport interface SoundResult extends BaseTaskResult {\n output_url?: string;\n output_type?: \"audio\" | \"video\";\n output_bytes?: number;\n music?: SfxMedia;\n /** Present only when `preserveSpeech`/`ducking` altered the music bed. */\n music_processed?: SfxMedia;\n sfx?: SfxMedia;\n duration_seconds?: number;\n /** One entry per variant; see `SoundOutputEntry`. */\n outputs?: SoundOutputEntry[];\n}\n\n/**\n * A target language for /v1/dubbing. The union stays open (`string & {}`) so a\n * language added server-side still type-checks against an older SDK — the\n * backend, not this list, is the authority on what is supported.\n */\nexport type DubbingLanguage =\n | \"en\"\n | \"zh_cn\"\n | \"ja\"\n | \"ko\"\n | \"pt\"\n | \"es\"\n | \"de\"\n | \"fr\"\n | \"it\"\n | \"ru\"\n | (string & {});\n\nexport interface DubbingParams {\n /** Exactly one of `video` / `videoUrl`. */\n video?: VideoInput;\n /**\n * Exactly one of `video` / `videoUrl`. Must be an `https://` URL — the\n * dubbing pipeline fetches the source itself and rejects plain http.\n */\n videoUrl?: string;\n /** Omit to get the server default, `[\"zh_cn\", \"es\", \"fr\"]`. */\n languages?: DubbingLanguage[];\n}\n\nexport interface DubbingResult extends BaseTaskResult {\n /**\n * One dubbed video URL per requested language, keyed by language code.\n * Unlike every other endpoint's envelope this is a map, not an `audio`/\n * `video` slot — a dubbing task renders N artifacts, one per language.\n */\n outputs?: Record<string, string>;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAO,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,UAAM,MAAM,MAAM,KAAK,OAAO,QAAQ,qBAAqB;AAAA,MACzD,QAAQ;AAAA,MACR,MAAM;AAAA,IACR,CAAC;AACD,WAAQ,MAAM,IAAI,KAAK;AAAA,EACzB;AACF;;;AC9DA,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;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,UACnB,OAAO,iBAAiB,SACvB,OAAO,gBAAgB,UAAa,OAAO,cAAc;AAI5D,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,UAAM,MAAM,MAAM,KAAK,OAAO,QAAQ,sBAAsB;AAAA,MAC1D,QAAQ;AAAA,MACR,MAAM;AAAA,IACR,CAAC;AACD,WAAQ,MAAM,IAAI,KAAK;AAAA,EACzB;AACF;;;ACpGO,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,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;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;;;ACpCO,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;;;ACzBA,eAAsB,eAAe,QAA+C;AAClF,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,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,gBAAgB,QAAW;AACpC,SAAK,IAAI,gBAAgB,OAAO,OAAO,WAAW,CAAC;AAAA,EACrD;AACA,SAAO;AACT;;;AC7BO,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;;;ACfO,IAAM,oBAAN,MAAwB;AAAA,EAC7B,YAA6B,QAAsB;AAAtB;AAAA,EAAuB;AAAA,EAEpD,MAAM,OAAO,QAA8C;AACzD,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,QAA4B,MAA0C;AACnF,UAAM,OAAO,MAAM,KAAK,OAAO,MAAM;AACrC,WAAO,KAAK,OAAO,MAAM,KAAkB,KAAK,SAAS,IAAI;AAAA,EAC/D;AACF;;;ACJA,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,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;;;ACxDO,IAAM,UAAU;;;ACgCvB,IAAM,mBAAmB;AAOlB,IAAM,sBAAsB;AAG5B,IAAM,qBAAqB;AAE3B,IAAM,eAAN,MAAmB;AAAA,EAmBxB,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,UAAU,IAAI,QAAQ,IAAI;AAAA,EACjC;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;;;ACrHA,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;;;AC0JO,SAAS,kBAAkB,OAA8C;AAC9E,SAAO,MAAM,SAAS,iBAAkB,MAA0B,gBAAgB;AACpF;AAEO,SAAS,aAAa,OAAyC;AACpE,SAAO,MAAM,SAAS;AACxB;","names":[]}
package/dist/index.d.cts CHANGED
@@ -55,6 +55,12 @@ interface TextToMusicParams {
55
55
  mode?: "stream" | "async";
56
56
  /** Container for the async result. `wav` requires `mode: "async"`. Defaults to m4a server-side. */
57
57
  outputFormat?: "m4a" | "wav";
58
+ /** How many distinct music variants to generate in one request (1-10,
59
+ * default 1). Cost scales linearly, and values above 1 are never covered
60
+ * by the free trial. Values above 1 require `mode: "async"` — only
61
+ * meaningful via `submit()`; `stream()`/`generate()` never send it, since
62
+ * they always request a plain stream. */
63
+ variantsNum?: number;
58
64
  /** Bounds the stream: aborting this cancels the in-flight generation.
59
65
  * Passed straight through to `fetch` — it is never rewrapped as
60
66
  * RequestTimeoutError, since the client's own absolute timeout does not
@@ -93,7 +99,15 @@ interface VideoToMusicParams {
93
99
  * Default-ON server-side in async mode: leave unset to keep it on, pass
94
100
  * `false` to opt out. Free, best-effort; only valid on `submit()`. */
95
101
  ducking?: boolean;
96
- }
102
+ /** How many distinct music variants to generate in one request (1-10,
103
+ * default 1). Cost scales linearly, and values above 1 are never covered
104
+ * by the free trial. Values above 1 require `mode: "async"` (auto-selected
105
+ * by `submit()`) — only meaningful via `submit()`; `stream()`/`generate()`
106
+ * never send it, since they always request a plain stream. */
107
+ variantsNum?: number;
108
+ }
109
+ /** One service's free-trial allowance. `remaining` is already floored at 0,
110
+ * so it is safe to compare directly. */
97
111
  interface TrialQuota {
98
112
  granted: number;
99
113
  used: number;
@@ -105,8 +119,10 @@ interface AccountServices {
105
119
  concurrency_limit: number;
106
120
  discount_factor: number | string;
107
121
  max_upload_size_mb: number | null;
108
- /** Free-trial allowance keyed by service. Returned only for self-serve
109
- * accounts; absent entirely for invoiced accounts. */
122
+ /** Free-trial allowance keyed by service (`granted` / `used` /
123
+ * `remaining`). Present only for self-serve accounts — always treat it as
124
+ * possibly absent, and treat a service missing from the map as "no trial
125
+ * allowance", not as an error. */
110
126
  trial?: Record<string, TrialQuota>;
111
127
  }
112
128
  interface UsageSummary {
@@ -167,6 +183,11 @@ interface BaseTaskResult {
167
183
  cost?: number;
168
184
  error?: SfxError;
169
185
  refunded?: boolean;
186
+ /** Echoes the request's `variantsNum`. Present regardless of task status
187
+ * (so a `processing`/`failed` poll explains the charge too), but only
188
+ * when it was above 1 — a default (single-variant) request sees the same
189
+ * shape it always has. */
190
+ variants_num?: number;
170
191
  [key: string]: unknown;
171
192
  }
172
193
  /** State of an SFX task (`tasks.get`) or its final result (`wait`/`generate`). */
@@ -194,6 +215,11 @@ interface MusicMediaEntry extends SfxMedia {
194
215
  stream_index: number;
195
216
  sample_rate?: number;
196
217
  channels?: number;
218
+ /** This entry's own title, present when `variantsNum` was above 1 (and
219
+ * titles are visible on the account). Each variant is a distinct creative
220
+ * direction, so it can carry its own title rather than sharing the
221
+ * top-level `MusicTaskResult.title`, which always names variant 0. */
222
+ title?: MusicTitle;
197
223
  }
198
224
  /** One muxed audio+video-aligned output, present only when `isolateVocals`
199
225
  * is set. */
@@ -209,13 +235,20 @@ interface MusicTitle {
209
235
  * (`tasks.wait<MusicTaskResult>()`). Only reachable via `videoToMusic.submit()`
210
236
  * with `mode: "async"`. */
211
237
  interface MusicTaskResult extends BaseTaskResult {
238
+ /** One entry per stream, or one entry per variant when `variantsNum` was
239
+ * greater than 1 — each variant entry may carry its own `title`. */
212
240
  audio?: MusicMediaEntry[];
213
241
  /** Vocals-only stem; present only when `isolateVocals` was requested. */
214
242
  vocals?: SfxMedia;
215
- /** Muxed output per stream; present only when `isolateVocals` was requested. */
243
+ /** Muxed output per stream (or per variant); present only when
244
+ * `isolateVocals` was requested. */
216
245
  mux?: MusicMuxEntry[];
217
- /** Music ducked under the source voice; present only when `ducking` ran. */
246
+ /** Music ducked under the source voice (per variant when `variantsNum` is
247
+ * above 1); present only when `ducking` ran. */
218
248
  ducked?: MusicMediaEntry[];
249
+ /** Variant 0's title — the top-level field always names the first variant,
250
+ * even when `variantsNum` produced others with their own titles on
251
+ * `audio[]`. */
219
252
  title?: MusicTitle;
220
253
  duration_seconds?: number;
221
254
  }
@@ -228,6 +261,11 @@ interface WaitOptions {
228
261
  /** Result of an async video-to-video task (`videoToVideoMusic`/`videoToVideoSfx`):
229
262
  * a re-hosted video with generated music or SFX muxed in. */
230
263
  interface VideoResult extends BaseTaskResult {
264
+ /** One re-hosted video per variant. On `videoToVideoMusic` this is
265
+ * populated even at the default `variantsNum` of 1 (as a single-entry
266
+ * array); `videoToVideoSfx` has no variants knob and always sends one. */
267
+ videos?: SfxMedia[];
268
+ /** Permanent alias for `videos[0]`. */
231
269
  video?: SfxMedia;
232
270
  duration_seconds?: number;
233
271
  }
@@ -240,6 +278,11 @@ interface VideoToVideoMusicParams {
240
278
  preserveSpeech?: boolean;
241
279
  /** @deprecated Legacy alias for `preserveSpeech`. */
242
280
  isolateVocals?: boolean;
281
+ /** How many distinct music variants to generate in one request (1-10,
282
+ * default 1). Cost scales linearly, and values above 1 are never covered
283
+ * by the free trial. This endpoint is always async, so no extra `mode`
284
+ * gating applies. The result's `videos[]` gets one entry per variant. */
285
+ variantsNum?: number;
243
286
  }
244
287
  interface VideoToVideoSfxParams {
245
288
  video?: VideoInput;
@@ -263,6 +306,24 @@ interface VideoToSoundParams {
263
306
  /** Duck the generated music under the source speech. Default-ON
264
307
  * server-side: leave unset to keep it on, pass `false` to opt out. */
265
308
  ducking?: boolean;
309
+ /** How many distinct variants to generate in one request (1-10, default
310
+ * 1). Cost scales linearly, and values above 1 are never covered by the
311
+ * free trial. Both `videoToSound` and `videoToVideoSound` are always
312
+ * async, so no extra `mode` gating applies. The result's `outputs[]` gets
313
+ * one entry per variant. */
314
+ variantsNum?: number;
315
+ }
316
+ /** One variant's outputs on a `videoToSound` / `videoToVideoSound` result.
317
+ * Present even at the default `variantsNum` of 1, as a single-entry array. */
318
+ interface SoundOutputEntry {
319
+ variant_index: number;
320
+ output_url: string;
321
+ output_type: "audio" | "video";
322
+ output_bytes: number;
323
+ music?: SfxMedia;
324
+ /** Present only when `preserveSpeech`/`ducking` altered this variant's music bed. */
325
+ music_processed?: SfxMedia;
326
+ sfx?: SfxMedia;
266
327
  }
267
328
  /** Result of a `videoToSound` / `videoToVideoSound` task (`tasks.get`) or its
268
329
  * final state (`generate`).
@@ -271,7 +332,11 @@ interface VideoToSoundParams {
271
332
  * than a media object, since these endpoints render one artifact whose kind is
272
333
  * announced by `output_type` ("audio" for video-to-sound, "video" for
273
334
  * video-to-video-sound). `music`, `music_processed` and `sfx` are the
274
- * individual stems; pass any of them, or `output_url` itself, to `download()`. */
335
+ * individual stems; pass any of them, or `output_url` itself, to `download()`.
336
+ *
337
+ * `outputs` carries the same fields per variant when `variantsNum` was
338
+ * greater than 1; `output_url`/`output_type`/`output_bytes`/`music`/
339
+ * `music_processed`/`sfx` remain permanent aliases for `outputs[0]`. */
275
340
  interface SoundResult extends BaseTaskResult {
276
341
  output_url?: string;
277
342
  output_type?: "audio" | "video";
@@ -281,6 +346,33 @@ interface SoundResult extends BaseTaskResult {
281
346
  music_processed?: SfxMedia;
282
347
  sfx?: SfxMedia;
283
348
  duration_seconds?: number;
349
+ /** One entry per variant; see `SoundOutputEntry`. */
350
+ outputs?: SoundOutputEntry[];
351
+ }
352
+ /**
353
+ * A target language for /v1/dubbing. The union stays open (`string & {}`) so a
354
+ * language added server-side still type-checks against an older SDK — the
355
+ * backend, not this list, is the authority on what is supported.
356
+ */
357
+ type DubbingLanguage = "en" | "zh_cn" | "ja" | "ko" | "pt" | "es" | "de" | "fr" | "it" | "ru" | (string & {});
358
+ interface DubbingParams {
359
+ /** Exactly one of `video` / `videoUrl`. */
360
+ video?: VideoInput;
361
+ /**
362
+ * Exactly one of `video` / `videoUrl`. Must be an `https://` URL — the
363
+ * dubbing pipeline fetches the source itself and rejects plain http.
364
+ */
365
+ videoUrl?: string;
366
+ /** Omit to get the server default, `["zh_cn", "es", "fr"]`. */
367
+ languages?: DubbingLanguage[];
368
+ }
369
+ interface DubbingResult extends BaseTaskResult {
370
+ /**
371
+ * One dubbed video URL per requested language, keyed by language code.
372
+ * Unlike every other endpoint's envelope this is a map, not an `audio`/
373
+ * `video` slot — a dubbing task renders N artifacts, one per language.
374
+ */
375
+ outputs?: Record<string, string>;
284
376
  }
285
377
 
286
378
  declare class Account {
@@ -323,7 +415,8 @@ declare class TextToMusic {
323
415
  /**
324
416
  * Submit an async text-to-music task; poll with
325
417
  * `client.tasks.wait<MusicTaskResult>(task.task_id)`. Required for
326
- * `outputFormat: "wav"`. `stream()`/`generate()` remain the streaming path.
418
+ * `outputFormat: "wav"` and `variantsNum` above 1. `stream()`/`generate()`
419
+ * remain the streaming path.
327
420
  */
328
421
  submit(params: TextToMusicParams): Promise<SfxTask>;
329
422
  }
@@ -336,8 +429,9 @@ declare class VideoToMusic {
336
429
  /**
337
430
  * Submit an async video-to-music task; poll its result with
338
431
  * `client.tasks.wait<MusicTaskResult>(task.task_id)`. Required for
339
- * `isolateVocals` the backend rejects vocal isolation on the plain
340
- * stream, and it only ever runs in async mode.
432
+ * `isolateVocals`/`preserveSpeech`, `outputFormat: "wav"`, and
433
+ * `variantsNum` above 1 the backend rejects all of these on the plain
434
+ * stream, and they only ever run in async mode.
341
435
  */
342
436
  submit(params: VideoToMusicParams): Promise<SfxTask>;
343
437
  }
@@ -393,6 +487,15 @@ declare class VideoToVideoSound {
393
487
  generate(params: VideoToSoundParams, opts?: WaitOptions): Promise<SoundResult>;
394
488
  }
395
489
 
490
+ /** Dub a video into one or more target languages. Async only; the result
491
+ * carries a language → dubbed-video-URL map under `outputs`. */
492
+ declare class Dubbing {
493
+ private readonly client;
494
+ constructor(client: SoniloClient);
495
+ submit(params: DubbingParams): Promise<SfxTask>;
496
+ generate(params: DubbingParams, opts?: WaitOptions): Promise<DubbingResult>;
497
+ }
498
+
396
499
  interface SoniloClientOptions {
397
500
  /** Defaults to the SONILO_API_KEY environment variable (Node.js only). */
398
501
  apiKey?: string;
@@ -430,6 +533,7 @@ declare class SoniloClient {
430
533
  readonly videoToVideoSfx: VideoToVideoSfx;
431
534
  readonly videoToSound: VideoToSound;
432
535
  readonly videoToVideoSound: VideoToVideoSound;
536
+ readonly dubbing: Dubbing;
433
537
  constructor(options?: SoniloClientOptions);
434
538
  /**
435
539
  * Perform an authenticated request; throws a typed error on non-2xx.
@@ -460,6 +564,14 @@ declare class AuthenticationError extends APIError {
460
564
  }
461
565
  declare class PaymentRequiredError extends APIError {
462
566
  }
567
+ /** The account's free trial for this service is spent and it has never been
568
+ * funded — the caller should add a payment method rather than retry. A
569
+ * subclass of `PaymentRequiredError`, so code that already catches every 402
570
+ * keeps working; catch this first to tell "you haven't paid us yet" apart
571
+ * from a funded wallet that ran dry (`PaymentRequiredError` with
572
+ * `code === "insufficient_balance"`). */
573
+ declare class TrialExhaustedError extends PaymentRequiredError {
574
+ }
463
575
  declare class BadRequestError extends APIError {
464
576
  get detail(): string | undefined;
465
577
  }
@@ -503,6 +615,6 @@ declare class RequestTimeoutError extends SoniloError {
503
615
  declare function download(media: SfxMedia | string | undefined, fetchFn?: typeof globalThis.fetch, timeout?: number): Promise<Uint8Array>;
504
616
 
505
617
  /** The SDK's own version. Generated by scripts/sync-versions.mjs — do not edit. */
506
- declare const VERSION = "0.6.0";
618
+ declare const VERSION = "0.8.0";
507
619
 
508
- export { APIError, type AccountServices, type AudioChunkEvent, AuthenticationError, BadRequestError, type BaseTaskResult, type CompleteEvent, type CostEvent, type CostInfo, DEFAULT_TIMEOUT_MS, type DailyUsage, 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 SoundResult, type StreamEvent, TaskFailedError, TaskTimeoutError, type TextToMusicParams, type TextToSfxParams, type TitleEvent, type Track, type TrialQuota, type UnknownEvent, type UsageResponse, type UsageSummary, VERSION, type VideoInput, type VideoResult, type VideoToMusicParams, type VideoToSfxParams, type VideoToSoundParams, type VideoToVideoMusicParams, type VideoToVideoSfxParams, type WaitOptions, download, isAudioChunkEvent, isErrorEvent };
620
+ export { APIError, type AccountServices, type AudioChunkEvent, AuthenticationError, BadRequestError, type BaseTaskResult, type CompleteEvent, type CostEvent, type CostInfo, DEFAULT_TIMEOUT_MS, type DailyUsage, type DubbingLanguage, type DubbingParams, type DubbingResult, 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 StreamEvent, TaskFailedError, TaskTimeoutError, type TextToMusicParams, type TextToSfxParams, type TitleEvent, type Track, TrialExhaustedError, type TrialQuota, type UnknownEvent, type UsageResponse, type UsageSummary, VERSION, type VideoInput, type VideoResult, type VideoToMusicParams, type VideoToSfxParams, type VideoToSoundParams, type VideoToVideoMusicParams, type VideoToVideoSfxParams, type WaitOptions, download, isAudioChunkEvent, isErrorEvent };