sonilo 0.14.0 → 0.16.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/dist/index.d.cts CHANGED
@@ -64,6 +64,16 @@ interface TextToMusicParams {
64
64
  * meaningful via `submit()`; `stream()`/`generate()` never send it, since
65
65
  * they always request a plain stream. */
66
66
  variantsNum?: number;
67
+ /** Also split the generated track into four separated stems — `drums`,
68
+ * `bass`, `vocals`, `other` — delivered on the task result's `stems`
69
+ * array. Free of charge. Requires `mode: "async"` (the backend rejects it
70
+ * on the plain stream with a 400), so it is only meaningful via
71
+ * `submit()`; `stream()`/`generate()` never send it. Separation runs after
72
+ * generation and typically adds 2-6 minutes to the wait (it gives up after
73
+ * 30), so raise `tasks.wait`'s `timeout` accordingly. See `StemsEntry` for
74
+ * the result shape, and `MusicTaskResult.stems_error` for how failures are
75
+ * reported. */
76
+ stems?: boolean;
67
77
  /** Bounds the stream: aborting this cancels the in-flight generation.
68
78
  * Passed straight through to `fetch` — it is never rewrapped as
69
79
  * RequestTimeoutError, since the client's own absolute timeout does not
@@ -118,6 +128,17 @@ interface VideoToMusicParams {
118
128
  * default applies; `0` is a meaningful value and is sent. Out-of-range
119
129
  * values are rejected server-side with a 422. */
120
130
  promptInfluence?: number;
131
+ /** Also split the generated music into four separated stems — `drums`,
132
+ * `bass`, `vocals`, `other` — delivered on the task result's `stems`
133
+ * array. It splits the GENERATED music, never the source video's own
134
+ * audio. Free of charge. Requires `mode: "async"` (auto-selected by
135
+ * `submit()`; the backend rejects it on the plain stream with a 400), so
136
+ * it is only meaningful via `submit()` — `stream()`/`generate()` never
137
+ * send it. Separation runs after generation and typically adds 2-6
138
+ * minutes to the wait (it gives up after 30), so raise `tasks.wait`'s
139
+ * `timeout` accordingly. See `StemsEntry` for the result shape, and
140
+ * `MusicTaskResult.stems_error` for how failures are reported. */
141
+ stems?: boolean;
121
142
  }
122
143
  /** One service's free-trial allowance. `remaining` is already floored at 0,
123
144
  * so it is safe to compare directly. */
@@ -244,6 +265,21 @@ interface MusicTitle {
244
265
  summary?: string;
245
266
  display_tags?: string[];
246
267
  }
268
+ /** The four separated stems of one generated stream, present when the
269
+ * request set `stems: true`. Each stem is an ordinary media object
270
+ * (`url` / `content_type` / `file_size`), so any of them can be passed to
271
+ * `download()`. The stems normally follow the request's `outputFormat`;
272
+ * each stem's own `content_type` reports what was actually delivered. */
273
+ interface StemsEntry {
274
+ /** Which `audio` entry this stems set belongs to. Match on this field,
275
+ * never on array position — `stems` carries only the streams that
276
+ * separated successfully, so it can be shorter than `audio`. */
277
+ stream_index: number;
278
+ drums: SfxMedia;
279
+ bass: SfxMedia;
280
+ vocals: SfxMedia;
281
+ other: SfxMedia;
282
+ }
247
283
  /** State of an async video-to-music task (`tasks.get`) or its final result
248
284
  * (`tasks.wait<MusicTaskResult>()`). Only reachable via `videoToMusic.submit()`
249
285
  * with `mode: "async"`. */
@@ -259,6 +295,16 @@ interface MusicTaskResult extends BaseTaskResult {
259
295
  /** Music ducked under the source voice (per variant when `variantsNum` is
260
296
  * above 1); present only when `ducking` ran. */
261
297
  ducked?: MusicMediaEntry[];
298
+ /** Separated stems, one entry per stream that separated successfully;
299
+ * only appears when the request set `stems: true`. Look entries up by
300
+ * `stream_index`, never by array position — the array can be shorter than
301
+ * `audio` when separation failed for some streams (see `stems_error`). */
302
+ stems?: StemsEntry[];
303
+ /** Why stem separation failed wholly or in part, or was skipped. It can
304
+ * appear ALONGSIDE a partial `stems` array, so never treat its presence as
305
+ * "no stems" — check `stems` itself for what did arrive. Independent of
306
+ * the task's own `status`/`error`: the generation is intact either way. */
307
+ stems_error?: string;
262
308
  /** Variant 0's title — the top-level field always names the first variant,
263
309
  * even when `variantsNum` produced others with their own titles on
264
310
  * `audio[]`. */
@@ -511,6 +557,50 @@ interface DubbingResult extends BaseTaskResult {
511
557
  */
512
558
  outputs?: Record<string, string>;
513
559
  }
560
+ interface VideoAnalysisParams {
561
+ /** Exactly one of `video` / `videoUrl`. */
562
+ video?: VideoInput;
563
+ /** Exactly one of `video` / `videoUrl`. */
564
+ videoUrl?: string;
565
+ /** Optional guidance for the analysis, at most 2000 characters. */
566
+ prompt?: string;
567
+ /**
568
+ * How many independent creative briefs to author for the same video
569
+ * (1-5, default 1). Billed per brief.
570
+ */
571
+ variantsNum?: number;
572
+ }
573
+ /** One time-aligned section of the analyzed video, with the scoring
574
+ * direction for that stretch. Bounds are whole seconds — the backend
575
+ * truncates any fractional upstream bound before it reaches the envelope. */
576
+ interface AnalysisSegment {
577
+ start: number;
578
+ end: number;
579
+ /** The backend always emits one, defaulting to the string `"none"`. */
580
+ label: string;
581
+ prompt: string;
582
+ }
583
+ /** One independent creative brief for the whole video. Only the generation
584
+ * prompt is public — the upstream's title/summary/tags are internal display
585
+ * copy the API deliberately does not resell. */
586
+ interface AnalysisVariation {
587
+ prompt: string;
588
+ }
589
+ /**
590
+ * The only Sonilo result with no media artifact at all: video-analysis
591
+ * generates nothing and there is nothing to download. The payload is the
592
+ * work order — `segments` for a time-aligned plan, and one `prompt` per
593
+ * requested variation, each ready to pass to videoToMusic, videoToSfx,
594
+ * videoToSound or their video-to-video counterparts.
595
+ *
596
+ * Both lists are optional because a `processing` or `failed` poll carries
597
+ * neither.
598
+ */
599
+ interface VideoAnalysisResult extends BaseTaskResult {
600
+ segments?: AnalysisSegment[];
601
+ variations?: AnalysisVariation[];
602
+ duration_seconds?: number;
603
+ }
514
604
 
515
605
  declare class Account {
516
606
  private readonly client;
@@ -552,8 +642,8 @@ declare class TextToMusic {
552
642
  /**
553
643
  * Submit an async text-to-music task; poll with
554
644
  * `client.tasks.wait<MusicTaskResult>(task.task_id)`. Required for
555
- * a non-m4a `outputFormat` and `variantsNum` above 1. `stream()`/`generate()`
556
- * remain the streaming path.
645
+ * a non-m4a `outputFormat`, `variantsNum` above 1, and `stems`.
646
+ * `stream()`/`generate()` remain the streaming path.
557
647
  */
558
648
  submit(params: TextToMusicParams): Promise<SfxTask>;
559
649
  }
@@ -566,9 +656,9 @@ declare class VideoToMusic {
566
656
  /**
567
657
  * Submit an async video-to-music task; poll its result with
568
658
  * `client.tasks.wait<MusicTaskResult>(task.task_id)`. Required for
569
- * `isolateVocals`/`preserveSpeech`, a non-m4a `outputFormat`, and
570
- * `variantsNum` above 1 — the backend rejects all of these on the plain
571
- * stream, and they only ever run in async mode.
659
+ * `isolateVocals`/`preserveSpeech`, a non-m4a `outputFormat`,
660
+ * `variantsNum` above 1, and `stems` — the backend rejects all of these on
661
+ * the plain stream, and they only ever run in async mode.
572
662
  */
573
663
  submit(params: VideoToMusicParams): Promise<SfxTask>;
574
664
  }
@@ -648,6 +738,28 @@ declare class Dubbing {
648
738
  generate(params: DubbingParams, opts?: WaitOptions): Promise<DubbingResult>;
649
739
  }
650
740
 
741
+ /** Analyze a video and get back a creative brief for scoring it. Async only.
742
+ *
743
+ * This endpoint generates nothing — no audio, no video, no artifact to
744
+ * download. The result is the work order: `segments` (a time-aligned section
745
+ * plan) plus one `prompt` per requested variation, each ready to hand
746
+ * straight to videoToMusic, videoToSfx, videoToSound or their
747
+ * video-to-video counterparts.
748
+ *
749
+ * The method is `analyze`, not `generate`, for that reason: every other
750
+ * resource's `generate` returns something you download, and this one never
751
+ * does.
752
+ *
753
+ * The 1-5 bound on `variantsNum` and the 2000-character bound on `prompt`
754
+ * are deliberately not checked here — the backend owns them, and a hardcoded
755
+ * copy would make this SDK reject values a later API widens. */
756
+ declare class VideoAnalysis {
757
+ private readonly client;
758
+ constructor(client: SoniloClient);
759
+ submit(params: VideoAnalysisParams): Promise<SfxTask>;
760
+ analyze(params: VideoAnalysisParams, opts?: WaitOptions): Promise<VideoAnalysisResult>;
761
+ }
762
+
651
763
  interface SoniloClientOptions {
652
764
  /** Defaults to the SONILO_API_KEY environment variable (Node.js only). */
653
765
  apiKey?: string;
@@ -687,6 +799,7 @@ declare class SoniloClient {
687
799
  readonly videoToVideoSound: VideoToVideoSound;
688
800
  readonly audioDucking: AudioDucking;
689
801
  readonly dubbing: Dubbing;
802
+ readonly videoAnalysis: VideoAnalysis;
690
803
  constructor(options?: SoniloClientOptions);
691
804
  /**
692
805
  * Perform an authenticated request; throws a typed error on non-2xx.
@@ -768,6 +881,6 @@ declare class RequestTimeoutError extends SoniloError {
768
881
  declare function download(media: SfxMedia | string | undefined, fetchFn?: typeof globalThis.fetch, timeout?: number): Promise<Uint8Array>;
769
882
 
770
883
  /** The SDK's own version. Generated by scripts/sync-versions.mjs — do not edit. */
771
- declare const VERSION = "0.14.0";
884
+ declare const VERSION = "0.16.0";
772
885
 
773
- export { APIError, type AccountServices, type AudioChunkEvent, type AudioDuckingParams, AuthenticationError, BadRequestError, type BaseTaskResult, type CompleteEvent, type CostEvent, type CostInfo, DEFAULT_TIMEOUT_MS, type DailyUsage, type DubbingLanguage, type DubbingParams, type DubbingResult, type DuckingResult, type ErrorEvent, GenerationError, type MusicMediaEntry, type MusicMuxEntry, type MusicTaskResult, type MusicTitle, PaymentRequiredError, RateLimitError, RequestTimeoutError, type Segment, type SegmentLabel, type SfxAudioFormat, type SfxError, type SfxMedia, type SfxResult, type SfxSegment, type SfxTask, SoniloClient, type SoniloClientOptions, SoniloError, type SoundOutputEntry, type SoundResult, type 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 VideoToVideoSoundParams, type WaitOptions, download, isAudioChunkEvent, isErrorEvent };
886
+ export { APIError, type AccountServices, type AnalysisSegment, type AnalysisVariation, type AudioChunkEvent, type AudioDuckingParams, AuthenticationError, BadRequestError, type BaseTaskResult, type CompleteEvent, type CostEvent, type CostInfo, DEFAULT_TIMEOUT_MS, type DailyUsage, type DubbingLanguage, type DubbingParams, type DubbingResult, type DuckingResult, type ErrorEvent, GenerationError, type MusicMediaEntry, type MusicMuxEntry, type MusicTaskResult, type MusicTitle, PaymentRequiredError, RateLimitError, RequestTimeoutError, type Segment, type SegmentLabel, type SfxAudioFormat, type SfxError, type SfxMedia, type SfxResult, type SfxSegment, type SfxTask, SoniloClient, type SoniloClientOptions, SoniloError, type SoundOutputEntry, type SoundResult, type StemsEntry, type StreamEvent, TaskFailedError, TaskTimeoutError, type TextToMusicParams, type TextToSfxParams, type TitleEvent, type Track, TrialExhaustedError, type TrialQuota, type UnknownEvent, type UsageResponse, type UsageSummary, VERSION, type VideoAnalysisParams, type VideoAnalysisResult, type VideoInput, type VideoResult, type VideoToMusicParams, type VideoToSfxParams, type VideoToSoundParams, type VideoToVideoMusicParams, type VideoToVideoSfxParams, type VideoToVideoSoundParams, type WaitOptions, download, isAudioChunkEvent, isErrorEvent };
package/dist/index.d.ts CHANGED
@@ -64,6 +64,16 @@ interface TextToMusicParams {
64
64
  * meaningful via `submit()`; `stream()`/`generate()` never send it, since
65
65
  * they always request a plain stream. */
66
66
  variantsNum?: number;
67
+ /** Also split the generated track into four separated stems — `drums`,
68
+ * `bass`, `vocals`, `other` — delivered on the task result's `stems`
69
+ * array. Free of charge. Requires `mode: "async"` (the backend rejects it
70
+ * on the plain stream with a 400), so it is only meaningful via
71
+ * `submit()`; `stream()`/`generate()` never send it. Separation runs after
72
+ * generation and typically adds 2-6 minutes to the wait (it gives up after
73
+ * 30), so raise `tasks.wait`'s `timeout` accordingly. See `StemsEntry` for
74
+ * the result shape, and `MusicTaskResult.stems_error` for how failures are
75
+ * reported. */
76
+ stems?: boolean;
67
77
  /** Bounds the stream: aborting this cancels the in-flight generation.
68
78
  * Passed straight through to `fetch` — it is never rewrapped as
69
79
  * RequestTimeoutError, since the client's own absolute timeout does not
@@ -118,6 +128,17 @@ interface VideoToMusicParams {
118
128
  * default applies; `0` is a meaningful value and is sent. Out-of-range
119
129
  * values are rejected server-side with a 422. */
120
130
  promptInfluence?: number;
131
+ /** Also split the generated music into four separated stems — `drums`,
132
+ * `bass`, `vocals`, `other` — delivered on the task result's `stems`
133
+ * array. It splits the GENERATED music, never the source video's own
134
+ * audio. Free of charge. Requires `mode: "async"` (auto-selected by
135
+ * `submit()`; the backend rejects it on the plain stream with a 400), so
136
+ * it is only meaningful via `submit()` — `stream()`/`generate()` never
137
+ * send it. Separation runs after generation and typically adds 2-6
138
+ * minutes to the wait (it gives up after 30), so raise `tasks.wait`'s
139
+ * `timeout` accordingly. See `StemsEntry` for the result shape, and
140
+ * `MusicTaskResult.stems_error` for how failures are reported. */
141
+ stems?: boolean;
121
142
  }
122
143
  /** One service's free-trial allowance. `remaining` is already floored at 0,
123
144
  * so it is safe to compare directly. */
@@ -244,6 +265,21 @@ interface MusicTitle {
244
265
  summary?: string;
245
266
  display_tags?: string[];
246
267
  }
268
+ /** The four separated stems of one generated stream, present when the
269
+ * request set `stems: true`. Each stem is an ordinary media object
270
+ * (`url` / `content_type` / `file_size`), so any of them can be passed to
271
+ * `download()`. The stems normally follow the request's `outputFormat`;
272
+ * each stem's own `content_type` reports what was actually delivered. */
273
+ interface StemsEntry {
274
+ /** Which `audio` entry this stems set belongs to. Match on this field,
275
+ * never on array position — `stems` carries only the streams that
276
+ * separated successfully, so it can be shorter than `audio`. */
277
+ stream_index: number;
278
+ drums: SfxMedia;
279
+ bass: SfxMedia;
280
+ vocals: SfxMedia;
281
+ other: SfxMedia;
282
+ }
247
283
  /** State of an async video-to-music task (`tasks.get`) or its final result
248
284
  * (`tasks.wait<MusicTaskResult>()`). Only reachable via `videoToMusic.submit()`
249
285
  * with `mode: "async"`. */
@@ -259,6 +295,16 @@ interface MusicTaskResult extends BaseTaskResult {
259
295
  /** Music ducked under the source voice (per variant when `variantsNum` is
260
296
  * above 1); present only when `ducking` ran. */
261
297
  ducked?: MusicMediaEntry[];
298
+ /** Separated stems, one entry per stream that separated successfully;
299
+ * only appears when the request set `stems: true`. Look entries up by
300
+ * `stream_index`, never by array position — the array can be shorter than
301
+ * `audio` when separation failed for some streams (see `stems_error`). */
302
+ stems?: StemsEntry[];
303
+ /** Why stem separation failed wholly or in part, or was skipped. It can
304
+ * appear ALONGSIDE a partial `stems` array, so never treat its presence as
305
+ * "no stems" — check `stems` itself for what did arrive. Independent of
306
+ * the task's own `status`/`error`: the generation is intact either way. */
307
+ stems_error?: string;
262
308
  /** Variant 0's title — the top-level field always names the first variant,
263
309
  * even when `variantsNum` produced others with their own titles on
264
310
  * `audio[]`. */
@@ -511,6 +557,50 @@ interface DubbingResult extends BaseTaskResult {
511
557
  */
512
558
  outputs?: Record<string, string>;
513
559
  }
560
+ interface VideoAnalysisParams {
561
+ /** Exactly one of `video` / `videoUrl`. */
562
+ video?: VideoInput;
563
+ /** Exactly one of `video` / `videoUrl`. */
564
+ videoUrl?: string;
565
+ /** Optional guidance for the analysis, at most 2000 characters. */
566
+ prompt?: string;
567
+ /**
568
+ * How many independent creative briefs to author for the same video
569
+ * (1-5, default 1). Billed per brief.
570
+ */
571
+ variantsNum?: number;
572
+ }
573
+ /** One time-aligned section of the analyzed video, with the scoring
574
+ * direction for that stretch. Bounds are whole seconds — the backend
575
+ * truncates any fractional upstream bound before it reaches the envelope. */
576
+ interface AnalysisSegment {
577
+ start: number;
578
+ end: number;
579
+ /** The backend always emits one, defaulting to the string `"none"`. */
580
+ label: string;
581
+ prompt: string;
582
+ }
583
+ /** One independent creative brief for the whole video. Only the generation
584
+ * prompt is public — the upstream's title/summary/tags are internal display
585
+ * copy the API deliberately does not resell. */
586
+ interface AnalysisVariation {
587
+ prompt: string;
588
+ }
589
+ /**
590
+ * The only Sonilo result with no media artifact at all: video-analysis
591
+ * generates nothing and there is nothing to download. The payload is the
592
+ * work order — `segments` for a time-aligned plan, and one `prompt` per
593
+ * requested variation, each ready to pass to videoToMusic, videoToSfx,
594
+ * videoToSound or their video-to-video counterparts.
595
+ *
596
+ * Both lists are optional because a `processing` or `failed` poll carries
597
+ * neither.
598
+ */
599
+ interface VideoAnalysisResult extends BaseTaskResult {
600
+ segments?: AnalysisSegment[];
601
+ variations?: AnalysisVariation[];
602
+ duration_seconds?: number;
603
+ }
514
604
 
515
605
  declare class Account {
516
606
  private readonly client;
@@ -552,8 +642,8 @@ declare class TextToMusic {
552
642
  /**
553
643
  * Submit an async text-to-music task; poll with
554
644
  * `client.tasks.wait<MusicTaskResult>(task.task_id)`. Required for
555
- * a non-m4a `outputFormat` and `variantsNum` above 1. `stream()`/`generate()`
556
- * remain the streaming path.
645
+ * a non-m4a `outputFormat`, `variantsNum` above 1, and `stems`.
646
+ * `stream()`/`generate()` remain the streaming path.
557
647
  */
558
648
  submit(params: TextToMusicParams): Promise<SfxTask>;
559
649
  }
@@ -566,9 +656,9 @@ declare class VideoToMusic {
566
656
  /**
567
657
  * Submit an async video-to-music task; poll its result with
568
658
  * `client.tasks.wait<MusicTaskResult>(task.task_id)`. Required for
569
- * `isolateVocals`/`preserveSpeech`, a non-m4a `outputFormat`, and
570
- * `variantsNum` above 1 — the backend rejects all of these on the plain
571
- * stream, and they only ever run in async mode.
659
+ * `isolateVocals`/`preserveSpeech`, a non-m4a `outputFormat`,
660
+ * `variantsNum` above 1, and `stems` — the backend rejects all of these on
661
+ * the plain stream, and they only ever run in async mode.
572
662
  */
573
663
  submit(params: VideoToMusicParams): Promise<SfxTask>;
574
664
  }
@@ -648,6 +738,28 @@ declare class Dubbing {
648
738
  generate(params: DubbingParams, opts?: WaitOptions): Promise<DubbingResult>;
649
739
  }
650
740
 
741
+ /** Analyze a video and get back a creative brief for scoring it. Async only.
742
+ *
743
+ * This endpoint generates nothing — no audio, no video, no artifact to
744
+ * download. The result is the work order: `segments` (a time-aligned section
745
+ * plan) plus one `prompt` per requested variation, each ready to hand
746
+ * straight to videoToMusic, videoToSfx, videoToSound or their
747
+ * video-to-video counterparts.
748
+ *
749
+ * The method is `analyze`, not `generate`, for that reason: every other
750
+ * resource's `generate` returns something you download, and this one never
751
+ * does.
752
+ *
753
+ * The 1-5 bound on `variantsNum` and the 2000-character bound on `prompt`
754
+ * are deliberately not checked here — the backend owns them, and a hardcoded
755
+ * copy would make this SDK reject values a later API widens. */
756
+ declare class VideoAnalysis {
757
+ private readonly client;
758
+ constructor(client: SoniloClient);
759
+ submit(params: VideoAnalysisParams): Promise<SfxTask>;
760
+ analyze(params: VideoAnalysisParams, opts?: WaitOptions): Promise<VideoAnalysisResult>;
761
+ }
762
+
651
763
  interface SoniloClientOptions {
652
764
  /** Defaults to the SONILO_API_KEY environment variable (Node.js only). */
653
765
  apiKey?: string;
@@ -687,6 +799,7 @@ declare class SoniloClient {
687
799
  readonly videoToVideoSound: VideoToVideoSound;
688
800
  readonly audioDucking: AudioDucking;
689
801
  readonly dubbing: Dubbing;
802
+ readonly videoAnalysis: VideoAnalysis;
690
803
  constructor(options?: SoniloClientOptions);
691
804
  /**
692
805
  * Perform an authenticated request; throws a typed error on non-2xx.
@@ -768,6 +881,6 @@ declare class RequestTimeoutError extends SoniloError {
768
881
  declare function download(media: SfxMedia | string | undefined, fetchFn?: typeof globalThis.fetch, timeout?: number): Promise<Uint8Array>;
769
882
 
770
883
  /** The SDK's own version. Generated by scripts/sync-versions.mjs — do not edit. */
771
- declare const VERSION = "0.14.0";
884
+ declare const VERSION = "0.16.0";
772
885
 
773
- export { APIError, type AccountServices, type AudioChunkEvent, type AudioDuckingParams, AuthenticationError, BadRequestError, type BaseTaskResult, type CompleteEvent, type CostEvent, type CostInfo, DEFAULT_TIMEOUT_MS, type DailyUsage, type DubbingLanguage, type DubbingParams, type DubbingResult, type DuckingResult, type ErrorEvent, GenerationError, type MusicMediaEntry, type MusicMuxEntry, type MusicTaskResult, type MusicTitle, PaymentRequiredError, RateLimitError, RequestTimeoutError, type Segment, type SegmentLabel, type SfxAudioFormat, type SfxError, type SfxMedia, type SfxResult, type SfxSegment, type SfxTask, SoniloClient, type SoniloClientOptions, SoniloError, type SoundOutputEntry, type SoundResult, type 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 VideoToVideoSoundParams, type WaitOptions, download, isAudioChunkEvent, isErrorEvent };
886
+ export { APIError, type AccountServices, type AnalysisSegment, type AnalysisVariation, type AudioChunkEvent, type AudioDuckingParams, AuthenticationError, BadRequestError, type BaseTaskResult, type CompleteEvent, type CostEvent, type CostInfo, DEFAULT_TIMEOUT_MS, type DailyUsage, type DubbingLanguage, type DubbingParams, type DubbingResult, type DuckingResult, type ErrorEvent, GenerationError, type MusicMediaEntry, type MusicMuxEntry, type MusicTaskResult, type MusicTitle, PaymentRequiredError, RateLimitError, RequestTimeoutError, type Segment, type SegmentLabel, type SfxAudioFormat, type SfxError, type SfxMedia, type SfxResult, type SfxSegment, type SfxTask, SoniloClient, type SoniloClientOptions, SoniloError, type SoundOutputEntry, type SoundResult, type StemsEntry, type StreamEvent, TaskFailedError, TaskTimeoutError, type TextToMusicParams, type TextToSfxParams, type TitleEvent, type Track, TrialExhaustedError, type TrialQuota, type UnknownEvent, type UsageResponse, type UsageSummary, VERSION, type VideoAnalysisParams, type VideoAnalysisResult, type VideoInput, type VideoResult, type VideoToMusicParams, type VideoToSfxParams, type VideoToSoundParams, type VideoToVideoMusicParams, type VideoToVideoSfxParams, type VideoToVideoSoundParams, type WaitOptions, download, isAudioChunkEvent, isErrorEvent };
package/dist/index.js CHANGED
@@ -305,8 +305,8 @@ var TextToMusic = class {
305
305
  /**
306
306
  * Submit an async text-to-music task; poll with
307
307
  * `client.tasks.wait<MusicTaskResult>(task.task_id)`. Required for
308
- * a non-m4a `outputFormat` and `variantsNum` above 1. `stream()`/`generate()`
309
- * remain the streaming path.
308
+ * a non-m4a `outputFormat`, `variantsNum` above 1, and `stems`.
309
+ * `stream()`/`generate()` remain the streaming path.
310
310
  */
311
311
  async submit(params) {
312
312
  const mode = params.mode ?? "async";
@@ -326,6 +326,9 @@ var TextToMusic = class {
326
326
  if (params.variantsNum !== void 0) {
327
327
  form.set("variants_num", String(params.variantsNum));
328
328
  }
329
+ if (params.stems !== void 0) {
330
+ form.set("stems", String(params.stems));
331
+ }
329
332
  const res = await this.client.request("/v1/text-to-music", {
330
333
  method: "POST",
331
334
  body: form
@@ -409,9 +412,9 @@ var VideoToMusic = class {
409
412
  /**
410
413
  * Submit an async video-to-music task; poll its result with
411
414
  * `client.tasks.wait<MusicTaskResult>(task.task_id)`. Required for
412
- * `isolateVocals`/`preserveSpeech`, a non-m4a `outputFormat`, and
413
- * `variantsNum` above 1 — the backend rejects all of these on the plain
414
- * stream, and they only ever run in async mode.
415
+ * `isolateVocals`/`preserveSpeech`, a non-m4a `outputFormat`,
416
+ * `variantsNum` above 1, and `stems` — the backend rejects all of these on
417
+ * the plain stream, and they only ever run in async mode.
415
418
  */
416
419
  async submit(params) {
417
420
  if (params.video === void 0 === (params.videoUrl === void 0)) {
@@ -421,11 +424,11 @@ var VideoToMusic = class {
421
424
  const needsAsync = params.isolateVocals || params.preserveSpeech || params.ducking !== void 0 || // Any non-m4a container is a finalize-time transcode, so it needs
422
425
  // async. Checking != "m4a" rather than == "wav" keeps this correct
423
426
  // as formats are added (mp3 landed after the original check).
424
- params.outputFormat !== void 0 && params.outputFormat !== "m4a" || params.variantsNum !== void 0 && params.variantsNum > 1;
427
+ params.outputFormat !== void 0 && params.outputFormat !== "m4a" || params.variantsNum !== void 0 && params.variantsNum > 1 || params.stems !== void 0;
425
428
  if (mode === void 0) mode = "async";
426
429
  if (needsAsync && mode !== "async") {
427
430
  throw new SoniloError(
428
- 'isolateVocals/preserveSpeech/ducking/outputFormat other than "m4a"/variantsNum > 1 require mode: "async"'
431
+ 'isolateVocals/preserveSpeech/ducking/stems/outputFormat other than "m4a"/variantsNum > 1 require mode: "async"'
429
432
  );
430
433
  }
431
434
  const form = new FormData();
@@ -455,6 +458,9 @@ var VideoToMusic = class {
455
458
  if (params.variantsNum !== void 0) {
456
459
  form.set("variants_num", String(params.variantsNum));
457
460
  }
461
+ if (params.stems !== void 0) {
462
+ form.set("stems", String(params.stems));
463
+ }
458
464
  if (params.promptInfluence !== void 0) {
459
465
  form.set("prompt_influence", String(params.promptInfluence));
460
466
  }
@@ -750,8 +756,40 @@ var Dubbing = class {
750
756
  }
751
757
  };
752
758
 
759
+ // src/resources/videoAnalysis.ts
760
+ var VideoAnalysis = class {
761
+ constructor(client) {
762
+ this.client = client;
763
+ }
764
+ async submit(params) {
765
+ if (params.video === void 0 === (params.videoUrl === void 0)) {
766
+ throw new SoniloError("Provide exactly one of video or videoUrl");
767
+ }
768
+ const form = new FormData();
769
+ if (params.video !== void 0) {
770
+ const { blob, filename } = await toUploadBlob(params.video);
771
+ form.set("video", blob, filename);
772
+ } else {
773
+ form.set("video_url", params.videoUrl);
774
+ }
775
+ if (params.prompt !== void 0) form.set("prompt", params.prompt);
776
+ if (params.variantsNum !== void 0) {
777
+ form.set("variants_num", String(params.variantsNum));
778
+ }
779
+ const res = await this.client.request("/v1/video-analysis", {
780
+ method: "POST",
781
+ body: form
782
+ });
783
+ return await res.json();
784
+ }
785
+ async analyze(params, opts) {
786
+ const task = await this.submit(params);
787
+ return this.client.tasks.wait(task.task_id, opts);
788
+ }
789
+ };
790
+
753
791
  // src/version.ts
754
- var VERSION = "0.14.0";
792
+ var VERSION = "0.16.0";
755
793
 
756
794
  // src/client.ts
757
795
  var DEFAULT_BASE_URL = "https://api.sonilo.com";
@@ -784,6 +822,7 @@ var SoniloClient = class {
784
822
  this.videoToVideoSound = new VideoToVideoSound(this);
785
823
  this.audioDucking = new AudioDucking(this);
786
824
  this.dubbing = new Dubbing(this);
825
+ this.videoAnalysis = new VideoAnalysis(this);
787
826
  }
788
827
  /**
789
828
  * Perform an authenticated request; throws a typed error on non-2xx.