@picsart/ai-sdk 6.15.1 → 6.16.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/index.d.ts +40 -4
- package/index.js +154 -43
- package/package.json +1 -1
package/index.d.ts
CHANGED
|
@@ -349,14 +349,30 @@ type ModelInputById = {
|
|
|
349
349
|
"gemini-2.5-flash-tts": {
|
|
350
350
|
language?: string;
|
|
351
351
|
accent?: string;
|
|
352
|
-
prompt
|
|
352
|
+
prompt?: string;
|
|
353
353
|
voiceId?: string;
|
|
354
|
+
parts?: Array<{
|
|
355
|
+
text: string;
|
|
356
|
+
speaker?: string;
|
|
357
|
+
}>;
|
|
358
|
+
multiSpeakerVoiceConfigs?: Array<{
|
|
359
|
+
speaker: string;
|
|
360
|
+
voiceName: string;
|
|
361
|
+
}>;
|
|
354
362
|
};
|
|
355
363
|
"gemini-2.5-pro-tts": {
|
|
356
364
|
language?: string;
|
|
357
365
|
accent?: string;
|
|
358
|
-
prompt
|
|
366
|
+
prompt?: string;
|
|
359
367
|
voiceId?: string;
|
|
368
|
+
parts?: Array<{
|
|
369
|
+
text: string;
|
|
370
|
+
speaker?: string;
|
|
371
|
+
}>;
|
|
372
|
+
multiSpeakerVoiceConfigs?: Array<{
|
|
373
|
+
speaker: string;
|
|
374
|
+
voiceName: string;
|
|
375
|
+
}>;
|
|
360
376
|
};
|
|
361
377
|
"gemini-3-pro": {
|
|
362
378
|
prompt: string;
|
|
@@ -412,14 +428,34 @@ type ModelInputById = {
|
|
|
412
428
|
"gemini-3.8-flash-lite-tts": {
|
|
413
429
|
language?: string;
|
|
414
430
|
accent?: string;
|
|
415
|
-
prompt
|
|
431
|
+
prompt?: string;
|
|
416
432
|
voiceId?: string;
|
|
433
|
+
style?: string;
|
|
434
|
+
parts?: Array<{
|
|
435
|
+
text: string;
|
|
436
|
+
speaker?: string;
|
|
437
|
+
style?: string;
|
|
438
|
+
}>;
|
|
439
|
+
multiSpeakerVoiceConfigs?: Array<{
|
|
440
|
+
speaker: string;
|
|
441
|
+
voiceName: string;
|
|
442
|
+
}>;
|
|
417
443
|
};
|
|
418
444
|
"gemini-3.8-flash-tts": {
|
|
419
445
|
language?: string;
|
|
420
446
|
accent?: string;
|
|
421
|
-
prompt
|
|
447
|
+
prompt?: string;
|
|
422
448
|
voiceId?: string;
|
|
449
|
+
style?: string;
|
|
450
|
+
parts?: Array<{
|
|
451
|
+
text: string;
|
|
452
|
+
speaker?: string;
|
|
453
|
+
style?: string;
|
|
454
|
+
}>;
|
|
455
|
+
multiSpeakerVoiceConfigs?: Array<{
|
|
456
|
+
speaker: string;
|
|
457
|
+
voiceName: string;
|
|
458
|
+
}>;
|
|
423
459
|
};
|
|
424
460
|
"gemini-omni-1.1-flash-preview": {
|
|
425
461
|
prompt: string;
|
package/index.js
CHANGED
|
@@ -6453,11 +6453,6 @@ var buildGemini31FlashLiteImagePayload = (ctx) => ({
|
|
|
6453
6453
|
imageSize: ctx.resolution ?? "1K",
|
|
6454
6454
|
...buildThinkingConfig(ctx)
|
|
6455
6455
|
});
|
|
6456
|
-
var buildGeminiTTSPayload = (model) => (ctx) => ({
|
|
6457
|
-
text: ctx.prompt,
|
|
6458
|
-
model,
|
|
6459
|
-
voiceName: ctx.voiceId ?? "Kore"
|
|
6460
|
-
});
|
|
6461
6456
|
function inferMimeType2(url) {
|
|
6462
6457
|
return url.match(/\.png(\?|$)/i) ? "image/png" : "image/jpeg";
|
|
6463
6458
|
}
|
|
@@ -6469,6 +6464,52 @@ var buildGeminiOmniVideoPayload = (ctx) => ({
|
|
|
6469
6464
|
...ctx.imageUrls?.[0] ? { image: { url: ctx.imageUrls[0], mimeType: inferMimeType2(ctx.imageUrls[0]) } } : {},
|
|
6470
6465
|
...ctx.videoUrl ? { video: { url: ctx.videoUrl } } : {}
|
|
6471
6466
|
});
|
|
6467
|
+
var GEMINI_TTS_TEXT_MAX = 6e3;
|
|
6468
|
+
var GEMINI_TTS_STYLE_MAX = 500;
|
|
6469
|
+
var geminiTtsParams = (directable) => ({
|
|
6470
|
+
...params.language(true),
|
|
6471
|
+
// 6,000 boundary-verified against the live gemini/v1/audios worker
|
|
6472
|
+
// (accepts >5,000; see scripts/api-tests/audio-charlimit-boundary-probe.mjs).
|
|
6473
|
+
...params.prompt({ required: false, maxLength: GEMINI_TTS_TEXT_MAX }),
|
|
6474
|
+
...params.voiceId([], GEMINI_DEFAULT_VOICE_ID, { catalog: { workflow: "gemini/v1/catalog/voices" } }),
|
|
6475
|
+
...directable ? {
|
|
6476
|
+
style: {
|
|
6477
|
+
label: "Style",
|
|
6478
|
+
descriptor: {
|
|
6479
|
+
kind: "text",
|
|
6480
|
+
maxLength: GEMINI_TTS_STYLE_MAX,
|
|
6481
|
+
placeholder: "e.g. warm, unhurried; a bedtime story"
|
|
6482
|
+
}
|
|
6483
|
+
}
|
|
6484
|
+
} : {},
|
|
6485
|
+
// Worker `SpeechPartDto[]`, same names. Used instead of `prompt`.
|
|
6486
|
+
parts: {
|
|
6487
|
+
label: "Spoken Parts",
|
|
6488
|
+
descriptor: {
|
|
6489
|
+
kind: "object",
|
|
6490
|
+
array: { min: 1, max: 200 },
|
|
6491
|
+
fields: {
|
|
6492
|
+
text: { label: "Text", kind: "text", maxLength: GEMINI_TTS_TEXT_MAX },
|
|
6493
|
+
speaker: { label: "Speaker", kind: "text", required: false },
|
|
6494
|
+
...directable ? { style: { label: "Style", kind: "text", maxLength: GEMINI_TTS_STYLE_MAX, required: false } } : {}
|
|
6495
|
+
}
|
|
6496
|
+
}
|
|
6497
|
+
},
|
|
6498
|
+
// Worker `SpeakerVoiceConfigDto[]`, max 2. Replaces `voiceId`. The voice is
|
|
6499
|
+
// a plain id, not a catalog picker: catalog loading resolves top-level params
|
|
6500
|
+
// only, so a caller lists voices with `ai.catalogs.voices(<model>)`.
|
|
6501
|
+
multiSpeakerVoiceConfigs: {
|
|
6502
|
+
label: "Speakers",
|
|
6503
|
+
descriptor: {
|
|
6504
|
+
kind: "object",
|
|
6505
|
+
array: { min: 1, max: 2 },
|
|
6506
|
+
fields: {
|
|
6507
|
+
speaker: { label: "Speaker", kind: "text", placeholder: "Speaker 1" },
|
|
6508
|
+
voiceName: { label: "Voice", kind: "text", placeholder: GEMINI_DEFAULT_VOICE_ID }
|
|
6509
|
+
}
|
|
6510
|
+
}
|
|
6511
|
+
}
|
|
6512
|
+
});
|
|
6472
6513
|
var GEMINI_AR_WIDE = ["1:1", "16:9", "9:16", "3:4", "4:3", "2:3", "21:9", "auto"];
|
|
6473
6514
|
var thinkingLevelParam = {
|
|
6474
6515
|
thinkingLevel: {
|
|
@@ -6586,32 +6627,35 @@ var { MODELS: MODELS22 } = defineModels("google", [
|
|
|
6586
6627
|
}
|
|
6587
6628
|
},
|
|
6588
6629
|
// ── Audio ─────────────────────────────────────────────────────────
|
|
6630
|
+
// Payload builders live in gemini.payloads.ts (typed against ModelInput).
|
|
6631
|
+
// The wire `model` is fixed per entry there: `modelId` is the pricing key and
|
|
6632
|
+
// never reaches the builder.
|
|
6633
|
+
//
|
|
6634
|
+
// 2.5 and 3.8 take direction and speakers differently, so the builders
|
|
6635
|
+
// resolve them per generation. 3.8 reads `style` and per-part speakers from
|
|
6636
|
+
// `speechMetadata` and speaks a natural-language prefix in the text aloud:
|
|
6637
|
+
// `parts` go through and `language` / `accent` fold into `style`. 2.5
|
|
6638
|
+
// ignores `speechMetadata`: it reads speakers from "Speaker: line" labels
|
|
6639
|
+
// and direction from a "Say …:" prefix, so the builder writes both into
|
|
6640
|
+
// one text.
|
|
6589
6641
|
{
|
|
6590
6642
|
id: "gemini-2.5-flash-tts",
|
|
6591
6643
|
name: "Gemini 2.5 Flash TTS",
|
|
6592
6644
|
addedAt: "2026-02-15",
|
|
6593
6645
|
workflow: "gemini/v1/audios",
|
|
6594
|
-
buildPayload: buildGeminiTTSPayload("gemini-2.5-flash-tts"),
|
|
6595
6646
|
estimatedTime: 15,
|
|
6596
6647
|
mode: "audio",
|
|
6597
6648
|
inputType: "tts",
|
|
6598
6649
|
modelId: "gemini-2.5-flash-tts",
|
|
6599
6650
|
description: "Google Gemini native text-to-speech with expressive multilingual voices.",
|
|
6600
|
-
features: [feat("Multilingual", "characteristic"), feat("30 Voices", "characteristic")],
|
|
6601
|
-
paramConfig:
|
|
6602
|
-
...params.language(true),
|
|
6603
|
-
// 6,000 boundary-verified against the live gemini/v1/audios worker
|
|
6604
|
-
// (accepts >5,000; see scripts/api-tests/audio-charlimit-boundary-probe.mjs).
|
|
6605
|
-
...params.prompt({ maxLength: 6e3 }),
|
|
6606
|
-
...params.voiceId([], GEMINI_DEFAULT_VOICE_ID, { catalog: { workflow: "gemini/v1/catalog/voices" } })
|
|
6607
|
-
}
|
|
6651
|
+
features: [feat("Multilingual", "characteristic"), feat("30 Voices", "characteristic"), feat("Multi-Speaker", "characteristic")],
|
|
6652
|
+
paramConfig: geminiTtsParams(false)
|
|
6608
6653
|
},
|
|
6609
6654
|
{
|
|
6610
6655
|
id: "gemini-2.5-pro-tts",
|
|
6611
6656
|
name: "Gemini 2.5 Pro TTS",
|
|
6612
6657
|
addedAt: "2026-03-18",
|
|
6613
6658
|
workflow: "gemini/v1/audios",
|
|
6614
|
-
buildPayload: buildGeminiTTSPayload("gemini-2.5-pro-tts"),
|
|
6615
6659
|
estimatedTime: 20,
|
|
6616
6660
|
mode: "audio",
|
|
6617
6661
|
inputType: "tts",
|
|
@@ -6619,54 +6663,34 @@ var { MODELS: MODELS22 } = defineModels("google", [
|
|
|
6619
6663
|
badge: ["premium"],
|
|
6620
6664
|
description: "Premium Gemini TTS with richer expressiveness and multi-speaker support.",
|
|
6621
6665
|
features: [feat("Multilingual", "characteristic"), feat("30 Voices", "characteristic"), feat("Multi-Speaker", "characteristic")],
|
|
6622
|
-
paramConfig:
|
|
6623
|
-
...params.language(true),
|
|
6624
|
-
// 6,000 boundary-verified against the live gemini/v1/audios worker
|
|
6625
|
-
// (accepts >5,000; see scripts/api-tests/audio-charlimit-boundary-probe.mjs).
|
|
6626
|
-
...params.prompt({ maxLength: 6e3 }),
|
|
6627
|
-
...params.voiceId([], GEMINI_DEFAULT_VOICE_ID, { catalog: { workflow: "gemini/v1/catalog/voices" } })
|
|
6628
|
-
}
|
|
6666
|
+
paramConfig: geminiTtsParams(false)
|
|
6629
6667
|
},
|
|
6630
6668
|
{
|
|
6631
6669
|
id: "gemini-3.8-flash-tts",
|
|
6632
6670
|
name: "Gemini 3.8 Flash TTS",
|
|
6633
6671
|
addedAt: "2026-09-24",
|
|
6634
6672
|
workflow: "gemini/v1/audios",
|
|
6635
|
-
buildPayload: buildGeminiTTSPayload("gemini-3.8-flash-tts"),
|
|
6636
6673
|
estimatedTime: 15,
|
|
6637
6674
|
mode: "audio",
|
|
6638
6675
|
inputType: "tts",
|
|
6639
6676
|
modelId: "gemini-3.8-flash-tts",
|
|
6640
|
-
description: "Latest Gemini native text-to-speech with
|
|
6641
|
-
features: [feat("Multilingual", "characteristic"), feat("30 Voices", "characteristic")],
|
|
6642
|
-
paramConfig:
|
|
6643
|
-
...params.language(true),
|
|
6644
|
-
// 6,000 boundary-verified against the live gemini/v1/audios worker
|
|
6645
|
-
// (accepts >5,000; see scripts/api-tests/audio-charlimit-boundary-probe.mjs).
|
|
6646
|
-
...params.prompt({ maxLength: 6e3 }),
|
|
6647
|
-
...params.voiceId([], GEMINI_DEFAULT_VOICE_ID, { catalog: { workflow: "gemini/v1/catalog/voices" } })
|
|
6648
|
-
}
|
|
6677
|
+
description: "Latest Gemini native text-to-speech with directable delivery and inline vocal events like <laugh> and <sigh>.",
|
|
6678
|
+
features: [feat("Multilingual", "characteristic"), feat("30 Voices", "characteristic"), feat("Multi-Speaker", "characteristic"), feat("Style Direction", "characteristic")],
|
|
6679
|
+
paramConfig: geminiTtsParams(true)
|
|
6649
6680
|
},
|
|
6650
6681
|
{
|
|
6651
6682
|
id: "gemini-3.8-flash-lite-tts",
|
|
6652
6683
|
name: "Gemini 3.8 Flash Lite TTS",
|
|
6653
6684
|
addedAt: "2026-09-24",
|
|
6654
6685
|
workflow: "gemini/v1/audios",
|
|
6655
|
-
buildPayload: buildGeminiTTSPayload("gemini-3.8-flash-lite-tts"),
|
|
6656
6686
|
estimatedTime: 12,
|
|
6657
6687
|
mode: "audio",
|
|
6658
6688
|
inputType: "tts",
|
|
6659
6689
|
modelId: "gemini-3.8-flash-lite-tts",
|
|
6660
6690
|
badge: ["fast"],
|
|
6661
|
-
description: "Lightweight Gemini 3.8 TTS
|
|
6662
|
-
features: [feat("Multilingual", "characteristic"), feat("30 Voices", "characteristic")],
|
|
6663
|
-
paramConfig:
|
|
6664
|
-
...params.language(true),
|
|
6665
|
-
// 6,000 boundary-verified against the live gemini/v1/audios worker
|
|
6666
|
-
// (accepts >5,000; see scripts/api-tests/audio-charlimit-boundary-probe.mjs).
|
|
6667
|
-
...params.prompt({ maxLength: 6e3 }),
|
|
6668
|
-
...params.voiceId([], GEMINI_DEFAULT_VOICE_ID, { catalog: { workflow: "gemini/v1/catalog/voices" } })
|
|
6669
|
-
}
|
|
6691
|
+
description: "Lightweight Gemini 3.8 TTS with directable delivery for faster, high-volume speech synthesis.",
|
|
6692
|
+
features: [feat("Multilingual", "characteristic"), feat("30 Voices", "characteristic"), feat("Multi-Speaker", "characteristic"), feat("Style Direction", "characteristic")],
|
|
6693
|
+
paramConfig: geminiTtsParams(true)
|
|
6670
6694
|
},
|
|
6671
6695
|
// ── Video ─────────────────────────────────────────────────────────
|
|
6672
6696
|
{
|
|
@@ -6733,8 +6757,95 @@ var buildOmniFlash11Payload = (input) => ({
|
|
|
6733
6757
|
...input.videoUrl ? { video: { url: input.videoUrl } } : {},
|
|
6734
6758
|
...input.videoUrls?.length ? { referenceVideos: input.videoUrls.map((url) => ({ url })) } : {}
|
|
6735
6759
|
});
|
|
6760
|
+
var STYLE_MAX = 500;
|
|
6761
|
+
var TEXT_MAX = 6e3;
|
|
6762
|
+
var invalid = (message) => new ApiError(message, { status: 400, code: "validation_error" });
|
|
6763
|
+
var blank = (value) => !value?.trim();
|
|
6764
|
+
function checkInput(input) {
|
|
6765
|
+
const configs = input.multiSpeakerVoiceConfigs ?? [];
|
|
6766
|
+
for (const [i, config] of configs.entries()) {
|
|
6767
|
+
if (blank(config.speaker)) throw invalid(`Gemini TTS: speaker config ${i + 1} has no speaker.`);
|
|
6768
|
+
if (blank(config.voiceName)) throw invalid(`Gemini TTS: speaker config ${i + 1} has no voiceName.`);
|
|
6769
|
+
}
|
|
6770
|
+
const speakers = configs.map((config) => config.speaker);
|
|
6771
|
+
if (new Set(speakers).size !== speakers.length) {
|
|
6772
|
+
throw invalid("Gemini TTS: multiSpeakerVoiceConfigs names the same speaker twice.");
|
|
6773
|
+
}
|
|
6774
|
+
const parts = input.parts?.length ? input.parts : void 0;
|
|
6775
|
+
if (!parts) {
|
|
6776
|
+
if (blank(input.prompt)) throw invalid("Gemini TTS: provide a prompt or parts.");
|
|
6777
|
+
return { speakers };
|
|
6778
|
+
}
|
|
6779
|
+
for (const [i, part] of parts.entries()) {
|
|
6780
|
+
if (blank(part.text)) throw invalid(`Gemini TTS: part ${i + 1} has no text.`);
|
|
6781
|
+
if (speakers.length && (!part.speaker || !speakers.includes(part.speaker))) {
|
|
6782
|
+
throw invalid(
|
|
6783
|
+
`Gemini TTS: part ${i + 1} needs a speaker from multiSpeakerVoiceConfigs (${speakers.join(", ")}).`
|
|
6784
|
+
);
|
|
6785
|
+
}
|
|
6786
|
+
if (!speakers.length && part.speaker) {
|
|
6787
|
+
throw invalid(`Gemini TTS: part ${i + 1} names a speaker but no multiSpeakerVoiceConfigs are set.`);
|
|
6788
|
+
}
|
|
6789
|
+
}
|
|
6790
|
+
return { parts, speakers };
|
|
6791
|
+
}
|
|
6792
|
+
function assertLength(spoken) {
|
|
6793
|
+
if (spoken.length > TEXT_MAX) {
|
|
6794
|
+
throw invalid(`Gemini TTS: the text totals ${spoken.length} characters; the limit is ${TEXT_MAX}.`);
|
|
6795
|
+
}
|
|
6796
|
+
}
|
|
6797
|
+
var voiceFields = (input) => input.multiSpeakerVoiceConfigs?.length ? { multiSpeakerVoiceConfigs: input.multiSpeakerVoiceConfigs } : { voiceName: input.voiceId ?? GEMINI_DEFAULT_VOICE_ID };
|
|
6798
|
+
function composeStyle(input) {
|
|
6799
|
+
const language = input.language?.trim();
|
|
6800
|
+
const accent = input.accent?.trim();
|
|
6801
|
+
const voice = language || accent ? `speak${language ? ` in ${language}` : ""}${accent ? ` with a ${accent} accent` : ""}` : void 0;
|
|
6802
|
+
const composed = [...input.styles.map((style) => style?.trim()), voice].filter(Boolean).join("; ") || void 0;
|
|
6803
|
+
if (composed && composed.length > STYLE_MAX) {
|
|
6804
|
+
throw invalid(`Gemini TTS: style with language/accent exceeds ${STYLE_MAX} characters.`);
|
|
6805
|
+
}
|
|
6806
|
+
return composed;
|
|
6807
|
+
}
|
|
6808
|
+
function directionPrefix(input) {
|
|
6809
|
+
const language = input.language?.trim();
|
|
6810
|
+
const accent = input.accent?.trim();
|
|
6811
|
+
if (!language && !accent) return "";
|
|
6812
|
+
return `Say${language ? ` in ${language}` : ""}${accent ? ` with a ${accent} accent` : ""}: `;
|
|
6813
|
+
}
|
|
6814
|
+
var buildTts25Payload = (model) => (input) => {
|
|
6815
|
+
const { parts, speakers } = checkInput(input);
|
|
6816
|
+
const body = parts ? parts.map((part) => speakers.length ? `${part.speaker}: ${part.text}` : part.text).join("\n") : input.prompt;
|
|
6817
|
+
const text = `${directionPrefix(input)}${body}`;
|
|
6818
|
+
assertLength(text);
|
|
6819
|
+
return { text, model, ...voiceFields(input) };
|
|
6820
|
+
};
|
|
6821
|
+
var buildTts38Payload = (model) => (input) => {
|
|
6822
|
+
const { parts } = checkInput(input);
|
|
6823
|
+
const direction = { language: input.language, accent: input.accent };
|
|
6824
|
+
if (!parts) {
|
|
6825
|
+
assertLength(input.prompt);
|
|
6826
|
+
const style = composeStyle({ styles: [input.style], ...direction });
|
|
6827
|
+
return { text: input.prompt, model, ...voiceFields(input), ...style ? { style } : {} };
|
|
6828
|
+
}
|
|
6829
|
+
assertLength(parts.map((part) => part.text).join("\n"));
|
|
6830
|
+
return {
|
|
6831
|
+
parts: parts.map((part) => {
|
|
6832
|
+
const style = composeStyle({ styles: [input.style, part.style], ...direction });
|
|
6833
|
+
return {
|
|
6834
|
+
text: part.text,
|
|
6835
|
+
...part.speaker ? { speaker: part.speaker } : {},
|
|
6836
|
+
...style ? { style } : {}
|
|
6837
|
+
};
|
|
6838
|
+
}),
|
|
6839
|
+
model,
|
|
6840
|
+
...voiceFields(input)
|
|
6841
|
+
};
|
|
6842
|
+
};
|
|
6736
6843
|
registerPayloads(MODELS22, {
|
|
6737
|
-
"gemini-omni-1.1-flash-preview": buildOmniFlash11Payload
|
|
6844
|
+
"gemini-omni-1.1-flash-preview": buildOmniFlash11Payload,
|
|
6845
|
+
"gemini-2.5-flash-tts": buildTts25Payload("gemini-2.5-flash-tts"),
|
|
6846
|
+
"gemini-2.5-pro-tts": buildTts25Payload("gemini-2.5-pro-tts"),
|
|
6847
|
+
"gemini-3.8-flash-tts": buildTts38Payload("gemini-3.8-flash-tts"),
|
|
6848
|
+
"gemini-3.8-flash-lite-tts": buildTts38Payload("gemini-3.8-flash-lite-tts")
|
|
6738
6849
|
});
|
|
6739
6850
|
|
|
6740
6851
|
// src/vendors/catalog/openai.ts
|