@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
package/dist/render.js
ADDED
|
@@ -0,0 +1,480 @@
|
|
|
1
|
+
import { COPYFILE_EXCL } from 'node:constants';
|
|
2
|
+
import { createHash } from 'node:crypto';
|
|
3
|
+
import { existsSync } from 'node:fs';
|
|
4
|
+
import { copyFile, lstat, mkdir, readFile, realpath, rename } from 'node:fs/promises';
|
|
5
|
+
import { basename, dirname, extname, join, resolve, sep } from 'node:path';
|
|
6
|
+
import { resolveOutputDir } from './config.js';
|
|
7
|
+
import { AmbiguousSubmitError, errorMessageForUser, RemoteTaskFailedError, RemoteTaskNotFoundError, safeBasename, toLogSummary, VideoGenError, } from './errors.js';
|
|
8
|
+
import { concatVideos } from './ffmpeg.js';
|
|
9
|
+
import { assertSafeId, loadRenderJob, readJsonFile, saveRenderJob, writeJsonAtomic, } from './jobs/store.js';
|
|
10
|
+
import { requestFingerprint } from './providers/request.js';
|
|
11
|
+
import { CancelledError, pollTask } from './providers/task.js';
|
|
12
|
+
let snapshotCounter = 0;
|
|
13
|
+
function sha256hex(content) {
|
|
14
|
+
return createHash('sha256').update(content).digest('hex');
|
|
15
|
+
}
|
|
16
|
+
function specFingerprint(specRaw, resolved) {
|
|
17
|
+
return sha256hex(JSON.stringify({
|
|
18
|
+
spec: specRaw,
|
|
19
|
+
model: resolved.remoteId,
|
|
20
|
+
provider: resolved.provider.style,
|
|
21
|
+
baseUrl: resolved.provider.baseUrl,
|
|
22
|
+
defaults: {
|
|
23
|
+
resolution: resolved.entry.defaultResolution,
|
|
24
|
+
aspectRatio: resolved.entry.defaultAspectRatio,
|
|
25
|
+
durationSec: resolved.entry.defaultDurationSec,
|
|
26
|
+
},
|
|
27
|
+
capabilities: resolved.entry.capabilities,
|
|
28
|
+
}));
|
|
29
|
+
}
|
|
30
|
+
function expectedSnapshotKeys(spec, cwd) {
|
|
31
|
+
return spec.shots.flatMap((shot) => {
|
|
32
|
+
const keys = [
|
|
33
|
+
join('shots', shot.id, `first_frame${extname(resolve(cwd, shot.firstFramePath)) || '.png'}`),
|
|
34
|
+
];
|
|
35
|
+
if (shot.lastFramePath) {
|
|
36
|
+
keys.push(join('shots', shot.id, `last_frame${extname(resolve(cwd, shot.lastFramePath)) || '.png'}`));
|
|
37
|
+
}
|
|
38
|
+
return keys;
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
function sameKeys(actual, expected) {
|
|
42
|
+
if (actual.length !== expected.length)
|
|
43
|
+
return false;
|
|
44
|
+
const wanted = new Set(expected);
|
|
45
|
+
return actual.every((key) => wanted.has(key));
|
|
46
|
+
}
|
|
47
|
+
/** Manual validation with agent-fixable error messages (better than a schema dump). */
|
|
48
|
+
function parseRenderSpec(raw) {
|
|
49
|
+
let parsed;
|
|
50
|
+
try {
|
|
51
|
+
parsed = JSON.parse(raw);
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
throw new VideoGenError('render-input.json is not valid JSON.', 'render: spec not json');
|
|
55
|
+
}
|
|
56
|
+
const spec = parsed;
|
|
57
|
+
if (!spec || typeof spec !== 'object' || !Array.isArray(spec.shots) || spec.shots.length === 0) {
|
|
58
|
+
throw new VideoGenError('render-input.json must contain a non-empty "shots" array.', 'render: no shots');
|
|
59
|
+
}
|
|
60
|
+
const seen = new Set();
|
|
61
|
+
spec.shots.forEach((shot, i) => {
|
|
62
|
+
const where = `shots[${i}]${shot?.id ? ` ("${shot.id}")` : ''}`;
|
|
63
|
+
if (!shot || typeof shot !== 'object') {
|
|
64
|
+
throw new VideoGenError(`${where} is not an object.`, 'render: bad shot');
|
|
65
|
+
}
|
|
66
|
+
assertSafeId(String(shot.id ?? ''), 'shot');
|
|
67
|
+
if (seen.has(shot.id)) {
|
|
68
|
+
throw new VideoGenError(`Duplicate shot id "${shot.id}" — ids must be unique.`, 'render: dup shot id');
|
|
69
|
+
}
|
|
70
|
+
seen.add(shot.id);
|
|
71
|
+
if (typeof shot.videoPrompt !== 'string' || shot.videoPrompt.trim() === '') {
|
|
72
|
+
throw new VideoGenError(`${where}.videoPrompt is required (motion + optional audio cues).`, 'render: no prompt');
|
|
73
|
+
}
|
|
74
|
+
if (typeof shot.firstFramePath !== 'string' || shot.firstFramePath.trim() === '') {
|
|
75
|
+
throw new VideoGenError(`${where}.firstFramePath is required — generate the frame via image_generate first and point at its returned path.`, 'render: no frame');
|
|
76
|
+
}
|
|
77
|
+
if (shot.durationSec !== undefined &&
|
|
78
|
+
(typeof shot.durationSec !== 'number' || !Number.isSafeInteger(shot.durationSec))) {
|
|
79
|
+
throw new VideoGenError(`${where}.durationSec must be an integer number of seconds.`, 'render: bad duration type');
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
return spec;
|
|
83
|
+
}
|
|
84
|
+
async function runPool(items, size, worker) {
|
|
85
|
+
let idx = 0;
|
|
86
|
+
let firstError;
|
|
87
|
+
const runners = Array.from({ length: Math.max(1, Math.min(size, items.length)) }, async () => {
|
|
88
|
+
while (idx < items.length && firstError === undefined) {
|
|
89
|
+
const item = items[idx++];
|
|
90
|
+
try {
|
|
91
|
+
await worker(item);
|
|
92
|
+
}
|
|
93
|
+
catch (error) {
|
|
94
|
+
firstError ??= error;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
await Promise.all(runners);
|
|
99
|
+
if (firstError !== undefined)
|
|
100
|
+
throw firstError;
|
|
101
|
+
}
|
|
102
|
+
export async function runRender(opts) {
|
|
103
|
+
const { settings, cwd, resolved, adapter } = opts;
|
|
104
|
+
const caps = resolved.entry.capabilities;
|
|
105
|
+
const outputDir = resolveOutputDir(settings, cwd);
|
|
106
|
+
// 1. spec + job identity
|
|
107
|
+
const absSpecPath = resolve(cwd, opts.renderSpecPath);
|
|
108
|
+
const specRaw = await readFile(absSpecPath, 'utf-8').catch(() => {
|
|
109
|
+
throw new VideoGenError('Render spec not readable. Expected <jobDir>/render-input.json under the video-gen output directory (.video-gen).', 'render: spec unreadable');
|
|
110
|
+
});
|
|
111
|
+
const spec = parseRenderSpec(specRaw);
|
|
112
|
+
// Containment must survive symlinks: compare REAL paths, not lexical
|
|
113
|
+
// prefixes — a symlinked jobDir would otherwise let writes escape outputDir.
|
|
114
|
+
const realOutput = await realpath(outputDir).catch(() => resolve(outputDir));
|
|
115
|
+
const requestedJobDir = dirname(absSpecPath);
|
|
116
|
+
const realJobDir = await realpath(requestedJobDir).catch(() => {
|
|
117
|
+
throw new VideoGenError('The job directory does not exist.', 'render: job missing');
|
|
118
|
+
});
|
|
119
|
+
if (realJobDir !== realOutput && !realJobDir.startsWith(`${realOutput}${sep}`)) {
|
|
120
|
+
throw new VideoGenError('The job directory must live under the video-gen output directory (.video-gen). Move your render spec there.', 'render: job outside outputDir');
|
|
121
|
+
}
|
|
122
|
+
const jobId = basename(requestedJobDir);
|
|
123
|
+
const jobDir = realJobDir;
|
|
124
|
+
assertSafeId(jobId, 'job');
|
|
125
|
+
if (basename(absSpecPath) !== 'render-input.json') {
|
|
126
|
+
throw new VideoGenError('The render spec file must be named render-input.json inside the job directory.', 'render: spec name');
|
|
127
|
+
}
|
|
128
|
+
// 2. capability preflight — fail BEFORE anything paid
|
|
129
|
+
const degraded = [];
|
|
130
|
+
const wantsLastFrame = spec.shots.filter((s) => s.lastFramePath).map((s) => s.id);
|
|
131
|
+
if (wantsLastFrame.length > 0 && !caps.supportsFirstLastFrame) {
|
|
132
|
+
if (opts.allowDegradations?.includes('first-frame-only')) {
|
|
133
|
+
for (const shot of spec.shots)
|
|
134
|
+
shot.lastFramePath = undefined;
|
|
135
|
+
degraded.push(`first-frame-only (dropped last frames for: ${wantsLastFrame.join(', ')})`);
|
|
136
|
+
}
|
|
137
|
+
else {
|
|
138
|
+
throw new VideoGenError(`Shots ${wantsLastFrame.join(', ')} request last-frame interpolation, but ${resolved.entry.id} does not support it. Options: switch model (/video-gen models), remove lastFramePath from those shots, or explicitly pass allowDegradations: ["first-frame-only"].`, 'render: flf unsupported');
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
if (spec.aspectRatio && !caps.aspectRatios.includes(spec.aspectRatio)) {
|
|
142
|
+
throw new VideoGenError(`aspectRatio must be one of ${caps.aspectRatios.join(', ')} for ${resolved.entry.id} (got ${spec.aspectRatio}).`, 'render: bad ratio');
|
|
143
|
+
}
|
|
144
|
+
for (const shot of spec.shots) {
|
|
145
|
+
const d = shot.durationSec ?? resolved.entry.defaultDurationSec;
|
|
146
|
+
if (d < caps.durations[0] || d > caps.durations[1]) {
|
|
147
|
+
throw new VideoGenError(`Shot "${shot.id}" durationSec ${d}s is outside ${caps.durations[0]}-${caps.durations[1]}s for ${resolved.entry.id}.`, 'render: bad duration');
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
// Key the concurrency lock on the REAL path: two lexical aliases of the
|
|
151
|
+
// same job directory must collide here, not run concurrently.
|
|
152
|
+
const release = opts.activeJobs.acquire(realJobDir);
|
|
153
|
+
try {
|
|
154
|
+
// Validate the shared parent before creating per-shot directories. A
|
|
155
|
+
// pre-placed `shots` symlink must not create `<outside>/<shotId>` first.
|
|
156
|
+
const shotsDir = join(jobDir, 'shots');
|
|
157
|
+
await mkdir(shotsDir, { recursive: true });
|
|
158
|
+
const realShotsDir = await realpath(shotsDir);
|
|
159
|
+
if (!realShotsDir.startsWith(`${realJobDir}${sep}`)) {
|
|
160
|
+
throw new VideoGenError('The shots directory resolves outside the job directory (symlink?). Remove it and retry.', 'render: shots dir escapes');
|
|
161
|
+
}
|
|
162
|
+
const fingerprint = specFingerprint(specRaw, resolved);
|
|
163
|
+
let manifest = loadRenderJob(jobDir);
|
|
164
|
+
if (manifest) {
|
|
165
|
+
// 3a. resume: verify the whole input fingerprint before trusting anything
|
|
166
|
+
if (manifest.specFingerprint !== fingerprint) {
|
|
167
|
+
throw new VideoGenError('render-input.json or the model/provider config changed since this job was created. Revisions require a NEW job directory (rerunning the same path only resumes identical input).', 'render: spec drift');
|
|
168
|
+
}
|
|
169
|
+
const expectedShotIds = spec.shots.map((shot) => shot.id);
|
|
170
|
+
if (!sameKeys(Object.keys(manifest.shots), expectedShotIds)) {
|
|
171
|
+
throw new VideoGenError('manifest.json does not contain exactly the shots in render-input.json. Refusing to resume — a missing paid-task handle must never be recreated implicitly.', 'render: manifest shot set mismatch');
|
|
172
|
+
}
|
|
173
|
+
const expectedFrames = expectedSnapshotKeys(spec, cwd);
|
|
174
|
+
if (!sameKeys(Object.keys(manifest.frameHashes), expectedFrames)) {
|
|
175
|
+
throw new VideoGenError('manifest.json does not contain exactly the expected frame snapshot hashes. Refusing to resume on unverified frames.', 'render: frame hash set mismatch');
|
|
176
|
+
}
|
|
177
|
+
for (const [relSnap, entry] of Object.entries(manifest.frameHashes)) {
|
|
178
|
+
const snapPath = join(jobDir, relSnap);
|
|
179
|
+
if (!existsSync(snapPath)) {
|
|
180
|
+
throw new VideoGenError(`Frame snapshot missing: ${relSnap}. The job is incomplete; recreate it or start a new job.`, 'render: snapshot missing');
|
|
181
|
+
}
|
|
182
|
+
// The hash check alone is not enough: shots/<id> could have been
|
|
183
|
+
// swapped for an external symlink carrying a same-hash plant. Verify
|
|
184
|
+
// the RESOLVED snapshot is still inside the job.
|
|
185
|
+
const realSnap = await realpath(snapPath);
|
|
186
|
+
if (!realSnap.startsWith(`${realJobDir}${sep}`)) {
|
|
187
|
+
throw new VideoGenError(`${relSnap} resolves outside the job directory (swapped symlink?). Refusing to resume.`, 'render: snapshot escapes');
|
|
188
|
+
}
|
|
189
|
+
const hash = sha256hex(await readFile(snapPath));
|
|
190
|
+
if (hash !== entry) {
|
|
191
|
+
throw new VideoGenError(`Frame snapshot ${relSnap} changed on disk — the frozen input is no longer trustworthy. Start a new job.`, 'render: frame drift');
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
opts.onUpdate?.(`Resuming job ${jobId} (fingerprint verified).`);
|
|
195
|
+
}
|
|
196
|
+
else {
|
|
197
|
+
// 3b. fresh: snapshot frames into the job and freeze their hashes
|
|
198
|
+
opts.onUpdate?.('Snapshotting frames into the job…');
|
|
199
|
+
const frameHashes = {};
|
|
200
|
+
const assets = {};
|
|
201
|
+
for (const shot of spec.shots) {
|
|
202
|
+
const shotDir = join(realShotsDir, shot.id);
|
|
203
|
+
await mkdir(shotDir, { recursive: true });
|
|
204
|
+
const realShotDir = await realpath(shotDir);
|
|
205
|
+
if (!realShotDir.startsWith(`${realJobDir}${sep}`)) {
|
|
206
|
+
throw new VideoGenError(`shots/${shot.id} resolves outside the job directory (symlink?). Remove it and retry.`, 'render: shot dir escapes');
|
|
207
|
+
}
|
|
208
|
+
for (const kind of ['firstFrame', 'lastFrame']) {
|
|
209
|
+
const sourcePath = kind === 'firstFrame' ? shot.firstFramePath : shot.lastFramePath;
|
|
210
|
+
if (!sourcePath)
|
|
211
|
+
continue;
|
|
212
|
+
const absSource = resolve(cwd, sourcePath);
|
|
213
|
+
const ext = extname(absSource) || '.png';
|
|
214
|
+
const relSnap = join('shots', shot.id, `${kind === 'firstFrame' ? 'first_frame' : 'last_frame'}${ext}`);
|
|
215
|
+
const destPath = join(jobDir, relSnap);
|
|
216
|
+
// copyFile FOLLOWS destination symlinks — a pre-placed link would
|
|
217
|
+
// overwrite an arbitrary file outside the job. Refuse non-files.
|
|
218
|
+
const destStat = await lstat(destPath).catch(() => null);
|
|
219
|
+
if (destStat && (destStat.isSymbolicLink() || !destStat.isFile())) {
|
|
220
|
+
throw new VideoGenError(`Refusing to write ${relSnap} — it already exists and is not a regular file (symlink?). Remove it and retry.`, 'render: snapshot destination not a file');
|
|
221
|
+
}
|
|
222
|
+
// Copy to an EXCLUSIVELY-created sibling temp (COPYFILE_EXCL — a
|
|
223
|
+
// pre-placed symlink fails EEXIST instead of being followed), then
|
|
224
|
+
// atomic rename(2), which replaces the destination entry outright.
|
|
225
|
+
let tmpSnap = '';
|
|
226
|
+
for (let i = 0;; i++) {
|
|
227
|
+
const candidate = `${destPath}.tmp-${process.pid}-${snapshotCounter++}-${i}`;
|
|
228
|
+
try {
|
|
229
|
+
await copyFile(absSource, candidate, COPYFILE_EXCL);
|
|
230
|
+
tmpSnap = candidate;
|
|
231
|
+
break;
|
|
232
|
+
}
|
|
233
|
+
catch (error) {
|
|
234
|
+
if (error.code === 'EEXIST')
|
|
235
|
+
continue;
|
|
236
|
+
if (error.code === 'ENOENT') {
|
|
237
|
+
throw new VideoGenError(`Shot "${shot.id}" ${kind} not readable: ${safeBasename(sourcePath)}. Use the absolute path returned by image_generate.`, 'render: frame unreadable');
|
|
238
|
+
}
|
|
239
|
+
throw error;
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
await rename(tmpSnap, destPath);
|
|
243
|
+
// Hash the SNAPSHOT bytes (what we will actually submit) — hashing a
|
|
244
|
+
// pre-copy read of the source would race concurrent source rewrites.
|
|
245
|
+
const hash = sha256hex(await readFile(destPath));
|
|
246
|
+
frameHashes[relSnap] = hash;
|
|
247
|
+
assets[`${shot.id}/${kind}`] = {
|
|
248
|
+
sourcePath: absSource,
|
|
249
|
+
snapshotPath: relSnap,
|
|
250
|
+
sha256: hash,
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
// Merge, don't overwrite: the image stage already registered portraits
|
|
255
|
+
// and other semantic assets in assets.json — our frame snapshots are
|
|
256
|
+
// added. STRICT read: corrupted/unreadable assets.json refuses rather
|
|
257
|
+
// than being truncated to an empty index.
|
|
258
|
+
const assetsDoc = readJsonFile(join(jobDir, 'assets.json'));
|
|
259
|
+
// File ABSENT is fine (first run). File PRESENT but not a plain object —
|
|
260
|
+
// or with an "assets" field that is not a plain object — is corruption:
|
|
261
|
+
// refuse rather than truncate the image stage's index.
|
|
262
|
+
const assetsField = assetsDoc?.assets;
|
|
263
|
+
const docInvalid = assetsDoc !== undefined &&
|
|
264
|
+
(typeof assetsDoc !== 'object' ||
|
|
265
|
+
assetsDoc === null ||
|
|
266
|
+
Array.isArray(assetsDoc) ||
|
|
267
|
+
(assetsField !== undefined &&
|
|
268
|
+
(typeof assetsField !== 'object' ||
|
|
269
|
+
assetsField === null ||
|
|
270
|
+
Array.isArray(assetsField))));
|
|
271
|
+
if (docInvalid) {
|
|
272
|
+
throw new VideoGenError('assets.json is not a valid asset index (root must be an object, "assets" must be an object). Fix or remove it — refusing to overwrite.', 'render: assets shape invalid');
|
|
273
|
+
}
|
|
274
|
+
const existingAssets = (assetsField ?? {});
|
|
275
|
+
writeJsonAtomic(join(jobDir, 'assets.json'), {
|
|
276
|
+
assets: { ...existingAssets, ...assets },
|
|
277
|
+
updatedAt: new Date().toISOString(),
|
|
278
|
+
});
|
|
279
|
+
manifest = {
|
|
280
|
+
jobId,
|
|
281
|
+
kind: 'render',
|
|
282
|
+
state: 'rendering',
|
|
283
|
+
specFingerprint: fingerprint,
|
|
284
|
+
frameHashes,
|
|
285
|
+
shots: Object.fromEntries(spec.shots.map((s) => [s.id, { state: 'pending' }])),
|
|
286
|
+
updatedAt: new Date().toISOString(),
|
|
287
|
+
};
|
|
288
|
+
saveRenderJob(jobDir, manifest);
|
|
289
|
+
}
|
|
290
|
+
// 4. per-shot render loop (resume-aware)
|
|
291
|
+
const concat = opts.concatImpl ?? concatVideos;
|
|
292
|
+
const renderShot = async (shot) => {
|
|
293
|
+
const shotState = manifest.shots[shot.id];
|
|
294
|
+
const videoPath = join(realShotsDir, shot.id, 'video.mp4');
|
|
295
|
+
if (shotState.state === 'done' && existsSync(videoPath))
|
|
296
|
+
return;
|
|
297
|
+
const firstSnap = join(jobDir, 'shots', shot.id, `first_frame${pickExt(manifest, shot.id, 'firstFrame')}`);
|
|
298
|
+
const lastSnap = shot.lastFramePath
|
|
299
|
+
? join(jobDir, 'shots', shot.id, `last_frame${pickExt(manifest, shot.id, 'lastFrame')}`)
|
|
300
|
+
: undefined;
|
|
301
|
+
const attempt = shotState.attempt ?? 1;
|
|
302
|
+
const params = {
|
|
303
|
+
prompt: shot.videoPrompt,
|
|
304
|
+
requestId: `${jobId}:${shot.id}:${attempt}`,
|
|
305
|
+
firstFramePath: firstSnap,
|
|
306
|
+
lastFramePath: lastSnap,
|
|
307
|
+
durationSec: shot.durationSec ?? resolved.entry.defaultDurationSec,
|
|
308
|
+
aspectRatio: spec.aspectRatio ?? resolved.entry.defaultAspectRatio,
|
|
309
|
+
resolution: resolved.entry.defaultResolution,
|
|
310
|
+
generateAudio: caps.nativeAudio,
|
|
311
|
+
};
|
|
312
|
+
let activeFingerprint = requestFingerprint(resolved.remoteId, params);
|
|
313
|
+
// A previously ambiguous submit must NEVER auto-resubmit: a paid task
|
|
314
|
+
// may exist. Block the whole run until the user resolves it through the
|
|
315
|
+
// locked /video-gen recover reset/adopt paths.
|
|
316
|
+
if (shotState.state === 'ambiguous') {
|
|
317
|
+
throw new VideoGenError(`Shot "${shot.id}" had an ambiguous submit — a paid task MAY exist on the provider. Check the provider console, then run /video-gen recover ${jobId} ${shot.id} reset if no task exists, or /video-gen recover ${jobId} ${shot.id} adopt <taskId> to resume an existing task.`, 'render: ambiguous shot');
|
|
318
|
+
}
|
|
319
|
+
let handle = shotState.handle;
|
|
320
|
+
let currentAttempt = shotState.attempt;
|
|
321
|
+
if (handle &&
|
|
322
|
+
shotState.requestFingerprint !== 'manual-adopt' &&
|
|
323
|
+
shotState.requestFingerprint !== activeFingerprint) {
|
|
324
|
+
throw new VideoGenError(`Shot "${shot.id}" has a task handle that does not match its frozen request fingerprint. Refusing to poll it.`, 'render: handle fingerprint mismatch');
|
|
325
|
+
}
|
|
326
|
+
if (!handle) {
|
|
327
|
+
currentAttempt = (currentAttempt ?? 0) + 1;
|
|
328
|
+
params.requestId = `${jobId}:${shot.id}:${currentAttempt}`;
|
|
329
|
+
const submittedFingerprint = requestFingerprint(resolved.remoteId, params);
|
|
330
|
+
activeFingerprint = submittedFingerprint;
|
|
331
|
+
await opts.rateLimiter.acquire(opts.signal);
|
|
332
|
+
opts.onUpdate?.(`Shot ${shot.id}: submitting…`);
|
|
333
|
+
// Crash-safe paid boundary: until a handle is durably persisted, the
|
|
334
|
+
// only honest state is "a remote task may exist".
|
|
335
|
+
manifest.shots[shot.id] = {
|
|
336
|
+
state: 'ambiguous',
|
|
337
|
+
attempt: currentAttempt,
|
|
338
|
+
requestFingerprint: submittedFingerprint,
|
|
339
|
+
};
|
|
340
|
+
saveRenderJob(jobDir, manifest);
|
|
341
|
+
try {
|
|
342
|
+
handle = await adapter.submit(resolved.provider, resolved.remoteId, params, fetch, opts.signal);
|
|
343
|
+
}
|
|
344
|
+
catch (error) {
|
|
345
|
+
manifest.shots[shot.id] = {
|
|
346
|
+
state: error instanceof AmbiguousSubmitError ? 'ambiguous' : 'failed',
|
|
347
|
+
attempt: currentAttempt,
|
|
348
|
+
requestFingerprint: submittedFingerprint,
|
|
349
|
+
error: toLogSummary(error),
|
|
350
|
+
};
|
|
351
|
+
saveRenderJob(jobDir, manifest);
|
|
352
|
+
throw error;
|
|
353
|
+
}
|
|
354
|
+
manifest.shots[shot.id] = {
|
|
355
|
+
state: 'submitted',
|
|
356
|
+
attempt: currentAttempt,
|
|
357
|
+
handle,
|
|
358
|
+
requestFingerprint: submittedFingerprint,
|
|
359
|
+
};
|
|
360
|
+
saveRenderJob(jobDir, manifest);
|
|
361
|
+
}
|
|
362
|
+
opts.onUpdate?.(`Shot ${shot.id}: polling task ${handle.taskId}…`);
|
|
363
|
+
const succeeded = await pollTask({
|
|
364
|
+
check: () => adapter.inspect(resolved.provider, handle, fetch, opts.signal),
|
|
365
|
+
signal: opts.signal,
|
|
366
|
+
}).catch((error) => {
|
|
367
|
+
if (error instanceof RemoteTaskNotFoundError) {
|
|
368
|
+
manifest.shots[shot.id] = {
|
|
369
|
+
state: 'ambiguous',
|
|
370
|
+
attempt: currentAttempt,
|
|
371
|
+
handle,
|
|
372
|
+
requestFingerprint: shotState.requestFingerprint ?? activeFingerprint,
|
|
373
|
+
error: toLogSummary(error),
|
|
374
|
+
};
|
|
375
|
+
saveRenderJob(jobDir, manifest);
|
|
376
|
+
throw new VideoGenError(`Shot "${shot.id}" is no longer found by the provider. Check the provider console, then run /video-gen recover ${jobId} ${shot.id} reset if the task is gone, or adopt its current task id.`, toLogSummary(error));
|
|
377
|
+
}
|
|
378
|
+
if (error instanceof RemoteTaskFailedError) {
|
|
379
|
+
manifest.shots[shot.id] = {
|
|
380
|
+
state: 'failed',
|
|
381
|
+
attempt: currentAttempt,
|
|
382
|
+
error: error instanceof RemoteTaskFailedError ? error.providerMessage : toLogSummary(error),
|
|
383
|
+
};
|
|
384
|
+
saveRenderJob(jobDir, manifest);
|
|
385
|
+
}
|
|
386
|
+
throw error;
|
|
387
|
+
});
|
|
388
|
+
opts.onUpdate?.(`Shot ${shot.id}: downloading…`);
|
|
389
|
+
await adapter.downloadTo(resolved.provider, handle, succeeded.videoUrl, videoPath, fetch, opts.signal);
|
|
390
|
+
manifest.shots[shot.id] = {
|
|
391
|
+
state: 'done',
|
|
392
|
+
attempt: currentAttempt,
|
|
393
|
+
handle,
|
|
394
|
+
requestFingerprint: shotState.requestFingerprint ?? activeFingerprint,
|
|
395
|
+
videoPath,
|
|
396
|
+
};
|
|
397
|
+
saveRenderJob(jobDir, manifest);
|
|
398
|
+
opts.onUpdate?.(`Shot ${shot.id}: done.`);
|
|
399
|
+
};
|
|
400
|
+
try {
|
|
401
|
+
await runPool(spec.shots, opts.settings.concurrency?.clips ?? 2, renderShot);
|
|
402
|
+
}
|
|
403
|
+
catch (error) {
|
|
404
|
+
if (error instanceof CancelledError || opts.signal?.aborted) {
|
|
405
|
+
let cancelledRemotely = 0;
|
|
406
|
+
for (const [shotId, shotState] of Object.entries(manifest.shots)) {
|
|
407
|
+
if (!shotState.handle || shotState.state === 'done')
|
|
408
|
+
continue;
|
|
409
|
+
let cancelled = false;
|
|
410
|
+
if (adapter.cancel) {
|
|
411
|
+
try {
|
|
412
|
+
cancelled = (await adapter.cancel(resolved.provider, shotState.handle, fetch, AbortSignal.timeout(10_000))).cancelled;
|
|
413
|
+
}
|
|
414
|
+
catch {
|
|
415
|
+
console.error('[pi-video-gen] remote cancel failed');
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
if (cancelled) {
|
|
419
|
+
cancelledRemotely++;
|
|
420
|
+
manifest.shots[shotId] = {
|
|
421
|
+
state: 'failed',
|
|
422
|
+
attempt: shotState.attempt,
|
|
423
|
+
error: 'cancelled remotely',
|
|
424
|
+
};
|
|
425
|
+
}
|
|
426
|
+
else {
|
|
427
|
+
manifest.shots[shotId] = { ...shotState, state: 'polling_stopped' };
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
saveRenderJob(jobDir, { ...manifest, state: 'polling_stopped' });
|
|
431
|
+
throw new VideoGenError(cancelledRemotely > 0
|
|
432
|
+
? `Stopped locally and cancelled ${cancelledRemotely} remote task(s). Any remaining tasks may still be running and billable; rerun the same render-input.json to resume them.`
|
|
433
|
+
: `Stopped locally. Remote tasks may still be running and billable. Rerun the same render-input.json to resume after they finish.`, 'render: polling_stopped');
|
|
434
|
+
}
|
|
435
|
+
saveRenderJob(jobDir, { ...manifest, state: 'failed', error: toLogSummary(error) });
|
|
436
|
+
throw error;
|
|
437
|
+
}
|
|
438
|
+
// 5. concat
|
|
439
|
+
manifest.state = 'concatenating';
|
|
440
|
+
saveRenderJob(jobDir, manifest);
|
|
441
|
+
const inputs = spec.shots.map((s) => join(realShotsDir, s.id, 'video.mp4'));
|
|
442
|
+
const finalVideoPath = join(jobDir, 'final_video.mp4');
|
|
443
|
+
opts.onUpdate?.(`Concatenating ${inputs.length} clips…`);
|
|
444
|
+
try {
|
|
445
|
+
await concat({
|
|
446
|
+
inputs,
|
|
447
|
+
outputPath: finalVideoPath,
|
|
448
|
+
ffmpegPath: opts.ffmpegPath,
|
|
449
|
+
signal: opts.signal,
|
|
450
|
+
});
|
|
451
|
+
}
|
|
452
|
+
catch (error) {
|
|
453
|
+
const cancelled = error instanceof CancelledError || opts.signal?.aborted;
|
|
454
|
+
saveRenderJob(jobDir, {
|
|
455
|
+
...manifest,
|
|
456
|
+
state: cancelled ? 'polling_stopped' : 'failed',
|
|
457
|
+
error: toLogSummary(error),
|
|
458
|
+
});
|
|
459
|
+
throw error;
|
|
460
|
+
}
|
|
461
|
+
manifest.state = 'done';
|
|
462
|
+
manifest.finalVideoPath = finalVideoPath;
|
|
463
|
+
saveRenderJob(jobDir, manifest);
|
|
464
|
+
return { jobId, finalVideoPath, shotsDone: spec.shots.length, degraded };
|
|
465
|
+
}
|
|
466
|
+
finally {
|
|
467
|
+
release();
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
/** Recover a snapshot's extension from the manifest's frameHashes (defaults to .png). */
|
|
471
|
+
function pickExt(manifest, shotId, kind) {
|
|
472
|
+
const prefix = join('shots', shotId, kind === 'firstFrame' ? 'first_frame' : 'last_frame');
|
|
473
|
+
for (const relSnap of Object.keys(manifest.frameHashes)) {
|
|
474
|
+
if (relSnap.startsWith(prefix))
|
|
475
|
+
return relSnap.slice(prefix.length);
|
|
476
|
+
}
|
|
477
|
+
return '.png';
|
|
478
|
+
}
|
|
479
|
+
export { errorMessageForUser };
|
|
480
|
+
//# sourceMappingURL=render.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render.js","sourceRoot":"","sources":["../src/render.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { TimelineOverlay, TimelineSubtitles } from './timeline.js';
|
|
2
|
+
export declare function hasCjkFont(): boolean;
|
|
3
|
+
/** Render an overlay to a PNG with alpha, sized to the video frame. */
|
|
4
|
+
export declare function renderTextOverlay(opts: {
|
|
5
|
+
overlay: TimelineOverlay;
|
|
6
|
+
width: number;
|
|
7
|
+
height: number;
|
|
8
|
+
outPath: string;
|
|
9
|
+
}): Promise<string | null>;
|
|
10
|
+
/** Render one narration cue as a branded, bottom-centered burned subtitle. */
|
|
11
|
+
export declare function renderBurnedSubtitle(opts: {
|
|
12
|
+
text: string;
|
|
13
|
+
style: TimelineSubtitles;
|
|
14
|
+
width: number;
|
|
15
|
+
height: number;
|
|
16
|
+
outPath: string;
|
|
17
|
+
}): Promise<string>;
|
|
18
|
+
//# sourceMappingURL=text-layer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"text-layer.d.ts","sourceRoot":"","sources":["../src/text-layer.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAmB,eAAe,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAczF,wBAAgB,UAAU,IAAI,OAAO,CAgBpC;AA6GD,uEAAuE;AACvE,wBAAsB,iBAAiB,CAAC,IAAI,EAAE;IAC5C,OAAO,EAAE,eAAe,CAAC;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;CACjB,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAgBzB;AAED,8EAA8E;AAC9E,wBAAsB,oBAAoB,CAAC,IAAI,EAAE;IAC/C,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,iBAAiB,CAAC;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;CACjB,GAAG,OAAO,CAAC,MAAM,CAAC,CAuClB"}
|