sonilo 0.13.0 → 0.15.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.ts CHANGED
@@ -452,6 +452,34 @@ interface SoundResult extends BaseTaskResult {
452
452
  /** One entry per variant; see `SoundOutputEntry`. */
453
453
  outputs?: SoundOutputEntry[];
454
454
  }
455
+ /** Params for `audioDucking`: mix an existing music bed under an existing
456
+ * voice track, ducking the music wherever the voice speaks. Exactly one of
457
+ * `voice`/`voiceUrl` and exactly one of `music`/`musicUrl`; a local input and
458
+ * a URL may be mixed across the two.
459
+ *
460
+ * The voice may be audio or video (`VideoInput` is the SDK's generic media
461
+ * input union) — a video's own audio track becomes the voice, and the ducked
462
+ * mix is re-muxed back into a new video. The music must be audio: the backend
463
+ * never probes it for a video stream, so a video there would be silently
464
+ * mishandled. Each input is capped at 360 seconds server-side. */
465
+ interface AudioDuckingParams {
466
+ voice?: VideoInput;
467
+ voiceUrl?: string;
468
+ music?: VideoInput;
469
+ musicUrl?: string;
470
+ }
471
+ /** Result of an `audioDucking` task (`tasks.get`) or its final state
472
+ * (`generate`). Same flat envelope as `SoundResult`, but a ducking task
473
+ * renders exactly one artifact and no stems: a `.wav` (`output_type`
474
+ * "audio"), or a `.mp4` with the ducked mix re-muxed in (`output_type`
475
+ * "video") when the voice input was a video. Pass `output_url` to
476
+ * `download()`. */
477
+ interface DuckingResult extends BaseTaskResult {
478
+ output_url?: string;
479
+ output_type?: "audio" | "video";
480
+ output_bytes?: number;
481
+ duration_seconds?: number;
482
+ }
455
483
  /**
456
484
  * A target language for /v1/dubbing. The union stays open (`string & {}`) so a
457
485
  * language added server-side still type-checks against an older SDK — the
@@ -483,6 +511,50 @@ interface DubbingResult extends BaseTaskResult {
483
511
  */
484
512
  outputs?: Record<string, string>;
485
513
  }
514
+ interface VideoAnalysisParams {
515
+ /** Exactly one of `video` / `videoUrl`. */
516
+ video?: VideoInput;
517
+ /** Exactly one of `video` / `videoUrl`. */
518
+ videoUrl?: string;
519
+ /** Optional guidance for the analysis, at most 2000 characters. */
520
+ prompt?: string;
521
+ /**
522
+ * How many independent creative briefs to author for the same video
523
+ * (1-5, default 1). Billed per brief.
524
+ */
525
+ variantsNum?: number;
526
+ }
527
+ /** One time-aligned section of the analyzed video, with the scoring
528
+ * direction for that stretch. Bounds are whole seconds — the backend
529
+ * truncates any fractional upstream bound before it reaches the envelope. */
530
+ interface AnalysisSegment {
531
+ start: number;
532
+ end: number;
533
+ /** The backend always emits one, defaulting to the string `"none"`. */
534
+ label: string;
535
+ prompt: string;
536
+ }
537
+ /** One independent creative brief for the whole video. Only the generation
538
+ * prompt is public — the upstream's title/summary/tags are internal display
539
+ * copy the API deliberately does not resell. */
540
+ interface AnalysisVariation {
541
+ prompt: string;
542
+ }
543
+ /**
544
+ * The only Sonilo result with no media artifact at all: video-analysis
545
+ * generates nothing and there is nothing to download. The payload is the
546
+ * work order — `segments` for a time-aligned plan, and one `prompt` per
547
+ * requested variation, each ready to pass to videoToMusic, videoToSfx,
548
+ * videoToSound or their video-to-video counterparts.
549
+ *
550
+ * Both lists are optional because a `processing` or `failed` poll carries
551
+ * neither.
552
+ */
553
+ interface VideoAnalysisResult extends BaseTaskResult {
554
+ segments?: AnalysisSegment[];
555
+ variations?: AnalysisVariation[];
556
+ duration_seconds?: number;
557
+ }
486
558
 
487
559
  declare class Account {
488
560
  private readonly client;
@@ -596,6 +668,21 @@ declare class VideoToVideoSound {
596
668
  generate(params: VideoToVideoSoundParams, opts?: WaitOptions): Promise<SoundResult>;
597
669
  }
598
670
 
671
+ /** Duck an existing music bed under a voice track. Async only (202 + poll).
672
+ *
673
+ * Both inputs are user-supplied — nothing is generated here. The voice may be
674
+ * audio OR a video: the backend extracts a video's audio track, ducks the
675
+ * music under it, and re-muxes the ducked mix back into a new video (the
676
+ * result's `output_type` announces which came back). The music must be audio —
677
+ * the backend never probes it for a video stream, so a video there would be
678
+ * silently mishandled. */
679
+ declare class AudioDucking {
680
+ private readonly client;
681
+ constructor(client: SoniloClient);
682
+ submit(params: AudioDuckingParams): Promise<SfxTask>;
683
+ generate(params: AudioDuckingParams, opts?: WaitOptions): Promise<DuckingResult>;
684
+ }
685
+
599
686
  /** Dub a video into one or more target languages. Async only; the result
600
687
  * carries a language → dubbed-video-URL map under `outputs`. */
601
688
  declare class Dubbing {
@@ -605,6 +692,28 @@ declare class Dubbing {
605
692
  generate(params: DubbingParams, opts?: WaitOptions): Promise<DubbingResult>;
606
693
  }
607
694
 
695
+ /** Analyze a video and get back a creative brief for scoring it. Async only.
696
+ *
697
+ * This endpoint generates nothing — no audio, no video, no artifact to
698
+ * download. The result is the work order: `segments` (a time-aligned section
699
+ * plan) plus one `prompt` per requested variation, each ready to hand
700
+ * straight to videoToMusic, videoToSfx, videoToSound or their
701
+ * video-to-video counterparts.
702
+ *
703
+ * The method is `analyze`, not `generate`, for that reason: every other
704
+ * resource's `generate` returns something you download, and this one never
705
+ * does.
706
+ *
707
+ * The 1-5 bound on `variantsNum` and the 2000-character bound on `prompt`
708
+ * are deliberately not checked here — the backend owns them, and a hardcoded
709
+ * copy would make this SDK reject values a later API widens. */
710
+ declare class VideoAnalysis {
711
+ private readonly client;
712
+ constructor(client: SoniloClient);
713
+ submit(params: VideoAnalysisParams): Promise<SfxTask>;
714
+ analyze(params: VideoAnalysisParams, opts?: WaitOptions): Promise<VideoAnalysisResult>;
715
+ }
716
+
608
717
  interface SoniloClientOptions {
609
718
  /** Defaults to the SONILO_API_KEY environment variable (Node.js only). */
610
719
  apiKey?: string;
@@ -642,7 +751,9 @@ declare class SoniloClient {
642
751
  readonly videoToVideoSfx: VideoToVideoSfx;
643
752
  readonly videoToSound: VideoToSound;
644
753
  readonly videoToVideoSound: VideoToVideoSound;
754
+ readonly audioDucking: AudioDucking;
645
755
  readonly dubbing: Dubbing;
756
+ readonly videoAnalysis: VideoAnalysis;
646
757
  constructor(options?: SoniloClientOptions);
647
758
  /**
648
759
  * Perform an authenticated request; throws a typed error on non-2xx.
@@ -724,6 +835,6 @@ declare class RequestTimeoutError extends SoniloError {
724
835
  declare function download(media: SfxMedia | string | undefined, fetchFn?: typeof globalThis.fetch, timeout?: number): Promise<Uint8Array>;
725
836
 
726
837
  /** The SDK's own version. Generated by scripts/sync-versions.mjs — do not edit. */
727
- declare const VERSION = "0.13.0";
838
+ declare const VERSION = "0.15.0";
728
839
 
729
- 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 VideoToVideoSoundParams, type WaitOptions, download, isAudioChunkEvent, isErrorEvent };
840
+ 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 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
@@ -670,6 +670,43 @@ var VideoToVideoSound = class {
670
670
  }
671
671
  };
672
672
 
673
+ // src/resources/audioDucking.ts
674
+ var AudioDucking = class {
675
+ constructor(client) {
676
+ this.client = client;
677
+ }
678
+ async submit(params) {
679
+ if (params.voice === void 0 === (params.voiceUrl === void 0)) {
680
+ throw new SoniloError("Provide exactly one of voice or voiceUrl");
681
+ }
682
+ if (params.music === void 0 === (params.musicUrl === void 0)) {
683
+ throw new SoniloError("Provide exactly one of music or musicUrl");
684
+ }
685
+ const form = new FormData();
686
+ if (params.voice !== void 0) {
687
+ const { blob, filename } = await toUploadBlob(params.voice);
688
+ form.set("voice_file", blob, filename);
689
+ } else {
690
+ form.set("voice_url", params.voiceUrl);
691
+ }
692
+ if (params.music !== void 0) {
693
+ const { blob, filename } = await toUploadBlob(params.music);
694
+ form.set("music_file", blob, filename);
695
+ } else {
696
+ form.set("music_url", params.musicUrl);
697
+ }
698
+ const res = await this.client.request("/v1/audio-ducking", {
699
+ method: "POST",
700
+ body: form
701
+ });
702
+ return await res.json();
703
+ }
704
+ async generate(params, opts) {
705
+ const task = await this.submit(params);
706
+ return this.client.tasks.wait(task.task_id, opts);
707
+ }
708
+ };
709
+
673
710
  // src/resources/dubbing.ts
674
711
  async function buildDubbingForm(params) {
675
712
  if (params.video === void 0 === (params.videoUrl === void 0)) {
@@ -713,8 +750,40 @@ var Dubbing = class {
713
750
  }
714
751
  };
715
752
 
753
+ // src/resources/videoAnalysis.ts
754
+ var VideoAnalysis = class {
755
+ constructor(client) {
756
+ this.client = client;
757
+ }
758
+ async submit(params) {
759
+ if (params.video === void 0 === (params.videoUrl === void 0)) {
760
+ throw new SoniloError("Provide exactly one of video or videoUrl");
761
+ }
762
+ const form = new FormData();
763
+ if (params.video !== void 0) {
764
+ const { blob, filename } = await toUploadBlob(params.video);
765
+ form.set("video", blob, filename);
766
+ } else {
767
+ form.set("video_url", params.videoUrl);
768
+ }
769
+ if (params.prompt !== void 0) form.set("prompt", params.prompt);
770
+ if (params.variantsNum !== void 0) {
771
+ form.set("variants_num", String(params.variantsNum));
772
+ }
773
+ const res = await this.client.request("/v1/video-analysis", {
774
+ method: "POST",
775
+ body: form
776
+ });
777
+ return await res.json();
778
+ }
779
+ async analyze(params, opts) {
780
+ const task = await this.submit(params);
781
+ return this.client.tasks.wait(task.task_id, opts);
782
+ }
783
+ };
784
+
716
785
  // src/version.ts
717
- var VERSION = "0.13.0";
786
+ var VERSION = "0.15.0";
718
787
 
719
788
  // src/client.ts
720
789
  var DEFAULT_BASE_URL = "https://api.sonilo.com";
@@ -745,7 +814,9 @@ var SoniloClient = class {
745
814
  this.videoToVideoSfx = new VideoToVideoSfx(this);
746
815
  this.videoToSound = new VideoToSound(this);
747
816
  this.videoToVideoSound = new VideoToVideoSound(this);
817
+ this.audioDucking = new AudioDucking(this);
748
818
  this.dubbing = new Dubbing(this);
819
+ this.videoAnalysis = new VideoAnalysis(this);
749
820
  }
750
821
  /**
751
822
  * Perform an authenticated request; throws a typed error on non-2xx.