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.
- package/README.md +148 -4
- package/dist/index.cjs +71 -7
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +123 -11
- package/dist/index.d.ts +123 -11
- package/dist/index.js +70 -7
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
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
|
|
109
|
-
*
|
|
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
|
|
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
|
|
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"
|
|
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`
|
|
340
|
-
*
|
|
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.
|
|
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 };
|
package/dist/index.js
CHANGED
|
@@ -19,6 +19,8 @@ var AuthenticationError = class extends APIError {
|
|
|
19
19
|
};
|
|
20
20
|
var PaymentRequiredError = class extends APIError {
|
|
21
21
|
};
|
|
22
|
+
var TrialExhaustedError = class extends PaymentRequiredError {
|
|
23
|
+
};
|
|
22
24
|
var BadRequestError = class extends APIError {
|
|
23
25
|
get detail() {
|
|
24
26
|
const body = this.body;
|
|
@@ -88,8 +90,13 @@ async function errorFromResponse(res) {
|
|
|
88
90
|
switch (res.status) {
|
|
89
91
|
case 401:
|
|
90
92
|
return new AuthenticationError(message, res.status, body);
|
|
91
|
-
case 402:
|
|
93
|
+
case 402: {
|
|
94
|
+
const code = body?.code;
|
|
95
|
+
if (code === "trial_exhausted") {
|
|
96
|
+
return new TrialExhaustedError(message, res.status, body);
|
|
97
|
+
}
|
|
92
98
|
return new PaymentRequiredError(message, res.status, body);
|
|
99
|
+
}
|
|
93
100
|
case 429: {
|
|
94
101
|
const ra = res.headers.get("retry-after");
|
|
95
102
|
const retryAfter = ra !== null && ra !== "" && !Number.isNaN(Number(ra)) ? Number(ra) : void 0;
|
|
@@ -298,7 +305,8 @@ var TextToMusic = class {
|
|
|
298
305
|
/**
|
|
299
306
|
* Submit an async text-to-music task; poll with
|
|
300
307
|
* `client.tasks.wait<MusicTaskResult>(task.task_id)`. Required for
|
|
301
|
-
* `outputFormat: "wav"
|
|
308
|
+
* `outputFormat: "wav"` and `variantsNum` above 1. `stream()`/`generate()`
|
|
309
|
+
* remain the streaming path.
|
|
302
310
|
*/
|
|
303
311
|
async submit(params) {
|
|
304
312
|
const mode = params.mode ?? "async";
|
|
@@ -315,6 +323,9 @@ var TextToMusic = class {
|
|
|
315
323
|
if (params.outputFormat !== void 0) {
|
|
316
324
|
form.set("output_format", params.outputFormat);
|
|
317
325
|
}
|
|
326
|
+
if (params.variantsNum !== void 0) {
|
|
327
|
+
form.set("variants_num", String(params.variantsNum));
|
|
328
|
+
}
|
|
318
329
|
const res = await this.client.request("/v1/text-to-music", {
|
|
319
330
|
method: "POST",
|
|
320
331
|
body: form
|
|
@@ -395,19 +406,20 @@ var VideoToMusic = class {
|
|
|
395
406
|
/**
|
|
396
407
|
* Submit an async video-to-music task; poll its result with
|
|
397
408
|
* `client.tasks.wait<MusicTaskResult>(task.task_id)`. Required for
|
|
398
|
-
* `isolateVocals`
|
|
399
|
-
*
|
|
409
|
+
* `isolateVocals`/`preserveSpeech`, `outputFormat: "wav"`, and
|
|
410
|
+
* `variantsNum` above 1 — the backend rejects all of these on the plain
|
|
411
|
+
* stream, and they only ever run in async mode.
|
|
400
412
|
*/
|
|
401
413
|
async submit(params) {
|
|
402
414
|
if (params.video === void 0 === (params.videoUrl === void 0)) {
|
|
403
415
|
throw new SoniloError("Provide exactly one of video or videoUrl");
|
|
404
416
|
}
|
|
405
417
|
let mode = params.mode;
|
|
406
|
-
const needsAsync = params.isolateVocals || params.preserveSpeech || params.ducking !== void 0 || params.outputFormat === "wav";
|
|
418
|
+
const needsAsync = params.isolateVocals || params.preserveSpeech || params.ducking !== void 0 || params.outputFormat === "wav" || params.variantsNum !== void 0 && params.variantsNum > 1;
|
|
407
419
|
if (mode === void 0) mode = "async";
|
|
408
420
|
if (needsAsync && mode !== "async") {
|
|
409
421
|
throw new SoniloError(
|
|
410
|
-
'isolateVocals/preserveSpeech/ducking/outputFormat "wav" require mode: "async"'
|
|
422
|
+
'isolateVocals/preserveSpeech/ducking/outputFormat "wav"/variantsNum > 1 require mode: "async"'
|
|
411
423
|
);
|
|
412
424
|
}
|
|
413
425
|
const form = new FormData();
|
|
@@ -434,6 +446,9 @@ var VideoToMusic = class {
|
|
|
434
446
|
if (params.ducking !== void 0) {
|
|
435
447
|
form.set("ducking", String(params.ducking));
|
|
436
448
|
}
|
|
449
|
+
if (params.variantsNum !== void 0) {
|
|
450
|
+
form.set("variants_num", String(params.variantsNum));
|
|
451
|
+
}
|
|
437
452
|
const res = await this.client.request("/v1/video-to-music", {
|
|
438
453
|
method: "POST",
|
|
439
454
|
body: form
|
|
@@ -520,6 +535,9 @@ var VideoToVideoMusic = class {
|
|
|
520
535
|
if (params.isolateVocals !== void 0) {
|
|
521
536
|
form.set("isolate_vocals", String(params.isolateVocals));
|
|
522
537
|
}
|
|
538
|
+
if (params.variantsNum !== void 0) {
|
|
539
|
+
form.set("variants_num", String(params.variantsNum));
|
|
540
|
+
}
|
|
523
541
|
const res = await this.client.request("/v1/video-to-video-music", {
|
|
524
542
|
method: "POST",
|
|
525
543
|
body: form
|
|
@@ -585,6 +603,9 @@ async function buildSoundForm(params) {
|
|
|
585
603
|
form.set("preserve_speech", String(params.preserveSpeech));
|
|
586
604
|
}
|
|
587
605
|
if (params.ducking !== void 0) form.set("ducking", String(params.ducking));
|
|
606
|
+
if (params.variantsNum !== void 0) {
|
|
607
|
+
form.set("variants_num", String(params.variantsNum));
|
|
608
|
+
}
|
|
588
609
|
return form;
|
|
589
610
|
}
|
|
590
611
|
|
|
@@ -624,8 +645,48 @@ var VideoToVideoSound = class {
|
|
|
624
645
|
}
|
|
625
646
|
};
|
|
626
647
|
|
|
648
|
+
// src/resources/dubbing.ts
|
|
649
|
+
async function buildDubbingForm(params) {
|
|
650
|
+
if (params.video === void 0 === (params.videoUrl === void 0)) {
|
|
651
|
+
throw new SoniloError("Provide exactly one of video or videoUrl");
|
|
652
|
+
}
|
|
653
|
+
const form = new FormData();
|
|
654
|
+
if (params.video !== void 0) {
|
|
655
|
+
const { blob, filename } = await toUploadBlob(params.video);
|
|
656
|
+
form.set("video", blob, filename);
|
|
657
|
+
} else {
|
|
658
|
+
const url = params.videoUrl;
|
|
659
|
+
if (!url.toLowerCase().startsWith("https://")) {
|
|
660
|
+
throw new SoniloError(
|
|
661
|
+
"videoUrl must use https \u2014 the dubbing pipeline requires an https URL"
|
|
662
|
+
);
|
|
663
|
+
}
|
|
664
|
+
form.set("video_url", url);
|
|
665
|
+
}
|
|
666
|
+
if (params.languages !== void 0) {
|
|
667
|
+
form.set("languages", JSON.stringify(params.languages));
|
|
668
|
+
}
|
|
669
|
+
return form;
|
|
670
|
+
}
|
|
671
|
+
var Dubbing = class {
|
|
672
|
+
constructor(client) {
|
|
673
|
+
this.client = client;
|
|
674
|
+
}
|
|
675
|
+
async submit(params) {
|
|
676
|
+
const res = await this.client.request("/v1/dubbing", {
|
|
677
|
+
method: "POST",
|
|
678
|
+
body: await buildDubbingForm(params)
|
|
679
|
+
});
|
|
680
|
+
return await res.json();
|
|
681
|
+
}
|
|
682
|
+
async generate(params, opts) {
|
|
683
|
+
const task = await this.submit(params);
|
|
684
|
+
return this.client.tasks.wait(task.task_id, opts);
|
|
685
|
+
}
|
|
686
|
+
};
|
|
687
|
+
|
|
627
688
|
// src/version.ts
|
|
628
|
-
var VERSION = "0.
|
|
689
|
+
var VERSION = "0.8.0";
|
|
629
690
|
|
|
630
691
|
// src/client.ts
|
|
631
692
|
var DEFAULT_BASE_URL = "https://api.sonilo.com";
|
|
@@ -656,6 +717,7 @@ var SoniloClient = class {
|
|
|
656
717
|
this.videoToVideoSfx = new VideoToVideoSfx(this);
|
|
657
718
|
this.videoToSound = new VideoToSound(this);
|
|
658
719
|
this.videoToVideoSound = new VideoToVideoSound(this);
|
|
720
|
+
this.dubbing = new Dubbing(this);
|
|
659
721
|
}
|
|
660
722
|
/**
|
|
661
723
|
* Perform an authenticated request; throws a typed error on non-2xx.
|
|
@@ -727,6 +789,7 @@ export {
|
|
|
727
789
|
SoniloError,
|
|
728
790
|
TaskFailedError,
|
|
729
791
|
TaskTimeoutError,
|
|
792
|
+
TrialExhaustedError,
|
|
730
793
|
VERSION,
|
|
731
794
|
download,
|
|
732
795
|
isAudioChunkEvent,
|