songbrain 0.1.2 → 0.3.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 +51 -5
- package/dist/index.cjs +110 -19
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +152 -15
- package/dist/index.d.ts +152 -15
- package/dist/index.js +110 -19
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -124,11 +124,27 @@ interface LyricLine {
|
|
|
124
124
|
start: number;
|
|
125
125
|
end: number;
|
|
126
126
|
text: string;
|
|
127
|
+
/** 0-1 transcription confidence; null when the words were provided. */
|
|
128
|
+
confidence?: number | null;
|
|
127
129
|
/** Omitted in view=summary. */
|
|
128
130
|
words?: Word[];
|
|
129
131
|
}
|
|
132
|
+
interface LyricsAlignment {
|
|
133
|
+
/** Share of the provided words that were found in the audio. */
|
|
134
|
+
match_ratio?: number | null;
|
|
135
|
+
reference_words?: number | null;
|
|
136
|
+
corrected_words?: number | null;
|
|
137
|
+
/** false when the provided lyrics did not match the audio well enough. */
|
|
138
|
+
used?: boolean;
|
|
139
|
+
reason?: string;
|
|
140
|
+
}
|
|
130
141
|
interface Lyrics {
|
|
131
142
|
language?: string | null;
|
|
143
|
+
/** Where the words come from. */
|
|
144
|
+
source?: "transcribed" | "provided_lyrics" | "suno_lyrics";
|
|
145
|
+
basis?: "transcribed" | "provided";
|
|
146
|
+
note?: string;
|
|
147
|
+
alignment?: LyricsAlignment;
|
|
132
148
|
lines?: LyricLine[];
|
|
133
149
|
/** true for recognised commercial recordings; then `lines` is absent. */
|
|
134
150
|
hidden?: boolean;
|
|
@@ -139,6 +155,17 @@ interface ScoreBlock {
|
|
|
139
155
|
score: number;
|
|
140
156
|
breakdown: Record<string, number>;
|
|
141
157
|
note?: string;
|
|
158
|
+
/** "model_estimate": an AI model's listening judgement, not a measurement. */
|
|
159
|
+
basis?: "model_estimate";
|
|
160
|
+
}
|
|
161
|
+
/** Which fields are measured from the audio and which are a model's reading. */
|
|
162
|
+
interface Provenance {
|
|
163
|
+
measured: string[];
|
|
164
|
+
transcribed: string[];
|
|
165
|
+
model_estimate: string[];
|
|
166
|
+
generated: string[];
|
|
167
|
+
confidence_fields: string[];
|
|
168
|
+
doc: string;
|
|
142
169
|
}
|
|
143
170
|
interface WhatWorks {
|
|
144
171
|
title: string;
|
|
@@ -158,6 +185,8 @@ interface Scores {
|
|
|
158
185
|
what_works: WhatWorks[];
|
|
159
186
|
what_to_fix: WhatToFix[];
|
|
160
187
|
audience: string[];
|
|
188
|
+
basis?: "model_estimate";
|
|
189
|
+
basis_note?: string;
|
|
161
190
|
}
|
|
162
191
|
interface StoryElement {
|
|
163
192
|
/** The one object the video is about. */
|
|
@@ -273,6 +302,8 @@ interface ShotPlan {
|
|
|
273
302
|
interface ErrorInfo {
|
|
274
303
|
code: string;
|
|
275
304
|
message: string;
|
|
305
|
+
/** "req_…", also in the Songbrain-Request-Id header. */
|
|
306
|
+
request_id?: string;
|
|
276
307
|
}
|
|
277
308
|
/**
|
|
278
309
|
* The song document. While processing, only `id`, `status`, `progress` and
|
|
@@ -298,6 +329,10 @@ interface Song {
|
|
|
298
329
|
created_at?: string | null;
|
|
299
330
|
external_ref?: string | null;
|
|
300
331
|
billing?: Billing;
|
|
332
|
+
/** false for test-mode songs. */
|
|
333
|
+
livemode?: boolean;
|
|
334
|
+
/** Measured vs. transcribed vs. model estimate vs. generated. */
|
|
335
|
+
provenance?: Provenance;
|
|
301
336
|
}
|
|
302
337
|
/** The 202 body of POST /songs. */
|
|
303
338
|
interface SongCreated {
|
|
@@ -308,6 +343,7 @@ interface SongCreated {
|
|
|
308
343
|
billing: Billing;
|
|
309
344
|
external_ref?: string | null;
|
|
310
345
|
url: string;
|
|
346
|
+
livemode?: boolean;
|
|
311
347
|
}
|
|
312
348
|
/** GET /songs/{id}/shot-plan and GET /examples/{id}/shot-plan. */
|
|
313
349
|
interface SongShotPlan {
|
|
@@ -323,10 +359,14 @@ interface SongListItem {
|
|
|
323
359
|
external_ref: string | null;
|
|
324
360
|
created_at: string | null;
|
|
325
361
|
billing: Billing;
|
|
362
|
+
livemode?: boolean;
|
|
326
363
|
}
|
|
327
364
|
interface SongList {
|
|
328
365
|
object: "list";
|
|
329
366
|
data: SongListItem[];
|
|
367
|
+
has_more?: boolean;
|
|
368
|
+
/** Pass as `startingAfter` for the next page. */
|
|
369
|
+
next_cursor?: string | null;
|
|
330
370
|
}
|
|
331
371
|
interface DeleteResult {
|
|
332
372
|
id: string;
|
|
@@ -383,11 +423,44 @@ interface Pricing {
|
|
|
383
423
|
}
|
|
384
424
|
/** A webhook event body. */
|
|
385
425
|
interface WebhookEvent<T = Record<string, unknown>> {
|
|
386
|
-
|
|
426
|
+
/** "evt_…". Stays the same across retries of one event: dedupe on it. */
|
|
427
|
+
id: string;
|
|
428
|
+
type: "song.done" | "song.failed" | "account.low_balance" | "ping" | (string & {});
|
|
387
429
|
/** Unix seconds. */
|
|
388
430
|
created: number;
|
|
431
|
+
livemode: boolean;
|
|
389
432
|
data: T;
|
|
390
433
|
}
|
|
434
|
+
/** From the X-RateLimit-* headers. See `Songbrain.lastRateLimit`. */
|
|
435
|
+
interface RateLimitInfo {
|
|
436
|
+
/** Requests per minute. */
|
|
437
|
+
limit: number;
|
|
438
|
+
remaining: number | null;
|
|
439
|
+
/** Seconds until the window has room again. */
|
|
440
|
+
reset: number | null;
|
|
441
|
+
}
|
|
442
|
+
/** POST /webhooks/test. */
|
|
443
|
+
interface WebhookTestResult {
|
|
444
|
+
delivered: boolean;
|
|
445
|
+
status_code: number | null;
|
|
446
|
+
latency_ms: number;
|
|
447
|
+
event_id: string;
|
|
448
|
+
}
|
|
449
|
+
interface WebhookDelivery {
|
|
450
|
+
event_id: string;
|
|
451
|
+
type: WebhookEvent["type"];
|
|
452
|
+
song_id: string | null;
|
|
453
|
+
url: string;
|
|
454
|
+
attempt: number;
|
|
455
|
+
status_code: number | null;
|
|
456
|
+
delivered: boolean;
|
|
457
|
+
latency_ms: number | null;
|
|
458
|
+
created_at: string;
|
|
459
|
+
}
|
|
460
|
+
interface WebhookDeliveryList {
|
|
461
|
+
object: "list";
|
|
462
|
+
data: WebhookDelivery[];
|
|
463
|
+
}
|
|
391
464
|
|
|
392
465
|
declare const DEFAULT_BASE_URL = "https://api.songbrain.ai/v1";
|
|
393
466
|
/** A Blob/File, a Buffer or bytes, or a local file path (Node). */
|
|
@@ -399,7 +472,10 @@ interface SongbrainOptions {
|
|
|
399
472
|
baseUrl?: string;
|
|
400
473
|
/** Timeout for each HTTP request in ms (uploads included). Default 60 000. */
|
|
401
474
|
timeoutMs?: number;
|
|
402
|
-
/**
|
|
475
|
+
/**
|
|
476
|
+
* How often to retry network errors, 429 and 5xx responses, with backoff. Default 3.
|
|
477
|
+
* Song creation is retried too, because every create sends an `Idempotency-Key`.
|
|
478
|
+
*/
|
|
403
479
|
maxRetries?: number;
|
|
404
480
|
/** A custom fetch implementation. Defaults to the global fetch. */
|
|
405
481
|
fetch?: typeof fetch;
|
|
@@ -417,6 +493,25 @@ interface AnalyzeOptions {
|
|
|
417
493
|
externalRef?: string;
|
|
418
494
|
/** File name for an upload. Its extension must match the audio format. Taken from the path or File name, or guessed from the bytes. */
|
|
419
495
|
filename?: string;
|
|
496
|
+
/**
|
|
497
|
+
* The song's lyrics as plain text (up to 20,000 characters), e.g. from Suno. The
|
|
498
|
+
* analysis then uses your exact words on the transcription's timing
|
|
499
|
+
* (`lyrics.source` = "provided_lyrics"); words the singer can't be heard on are
|
|
500
|
+
* left out, never guessed.
|
|
501
|
+
*/
|
|
502
|
+
lyrics?: string;
|
|
503
|
+
/**
|
|
504
|
+
* Test mode: free, never charged, no audio needed. The song is done right away and
|
|
505
|
+
* returns the Sugar Rush example analysis with `livemode: false`. `song.done` is
|
|
506
|
+
* still sent to `webhookUrl`. Made for CI and integration tests.
|
|
507
|
+
*/
|
|
508
|
+
test?: boolean;
|
|
509
|
+
/**
|
|
510
|
+
* Sent as `Idempotency-Key`. By default a random UUID per call, reused across the
|
|
511
|
+
* client's own retries, so a retried create never makes a second song. Pass your
|
|
512
|
+
* own (e.g. your job id) to make retries across processes safe too (24 h window).
|
|
513
|
+
*/
|
|
514
|
+
idempotencyKey?: string;
|
|
420
515
|
/** Wait until the song is done and return the full document (default true). */
|
|
421
516
|
wait?: boolean;
|
|
422
517
|
/** Time between status checks while waiting. Default 5 000. */
|
|
@@ -428,6 +523,18 @@ interface WaitOptions {
|
|
|
428
523
|
pollIntervalMs?: number;
|
|
429
524
|
timeoutMs?: number;
|
|
430
525
|
}
|
|
526
|
+
interface ListSongsOptions {
|
|
527
|
+
/** Page size, 1-100. Default 20. */
|
|
528
|
+
limit?: number;
|
|
529
|
+
/** A song id, usually the previous page's `next_cursor`. Returns the songs after it. */
|
|
530
|
+
startingAfter?: string;
|
|
531
|
+
}
|
|
532
|
+
interface IterSongsOptions {
|
|
533
|
+
/** Songs per request, 1-100. Default 100. */
|
|
534
|
+
pageSize?: number;
|
|
535
|
+
/** Start after this song id. */
|
|
536
|
+
startingAfter?: string;
|
|
537
|
+
}
|
|
431
538
|
interface GetSongOptions {
|
|
432
539
|
/** "summary" drops word timings and beat arrays (about 3x smaller). */
|
|
433
540
|
view?: "full" | "summary";
|
|
@@ -450,11 +557,19 @@ declare class Songbrain {
|
|
|
450
557
|
readonly timeoutMs: number;
|
|
451
558
|
readonly maxRetries: number;
|
|
452
559
|
private readonly fetchImpl;
|
|
560
|
+
/**
|
|
561
|
+
* `{ limit, remaining, reset }` from the `X-RateLimit-*` headers of the last response
|
|
562
|
+
* that had them (null before that). `reset` is seconds until the window has room.
|
|
563
|
+
*/
|
|
564
|
+
lastRateLimit: RateLimitInfo | null;
|
|
565
|
+
/** The `Songbrain-Request-Id` of the last response (null before the first one). */
|
|
566
|
+
lastRequestId: string | null;
|
|
453
567
|
/** @internal Overridable in tests. */
|
|
454
568
|
_sleep: (ms: number) => Promise<void>;
|
|
455
569
|
constructor(options?: SongbrainOptions);
|
|
456
570
|
/**
|
|
457
|
-
* Analyse a song from a file or a public URL. Pass exactly one of `file` or `audioUrl
|
|
571
|
+
* Analyse a song from a file or a public URL. Pass exactly one of `file` or `audioUrl`
|
|
572
|
+
* (or neither with `test: true`).
|
|
458
573
|
* Typically 60-90 s. With `wait: true` (default) resolves to the full document;
|
|
459
574
|
* with `wait: false` to the 202 body `{ id, status: "processing", eta_sec, billing }`.
|
|
460
575
|
*/
|
|
@@ -471,16 +586,31 @@ declare class Songbrain {
|
|
|
471
586
|
getSong(songId: string, options?: GetSongOptions): Promise<Song>;
|
|
472
587
|
/** Only the story and the shot plan: `{ id, status, song, story, shot_plan }`. */
|
|
473
588
|
shotPlan(songId: string): Promise<SongShotPlan>;
|
|
474
|
-
/**
|
|
475
|
-
listSongs(options?:
|
|
476
|
-
|
|
477
|
-
|
|
589
|
+
/** One page of your songs, newest first: `{ object: "list", data, has_more, next_cursor }`. */
|
|
590
|
+
listSongs(options?: ListSongsOptions): Promise<SongList>;
|
|
591
|
+
/**
|
|
592
|
+
* All your songs, newest first, fetching pages as needed.
|
|
593
|
+
*
|
|
594
|
+
* ```ts
|
|
595
|
+
* for await (const item of sb.iterSongs()) console.log(item.id, item.status);
|
|
596
|
+
* ```
|
|
597
|
+
*/
|
|
598
|
+
iterSongs(options?: IterSongsOptions): AsyncGenerator<SongListItem, void, undefined>;
|
|
478
599
|
/** Delete a song's audio and analysis now. 409 `still_processing` while it runs. */
|
|
479
600
|
deleteSong(songId: string): Promise<DeleteResult>;
|
|
480
601
|
/** Free songs left this month, credit balance and price per song. */
|
|
481
602
|
account(): Promise<Account>;
|
|
482
603
|
/** Prices and limits. No key needed. */
|
|
483
604
|
pricing(): Promise<Pricing>;
|
|
605
|
+
/**
|
|
606
|
+
* Send a signed `ping` event to `url` right now:
|
|
607
|
+
* `{ delivered, status_code, latency_ms, event_id }`. Checks your receiver before real songs.
|
|
608
|
+
*/
|
|
609
|
+
testWebhook(url: string): Promise<WebhookTestResult>;
|
|
610
|
+
/** The last webhook delivery attempts for your account, newest first. */
|
|
611
|
+
webhookDeliveries(options?: {
|
|
612
|
+
limit?: number;
|
|
613
|
+
}): Promise<WebhookDeliveryList>;
|
|
484
614
|
/** Example analyses of Songbrain's own songs. No key needed. */
|
|
485
615
|
examples(): Promise<ExampleList>;
|
|
486
616
|
/** A full example document, in the same format as `getSong`. No key needed. */
|
|
@@ -492,9 +622,10 @@ declare class Songbrain {
|
|
|
492
622
|
}
|
|
493
623
|
|
|
494
624
|
/**
|
|
495
|
-
* Every API error has the shape `{ error: { code, message } }`.
|
|
496
|
-
* turns it into a `SongbrainError` (or a subclass) with `status`,
|
|
497
|
-
* `message`.
|
|
625
|
+
* Every API error has the shape `{ error: { code, message, request_id } }`.
|
|
626
|
+
* The client turns it into a `SongbrainError` (or a subclass) with `status`,
|
|
627
|
+
* `code`, `message` and `requestId`. The message ends with
|
|
628
|
+
* ` (request_id: req_…)` when there is one; quote it when you contact support.
|
|
498
629
|
*/
|
|
499
630
|
declare class SongbrainError extends Error {
|
|
500
631
|
/** HTTP status, or 0 when the error did not come from an HTTP response. */
|
|
@@ -503,7 +634,9 @@ declare class SongbrainError extends Error {
|
|
|
503
634
|
readonly code: string;
|
|
504
635
|
/** The parsed response body, when there was one. */
|
|
505
636
|
readonly body: unknown;
|
|
506
|
-
|
|
637
|
+
/** The `Songbrain-Request-Id` of the failed request (`req_…`), or null. */
|
|
638
|
+
readonly requestId: string | null;
|
|
639
|
+
constructor(status: number, code: string, message: string, body?: unknown, requestId?: string | null);
|
|
507
640
|
}
|
|
508
641
|
/** 401: the API key is missing, invalid or revoked. */
|
|
509
642
|
declare class AuthenticationError extends SongbrainError {
|
|
@@ -518,7 +651,7 @@ declare class NotFound extends SongbrainError {
|
|
|
518
651
|
declare class RateLimited extends SongbrainError {
|
|
519
652
|
/** Seconds to wait, from the Retry-After header (null if absent). */
|
|
520
653
|
readonly retryAfter: number | null;
|
|
521
|
-
constructor(status: number, code: string, message: string, body?: unknown, retryAfter?: number | null);
|
|
654
|
+
constructor(status: number, code: string, message: string, body?: unknown, retryAfter?: number | null, requestId?: string | null);
|
|
522
655
|
}
|
|
523
656
|
/** The song was accepted but its analysis failed. Paid credits are refunded automatically. */
|
|
524
657
|
declare class AnalysisFailed extends SongbrainError {
|
|
@@ -546,13 +679,17 @@ type RawBody = string | Uint8Array | ArrayBuffer;
|
|
|
546
679
|
declare function verifyWebhook(rawBody: RawBody, header: string | null | undefined, secret: string, toleranceSec?: number): boolean;
|
|
547
680
|
/**
|
|
548
681
|
* Verify the signature and return the parsed event:
|
|
549
|
-
* `{ type: "song.done" | "song.failed" | "account.low_balance", created, data }`.
|
|
682
|
+
* `{ id, type: "song.done" | "song.failed" | "account.low_balance" | "ping", created, livemode, data }`.
|
|
550
683
|
* Throws if the signature is not valid.
|
|
684
|
+
*
|
|
685
|
+
* `id` (`evt_…`, also the `Songbrain-Event-Id` header) stays the same when
|
|
686
|
+
* Songbrain retries an event (up to 10 attempts over about 3 days): store the
|
|
687
|
+
* ids you have handled and skip repeats.
|
|
551
688
|
*/
|
|
552
689
|
declare function constructWebhookEvent<T = Record<string, unknown>>(rawBody: RawBody, header: string | null | undefined, secret: string, toleranceSec?: number): WebhookEvent<T>;
|
|
553
690
|
/** Build a signature header value. Useful to test your webhook handler. */
|
|
554
691
|
declare function signWebhook(rawBody: RawBody, secret: string, timestampSec?: number): string;
|
|
555
692
|
|
|
556
|
-
declare const VERSION = "0.
|
|
693
|
+
declare const VERSION = "0.3.0";
|
|
557
694
|
|
|
558
|
-
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 KeyChange, type LoudnessCheck, type LyricHook, type LyricLine, type Lyrics, NotFound, type Phases, type Pricing, 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 WebhookEvent, type WhatToFix, type WhatWorks, type Word, constructWebhookEvent, signWebhook, verifyWebhook };
|
|
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 };
|
package/dist/index.d.ts
CHANGED
|
@@ -124,11 +124,27 @@ interface LyricLine {
|
|
|
124
124
|
start: number;
|
|
125
125
|
end: number;
|
|
126
126
|
text: string;
|
|
127
|
+
/** 0-1 transcription confidence; null when the words were provided. */
|
|
128
|
+
confidence?: number | null;
|
|
127
129
|
/** Omitted in view=summary. */
|
|
128
130
|
words?: Word[];
|
|
129
131
|
}
|
|
132
|
+
interface LyricsAlignment {
|
|
133
|
+
/** Share of the provided words that were found in the audio. */
|
|
134
|
+
match_ratio?: number | null;
|
|
135
|
+
reference_words?: number | null;
|
|
136
|
+
corrected_words?: number | null;
|
|
137
|
+
/** false when the provided lyrics did not match the audio well enough. */
|
|
138
|
+
used?: boolean;
|
|
139
|
+
reason?: string;
|
|
140
|
+
}
|
|
130
141
|
interface Lyrics {
|
|
131
142
|
language?: string | null;
|
|
143
|
+
/** Where the words come from. */
|
|
144
|
+
source?: "transcribed" | "provided_lyrics" | "suno_lyrics";
|
|
145
|
+
basis?: "transcribed" | "provided";
|
|
146
|
+
note?: string;
|
|
147
|
+
alignment?: LyricsAlignment;
|
|
132
148
|
lines?: LyricLine[];
|
|
133
149
|
/** true for recognised commercial recordings; then `lines` is absent. */
|
|
134
150
|
hidden?: boolean;
|
|
@@ -139,6 +155,17 @@ interface ScoreBlock {
|
|
|
139
155
|
score: number;
|
|
140
156
|
breakdown: Record<string, number>;
|
|
141
157
|
note?: string;
|
|
158
|
+
/** "model_estimate": an AI model's listening judgement, not a measurement. */
|
|
159
|
+
basis?: "model_estimate";
|
|
160
|
+
}
|
|
161
|
+
/** Which fields are measured from the audio and which are a model's reading. */
|
|
162
|
+
interface Provenance {
|
|
163
|
+
measured: string[];
|
|
164
|
+
transcribed: string[];
|
|
165
|
+
model_estimate: string[];
|
|
166
|
+
generated: string[];
|
|
167
|
+
confidence_fields: string[];
|
|
168
|
+
doc: string;
|
|
142
169
|
}
|
|
143
170
|
interface WhatWorks {
|
|
144
171
|
title: string;
|
|
@@ -158,6 +185,8 @@ interface Scores {
|
|
|
158
185
|
what_works: WhatWorks[];
|
|
159
186
|
what_to_fix: WhatToFix[];
|
|
160
187
|
audience: string[];
|
|
188
|
+
basis?: "model_estimate";
|
|
189
|
+
basis_note?: string;
|
|
161
190
|
}
|
|
162
191
|
interface StoryElement {
|
|
163
192
|
/** The one object the video is about. */
|
|
@@ -273,6 +302,8 @@ interface ShotPlan {
|
|
|
273
302
|
interface ErrorInfo {
|
|
274
303
|
code: string;
|
|
275
304
|
message: string;
|
|
305
|
+
/** "req_…", also in the Songbrain-Request-Id header. */
|
|
306
|
+
request_id?: string;
|
|
276
307
|
}
|
|
277
308
|
/**
|
|
278
309
|
* The song document. While processing, only `id`, `status`, `progress` and
|
|
@@ -298,6 +329,10 @@ interface Song {
|
|
|
298
329
|
created_at?: string | null;
|
|
299
330
|
external_ref?: string | null;
|
|
300
331
|
billing?: Billing;
|
|
332
|
+
/** false for test-mode songs. */
|
|
333
|
+
livemode?: boolean;
|
|
334
|
+
/** Measured vs. transcribed vs. model estimate vs. generated. */
|
|
335
|
+
provenance?: Provenance;
|
|
301
336
|
}
|
|
302
337
|
/** The 202 body of POST /songs. */
|
|
303
338
|
interface SongCreated {
|
|
@@ -308,6 +343,7 @@ interface SongCreated {
|
|
|
308
343
|
billing: Billing;
|
|
309
344
|
external_ref?: string | null;
|
|
310
345
|
url: string;
|
|
346
|
+
livemode?: boolean;
|
|
311
347
|
}
|
|
312
348
|
/** GET /songs/{id}/shot-plan and GET /examples/{id}/shot-plan. */
|
|
313
349
|
interface SongShotPlan {
|
|
@@ -323,10 +359,14 @@ interface SongListItem {
|
|
|
323
359
|
external_ref: string | null;
|
|
324
360
|
created_at: string | null;
|
|
325
361
|
billing: Billing;
|
|
362
|
+
livemode?: boolean;
|
|
326
363
|
}
|
|
327
364
|
interface SongList {
|
|
328
365
|
object: "list";
|
|
329
366
|
data: SongListItem[];
|
|
367
|
+
has_more?: boolean;
|
|
368
|
+
/** Pass as `startingAfter` for the next page. */
|
|
369
|
+
next_cursor?: string | null;
|
|
330
370
|
}
|
|
331
371
|
interface DeleteResult {
|
|
332
372
|
id: string;
|
|
@@ -383,11 +423,44 @@ interface Pricing {
|
|
|
383
423
|
}
|
|
384
424
|
/** A webhook event body. */
|
|
385
425
|
interface WebhookEvent<T = Record<string, unknown>> {
|
|
386
|
-
|
|
426
|
+
/** "evt_…". Stays the same across retries of one event: dedupe on it. */
|
|
427
|
+
id: string;
|
|
428
|
+
type: "song.done" | "song.failed" | "account.low_balance" | "ping" | (string & {});
|
|
387
429
|
/** Unix seconds. */
|
|
388
430
|
created: number;
|
|
431
|
+
livemode: boolean;
|
|
389
432
|
data: T;
|
|
390
433
|
}
|
|
434
|
+
/** From the X-RateLimit-* headers. See `Songbrain.lastRateLimit`. */
|
|
435
|
+
interface RateLimitInfo {
|
|
436
|
+
/** Requests per minute. */
|
|
437
|
+
limit: number;
|
|
438
|
+
remaining: number | null;
|
|
439
|
+
/** Seconds until the window has room again. */
|
|
440
|
+
reset: number | null;
|
|
441
|
+
}
|
|
442
|
+
/** POST /webhooks/test. */
|
|
443
|
+
interface WebhookTestResult {
|
|
444
|
+
delivered: boolean;
|
|
445
|
+
status_code: number | null;
|
|
446
|
+
latency_ms: number;
|
|
447
|
+
event_id: string;
|
|
448
|
+
}
|
|
449
|
+
interface WebhookDelivery {
|
|
450
|
+
event_id: string;
|
|
451
|
+
type: WebhookEvent["type"];
|
|
452
|
+
song_id: string | null;
|
|
453
|
+
url: string;
|
|
454
|
+
attempt: number;
|
|
455
|
+
status_code: number | null;
|
|
456
|
+
delivered: boolean;
|
|
457
|
+
latency_ms: number | null;
|
|
458
|
+
created_at: string;
|
|
459
|
+
}
|
|
460
|
+
interface WebhookDeliveryList {
|
|
461
|
+
object: "list";
|
|
462
|
+
data: WebhookDelivery[];
|
|
463
|
+
}
|
|
391
464
|
|
|
392
465
|
declare const DEFAULT_BASE_URL = "https://api.songbrain.ai/v1";
|
|
393
466
|
/** A Blob/File, a Buffer or bytes, or a local file path (Node). */
|
|
@@ -399,7 +472,10 @@ interface SongbrainOptions {
|
|
|
399
472
|
baseUrl?: string;
|
|
400
473
|
/** Timeout for each HTTP request in ms (uploads included). Default 60 000. */
|
|
401
474
|
timeoutMs?: number;
|
|
402
|
-
/**
|
|
475
|
+
/**
|
|
476
|
+
* How often to retry network errors, 429 and 5xx responses, with backoff. Default 3.
|
|
477
|
+
* Song creation is retried too, because every create sends an `Idempotency-Key`.
|
|
478
|
+
*/
|
|
403
479
|
maxRetries?: number;
|
|
404
480
|
/** A custom fetch implementation. Defaults to the global fetch. */
|
|
405
481
|
fetch?: typeof fetch;
|
|
@@ -417,6 +493,25 @@ interface AnalyzeOptions {
|
|
|
417
493
|
externalRef?: string;
|
|
418
494
|
/** File name for an upload. Its extension must match the audio format. Taken from the path or File name, or guessed from the bytes. */
|
|
419
495
|
filename?: string;
|
|
496
|
+
/**
|
|
497
|
+
* The song's lyrics as plain text (up to 20,000 characters), e.g. from Suno. The
|
|
498
|
+
* analysis then uses your exact words on the transcription's timing
|
|
499
|
+
* (`lyrics.source` = "provided_lyrics"); words the singer can't be heard on are
|
|
500
|
+
* left out, never guessed.
|
|
501
|
+
*/
|
|
502
|
+
lyrics?: string;
|
|
503
|
+
/**
|
|
504
|
+
* Test mode: free, never charged, no audio needed. The song is done right away and
|
|
505
|
+
* returns the Sugar Rush example analysis with `livemode: false`. `song.done` is
|
|
506
|
+
* still sent to `webhookUrl`. Made for CI and integration tests.
|
|
507
|
+
*/
|
|
508
|
+
test?: boolean;
|
|
509
|
+
/**
|
|
510
|
+
* Sent as `Idempotency-Key`. By default a random UUID per call, reused across the
|
|
511
|
+
* client's own retries, so a retried create never makes a second song. Pass your
|
|
512
|
+
* own (e.g. your job id) to make retries across processes safe too (24 h window).
|
|
513
|
+
*/
|
|
514
|
+
idempotencyKey?: string;
|
|
420
515
|
/** Wait until the song is done and return the full document (default true). */
|
|
421
516
|
wait?: boolean;
|
|
422
517
|
/** Time between status checks while waiting. Default 5 000. */
|
|
@@ -428,6 +523,18 @@ interface WaitOptions {
|
|
|
428
523
|
pollIntervalMs?: number;
|
|
429
524
|
timeoutMs?: number;
|
|
430
525
|
}
|
|
526
|
+
interface ListSongsOptions {
|
|
527
|
+
/** Page size, 1-100. Default 20. */
|
|
528
|
+
limit?: number;
|
|
529
|
+
/** A song id, usually the previous page's `next_cursor`. Returns the songs after it. */
|
|
530
|
+
startingAfter?: string;
|
|
531
|
+
}
|
|
532
|
+
interface IterSongsOptions {
|
|
533
|
+
/** Songs per request, 1-100. Default 100. */
|
|
534
|
+
pageSize?: number;
|
|
535
|
+
/** Start after this song id. */
|
|
536
|
+
startingAfter?: string;
|
|
537
|
+
}
|
|
431
538
|
interface GetSongOptions {
|
|
432
539
|
/** "summary" drops word timings and beat arrays (about 3x smaller). */
|
|
433
540
|
view?: "full" | "summary";
|
|
@@ -450,11 +557,19 @@ declare class Songbrain {
|
|
|
450
557
|
readonly timeoutMs: number;
|
|
451
558
|
readonly maxRetries: number;
|
|
452
559
|
private readonly fetchImpl;
|
|
560
|
+
/**
|
|
561
|
+
* `{ limit, remaining, reset }` from the `X-RateLimit-*` headers of the last response
|
|
562
|
+
* that had them (null before that). `reset` is seconds until the window has room.
|
|
563
|
+
*/
|
|
564
|
+
lastRateLimit: RateLimitInfo | null;
|
|
565
|
+
/** The `Songbrain-Request-Id` of the last response (null before the first one). */
|
|
566
|
+
lastRequestId: string | null;
|
|
453
567
|
/** @internal Overridable in tests. */
|
|
454
568
|
_sleep: (ms: number) => Promise<void>;
|
|
455
569
|
constructor(options?: SongbrainOptions);
|
|
456
570
|
/**
|
|
457
|
-
* Analyse a song from a file or a public URL. Pass exactly one of `file` or `audioUrl
|
|
571
|
+
* Analyse a song from a file or a public URL. Pass exactly one of `file` or `audioUrl`
|
|
572
|
+
* (or neither with `test: true`).
|
|
458
573
|
* Typically 60-90 s. With `wait: true` (default) resolves to the full document;
|
|
459
574
|
* with `wait: false` to the 202 body `{ id, status: "processing", eta_sec, billing }`.
|
|
460
575
|
*/
|
|
@@ -471,16 +586,31 @@ declare class Songbrain {
|
|
|
471
586
|
getSong(songId: string, options?: GetSongOptions): Promise<Song>;
|
|
472
587
|
/** Only the story and the shot plan: `{ id, status, song, story, shot_plan }`. */
|
|
473
588
|
shotPlan(songId: string): Promise<SongShotPlan>;
|
|
474
|
-
/**
|
|
475
|
-
listSongs(options?:
|
|
476
|
-
|
|
477
|
-
|
|
589
|
+
/** One page of your songs, newest first: `{ object: "list", data, has_more, next_cursor }`. */
|
|
590
|
+
listSongs(options?: ListSongsOptions): Promise<SongList>;
|
|
591
|
+
/**
|
|
592
|
+
* All your songs, newest first, fetching pages as needed.
|
|
593
|
+
*
|
|
594
|
+
* ```ts
|
|
595
|
+
* for await (const item of sb.iterSongs()) console.log(item.id, item.status);
|
|
596
|
+
* ```
|
|
597
|
+
*/
|
|
598
|
+
iterSongs(options?: IterSongsOptions): AsyncGenerator<SongListItem, void, undefined>;
|
|
478
599
|
/** Delete a song's audio and analysis now. 409 `still_processing` while it runs. */
|
|
479
600
|
deleteSong(songId: string): Promise<DeleteResult>;
|
|
480
601
|
/** Free songs left this month, credit balance and price per song. */
|
|
481
602
|
account(): Promise<Account>;
|
|
482
603
|
/** Prices and limits. No key needed. */
|
|
483
604
|
pricing(): Promise<Pricing>;
|
|
605
|
+
/**
|
|
606
|
+
* Send a signed `ping` event to `url` right now:
|
|
607
|
+
* `{ delivered, status_code, latency_ms, event_id }`. Checks your receiver before real songs.
|
|
608
|
+
*/
|
|
609
|
+
testWebhook(url: string): Promise<WebhookTestResult>;
|
|
610
|
+
/** The last webhook delivery attempts for your account, newest first. */
|
|
611
|
+
webhookDeliveries(options?: {
|
|
612
|
+
limit?: number;
|
|
613
|
+
}): Promise<WebhookDeliveryList>;
|
|
484
614
|
/** Example analyses of Songbrain's own songs. No key needed. */
|
|
485
615
|
examples(): Promise<ExampleList>;
|
|
486
616
|
/** A full example document, in the same format as `getSong`. No key needed. */
|
|
@@ -492,9 +622,10 @@ declare class Songbrain {
|
|
|
492
622
|
}
|
|
493
623
|
|
|
494
624
|
/**
|
|
495
|
-
* Every API error has the shape `{ error: { code, message } }`.
|
|
496
|
-
* turns it into a `SongbrainError` (or a subclass) with `status`,
|
|
497
|
-
* `message`.
|
|
625
|
+
* Every API error has the shape `{ error: { code, message, request_id } }`.
|
|
626
|
+
* The client turns it into a `SongbrainError` (or a subclass) with `status`,
|
|
627
|
+
* `code`, `message` and `requestId`. The message ends with
|
|
628
|
+
* ` (request_id: req_…)` when there is one; quote it when you contact support.
|
|
498
629
|
*/
|
|
499
630
|
declare class SongbrainError extends Error {
|
|
500
631
|
/** HTTP status, or 0 when the error did not come from an HTTP response. */
|
|
@@ -503,7 +634,9 @@ declare class SongbrainError extends Error {
|
|
|
503
634
|
readonly code: string;
|
|
504
635
|
/** The parsed response body, when there was one. */
|
|
505
636
|
readonly body: unknown;
|
|
506
|
-
|
|
637
|
+
/** The `Songbrain-Request-Id` of the failed request (`req_…`), or null. */
|
|
638
|
+
readonly requestId: string | null;
|
|
639
|
+
constructor(status: number, code: string, message: string, body?: unknown, requestId?: string | null);
|
|
507
640
|
}
|
|
508
641
|
/** 401: the API key is missing, invalid or revoked. */
|
|
509
642
|
declare class AuthenticationError extends SongbrainError {
|
|
@@ -518,7 +651,7 @@ declare class NotFound extends SongbrainError {
|
|
|
518
651
|
declare class RateLimited extends SongbrainError {
|
|
519
652
|
/** Seconds to wait, from the Retry-After header (null if absent). */
|
|
520
653
|
readonly retryAfter: number | null;
|
|
521
|
-
constructor(status: number, code: string, message: string, body?: unknown, retryAfter?: number | null);
|
|
654
|
+
constructor(status: number, code: string, message: string, body?: unknown, retryAfter?: number | null, requestId?: string | null);
|
|
522
655
|
}
|
|
523
656
|
/** The song was accepted but its analysis failed. Paid credits are refunded automatically. */
|
|
524
657
|
declare class AnalysisFailed extends SongbrainError {
|
|
@@ -546,13 +679,17 @@ type RawBody = string | Uint8Array | ArrayBuffer;
|
|
|
546
679
|
declare function verifyWebhook(rawBody: RawBody, header: string | null | undefined, secret: string, toleranceSec?: number): boolean;
|
|
547
680
|
/**
|
|
548
681
|
* Verify the signature and return the parsed event:
|
|
549
|
-
* `{ type: "song.done" | "song.failed" | "account.low_balance", created, data }`.
|
|
682
|
+
* `{ id, type: "song.done" | "song.failed" | "account.low_balance" | "ping", created, livemode, data }`.
|
|
550
683
|
* Throws if the signature is not valid.
|
|
684
|
+
*
|
|
685
|
+
* `id` (`evt_…`, also the `Songbrain-Event-Id` header) stays the same when
|
|
686
|
+
* Songbrain retries an event (up to 10 attempts over about 3 days): store the
|
|
687
|
+
* ids you have handled and skip repeats.
|
|
551
688
|
*/
|
|
552
689
|
declare function constructWebhookEvent<T = Record<string, unknown>>(rawBody: RawBody, header: string | null | undefined, secret: string, toleranceSec?: number): WebhookEvent<T>;
|
|
553
690
|
/** Build a signature header value. Useful to test your webhook handler. */
|
|
554
691
|
declare function signWebhook(rawBody: RawBody, secret: string, timestampSec?: number): string;
|
|
555
692
|
|
|
556
|
-
declare const VERSION = "0.
|
|
693
|
+
declare const VERSION = "0.3.0";
|
|
557
694
|
|
|
558
|
-
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 KeyChange, type LoudnessCheck, type LyricHook, type LyricLine, type Lyrics, NotFound, type Phases, type Pricing, 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 WebhookEvent, type WhatToFix, type WhatWorks, type Word, constructWebhookEvent, signWebhook, verifyWebhook };
|
|
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 };
|