@omelhorsite/sdk 0.4.1 → 0.4.2
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.js
CHANGED
|
@@ -12560,11 +12560,9 @@ function songImportProgress(record) {
|
|
|
12560
12560
|
|
|
12561
12561
|
class MusicImportsNamespace extends Resource {
|
|
12562
12562
|
spotify;
|
|
12563
|
-
srMachine;
|
|
12564
12563
|
constructor(http) {
|
|
12565
12564
|
super(http);
|
|
12566
12565
|
this.spotify = new SpotifySyncNamespace(http);
|
|
12567
|
-
this.srMachine = new SRMachineNamespace(http);
|
|
12568
12566
|
}
|
|
12569
12567
|
async list(params = {}, options = {}) {
|
|
12570
12568
|
const base = {
|
|
@@ -12658,48 +12656,6 @@ class SpotifySyncNamespace extends Resource {
|
|
|
12658
12656
|
};
|
|
12659
12657
|
}
|
|
12660
12658
|
}
|
|
12661
|
-
|
|
12662
|
-
class SRMachineNamespace extends Resource {
|
|
12663
|
-
async metadata(url, options = {}) {
|
|
12664
|
-
return this.http.get("/s_r_machine/metadata", {
|
|
12665
|
-
timeoutMs: 120000,
|
|
12666
|
-
...options,
|
|
12667
|
-
query: { url },
|
|
12668
|
-
retry: options.retry ?? false
|
|
12669
|
-
});
|
|
12670
|
-
}
|
|
12671
|
-
async artwork(url, options = {}) {
|
|
12672
|
-
return this.http.download("/s_r_machine/artwork", {
|
|
12673
|
-
timeoutMs: 120000,
|
|
12674
|
-
...options,
|
|
12675
|
-
query: { url },
|
|
12676
|
-
retry: options.retry ?? false
|
|
12677
|
-
});
|
|
12678
|
-
}
|
|
12679
|
-
async audio(url, options = {}) {
|
|
12680
|
-
return this.http.download("/s_r_machine/audio", {
|
|
12681
|
-
timeoutMs: 600000,
|
|
12682
|
-
...options,
|
|
12683
|
-
query: { url },
|
|
12684
|
-
retry: options.retry ?? false
|
|
12685
|
-
});
|
|
12686
|
-
}
|
|
12687
|
-
async convertToOpus(file2, options = {}) {
|
|
12688
|
-
const form = await buildFormData({ file: file2 });
|
|
12689
|
-
const response = await this.http.raw("POST", "/s_r_machine/convert-opus", {
|
|
12690
|
-
timeoutMs: 600000,
|
|
12691
|
-
...options,
|
|
12692
|
-
body: form
|
|
12693
|
-
});
|
|
12694
|
-
const data = await response.blob();
|
|
12695
|
-
return {
|
|
12696
|
-
data,
|
|
12697
|
-
filename: filenameFromDisposition(response.headers.get("content-disposition")),
|
|
12698
|
-
contentType: response.headers.get("content-type") ?? undefined,
|
|
12699
|
-
size: data.size
|
|
12700
|
-
};
|
|
12701
|
-
}
|
|
12702
|
-
}
|
|
12703
12659
|
function spotifySyncProgress(status) {
|
|
12704
12660
|
const playlists = status.sync_progress?.playlists ?? [];
|
|
12705
12661
|
let loaded = 0;
|
|
@@ -14818,23 +14774,29 @@ class CaptionsNamespace extends Resource {
|
|
|
14818
14774
|
return this.http.get(`/caption_jobs/${encodeURIComponent(id)}`, options);
|
|
14819
14775
|
}
|
|
14820
14776
|
async transcribe(id, input, options = {}) {
|
|
14821
|
-
const started = await this.
|
|
14777
|
+
const started = await this.startTranscribe(id, input, options);
|
|
14778
|
+
return this.settle(id, started, options, "the transcription");
|
|
14779
|
+
}
|
|
14780
|
+
async startTranscribe(id, input, options = {}) {
|
|
14781
|
+
return this.http.post(`/caption_jobs/${encodeURIComponent(id)}/transcribe`, {
|
|
14822
14782
|
start: input.start,
|
|
14823
14783
|
end: input.end,
|
|
14824
14784
|
...input.language === undefined ? {} : { language: input.language }
|
|
14825
14785
|
}, { ...options, retry: options.retry ?? false });
|
|
14826
|
-
return this.settle(id, started, options, "the transcription");
|
|
14827
14786
|
}
|
|
14828
14787
|
async render(id, input = {}, options = {}) {
|
|
14788
|
+
const started = await this.startRender(id, input, options);
|
|
14789
|
+
return this.settle(id, started, options, "the render");
|
|
14790
|
+
}
|
|
14791
|
+
async startRender(id, input = {}, options = {}) {
|
|
14829
14792
|
const words = input.words ?? (await this.get(id, options)).words ?? [];
|
|
14830
14793
|
if (words.length === 0) {
|
|
14831
14794
|
throw new OmsError(`Caption job ${id} has no words to render. Transcribe a window first with transcribe(), ` + `or pass an edited list as \`words\`.`, "conflict");
|
|
14832
14795
|
}
|
|
14833
|
-
|
|
14796
|
+
return this.http.post(`/caption_jobs/${encodeURIComponent(id)}/render`, {
|
|
14834
14797
|
words,
|
|
14835
14798
|
...input.style === undefined ? {} : { style: input.style }
|
|
14836
14799
|
}, { ...options, retry: options.retry ?? false });
|
|
14837
|
-
return this.settle(id, started, options, "the render");
|
|
14838
14800
|
}
|
|
14839
14801
|
async delete(id, options = {}) {
|
|
14840
14802
|
await this.http.delete(`/caption_jobs/${encodeURIComponent(id)}`, options);
|
|
@@ -15136,6 +15098,49 @@ class UpscaleNamespace extends Resource {
|
|
|
15136
15098
|
}
|
|
15137
15099
|
}
|
|
15138
15100
|
|
|
15101
|
+
// src/resources/tools/srMachine.ts
|
|
15102
|
+
class SRMachineNamespace extends Resource {
|
|
15103
|
+
async metadata(url, options = {}) {
|
|
15104
|
+
return this.http.get("/s_r_machine/metadata", {
|
|
15105
|
+
timeoutMs: 120000,
|
|
15106
|
+
...options,
|
|
15107
|
+
query: { url },
|
|
15108
|
+
retry: options.retry ?? false
|
|
15109
|
+
});
|
|
15110
|
+
}
|
|
15111
|
+
async artwork(url, options = {}) {
|
|
15112
|
+
return this.http.download("/s_r_machine/artwork", {
|
|
15113
|
+
timeoutMs: 120000,
|
|
15114
|
+
...options,
|
|
15115
|
+
query: { url },
|
|
15116
|
+
retry: options.retry ?? false
|
|
15117
|
+
});
|
|
15118
|
+
}
|
|
15119
|
+
async audio(url, options = {}) {
|
|
15120
|
+
return this.http.download("/s_r_machine/audio", {
|
|
15121
|
+
timeoutMs: 600000,
|
|
15122
|
+
...options,
|
|
15123
|
+
query: { url },
|
|
15124
|
+
retry: options.retry ?? false
|
|
15125
|
+
});
|
|
15126
|
+
}
|
|
15127
|
+
async convertToOpus(file2, options = {}) {
|
|
15128
|
+
const form = await buildFormData({ file: file2 });
|
|
15129
|
+
const response = await this.http.raw("POST", "/s_r_machine/convert-opus", {
|
|
15130
|
+
timeoutMs: 600000,
|
|
15131
|
+
...options,
|
|
15132
|
+
body: form
|
|
15133
|
+
});
|
|
15134
|
+
const data = await response.blob();
|
|
15135
|
+
return {
|
|
15136
|
+
data,
|
|
15137
|
+
filename: filenameFromDisposition(response.headers.get("content-disposition")),
|
|
15138
|
+
contentType: response.headers.get("content-type") ?? undefined,
|
|
15139
|
+
size: data.size
|
|
15140
|
+
};
|
|
15141
|
+
}
|
|
15142
|
+
}
|
|
15143
|
+
|
|
15139
15144
|
// src/resources/tools/vocalSeparation.ts
|
|
15140
15145
|
function vocalSeparationProgress(record) {
|
|
15141
15146
|
const base = toolProgress(record);
|
|
@@ -15267,6 +15272,7 @@ class ToolsNamespace extends Resource {
|
|
|
15267
15272
|
captions;
|
|
15268
15273
|
jumpstyle;
|
|
15269
15274
|
downloader;
|
|
15275
|
+
srMachine;
|
|
15270
15276
|
constructor(http) {
|
|
15271
15277
|
super(http);
|
|
15272
15278
|
this.backgroundRemoval = new BackgroundRemovalNamespace(http);
|
|
@@ -15276,6 +15282,7 @@ class ToolsNamespace extends Resource {
|
|
|
15276
15282
|
this.captions = new CaptionsNamespace(http);
|
|
15277
15283
|
this.jumpstyle = new JumpstyleNamespace(http);
|
|
15278
15284
|
this.downloader = new DownloaderNamespace(http);
|
|
15285
|
+
this.srMachine = new SRMachineNamespace(http);
|
|
15279
15286
|
}
|
|
15280
15287
|
}
|
|
15281
15288
|
|
|
@@ -10,7 +10,6 @@
|
|
|
10
10
|
* | `/song_imports` | one track, downloaded from a URL or found by search | any signed-in user |
|
|
11
11
|
* | `/playlist_imports/preview` | read a playlist URL without importing it | any signed-in user |
|
|
12
12
|
* | `/spotify_syncs/*` | mirror a Spotify account into playlists | Spotify-enabled accounts only |
|
|
13
|
-
* | `/s_r_machine/*` | raw fetch + transcode helpers | **admins only** |
|
|
14
13
|
*
|
|
15
14
|
* ## An import is not a `Job`
|
|
16
15
|
*
|
|
@@ -48,7 +47,7 @@
|
|
|
48
47
|
*/
|
|
49
48
|
import { type ApiClient, Resource } from "../../http";
|
|
50
49
|
import type { ListParams } from "../../listing";
|
|
51
|
-
import type { BaseRecord,
|
|
50
|
+
import type { BaseRecord, Id, Paginated, Progress, RequestOptions, Timestamp, WaitOptions } from "../../types";
|
|
52
51
|
import type { DownloaderPreview } from "../tools/downloader";
|
|
53
52
|
/**
|
|
54
53
|
* Primary key of a song import. An **integer**, like `songs` and `playlists`
|
|
@@ -314,8 +313,6 @@ export declare function songImportProgress(record: SongImport): Progress;
|
|
|
314
313
|
export declare class MusicImportsNamespace extends Resource {
|
|
315
314
|
/** Spotify account mirroring. Spotify-enabled accounts only - see the class. */
|
|
316
315
|
readonly spotify: SpotifySyncNamespace;
|
|
317
|
-
/** Admin-only fetch and transcode helpers. */
|
|
318
|
-
readonly srMachine: SRMachineNamespace;
|
|
319
316
|
constructor(http: ApiClient);
|
|
320
317
|
/**
|
|
321
318
|
* `GET /song_imports` - your import history, newest first only if you ask.
|
|
@@ -788,117 +785,6 @@ export declare class SpotifySyncNamespace extends Resource {
|
|
|
788
785
|
/** The one description of "watching a sync", shared by the two watchers. */
|
|
789
786
|
private syncPollPlan;
|
|
790
787
|
}
|
|
791
|
-
/** What `GET /s_r_machine/metadata` answers. Two keys, both nullable. */
|
|
792
|
-
export interface SRMachineMetadata {
|
|
793
|
-
readonly title: string | null;
|
|
794
|
-
readonly artist: string | null;
|
|
795
|
-
}
|
|
796
|
-
/**
|
|
797
|
-
* The SR Machine helpers, reachable as `oms.music.imports.srMachine`.
|
|
798
|
-
*
|
|
799
|
-
* ## Admin only, and the check is blunt
|
|
800
|
-
*
|
|
801
|
-
* Every route answers `403 "You SHALL NOT use this resource"` to anyone who is
|
|
802
|
-
* not an administrator. There is no allowlist, no scope and no per-user
|
|
803
|
-
* quota.
|
|
804
|
-
*
|
|
805
|
-
* ## What it is
|
|
806
|
-
*
|
|
807
|
-
* Four unrelated primitives left over from the "slowed + reverb" video tool:
|
|
808
|
-
* fetch the artwork behind a URL, fetch its audio, read its title and artist,
|
|
809
|
-
* and transcode an arbitrary audio blob to Opus. Nothing here touches the
|
|
810
|
-
* library - no song is created, nothing is stored, and the bytes come back in
|
|
811
|
-
* the response body. If you want a track IN the library, use
|
|
812
|
-
* {@link MusicImportsNamespace.create} instead; this is the raw pipe.
|
|
813
|
-
*
|
|
814
|
-
* Three of the four fetch a caller-supplied URL and hold a server thread while
|
|
815
|
-
* they do it, exactly like {@link MusicImportsNamespace.previewPlaylist} - but
|
|
816
|
-
* they have no budget of their own, so the only ceiling is the general
|
|
817
|
-
* 600/min. The admin gate is what stands in for a budget here. Do not build a
|
|
818
|
-
* batch loop on top of these.
|
|
819
|
-
*
|
|
820
|
-
* A YouTube URL carrying `?list=` is truncated at the `?list=` before the fetch,
|
|
821
|
-
* so a link copied from inside a playlist resolves to the single video rather
|
|
822
|
-
* than the playlist. That happens server-side, in all three fetchers.
|
|
823
|
-
*
|
|
824
|
-
* All three fetchers respond with `Content-Disposition: attachment` and a
|
|
825
|
-
* fixed filename (`artwork.jpg`, `audio.opus`), so `FileOutput.filename` is
|
|
826
|
-
* that constant rather than anything derived from the source.
|
|
827
|
-
*/
|
|
828
|
-
export declare class SRMachineNamespace extends Resource {
|
|
829
|
-
/**
|
|
830
|
-
* `GET /s_r_machine/metadata` - the title and artist read off a URL.
|
|
831
|
-
*
|
|
832
|
-
* Both keys can be `null` for a source that carries no tags; it is a
|
|
833
|
-
* best-effort read, not a lookup.
|
|
834
|
-
*
|
|
835
|
-
* Not retried by default: it parks a server thread for up to 60 seconds,
|
|
836
|
-
* and a failure means the source refused.
|
|
837
|
-
*
|
|
838
|
-
* @throws {OmsAuthError} 403 `"You SHALL NOT use this resource"` for a
|
|
839
|
-
* non-admin.
|
|
840
|
-
* @throws {OmsApiError} 400 `"url is not allowed"` for a URL that is not
|
|
841
|
-
* public http(s); 500 when the fetch itself fails - an upstream failure
|
|
842
|
-
* surfaces as a server error here, not as a 502.
|
|
843
|
-
*/
|
|
844
|
-
metadata(url: string, options?: RequestOptions): Promise<SRMachineMetadata>;
|
|
845
|
-
/**
|
|
846
|
-
* `GET /s_r_machine/artwork` - the cover behind a URL, as `image/jpeg`.
|
|
847
|
-
*
|
|
848
|
-
* Buffered fully into memory in every runtime, React Native included. It is a
|
|
849
|
-
* cover, so that is fine; {@link SRMachineNamespace.audio} is where it is not.
|
|
850
|
-
*
|
|
851
|
-
* @throws {OmsAuthError} 403 for a non-admin.
|
|
852
|
-
* @throws {OmsApiError} 400 `"url is not allowed"`; 500 on a fetch failure.
|
|
853
|
-
*/
|
|
854
|
-
artwork(url: string, options?: RequestOptions): Promise<FileOutput>;
|
|
855
|
-
/**
|
|
856
|
-
* `GET /s_r_machine/audio` - the audio behind a URL, as `audio/opus`.
|
|
857
|
-
*
|
|
858
|
-
* The whole track is downloaded server-side, held in memory there, and sent
|
|
859
|
-
* back in one body which this then buffers into memory again on the client.
|
|
860
|
-
* Nothing streams. On a phone that is a whole track in the JavaScript heap,
|
|
861
|
-
* and there is no signed-URL alternative here the way there is for library
|
|
862
|
-
* media - this endpoint has no storage node behind it. Reach for it on
|
|
863
|
-
* desktop, think twice on React Native, and never for a batch.
|
|
864
|
-
*
|
|
865
|
-
* Generous `timeoutMs` by default because a long track legitimately takes
|
|
866
|
-
* minutes.
|
|
867
|
-
*
|
|
868
|
-
* @throws {OmsAuthError} 403 for a non-admin.
|
|
869
|
-
* @throws {OmsApiError} 400 `"url is not allowed"`; 500 on a fetch failure.
|
|
870
|
-
*/
|
|
871
|
-
audio(url: string, options?: RequestOptions): Promise<FileOutput>;
|
|
872
|
-
/**
|
|
873
|
-
* `POST /s_r_machine/convert-opus` - transcode an audio file to Opus.
|
|
874
|
-
*
|
|
875
|
-
* Multipart, field name `file`, and the only method in this namespace that
|
|
876
|
-
* uploads. The response is `audio/opus` bytes, not JSON.
|
|
877
|
-
*
|
|
878
|
-
* Works on all three runtimes: a React Native `{ uri, name, type }` descriptor
|
|
879
|
-
* goes into the `FormData` verbatim and is streamed off disk by the native
|
|
880
|
-
* layer, while a browser or Bun caller passes a `FileInput` carrying a Blob
|
|
881
|
-
* or a `Uint8Array`. A `ReadableStream` is buffered first, because
|
|
882
|
-
* `FormData` has no streaming entry.
|
|
883
|
-
*
|
|
884
|
-
* The upload has no client-side size cap here because the server declares
|
|
885
|
-
* none - but the CDN in front of the API rejects a request body over roughly
|
|
886
|
-
* 100 MB with a 413 that never reaches it. There is no chunked path for this
|
|
887
|
-
* route, so a file above that simply cannot go through it.
|
|
888
|
-
*
|
|
889
|
-
* The server reads the whole part into memory before transcoding, so a large
|
|
890
|
-
* input is a large allocation on both sides.
|
|
891
|
-
*
|
|
892
|
-
* @throws {OmsAuthError} 403 `"You SHALL NOT use this resource"` for a
|
|
893
|
-
* non-admin.
|
|
894
|
-
* @throws {OmsApiError} 500 when no `file` part was sent or when the input
|
|
895
|
-
* cannot be transcoded. Neither is a graceful 400.
|
|
896
|
-
* @throws {TypeError} when a React Native descriptor is passed on a runtime
|
|
897
|
-
* whose `FormData` is the web one, which would otherwise upload the literal
|
|
898
|
-
* text `"[object Object]"` and answer 500.
|
|
899
|
-
*/
|
|
900
|
-
convertToOpus(file: FileInput | NativeFile, options?: RequestOptions): Promise<FileOutput>;
|
|
901
|
-
}
|
|
902
788
|
/**
|
|
903
789
|
* Renders a sync run as the SDK's shared {@link Progress}.
|
|
904
790
|
*
|
|
@@ -506,6 +506,13 @@ export declare class CaptionsNamespace extends Resource {
|
|
|
506
506
|
* quota is spent either way and the words still land on the row.
|
|
507
507
|
*/
|
|
508
508
|
transcribe(id: Id, input: TranscribeCaptionInput, options?: ToolRunOptions): Promise<CaptionJob>;
|
|
509
|
+
/**
|
|
510
|
+
* `POST /caption_jobs/:id/transcribe` without waiting: answers the row as
|
|
511
|
+
* soon as it is `"transcribing"`. For a screen that polls {@link get} itself
|
|
512
|
+
* and shows progress meanwhile. Same errors as {@link transcribe}, minus the
|
|
513
|
+
* timeouts.
|
|
514
|
+
*/
|
|
515
|
+
startTranscribe(id: Id, input: TranscribeCaptionInput, options?: RequestOptions): Promise<CaptionJob>;
|
|
509
516
|
/**
|
|
510
517
|
* `POST /caption_jobs/:id/render` - step 3.
|
|
511
518
|
*
|
|
@@ -532,6 +539,12 @@ export declare class CaptionsNamespace extends Resource {
|
|
|
532
539
|
* `code: "aborted"` when the signal fires. Neither cancels the render.
|
|
533
540
|
*/
|
|
534
541
|
render(id: Id, input?: RenderCaptionInput, options?: ToolRunOptions): Promise<CaptionJob>;
|
|
542
|
+
/**
|
|
543
|
+
* `POST /caption_jobs/:id/render` without waiting: answers the row as soon
|
|
544
|
+
* as it is `"rendering"`. Same word handling and errors as {@link render},
|
|
545
|
+
* minus the timeouts.
|
|
546
|
+
*/
|
|
547
|
+
startRender(id: Id, input?: RenderCaptionInput, options?: RequestOptions): Promise<CaptionJob>;
|
|
535
548
|
/**
|
|
536
549
|
* `DELETE /caption_jobs/:id` - drops the job and its uploaded video.
|
|
537
550
|
*
|
|
@@ -40,6 +40,7 @@ import { DownloaderNamespace } from "./downloader";
|
|
|
40
40
|
import { JumpstyleNamespace } from "./jumpstyle";
|
|
41
41
|
import { TranscriptionNamespace } from "./transcription";
|
|
42
42
|
import { UpscaleNamespace } from "./upscale";
|
|
43
|
+
import { SRMachineNamespace } from "./srMachine";
|
|
43
44
|
import { VocalSeparationNamespace } from "./vocalSeparation";
|
|
44
45
|
export * from "./backgroundRemoval";
|
|
45
46
|
export * from "./captions";
|
|
@@ -47,6 +48,7 @@ export * from "./downloader";
|
|
|
47
48
|
export * from "./jumpstyle";
|
|
48
49
|
export * from "./transcription";
|
|
49
50
|
export * from "./upscale";
|
|
51
|
+
export * from "./srMachine";
|
|
50
52
|
export * from "./vocalSeparation";
|
|
51
53
|
/**
|
|
52
54
|
* Lifecycle of a tool row.
|
|
@@ -255,5 +257,7 @@ export declare class ToolsNamespace extends Resource {
|
|
|
255
257
|
readonly jumpstyle: JumpstyleNamespace;
|
|
256
258
|
/** Fetches media from a public URL. */
|
|
257
259
|
readonly downloader: DownloaderNamespace;
|
|
260
|
+
/** Fetch, convert and package a track. Administrators only. */
|
|
261
|
+
readonly srMachine: SRMachineNamespace;
|
|
258
262
|
constructor(http: ApiClient);
|
|
259
263
|
}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
/** The `tools.srMachine` namespace: fetch a track's audio, artwork and metadata by URL, and transcode audio to Opus. Administrators only. */
|
|
2
|
+
import { Resource } from "../../http";
|
|
3
|
+
import type { FileInput, FileOutput, NativeFile, RequestOptions } from "../../types";
|
|
4
|
+
/** What `GET /s_r_machine/metadata` answers. Two keys, both nullable. */
|
|
5
|
+
export interface SRMachineMetadata {
|
|
6
|
+
readonly title: string | null;
|
|
7
|
+
readonly artist: string | null;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* The SR Machine helpers, reachable as `oms.tools.srMachine`.
|
|
11
|
+
*
|
|
12
|
+
* ## Admin only, and the check is blunt
|
|
13
|
+
*
|
|
14
|
+
* Every route answers `403 "You SHALL NOT use this resource"` to anyone who is
|
|
15
|
+
* not an administrator. There is no allowlist, no scope and no per-user
|
|
16
|
+
* quota.
|
|
17
|
+
*
|
|
18
|
+
* ## What it is
|
|
19
|
+
*
|
|
20
|
+
* Four unrelated primitives left over from the "slowed + reverb" video tool:
|
|
21
|
+
* fetch the artwork behind a URL, fetch its audio, read its title and artist,
|
|
22
|
+
* and transcode an arbitrary audio blob to Opus. Nothing here touches the
|
|
23
|
+
* library - no song is created, nothing is stored, and the bytes come back in
|
|
24
|
+
* the response body. If you want a track IN the library, use
|
|
25
|
+
* `oms.music.imports.create()` instead; this is the raw pipe.
|
|
26
|
+
*
|
|
27
|
+
* Three of the four fetch a caller-supplied URL and hold a server thread while
|
|
28
|
+
* they do it, exactly like `oms.music.imports.previewPlaylist()` - but
|
|
29
|
+
* they have no budget of their own, so the only ceiling is the general
|
|
30
|
+
* 600/min. The admin gate is what stands in for a budget here. Do not build a
|
|
31
|
+
* batch loop on top of these.
|
|
32
|
+
*
|
|
33
|
+
* A YouTube URL carrying `?list=` is truncated at the `?list=` before the fetch,
|
|
34
|
+
* so a link copied from inside a playlist resolves to the single video rather
|
|
35
|
+
* than the playlist. That happens server-side, in all three fetchers.
|
|
36
|
+
*
|
|
37
|
+
* All three fetchers respond with `Content-Disposition: attachment` and a
|
|
38
|
+
* fixed filename (`artwork.jpg`, `audio.opus`), so `FileOutput.filename` is
|
|
39
|
+
* that constant rather than anything derived from the source.
|
|
40
|
+
*/
|
|
41
|
+
export declare class SRMachineNamespace extends Resource {
|
|
42
|
+
/**
|
|
43
|
+
* `GET /s_r_machine/metadata` - the title and artist read off a URL.
|
|
44
|
+
*
|
|
45
|
+
* Both keys can be `null` for a source that carries no tags; it is a
|
|
46
|
+
* best-effort read, not a lookup.
|
|
47
|
+
*
|
|
48
|
+
* Not retried by default: it parks a server thread for up to 60 seconds,
|
|
49
|
+
* and a failure means the source refused.
|
|
50
|
+
*
|
|
51
|
+
* @throws {OmsAuthError} 403 `"You SHALL NOT use this resource"` for a
|
|
52
|
+
* non-admin.
|
|
53
|
+
* @throws {OmsApiError} 400 `"url is not allowed"` for a URL that is not
|
|
54
|
+
* public http(s); 500 when the fetch itself fails - an upstream failure
|
|
55
|
+
* surfaces as a server error here, not as a 502.
|
|
56
|
+
*/
|
|
57
|
+
metadata(url: string, options?: RequestOptions): Promise<SRMachineMetadata>;
|
|
58
|
+
/**
|
|
59
|
+
* `GET /s_r_machine/artwork` - the cover behind a URL, as `image/jpeg`.
|
|
60
|
+
*
|
|
61
|
+
* Buffered fully into memory in every runtime, React Native included. It is a
|
|
62
|
+
* cover, so that is fine; {@link SRMachineNamespace.audio} is where it is not.
|
|
63
|
+
*
|
|
64
|
+
* @throws {OmsAuthError} 403 for a non-admin.
|
|
65
|
+
* @throws {OmsApiError} 400 `"url is not allowed"`; 500 on a fetch failure.
|
|
66
|
+
*/
|
|
67
|
+
artwork(url: string, options?: RequestOptions): Promise<FileOutput>;
|
|
68
|
+
/**
|
|
69
|
+
* `GET /s_r_machine/audio` - the audio behind a URL, as `audio/opus`.
|
|
70
|
+
*
|
|
71
|
+
* The whole track is downloaded server-side, held in memory there, and sent
|
|
72
|
+
* back in one body which this then buffers into memory again on the client.
|
|
73
|
+
* Nothing streams. On a phone that is a whole track in the JavaScript heap,
|
|
74
|
+
* and there is no signed-URL alternative here the way there is for library
|
|
75
|
+
* media - this endpoint has no storage node behind it. Reach for it on
|
|
76
|
+
* desktop, think twice on React Native, and never for a batch.
|
|
77
|
+
*
|
|
78
|
+
* Generous `timeoutMs` by default because a long track legitimately takes
|
|
79
|
+
* minutes.
|
|
80
|
+
*
|
|
81
|
+
* @throws {OmsAuthError} 403 for a non-admin.
|
|
82
|
+
* @throws {OmsApiError} 400 `"url is not allowed"`; 500 on a fetch failure.
|
|
83
|
+
*/
|
|
84
|
+
audio(url: string, options?: RequestOptions): Promise<FileOutput>;
|
|
85
|
+
/**
|
|
86
|
+
* `POST /s_r_machine/convert-opus` - transcode an audio file to Opus.
|
|
87
|
+
*
|
|
88
|
+
* Multipart, field name `file`, and the only method in this namespace that
|
|
89
|
+
* uploads. The response is `audio/opus` bytes, not JSON.
|
|
90
|
+
*
|
|
91
|
+
* Works on all three runtimes: a React Native `{ uri, name, type }` descriptor
|
|
92
|
+
* goes into the `FormData` verbatim and is streamed off disk by the native
|
|
93
|
+
* layer, while a browser or Bun caller passes a `FileInput` carrying a Blob
|
|
94
|
+
* or a `Uint8Array`. A `ReadableStream` is buffered first, because
|
|
95
|
+
* `FormData` has no streaming entry.
|
|
96
|
+
*
|
|
97
|
+
* The upload has no client-side size cap here because the server declares
|
|
98
|
+
* none - but the CDN in front of the API rejects a request body over roughly
|
|
99
|
+
* 100 MB with a 413 that never reaches it. There is no chunked path for this
|
|
100
|
+
* route, so a file above that simply cannot go through it.
|
|
101
|
+
*
|
|
102
|
+
* The server reads the whole part into memory before transcoding, so a large
|
|
103
|
+
* input is a large allocation on both sides.
|
|
104
|
+
*
|
|
105
|
+
* @throws {OmsAuthError} 403 `"You SHALL NOT use this resource"` for a
|
|
106
|
+
* non-admin.
|
|
107
|
+
* @throws {OmsApiError} 500 when no `file` part was sent or when the input
|
|
108
|
+
* cannot be transcoded. Neither is a graceful 400.
|
|
109
|
+
* @throws {TypeError} when a React Native descriptor is passed on a runtime
|
|
110
|
+
* whose `FormData` is the web one, which would otherwise upload the literal
|
|
111
|
+
* text `"[object Object]"` and answer 500.
|
|
112
|
+
*/
|
|
113
|
+
convertToOpus(file: FileInput | NativeFile, options?: RequestOptions): Promise<FileOutput>;
|
|
114
|
+
}
|
package/package.json
CHANGED