songbrain 0.3.3 → 0.4.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 +29 -6
- package/dist/index.cjs +31 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +126 -9
- package/dist/index.d.ts +126 -9
- package/dist/index.js +31 -6
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -7,6 +7,12 @@
|
|
|
7
7
|
* otherwise (`start_in_clip`).
|
|
8
8
|
*/
|
|
9
9
|
type SongStatus = "processing" | "done" | "failed";
|
|
10
|
+
/**
|
|
11
|
+
* What a song includes. "full" (the default): Song DNA + video direction (story,
|
|
12
|
+
* shot plan), 25 credits. "dna": Song DNA only (song_dna, timeline, best_moments,
|
|
13
|
+
* lyrics, scores), 10 credits. Add the direction to a dna song later for 15 credits.
|
|
14
|
+
*/
|
|
15
|
+
type Mode = "full" | "dna";
|
|
10
16
|
/** One of the sections a song document has. Use with `include`. */
|
|
11
17
|
type SectionName = "song_dna" | "timeline" | "best_moments" | "lyrics" | "scores" | "story" | "shot_plan";
|
|
12
18
|
interface Billing {
|
|
@@ -305,9 +311,22 @@ interface ErrorInfo {
|
|
|
305
311
|
/** "req_…", also in the Songbrain-Request-Id header. */
|
|
306
312
|
request_id?: string;
|
|
307
313
|
}
|
|
314
|
+
/** On a "dna" song: how to add the video direction (story + shot plan) later. */
|
|
315
|
+
interface DirectionOffer {
|
|
316
|
+
included: false;
|
|
317
|
+
/** "POST https://api.songbrain.ai/v1/songs/{id}/direction" */
|
|
318
|
+
add: string;
|
|
319
|
+
/** 15 */
|
|
320
|
+
credits: number;
|
|
321
|
+
/** 0.3 */
|
|
322
|
+
usd: number;
|
|
323
|
+
/** ["story", "shot_plan"] */
|
|
324
|
+
adds: SectionName[];
|
|
325
|
+
}
|
|
308
326
|
/**
|
|
309
|
-
* The song document. While processing, only `id`, `status`, `progress
|
|
310
|
-
* `eta_sec` are set. With `include`, only the named sections are
|
|
327
|
+
* The song document. While processing, only `id`, `status`, `progress`,
|
|
328
|
+
* `eta_sec` and `mode` are set. With `include`, only the named sections are
|
|
329
|
+
* present. A "dna" song has no `story` and no `shot_plan`; it has `direction`.
|
|
311
330
|
*/
|
|
312
331
|
interface Song {
|
|
313
332
|
object: "song";
|
|
@@ -333,18 +352,35 @@ interface Song {
|
|
|
333
352
|
livemode?: boolean;
|
|
334
353
|
/** Measured vs. transcribed vs. model estimate vs. generated. */
|
|
335
354
|
provenance?: Provenance;
|
|
355
|
+
/** "full" or "dna" (API 1.3). */
|
|
356
|
+
mode?: Mode;
|
|
357
|
+
/** Only on "dna" songs: how to add the story and shot plan. */
|
|
358
|
+
direction?: DirectionOffer;
|
|
336
359
|
}
|
|
337
360
|
/** The 202 body of POST /songs. */
|
|
338
361
|
interface SongCreated {
|
|
339
362
|
object: "song";
|
|
340
363
|
id: string;
|
|
341
364
|
status: "processing";
|
|
365
|
+
mode?: Mode;
|
|
342
366
|
eta_sec: number;
|
|
343
367
|
billing: Billing;
|
|
344
368
|
external_ref?: string | null;
|
|
345
369
|
url: string;
|
|
346
370
|
livemode?: boolean;
|
|
347
371
|
}
|
|
372
|
+
/** The 202 body of POST /songs/{id}/direction. */
|
|
373
|
+
interface DirectionCreated {
|
|
374
|
+
object: "song";
|
|
375
|
+
id: string;
|
|
376
|
+
/** "processing"; "done" right away for a test-mode song. */
|
|
377
|
+
status: "processing" | "done";
|
|
378
|
+
mode: "full";
|
|
379
|
+
eta_sec: number;
|
|
380
|
+
billing: Billing;
|
|
381
|
+
url: string;
|
|
382
|
+
livemode?: boolean;
|
|
383
|
+
}
|
|
348
384
|
/** GET /songs/{id}/shot-plan and GET /examples/{id}/shot-plan. */
|
|
349
385
|
interface SongShotPlan {
|
|
350
386
|
id: string;
|
|
@@ -356,6 +392,7 @@ interface SongShotPlan {
|
|
|
356
392
|
interface SongListItem {
|
|
357
393
|
id: string;
|
|
358
394
|
status: string;
|
|
395
|
+
mode?: Mode;
|
|
359
396
|
external_ref: string | null;
|
|
360
397
|
created_at: string | null;
|
|
361
398
|
billing: Billing;
|
|
@@ -391,13 +428,36 @@ interface ExampleList {
|
|
|
391
428
|
object: "list";
|
|
392
429
|
data: ExampleSummary[];
|
|
393
430
|
}
|
|
431
|
+
interface Price {
|
|
432
|
+
credits: number;
|
|
433
|
+
usd: number;
|
|
434
|
+
}
|
|
435
|
+
interface ModePrice extends Price {
|
|
436
|
+
name: string;
|
|
437
|
+
/** Section names the mode returns. */
|
|
438
|
+
includes: SectionName[];
|
|
439
|
+
default?: boolean;
|
|
440
|
+
}
|
|
441
|
+
interface AddDirectionPrice extends Price {
|
|
442
|
+
/** "POST /v1/songs/{id}/direction" */
|
|
443
|
+
endpoint: string;
|
|
444
|
+
note?: string;
|
|
445
|
+
}
|
|
394
446
|
interface Account {
|
|
395
447
|
credits: number;
|
|
396
448
|
free_songs_per_month: number;
|
|
397
449
|
free_songs_used: number;
|
|
398
450
|
free_songs_left: number;
|
|
451
|
+
/** Mode "full". */
|
|
399
452
|
price_per_song_credits: number;
|
|
453
|
+
/** Mode "full". */
|
|
400
454
|
price_per_song_usd: number;
|
|
455
|
+
/** Price per mode (API 1.3). */
|
|
456
|
+
prices?: {
|
|
457
|
+
full: Price;
|
|
458
|
+
dna: Price;
|
|
459
|
+
add_direction: Price;
|
|
460
|
+
};
|
|
401
461
|
songs_this_month: number;
|
|
402
462
|
buy_credits_url: string;
|
|
403
463
|
songs_left_from_credits?: number;
|
|
@@ -410,8 +470,19 @@ interface Account {
|
|
|
410
470
|
}
|
|
411
471
|
interface Pricing {
|
|
412
472
|
free_songs_per_month: number;
|
|
473
|
+
/** "either mode" */
|
|
474
|
+
free_songs_cover?: string;
|
|
475
|
+
/** Mode "full". */
|
|
413
476
|
price_per_song_credits: number;
|
|
477
|
+
/** Mode "full". */
|
|
414
478
|
price_per_song_usd: number;
|
|
479
|
+
/** API 1.3. */
|
|
480
|
+
modes?: {
|
|
481
|
+
full: ModePrice;
|
|
482
|
+
dna: ModePrice;
|
|
483
|
+
};
|
|
484
|
+
/** API 1.3: story + shot plan for a finished dna song. */
|
|
485
|
+
add_direction?: AddDirectionPrice;
|
|
415
486
|
credit_packs: {
|
|
416
487
|
credits: number;
|
|
417
488
|
usd: number;
|
|
@@ -421,7 +492,12 @@ interface Pricing {
|
|
|
421
492
|
limits: Record<string, number>;
|
|
422
493
|
examples_are_free: boolean;
|
|
423
494
|
}
|
|
424
|
-
/**
|
|
495
|
+
/**
|
|
496
|
+
* A webhook event body. For song.* events `data` has `id`, `status`, `mode`,
|
|
497
|
+
* `external_ref`, `url`, and `shot_plan_url` for "full" songs only. After
|
|
498
|
+
* `addDirection` a second `song.done` arrives with its own `id` and
|
|
499
|
+
* `data.direction_added: true`.
|
|
500
|
+
*/
|
|
425
501
|
interface WebhookEvent<T = Record<string, unknown>> {
|
|
426
502
|
/** "evt_…". Stays the same across retries of one event: dedupe on it. */
|
|
427
503
|
id: string;
|
|
@@ -500,6 +576,13 @@ interface AnalyzeOptions {
|
|
|
500
576
|
* left out, never guessed.
|
|
501
577
|
*/
|
|
502
578
|
lyrics?: string;
|
|
579
|
+
/**
|
|
580
|
+
* "full" (the API default, 25 credits) = Song DNA + video direction (story, shot plan).
|
|
581
|
+
* "dna" (10 credits) = Song DNA only: song_dna, timeline, best_moments, lyrics and
|
|
582
|
+
* scores, no story and no shot plan. Add the direction later with `addDirection`
|
|
583
|
+
* (15 credits). Left out, nothing is sent and the API uses "full". A free song covers either mode.
|
|
584
|
+
*/
|
|
585
|
+
mode?: Mode;
|
|
503
586
|
/**
|
|
504
587
|
* Test mode: free, never charged, no audio needed. The song is done right away and
|
|
505
588
|
* returns the Sugar Rush example analysis with `livemode: false`. `song.done` is
|
|
@@ -541,6 +624,14 @@ interface GetSongOptions {
|
|
|
541
624
|
/** Only these sections, e.g. ["song_dna", "shot_plan"]. */
|
|
542
625
|
include?: SectionName[] | string;
|
|
543
626
|
}
|
|
627
|
+
interface ExampleOptions extends GetSongOptions {
|
|
628
|
+
/** "dna" returns what a Song DNA-only song looks like: no story, no shot plan, a `direction` offer. */
|
|
629
|
+
mode?: Mode;
|
|
630
|
+
}
|
|
631
|
+
interface AddDirectionOptions extends WaitOptions {
|
|
632
|
+
/** Wait until the direction is there and return the full document (default true). */
|
|
633
|
+
wait?: boolean;
|
|
634
|
+
}
|
|
544
635
|
/**
|
|
545
636
|
* Client for the Songbrain API. Every method resolves to the JSON body of
|
|
546
637
|
* the response.
|
|
@@ -582,9 +673,32 @@ declare class Songbrain {
|
|
|
582
673
|
analyze(options: AnalyzeOptions): Promise<Song | SongCreated>;
|
|
583
674
|
/** Poll GET /songs/{id} until the song is done. Throws `AnalysisFailed` or `WaitTimeout`. */
|
|
584
675
|
waitFor(songId: string, options?: WaitOptions): Promise<Song>;
|
|
676
|
+
/**
|
|
677
|
+
* Add the video direction (story + shot plan) to a finished `mode: "dna"` song:
|
|
678
|
+
* `POST /songs/{id}/direction`. 15 credits (never a free song), refunded automatically
|
|
679
|
+
* if it fails. No new upload. Takes about 30-40 s; the song is "processing" meanwhile,
|
|
680
|
+
* then "done" again with `mode: "full"`. Test-mode songs (`test_…`) upgrade right away, for free.
|
|
681
|
+
*
|
|
682
|
+
* With `wait: true` (default) resolves to the full document; with `wait: false` to the
|
|
683
|
+
* 202 body `{ id, status: "processing", mode: "full", eta_sec, billing }`.
|
|
684
|
+
* Throws `AnalysisFailed` (code "direction_failed", credits refunded, the song stays "dna"),
|
|
685
|
+
* `InsufficientCredits` (402), or `SongbrainError` 409 `direction_included`, `not_done`,
|
|
686
|
+
* `song_failed`, `direction_in_progress`.
|
|
687
|
+
*/
|
|
688
|
+
addDirection(songId: string, options: AddDirectionOptions & {
|
|
689
|
+
wait: false;
|
|
690
|
+
}): Promise<DirectionCreated>;
|
|
691
|
+
addDirection(songId: string, options?: AddDirectionOptions & {
|
|
692
|
+
wait?: true;
|
|
693
|
+
}): Promise<Song>;
|
|
694
|
+
addDirection(songId: string, options?: AddDirectionOptions): Promise<Song | DirectionCreated>;
|
|
695
|
+
private poll;
|
|
585
696
|
/** Status while processing, then the full document. */
|
|
586
697
|
getSong(songId: string, options?: GetSongOptions): Promise<Song>;
|
|
587
|
-
/**
|
|
698
|
+
/**
|
|
699
|
+
* Only the story and the shot plan: `{ id, status, song, story, shot_plan }`.
|
|
700
|
+
* A "dna" song has none: 409 `no_direction` (the error body's `direction` says how to add it).
|
|
701
|
+
*/
|
|
588
702
|
shotPlan(songId: string): Promise<SongShotPlan>;
|
|
589
703
|
/** One page of your songs, newest first: `{ object: "list", data, has_more, next_cursor }`. */
|
|
590
704
|
listSongs(options?: ListSongsOptions): Promise<SongList>;
|
|
@@ -598,7 +712,7 @@ declare class Songbrain {
|
|
|
598
712
|
iterSongs(options?: IterSongsOptions): AsyncGenerator<SongListItem, void, undefined>;
|
|
599
713
|
/** Delete a song's audio and analysis now. 409 `still_processing` while it runs. */
|
|
600
714
|
deleteSong(songId: string): Promise<DeleteResult>;
|
|
601
|
-
/** Free songs left this month, credit balance and
|
|
715
|
+
/** Free songs left this month, credit balance and prices (`prices`: full, dna, add_direction). */
|
|
602
716
|
account(): Promise<Account>;
|
|
603
717
|
/** Prices and limits. No key needed. */
|
|
604
718
|
pricing(): Promise<Pricing>;
|
|
@@ -613,8 +727,11 @@ declare class Songbrain {
|
|
|
613
727
|
}): Promise<WebhookDeliveryList>;
|
|
614
728
|
/** Example analyses of Songbrain's own songs. No key needed. */
|
|
615
729
|
examples(): Promise<ExampleList>;
|
|
616
|
-
/**
|
|
617
|
-
|
|
730
|
+
/**
|
|
731
|
+
* A full example document, in the same format as `getSong`. No key needed.
|
|
732
|
+
* `mode: "dna"` returns the Song DNA view (no story, no shot plan).
|
|
733
|
+
*/
|
|
734
|
+
example(exampleId: string, options?: ExampleOptions): Promise<Song>;
|
|
618
735
|
/** An example story and shot plan, in the same format as `shotPlan`. No key needed. */
|
|
619
736
|
exampleShotPlan(exampleId: string): Promise<SongShotPlan>;
|
|
620
737
|
private backoffMs;
|
|
@@ -690,6 +807,6 @@ declare function constructWebhookEvent<T = Record<string, unknown>>(rawBody: Raw
|
|
|
690
807
|
/** Build a signature header value. Useful to test your webhook handler. */
|
|
691
808
|
declare function signWebhook(rawBody: RawBody, secret: string, timestampSec?: number): string;
|
|
692
809
|
|
|
693
|
-
declare const VERSION = "0.
|
|
810
|
+
declare const VERSION = "0.4.0";
|
|
694
811
|
|
|
695
|
-
export { type Account, type Act, AnalysisFailed, type AnalyzeOptions, AuthenticationError, type BestMoment, type Billing, type Clip, DEFAULT_BASE_URL, type DeleteResult, type ErrorInfo, type ExampleList, type ExampleSummary, type FileInput, type FullSong, type FullSongSection, type GetSongOptions, type Instrument, InsufficientCredits, type IterSongsOptions, type KeyChange, type ListSongsOptions, type LoudnessCheck, type LyricHook, type LyricLine, type Lyrics, type LyricsAlignment, NotFound, type Phases, type Pricing, type Provenance, type RateLimitInfo, RateLimited, SIGNATURE_HEADER, type Scene, type SceneKind, type ScoreBlock, type Scores, type Section, type SectionName, type ShotPlan, type ShotStyle, type Song, type SongCreated, type SongDNA, type SongInfo, type SongList, type SongListItem, type SongShotPlan, type SongStatus, Songbrain, SongbrainError, type SongbrainOptions, type SoundsLike, type Story, type StoryBeats, type StoryElement, type Timeline, VERSION, type VocalChange, type WaitOptions, WaitTimeout, type WebhookDelivery, type WebhookDeliveryList, type WebhookEvent, type WebhookTestResult, type WhatToFix, type WhatWorks, type Word, constructWebhookEvent, signWebhook, verifyWebhook };
|
|
812
|
+
export { type Account, type Act, type AddDirectionOptions, type AddDirectionPrice, AnalysisFailed, type AnalyzeOptions, AuthenticationError, type BestMoment, type Billing, type Clip, DEFAULT_BASE_URL, type DeleteResult, type DirectionCreated, type DirectionOffer, type ErrorInfo, type ExampleList, type ExampleOptions, type ExampleSummary, type FileInput, type FullSong, type FullSongSection, type GetSongOptions, type Instrument, InsufficientCredits, type IterSongsOptions, type KeyChange, type ListSongsOptions, type LoudnessCheck, type LyricHook, type LyricLine, type Lyrics, type LyricsAlignment, type Mode, type ModePrice, NotFound, type Phases, type Price, type Pricing, type Provenance, type RateLimitInfo, RateLimited, SIGNATURE_HEADER, type Scene, type SceneKind, type ScoreBlock, type Scores, type Section, type SectionName, type ShotPlan, type ShotStyle, type Song, type SongCreated, type SongDNA, type SongInfo, type SongList, type SongListItem, type SongShotPlan, type SongStatus, Songbrain, SongbrainError, type SongbrainOptions, type SoundsLike, type Story, type StoryBeats, type StoryElement, type Timeline, VERSION, type VocalChange, type WaitOptions, WaitTimeout, type WebhookDelivery, type WebhookDeliveryList, type WebhookEvent, type WebhookTestResult, type WhatToFix, type WhatWorks, type Word, constructWebhookEvent, signWebhook, verifyWebhook };
|
package/dist/index.d.ts
CHANGED
|
@@ -7,6 +7,12 @@
|
|
|
7
7
|
* otherwise (`start_in_clip`).
|
|
8
8
|
*/
|
|
9
9
|
type SongStatus = "processing" | "done" | "failed";
|
|
10
|
+
/**
|
|
11
|
+
* What a song includes. "full" (the default): Song DNA + video direction (story,
|
|
12
|
+
* shot plan), 25 credits. "dna": Song DNA only (song_dna, timeline, best_moments,
|
|
13
|
+
* lyrics, scores), 10 credits. Add the direction to a dna song later for 15 credits.
|
|
14
|
+
*/
|
|
15
|
+
type Mode = "full" | "dna";
|
|
10
16
|
/** One of the sections a song document has. Use with `include`. */
|
|
11
17
|
type SectionName = "song_dna" | "timeline" | "best_moments" | "lyrics" | "scores" | "story" | "shot_plan";
|
|
12
18
|
interface Billing {
|
|
@@ -305,9 +311,22 @@ interface ErrorInfo {
|
|
|
305
311
|
/** "req_…", also in the Songbrain-Request-Id header. */
|
|
306
312
|
request_id?: string;
|
|
307
313
|
}
|
|
314
|
+
/** On a "dna" song: how to add the video direction (story + shot plan) later. */
|
|
315
|
+
interface DirectionOffer {
|
|
316
|
+
included: false;
|
|
317
|
+
/** "POST https://api.songbrain.ai/v1/songs/{id}/direction" */
|
|
318
|
+
add: string;
|
|
319
|
+
/** 15 */
|
|
320
|
+
credits: number;
|
|
321
|
+
/** 0.3 */
|
|
322
|
+
usd: number;
|
|
323
|
+
/** ["story", "shot_plan"] */
|
|
324
|
+
adds: SectionName[];
|
|
325
|
+
}
|
|
308
326
|
/**
|
|
309
|
-
* The song document. While processing, only `id`, `status`, `progress
|
|
310
|
-
* `eta_sec` are set. With `include`, only the named sections are
|
|
327
|
+
* The song document. While processing, only `id`, `status`, `progress`,
|
|
328
|
+
* `eta_sec` and `mode` are set. With `include`, only the named sections are
|
|
329
|
+
* present. A "dna" song has no `story` and no `shot_plan`; it has `direction`.
|
|
311
330
|
*/
|
|
312
331
|
interface Song {
|
|
313
332
|
object: "song";
|
|
@@ -333,18 +352,35 @@ interface Song {
|
|
|
333
352
|
livemode?: boolean;
|
|
334
353
|
/** Measured vs. transcribed vs. model estimate vs. generated. */
|
|
335
354
|
provenance?: Provenance;
|
|
355
|
+
/** "full" or "dna" (API 1.3). */
|
|
356
|
+
mode?: Mode;
|
|
357
|
+
/** Only on "dna" songs: how to add the story and shot plan. */
|
|
358
|
+
direction?: DirectionOffer;
|
|
336
359
|
}
|
|
337
360
|
/** The 202 body of POST /songs. */
|
|
338
361
|
interface SongCreated {
|
|
339
362
|
object: "song";
|
|
340
363
|
id: string;
|
|
341
364
|
status: "processing";
|
|
365
|
+
mode?: Mode;
|
|
342
366
|
eta_sec: number;
|
|
343
367
|
billing: Billing;
|
|
344
368
|
external_ref?: string | null;
|
|
345
369
|
url: string;
|
|
346
370
|
livemode?: boolean;
|
|
347
371
|
}
|
|
372
|
+
/** The 202 body of POST /songs/{id}/direction. */
|
|
373
|
+
interface DirectionCreated {
|
|
374
|
+
object: "song";
|
|
375
|
+
id: string;
|
|
376
|
+
/** "processing"; "done" right away for a test-mode song. */
|
|
377
|
+
status: "processing" | "done";
|
|
378
|
+
mode: "full";
|
|
379
|
+
eta_sec: number;
|
|
380
|
+
billing: Billing;
|
|
381
|
+
url: string;
|
|
382
|
+
livemode?: boolean;
|
|
383
|
+
}
|
|
348
384
|
/** GET /songs/{id}/shot-plan and GET /examples/{id}/shot-plan. */
|
|
349
385
|
interface SongShotPlan {
|
|
350
386
|
id: string;
|
|
@@ -356,6 +392,7 @@ interface SongShotPlan {
|
|
|
356
392
|
interface SongListItem {
|
|
357
393
|
id: string;
|
|
358
394
|
status: string;
|
|
395
|
+
mode?: Mode;
|
|
359
396
|
external_ref: string | null;
|
|
360
397
|
created_at: string | null;
|
|
361
398
|
billing: Billing;
|
|
@@ -391,13 +428,36 @@ interface ExampleList {
|
|
|
391
428
|
object: "list";
|
|
392
429
|
data: ExampleSummary[];
|
|
393
430
|
}
|
|
431
|
+
interface Price {
|
|
432
|
+
credits: number;
|
|
433
|
+
usd: number;
|
|
434
|
+
}
|
|
435
|
+
interface ModePrice extends Price {
|
|
436
|
+
name: string;
|
|
437
|
+
/** Section names the mode returns. */
|
|
438
|
+
includes: SectionName[];
|
|
439
|
+
default?: boolean;
|
|
440
|
+
}
|
|
441
|
+
interface AddDirectionPrice extends Price {
|
|
442
|
+
/** "POST /v1/songs/{id}/direction" */
|
|
443
|
+
endpoint: string;
|
|
444
|
+
note?: string;
|
|
445
|
+
}
|
|
394
446
|
interface Account {
|
|
395
447
|
credits: number;
|
|
396
448
|
free_songs_per_month: number;
|
|
397
449
|
free_songs_used: number;
|
|
398
450
|
free_songs_left: number;
|
|
451
|
+
/** Mode "full". */
|
|
399
452
|
price_per_song_credits: number;
|
|
453
|
+
/** Mode "full". */
|
|
400
454
|
price_per_song_usd: number;
|
|
455
|
+
/** Price per mode (API 1.3). */
|
|
456
|
+
prices?: {
|
|
457
|
+
full: Price;
|
|
458
|
+
dna: Price;
|
|
459
|
+
add_direction: Price;
|
|
460
|
+
};
|
|
401
461
|
songs_this_month: number;
|
|
402
462
|
buy_credits_url: string;
|
|
403
463
|
songs_left_from_credits?: number;
|
|
@@ -410,8 +470,19 @@ interface Account {
|
|
|
410
470
|
}
|
|
411
471
|
interface Pricing {
|
|
412
472
|
free_songs_per_month: number;
|
|
473
|
+
/** "either mode" */
|
|
474
|
+
free_songs_cover?: string;
|
|
475
|
+
/** Mode "full". */
|
|
413
476
|
price_per_song_credits: number;
|
|
477
|
+
/** Mode "full". */
|
|
414
478
|
price_per_song_usd: number;
|
|
479
|
+
/** API 1.3. */
|
|
480
|
+
modes?: {
|
|
481
|
+
full: ModePrice;
|
|
482
|
+
dna: ModePrice;
|
|
483
|
+
};
|
|
484
|
+
/** API 1.3: story + shot plan for a finished dna song. */
|
|
485
|
+
add_direction?: AddDirectionPrice;
|
|
415
486
|
credit_packs: {
|
|
416
487
|
credits: number;
|
|
417
488
|
usd: number;
|
|
@@ -421,7 +492,12 @@ interface Pricing {
|
|
|
421
492
|
limits: Record<string, number>;
|
|
422
493
|
examples_are_free: boolean;
|
|
423
494
|
}
|
|
424
|
-
/**
|
|
495
|
+
/**
|
|
496
|
+
* A webhook event body. For song.* events `data` has `id`, `status`, `mode`,
|
|
497
|
+
* `external_ref`, `url`, and `shot_plan_url` for "full" songs only. After
|
|
498
|
+
* `addDirection` a second `song.done` arrives with its own `id` and
|
|
499
|
+
* `data.direction_added: true`.
|
|
500
|
+
*/
|
|
425
501
|
interface WebhookEvent<T = Record<string, unknown>> {
|
|
426
502
|
/** "evt_…". Stays the same across retries of one event: dedupe on it. */
|
|
427
503
|
id: string;
|
|
@@ -500,6 +576,13 @@ interface AnalyzeOptions {
|
|
|
500
576
|
* left out, never guessed.
|
|
501
577
|
*/
|
|
502
578
|
lyrics?: string;
|
|
579
|
+
/**
|
|
580
|
+
* "full" (the API default, 25 credits) = Song DNA + video direction (story, shot plan).
|
|
581
|
+
* "dna" (10 credits) = Song DNA only: song_dna, timeline, best_moments, lyrics and
|
|
582
|
+
* scores, no story and no shot plan. Add the direction later with `addDirection`
|
|
583
|
+
* (15 credits). Left out, nothing is sent and the API uses "full". A free song covers either mode.
|
|
584
|
+
*/
|
|
585
|
+
mode?: Mode;
|
|
503
586
|
/**
|
|
504
587
|
* Test mode: free, never charged, no audio needed. The song is done right away and
|
|
505
588
|
* returns the Sugar Rush example analysis with `livemode: false`. `song.done` is
|
|
@@ -541,6 +624,14 @@ interface GetSongOptions {
|
|
|
541
624
|
/** Only these sections, e.g. ["song_dna", "shot_plan"]. */
|
|
542
625
|
include?: SectionName[] | string;
|
|
543
626
|
}
|
|
627
|
+
interface ExampleOptions extends GetSongOptions {
|
|
628
|
+
/** "dna" returns what a Song DNA-only song looks like: no story, no shot plan, a `direction` offer. */
|
|
629
|
+
mode?: Mode;
|
|
630
|
+
}
|
|
631
|
+
interface AddDirectionOptions extends WaitOptions {
|
|
632
|
+
/** Wait until the direction is there and return the full document (default true). */
|
|
633
|
+
wait?: boolean;
|
|
634
|
+
}
|
|
544
635
|
/**
|
|
545
636
|
* Client for the Songbrain API. Every method resolves to the JSON body of
|
|
546
637
|
* the response.
|
|
@@ -582,9 +673,32 @@ declare class Songbrain {
|
|
|
582
673
|
analyze(options: AnalyzeOptions): Promise<Song | SongCreated>;
|
|
583
674
|
/** Poll GET /songs/{id} until the song is done. Throws `AnalysisFailed` or `WaitTimeout`. */
|
|
584
675
|
waitFor(songId: string, options?: WaitOptions): Promise<Song>;
|
|
676
|
+
/**
|
|
677
|
+
* Add the video direction (story + shot plan) to a finished `mode: "dna"` song:
|
|
678
|
+
* `POST /songs/{id}/direction`. 15 credits (never a free song), refunded automatically
|
|
679
|
+
* if it fails. No new upload. Takes about 30-40 s; the song is "processing" meanwhile,
|
|
680
|
+
* then "done" again with `mode: "full"`. Test-mode songs (`test_…`) upgrade right away, for free.
|
|
681
|
+
*
|
|
682
|
+
* With `wait: true` (default) resolves to the full document; with `wait: false` to the
|
|
683
|
+
* 202 body `{ id, status: "processing", mode: "full", eta_sec, billing }`.
|
|
684
|
+
* Throws `AnalysisFailed` (code "direction_failed", credits refunded, the song stays "dna"),
|
|
685
|
+
* `InsufficientCredits` (402), or `SongbrainError` 409 `direction_included`, `not_done`,
|
|
686
|
+
* `song_failed`, `direction_in_progress`.
|
|
687
|
+
*/
|
|
688
|
+
addDirection(songId: string, options: AddDirectionOptions & {
|
|
689
|
+
wait: false;
|
|
690
|
+
}): Promise<DirectionCreated>;
|
|
691
|
+
addDirection(songId: string, options?: AddDirectionOptions & {
|
|
692
|
+
wait?: true;
|
|
693
|
+
}): Promise<Song>;
|
|
694
|
+
addDirection(songId: string, options?: AddDirectionOptions): Promise<Song | DirectionCreated>;
|
|
695
|
+
private poll;
|
|
585
696
|
/** Status while processing, then the full document. */
|
|
586
697
|
getSong(songId: string, options?: GetSongOptions): Promise<Song>;
|
|
587
|
-
/**
|
|
698
|
+
/**
|
|
699
|
+
* Only the story and the shot plan: `{ id, status, song, story, shot_plan }`.
|
|
700
|
+
* A "dna" song has none: 409 `no_direction` (the error body's `direction` says how to add it).
|
|
701
|
+
*/
|
|
588
702
|
shotPlan(songId: string): Promise<SongShotPlan>;
|
|
589
703
|
/** One page of your songs, newest first: `{ object: "list", data, has_more, next_cursor }`. */
|
|
590
704
|
listSongs(options?: ListSongsOptions): Promise<SongList>;
|
|
@@ -598,7 +712,7 @@ declare class Songbrain {
|
|
|
598
712
|
iterSongs(options?: IterSongsOptions): AsyncGenerator<SongListItem, void, undefined>;
|
|
599
713
|
/** Delete a song's audio and analysis now. 409 `still_processing` while it runs. */
|
|
600
714
|
deleteSong(songId: string): Promise<DeleteResult>;
|
|
601
|
-
/** Free songs left this month, credit balance and
|
|
715
|
+
/** Free songs left this month, credit balance and prices (`prices`: full, dna, add_direction). */
|
|
602
716
|
account(): Promise<Account>;
|
|
603
717
|
/** Prices and limits. No key needed. */
|
|
604
718
|
pricing(): Promise<Pricing>;
|
|
@@ -613,8 +727,11 @@ declare class Songbrain {
|
|
|
613
727
|
}): Promise<WebhookDeliveryList>;
|
|
614
728
|
/** Example analyses of Songbrain's own songs. No key needed. */
|
|
615
729
|
examples(): Promise<ExampleList>;
|
|
616
|
-
/**
|
|
617
|
-
|
|
730
|
+
/**
|
|
731
|
+
* A full example document, in the same format as `getSong`. No key needed.
|
|
732
|
+
* `mode: "dna"` returns the Song DNA view (no story, no shot plan).
|
|
733
|
+
*/
|
|
734
|
+
example(exampleId: string, options?: ExampleOptions): Promise<Song>;
|
|
618
735
|
/** An example story and shot plan, in the same format as `shotPlan`. No key needed. */
|
|
619
736
|
exampleShotPlan(exampleId: string): Promise<SongShotPlan>;
|
|
620
737
|
private backoffMs;
|
|
@@ -690,6 +807,6 @@ declare function constructWebhookEvent<T = Record<string, unknown>>(rawBody: Raw
|
|
|
690
807
|
/** Build a signature header value. Useful to test your webhook handler. */
|
|
691
808
|
declare function signWebhook(rawBody: RawBody, secret: string, timestampSec?: number): string;
|
|
692
809
|
|
|
693
|
-
declare const VERSION = "0.
|
|
810
|
+
declare const VERSION = "0.4.0";
|
|
694
811
|
|
|
695
|
-
export { type Account, type Act, AnalysisFailed, type AnalyzeOptions, AuthenticationError, type BestMoment, type Billing, type Clip, DEFAULT_BASE_URL, type DeleteResult, type ErrorInfo, type ExampleList, type ExampleSummary, type FileInput, type FullSong, type FullSongSection, type GetSongOptions, type Instrument, InsufficientCredits, type IterSongsOptions, type KeyChange, type ListSongsOptions, type LoudnessCheck, type LyricHook, type LyricLine, type Lyrics, type LyricsAlignment, NotFound, type Phases, type Pricing, type Provenance, type RateLimitInfo, RateLimited, SIGNATURE_HEADER, type Scene, type SceneKind, type ScoreBlock, type Scores, type Section, type SectionName, type ShotPlan, type ShotStyle, type Song, type SongCreated, type SongDNA, type SongInfo, type SongList, type SongListItem, type SongShotPlan, type SongStatus, Songbrain, SongbrainError, type SongbrainOptions, type SoundsLike, type Story, type StoryBeats, type StoryElement, type Timeline, VERSION, type VocalChange, type WaitOptions, WaitTimeout, type WebhookDelivery, type WebhookDeliveryList, type WebhookEvent, type WebhookTestResult, type WhatToFix, type WhatWorks, type Word, constructWebhookEvent, signWebhook, verifyWebhook };
|
|
812
|
+
export { type Account, type Act, type AddDirectionOptions, type AddDirectionPrice, AnalysisFailed, type AnalyzeOptions, AuthenticationError, type BestMoment, type Billing, type Clip, DEFAULT_BASE_URL, type DeleteResult, type DirectionCreated, type DirectionOffer, type ErrorInfo, type ExampleList, type ExampleOptions, type ExampleSummary, type FileInput, type FullSong, type FullSongSection, type GetSongOptions, type Instrument, InsufficientCredits, type IterSongsOptions, type KeyChange, type ListSongsOptions, type LoudnessCheck, type LyricHook, type LyricLine, type Lyrics, type LyricsAlignment, type Mode, type ModePrice, NotFound, type Phases, type Price, type Pricing, type Provenance, type RateLimitInfo, RateLimited, SIGNATURE_HEADER, type Scene, type SceneKind, type ScoreBlock, type Scores, type Section, type SectionName, type ShotPlan, type ShotStyle, type Song, type SongCreated, type SongDNA, type SongInfo, type SongList, type SongListItem, type SongShotPlan, type SongStatus, Songbrain, SongbrainError, type SongbrainOptions, type SoundsLike, type Story, type StoryBeats, type StoryElement, type Timeline, VERSION, type VocalChange, type WaitOptions, WaitTimeout, type WebhookDelivery, type WebhookDeliveryList, type WebhookEvent, type WebhookTestResult, type WhatToFix, type WhatWorks, type Word, constructWebhookEvent, signWebhook, verifyWebhook };
|
package/dist/index.js
CHANGED
|
@@ -54,7 +54,7 @@ var WaitTimeout = class extends SongbrainError {
|
|
|
54
54
|
};
|
|
55
55
|
|
|
56
56
|
// src/version.ts
|
|
57
|
-
var VERSION = "0.
|
|
57
|
+
var VERSION = "0.4.0";
|
|
58
58
|
|
|
59
59
|
// src/agent.ts
|
|
60
60
|
var FLAGS = [
|
|
@@ -199,6 +199,7 @@ var Songbrain = class {
|
|
|
199
199
|
if (options.webhookUrl !== void 0) fields.webhook_url = options.webhookUrl;
|
|
200
200
|
if (options.externalRef !== void 0) fields.external_ref = options.externalRef;
|
|
201
201
|
if (options.lyrics !== void 0) fields.lyrics = options.lyrics;
|
|
202
|
+
if (options.mode !== void 0) fields.mode = options.mode;
|
|
202
203
|
const headers = { [IDEMPOTENCY_HEADER]: options.idempotencyKey || await newIdempotencyKey() };
|
|
203
204
|
let created;
|
|
204
205
|
if (file === void 0) {
|
|
@@ -225,12 +226,28 @@ var Songbrain = class {
|
|
|
225
226
|
});
|
|
226
227
|
}
|
|
227
228
|
/** Poll GET /songs/{id} until the song is done. Throws `AnalysisFailed` or `WaitTimeout`. */
|
|
228
|
-
|
|
229
|
+
waitFor(songId, options = {}) {
|
|
230
|
+
return this.poll(songId, options, false);
|
|
231
|
+
}
|
|
232
|
+
async addDirection(songId, options = {}) {
|
|
233
|
+
const created = await this.request("POST", `/songs/${encodeURIComponent(songId)}/direction`);
|
|
234
|
+
if (options.wait === false) return created;
|
|
235
|
+
return this.poll(songId, options, true);
|
|
236
|
+
}
|
|
237
|
+
async poll(songId, options, direction) {
|
|
229
238
|
const timeoutMs = options.timeoutMs ?? 3e5;
|
|
230
239
|
const interval = Math.max(500, options.pollIntervalMs ?? 5e3);
|
|
231
240
|
const deadline = Date.now() + timeoutMs;
|
|
232
241
|
for (; ; ) {
|
|
233
242
|
const doc = await this.getSong(songId);
|
|
243
|
+
if (doc.status === "done" && direction && doc.mode === "dna") {
|
|
244
|
+
throw new AnalysisFailed(
|
|
245
|
+
songId,
|
|
246
|
+
"direction_failed",
|
|
247
|
+
"The video direction could not be added. The 15 credits were refunded automatically; the Song DNA is unchanged.",
|
|
248
|
+
doc
|
|
249
|
+
);
|
|
250
|
+
}
|
|
234
251
|
if (doc.status === "done") return doc;
|
|
235
252
|
if (doc.status === "failed") {
|
|
236
253
|
throw new AnalysisFailed(
|
|
@@ -249,7 +266,10 @@ var Songbrain = class {
|
|
|
249
266
|
getSong(songId, options = {}) {
|
|
250
267
|
return this.request("GET", `/songs/${encodeURIComponent(songId)}`, { query: docQuery(options) });
|
|
251
268
|
}
|
|
252
|
-
/**
|
|
269
|
+
/**
|
|
270
|
+
* Only the story and the shot plan: `{ id, status, song, story, shot_plan }`.
|
|
271
|
+
* A "dna" song has none: 409 `no_direction` (the error body's `direction` says how to add it).
|
|
272
|
+
*/
|
|
253
273
|
shotPlan(songId) {
|
|
254
274
|
return this.request("GET", `/songs/${encodeURIComponent(songId)}/shot-plan`);
|
|
255
275
|
}
|
|
@@ -281,7 +301,7 @@ var Songbrain = class {
|
|
|
281
301
|
return this.request("DELETE", `/songs/${encodeURIComponent(songId)}`);
|
|
282
302
|
}
|
|
283
303
|
// ── account ──────────────────────────────────────────────────────────────
|
|
284
|
-
/** Free songs left this month, credit balance and
|
|
304
|
+
/** Free songs left this month, credit balance and prices (`prices`: full, dna, add_direction). */
|
|
285
305
|
account() {
|
|
286
306
|
return this.request("GET", "/account");
|
|
287
307
|
}
|
|
@@ -308,9 +328,14 @@ var Songbrain = class {
|
|
|
308
328
|
examples() {
|
|
309
329
|
return this.request("GET", "/examples");
|
|
310
330
|
}
|
|
311
|
-
/**
|
|
331
|
+
/**
|
|
332
|
+
* A full example document, in the same format as `getSong`. No key needed.
|
|
333
|
+
* `mode: "dna"` returns the Song DNA view (no story, no shot plan).
|
|
334
|
+
*/
|
|
312
335
|
example(exampleId, options = {}) {
|
|
313
|
-
return this.request("GET", `/examples/${encodeURIComponent(exampleId)}`, {
|
|
336
|
+
return this.request("GET", `/examples/${encodeURIComponent(exampleId)}`, {
|
|
337
|
+
query: { ...docQuery(options), mode: options.mode }
|
|
338
|
+
});
|
|
314
339
|
}
|
|
315
340
|
/** An example story and shot plan, in the same format as `shotPlan`. No key needed. */
|
|
316
341
|
exampleShotPlan(exampleId) {
|