@amaster.ai/pi-video-gen 0.1.2-beta.48
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/LICENSE +201 -0
- package/README.md +196 -0
- package/dist/compose.d.ts +43 -0
- package/dist/compose.d.ts.map +1 -0
- package/dist/compose.js +308 -0
- package/dist/compose.js.map +1 -0
- package/dist/config.d.ts +29 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +305 -0
- package/dist/config.js.map +1 -0
- package/dist/errors.d.ts +50 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +99 -0
- package/dist/errors.js.map +1 -0
- package/dist/ffmpeg.d.ts +64 -0
- package/dist/ffmpeg.d.ts.map +1 -0
- package/dist/ffmpeg.js +292 -0
- package/dist/ffmpeg.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +837 -0
- package/dist/index.js.map +1 -0
- package/dist/jobs/store.d.ts +124 -0
- package/dist/jobs/store.d.ts.map +1 -0
- package/dist/jobs/store.js +386 -0
- package/dist/jobs/store.js.map +1 -0
- package/dist/providers/ark.d.ts +26 -0
- package/dist/providers/ark.d.ts.map +1 -0
- package/dist/providers/ark.js +178 -0
- package/dist/providers/ark.js.map +1 -0
- package/dist/providers/dashscope.d.ts +28 -0
- package/dist/providers/dashscope.d.ts.map +1 -0
- package/dist/providers/dashscope.js +200 -0
- package/dist/providers/dashscope.js.map +1 -0
- package/dist/providers/kling.d.ts +46 -0
- package/dist/providers/kling.d.ts.map +1 -0
- package/dist/providers/kling.js +245 -0
- package/dist/providers/kling.js.map +1 -0
- package/dist/providers/models.d.ts +16 -0
- package/dist/providers/models.d.ts.map +1 -0
- package/dist/providers/models.js +152 -0
- package/dist/providers/models.js.map +1 -0
- package/dist/providers/newapi.d.ts +3 -0
- package/dist/providers/newapi.d.ts.map +1 -0
- package/dist/providers/newapi.js +203 -0
- package/dist/providers/newapi.js.map +1 -0
- package/dist/providers/openrouter.d.ts +21 -0
- package/dist/providers/openrouter.d.ts.map +1 -0
- package/dist/providers/openrouter.js +169 -0
- package/dist/providers/openrouter.js.map +1 -0
- package/dist/providers/request.d.ts +4 -0
- package/dist/providers/request.d.ts.map +1 -0
- package/dist/providers/request.js +20 -0
- package/dist/providers/request.js.map +1 -0
- package/dist/providers/task.d.ts +53 -0
- package/dist/providers/task.d.ts.map +1 -0
- package/dist/providers/task.js +209 -0
- package/dist/providers/task.js.map +1 -0
- package/dist/render.d.ts +53 -0
- package/dist/render.d.ts.map +1 -0
- package/dist/render.js +480 -0
- package/dist/render.js.map +1 -0
- package/dist/text-layer.d.ts +18 -0
- package/dist/text-layer.d.ts.map +1 -0
- package/dist/text-layer.js +168 -0
- package/dist/text-layer.js.map +1 -0
- package/dist/timeline-render.d.ts +33 -0
- package/dist/timeline-render.d.ts.map +1 -0
- package/dist/timeline-render.js +1051 -0
- package/dist/timeline-render.js.map +1 -0
- package/dist/timeline.d.ts +64 -0
- package/dist/timeline.d.ts.map +1 -0
- package/dist/timeline.js +246 -0
- package/dist/timeline.js.map +1 -0
- package/dist/tts/edge-tts.d.ts +22 -0
- package/dist/tts/edge-tts.d.ts.map +1 -0
- package/dist/tts/edge-tts.js +55 -0
- package/dist/tts/edge-tts.js.map +1 -0
- package/dist/types.d.ts +161 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +13 -0
- package/dist/types.js.map +1 -0
- package/package.json +93 -0
- package/preview.png +0 -0
- package/skills/video-gen/SKILL.md +284 -0
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { VideoProviderAdapter } from '../types.js';
|
|
2
|
+
import { requestFingerprint } from './request.js';
|
|
3
|
+
/**
|
|
4
|
+
* Volcengine Ark video generation (ByteDance Seedance series).
|
|
5
|
+
*
|
|
6
|
+
* POST {baseUrl}/contents/generations/tasks → { id }
|
|
7
|
+
* GET {baseUrl}/contents/generations/tasks/{id} → { status, content.video_url }
|
|
8
|
+
*
|
|
9
|
+
* Seedance 2.0 takes structured params (resolution/ratio/duration/
|
|
10
|
+
* generate_audio/watermark) alongside the content array.
|
|
11
|
+
* Reference images ride in the content array with a `role` of
|
|
12
|
+
* `first_frame` / `last_frame` / `reference_image`.
|
|
13
|
+
*
|
|
14
|
+
* Docs: https://www.volcengine.com/docs/82379/1520757
|
|
15
|
+
*
|
|
16
|
+
* Idempotency note (per design review): Ark's task-creation idempotency
|
|
17
|
+
* support (client token / idempotency key / task-list lookup) is UNVERIFIED
|
|
18
|
+
* until the M0 probe reports. So submit() never silently retries: 4xx fails
|
|
19
|
+
* fast (the request won't become valid), and network/5xx failures raise an
|
|
20
|
+
* AMBIGUOUS error that tells the user to check the console for a possibly
|
|
21
|
+
* created paid task before retrying.
|
|
22
|
+
*/
|
|
23
|
+
export declare const ARK_DEFAULT_BASE_URL = "https://ark.cn-beijing.volces.com/api/v3";
|
|
24
|
+
export { requestFingerprint as fingerprint };
|
|
25
|
+
export declare const arkAdapter: VideoProviderAdapter;
|
|
26
|
+
//# sourceMappingURL=ark.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ark.d.ts","sourceRoot":"","sources":["../../src/providers/ark.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAIV,oBAAoB,EACrB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAGlD;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,eAAO,MAAM,oBAAoB,6CAA6C,CAAC;AAiC/E,OAAO,EAAE,kBAAkB,IAAI,WAAW,EAAE,CAAC;AAU7C,eAAO,MAAM,UAAU,EAAE,oBAkJxB,CAAC"}
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
import { readFile } from 'node:fs/promises';
|
|
2
|
+
import { extname } from 'node:path';
|
|
3
|
+
import { AmbiguousSubmitError, httpStatusError, missingKeyError, networkError, redactUrl, safeBasename, VideoGenError, } from '../errors.js';
|
|
4
|
+
import { requestFingerprint } from './request.js';
|
|
5
|
+
import { downloadFile } from './task.js';
|
|
6
|
+
/**
|
|
7
|
+
* Volcengine Ark video generation (ByteDance Seedance series).
|
|
8
|
+
*
|
|
9
|
+
* POST {baseUrl}/contents/generations/tasks → { id }
|
|
10
|
+
* GET {baseUrl}/contents/generations/tasks/{id} → { status, content.video_url }
|
|
11
|
+
*
|
|
12
|
+
* Seedance 2.0 takes structured params (resolution/ratio/duration/
|
|
13
|
+
* generate_audio/watermark) alongside the content array.
|
|
14
|
+
* Reference images ride in the content array with a `role` of
|
|
15
|
+
* `first_frame` / `last_frame` / `reference_image`.
|
|
16
|
+
*
|
|
17
|
+
* Docs: https://www.volcengine.com/docs/82379/1520757
|
|
18
|
+
*
|
|
19
|
+
* Idempotency note (per design review): Ark's task-creation idempotency
|
|
20
|
+
* support (client token / idempotency key / task-list lookup) is UNVERIFIED
|
|
21
|
+
* until the M0 probe reports. So submit() never silently retries: 4xx fails
|
|
22
|
+
* fast (the request won't become valid), and network/5xx failures raise an
|
|
23
|
+
* AMBIGUOUS error that tells the user to check the console for a possibly
|
|
24
|
+
* created paid task before retrying.
|
|
25
|
+
*/
|
|
26
|
+
export const ARK_DEFAULT_BASE_URL = 'https://ark.cn-beijing.volces.com/api/v3';
|
|
27
|
+
const MIME_BY_EXT = {
|
|
28
|
+
'.png': 'image/png',
|
|
29
|
+
'.jpg': 'image/jpeg',
|
|
30
|
+
'.jpeg': 'image/jpeg',
|
|
31
|
+
'.webp': 'image/webp',
|
|
32
|
+
};
|
|
33
|
+
async function imageFileToDataUri(path) {
|
|
34
|
+
const mime = MIME_BY_EXT[extname(path).toLowerCase()];
|
|
35
|
+
if (!mime) {
|
|
36
|
+
throw new VideoGenError(`Reference image must be png/jpg/webp: ${safeBasename(path)}`, 'ark: unsupported image extension');
|
|
37
|
+
}
|
|
38
|
+
let bytes;
|
|
39
|
+
try {
|
|
40
|
+
bytes = await readFile(path);
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
throw new VideoGenError(`Reference image is not readable: ${safeBasename(path)}`, 'ark: image unreadable');
|
|
44
|
+
}
|
|
45
|
+
return `data:${mime};base64,${bytes.toString('base64')}`;
|
|
46
|
+
}
|
|
47
|
+
function bearerHeaders(apiKey) {
|
|
48
|
+
return { authorization: `Bearer ${apiKey}`, 'content-type': 'application/json' };
|
|
49
|
+
}
|
|
50
|
+
export { requestFingerprint as fingerprint };
|
|
51
|
+
/** Thrown when submit failed without a definitive server verdict (network/5xx). */
|
|
52
|
+
function ambiguousSubmitError() {
|
|
53
|
+
return new AmbiguousSubmitError('Task creation failed with an ambiguous result (network error or server 5xx). The provider MAY have created a paid task — check the Volcengine Ark console before retrying to avoid double billing.', 'ark submit: ambiguous outcome');
|
|
54
|
+
}
|
|
55
|
+
export const arkAdapter = {
|
|
56
|
+
async submit(provider, remoteModelId, params, fetchImpl, signal) {
|
|
57
|
+
if (!provider.apiKey)
|
|
58
|
+
throw missingKeyError('ark', 'ARK_API_KEY', provider.apiKeyPath);
|
|
59
|
+
const content = [{ type: 'text', text: params.prompt }];
|
|
60
|
+
if (params.firstFramePath) {
|
|
61
|
+
content.push({
|
|
62
|
+
type: 'image_url',
|
|
63
|
+
image_url: { url: await imageFileToDataUri(params.firstFramePath) },
|
|
64
|
+
role: 'first_frame',
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
if (params.lastFramePath) {
|
|
68
|
+
content.push({
|
|
69
|
+
type: 'image_url',
|
|
70
|
+
image_url: { url: await imageFileToDataUri(params.lastFramePath) },
|
|
71
|
+
role: 'last_frame',
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
for (const path of params.referenceImagePaths ?? []) {
|
|
75
|
+
content.push({
|
|
76
|
+
type: 'image_url',
|
|
77
|
+
image_url: { url: await imageFileToDataUri(path) },
|
|
78
|
+
role: 'reference_image',
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
const body = {
|
|
82
|
+
model: remoteModelId,
|
|
83
|
+
content,
|
|
84
|
+
watermark: false,
|
|
85
|
+
};
|
|
86
|
+
if (params.resolution)
|
|
87
|
+
body.resolution = params.resolution;
|
|
88
|
+
if (params.aspectRatio)
|
|
89
|
+
body.ratio = params.aspectRatio;
|
|
90
|
+
if (params.durationSec != null)
|
|
91
|
+
body.duration = params.durationSec;
|
|
92
|
+
if (params.generateAudio != null)
|
|
93
|
+
body.generate_audio = params.generateAudio;
|
|
94
|
+
let res;
|
|
95
|
+
try {
|
|
96
|
+
res = await fetchImpl(`${provider.baseUrl}/contents/generations/tasks`, {
|
|
97
|
+
method: 'POST',
|
|
98
|
+
headers: bearerHeaders(provider.apiKey),
|
|
99
|
+
body: JSON.stringify(body),
|
|
100
|
+
signal: signal ?? null,
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
catch {
|
|
104
|
+
throw ambiguousSubmitError();
|
|
105
|
+
}
|
|
106
|
+
if (!res.ok) {
|
|
107
|
+
if (res.status >= 500)
|
|
108
|
+
throw ambiguousSubmitError();
|
|
109
|
+
throw httpStatusError('ark', 'submit', res.status);
|
|
110
|
+
}
|
|
111
|
+
let taskId;
|
|
112
|
+
try {
|
|
113
|
+
const json = (await res.json());
|
|
114
|
+
taskId = json.id;
|
|
115
|
+
}
|
|
116
|
+
catch {
|
|
117
|
+
// Response said OK but wasn't JSON — treat as ambiguous rather than assume.
|
|
118
|
+
throw ambiguousSubmitError();
|
|
119
|
+
}
|
|
120
|
+
if (!taskId) {
|
|
121
|
+
// 2xx but no id: the task MAY exist server-side — this is ambiguous,
|
|
122
|
+
// not a clean failure, and must park the shot rather than re-submit.
|
|
123
|
+
throw new AmbiguousSubmitError('The provider accepted the request but returned no task id. Not retrying automatically; check the Ark console.', 'ark submit: no task id');
|
|
124
|
+
}
|
|
125
|
+
return {
|
|
126
|
+
taskId,
|
|
127
|
+
submittedAt: new Date().toISOString(),
|
|
128
|
+
requestFingerprint: requestFingerprint(remoteModelId, params),
|
|
129
|
+
};
|
|
130
|
+
},
|
|
131
|
+
async inspect(provider, handle, fetchImpl, signal) {
|
|
132
|
+
if (!provider.apiKey)
|
|
133
|
+
throw missingKeyError('ark', 'ARK_API_KEY', provider.apiKeyPath);
|
|
134
|
+
let res;
|
|
135
|
+
try {
|
|
136
|
+
res = await fetchImpl(`${provider.baseUrl}/contents/generations/tasks/${encodeURIComponent(handle.taskId)}`, {
|
|
137
|
+
headers: { authorization: `Bearer ${provider.apiKey}` },
|
|
138
|
+
signal: signal ?? null,
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
catch {
|
|
142
|
+
throw networkError('ark', 'inspect');
|
|
143
|
+
}
|
|
144
|
+
if (!res.ok)
|
|
145
|
+
throw httpStatusError('ark', 'inspect', res.status);
|
|
146
|
+
const json = (await res.json());
|
|
147
|
+
switch (json.status) {
|
|
148
|
+
case 'queued':
|
|
149
|
+
return { phase: 'pending' };
|
|
150
|
+
case 'running':
|
|
151
|
+
return { phase: 'running' };
|
|
152
|
+
case 'succeeded': {
|
|
153
|
+
const videoUrl = json.content?.video_url;
|
|
154
|
+
if (!videoUrl) {
|
|
155
|
+
throw new VideoGenError('The task succeeded but returned no video URL. Report this with the task id.', 'ark inspect: succeeded without url');
|
|
156
|
+
}
|
|
157
|
+
return { phase: 'succeeded', videoUrl };
|
|
158
|
+
}
|
|
159
|
+
case 'failed':
|
|
160
|
+
return { phase: 'failed', message: json.error?.message ?? 'unknown provider error' };
|
|
161
|
+
default:
|
|
162
|
+
throw new VideoGenError(`The provider returned an unknown task status. Task id kept for support: ${handle.taskId}.`, 'ark inspect: unknown status');
|
|
163
|
+
}
|
|
164
|
+
},
|
|
165
|
+
async downloadTo(_provider, _handle, videoUrl, destPath, fetchImpl, signal) {
|
|
166
|
+
try {
|
|
167
|
+
return await downloadFile({ url: videoUrl, destPath, fetchImpl, signal });
|
|
168
|
+
}
|
|
169
|
+
catch (error) {
|
|
170
|
+
if (error instanceof VideoGenError)
|
|
171
|
+
throw error;
|
|
172
|
+
throw new VideoGenError(`Downloading the video failed (${redactUrl(videoUrl)}). The URL expires after 24h — rerun to regenerate.`, 'ark download: failed');
|
|
173
|
+
}
|
|
174
|
+
},
|
|
175
|
+
// cancel: intentionally omitted — Ark task-cancellation support is unverified
|
|
176
|
+
// until the M0 probe reports. Local stops are surfaced as `polling_stopped`.
|
|
177
|
+
};
|
|
178
|
+
//# sourceMappingURL=ark.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ark.js","sourceRoot":"","sources":["../../src/providers/ark.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { VideoProviderAdapter } from '../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Alibaba DashScope video generation (HappyHorse series).
|
|
4
|
+
*
|
|
5
|
+
* POST {baseUrl}/api/v1/services/aigc/video-generation/video-synthesis
|
|
6
|
+
* (headers: X-DashScope-Async: enable) → output.task_id
|
|
7
|
+
* GET {baseUrl}/api/v1/tasks/{taskId} → output.task_status / video_url
|
|
8
|
+
* POST {baseUrl}/api/v1/tasks/{taskId}/cancel (generic DashScope task API)
|
|
9
|
+
*
|
|
10
|
+
* Model family routing (one logical model id maps to three real ones):
|
|
11
|
+
* no images → {family}-t2v
|
|
12
|
+
* firstFramePath → {family}-i2v (exactly ONE first frame, ratio follows image)
|
|
13
|
+
* referenceImagePaths → {family}-r2v (1-9 reference images, prompt uses [Image N])
|
|
14
|
+
* firstFrame + references together are NOT supported (i2v and r2v are distinct
|
|
15
|
+
* endpoints); last-frame interpolation does not exist on HappyHorse.
|
|
16
|
+
*
|
|
17
|
+
* Workspace note: the default baseUrl is the classic dashscope.aliyuncs.com,
|
|
18
|
+
* which needs NO workspace id. New Bailian workspaces use a per-workspace
|
|
19
|
+
* hostname — set providers.dashscope.baseUrl to
|
|
20
|
+
* https://{workspaceId}.cn-beijing.maas.aliyuncs.com — and aggregators speaking
|
|
21
|
+
* this wire format just point customProviders at themselves.
|
|
22
|
+
*
|
|
23
|
+
* Docs: https://help.aliyun.com/zh/model-studio/happyhorse-text-to-video-api-reference
|
|
24
|
+
* (and the image-to-video / reference-to-video siblings)
|
|
25
|
+
*/
|
|
26
|
+
export declare const DASHSCOPE_DEFAULT_BASE_URL = "https://dashscope.aliyuncs.com";
|
|
27
|
+
export declare const dashscopeAdapter: VideoProviderAdapter;
|
|
28
|
+
//# sourceMappingURL=dashscope.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dashscope.d.ts","sourceRoot":"","sources":["../../src/providers/dashscope.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAIV,oBAAoB,EACrB,MAAM,aAAa,CAAC;AAIrB;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,eAAO,MAAM,0BAA0B,mCAAmC,CAAC;AAoC3E,eAAO,MAAM,gBAAgB,EAAE,oBAgL9B,CAAC"}
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
import { readFile } from 'node:fs/promises';
|
|
2
|
+
import { extname } from 'node:path';
|
|
3
|
+
import { AmbiguousSubmitError, httpStatusError, missingKeyError, networkError, safeBasename, VideoGenError, } from '../errors.js';
|
|
4
|
+
import { requestFingerprint } from './request.js';
|
|
5
|
+
import { downloadFile } from './task.js';
|
|
6
|
+
/**
|
|
7
|
+
* Alibaba DashScope video generation (HappyHorse series).
|
|
8
|
+
*
|
|
9
|
+
* POST {baseUrl}/api/v1/services/aigc/video-generation/video-synthesis
|
|
10
|
+
* (headers: X-DashScope-Async: enable) → output.task_id
|
|
11
|
+
* GET {baseUrl}/api/v1/tasks/{taskId} → output.task_status / video_url
|
|
12
|
+
* POST {baseUrl}/api/v1/tasks/{taskId}/cancel (generic DashScope task API)
|
|
13
|
+
*
|
|
14
|
+
* Model family routing (one logical model id maps to three real ones):
|
|
15
|
+
* no images → {family}-t2v
|
|
16
|
+
* firstFramePath → {family}-i2v (exactly ONE first frame, ratio follows image)
|
|
17
|
+
* referenceImagePaths → {family}-r2v (1-9 reference images, prompt uses [Image N])
|
|
18
|
+
* firstFrame + references together are NOT supported (i2v and r2v are distinct
|
|
19
|
+
* endpoints); last-frame interpolation does not exist on HappyHorse.
|
|
20
|
+
*
|
|
21
|
+
* Workspace note: the default baseUrl is the classic dashscope.aliyuncs.com,
|
|
22
|
+
* which needs NO workspace id. New Bailian workspaces use a per-workspace
|
|
23
|
+
* hostname — set providers.dashscope.baseUrl to
|
|
24
|
+
* https://{workspaceId}.cn-beijing.maas.aliyuncs.com — and aggregators speaking
|
|
25
|
+
* this wire format just point customProviders at themselves.
|
|
26
|
+
*
|
|
27
|
+
* Docs: https://help.aliyun.com/zh/model-studio/happyhorse-text-to-video-api-reference
|
|
28
|
+
* (and the image-to-video / reference-to-video siblings)
|
|
29
|
+
*/
|
|
30
|
+
export const DASHSCOPE_DEFAULT_BASE_URL = 'https://dashscope.aliyuncs.com';
|
|
31
|
+
const MIME_BY_EXT = {
|
|
32
|
+
'.png': 'image/png',
|
|
33
|
+
'.jpg': 'image/jpeg',
|
|
34
|
+
'.jpeg': 'image/jpeg',
|
|
35
|
+
'.webp': 'image/webp',
|
|
36
|
+
};
|
|
37
|
+
async function imageFileToDataUri(path) {
|
|
38
|
+
const mime = MIME_BY_EXT[extname(path).toLowerCase()];
|
|
39
|
+
if (!mime) {
|
|
40
|
+
throw new VideoGenError(`Reference image must be png/jpg/webp: ${safeBasename(path)}`, 'dashscope: unsupported image extension');
|
|
41
|
+
}
|
|
42
|
+
let bytes;
|
|
43
|
+
try {
|
|
44
|
+
bytes = await readFile(path);
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
throw new VideoGenError(`Reference image is not readable: ${safeBasename(path)}`, 'dashscope: image unreadable');
|
|
48
|
+
}
|
|
49
|
+
return `data:${mime};base64,${bytes.toString('base64')}`;
|
|
50
|
+
}
|
|
51
|
+
function ambiguousSubmitError() {
|
|
52
|
+
return new AmbiguousSubmitError('Task creation failed with an ambiguous result (network error or server 5xx). The provider MAY have created a paid task — check the DashScope console before retrying to avoid double billing.', 'dashscope submit: ambiguous outcome');
|
|
53
|
+
}
|
|
54
|
+
export const dashscopeAdapter = {
|
|
55
|
+
async submit(provider, remoteModelId, params, fetchImpl, signal) {
|
|
56
|
+
if (!provider.apiKey) {
|
|
57
|
+
throw missingKeyError('dashscope', 'DASHSCOPE_API_KEY', provider.apiKeyPath);
|
|
58
|
+
}
|
|
59
|
+
if (params.lastFramePath) {
|
|
60
|
+
throw new VideoGenError('HappyHorse does not support last-frame interpolation. Remove lastFramePath.', 'dashscope: last frame unsupported');
|
|
61
|
+
}
|
|
62
|
+
if (params.firstFramePath && params.referenceImagePaths?.length) {
|
|
63
|
+
throw new VideoGenError('HappyHorse supports either a first frame (i2v) OR reference images (r2v), not both in one call.', 'dashscope: mixed frame and references');
|
|
64
|
+
}
|
|
65
|
+
// Model family routing: strip a trailing -t2v/-i2v/-r2v if the caller
|
|
66
|
+
// passed one, then re-derive from the actual params.
|
|
67
|
+
const family = remoteModelId.replace(/-(t2v|i2v|r2v)$/, '');
|
|
68
|
+
const media = [];
|
|
69
|
+
let model;
|
|
70
|
+
if (params.referenceImagePaths?.length) {
|
|
71
|
+
model = `${family}-r2v`;
|
|
72
|
+
for (const path of params.referenceImagePaths) {
|
|
73
|
+
media.push({ type: 'reference_image', url: await imageFileToDataUri(path) });
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
else if (params.firstFramePath) {
|
|
77
|
+
model = `${family}-i2v`;
|
|
78
|
+
media.push({ type: 'first_frame', url: await imageFileToDataUri(params.firstFramePath) });
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
model = `${family}-t2v`;
|
|
82
|
+
}
|
|
83
|
+
const parameters = { watermark: false };
|
|
84
|
+
if (params.resolution)
|
|
85
|
+
parameters.resolution = params.resolution;
|
|
86
|
+
// i2v follows the frame's aspect ratio — ratio is rejected there.
|
|
87
|
+
if (params.aspectRatio && model !== `${family}-i2v`)
|
|
88
|
+
parameters.ratio = params.aspectRatio;
|
|
89
|
+
if (params.durationSec != null)
|
|
90
|
+
parameters.duration = params.durationSec;
|
|
91
|
+
const body = {
|
|
92
|
+
model,
|
|
93
|
+
input: { prompt: params.prompt, ...(media.length > 0 ? { media } : {}) },
|
|
94
|
+
parameters,
|
|
95
|
+
};
|
|
96
|
+
let res;
|
|
97
|
+
try {
|
|
98
|
+
res = await fetchImpl(`${provider.baseUrl}/api/v1/services/aigc/video-generation/video-synthesis`, {
|
|
99
|
+
method: 'POST',
|
|
100
|
+
headers: {
|
|
101
|
+
authorization: `Bearer ${provider.apiKey}`,
|
|
102
|
+
'content-type': 'application/json',
|
|
103
|
+
'x-dashscope-async': 'enable',
|
|
104
|
+
},
|
|
105
|
+
body: JSON.stringify(body),
|
|
106
|
+
signal: signal ?? null,
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
catch {
|
|
110
|
+
throw ambiguousSubmitError();
|
|
111
|
+
}
|
|
112
|
+
if (!res.ok) {
|
|
113
|
+
if (res.status >= 500)
|
|
114
|
+
throw ambiguousSubmitError();
|
|
115
|
+
throw httpStatusError('dashscope', 'submit', res.status);
|
|
116
|
+
}
|
|
117
|
+
let taskId;
|
|
118
|
+
try {
|
|
119
|
+
const json = (await res.json());
|
|
120
|
+
taskId = json.output?.task_id;
|
|
121
|
+
}
|
|
122
|
+
catch {
|
|
123
|
+
throw ambiguousSubmitError();
|
|
124
|
+
}
|
|
125
|
+
if (!taskId) {
|
|
126
|
+
// 2xx but no id: the task MAY exist server-side — this is ambiguous,
|
|
127
|
+
// not a clean failure, and must park the shot rather than re-submit.
|
|
128
|
+
throw new AmbiguousSubmitError('The provider accepted the request but returned no task id. Not retrying automatically; check the DashScope console.', 'dashscope submit: no task id');
|
|
129
|
+
}
|
|
130
|
+
return {
|
|
131
|
+
taskId,
|
|
132
|
+
submittedAt: new Date().toISOString(),
|
|
133
|
+
requestFingerprint: requestFingerprint(remoteModelId, params),
|
|
134
|
+
};
|
|
135
|
+
},
|
|
136
|
+
async inspect(provider, handle, fetchImpl, signal) {
|
|
137
|
+
if (!provider.apiKey) {
|
|
138
|
+
throw missingKeyError('dashscope', 'DASHSCOPE_API_KEY', provider.apiKeyPath);
|
|
139
|
+
}
|
|
140
|
+
let res;
|
|
141
|
+
try {
|
|
142
|
+
res = await fetchImpl(`${provider.baseUrl}/api/v1/tasks/${encodeURIComponent(handle.taskId)}`, {
|
|
143
|
+
headers: { authorization: `Bearer ${provider.apiKey}` },
|
|
144
|
+
signal: signal ?? null,
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
catch {
|
|
148
|
+
throw networkError('dashscope', 'inspect');
|
|
149
|
+
}
|
|
150
|
+
if (!res.ok)
|
|
151
|
+
throw httpStatusError('dashscope', 'inspect', res.status);
|
|
152
|
+
const json = (await res.json());
|
|
153
|
+
switch (json.output?.task_status) {
|
|
154
|
+
case 'PENDING':
|
|
155
|
+
return { phase: 'pending' };
|
|
156
|
+
case 'RUNNING':
|
|
157
|
+
return { phase: 'running' };
|
|
158
|
+
case 'SUCCEEDED': {
|
|
159
|
+
const videoUrl = json.output?.video_url;
|
|
160
|
+
if (!videoUrl) {
|
|
161
|
+
throw new VideoGenError('The task succeeded but returned no video URL. Report this with the task id.', 'dashscope inspect: succeeded without url');
|
|
162
|
+
}
|
|
163
|
+
return { phase: 'succeeded', videoUrl };
|
|
164
|
+
}
|
|
165
|
+
case 'FAILED':
|
|
166
|
+
return { phase: 'failed', message: json.output?.message ?? 'unknown provider error' };
|
|
167
|
+
case 'CANCELED':
|
|
168
|
+
return { phase: 'failed', message: 'task was cancelled on the provider' };
|
|
169
|
+
case 'UNKNOWN':
|
|
170
|
+
return { phase: 'failed', message: 'task unknown or expired (task ids live 24h)' };
|
|
171
|
+
default:
|
|
172
|
+
throw new VideoGenError(`The provider returned an unknown task status. Task id kept for support: ${handle.taskId}.`, 'dashscope inspect: unknown status');
|
|
173
|
+
}
|
|
174
|
+
},
|
|
175
|
+
async downloadTo(_provider, _handle, videoUrl, destPath, fetchImpl, signal) {
|
|
176
|
+
// DashScope result URLs are signed OSS links (24h expiry); download promptly.
|
|
177
|
+
return downloadFile({ url: videoUrl, destPath, fetchImpl, signal });
|
|
178
|
+
},
|
|
179
|
+
/** Generic DashScope task cancellation: POST /api/v1/tasks/{id}/cancel. */
|
|
180
|
+
async cancel(provider, handle, fetchImpl, signal) {
|
|
181
|
+
if (!provider.apiKey) {
|
|
182
|
+
throw missingKeyError('dashscope', 'DASHSCOPE_API_KEY', provider.apiKeyPath);
|
|
183
|
+
}
|
|
184
|
+
let res;
|
|
185
|
+
try {
|
|
186
|
+
res = await fetchImpl(`${provider.baseUrl}/api/v1/tasks/${encodeURIComponent(handle.taskId)}/cancel`, {
|
|
187
|
+
method: 'POST',
|
|
188
|
+
headers: { authorization: `Bearer ${provider.apiKey}` },
|
|
189
|
+
signal: signal ?? null,
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
catch {
|
|
193
|
+
throw networkError('dashscope', 'cancel');
|
|
194
|
+
}
|
|
195
|
+
if (!res.ok)
|
|
196
|
+
throw httpStatusError('dashscope', 'cancel', res.status);
|
|
197
|
+
return { cancelled: true };
|
|
198
|
+
},
|
|
199
|
+
};
|
|
200
|
+
//# sourceMappingURL=dashscope.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dashscope.js","sourceRoot":"","sources":["../../src/providers/dashscope.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { RemoteTaskHandle, VideoProviderAdapter } from '../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Kling (Kuaishou) video generation — official Kling API 2.0.
|
|
4
|
+
*
|
|
5
|
+
* POST {baseUrl}/text-to-video/{model} { prompt, settings, options }
|
|
6
|
+
* POST {baseUrl}/image-to-video/{model} { contents, settings, options }
|
|
7
|
+
* GET {baseUrl}/tasks?task_ids={id} → data[0].status / outputs[].url
|
|
8
|
+
*
|
|
9
|
+
* Verified against the official docs (kling.ai/document-api, 2026-07):
|
|
10
|
+
* - Auth: `Authorization: Bearer {apiKey}` — the older JWT ak/sk scheme is legacy.
|
|
11
|
+
* - The model lives in the PATH (`kling-3.0-turbo`, `kling-3.0`), not the body.
|
|
12
|
+
* - t2v takes a plain `prompt` string; i2v takes a `contents` array
|
|
13
|
+
* (prompt + first_frame [+ last_frame]). i2v follows the frame's ratio, so
|
|
14
|
+
* aspect_ratio is t2v-only.
|
|
15
|
+
* - `options.external_task_id` is a client-provided, account-unique id that is
|
|
16
|
+
* QUERYABLE (GET /tasks?external_task_ids=…) — we set it to our request
|
|
17
|
+
* fingerprint, so an ambiguous submit failure can be resolved by lookup
|
|
18
|
+
* instead of blindly resubmitting a paid task. See recoverByExternalId().
|
|
19
|
+
* - Kling 3.0 (Omni) adds last_frame, audio: "native"|"off", and 4k; the 3.0
|
|
20
|
+
* Turbo is first-frame-only and silent.
|
|
21
|
+
* - Default base is api-singapore.klingai.com (the documented current domain);
|
|
22
|
+
* China-region accounts can point baseUrl at their regional endpoint.
|
|
23
|
+
*/
|
|
24
|
+
export declare const KLING_DEFAULT_BASE_URL = "https://api-singapore.klingai.com";
|
|
25
|
+
type RecoverResult = {
|
|
26
|
+
outcome: 'found';
|
|
27
|
+
handle: RemoteTaskHandle;
|
|
28
|
+
} | {
|
|
29
|
+
outcome: 'not-found';
|
|
30
|
+
} | {
|
|
31
|
+
outcome: 'unknown';
|
|
32
|
+
};
|
|
33
|
+
export declare const klingAdapter: VideoProviderAdapter;
|
|
34
|
+
/**
|
|
35
|
+
* Best-effort idempotency lookup with its OWN short timeout — the caller's
|
|
36
|
+
* signal may already be aborted (that's why we're here), and the lookup must
|
|
37
|
+
* still run to tell whether a paid task exists. Returns null on any failure;
|
|
38
|
+
* callers decide between CancelledError (user aborted) and ambiguous error.
|
|
39
|
+
*/
|
|
40
|
+
/** Exported for tests: the lookup deadline is injectable (default 10s). */
|
|
41
|
+
export declare function tryRecoverByExternalId(provider: {
|
|
42
|
+
apiKey?: string | undefined;
|
|
43
|
+
baseUrl: string;
|
|
44
|
+
}, fp: string, taskType: string, fetchImpl: typeof fetch, timeoutMs?: number): Promise<RecoverResult>;
|
|
45
|
+
export {};
|
|
46
|
+
//# sourceMappingURL=kling.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kling.d.ts","sourceRoot":"","sources":["../../src/providers/kling.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EACV,gBAAgB,EAGhB,oBAAoB,EACrB,MAAM,aAAa,CAAC;AAIrB;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,eAAO,MAAM,sBAAsB,sCAAsC,CAAC;AA4B1E,KAAK,aAAa,GACd;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,gBAAgB,CAAA;CAAE,GAC9C;IAAE,OAAO,EAAE,WAAW,CAAA;CAAE,GACxB;IAAE,OAAO,EAAE,SAAS,CAAA;CAAE,CAAC;AAmF3B,eAAO,MAAM,YAAY,EAAE,oBAuH1B,CAAC;AAEF;;;;;GAKG;AACH,2EAA2E;AAC3E,wBAAsB,sBAAsB,CAC1C,QAAQ,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,EAC1D,EAAE,EAAE,MAAM,EACV,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,OAAO,KAAK,EACvB,SAAS,SAAS,GACjB,OAAO,CAAC,aAAa,CAAC,CAgCxB"}
|