vidspotai-shared 1.0.95 → 1.0.97
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/lib/globals/aiModels/enums.d.ts +3 -0
- package/lib/globals/aiModels/enums.d.ts.map +1 -1
- package/lib/globals/aiModels/enums.js +9 -0
- package/lib/globals/aiModels/index.d.ts.map +1 -1
- package/lib/globals/aiModels/index.js +2 -0
- package/lib/globals/aiModels/providers/hostedAvatars.d.ts +22 -0
- package/lib/globals/aiModels/providers/hostedAvatars.d.ts.map +1 -0
- package/lib/globals/aiModels/providers/hostedAvatars.js +129 -0
- package/lib/globals/aiModels/providers/kling.d.ts.map +1 -1
- package/lib/globals/aiModels/providers/kling.js +85 -1
- package/lib/globals/creditUnit.d.ts +29 -0
- package/lib/globals/creditUnit.d.ts.map +1 -1
- package/lib/globals/creditUnit.js +30 -1
- package/lib/globals/types.d.ts +58 -1
- package/lib/globals/types.d.ts.map +1 -1
- package/lib/globals/types.js +61 -1
- package/lib/models/demoVideoProject.model.d.ts +244 -0
- package/lib/models/demoVideoProject.model.d.ts.map +1 -0
- package/lib/models/demoVideoProject.model.js +2 -0
- package/lib/models/githubConnection.model.d.ts +35 -0
- package/lib/models/githubConnection.model.d.ts.map +1 -0
- package/lib/models/githubConnection.model.js +2 -0
- package/lib/models/index.d.ts +3 -0
- package/lib/models/index.d.ts.map +1 -1
- package/lib/models/index.js +3 -0
- package/lib/models/outreach.model.d.ts +175 -0
- package/lib/models/outreach.model.d.ts.map +1 -0
- package/lib/models/outreach.model.js +2 -0
- package/lib/models/video.model.d.ts +4 -0
- package/lib/models/video.model.d.ts.map +1 -1
- package/lib/schemas/brandKit.schema.d.ts +4 -0
- package/lib/schemas/brandKit.schema.d.ts.map +1 -1
- package/lib/schemas/brandKit.schema.js +10 -0
- package/lib/schemas/demoQuestion.schema.d.ts +286 -0
- package/lib/schemas/demoQuestion.schema.d.ts.map +1 -0
- package/lib/schemas/demoQuestion.schema.js +210 -0
- package/lib/schemas/demoSpec.schema.d.ts +109 -6
- package/lib/schemas/demoSpec.schema.d.ts.map +1 -1
- package/lib/schemas/demoSpec.schema.js +95 -7
- package/lib/schemas/index.d.ts +1 -0
- package/lib/schemas/index.d.ts.map +1 -1
- package/lib/schemas/index.js +1 -0
- package/lib/services/agent/providerFallback/chains.d.ts.map +1 -1
- package/lib/services/agent/providerFallback/chains.js +9 -1
- package/lib/services/agent/taskPoller.d.ts.map +1 -1
- package/lib/services/agent/taskPoller.js +17 -6
- package/lib/services/agent/tools/generateAvatarVideo.tool.d.ts +21 -9
- package/lib/services/agent/tools/generateAvatarVideo.tool.d.ts.map +1 -1
- package/lib/services/agent/tools/generateAvatarVideo.tool.js +135 -39
- package/lib/services/aiGen/aiGenFactory.service.d.ts +1 -1
- package/lib/services/aiGen/aiGenFactory.service.d.ts.map +1 -1
- package/lib/services/aiGen/aiGenFactory.service.js +11 -2
- package/lib/services/aiGen/providers/kling/kling.service.d.ts +36 -1
- package/lib/services/aiGen/providers/kling/kling.service.d.ts.map +1 -1
- package/lib/services/aiGen/providers/kling/kling.service.js +62 -5
- package/lib/services/aiGen/providers/kling/klingCredits.d.ts.map +1 -1
- package/lib/services/aiGen/providers/kling/klingCredits.js +12 -0
- package/lib/services/aiGen/providers/kling/klingRequests.d.ts +14 -1
- package/lib/services/aiGen/providers/kling/klingRequests.d.ts.map +1 -1
- package/lib/services/aiGen/providers/kling/klingRequests.js +44 -0
- package/lib/services/aiGen/providers/kling/klingStatus.d.ts +13 -1
- package/lib/services/aiGen/providers/kling/klingStatus.d.ts.map +1 -1
- package/lib/services/aiGen/providers/kling/klingStatus.js +111 -0
- package/lib/services/aiGen/providers/kling/types.d.ts +71 -0
- package/lib/services/aiGen/providers/kling/types.d.ts.map +1 -1
- package/lib/services/avatarGen/IAvatarVideoProvider.d.ts +136 -0
- package/lib/services/avatarGen/IAvatarVideoProvider.d.ts.map +1 -0
- package/lib/services/avatarGen/IAvatarVideoProvider.js +42 -0
- package/lib/services/avatarGen/avatarProviderFactory.d.ts +18 -0
- package/lib/services/avatarGen/avatarProviderFactory.d.ts.map +1 -0
- package/lib/services/avatarGen/avatarProviderFactory.js +54 -0
- package/lib/services/avatarGen/index.d.ts +6 -0
- package/lib/services/avatarGen/index.d.ts.map +1 -0
- package/lib/services/avatarGen/index.js +21 -0
- package/lib/services/avatarGen/providers/heygenAvatarProvider.d.ts +45 -0
- package/lib/services/avatarGen/providers/heygenAvatarProvider.d.ts.map +1 -0
- package/lib/services/avatarGen/providers/heygenAvatarProvider.js +190 -0
- package/lib/services/avatarGen/providers/klingAvatarProvider.d.ts +32 -0
- package/lib/services/avatarGen/providers/klingAvatarProvider.d.ts.map +1 -0
- package/lib/services/avatarGen/providers/klingAvatarProvider.js +69 -0
- package/lib/services/avatarGen/providers/tavusAvatarProvider.d.ts +56 -0
- package/lib/services/avatarGen/providers/tavusAvatarProvider.d.ts.map +1 -0
- package/lib/services/avatarGen/providers/tavusAvatarProvider.js +183 -0
- package/lib/services/demo/demoAuthor.d.ts +45 -0
- package/lib/services/demo/demoAuthor.d.ts.map +1 -0
- package/lib/services/demo/demoAuthor.js +75 -0
- package/lib/services/demo/demoAuthorNormalize.d.ts +49 -0
- package/lib/services/demo/demoAuthorNormalize.d.ts.map +1 -0
- package/lib/services/demo/demoAuthorNormalize.js +327 -0
- package/lib/services/demo/demoAuthorPrompt.d.ts +102 -0
- package/lib/services/demo/demoAuthorPrompt.d.ts.map +1 -0
- package/lib/services/demo/demoAuthorPrompt.js +243 -0
- package/lib/services/demo/demoCredits.d.ts +20 -0
- package/lib/services/demo/demoCredits.d.ts.map +1 -0
- package/lib/services/demo/demoCredits.js +51 -0
- package/lib/services/demo/demoMediaGuard.d.ts +43 -0
- package/lib/services/demo/demoMediaGuard.d.ts.map +1 -0
- package/lib/services/demo/demoMediaGuard.js +207 -0
- package/lib/services/demo/demoMusic.d.ts +13 -0
- package/lib/services/demo/demoMusic.d.ts.map +1 -0
- package/lib/services/demo/demoMusic.js +93 -0
- package/lib/services/demo/demoPrefill.d.ts +76 -0
- package/lib/services/demo/demoPrefill.d.ts.map +1 -0
- package/lib/services/demo/demoPrefill.js +435 -0
- package/lib/services/demo/demoRevisePrompt.d.ts +17 -0
- package/lib/services/demo/demoRevisePrompt.d.ts.map +1 -0
- package/lib/services/demo/demoRevisePrompt.js +85 -0
- package/lib/services/demo/demoReviser.d.ts +63 -0
- package/lib/services/demo/demoReviser.d.ts.map +1 -0
- package/lib/services/demo/demoReviser.js +81 -0
- package/lib/services/demo/demoScriptPrompt.d.ts +63 -0
- package/lib/services/demo/demoScriptPrompt.d.ts.map +1 -0
- package/lib/services/demo/demoScriptPrompt.js +234 -0
- package/lib/services/demo/demoScriptWriter.d.ts +65 -0
- package/lib/services/demo/demoScriptWriter.d.ts.map +1 -0
- package/lib/services/demo/demoScriptWriter.js +211 -0
- package/lib/services/demo/demoTriage.d.ts +65 -0
- package/lib/services/demo/demoTriage.d.ts.map +1 -0
- package/lib/services/demo/demoTriage.js +130 -0
- package/lib/services/demo/githubOAuth.d.ts +78 -0
- package/lib/services/demo/githubOAuth.d.ts.map +1 -0
- package/lib/services/demo/githubOAuth.js +209 -0
- package/lib/services/demo/githubOAuthState.d.ts +10 -0
- package/lib/services/demo/githubOAuthState.d.ts.map +1 -0
- package/lib/services/demo/githubOAuthState.js +63 -0
- package/lib/services/demo/index.d.ts +24 -0
- package/lib/services/demo/index.d.ts.map +1 -0
- package/lib/services/demo/index.js +39 -0
- package/lib/services/firestore.service.d.ts +11 -0
- package/lib/services/firestore.service.d.ts.map +1 -1
- package/lib/services/firestore.service.js +24 -0
- package/lib/services/index.d.ts +2 -0
- package/lib/services/index.d.ts.map +1 -1
- package/lib/services/index.js +2 -0
- package/lib/services/tts/providers/elevenlabs.service.d.ts.map +1 -1
- package/lib/services/tts/providers/elevenlabs.service.js +16 -8
- package/lib/utils/index.d.ts +1 -0
- package/lib/utils/index.d.ts.map +1 -1
- package/lib/utils/index.js +1 -0
- package/lib/utils/outreachTemplate.d.ts +46 -0
- package/lib/utils/outreachTemplate.d.ts.map +1 -0
- package/lib/utils/outreachTemplate.js +174 -0
- package/package.json +1 -1
|
@@ -4,79 +4,177 @@ exports.generateAvatarVideoTool = void 0;
|
|
|
4
4
|
const zod_1 = require("zod");
|
|
5
5
|
const aiModels_1 = require("../../../globals/aiModels");
|
|
6
6
|
const firebase_1 = require("../../../libs/firebase");
|
|
7
|
-
const
|
|
7
|
+
const avatarProviderFactory_1 = require("../../avatarGen/avatarProviderFactory");
|
|
8
8
|
const types_1 = require("../../aiGen/types");
|
|
9
9
|
const rateLimiter_1 = require("../../rateLimiter");
|
|
10
10
|
const ttsFactory_service_1 = require("../../tts/ttsFactory.service");
|
|
11
11
|
const toolRegistry_1 = require("../toolRegistry");
|
|
12
12
|
/**
|
|
13
|
-
* generate_avatar_video —
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
* before handing off, since Kling avatar requires a public sound_file URL).
|
|
13
|
+
* generate_avatar_video — drives avatar generation through the dedicated avatar
|
|
14
|
+
* provider seam (getAvatarVideoProvider / IAvatarVideoProvider), so the planner's
|
|
15
|
+
* `talking-head-avatar` scene strategy is executable. Avatar gen is handled by
|
|
16
|
+
* the avatar provider — NOT the generic video-gen provider. Two engine families:
|
|
18
17
|
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
18
|
+
* - byo-media (default kling-avatar): caller supplies a presenter face image
|
|
19
|
+
* plus either a pre-uploaded audio URL or raw TTS text (the tool synthesizes
|
|
20
|
+
* via ElevenLabs + uploads to GCS first, since the engine needs a public
|
|
21
|
+
* audio URL).
|
|
22
|
+
* - hosted (heygen-avatar / tavus-avatar, via `model`): caller supplies a
|
|
23
|
+
* provider-hosted avatar id + a script; the engine runs its own TTS/lipsync,
|
|
24
|
+
* so the tool does NO TTS and passes no audio.
|
|
25
|
+
*
|
|
26
|
+
* Returns a provider task id; the executor's TaskPoller polls completion — it
|
|
27
|
+
* routes hosted models through the avatar seam and everything else through the
|
|
28
|
+
* generic video factory, so this works for both families.
|
|
21
29
|
*/
|
|
22
30
|
const InputSchema = zod_1.z
|
|
23
31
|
.object({
|
|
32
|
+
model: zod_1.z
|
|
33
|
+
.nativeEnum(aiModels_1.EVideoGenModels)
|
|
34
|
+
.optional()
|
|
35
|
+
.describe("Avatar engine. Default kling-avatar (byo-media: animate a face image). heygen-avatar / tavus-avatar are hosted (animate a provider-hosted avatar + native TTS)."),
|
|
24
36
|
inputImageUrl: zod_1.z
|
|
25
37
|
.string()
|
|
26
38
|
.url()
|
|
27
|
-
.
|
|
39
|
+
.optional()
|
|
40
|
+
.describe("byo-media: presenter face still the engine animates to lipsync the audio. Required for byo-media; omit for hosted."),
|
|
41
|
+
hostedAvatarId: zod_1.z
|
|
42
|
+
.string()
|
|
43
|
+
.optional()
|
|
44
|
+
.describe("hosted: provider-hosted avatar id (HeyGen) or replica_id (Tavus) to animate. Required for hosted engines."),
|
|
45
|
+
hostedVoiceId: zod_1.z
|
|
46
|
+
.string()
|
|
47
|
+
.optional()
|
|
48
|
+
.describe("hosted: provider-hosted voice id (HeyGen). Unused for Tavus (the replica owns its voice)."),
|
|
28
49
|
ttsText: zod_1.z
|
|
29
50
|
.string()
|
|
30
51
|
.min(1)
|
|
31
52
|
.optional()
|
|
32
|
-
.describe("VO line
|
|
53
|
+
.describe("VO line / script. byo-media: synthesized to audio (or use inputAudioUrl; if both set, inputAudioUrl wins). hosted: spoken natively by the engine (required)."),
|
|
33
54
|
inputAudioUrl: zod_1.z
|
|
34
55
|
.string()
|
|
35
56
|
.url()
|
|
36
57
|
.optional()
|
|
37
|
-
.describe("
|
|
58
|
+
.describe("byo-media only: pre-uploaded audio URL (mp3/wav). Skips internal TTS+upload."),
|
|
38
59
|
voiceId: zod_1.z.string().optional(),
|
|
39
60
|
languageCode: zod_1.z.string().optional(),
|
|
40
61
|
mode: zod_1.z.enum(["std", "pro"]).default("std"),
|
|
41
62
|
prompt: zod_1.z
|
|
42
63
|
.string()
|
|
43
64
|
.optional()
|
|
44
|
-
.describe("
|
|
65
|
+
.describe("byo-media only: optional motion/emotion hint passed through to the engine."),
|
|
45
66
|
})
|
|
46
67
|
.superRefine((v, ctx) => {
|
|
47
|
-
if (
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
68
|
+
if (v.model && (0, avatarProviderFactory_1.isHostedAvatarModel)(v.model)) {
|
|
69
|
+
if (!v.hostedAvatarId) {
|
|
70
|
+
ctx.addIssue({
|
|
71
|
+
code: zod_1.z.ZodIssueCode.custom,
|
|
72
|
+
message: "hostedAvatarId is required for hosted avatar engines.",
|
|
73
|
+
path: ["hostedAvatarId"],
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
if (!v.ttsText) {
|
|
77
|
+
ctx.addIssue({
|
|
78
|
+
code: zod_1.z.ZodIssueCode.custom,
|
|
79
|
+
message: "ttsText (the script) is required for hosted avatar engines.",
|
|
80
|
+
path: ["ttsText"],
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
if (!v.inputImageUrl) {
|
|
86
|
+
ctx.addIssue({
|
|
87
|
+
code: zod_1.z.ZodIssueCode.custom,
|
|
88
|
+
message: "inputImageUrl is required for byo-media avatar engines.",
|
|
89
|
+
path: ["inputImageUrl"],
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
if (!v.ttsText && !v.inputAudioUrl) {
|
|
93
|
+
ctx.addIssue({
|
|
94
|
+
code: zod_1.z.ZodIssueCode.custom,
|
|
95
|
+
message: "Either ttsText or inputAudioUrl is required.",
|
|
96
|
+
});
|
|
97
|
+
}
|
|
52
98
|
}
|
|
53
99
|
});
|
|
54
100
|
const OutputSchema = zod_1.z.object({
|
|
55
101
|
status: zod_1.z.literal("triggered"),
|
|
56
102
|
taskId: zod_1.z.string(),
|
|
57
|
-
audioUrl: zod_1.z
|
|
103
|
+
audioUrl: zod_1.z
|
|
104
|
+
.string()
|
|
105
|
+
.url()
|
|
106
|
+
.optional()
|
|
107
|
+
.describe("byo-media: audio URL fed to the engine — host can reuse for caption sync. Absent for hosted engines (native TTS)."),
|
|
58
108
|
});
|
|
59
109
|
exports.generateAvatarVideoTool = {
|
|
60
110
|
name: "generate_avatar_video",
|
|
61
111
|
description: [
|
|
62
|
-
"Generate a talking-head avatar video
|
|
63
|
-
"
|
|
112
|
+
"Generate a talking-head avatar video that lipsyncs a voiceover. Routed",
|
|
113
|
+
"through the dedicated avatar provider seam. Two engine families: byo-media",
|
|
114
|
+
"(default kling-avatar) animates a presenter face still you supply; hosted",
|
|
115
|
+
"(heygen-avatar / tavus-avatar, via `model`) animates a provider-hosted",
|
|
116
|
+
"avatar and runs its own TTS from a script.",
|
|
64
117
|
"Use this for the `talking-head-avatar` scene strategy. Do NOT use it for",
|
|
65
118
|
"general motion shots — generate_video is cheaper and more flexible there.",
|
|
66
119
|
"Examples:",
|
|
67
120
|
' { inputImageUrl: "https://.../face.png", ttsText: "Hi, today we\'re testing the new serum." }',
|
|
68
121
|
' { inputImageUrl: "https://.../face.png", inputAudioUrl: "https://.../vo.mp3", mode: "pro" }',
|
|
122
|
+
' { model: "heygen-avatar", hostedAvatarId: "Daisy-inskirt-20220818", hostedVoiceId: "2d5b0e6cf36f460aa7fc47e3eee4ba54", ttsText: "Welcome back!" }',
|
|
69
123
|
].join(" "),
|
|
70
124
|
inputSchema: InputSchema,
|
|
71
125
|
outputSchema: OutputSchema,
|
|
72
126
|
idempotent: false,
|
|
73
127
|
estimateCost: async (input) => {
|
|
74
|
-
//
|
|
128
|
+
// Without a length we assume 6s (typical scene).
|
|
75
129
|
const approxSec = input.ttsText ? Math.max(2, Math.ceil(input.ttsText.length / 15)) : 6;
|
|
130
|
+
const modelKey = input.model ?? aiModels_1.EVideoGenModels.KLING_AVATAR;
|
|
131
|
+
if ((0, avatarProviderFactory_1.isHostedAvatarModel)(modelKey)) {
|
|
132
|
+
// Hosted engines bill per generated MINUTE (min 1 minute).
|
|
133
|
+
const perMinute = aiModels_1.aiModelConfigs[modelKey]?.cost?.perMinute ?? 0.5;
|
|
134
|
+
const billedMinutes = Math.max(1, Math.ceil(approxSec / 60));
|
|
135
|
+
return Math.ceil(perMinute * billedMinutes * 100); // rough credit conversion
|
|
136
|
+
}
|
|
137
|
+
// byo-media (Kling) bills per audio second.
|
|
76
138
|
const perSec = input.mode === "pro" ? 0.028 : 0.014;
|
|
77
|
-
return Math.ceil(approxSec * perSec * 100);
|
|
139
|
+
return Math.ceil(approxSec * perSec * 100);
|
|
78
140
|
},
|
|
79
141
|
handler: async (input, ctx) => {
|
|
142
|
+
const modelKey = input.model ?? aiModels_1.EVideoGenModels.KLING_AVATAR;
|
|
143
|
+
const renderMode = input.mode === "pro" ? types_1.EVideoMode.PROFESSIONAL : types_1.EVideoMode.STANDARD;
|
|
144
|
+
// ── Hosted engines (HeyGen/Tavus) ────────────────────────────────────────
|
|
145
|
+
// The engine does its own TTS + lipsync from the script, so there's no TTS
|
|
146
|
+
// synthesis / GCS upload here. Submit and hand the task id to the poller,
|
|
147
|
+
// which routes hosted models through the avatar seam.
|
|
148
|
+
if ((0, avatarProviderFactory_1.isHostedAvatarModel)(modelKey)) {
|
|
149
|
+
const limiter = (0, rateLimiter_1.getAiGenModelRateLimiter)(modelKey);
|
|
150
|
+
await limiter.waitUntilAvailable();
|
|
151
|
+
let heldSlot = true;
|
|
152
|
+
try {
|
|
153
|
+
const provider = (0, avatarProviderFactory_1.getAvatarVideoProvider)(modelKey);
|
|
154
|
+
const result = await provider.generate({
|
|
155
|
+
mode: "hosted",
|
|
156
|
+
hostedAvatarId: input.hostedAvatarId,
|
|
157
|
+
hostedVoiceId: input.hostedVoiceId ?? "",
|
|
158
|
+
script: input.ttsText,
|
|
159
|
+
locale: input.languageCode,
|
|
160
|
+
renderMode,
|
|
161
|
+
});
|
|
162
|
+
const taskId = result.providerTaskId?.taskId ??
|
|
163
|
+
result.providerTaskId?.id ??
|
|
164
|
+
(typeof result.providerTaskId === "string" ? result.providerTaskId : "unknown");
|
|
165
|
+
if (taskId === "unknown") {
|
|
166
|
+
limiter.releaseSlot();
|
|
167
|
+
heldSlot = false;
|
|
168
|
+
}
|
|
169
|
+
return { status: "triggered", taskId };
|
|
170
|
+
}
|
|
171
|
+
catch (err) {
|
|
172
|
+
if (heldSlot)
|
|
173
|
+
limiter.releaseSlot();
|
|
174
|
+
throw err;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
// ── byo-media engines (Kling) ─────────────────────────────────────────────
|
|
80
178
|
let audioUrl = input.inputAudioUrl;
|
|
81
179
|
if (!audioUrl) {
|
|
82
180
|
const ttsLimiter = (0, rateLimiter_1.getTtsProviderRateLimiter)("elevenlabs");
|
|
@@ -100,29 +198,27 @@ exports.generateAvatarVideoTool = {
|
|
|
100
198
|
const [signedUrl] = await file.getSignedUrl({ action: "read", expires: "03-09-2491" });
|
|
101
199
|
audioUrl = signedUrl;
|
|
102
200
|
}
|
|
103
|
-
// Hold the
|
|
201
|
+
// Hold the byo-media model slot through return — host's TaskPoller releases
|
|
104
202
|
// when the task settles. Release here on submit error.
|
|
105
|
-
const limiter = (0, rateLimiter_1.getAiGenModelRateLimiter)(
|
|
203
|
+
const limiter = (0, rateLimiter_1.getAiGenModelRateLimiter)(modelKey);
|
|
106
204
|
await limiter.waitUntilAvailable();
|
|
107
205
|
let heldSlot = true;
|
|
108
206
|
try {
|
|
109
|
-
|
|
110
|
-
//
|
|
111
|
-
//
|
|
112
|
-
//
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
207
|
+
// byo-media avatar request: a face still + the audio we just resolved. The
|
|
208
|
+
// avatar provider owns endpoint/type dispatch internally (Kling routes on
|
|
209
|
+
// modelKey === "kling-avatar"), so no generic-video `type` is passed here.
|
|
210
|
+
// inputImageUrl presence is guaranteed by the byo-media superRefine branch.
|
|
211
|
+
const provider = (0, avatarProviderFactory_1.getAvatarVideoProvider)(modelKey);
|
|
212
|
+
const result = await provider.generate({
|
|
213
|
+
mode: "byo-media",
|
|
214
|
+
faceImageUrl: input.inputImageUrl,
|
|
215
|
+
audioUrl,
|
|
118
216
|
prompt: input.prompt,
|
|
119
|
-
|
|
120
|
-
inputAudioUrl: audioUrl,
|
|
121
|
-
mode: input.mode === "pro" ? types_1.EVideoMode.PROFESSIONAL : types_1.EVideoMode.STANDARD,
|
|
217
|
+
renderMode,
|
|
122
218
|
});
|
|
123
|
-
const taskId = result.
|
|
124
|
-
result.
|
|
125
|
-
(typeof result.
|
|
219
|
+
const taskId = result.providerTaskId?.taskId ??
|
|
220
|
+
result.providerTaskId?.id ??
|
|
221
|
+
(typeof result.providerTaskId === "string" ? result.providerTaskId : "unknown");
|
|
126
222
|
if (taskId === "unknown") {
|
|
127
223
|
limiter.releaseSlot();
|
|
128
224
|
heldSlot = false;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { BaseAiGenProviderService } from "./providers/baseAiGenProvider.service";
|
|
2
2
|
import { EImageGenModelKey, EMusicGenModels, ESfxGenModels, ETextGenModels, EVideoGenModels, TAiGenModel } from "../../globals/aiModels";
|
|
3
3
|
type AiGenServiceConstructor = new () => BaseAiGenProviderService;
|
|
4
|
-
export declare const videoServicesMap: Record<EVideoGenModels, AiGenServiceConstructor
|
|
4
|
+
export declare const videoServicesMap: Partial<Record<EVideoGenModels, AiGenServiceConstructor>>;
|
|
5
5
|
/**
|
|
6
6
|
* Image-gen factory. Each provider service implements `generateImage()` (sync;
|
|
7
7
|
* returns a URL or base64 in a single API roundtrip — no BullMQ worker needed).
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"aiGenFactory.service.d.ts","sourceRoot":"","sources":["../../../src/services/aiGen/aiGenFactory.service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAAE,MAAM,uCAAuC,CAAC;AACjF,OAAO,EACL,iBAAiB,EAEjB,eAAe,EACf,aAAa,EACb,cAAc,EACd,eAAe,EACf,WAAW,EACZ,MAAM,wBAAwB,CAAC;AAchC,KAAK,uBAAuB,GAAG,UAAU,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"aiGenFactory.service.d.ts","sourceRoot":"","sources":["../../../src/services/aiGen/aiGenFactory.service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAAE,MAAM,uCAAuC,CAAC;AACjF,OAAO,EACL,iBAAiB,EAEjB,eAAe,EACf,aAAa,EACb,cAAc,EACd,eAAe,EACf,WAAW,EACZ,MAAM,wBAAwB,CAAC;AAchC,KAAK,uBAAuB,GAAG,UAAU,wBAAwB,CAAC;AASlE,eAAO,MAAM,gBAAgB,EAAE,OAAO,CACpC,MAAM,CAAC,eAAe,EAAE,uBAAuB,CAAC,CAgEjD,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,gBAAgB,EAAE,MAAM,CACnC,iBAAiB,EACjB,uBAAuB,CA2CxB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,gBAAgB,EAAE,MAAM,CACnC,eAAe,EACf,uBAAuB,CAMxB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,cAAc,EAAE,MAAM,CACjC,aAAa,EACb,uBAAuB,CAGxB,CAAC;AAEF,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,cAAc,EAAE,uBAAuB,CAsBzE,CAAC;AAEJ,wBAAgB,uBAAuB,CACrC,QAAQ,EAAE,WAAW,GACpB,wBAAwB,CAmB1B"}
|
|
@@ -14,6 +14,13 @@ const pixverse_service_1 = require("./providers/pixverse/pixverse.service");
|
|
|
14
14
|
const bytedance_service_1 = require("./providers/bytedance/bytedance.service");
|
|
15
15
|
const elevenlabs_service_1 = require("./providers/elevenlabs/elevenlabs.service");
|
|
16
16
|
const anthropic_service_1 = require("./providers/anthropic/anthropic.service");
|
|
17
|
+
// Partial, intentionally: hosted avatar engines (heygen-avatar, tavus-avatar)
|
|
18
|
+
// are NOT generic video models — they're handled by the dedicated avatar seam
|
|
19
|
+
// (getAvatarVideoProvider / IAvatarVideoProvider). getAiGenProviderService gates
|
|
20
|
+
// on `modelKey in videoServicesMap` and throws for anything absent, so these
|
|
21
|
+
// keys correctly resolve through the avatar factory instead. (kling-avatar stays
|
|
22
|
+
// here because KlingService still backs both its generic-credit path and the
|
|
23
|
+
// KlingAvatarProvider adapter.)
|
|
17
24
|
exports.videoServicesMap = {
|
|
18
25
|
// --- Pixverse ---
|
|
19
26
|
"pixverse-v6": pixverse_service_1.PixVerseService,
|
|
@@ -44,6 +51,7 @@ exports.videoServicesMap = {
|
|
|
44
51
|
"kling-v2.1": kling_service_1.KlingService,
|
|
45
52
|
"kling-v2.1-master": kling_service_1.KlingService,
|
|
46
53
|
"kling-v3.0": kling_service_1.KlingService,
|
|
54
|
+
"kling-v3.0-turbo": kling_service_1.KlingService,
|
|
47
55
|
"kling-avatar": kling_service_1.KlingService,
|
|
48
56
|
"kling-video-o1": kling_service_1.KlingService,
|
|
49
57
|
"kling-v3-omni-video": kling_service_1.KlingService,
|
|
@@ -157,8 +165,9 @@ exports.textServicesMap = {
|
|
|
157
165
|
// "openai-gpt-3.5-turbo": OpenaiService,
|
|
158
166
|
};
|
|
159
167
|
function getAiGenProviderService(modelKey) {
|
|
160
|
-
|
|
161
|
-
|
|
168
|
+
const VideoService = exports.videoServicesMap[modelKey];
|
|
169
|
+
if (VideoService) {
|
|
170
|
+
return new VideoService();
|
|
162
171
|
}
|
|
163
172
|
if (modelKey in exports.imageServicesMap) {
|
|
164
173
|
return new exports.imageServicesMap[modelKey]();
|
|
@@ -1,7 +1,23 @@
|
|
|
1
1
|
import { BaseAiGenProviderService } from "../baseAiGenProvider.service";
|
|
2
2
|
import { CreditUsageParams, VideoGenerationParams, VideoGenerationResult, VideoStatusParams, VideoStatusResult } from "../types";
|
|
3
3
|
/**
|
|
4
|
-
* Kling
|
|
4
|
+
* Kling runs TWO incompatible auth schemes, split by API surface. Verified
|
|
5
|
+
* against the live API 2026-07-22.
|
|
6
|
+
*
|
|
7
|
+
* "jwt" — the legacy AK/SK flow: an HS256 JWT signed per request from
|
|
8
|
+
* KLING_ACCESS_KEY + KLING_SECRET_KEY. Accepted by every
|
|
9
|
+
* /v1/videos/*, /v1/images/* and /account/* endpoint.
|
|
10
|
+
*
|
|
11
|
+
* "apiKey" — a static console-issued key sent verbatim as a bearer token,
|
|
12
|
+
* required by the API 2.0 surface (/text-to-video/*,
|
|
13
|
+
* /image-to-video/*, /tasks). Presenting a JWT there returns
|
|
14
|
+
* HTTP 401 code 1002: "The current API does not support AK/SK;
|
|
15
|
+
* please go to the console to create API key."
|
|
16
|
+
* Created at https://kling.ai/dev/api-key → env KLING_API_KEY.
|
|
17
|
+
*/
|
|
18
|
+
export type KlingAuthMode = "jwt" | "apiKey";
|
|
19
|
+
/**
|
|
20
|
+
* Kling provider. This class is the transport (auth, IPv4-pinned agents,
|
|
5
21
|
* timeout/retry) plus the per-endpoint submit dispatch. Request-body building
|
|
6
22
|
* lives in ./klingRequests, status polling + result stashing in ./klingStatus,
|
|
7
23
|
* and credit math in ./klingCredits.
|
|
@@ -15,6 +31,16 @@ export declare class KlingService extends BaseAiGenProviderService {
|
|
|
15
31
|
constructor();
|
|
16
32
|
private request;
|
|
17
33
|
generateVideo(params: VideoGenerationParams): Promise<VideoGenerationResult>;
|
|
34
|
+
/**
|
|
35
|
+
* kling-3.0-turbo submit. Kling shipped this model on their "API 2.0"
|
|
36
|
+
* surface, which shares no shape with the /v1/videos/* endpoints the rest of
|
|
37
|
+
* this class targets:
|
|
38
|
+
* • the model is a PATH SEGMENT, not a `model_name` body field
|
|
39
|
+
* • the body is nested (contents/settings/options)
|
|
40
|
+
* • the submit response carries the task id at `data.id`, not `data.task_id`
|
|
41
|
+
* Polling likewise goes to checkTurboVideoStatus, never the v1 prober.
|
|
42
|
+
*/
|
|
43
|
+
private generateTurboVideo;
|
|
18
44
|
/**
|
|
19
45
|
* Extend a previously-generated Kling video by ~4-5s. Takes the Kling task id
|
|
20
46
|
* of the source video (must have been generated by this Kling account).
|
|
@@ -27,6 +53,15 @@ export declare class KlingService extends BaseAiGenProviderService {
|
|
|
27
53
|
private generateAvatarVideo;
|
|
28
54
|
private requestWithTimeoutRetry;
|
|
29
55
|
checkVideoStatus(params: VideoStatusParams): Promise<VideoStatusResult>;
|
|
56
|
+
/**
|
|
57
|
+
* Pick the credential for the surface being called. The API 2.0 key is
|
|
58
|
+
* optional in env — only kling-v3.0-turbo needs it — so its absence must not
|
|
59
|
+
* break the JWT models that make up the rest of the catalog. Failing here
|
|
60
|
+
* (rather than letting Kling return an opaque 401) means the scene fails at
|
|
61
|
+
* SUBMIT with no task id, which our refund policy treats as never-billed →
|
|
62
|
+
* the user is refunded in full.
|
|
63
|
+
*/
|
|
64
|
+
private resolveAuthToken;
|
|
30
65
|
encodeJwtToken(): string;
|
|
31
66
|
getCreditUsed(params: CreditUsageParams): number;
|
|
32
67
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"kling.service.d.ts","sourceRoot":"","sources":["../../../../../src/services/aiGen/providers/kling/kling.service.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,wBAAwB,EAAE,MAAM,8BAA8B,CAAC;AACxE,OAAO,EACL,iBAAiB,EACjB,qBAAqB,EACrB,qBAAqB,EACrB,iBAAiB,EACjB,iBAAiB,EAClB,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"kling.service.d.ts","sourceRoot":"","sources":["../../../../../src/services/aiGen/providers/kling/kling.service.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,wBAAwB,EAAE,MAAM,8BAA8B,CAAC;AACxE,OAAO,EACL,iBAAiB,EACjB,qBAAqB,EACrB,qBAAqB,EACrB,iBAAiB,EACjB,iBAAiB,EAClB,MAAM,UAAU,CAAC;AAyBlB;;;;;;;;;;;;;;GAcG;AACH,MAAM,MAAM,aAAa,GAAG,KAAK,GAAG,QAAQ,CAAC;AAE7C;;;;;GAKG;AACH,qBAAa,YAAa,SAAQ,wBAAwB;IACxD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAuC;IAC/D,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAW;IAC3C,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAU;IASxC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAkD;IAC9E,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAmD;;YAWlE,OAAO;IAiCf,aAAa,CACjB,MAAM,EAAE,qBAAqB,GAC5B,OAAO,CAAC,qBAAqB,CAAC;IA0DjC;;;;;;;;OAQG;YACW,kBAAkB;IAgChC;;;;OAIG;YACW,WAAW;YA6BX,iBAAiB;YA6BjB,qBAAqB;YAgCrB,eAAe;YAkDf,mBAAmB;YAgCnB,uBAAuB;IAsI/B,gBAAgB,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAiB7E;;;;;;;OAOG;IACH,OAAO,CAAC,gBAAgB;IAiBxB,cAAc,IAAI,MAAM;IAexB,aAAa,CAAC,MAAM,EAAE,iBAAiB,GAAG,MAAM;CAGjD"}
|
|
@@ -19,7 +19,7 @@ const klingRequests_1 = require("./klingRequests");
|
|
|
19
19
|
const klingCredits_1 = require("./klingCredits");
|
|
20
20
|
const klingStatus_1 = require("./klingStatus");
|
|
21
21
|
/**
|
|
22
|
-
* Kling provider. This class is the transport (
|
|
22
|
+
* Kling provider. This class is the transport (auth, IPv4-pinned agents,
|
|
23
23
|
* timeout/retry) plus the per-endpoint submit dispatch. Request-body building
|
|
24
24
|
* lives in ./klingRequests, status polling + result stashing in ./klingStatus,
|
|
25
25
|
* and credit math in ./klingCredits.
|
|
@@ -43,12 +43,12 @@ class KlingService extends baseAiGenProvider_service_1.BaseAiGenProviderService
|
|
|
43
43
|
throw new Error("Missing KLING_SECRET_KEY or KLING_ACCESS_KEY in environment variables");
|
|
44
44
|
}
|
|
45
45
|
}
|
|
46
|
-
async request(endpoint, method, body, timeout = this.generateTimeout) {
|
|
46
|
+
async request(endpoint, method, body, timeout = this.generateTimeout, authMode = "jwt") {
|
|
47
47
|
const config = {
|
|
48
48
|
method,
|
|
49
49
|
url: `${this.baseUrl}${endpoint}`,
|
|
50
50
|
headers: {
|
|
51
|
-
Authorization: `Bearer ${this.
|
|
51
|
+
Authorization: `Bearer ${this.resolveAuthToken(authMode)}`,
|
|
52
52
|
"Content-Type": "application/json",
|
|
53
53
|
},
|
|
54
54
|
timeout,
|
|
@@ -77,6 +77,9 @@ class KlingService extends baseAiGenProvider_service_1.BaseAiGenProviderService
|
|
|
77
77
|
params.modelKey === "kling-v3-omni-video") {
|
|
78
78
|
return this.generateOmniVideo(params);
|
|
79
79
|
}
|
|
80
|
+
if (params.modelKey === "kling-v3.0-turbo") {
|
|
81
|
+
return this.generateTurboVideo(params);
|
|
82
|
+
}
|
|
80
83
|
if (params.endpoint === "extend") {
|
|
81
84
|
return this.extendVideo(params);
|
|
82
85
|
}
|
|
@@ -95,6 +98,35 @@ class KlingService extends baseAiGenProvider_service_1.BaseAiGenProviderService
|
|
|
95
98
|
});
|
|
96
99
|
return { task: task.data.task_id, status: types_1.EVideoSceneStatus.TRIGGERED };
|
|
97
100
|
}
|
|
101
|
+
// ─── Kling 3.0 Turbo (API 2.0: /text-to-video|/image-to-video/<modelId>) ────
|
|
102
|
+
/**
|
|
103
|
+
* kling-3.0-turbo submit. Kling shipped this model on their "API 2.0"
|
|
104
|
+
* surface, which shares no shape with the /v1/videos/* endpoints the rest of
|
|
105
|
+
* this class targets:
|
|
106
|
+
* • the model is a PATH SEGMENT, not a `model_name` body field
|
|
107
|
+
* • the body is nested (contents/settings/options)
|
|
108
|
+
* • the submit response carries the task id at `data.id`, not `data.task_id`
|
|
109
|
+
* Polling likewise goes to checkTurboVideoStatus, never the v1 prober.
|
|
110
|
+
*/
|
|
111
|
+
async generateTurboVideo(params) {
|
|
112
|
+
const modelId = aiModels_1.aiModelConfigs[params.modelKey]?.modelId;
|
|
113
|
+
if (!modelId)
|
|
114
|
+
throw new Error(`Unknown modelKey: ${params.modelKey}`);
|
|
115
|
+
// Kling exposes T2V and I2V as two distinct paths (no shared endpoint with
|
|
116
|
+
// an optional image field, as v1 had).
|
|
117
|
+
const kind = params.inputImageUrl ? "image-to-video" : "text-to-video";
|
|
118
|
+
const body = (0, klingRequests_1.buildTurboVideoBody)(params);
|
|
119
|
+
const starttime = Date.now();
|
|
120
|
+
const task = await this.requestWithTimeoutRetry(`/${kind}/${modelId}`, "POST", body, 4, this.generateTimeout, "apiKey");
|
|
121
|
+
logger_1.logger.info("Kling generateTurboVideo submitted", {
|
|
122
|
+
modelKey: params.modelKey,
|
|
123
|
+
modelId,
|
|
124
|
+
kind,
|
|
125
|
+
taskId: task.data.id,
|
|
126
|
+
durationMs: Date.now() - starttime,
|
|
127
|
+
});
|
|
128
|
+
return { task: task.data.id, status: types_1.EVideoSceneStatus.TRIGGERED };
|
|
129
|
+
}
|
|
98
130
|
/**
|
|
99
131
|
* Extend a previously-generated Kling video by ~4-5s. Takes the Kling task id
|
|
100
132
|
* of the source video (must have been generated by this Kling account).
|
|
@@ -196,10 +228,10 @@ class KlingService extends baseAiGenProvider_service_1.BaseAiGenProviderService
|
|
|
196
228
|
});
|
|
197
229
|
return { task: task.data.task_id, status: types_1.EVideoSceneStatus.TRIGGERED };
|
|
198
230
|
}
|
|
199
|
-
async requestWithTimeoutRetry(endpoint, method, body, maxAttempts = 4, timeout = this.statusTimeout) {
|
|
231
|
+
async requestWithTimeoutRetry(endpoint, method, body, maxAttempts = 4, timeout = this.statusTimeout, authMode = "jwt") {
|
|
200
232
|
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
201
233
|
try {
|
|
202
|
-
return await this.request(endpoint, method, body, timeout);
|
|
234
|
+
return await this.request(endpoint, method, body, timeout, authMode);
|
|
203
235
|
}
|
|
204
236
|
catch (err) {
|
|
205
237
|
const httpStatus = err.response?.status;
|
|
@@ -314,8 +346,33 @@ class KlingService extends baseAiGenProvider_service_1.BaseAiGenProviderService
|
|
|
314
346
|
if (params.modelKey === "kling-avatar") {
|
|
315
347
|
return (0, klingStatus_1.checkAvatarVideoStatus)(deps, params);
|
|
316
348
|
}
|
|
349
|
+
// API 2.0 task — different endpoint, array response, and "succeeded" vs
|
|
350
|
+
// v1's "succeed". The v1 prober would 404 down its whole endpoint list and
|
|
351
|
+
// report the task missing.
|
|
352
|
+
if (params.modelKey === "kling-v3.0-turbo") {
|
|
353
|
+
return (0, klingStatus_1.checkTurboVideoStatus)(deps, params);
|
|
354
|
+
}
|
|
317
355
|
return (0, klingStatus_1.checkRegularVideoStatus)(deps, params);
|
|
318
356
|
}
|
|
357
|
+
/**
|
|
358
|
+
* Pick the credential for the surface being called. The API 2.0 key is
|
|
359
|
+
* optional in env — only kling-v3.0-turbo needs it — so its absence must not
|
|
360
|
+
* break the JWT models that make up the rest of the catalog. Failing here
|
|
361
|
+
* (rather than letting Kling return an opaque 401) means the scene fails at
|
|
362
|
+
* SUBMIT with no task id, which our refund policy treats as never-billed →
|
|
363
|
+
* the user is refunded in full.
|
|
364
|
+
*/
|
|
365
|
+
resolveAuthToken(mode) {
|
|
366
|
+
if (mode === "jwt")
|
|
367
|
+
return this.encodeJwtToken();
|
|
368
|
+
const apiKey = process.env.KLING_API_KEY;
|
|
369
|
+
if (!apiKey) {
|
|
370
|
+
// Operator detail goes to Loki/Slack; the user sees only the safe copy.
|
|
371
|
+
logger_1.logger.error("KLING_API_KEY is not set — Kling API 2.0 models (kling-v3.0-turbo) need a console-issued API key from https://kling.ai/dev/api-key. The legacy AK/SK JWT is rejected by that surface with HTTP 401 code 1002.");
|
|
372
|
+
throw new errors_1.UserFacingError("This model is temporarily unavailable. Please pick another model.", errors_1.USER_FACING_ERROR_CODES.PROVIDER_AUTH_ERROR);
|
|
373
|
+
}
|
|
374
|
+
return apiKey;
|
|
375
|
+
}
|
|
319
376
|
encodeJwtToken() {
|
|
320
377
|
const payload = {
|
|
321
378
|
iss: process.env.KLING_ACCESS_KEY,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"klingCredits.d.ts","sourceRoot":"","sources":["../../../../../src/services/aiGen/providers/kling/klingCredits.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAE7C;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,EACjC,QAAQ,EACR,IAA8B,EAC9B,QAAY,EACZ,SAAiB,EACjB,KAAa,EACb,SAAS,GACV,EAAE,iBAAiB,GAAG,MAAM,
|
|
1
|
+
{"version":3,"file":"klingCredits.d.ts","sourceRoot":"","sources":["../../../../../src/services/aiGen/providers/kling/klingCredits.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAE7C;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,EACjC,QAAQ,EACR,IAA8B,EAC9B,QAAY,EACZ,SAAiB,EACjB,KAAa,EACb,SAAS,GACV,EAAE,iBAAiB,GAAG,MAAM,CAoE5B"}
|
|
@@ -23,6 +23,18 @@ function getKlingCreditUsed({ modelKey, mode = types_1.EVideoMode.PROFESSIONAL,
|
|
|
23
23
|
const billedSeconds = Math.ceil(duration / 5) * 5;
|
|
24
24
|
return (0, helpers_1.getCreditsFromCost)(perSecond * billedSeconds, applyFloor);
|
|
25
25
|
}
|
|
26
|
+
// kling-3.0-turbo: one flat per-second rate by resolution, native audio
|
|
27
|
+
// always included. Priced per-second (not via a duration table) because
|
|
28
|
+
// Turbo allows every duration 3–15s — a {5,10} table would miss 13 of the 15
|
|
29
|
+
// legal values and silently fall through to the $1.00 fallback below.
|
|
30
|
+
// There is deliberately NO audio multiplier: Kling publishes a single tier
|
|
31
|
+
// for this model, so applying v3.0's 1.5× here would overcharge every call.
|
|
32
|
+
if (modelKey === "kling-v3.0-turbo") {
|
|
33
|
+
const perSecond = modelConfig?.cost?.perMode?.[mode]?.perSecond
|
|
34
|
+
?? modelConfig?.cost?.perMode?.["std"]?.perSecond
|
|
35
|
+
?? 0.112;
|
|
36
|
+
return (0, helpers_1.getCreditsFromCost)(perSecond * duration, applyFloor);
|
|
37
|
+
}
|
|
26
38
|
// v2.6 splits cost by audio/noAudio tier (audio is 2× upcharge).
|
|
27
39
|
if (modelKey === "kling-v2.6") {
|
|
28
40
|
const branch = audio ? modelConfig?.cost?.audio : modelConfig?.cost?.noAudio;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { VideoGenerationParams } from "../types";
|
|
2
|
-
import { KlingAvatarGenerateRequest, KlingImageToVideoRequest, KlingLipSyncRequest, KlingMotionControlRequest, KlingOmniVideoRequest, KlingVideoGenerateRequest } from "./types";
|
|
2
|
+
import { KlingAvatarGenerateRequest, KlingImageToVideoRequest, KlingLipSyncRequest, KlingMotionControlRequest, KlingOmniVideoRequest, KlingTurboImageToVideoRequest, KlingTurboTextToVideoRequest, KlingVideoGenerateRequest } from "./types";
|
|
3
3
|
/**
|
|
4
4
|
* Pure request-body builders mapping our provider-agnostic
|
|
5
5
|
* VideoGenerationParams onto Kling's per-endpoint request shapes. No I/O —
|
|
@@ -29,4 +29,17 @@ export declare function buildLipSyncBody(params: VideoGenerationParams, sessionI
|
|
|
29
29
|
face_id: string;
|
|
30
30
|
start_time: number;
|
|
31
31
|
}): KlingLipSyncRequest;
|
|
32
|
+
/**
|
|
33
|
+
* kling-3.0-turbo body (Kling API 2.0). Shares nothing with
|
|
34
|
+
* buildVideoGenerateRequest above — the surface is nested
|
|
35
|
+
* (`contents`/`settings`/`options`), the model lives in the URL path rather
|
|
36
|
+
* than a `model_name` field, and quality is `resolution` rather than `mode`.
|
|
37
|
+
*
|
|
38
|
+
* Deliberately drops params Turbo does not accept: negativePrompt, cfgScale,
|
|
39
|
+
* cameraControl, lastFrameImageUrl, staticMaskUrl, dynamicMasks, multiShot,
|
|
40
|
+
* and any audio toggle (native audio is always on and always billed). Silently
|
|
41
|
+
* ignoring them is intended — the config's `fields` is what gates the UI, and
|
|
42
|
+
* an agent-authored scene may carry extras from a prior model.
|
|
43
|
+
*/
|
|
44
|
+
export declare function buildTurboVideoBody(params: VideoGenerationParams): KlingTurboTextToVideoRequest | KlingTurboImageToVideoRequest;
|
|
32
45
|
//# sourceMappingURL=klingRequests.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"klingRequests.d.ts","sourceRoot":"","sources":["../../../../../src/services/aiGen/providers/kling/klingRequests.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,qBAAqB,EAAE,MAAM,UAAU,CAAC;AAEjD,OAAO,EAEL,0BAA0B,EAE1B,wBAAwB,EACxB,mBAAmB,EAEnB,yBAAyB,EACzB,qBAAqB,
|
|
1
|
+
{"version":3,"file":"klingRequests.d.ts","sourceRoot":"","sources":["../../../../../src/services/aiGen/providers/kling/klingRequests.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,qBAAqB,EAAE,MAAM,UAAU,CAAC;AAEjD,OAAO,EAEL,0BAA0B,EAE1B,wBAAwB,EACxB,mBAAmB,EAEnB,yBAAyB,EACzB,qBAAqB,EAErB,6BAA6B,EAI7B,4BAA4B,EAC5B,yBAAyB,EAC1B,MAAM,SAAS,CAAC;AAEjB;;;;;;GAMG;AAEH;;;;GAIG;AACH,wBAAgB,yBAAyB,CACvC,MAAM,EAAE,qBAAqB,EAC7B,OAAO,EAAE,MAAM,GACd,yBAAyB,GAAG,wBAAwB,CAmDtD;AAED,uEAAuE;AACvE,wBAAgB,eAAe,CAC7B,MAAM,EAAE,qBAAqB,GAC5B,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAQzB;AAED,gFAAgF;AAChF,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,qBAAqB,EAC7B,OAAO,EAAE,MAAM,GACd,qBAAqB,CA8CvB;AAED,sEAAsE;AACtE,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,qBAAqB,EAC7B,OAAO,EAAE,MAAM,GACd,yBAAyB,CAW3B;AAED,iDAAiD;AACjD,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,qBAAqB,GAC5B,0BAA0B,CAS5B;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,qBAAqB,EAC7B,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,GAC5C,mBAAmB,CAgBrB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,qBAAqB,GAC5B,4BAA4B,GAAG,6BAA6B,CA+B9D"}
|
|
@@ -6,6 +6,7 @@ exports.buildOmniVideoBody = buildOmniVideoBody;
|
|
|
6
6
|
exports.buildMotionControlBody = buildMotionControlBody;
|
|
7
7
|
exports.buildAvatarRequest = buildAvatarRequest;
|
|
8
8
|
exports.buildLipSyncBody = buildLipSyncBody;
|
|
9
|
+
exports.buildTurboVideoBody = buildTurboVideoBody;
|
|
9
10
|
const types_1 = require("../../types");
|
|
10
11
|
const cameraAdapter_1 = require("./cameraAdapter");
|
|
11
12
|
/**
|
|
@@ -192,3 +193,46 @@ function buildLipSyncBody(params, sessionId, face) {
|
|
|
192
193
|
...(params.externalTaskId ? { external_task_id: params.externalTaskId } : {}),
|
|
193
194
|
};
|
|
194
195
|
}
|
|
196
|
+
/**
|
|
197
|
+
* kling-3.0-turbo body (Kling API 2.0). Shares nothing with
|
|
198
|
+
* buildVideoGenerateRequest above — the surface is nested
|
|
199
|
+
* (`contents`/`settings`/`options`), the model lives in the URL path rather
|
|
200
|
+
* than a `model_name` field, and quality is `resolution` rather than `mode`.
|
|
201
|
+
*
|
|
202
|
+
* Deliberately drops params Turbo does not accept: negativePrompt, cfgScale,
|
|
203
|
+
* cameraControl, lastFrameImageUrl, staticMaskUrl, dynamicMasks, multiShot,
|
|
204
|
+
* and any audio toggle (native audio is always on and always billed). Silently
|
|
205
|
+
* ignoring them is intended — the config's `fields` is what gates the UI, and
|
|
206
|
+
* an agent-authored scene may carry extras from a prior model.
|
|
207
|
+
*/
|
|
208
|
+
function buildTurboVideoBody(params) {
|
|
209
|
+
const settings = {
|
|
210
|
+
// Explicit resolution wins; otherwise map our canonical mode using Kling's
|
|
211
|
+
// own legacy equivalence (std=720p, pro=1080p).
|
|
212
|
+
resolution: params.resolution ??
|
|
213
|
+
(params.mode === types_1.EVideoMode.PROFESSIONAL ? "1080p" : "720p"),
|
|
214
|
+
duration: params.duration ?? 5,
|
|
215
|
+
};
|
|
216
|
+
if (params.aspectRatio) {
|
|
217
|
+
settings.aspect_ratio = params.aspectRatio;
|
|
218
|
+
}
|
|
219
|
+
const options = {};
|
|
220
|
+
if (params.callbackUrl)
|
|
221
|
+
options.callback_url = params.callbackUrl;
|
|
222
|
+
if (params.externalTaskId)
|
|
223
|
+
options.external_task_id = params.externalTaskId;
|
|
224
|
+
if (params.watermark !== undefined) {
|
|
225
|
+
options.watermark_info = { enabled: Boolean(params.watermark) };
|
|
226
|
+
}
|
|
227
|
+
const maybeOptions = Object.keys(options).length ? { options } : {};
|
|
228
|
+
if (params.inputImageUrl) {
|
|
229
|
+
// I2V: prompt and image BOTH ride inside contents[].
|
|
230
|
+
const contents = [];
|
|
231
|
+
if (params.prompt)
|
|
232
|
+
contents.push({ type: "prompt", text: params.prompt });
|
|
233
|
+
contents.push({ type: "first_frame", url: params.inputImageUrl });
|
|
234
|
+
return { contents, settings, ...maybeOptions };
|
|
235
|
+
}
|
|
236
|
+
// T2V: prompt is a top-level string on this endpoint (not contents[]).
|
|
237
|
+
return { prompt: params.prompt, settings, ...maybeOptions };
|
|
238
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { VideoStatusParams, VideoStatusResult } from "../types";
|
|
2
|
+
import type { KlingAuthMode } from "./kling.service";
|
|
2
3
|
/**
|
|
3
4
|
* Kling status polling + result stashing. Extracted from KlingService so the
|
|
4
5
|
* class stays a thin transport/dispatch layer. These take a `request` dep (the
|
|
@@ -7,10 +8,21 @@ import { VideoStatusParams, VideoStatusResult } from "../types";
|
|
|
7
8
|
*/
|
|
8
9
|
export interface KlingStatusDeps {
|
|
9
10
|
/** Bound KlingService.requestWithTimeoutRetry. */
|
|
10
|
-
request: <T>(endpoint: string, method: "POST" | "GET", body?: any, maxAttempts?: number, timeout?: number
|
|
11
|
+
request: <T>(endpoint: string, method: "POST" | "GET", body?: any, maxAttempts?: number, timeout?: number,
|
|
12
|
+
/** "apiKey" for the API 2.0 surface (/tasks); defaults to the AK/SK JWT. */
|
|
13
|
+
authMode?: KlingAuthMode) => Promise<T>;
|
|
11
14
|
/** Submit-endpoint timeout (also used for the potentially-large video download). */
|
|
12
15
|
generateTimeout: number;
|
|
13
16
|
}
|
|
17
|
+
/**
|
|
18
|
+
* kling-3.0-turbo polling (Kling API 2.0). Separate from the v1 poller for
|
|
19
|
+
* three reasons, any one of which would break if the v1 path were reused:
|
|
20
|
+
* • the endpoint is GET /tasks?task_ids=<id>, not /v1/videos/<kind>/<id>
|
|
21
|
+
* • `data` is an ARRAY of tasks, not a single object
|
|
22
|
+
* • success is spelled "succeeded" here and "succeed" on v1
|
|
23
|
+
* It also means turbo needs no endpoint probing — one call, no 404 fan-out.
|
|
24
|
+
*/
|
|
25
|
+
export declare function checkTurboVideoStatus(deps: KlingStatusDeps, { task, outputFilename, outputFilePath }: VideoStatusParams): Promise<VideoStatusResult>;
|
|
14
26
|
export declare function checkRegularVideoStatus(deps: KlingStatusDeps, { task, outputFilename, outputFilePath }: VideoStatusParams): Promise<VideoStatusResult>;
|
|
15
27
|
export declare function checkAvatarVideoStatus(deps: KlingStatusDeps, { task, outputFilename, outputFilePath }: VideoStatusParams): Promise<VideoStatusResult>;
|
|
16
28
|
//# sourceMappingURL=klingStatus.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"klingStatus.d.ts","sourceRoot":"","sources":["../../../../../src/services/aiGen/providers/kling/klingStatus.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"klingStatus.d.ts","sourceRoot":"","sources":["../../../../../src/services/aiGen/providers/kling/klingStatus.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAChE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAGrD;;;;;GAKG;AACH,MAAM,WAAW,eAAe;IAC9B,kDAAkD;IAClD,OAAO,EAAE,CAAC,CAAC,EACT,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,GAAG,KAAK,EACtB,IAAI,CAAC,EAAE,GAAG,EACV,WAAW,CAAC,EAAE,MAAM,EACpB,OAAO,CAAC,EAAE,MAAM;IAChB,4EAA4E;IAC5E,QAAQ,CAAC,EAAE,aAAa,KACrB,OAAO,CAAC,CAAC,CAAC,CAAC;IAChB,oFAAoF;IACpF,eAAe,EAAE,MAAM,CAAC;CACzB;AA4ED;;;;;;;GAOG;AACH,wBAAsB,qBAAqB,CACzC,IAAI,EAAE,eAAe,EACrB,EAAE,IAAI,EAAE,cAAc,EAAE,cAAyB,EAAE,EAAE,iBAAiB,GACrE,OAAO,CAAC,iBAAiB,CAAC,CAuD5B;AAED,wBAAsB,uBAAuB,CAC3C,IAAI,EAAE,eAAe,EACrB,EAAE,IAAI,EAAE,cAAc,EAAE,cAAyB,EAAE,EAAE,iBAAiB,GACrE,OAAO,CAAC,iBAAiB,CAAC,CAyE5B;AAED,wBAAsB,sBAAsB,CAC1C,IAAI,EAAE,eAAe,EACrB,EAAE,IAAI,EAAE,cAAc,EAAE,cAAyB,EAAE,EAAE,iBAAiB,GACrE,OAAO,CAAC,iBAAiB,CAAC,CAqG5B"}
|