sonilo 0.3.0 → 0.5.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 +133 -8
- package/dist/index.cjs +178 -8
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +128 -4
- package/dist/index.d.ts +128 -4
- package/dist/index.js +178 -8
- package/dist/index.js.map +1 -1
- package/package.json +3 -2
package/dist/index.d.ts
CHANGED
|
@@ -51,6 +51,10 @@ interface TextToMusicParams {
|
|
|
51
51
|
prompt: string;
|
|
52
52
|
duration: number;
|
|
53
53
|
segments?: Segment[];
|
|
54
|
+
/** "stream" (default) or "async" (required by `submit()` and `output_format: "wav"`). */
|
|
55
|
+
mode?: "stream" | "async";
|
|
56
|
+
/** Container for the async result. `wav` requires `mode: "async"`. Defaults to m4a server-side. */
|
|
57
|
+
outputFormat?: "m4a" | "wav";
|
|
54
58
|
/** Bounds the stream: aborting this cancels the in-flight generation.
|
|
55
59
|
* Passed straight through to `fetch` — it is never rewrapped as
|
|
56
60
|
* RequestTimeoutError, since the client's own absolute timeout does not
|
|
@@ -79,6 +83,16 @@ interface VideoToMusicParams {
|
|
|
79
83
|
* "async" automatically. Only usable via `submit()` — the backend
|
|
80
84
|
* rejects it on the plain stream. */
|
|
81
85
|
isolateVocals?: boolean;
|
|
86
|
+
/** Keep the source speech/vocals in the async result. Current name for
|
|
87
|
+
* `isolateVocals`; both are accepted and OR'd server-side. Requires
|
|
88
|
+
* `mode: "async"` (auto-selected by `submit()`). */
|
|
89
|
+
preserveSpeech?: boolean;
|
|
90
|
+
/** Container for the async result. `wav` requires async. Defaults to m4a. */
|
|
91
|
+
outputFormat?: "m4a" | "wav";
|
|
92
|
+
/** Duck the generated music under the source voice at finalize time.
|
|
93
|
+
* Default-ON server-side in async mode: leave unset to keep it on, pass
|
|
94
|
+
* `false` to opt out. Free, best-effort; only valid on `submit()`. */
|
|
95
|
+
ducking?: boolean;
|
|
82
96
|
}
|
|
83
97
|
interface AccountServices {
|
|
84
98
|
available_services: string[];
|
|
@@ -192,6 +206,8 @@ interface MusicTaskResult extends BaseTaskResult {
|
|
|
192
206
|
vocals?: SfxMedia;
|
|
193
207
|
/** Muxed output per stream; present only when `isolateVocals` was requested. */
|
|
194
208
|
mux?: MusicMuxEntry[];
|
|
209
|
+
/** Music ducked under the source voice; present only when `ducking` ran. */
|
|
210
|
+
ducked?: MusicMediaEntry[];
|
|
195
211
|
title?: MusicTitle;
|
|
196
212
|
duration_seconds?: number;
|
|
197
213
|
}
|
|
@@ -201,6 +217,63 @@ interface WaitOptions {
|
|
|
201
217
|
/** Overall deadline in milliseconds. Default 600000. */
|
|
202
218
|
timeout?: number;
|
|
203
219
|
}
|
|
220
|
+
/** Result of an async video-to-video task (`videoToVideoMusic`/`videoToVideoSfx`):
|
|
221
|
+
* a re-hosted video with generated music or SFX muxed in. */
|
|
222
|
+
interface VideoResult extends BaseTaskResult {
|
|
223
|
+
video?: SfxMedia;
|
|
224
|
+
duration_seconds?: number;
|
|
225
|
+
}
|
|
226
|
+
interface VideoToVideoMusicParams {
|
|
227
|
+
video?: VideoInput;
|
|
228
|
+
videoUrl?: string;
|
|
229
|
+
prompt?: string;
|
|
230
|
+
/** Keep the source speech/vocals in the output. Both this and the legacy
|
|
231
|
+
* `isolateVocals` are accepted and OR'd server-side. */
|
|
232
|
+
preserveSpeech?: boolean;
|
|
233
|
+
/** @deprecated Legacy alias for `preserveSpeech`. */
|
|
234
|
+
isolateVocals?: boolean;
|
|
235
|
+
}
|
|
236
|
+
interface VideoToVideoSfxParams {
|
|
237
|
+
video?: VideoInput;
|
|
238
|
+
videoUrl?: string;
|
|
239
|
+
prompt?: string;
|
|
240
|
+
segments?: SfxSegment[];
|
|
241
|
+
}
|
|
242
|
+
/** Params for `videoToSound` and `videoToVideoSound`. Both endpoints take the
|
|
243
|
+
* identical form, so they share one params type. */
|
|
244
|
+
interface VideoToSoundParams {
|
|
245
|
+
video?: VideoInput;
|
|
246
|
+
videoUrl?: string;
|
|
247
|
+
/** Style hint for the generated music bed. */
|
|
248
|
+
musicPrompt?: string;
|
|
249
|
+
/** Description of the sound effects layered over the music. */
|
|
250
|
+
sfxPrompt?: string;
|
|
251
|
+
/** Per-segment SFX descriptions; must start at 0 and be contiguous. */
|
|
252
|
+
segments?: SfxSegment[];
|
|
253
|
+
/** Keep the source speech in the result. */
|
|
254
|
+
preserveSpeech?: boolean;
|
|
255
|
+
/** Duck the generated music under the source speech. Default-ON
|
|
256
|
+
* server-side: leave unset to keep it on, pass `false` to opt out. */
|
|
257
|
+
ducking?: boolean;
|
|
258
|
+
}
|
|
259
|
+
/** Result of a `videoToSound` / `videoToVideoSound` task (`tasks.get`) or its
|
|
260
|
+
* final state (`generate`).
|
|
261
|
+
*
|
|
262
|
+
* The combined music+SFX result is `output_url` — a bare presigned URL rather
|
|
263
|
+
* than a media object, since these endpoints render one artifact whose kind is
|
|
264
|
+
* announced by `output_type` ("audio" for video-to-sound, "video" for
|
|
265
|
+
* video-to-video-sound). `music`, `music_processed` and `sfx` are the
|
|
266
|
+
* individual stems; pass any of them, or `output_url` itself, to `download()`. */
|
|
267
|
+
interface SoundResult extends BaseTaskResult {
|
|
268
|
+
output_url?: string;
|
|
269
|
+
output_type?: "audio" | "video";
|
|
270
|
+
output_bytes?: number;
|
|
271
|
+
music?: SfxMedia;
|
|
272
|
+
/** Present only when `preserveSpeech`/`ducking` altered the music bed. */
|
|
273
|
+
music_processed?: SfxMedia;
|
|
274
|
+
sfx?: SfxMedia;
|
|
275
|
+
duration_seconds?: number;
|
|
276
|
+
}
|
|
204
277
|
|
|
205
278
|
declare class Account {
|
|
206
279
|
private readonly client;
|
|
@@ -239,6 +312,12 @@ declare class TextToMusic {
|
|
|
239
312
|
stream(params: TextToMusicParams): AsyncGenerator<StreamEvent, void, undefined>;
|
|
240
313
|
/** Generate and buffer the whole track; throws GenerationError on stream errors. */
|
|
241
314
|
generate(params: TextToMusicParams): Promise<Track>;
|
|
315
|
+
/**
|
|
316
|
+
* Submit an async text-to-music task; poll with
|
|
317
|
+
* `client.tasks.wait<MusicTaskResult>(task.task_id)`. Required for
|
|
318
|
+
* `outputFormat: "wav"`. `stream()`/`generate()` remain the streaming path.
|
|
319
|
+
*/
|
|
320
|
+
submit(params: TextToMusicParams): Promise<SfxTask>;
|
|
242
321
|
}
|
|
243
322
|
|
|
244
323
|
declare class VideoToMusic {
|
|
@@ -269,6 +348,43 @@ declare class VideoToSfx {
|
|
|
269
348
|
generate(params: VideoToSfxParams, opts?: WaitOptions): Promise<SfxResult>;
|
|
270
349
|
}
|
|
271
350
|
|
|
351
|
+
/** Generate an original score for a video and get back a re-hosted video with
|
|
352
|
+
* the music muxed in. Async only: `submit()` returns a task ack; poll with
|
|
353
|
+
* `client.tasks.wait<VideoResult>(id)`, or use `generate()` to do both. */
|
|
354
|
+
declare class VideoToVideoMusic {
|
|
355
|
+
private readonly client;
|
|
356
|
+
constructor(client: SoniloClient);
|
|
357
|
+
submit(params: VideoToVideoMusicParams): Promise<SfxTask>;
|
|
358
|
+
generate(params: VideoToVideoMusicParams, opts?: WaitOptions): Promise<VideoResult>;
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
/** Generate sound effects for a video and get back a re-hosted video with the
|
|
362
|
+
* SFX muxed in. Async only. */
|
|
363
|
+
declare class VideoToVideoSfx {
|
|
364
|
+
private readonly client;
|
|
365
|
+
constructor(client: SoniloClient);
|
|
366
|
+
submit(params: VideoToVideoSfxParams): Promise<SfxTask>;
|
|
367
|
+
generate(params: VideoToVideoSfxParams, opts?: WaitOptions): Promise<VideoResult>;
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
/** Generate a combined music + sound-effects track for a video and get back
|
|
371
|
+
* the mixed audio. Async only. */
|
|
372
|
+
declare class VideoToSound {
|
|
373
|
+
private readonly client;
|
|
374
|
+
constructor(client: SoniloClient);
|
|
375
|
+
submit(params: VideoToSoundParams): Promise<SfxTask>;
|
|
376
|
+
generate(params: VideoToSoundParams, opts?: WaitOptions): Promise<SoundResult>;
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
/** Generate a combined music + sound-effects track for a video and get back a
|
|
380
|
+
* re-hosted video with that track muxed in. Async only. */
|
|
381
|
+
declare class VideoToVideoSound {
|
|
382
|
+
private readonly client;
|
|
383
|
+
constructor(client: SoniloClient);
|
|
384
|
+
submit(params: VideoToSoundParams): Promise<SfxTask>;
|
|
385
|
+
generate(params: VideoToSoundParams, opts?: WaitOptions): Promise<SoundResult>;
|
|
386
|
+
}
|
|
387
|
+
|
|
272
388
|
interface SoniloClientOptions {
|
|
273
389
|
/** Defaults to the SONILO_API_KEY environment variable (Node.js only). */
|
|
274
390
|
apiKey?: string;
|
|
@@ -292,6 +408,10 @@ declare class SoniloClient {
|
|
|
292
408
|
readonly videoToMusic: VideoToMusic;
|
|
293
409
|
readonly textToSfx: TextToSfx;
|
|
294
410
|
readonly videoToSfx: VideoToSfx;
|
|
411
|
+
readonly videoToVideoMusic: VideoToVideoMusic;
|
|
412
|
+
readonly videoToVideoSfx: VideoToVideoSfx;
|
|
413
|
+
readonly videoToSound: VideoToSound;
|
|
414
|
+
readonly videoToVideoSound: VideoToVideoSound;
|
|
295
415
|
constructor(options?: SoniloClientOptions);
|
|
296
416
|
/**
|
|
297
417
|
* Perform an authenticated request; throws a typed error on non-2xx.
|
|
@@ -357,9 +477,13 @@ declare class TaskTimeoutError extends SoniloError {
|
|
|
357
477
|
declare class RequestTimeoutError extends SoniloError {
|
|
358
478
|
}
|
|
359
479
|
|
|
360
|
-
/** Fetch a result media file. The URL is presigned — no API key is sent.
|
|
361
|
-
|
|
480
|
+
/** Fetch a result media file. The URL is presigned — no API key is sent.
|
|
481
|
+
*
|
|
482
|
+
* Accepts either a media object (`result.audio`, `result.music`, …) or a bare
|
|
483
|
+
* URL string, which is what the combined video-to-sound endpoints return as
|
|
484
|
+
* `output_url`. */
|
|
485
|
+
declare function download(media: SfxMedia | string | undefined, fetchFn?: typeof globalThis.fetch, timeout?: number): Promise<Uint8Array>;
|
|
362
486
|
|
|
363
|
-
declare const VERSION = "0.
|
|
487
|
+
declare const VERSION = "0.4.0";
|
|
364
488
|
|
|
365
|
-
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 StreamEvent, TaskFailedError, TaskTimeoutError, type TextToMusicParams, type TextToSfxParams, type TitleEvent, type Track, type UnknownEvent, type UsageResponse, type UsageSummary, VERSION, type VideoInput, type VideoToMusicParams, type VideoToSfxParams, type WaitOptions, download, isAudioChunkEvent, isErrorEvent };
|
|
489
|
+
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 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
|
@@ -295,6 +295,32 @@ var TextToMusic = class {
|
|
|
295
295
|
generate(params) {
|
|
296
296
|
return collectTrack(this.stream(params));
|
|
297
297
|
}
|
|
298
|
+
/**
|
|
299
|
+
* Submit an async text-to-music task; poll with
|
|
300
|
+
* `client.tasks.wait<MusicTaskResult>(task.task_id)`. Required for
|
|
301
|
+
* `outputFormat: "wav"`. `stream()`/`generate()` remain the streaming path.
|
|
302
|
+
*/
|
|
303
|
+
async submit(params) {
|
|
304
|
+
const mode = params.mode ?? "async";
|
|
305
|
+
if (mode !== "async") {
|
|
306
|
+
throw new SoniloError('submit() requires mode: "async"');
|
|
307
|
+
}
|
|
308
|
+
const form = new FormData();
|
|
309
|
+
form.set("prompt", params.prompt);
|
|
310
|
+
form.set("duration", String(params.duration));
|
|
311
|
+
if (params.segments !== void 0) {
|
|
312
|
+
form.set("segments", JSON.stringify(params.segments));
|
|
313
|
+
}
|
|
314
|
+
form.set("mode", mode);
|
|
315
|
+
if (params.outputFormat !== void 0) {
|
|
316
|
+
form.set("output_format", params.outputFormat);
|
|
317
|
+
}
|
|
318
|
+
const res = await this.client.request("/v1/text-to-music", {
|
|
319
|
+
method: "POST",
|
|
320
|
+
body: form
|
|
321
|
+
});
|
|
322
|
+
return await res.json();
|
|
323
|
+
}
|
|
298
324
|
};
|
|
299
325
|
|
|
300
326
|
// src/upload.ts
|
|
@@ -377,9 +403,12 @@ var VideoToMusic = class {
|
|
|
377
403
|
throw new SoniloError("Provide exactly one of video or videoUrl");
|
|
378
404
|
}
|
|
379
405
|
let mode = params.mode;
|
|
380
|
-
|
|
381
|
-
if (
|
|
382
|
-
|
|
406
|
+
const needsAsync = params.isolateVocals || params.preserveSpeech || params.ducking !== void 0 || params.outputFormat === "wav";
|
|
407
|
+
if (mode === void 0) mode = "async";
|
|
408
|
+
if (needsAsync && mode !== "async") {
|
|
409
|
+
throw new SoniloError(
|
|
410
|
+
'isolateVocals/preserveSpeech/ducking/outputFormat "wav" require mode: "async"'
|
|
411
|
+
);
|
|
383
412
|
}
|
|
384
413
|
const form = new FormData();
|
|
385
414
|
if (params.video !== void 0) {
|
|
@@ -392,10 +421,19 @@ var VideoToMusic = class {
|
|
|
392
421
|
if (params.segments !== void 0) {
|
|
393
422
|
form.set("segments", JSON.stringify(params.segments));
|
|
394
423
|
}
|
|
395
|
-
|
|
424
|
+
form.set("mode", mode);
|
|
425
|
+
if (params.preserveSpeech !== void 0) {
|
|
426
|
+
form.set("preserve_speech", String(params.preserveSpeech));
|
|
427
|
+
}
|
|
396
428
|
if (params.isolateVocals !== void 0) {
|
|
397
429
|
form.set("isolate_vocals", String(params.isolateVocals));
|
|
398
430
|
}
|
|
431
|
+
if (params.outputFormat !== void 0) {
|
|
432
|
+
form.set("output_format", params.outputFormat);
|
|
433
|
+
}
|
|
434
|
+
if (params.ducking !== void 0) {
|
|
435
|
+
form.set("ducking", String(params.ducking));
|
|
436
|
+
}
|
|
399
437
|
const res = await this.client.request("/v1/video-to-music", {
|
|
400
438
|
method: "POST",
|
|
401
439
|
body: form
|
|
@@ -459,8 +497,135 @@ var VideoToSfx = class {
|
|
|
459
497
|
}
|
|
460
498
|
};
|
|
461
499
|
|
|
500
|
+
// src/resources/videoToVideoMusic.ts
|
|
501
|
+
var VideoToVideoMusic = class {
|
|
502
|
+
constructor(client) {
|
|
503
|
+
this.client = client;
|
|
504
|
+
}
|
|
505
|
+
async submit(params) {
|
|
506
|
+
if (params.video === void 0 === (params.videoUrl === void 0)) {
|
|
507
|
+
throw new SoniloError("Provide exactly one of video or videoUrl");
|
|
508
|
+
}
|
|
509
|
+
const form = new FormData();
|
|
510
|
+
if (params.video !== void 0) {
|
|
511
|
+
const { blob, filename } = await toUploadBlob(params.video);
|
|
512
|
+
form.set("video", blob, filename);
|
|
513
|
+
} else {
|
|
514
|
+
form.set("video_url", params.videoUrl);
|
|
515
|
+
}
|
|
516
|
+
if (params.prompt !== void 0) form.set("prompt", params.prompt);
|
|
517
|
+
if (params.preserveSpeech !== void 0) {
|
|
518
|
+
form.set("preserve_speech", String(params.preserveSpeech));
|
|
519
|
+
}
|
|
520
|
+
if (params.isolateVocals !== void 0) {
|
|
521
|
+
form.set("isolate_vocals", String(params.isolateVocals));
|
|
522
|
+
}
|
|
523
|
+
const res = await this.client.request("/v1/video-to-video-music", {
|
|
524
|
+
method: "POST",
|
|
525
|
+
body: form
|
|
526
|
+
});
|
|
527
|
+
return await res.json();
|
|
528
|
+
}
|
|
529
|
+
async generate(params, opts) {
|
|
530
|
+
const task = await this.submit(params);
|
|
531
|
+
return this.client.tasks.wait(task.task_id, opts);
|
|
532
|
+
}
|
|
533
|
+
};
|
|
534
|
+
|
|
535
|
+
// src/resources/videoToVideoSfx.ts
|
|
536
|
+
var VideoToVideoSfx = class {
|
|
537
|
+
constructor(client) {
|
|
538
|
+
this.client = client;
|
|
539
|
+
}
|
|
540
|
+
async submit(params) {
|
|
541
|
+
if (params.video === void 0 === (params.videoUrl === void 0)) {
|
|
542
|
+
throw new SoniloError("Provide exactly one of video or videoUrl");
|
|
543
|
+
}
|
|
544
|
+
const form = new FormData();
|
|
545
|
+
if (params.video !== void 0) {
|
|
546
|
+
const { blob, filename } = await toUploadBlob(params.video);
|
|
547
|
+
form.set("video", blob, filename);
|
|
548
|
+
} else {
|
|
549
|
+
form.set("video_url", params.videoUrl);
|
|
550
|
+
}
|
|
551
|
+
if (params.prompt !== void 0) form.set("prompt", params.prompt);
|
|
552
|
+
if (params.segments !== void 0) {
|
|
553
|
+
form.set("segments", JSON.stringify(params.segments));
|
|
554
|
+
}
|
|
555
|
+
const res = await this.client.request("/v1/video-to-video-sfx", {
|
|
556
|
+
method: "POST",
|
|
557
|
+
body: form
|
|
558
|
+
});
|
|
559
|
+
return await res.json();
|
|
560
|
+
}
|
|
561
|
+
async generate(params, opts) {
|
|
562
|
+
const task = await this.submit(params);
|
|
563
|
+
return this.client.tasks.wait(task.task_id, opts);
|
|
564
|
+
}
|
|
565
|
+
};
|
|
566
|
+
|
|
567
|
+
// src/resources/soundForm.ts
|
|
568
|
+
async function buildSoundForm(params) {
|
|
569
|
+
if (params.video === void 0 === (params.videoUrl === void 0)) {
|
|
570
|
+
throw new SoniloError("Provide exactly one of video or videoUrl");
|
|
571
|
+
}
|
|
572
|
+
const form = new FormData();
|
|
573
|
+
if (params.video !== void 0) {
|
|
574
|
+
const { blob, filename } = await toUploadBlob(params.video);
|
|
575
|
+
form.set("video", blob, filename);
|
|
576
|
+
} else {
|
|
577
|
+
form.set("video_url", params.videoUrl);
|
|
578
|
+
}
|
|
579
|
+
if (params.musicPrompt !== void 0) form.set("music_prompt", params.musicPrompt);
|
|
580
|
+
if (params.sfxPrompt !== void 0) form.set("sfx_prompt", params.sfxPrompt);
|
|
581
|
+
if (params.segments !== void 0) {
|
|
582
|
+
form.set("segments", JSON.stringify(params.segments));
|
|
583
|
+
}
|
|
584
|
+
if (params.preserveSpeech !== void 0) {
|
|
585
|
+
form.set("preserve_speech", String(params.preserveSpeech));
|
|
586
|
+
}
|
|
587
|
+
if (params.ducking !== void 0) form.set("ducking", String(params.ducking));
|
|
588
|
+
return form;
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
// src/resources/videoToSound.ts
|
|
592
|
+
var VideoToSound = class {
|
|
593
|
+
constructor(client) {
|
|
594
|
+
this.client = client;
|
|
595
|
+
}
|
|
596
|
+
async submit(params) {
|
|
597
|
+
const res = await this.client.request("/v1/video-to-sound", {
|
|
598
|
+
method: "POST",
|
|
599
|
+
body: await buildSoundForm(params)
|
|
600
|
+
});
|
|
601
|
+
return await res.json();
|
|
602
|
+
}
|
|
603
|
+
async generate(params, opts) {
|
|
604
|
+
const task = await this.submit(params);
|
|
605
|
+
return this.client.tasks.wait(task.task_id, opts);
|
|
606
|
+
}
|
|
607
|
+
};
|
|
608
|
+
|
|
609
|
+
// src/resources/videoToVideoSound.ts
|
|
610
|
+
var VideoToVideoSound = class {
|
|
611
|
+
constructor(client) {
|
|
612
|
+
this.client = client;
|
|
613
|
+
}
|
|
614
|
+
async submit(params) {
|
|
615
|
+
const res = await this.client.request("/v1/video-to-video-sound", {
|
|
616
|
+
method: "POST",
|
|
617
|
+
body: await buildSoundForm(params)
|
|
618
|
+
});
|
|
619
|
+
return await res.json();
|
|
620
|
+
}
|
|
621
|
+
async generate(params, opts) {
|
|
622
|
+
const task = await this.submit(params);
|
|
623
|
+
return this.client.tasks.wait(task.task_id, opts);
|
|
624
|
+
}
|
|
625
|
+
};
|
|
626
|
+
|
|
462
627
|
// src/version.ts
|
|
463
|
-
var VERSION = "0.
|
|
628
|
+
var VERSION = "0.4.0";
|
|
464
629
|
|
|
465
630
|
// src/client.ts
|
|
466
631
|
var DEFAULT_BASE_URL = "https://api.sonilo.com";
|
|
@@ -484,6 +649,10 @@ var SoniloClient = class {
|
|
|
484
649
|
this.videoToMusic = new VideoToMusic(this);
|
|
485
650
|
this.textToSfx = new TextToSfx(this);
|
|
486
651
|
this.videoToSfx = new VideoToSfx(this);
|
|
652
|
+
this.videoToVideoMusic = new VideoToVideoMusic(this);
|
|
653
|
+
this.videoToVideoSfx = new VideoToVideoSfx(this);
|
|
654
|
+
this.videoToSound = new VideoToSound(this);
|
|
655
|
+
this.videoToVideoSound = new VideoToVideoSound(this);
|
|
487
656
|
}
|
|
488
657
|
/**
|
|
489
658
|
* Perform an authenticated request; throws a typed error on non-2xx.
|
|
@@ -516,15 +685,16 @@ var SoniloClient = class {
|
|
|
516
685
|
|
|
517
686
|
// src/download.ts
|
|
518
687
|
async function download(media, fetchFn = globalThis.fetch, timeout = DEFAULT_TIMEOUT_MS) {
|
|
519
|
-
|
|
688
|
+
const url = typeof media === "string" ? media : media?.url;
|
|
689
|
+
if (!url) {
|
|
520
690
|
throw new SoniloError("No media to download");
|
|
521
691
|
}
|
|
522
692
|
let res;
|
|
523
693
|
try {
|
|
524
|
-
res = await fetchFn(
|
|
694
|
+
res = await fetchFn(url, { signal: AbortSignal.timeout(timeout) });
|
|
525
695
|
} catch (err) {
|
|
526
696
|
if (isTimeoutSignalError(err)) {
|
|
527
|
-
throw new RequestTimeoutError(`Download of ${
|
|
697
|
+
throw new RequestTimeoutError(`Download of ${url} timed out after ${timeout}ms`);
|
|
528
698
|
}
|
|
529
699
|
throw err;
|
|
530
700
|
}
|