samsar-js 0.48.28 → 0.48.30

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 CHANGED
@@ -107,6 +107,20 @@ await samsar.createVideoFromImageList({
107
107
  ],
108
108
  });
109
109
 
110
+ // Create the same generated QR outro and per-scene footer CTAs from one CTA link
111
+ await samsar.createVideoFromImageList({
112
+ image_urls: [
113
+ { image_url: 'https://example.com/a.jpg', title: 'Blue Lagoon Tour' },
114
+ { image_url: 'https://example.com/b.jpg', title: 'Sunset Dinner' },
115
+ ],
116
+ prompt: 'Travel offer reel with concise scene CTAs',
117
+ metadata: { brand: 'Guidestination', offer: 'Bookable Bangkok experiences' },
118
+ video_model: 'RUNWAYML',
119
+ aspect_ratio: '9:16',
120
+ express_cta_generation: true,
121
+ cta_url: 'https://example.com/book',
122
+ });
123
+
110
124
  // Update an existing outro with a new provided outro image URL
111
125
  await samsar.updateVideoOutroImage(
112
126
  {
@@ -547,11 +561,12 @@ console.log(externalLibrary.data.requests.map((request) => request.request_id));
547
561
 
548
562
  Video model support notes:
549
563
  - `createVideoFromText` image model keys include: `GPTIMAGE2`, `IMAGEN4`, `SEEDREAM`, `NANOBANANA2`, `CUSTOM_TEXT_TO_IMAGE`.
550
- - `createVideoFromText` supports these video models: `RUNWAYML`, `VEO3.1I2V`, `VEO3.1I2VFAST`, `SEEDANCEI2V` (Seedance 1.5), `KLINGIMGTOVID3PRO`, and `CUSTOM_IMAGE_TO_VIDEO`.
564
+ - `createVideoFromText` supports these video models: `RUNWAYML`, `VEO3.1I2V`, `VEO3.1I2VFAST`, `SEEDANCEI2V` (Seedance 1.5), `KLINGIMGTOVID3PRO`, and `HAPPYHORSEI2V`.
551
565
  - `createVideoFromText` accepts either a provided outro (`outro_image_url`) or server-generated QR outro (`generate_outro_image: true` with `cta_url`). It can also render bottom CTA footer QR cards with `add_footer_animation` and `footer_metadata`; one footer item applies to every generated scene, while multiple items map by scene index.
552
- - `createVideoFromImageList` supports `RUNWAYML`, `VEO3.1I2V`, `VEO3.1I2VFAST`, `SEEDANCEI2V`, `KLINGIMGTOVID3PRO`, and `CUSTOM_IMAGE_TO_VIDEO` via `video_model`; if omitted, it defaults to `RUNWAYML`. Use `aspect_ratio: '16:9'` or `'9:16'`; omitted or invalid values fall back to `16:9`.
566
+ - `createVideoFromImageList` supports `RUNWAYML`, `VEO3.1I2V`, `VEO3.1I2VFAST`, `SEEDANCEI2V`, `KLINGIMGTOVID3PRO`, and `HAPPYHORSEI2V` via `video_model`; if omitted, it defaults to `RUNWAYML`. Use `aspect_ratio: '16:9'` or `'9:16'`; omitted or invalid values fall back to `16:9`.
553
567
  - `createVideoFromImageList` accepts either a provided outro (`outro_image_url`) or server-generated QR outro (`generate_outro_image: true` with `cta_url`). Do not combine the two modes in a single request.
554
568
  - `createVideoFromImageList` can render per-scene footer QR cards by setting `add_footer_animation: true` and providing one `footer_metadata` item per image scene.
569
+ - `createVideoFromImageList` can also generate QR outro CTA text and each scene footer CTA from a single link by setting `express_cta_generation: true` with `cta_url`. CamelCase `expressCtaGeneration` and compatibility aliases `auto_generate_cta_text` / `generate_cta_texts` are normalized to the same API field.
555
570
  - `createVideoFromImageList` accepts `limit_single_narrator: true` to keep all narration under one narrator identity. `add_narrator_avatar: true` automatically enables `limit_single_narrator`, generates an influencer-style human narrator avatar, and overlays it bottom-center or centered in the footer row when footer metadata is present.
556
571
  - `updateVideoOutroImage` accepts either a replacement outro image URL (`outro_image_url`, `outroImageUrl`, `new_outro_image_url`) or a generated QR CTA outro (`generate_outro_image: true` with `cta_url`, or just `cta_url` when no outro image URL is supplied). Generated outro updates reuse the existing session image layers for tiling and only queue frame/video regeneration.
557
572
  - `updateVideoFooterImage` updates the footer CTA on a cloned session with `cta_text`, `cta_logo`, and/or `cta_url`, or removes all scene footers with `remove_footer: true`. Footer updates queue only frame/video regeneration.
@@ -559,13 +574,13 @@ Video model support notes:
559
574
  - Main video methods and external-user methods accept the same generated outro and footer parameters. The API can resolve either internal session ids or external `extreq_...` ids on repeated video routes, so client code can keep using `translateVideo`, `joinVideos`, `addSubtitles`, `removeSubtitles`, `addVideoOutroImage`, `updateVideoOutroImage`, and `updateVideoFooterImage`; the explicit external variants are available when you want to call `/external_users/*` directly. Do not strip the `extreq_` prefix.
560
575
  - Completed video status, latest-version, and completed-session list responses expose `has_subtitles` and `result_language` when the session metadata is available.
561
576
  - `publishPublication`, `editPublication`, and `revokePublication` manage public feed publications for completed sessions through free `/publications/*` endpoints. They work with account API keys, customer sub-account API keys, and client auth tokens when the session belongs to the authenticated actor.
562
- - Text-to-video and image-list video pricing use the same per-rendered-second rates for standard express models: `VEO3.1I2V` is 60 credits/sec, `VEO3.1I2VFAST` is 36 credits/sec, `SEEDANCEI2V` is 30 credits/sec, `KLINGIMGTOVID3PRO` is 36 credits/sec, and `RUNWAYML` is 30 credits/sec. Image-list narrator avatar generation adds 4 credits/sec when `add_narrator_avatar` is true.
563
- - Standard express video models expose a per-second pricing distribution through `EXPRESS_VIDEO_PRICING_DISTRIBUTION_PER_SECOND_BY_MODEL`: pipeline 4, inference 4, image gen/edit 2, speech 2, music 2, effects and lipsync 2, and video as the model-specific remainder.
577
+ - Text-to-video and image-list video pricing use the same per-rendered-second rates for standard express models: `VEO3.1I2V` is 60 credits/sec, `VEO3.1I2VFAST` is 36 credits/sec, `SEEDANCEI2V` is 30 credits/sec, `KLINGIMGTOVID3PRO` is 36 credits/sec, `HAPPYHORSEI2V` is 36 credits/sec, and `RUNWAYML` is 30 credits/sec. Image-list narrator avatar generation adds 4 credits/sec when `add_narrator_avatar` is true; express CTA generation adds 1 credit/sec when `express_cta_generation` is true.
578
+ - Standard express video models expose a per-second pricing distribution through `EXPRESS_VIDEO_PRICING_DISTRIBUTION_PER_SECOND_BY_MODEL`: pipeline 4, inference 4, image gen/edit 2, speech 2, music 2, effects and lipsync 2, video as the model-specific remainder, and `optionalAddons.express_cta_generation` at 1 credit/sec.
564
579
 
565
580
  Upcoming `/v2` omni route adapters:
566
581
  - `/v2` is additive; `/v1` is not deprecated.
567
- - `createV2VideoFromText`, `createV2VideoFromImageList`, `translateV2Video`, `cloneV2Video`, `updateV2VideoOutroImage`, `updateV2VideoFooterImage`, `addV2VideoOutroImage`, `getV2Status`, `getV2StatusDetailed`, `getV2Credits`, `listV2Requests`, and `createV2Session` call the new omni route surface.
568
- - Step-controlled video helpers include `createV2StepVideoFromText`, `createV2StepTextToVideo`, `createV2StepVideoFromImage`, `createV2StepImageToVideo`, `getV2StepVideoStatus`, `getV2StepVideoStatusDetailed`, and `processNextV2StepVideo`.
582
+ - `createV2VideoFromText`, `createV2VideoFromImageList`, `translateV2Video`, `cloneV2Video`, `regenerateV2VideoAvatar`, `updateV2VideoOutroImage`, `updateV2VideoFooterImage`, `addV2VideoOutroImage`, `getV2Status`, `getV2StatusDetailed`, `getV2Credits`, `listV2Requests`, and `createV2Session` call the new omni route surface.
583
+ - Step-controlled video helpers include `createV2StepVideoFromText`, `createV2StepTextToVideo`, `createV2StepVideoFromImage`, `createV2StepImageToVideo`, `getV2StepVideoStatus`, `getV2StepVideoStatusDetailed`, and `processNextV2StepVideo`. They default to 1-step express rendering by sending `auto_render_full_video: true` and `manual_step_stages: []`; pass `{ stepMode: 'two_step' }` or `manual_step_stages: ['ai_video_generation']` to require an explicit second-step approval before image-to-video generation.
569
584
  - Programmatic user helpers include `createV2ExternalUser`, `createV2UserRechargeCredits`, `refreshV2UserToken`, `createV2UserAppKey`, `refreshV2UserAppKey`, `getV2UserCredits`, `getV2UserUsageLogs`, and `getV2UserPaymentStatus`.
570
585
  - Omit `externalUser` for internal account billing, pass `externalUser` to scope an external user with the account API key, or authenticate the client directly with an external-user auth token/API key. V2 external users can be referenced by `unique_key`; if `unique_key` is omitted during creation, the server uses `external_user_id` as the key.
571
586
  - Detailed status adapters return the normal status payload plus a normalized `session` preview shape with `layers`, `audioLayers`, `globalAudioLayers`, and `globalVideos`. Layer timing uses `startTime` and `endTime` so clients can preview generated images, scene clips, and speech before final render completion.
@@ -574,9 +589,8 @@ Upcoming `/v2` omni route adapters:
574
589
  const v2Video = await platform.createV2VideoFromImageList({
575
590
  image_urls: ['https://cdn.example.com/a.png', 'https://cdn.example.com/b.png'],
576
591
  video_model: 'RUNWAYML',
577
- generate_outro_image: true,
592
+ express_cta_generation: true,
578
593
  cta_url: 'https://example.com/book',
579
- cta_text_top: 'Scan to book',
580
594
  });
581
595
 
582
596
  const v2ExternalVideo = await platform.createV2VideoFromImageList(
@@ -599,6 +613,10 @@ const v2Clone = await platform.cloneV2Video({
599
613
  videoSessionId: v2Video.data.request_id!,
600
614
  });
601
615
 
616
+ const v2AvatarRerender = await platform.regenerateV2VideoAvatar({
617
+ videoSessionId: v2Video.data.request_id!,
618
+ });
619
+
602
620
  const v2Status = await platform.getV2Status(v2Video.data.request_id!);
603
621
  console.log(v2Status.data.status);
604
622
 
@@ -606,7 +624,7 @@ const v2Detailed = await platform.getV2StatusDetailed(v2Video.data.request_id!);
606
624
  console.log(v2Detailed.data.session?.previewStage, v2Detailed.data.session?.layers?.[0]?.preview?.url);
607
625
  ```
608
626
 
609
- Step-controlled video generation pauses after each completed stage until you call `processNextV2StepVideo`:
627
+ Step video generation defaults to a 1-step express render, so it does not pause before image-to-video generation:
610
628
 
611
629
  ```ts
612
630
  const stepVideo = await platform.createV2StepVideoFromText({
@@ -618,12 +636,28 @@ const stepVideo = await platform.createV2StepVideoFromText({
618
636
  enable_subtitles: true,
619
637
  });
620
638
 
621
- let stepStatus = await platform.getV2StepVideoStatus(stepVideo.data.request_id);
622
- if (stepStatus.data.step_status === 'COMPLETED') {
623
- console.log(stepStatus.data.current_step, stepStatus.data.current_step_resources);
624
- const stepDetailed = await platform.getV2StepVideoStatusDetailed(stepVideo.data.request_id);
625
- console.log(stepDetailed.data.session?.previewStage, stepDetailed.data.session?.layers?.[0]?.preview?.url);
626
- stepStatus = await platform.processNextV2StepVideo(stepVideo.data.request_id);
639
+ const stepDetailed = await platform.getV2StepVideoStatusDetailed(stepVideo.data.request_id);
640
+ console.log(stepDetailed.data.session?.previewStage, stepDetailed.data.session?.layers?.[0]?.preview?.url);
641
+ ```
642
+
643
+ Use 2-step mode only when you want to review generated image/audio assets before starting the image-to-video stage:
644
+
645
+ ```ts
646
+ const twoStepVideo = await platform.createV2StepVideoFromText(
647
+ {
648
+ prompt: 'A 20 second launch teaser for a new travel app',
649
+ image_model: 'GPTIMAGE2',
650
+ video_model: 'RUNWAYML',
651
+ duration: 20,
652
+ aspect_ratio: '16:9',
653
+ enable_subtitles: true,
654
+ },
655
+ { stepMode: 'two_step' },
656
+ );
657
+
658
+ let stepStatus = await platform.getV2StepVideoStatus(twoStepVideo.data.request_id);
659
+ if (stepStatus.data.waiting_for_process_next || stepStatus.data.can_process_next) {
660
+ stepStatus = await platform.processNextV2StepVideo(twoStepVideo.data.request_id);
627
661
  }
628
662
 
629
663
  const stepImageVideo = await platform.createV2StepVideoFromImage({
@@ -9,7 +9,12 @@ export declare const EXPRESS_VIDEO_FIXED_PRICING_COMPONENTS_PER_SECOND: {
9
9
  export type ExpressVideoPricingDistribution = typeof EXPRESS_VIDEO_FIXED_PRICING_COMPONENTS_PER_SECOND & {
10
10
  video: number;
11
11
  total: number;
12
+ optionalAddons: ExpressVideoOptionalAddons;
12
13
  };
14
+ export declare const EXPRESS_VIDEO_OPTIONAL_ADDON_CREDITS_PER_SECOND: {
15
+ readonly express_cta_generation: 1;
16
+ };
17
+ export type ExpressVideoOptionalAddons = typeof EXPRESS_VIDEO_OPTIONAL_ADDON_CREDITS_PER_SECOND;
13
18
  export declare const EXPRESS_VIDEO_FIXED_COMPONENTS_TOTAL_PER_SECOND: number;
14
19
  export declare const EXPRESS_VIDEO_CREDITS_PER_SECOND_BY_MODEL: {
15
20
  readonly 'VEO3.1I2V': 60;
@@ -17,6 +22,7 @@ export declare const EXPRESS_VIDEO_CREDITS_PER_SECOND_BY_MODEL: {
17
22
  readonly SEEDANCEI2V: 30;
18
23
  readonly KLINGIMGTOVID3PRO: 36;
19
24
  readonly KLINGIMGTOVIDTURBO: 36;
25
+ readonly HAPPYHORSEI2V: 36;
20
26
  readonly RUNWAYML: 30;
21
27
  };
22
28
  export declare const EXPRESS_VIDEO_PRICING_DISTRIBUTION_PER_SECOND_BY_MODEL: Record<string, ExpressVideoPricingDistribution>;
@@ -6,6 +6,9 @@ export const EXPRESS_VIDEO_FIXED_PRICING_COMPONENTS_PER_SECOND = {
6
6
  music: 2,
7
7
  effects_and_lipsync: 2,
8
8
  };
9
+ export const EXPRESS_VIDEO_OPTIONAL_ADDON_CREDITS_PER_SECOND = {
10
+ express_cta_generation: 1,
11
+ };
9
12
  export const EXPRESS_VIDEO_FIXED_COMPONENTS_TOTAL_PER_SECOND = Object.values(EXPRESS_VIDEO_FIXED_PRICING_COMPONENTS_PER_SECOND).reduce((total, value) => total + value, 0);
10
13
  export const EXPRESS_VIDEO_CREDITS_PER_SECOND_BY_MODEL = {
11
14
  'VEO3.1I2V': 60,
@@ -13,6 +16,7 @@ export const EXPRESS_VIDEO_CREDITS_PER_SECOND_BY_MODEL = {
13
16
  SEEDANCEI2V: 30,
14
17
  KLINGIMGTOVID3PRO: 36,
15
18
  KLINGIMGTOVIDTURBO: 36,
19
+ HAPPYHORSEI2V: 36,
16
20
  RUNWAYML: 30,
17
21
  };
18
22
  export const EXPRESS_VIDEO_PRICING_DISTRIBUTION_PER_SECOND_BY_MODEL = Object.fromEntries(Object.entries(EXPRESS_VIDEO_CREDITS_PER_SECOND_BY_MODEL)
@@ -22,6 +26,7 @@ export const EXPRESS_VIDEO_PRICING_DISTRIBUTION_PER_SECOND_BY_MODEL = Object.fro
22
26
  ...EXPRESS_VIDEO_FIXED_PRICING_COMPONENTS_PER_SECOND,
23
27
  video: total - EXPRESS_VIDEO_FIXED_COMPONENTS_TOTAL_PER_SECOND,
24
28
  total,
29
+ optionalAddons: EXPRESS_VIDEO_OPTIONAL_ADDON_CREDITS_PER_SECOND,
25
30
  },
26
31
  ]));
27
32
  export function getExpressVideoCreditsPerSecond(model) {
package/dist/index.d.ts CHANGED
@@ -36,7 +36,14 @@ export interface FontOptions {
36
36
  language?: string;
37
37
  family?: string;
38
38
  }
39
- export interface CreateVideoFromTextInput {
39
+ export type V2StepGenerationMode = 'one_step' | 'two_step';
40
+ export interface V2StepGenerationOptions {
41
+ auto_render_full_video?: boolean;
42
+ autoRenderFullVideo?: boolean;
43
+ manual_step_stages?: Array<V2StepVideoStage | string>;
44
+ manualStepStages?: Array<V2StepVideoStage | string>;
45
+ }
46
+ export interface CreateVideoFromTextInput extends V2StepGenerationOptions {
40
47
  prompt: string;
41
48
  image_model: string;
42
49
  video_model: string;
@@ -111,7 +118,7 @@ export interface FooterMetadataItem {
111
118
  footerLogoImagePath?: string;
112
119
  }
113
120
  export type ImageListToVideoAspectRatio = '16:9' | '9:16';
114
- export type ImageListToVideoModel = 'RUNWAYML' | 'VEO3.1I2V' | 'VEO3.1I2VFAST' | 'SEEDANCEI2V' | 'KLINGIMGTOVID3PRO' | 'CUSTOM_IMAGE_TO_VIDEO';
121
+ export type ImageListToVideoModel = 'RUNWAYML' | 'VEO3.1I2V' | 'VEO3.1I2VFAST' | 'SEEDANCEI2V' | 'KLINGIMGTOVID3PRO' | 'HAPPYHORSEI2V';
115
122
  export interface ImageListToVideoItem {
116
123
  image_url?: string;
117
124
  imageUrl?: string;
@@ -139,7 +146,7 @@ export interface ImageListToVideoItem {
139
146
  label?: string;
140
147
  [key: string]: unknown;
141
148
  }
142
- export interface CreateVideoFromImageListInput {
149
+ export interface CreateVideoFromImageListInput extends V2StepGenerationOptions {
143
150
  image_urls: Array<string | ImageListToVideoItem>;
144
151
  metadata?: Record<string, unknown>;
145
152
  prompt?: string;
@@ -172,6 +179,12 @@ export interface CreateVideoFromImageListInput {
172
179
  outroFocusArea?: OutroFocusArea | null;
173
180
  generate_outro_image?: boolean;
174
181
  generateOutroImage?: boolean;
182
+ express_cta_generation?: boolean;
183
+ expressCtaGeneration?: boolean;
184
+ auto_generate_cta_text?: boolean;
185
+ autoGenerateCtaText?: boolean;
186
+ generate_cta_texts?: boolean;
187
+ generateCtaTexts?: boolean;
175
188
  cta_url?: string;
176
189
  ctaUrl?: string;
177
190
  cta_text_top?: string;
@@ -1411,6 +1424,9 @@ export interface V2RequestOptions extends SamsarRequestOptions {
1411
1424
  externalUser?: V2ExternalUserIdentity | null;
1412
1425
  webhookUrl?: string;
1413
1426
  }
1427
+ export interface V2StepVideoRequestOptions extends V2RequestOptions, V2StepGenerationOptions {
1428
+ stepMode?: V2StepGenerationMode;
1429
+ }
1414
1430
  export type V2StepVideoStage = 'prompt_generation' | 'image_generation' | 'speech_generation' | 'music_generation' | 'audio_generation' | 'ai_video_generation' | 'lip_sync_generation' | 'sound_effect_generation' | 'narrator_avatar_generation' | 'delete_reflow' | 'timeline_reflowed' | 'transcript_generation' | 'frame_generation' | 'video_generation';
1415
1431
  export type V2StepVideoStatus = 'INIT' | 'PENDING' | 'COMPLETED' | 'FAILED' | string;
1416
1432
  export interface VideoSessionPreviewAsset {
@@ -1541,7 +1557,11 @@ export interface V2StepVideoState {
1541
1557
  current_step?: V2StepVideoStage | string | null;
1542
1558
  current_step_label?: string | null;
1543
1559
  next_step?: V2StepVideoStage | string | null;
1560
+ manual_step_stages?: Array<V2StepVideoStage | string>;
1561
+ auto_advance_step_stages?: Array<V2StepVideoStage | string>;
1544
1562
  waiting_for_process_next?: boolean;
1563
+ requires_user_action?: boolean;
1564
+ can_process_next?: boolean;
1545
1565
  updated_at?: string | null;
1546
1566
  [key: string]: unknown;
1547
1567
  }
@@ -1944,16 +1964,17 @@ export declare class SamsarClient {
1944
1964
  }): Promise<SamsarResult<CreateLoginTokenResponse | ExternalCreateLoginTokenResponse>>;
1945
1965
  createV2VideoFromText(input: CreateVideoFromTextInput, options?: V2RequestOptions): Promise<SamsarResult<CreateVideoResponse | ExternalRequestResponse>>;
1946
1966
  createV2VideoFromImageList(input: CreateVideoFromImageListInput, options?: V2RequestOptions): Promise<SamsarResult<CreateVideoFromImageListResponse | ExternalRequestResponse>>;
1947
- createV2StepVideoFromText(input: CreateVideoFromTextInput, options?: V2RequestOptions): Promise<SamsarResult<V2StepVideoCreateResponse>>;
1948
- createV2StepTextToVideo(input: CreateVideoFromTextInput, options?: V2RequestOptions): Promise<SamsarResult<V2StepVideoCreateResponse>>;
1949
- createV2StepVideoFromImage(input: CreateV2StepImageToVideoInput, options?: V2RequestOptions): Promise<SamsarResult<V2StepVideoCreateResponse>>;
1950
- createV2StepImageToVideo(input: CreateV2StepImageToVideoInput, options?: V2RequestOptions): Promise<SamsarResult<V2StepVideoCreateResponse>>;
1967
+ createV2StepVideoFromText(input: CreateVideoFromTextInput, options?: V2StepVideoRequestOptions): Promise<SamsarResult<V2StepVideoCreateResponse>>;
1968
+ createV2StepTextToVideo(input: CreateVideoFromTextInput, options?: V2StepVideoRequestOptions): Promise<SamsarResult<V2StepVideoCreateResponse>>;
1969
+ createV2StepVideoFromImage(input: CreateV2StepImageToVideoInput, options?: V2StepVideoRequestOptions): Promise<SamsarResult<V2StepVideoCreateResponse>>;
1970
+ createV2StepImageToVideo(input: CreateV2StepImageToVideoInput, options?: V2StepVideoRequestOptions): Promise<SamsarResult<V2StepVideoCreateResponse>>;
1951
1971
  getV2StepVideoStatus(requestId: string, options?: V2RequestOptions): Promise<SamsarResult<V2StepVideoStatusResponse>>;
1952
1972
  getV2StepVideoStatusDetailed(requestId: string, options?: V2RequestOptions): Promise<SamsarResult<V2StepVideoDetailedStatusResponse>>;
1953
1973
  getV2StepVideoDetailedStatus(requestId: string, options?: V2RequestOptions): Promise<SamsarResult<V2StepVideoDetailedStatusResponse>>;
1954
1974
  processNextV2StepVideo(requestId: string, options?: V2RequestOptions): Promise<SamsarResult<V2StepVideoStatusResponse>>;
1955
1975
  translateV2Video(input: TranslateVideoInput, options?: V2RequestOptions): Promise<SamsarResult<TranslateVideoResponse | ExternalRequestResponse>>;
1956
1976
  cloneV2Video(input: CloneVideoInput, options?: V2RequestOptions): Promise<SamsarResult<CloneVideoResponse>>;
1977
+ regenerateV2VideoAvatar(input: CloneVideoInput, options?: V2RequestOptions): Promise<SamsarResult<CloneVideoResponse | ExternalRequestResponse>>;
1957
1978
  uploadV2ImageData(imageData: string[], options?: V2RequestOptions): Promise<SamsarResult<{
1958
1979
  image_urls: string[];
1959
1980
  }>>;
package/dist/index.js CHANGED
@@ -4,6 +4,7 @@ const DEBUG = (() => {
4
4
  const env = globalThis?.process?.env;
5
5
  return env?.SAMSAR_SDK_DEBUG === '1';
6
6
  })();
7
+ const DEFAULT_V2_STEP_MANUAL_STAGES = ['ai_video_generation'];
7
8
  export class SamsarRequestError extends Error {
8
9
  constructor(message, init) {
9
10
  super(message);
@@ -40,6 +41,85 @@ function assertOptionalBoolean(value, fieldName, context = 'createVideoFromImage
40
41
  throw new Error(`${fieldName} must be a boolean for ${context}`);
41
42
  }
42
43
  }
44
+ function getFirstDefinedInputValue(raw, aliases) {
45
+ for (const alias of aliases) {
46
+ if (Object.prototype.hasOwnProperty.call(raw, alias)) {
47
+ return raw[alias];
48
+ }
49
+ }
50
+ return undefined;
51
+ }
52
+ function normalizeV2StepGenerationMode(value) {
53
+ if (typeof value !== 'string') {
54
+ return null;
55
+ }
56
+ const normalized = value.trim().toLowerCase().replace(/\s+/g, '_');
57
+ if (['one_step', 'one-step', '1_step', '1-step', 'express', 'auto', 'automatic'].includes(normalized)) {
58
+ return 'one_step';
59
+ }
60
+ if (['two_step', 'two-step', '2_step', '2-step', 'manual'].includes(normalized)) {
61
+ return 'two_step';
62
+ }
63
+ return null;
64
+ }
65
+ function normalizeV2StepBoolean(value, fieldName) {
66
+ if (value === undefined) {
67
+ return undefined;
68
+ }
69
+ if (typeof value === 'boolean') {
70
+ return value;
71
+ }
72
+ throw new Error(`${fieldName} must be a boolean for step video generation`);
73
+ }
74
+ function normalizeV2ManualStepStages(value) {
75
+ if (value === undefined) {
76
+ return undefined;
77
+ }
78
+ if (value === false || value === null) {
79
+ return [];
80
+ }
81
+ if (Array.isArray(value)) {
82
+ return value
83
+ .filter((stage) => typeof stage === 'string' && stage.trim().length > 0)
84
+ .map((stage) => stage.trim());
85
+ }
86
+ if (typeof value === 'string') {
87
+ return value
88
+ .split(',')
89
+ .map((stage) => stage.trim())
90
+ .filter(Boolean);
91
+ }
92
+ if (typeof value === 'object') {
93
+ return Object.entries(value)
94
+ .filter(([, enabled]) => enabled === true || enabled === 'true' || enabled === 1 || enabled === '1')
95
+ .map(([stage]) => stage.trim())
96
+ .filter(Boolean);
97
+ }
98
+ throw new Error('manual_step_stages must be an array, comma-separated string, stage map, null, or false');
99
+ }
100
+ function buildV2StepGenerationFields(input, options) {
101
+ const optionRecord = (options ?? {});
102
+ const stepMode = normalizeV2StepGenerationMode(optionRecord.stepMode);
103
+ const optionAutoRender = normalizeV2StepBoolean(getFirstDefinedInputValue(optionRecord, ['auto_render_full_video', 'autoRenderFullVideo']), 'auto_render_full_video');
104
+ const inputAutoRender = normalizeV2StepBoolean(getFirstDefinedInputValue(input, ['auto_render_full_video', 'autoRenderFullVideo']), 'auto_render_full_video');
105
+ const optionManualStages = normalizeV2ManualStepStages(getFirstDefinedInputValue(optionRecord, ['manual_step_stages', 'manualStepStages']));
106
+ const inputManualStages = normalizeV2ManualStepStages(getFirstDefinedInputValue(input, ['manual_step_stages', 'manualStepStages']));
107
+ let autoRenderFullVideo = stepMode ? stepMode === 'one_step' : optionAutoRender ?? inputAutoRender;
108
+ if (autoRenderFullVideo === undefined) {
109
+ autoRenderFullVideo = optionManualStages !== undefined || inputManualStages !== undefined
110
+ ? false
111
+ : true;
112
+ }
113
+ const manualStepStages = autoRenderFullVideo
114
+ ? []
115
+ : optionManualStages ?? inputManualStages ?? [...DEFAULT_V2_STEP_MANUAL_STAGES];
116
+ return {
117
+ auto_render_full_video: autoRenderFullVideo,
118
+ autoRenderFullVideo,
119
+ manual_step_stages: manualStepStages,
120
+ manualStepStages: manualStepStages,
121
+ };
122
+ }
43
123
  function normalizeCreateVideoFromTextInput(input) {
44
124
  const raw = input;
45
125
  const normalized = { ...input };
@@ -96,6 +176,17 @@ function normalizeCreateVideoFromImageListInput(input) {
96
176
  ['add_outro_focus_area', ['add_outro_focus_area', 'addOutroFocusArea']],
97
177
  ['outro_focust_area', ['outro_focust_area', 'outro_focus_area', 'outroFocustArea', 'outroFocusArea']],
98
178
  ['generate_outro_image', ['generate_outro_image', 'generateOutroImage']],
179
+ [
180
+ 'express_cta_generation',
181
+ [
182
+ 'express_cta_generation',
183
+ 'expressCtaGeneration',
184
+ 'auto_generate_cta_text',
185
+ 'autoGenerateCtaText',
186
+ 'generate_cta_texts',
187
+ 'generateCtaTexts',
188
+ ],
189
+ ],
99
190
  ['cta_url', ['cta_url', 'ctaUrl']],
100
191
  ['cta_text_top', ['cta_text_top', 'ctaTextTop']],
101
192
  ['cta_text_bottom', ['cta_text_bottom', 'ctaTextBottom']],
@@ -117,12 +208,24 @@ function normalizeCreateVideoFromImageListInput(input) {
117
208
  assertOptionalBoolean(normalized.add_outro_animation, 'add_outro_animation');
118
209
  assertOptionalBoolean(normalized.add_outro_focus_area, 'add_outro_focus_area');
119
210
  assertOptionalBoolean(normalized.generate_outro_image, 'generate_outro_image');
211
+ assertOptionalBoolean(normalized.express_cta_generation, 'express_cta_generation');
120
212
  assertOptionalBoolean(normalized.add_footer_animation, 'add_footer_animation');
121
213
  assertOptionalBoolean(normalized.limit_single_narrator, 'limit_single_narrator');
122
214
  assertOptionalBoolean(normalized.add_narrator_avatar, 'add_narrator_avatar');
123
215
  if (normalized.add_narrator_avatar === true) {
124
216
  normalized.limit_single_narrator = true;
125
217
  }
218
+ if (normalized.express_cta_generation === true) {
219
+ const ctaUrl = typeof normalized.cta_url === 'string' ? normalized.cta_url.trim() : '';
220
+ if (!ctaUrl) {
221
+ throw new Error('cta_url is required when express_cta_generation is true for createVideoFromImageList');
222
+ }
223
+ normalized.cta_url = ctaUrl;
224
+ normalized.generate_outro_image = true;
225
+ normalized.add_outro_animation = true;
226
+ normalized.add_outro_focus_area = true;
227
+ normalized.add_footer_animation = true;
228
+ }
126
229
  if (normalized.generate_outro_image === true) {
127
230
  const ctaUrl = typeof normalized.cta_url === 'string' ? normalized.cta_url.trim() : '';
128
231
  if (!ctaUrl) {
@@ -606,8 +709,13 @@ export class SamsarClient {
606
709
  }
607
710
  async createV2StepVideoFromText(input, options) {
608
711
  const normalizedInput = normalizeCreateVideoFromTextInput(input);
712
+ const stepGenerationFields = buildV2StepGenerationFields(normalizedInput, options);
609
713
  return this.postV2('video/step/text_to_video', {
610
- input: normalizedInput,
714
+ ...stepGenerationFields,
715
+ input: {
716
+ ...normalizedInput,
717
+ ...stepGenerationFields,
718
+ },
611
719
  webhookUrl: options?.webhookUrl,
612
720
  }, options);
613
721
  }
@@ -616,8 +724,13 @@ export class SamsarClient {
616
724
  }
617
725
  async createV2StepVideoFromImage(input, options) {
618
726
  const normalizedInput = normalizeCreateV2StepImageToVideoInput(input);
727
+ const stepGenerationFields = buildV2StepGenerationFields(normalizedInput, options);
619
728
  return this.postV2('video/step/image_to_video', {
620
- input: normalizedInput,
729
+ ...stepGenerationFields,
730
+ input: {
731
+ ...normalizedInput,
732
+ ...stepGenerationFields,
733
+ },
621
734
  webhookUrl: options?.webhookUrl,
622
735
  }, options);
623
736
  }
@@ -662,6 +775,13 @@ export class SamsarClient {
662
775
  webhookUrl: options?.webhookUrl,
663
776
  }, options);
664
777
  }
778
+ async regenerateV2VideoAvatar(input, options) {
779
+ const normalizedInput = normalizeCloneVideoInput(input, 'regenerateV2VideoAvatar');
780
+ return this.postV2('video/regenerate_avatar', {
781
+ input: normalizedInput,
782
+ webhookUrl: options?.webhookUrl,
783
+ }, options);
784
+ }
665
785
  async uploadV2ImageData(imageData, options) {
666
786
  if (!Array.isArray(imageData) || imageData.length === 0) {
667
787
  throw new Error('imageData must be a non-empty array of data URLs');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "samsar-js",
3
- "version": "0.48.28",
3
+ "version": "0.48.30",
4
4
  "description": "TypeScript client for the Samsar Processor API routes.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",