@nodaro/sdk 2.11.0 → 2.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
- import { SCENE3D_V2_LIMITS, WORKSPACE_HEADER } from '@nodaro/shared';
2
- export { CHARACTER_ASPECT_DEFAULTS, CHARACTER_ASPECT_OPTIONS, CHARACTER_STYLES, OBJECT_ASPECT_DEFAULTS as CREATURE_ASPECT_DEFAULTS, OBJECT_ASPECT_OPTIONS as CREATURE_ASPECT_OPTIONS, CREATURE_ATTACH_COLUMNS, LOCATION_ASSET_TYPES, LOCATION_ATTACH_COLUMNS, OBJECT_ASPECT_DEFAULTS, OBJECT_ASPECT_OPTIONS, OBJECT_ASSET_TYPES, OBJECT_ATTACH_COLUMNS, OUTPUT_BEARING_NODE_STATUSES, PROMPT_PREFIX_KEY, PROMPT_SUFFIX_KEY, SURROUND_DIRECTIONS, USAGE_GROUP_BYS, WORKSPACE_HEADER, nodeStateMayCarryOutput } from '@nodaro/shared';
1
+ import { SCENE3D_V2_LIMITS, remapTranscriptThroughEdl, WORKSPACE_HEADER } from '@nodaro/shared';
2
+ export { CHARACTER_ASPECT_DEFAULTS, CHARACTER_ASPECT_OPTIONS, CHARACTER_STYLES, OBJECT_ASPECT_DEFAULTS as CREATURE_ASPECT_DEFAULTS, OBJECT_ASPECT_OPTIONS as CREATURE_ASPECT_OPTIONS, CREATURE_ATTACH_COLUMNS, LOCATION_ASSET_TYPES, LOCATION_ATTACH_COLUMNS, OBJECT_ASPECT_DEFAULTS, OBJECT_ASPECT_OPTIONS, OBJECT_ASSET_TYPES, OBJECT_ATTACH_COLUMNS, OUTPUT_BEARING_NODE_STATUSES, PROMPT_PREFIX_KEY, PROMPT_SUFFIX_KEY, SURROUND_DIRECTIONS, USAGE_GROUP_BYS, WORKSPACE_HEADER, nodeStateMayCarryOutput, unwrapEditPlanOutput } from '@nodaro/shared';
3
3
  import { buildPersonHints } from '@nodaro/prompts';
4
4
  export { PEOPLE, PERSON_DIMENSION_LABELS, PERSON_DIMENSION_ORDER, buildPersonHints } from '@nodaro/prompts';
5
5
 
@@ -2156,9 +2156,13 @@ var MediaResource = class {
2156
2156
  * Download a social video (YouTube / TikTok / Instagram / X / Facebook) into
2157
2157
  * your storage (`POST /v1/download-video`). `maxHeight` caps the resolution
2158
2158
  * (default "best"); `sectionStartSec` + `sectionEndSec` (both-or-neither) fetch
2159
- * ONLY that time range instead of the whole video. Returns a `downloadId`;
2160
- * progress streams from `GET /v1/download-video/progress/:downloadId`
2161
- * (server-sent events) and the finished file lands in your library.
2159
+ * ONLY that time range instead of the whole video. A download that arrives
2160
+ * with no audio stream FAILS by default (it is usually a degraded source
2161
+ * response, and is retried through other routes first); pass
2162
+ * `requireAudio: false` to accept a clip that really has no sound. Returns a
2163
+ * `downloadId`; progress streams from
2164
+ * `GET /v1/download-video/progress/:downloadId` (server-sent events) and the
2165
+ * finished file lands in your library.
2162
2166
  */
2163
2167
  downloadVideo(input) {
2164
2168
  return this.client.request("POST", "/v1/download-video", { body: input });
@@ -2260,6 +2264,52 @@ var MediaResource = class {
2260
2264
  trimVideo(input) {
2261
2265
  return this.client.request("POST", "/v1/trim-video", { body: input });
2262
2266
  }
2267
+ /**
2268
+ * Burn captions into a video (`POST /v1/add-captions`). Give the words as
2269
+ * `text`, word-timed `captions[]`, or let it transcribe (`autoTranscribe`,
2270
+ * the default when neither is set).
2271
+ *
2272
+ * `style: "subtitle"` renders statically (FFmpeg) UNLESS it carries a styling
2273
+ * lever, in which case it — like the KINETIC styles (`word-highlight` /
2274
+ * `karaoke` / `tiktok-words` / `word-pop` / `bouncy`) — renders via Remotion.
2275
+ * `look` picks a preset — `outline` (Montserrat 900, UPPERCASE, black outline,
2276
+ * yellow spoken word — the TikTok/Reels read) or `clean`; an UNSET look renders
2277
+ * as `outline`. The explicit STYLING levers (`fontFamily`, `fontWeight`,
2278
+ * `strokeColor`/`strokeWidth`, `uppercase`, `positionY`, `maxWordsPerLine`)
2279
+ * override individual fields of it and now apply to `subtitle` too. Only
2280
+ * `highlightColor` (the spoken-word cursor) and `animate` stay kinetic-only
2281
+ * and are REJECTED on `subtitle`.
2282
+ *
2283
+ * `animate` (default true) freezes the per-word MOTION on the kinetic styles
2284
+ * when set to false — the grouping, line-holding and spoken-word highlight
2285
+ * stay; only the movement stops.
2286
+ *
2287
+ * `maxWordsPerLine` (1-20) caps how many words a line — or a `tiktok-words`
2288
+ * page — may hold, on top of the width budget / sentence ends / pauses that
2289
+ * already close one; it is inert on `word-pop`, which is always one word.
2290
+ * Like every lever here it exists top-level AND per segment, and a segment
2291
+ * that does not name its own inherits the top-level value.
2292
+ *
2293
+ * `segments[]` applies DIFFERENT treatments to non-overlapping time ranges in
2294
+ * one call (e.g. a large top intro, then a small bottom body); a segment that
2295
+ * names its own `look` starts fresh from that preset and does not inherit the
2296
+ * top-level explicit levers. Poll `jobs.get(jobId)`.
2297
+ *
2298
+ * `word-highlight` shows ONE held line at a time and a word's
2299
+ * `startMs`/`endMs` is its SPOKEN window (what times the highlight, not how
2300
+ * long the text is on screen) — so `captions[]` can be handed over verbatim
2301
+ * from an `audio.transcribe()` job's `output_data.words`, with
2302
+ * `autoTranscribe: false`.
2303
+ */
2304
+ addCaptions(input) {
2305
+ const { autoTranscribe, transcribeProvider, ...rest } = input;
2306
+ const body = {
2307
+ ...rest,
2308
+ ...autoTranscribe !== void 0 ? { auto_transcribe: autoTranscribe } : {},
2309
+ ...transcribeProvider !== void 0 ? { transcribe_provider: transcribeProvider } : {}
2310
+ };
2311
+ return this.client.request("POST", "/v1/add-captions", { body });
2312
+ }
2263
2313
  /**
2264
2314
  * Trim (and extract) audio from a video or audio source
2265
2315
  * (`POST /v1/trim-audio`) to `[startTime, endTime]` seconds, in `audioFormat`
@@ -2363,6 +2413,32 @@ var AudioResource = class {
2363
2413
  combine(input) {
2364
2414
  return this.client.request("POST", "/v1/combine-audio", { body: input });
2365
2415
  }
2416
+ /**
2417
+ * Transcribe an audio (or video) track to text (`POST /v1/transcribe`).
2418
+ *
2419
+ * Three engines are accepted. `elevenlabs-stt` (Scribe) is always word-level,
2420
+ * flag or not, and is the only lane that honours `diarize` (who spoke) and
2421
+ * `tagAudioEvents` (laughter, applause, …); `incredibly-fast-whisper` returns
2422
+ * word timings when you ask for them. `whisper` returns NO word timings at
2423
+ * all — named explicitly or reached by OMITTING `provider`, which still falls
2424
+ * back to it — so asking it for them (`wordTimestamps: true`) is rejected with
2425
+ * a `400 validation_error` at ingress, before any credit is spent. A kinetic
2426
+ * caption render therefore has to name one of the other two.
2427
+ *
2428
+ * Poll `jobs.get(jobId)`; the finished job's `output_data` is a
2429
+ * {@link TranscribeJobOutput}: `text` (the whole transcript), `words`
2430
+ * (caption-shaped, in MILLISECONDS), `json` (the normalized
2431
+ * {@link Transcript}, also ms) — and a top-level `segments` array that is in
2432
+ * SECONDS, not ms.
2433
+ *
2434
+ * `words` is the caption source for a kinetic burn-in: hand it to
2435
+ * `media.addCaptions()` as `captions` with `autoTranscribe: false` and the
2436
+ * render uses those exact words (correct the `text` of an entry in between
2437
+ * and the fix is what burns in).
2438
+ */
2439
+ transcribe(input) {
2440
+ return this.client.request("POST", "/v1/transcribe", { body: input });
2441
+ }
2366
2442
  };
2367
2443
 
2368
2444
  // src/resources/credits.ts
@@ -3451,7 +3527,86 @@ var WorkspacesResource = class {
3451
3527
  return this.client.requestText("GET", `/v1/workspaces/${encodeURIComponent(id)}/usage`, { query: { ...opts, format: "csv" } });
3452
3528
  }
3453
3529
  };
3454
- var SDK_VERSION = "2.11.0" ;
3530
+ var EditResource = class {
3531
+ constructor(client) {
3532
+ this.client = client;
3533
+ }
3534
+ client;
3535
+ /**
3536
+ * Detect silence ranges in an audio/video source (`POST /v1/silence-detect`).
3537
+ * Keyless — one ffmpeg pass over the source's audio proxy.
3538
+ */
3539
+ silenceDetect(input) {
3540
+ return this.client.request("POST", "/v1/silence-detect", {
3541
+ body: {
3542
+ audioUrl: input.audioUrl,
3543
+ ...input.thresholdDb !== void 0 ? { thresholdDb: input.thresholdDb } : {},
3544
+ ...input.minSilenceMs !== void 0 ? { minSilenceMs: input.minSilenceMs } : {},
3545
+ ...input.padMs !== void 0 ? { padMs: input.padMs } : {},
3546
+ ...input.workflowId !== void 0 ? { workflowId: input.workflowId } : {}
3547
+ }
3548
+ });
3549
+ }
3550
+ /**
3551
+ * Render an edit decision list into a video or audio cut (`POST /v1/apply-edl`).
3552
+ * The EDL is validated at ingress — an unresolvable source or a picture-less
3553
+ * segment on a video edit throws a typed `NodaroError` (400, `code:
3554
+ * "invalid_edl"`) before any credits are reserved.
3555
+ */
3556
+ applyEdl(input) {
3557
+ return this.client.request("POST", "/v1/apply-edl", {
3558
+ body: {
3559
+ edl: input.edl,
3560
+ ...input.sources !== void 0 ? { sources: input.sources } : {},
3561
+ ...input.transcript !== void 0 ? { transcript: input.transcript } : {},
3562
+ ...input.output !== void 0 ? { output: input.output } : {},
3563
+ ...input.quality !== void 0 ? { quality: input.quality } : {},
3564
+ ...input.crossfadeMs !== void 0 ? { crossfadeMs: input.crossfadeMs } : {},
3565
+ ...input.workflowId !== void 0 ? { workflowId: input.workflowId } : {}
3566
+ }
3567
+ });
3568
+ }
3569
+ /**
3570
+ * Plan a transcript-driven cut (`POST /v1/edit-plan`). Reads a timed
3571
+ * transcript (plus optional silence ranges) and the media sources, and plans
3572
+ * the edit. The finished job's `output_data` holds the plan: an `Edl`
3573
+ * (`"tighten"`), an {@link EdlClipSet} (`"clips"`), or a {@link ChapterSet}
3574
+ * (`"chapters"`) — normalize it with {@link unwrapEditPlanOutput}.
3575
+ *
3576
+ * On a self-hosted install the request relays to nodaro.ai and needs the
3577
+ * install connected (a 503 `code: "nodaro_connection_required"` otherwise);
3578
+ * on nodaro.ai it runs directly.
3579
+ */
3580
+ editPlan(input) {
3581
+ return this.client.request("POST", "/v1/edit-plan", {
3582
+ body: {
3583
+ mode: input.mode,
3584
+ planTier: input.planTier,
3585
+ transcript: input.transcript,
3586
+ sources: input.sources,
3587
+ ...input.silence !== void 0 ? { silence: input.silence } : {},
3588
+ ...input.instructions !== void 0 ? { instructions: input.instructions } : {},
3589
+ ...input.styleGuide !== void 0 ? { styleGuide: input.styleGuide } : {},
3590
+ ...input.count !== void 0 ? { count: input.count } : {},
3591
+ ...input.targetDurationSec !== void 0 ? { targetDurationSec: input.targetDurationSec } : {},
3592
+ ...input.targetAspect !== void 0 ? { targetAspect: input.targetAspect } : {},
3593
+ ...input.platform !== void 0 ? { platform: input.platform } : {},
3594
+ ...input.workflowId !== void 0 ? { workflowId: input.workflowId } : {}
3595
+ }
3596
+ });
3597
+ }
3598
+ /**
3599
+ * Remap a transcript through an EDL — a PURE client-side transform (NO
3600
+ * request). Returns a new transcript whose word (and segment) timings are on
3601
+ * the EDL's rendered output clock, dropping words that fall in cut regions and
3602
+ * clipping straddlers. Runs `@nodaro/shared`'s canonical
3603
+ * `remapTranscriptThroughEdl`, the same remap `applyEdl` performs server-side.
3604
+ */
3605
+ remapTranscript(edl, transcript) {
3606
+ return remapTranscriptThroughEdl(edl, transcript);
3607
+ }
3608
+ };
3609
+ var SDK_VERSION = "2.14.0" ;
3455
3610
  var CLIENT_HEADER = "X-Nodaro-Client";
3456
3611
  var isBrowser = () => typeof window !== "undefined" && typeof window.document !== "undefined";
3457
3612
  var NodaroClient = class _NodaroClient {
@@ -3509,6 +3664,7 @@ var NodaroClient = class _NodaroClient {
3509
3664
  tutorials;
3510
3665
  organizations;
3511
3666
  workspaces;
3667
+ edit;
3512
3668
  /** The workspace this client acts in; undefined = the personal space. */
3513
3669
  workspaceId;
3514
3670
  constructor(opts) {
@@ -3556,6 +3712,7 @@ var NodaroClient = class _NodaroClient {
3556
3712
  this.tutorials = new TutorialsResource(this);
3557
3713
  this.organizations = new OrganizationsResource(this);
3558
3714
  this.workspaces = new WorkspacesResource(this);
3715
+ this.edit = new EditResource(this);
3559
3716
  }
3560
3717
  /**
3561
3718
  * A client that acts in `workspaceId`, sharing this one's auth and config.
@@ -3712,6 +3869,6 @@ function supabaseAuth(supabase) {
3712
3869
  };
3713
3870
  }
3714
3871
 
3715
- export { AppsResource, AudioResource, CREATURE_ASSET_TYPES, CallbackAuth, CatalogsResource, CharactersResource, CommunityResource, CopilotResource, CreaturesResource, CreditsResource, DeveloperAppsResource, ExecutionsResource, ForbiddenError, InsufficientCreditsError, JobAbortedError, JobBlockedError, JobFailedError, JobHeldError, JobTimeoutError, JobsResource, LibraryResource, LlmResource, LocationsResource, MediaResource, ModelsResource, NodaroClient, NodaroError, NodesResource, NotFoundError, OAuthResource, ObjectsResource, OrganizationsResource, PickerCatalogsResource, PipelinesResource, PresetsResource, ProjectsResource, PromptHelperResource, RateLimitedError, RecastResource, ReduceResource, SCENE3D_DELIVERY_ASSET_USAGE, Scene3DResource, ShotsResource, StaticTokenAuth, StorageExceededError, StudioOpError, StudioPreviewAppliedError, StudioPreviewUnavailable, StudioProductionsResource, StudioResource, TemplatesResource, TutorialsResource, UnauthorizedError, UploadsResource, VideoProResource, VoicesResource, WorkflowConflictError, WorkflowsResource, WorkspacesResource, buildPersonSeedPrompt, createClient, isStudioGenerateEstimate, supabaseAuth, throwFromResponse };
3872
+ export { AppsResource, AudioResource, CREATURE_ASSET_TYPES, CallbackAuth, CatalogsResource, CharactersResource, CommunityResource, CopilotResource, CreaturesResource, CreditsResource, DeveloperAppsResource, EditResource, ExecutionsResource, ForbiddenError, InsufficientCreditsError, JobAbortedError, JobBlockedError, JobFailedError, JobHeldError, JobTimeoutError, JobsResource, LibraryResource, LlmResource, LocationsResource, MediaResource, ModelsResource, NodaroClient, NodaroError, NodesResource, NotFoundError, OAuthResource, ObjectsResource, OrganizationsResource, PickerCatalogsResource, PipelinesResource, PresetsResource, ProjectsResource, PromptHelperResource, RateLimitedError, RecastResource, ReduceResource, SCENE3D_DELIVERY_ASSET_USAGE, Scene3DResource, ShotsResource, StaticTokenAuth, StorageExceededError, StudioOpError, StudioPreviewAppliedError, StudioPreviewUnavailable, StudioProductionsResource, StudioResource, TemplatesResource, TutorialsResource, UnauthorizedError, UploadsResource, VideoProResource, VoicesResource, WorkflowConflictError, WorkflowsResource, WorkspacesResource, buildPersonSeedPrompt, createClient, isStudioGenerateEstimate, supabaseAuth, throwFromResponse };
3716
3873
  //# sourceMappingURL=index.js.map
3717
3874
  //# sourceMappingURL=index.js.map