@vibeframe/cli 0.46.2 → 0.47.1
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/dist/commands/doctor.js +20 -0
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/export.d.ts +22 -0
- package/dist/commands/export.d.ts.map +1 -1
- package/dist/commands/export.js +159 -4
- package/dist/commands/export.js.map +1 -1
- package/dist/commands/export.test.d.ts +2 -0
- package/dist/commands/export.test.d.ts.map +1 -0
- package/dist/commands/export.test.js +107 -0
- package/dist/commands/export.test.js.map +1 -0
- package/dist/commands/output.js +1 -1
- package/dist/commands/output.js.map +1 -1
- package/dist/commands/output.test.d.ts +2 -0
- package/dist/commands/output.test.d.ts.map +1 -0
- package/dist/commands/output.test.js +139 -0
- package/dist/commands/output.test.js.map +1 -0
- package/dist/pipeline/renderers/__tests__/html-template.test.d.ts +2 -0
- package/dist/pipeline/renderers/__tests__/html-template.test.d.ts.map +1 -0
- package/dist/pipeline/renderers/__tests__/html-template.test.js +124 -0
- package/dist/pipeline/renderers/__tests__/html-template.test.js.map +1 -0
- package/dist/pipeline/renderers/__tests__/integration.test.d.ts +2 -0
- package/dist/pipeline/renderers/__tests__/integration.test.d.ts.map +1 -0
- package/dist/pipeline/renderers/__tests__/integration.test.js +111 -0
- package/dist/pipeline/renderers/__tests__/integration.test.js.map +1 -0
- package/dist/pipeline/renderers/html-clips.d.ts +20 -0
- package/dist/pipeline/renderers/html-clips.d.ts.map +1 -0
- package/dist/pipeline/renderers/html-clips.js +48 -0
- package/dist/pipeline/renderers/html-clips.js.map +1 -0
- package/dist/pipeline/renderers/html-runtime.d.ts +7 -0
- package/dist/pipeline/renderers/html-runtime.d.ts.map +1 -0
- package/dist/pipeline/renderers/html-runtime.js +80 -0
- package/dist/pipeline/renderers/html-runtime.js.map +1 -0
- package/dist/pipeline/renderers/html-template.d.ts +3 -0
- package/dist/pipeline/renderers/html-template.d.ts.map +1 -0
- package/dist/pipeline/renderers/html-template.js +28 -0
- package/dist/pipeline/renderers/html-template.js.map +1 -0
- package/dist/pipeline/renderers/hyperframes.d.ts +8 -0
- package/dist/pipeline/renderers/hyperframes.d.ts.map +1 -0
- package/dist/pipeline/renderers/hyperframes.js +92 -0
- package/dist/pipeline/renderers/hyperframes.js.map +1 -0
- package/dist/pipeline/renderers/project-builder.d.ts +8 -0
- package/dist/pipeline/renderers/project-builder.d.ts.map +1 -0
- package/dist/pipeline/renderers/project-builder.js +38 -0
- package/dist/pipeline/renderers/project-builder.js.map +1 -0
- package/dist/pipeline/renderers/types.d.ts +39 -0
- package/dist/pipeline/renderers/types.d.ts.map +1 -0
- package/dist/pipeline/renderers/types.js +11 -0
- package/dist/pipeline/renderers/types.js.map +1 -0
- package/package.json +4 -3
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Browser-side runtime script embedded into the generated HTML.
|
|
3
|
+
* Implements window.__hf.seek(t) and effect application.
|
|
4
|
+
* Kept as a string template so it can be embedded inline without a bundler.
|
|
5
|
+
*/
|
|
6
|
+
export const RUNTIME_SCRIPT = `
|
|
7
|
+
(function () {
|
|
8
|
+
var CLIPS = /*CLIPS_JSON*/[];
|
|
9
|
+
|
|
10
|
+
function interpolate(kfs, t) {
|
|
11
|
+
if (!kfs || kfs.length === 0) return null;
|
|
12
|
+
if (kfs.length === 1) return kfs[0].values;
|
|
13
|
+
var prev = kfs[0], next = kfs[kfs.length - 1];
|
|
14
|
+
for (var i = 0; i < kfs.length - 1; i++) {
|
|
15
|
+
if (t >= kfs[i].time && t <= kfs[i + 1].time) { prev = kfs[i]; next = kfs[i + 1]; break; }
|
|
16
|
+
}
|
|
17
|
+
if (t <= prev.time) return prev.values;
|
|
18
|
+
if (t >= next.time) return next.values;
|
|
19
|
+
var raw = (t - prev.time) / (next.time - prev.time);
|
|
20
|
+
var e = prev.easing || 'linear';
|
|
21
|
+
var p = e === 'easeIn' ? raw * raw
|
|
22
|
+
: e === 'easeOut' ? raw * (2 - raw)
|
|
23
|
+
: e === 'easeInOut' ? (raw < 0.5 ? 2 * raw * raw : -1 + (4 - 2 * raw) * raw)
|
|
24
|
+
: raw;
|
|
25
|
+
var out = {};
|
|
26
|
+
for (var k in prev.values) {
|
|
27
|
+
var a = +prev.values[k], b = +next.values[k];
|
|
28
|
+
out[k] = isNaN(a) || isNaN(b) ? prev.values[k] : a + (b - a) * p;
|
|
29
|
+
}
|
|
30
|
+
return out;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function applyEffects(el, effects, clipTime) {
|
|
34
|
+
var opacity = 1;
|
|
35
|
+
var filters = [];
|
|
36
|
+
for (var i = 0; i < effects.length; i++) {
|
|
37
|
+
var fx = effects[i];
|
|
38
|
+
var t = clipTime - fx.startTime;
|
|
39
|
+
if (t < 0 || t > fx.duration) continue;
|
|
40
|
+
var vals = (fx.keyframes && fx.keyframes.length > 0)
|
|
41
|
+
? interpolate(fx.keyframes, t)
|
|
42
|
+
: fx.params;
|
|
43
|
+
if (!vals) continue;
|
|
44
|
+
switch (fx.type) {
|
|
45
|
+
case 'fadeIn':
|
|
46
|
+
opacity = Math.min(opacity, t / fx.duration * (+(vals.intensity || 1))); break;
|
|
47
|
+
case 'fadeOut':
|
|
48
|
+
opacity = Math.min(opacity, (1 - t / fx.duration) * (+(vals.intensity || 1))); break;
|
|
49
|
+
case 'blur':
|
|
50
|
+
filters.push('blur(' + (+vals.radius || 0) + 'px)'); break;
|
|
51
|
+
case 'brightness':
|
|
52
|
+
filters.push('brightness(' + (+vals.value || 1) + ')'); break;
|
|
53
|
+
case 'contrast':
|
|
54
|
+
filters.push('contrast(' + (+vals.value || 1) + ')'); break;
|
|
55
|
+
case 'saturation':
|
|
56
|
+
filters.push('saturate(' + (+vals.value || 1) + ')'); break;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
el.style.opacity = String(opacity);
|
|
60
|
+
if (filters.length > 0) el.style.filter = filters.join(' ');
|
|
61
|
+
else el.style.filter = '';
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
window.__hf = {
|
|
65
|
+
duration: /*DURATION*/0,
|
|
66
|
+
media: /*MEDIA_JSON*/[],
|
|
67
|
+
seek: function (t) {
|
|
68
|
+
for (var i = 0; i < CLIPS.length; i++) {
|
|
69
|
+
var c = CLIPS[i];
|
|
70
|
+
var el = document.getElementById(c.id);
|
|
71
|
+
if (!el) continue;
|
|
72
|
+
var active = t >= c.startTime && t < c.startTime + c.duration;
|
|
73
|
+
el.style.display = active ? 'block' : 'none';
|
|
74
|
+
if (active) applyEffects(el, c.effects, t - c.startTime);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
})();
|
|
79
|
+
`;
|
|
80
|
+
//# sourceMappingURL=html-runtime.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"html-runtime.js","sourceRoot":"","sources":["../../../src/pipeline/renderers/html-runtime.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,MAAM,CAAC,MAAM,cAAc,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAyE7B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"html-template.d.ts","sourceRoot":"","sources":["../../../src/pipeline/renderers/html-template.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AASrD,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,aAAa,GAAG,MAAM,CAyBpE"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { aspectToResolution } from "./hyperframes.js";
|
|
2
|
+
import { buildClipElements, buildClipRuntimeData, buildMediaDeclarations, } from "./html-clips.js";
|
|
3
|
+
import { RUNTIME_SCRIPT } from "./html-runtime.js";
|
|
4
|
+
export function generateCompositionHtml(state) {
|
|
5
|
+
const { width, height } = aspectToResolution(state.project.aspectRatio);
|
|
6
|
+
const clipMarkup = buildClipElements(state);
|
|
7
|
+
const mediaDecls = buildMediaDeclarations(state);
|
|
8
|
+
const clipData = buildClipRuntimeData(state);
|
|
9
|
+
const duration = state.project.duration;
|
|
10
|
+
const script = RUNTIME_SCRIPT
|
|
11
|
+
.replace("/*CLIPS_JSON*/[]", JSON.stringify(clipData))
|
|
12
|
+
.replace("/*DURATION*/0", String(duration))
|
|
13
|
+
.replace("/*MEDIA_JSON*/[]", JSON.stringify(mediaDecls));
|
|
14
|
+
return `<!DOCTYPE html>
|
|
15
|
+
<html><head>
|
|
16
|
+
<meta charset="utf-8">
|
|
17
|
+
<style>
|
|
18
|
+
html, body { margin: 0; width: ${width}px; height: ${height}px; overflow: hidden; background: #000; }
|
|
19
|
+
.clip { position: absolute; inset: 0; display: none; }
|
|
20
|
+
</style>
|
|
21
|
+
</head><body>
|
|
22
|
+
${clipMarkup}
|
|
23
|
+
<script>
|
|
24
|
+
${script}
|
|
25
|
+
</script>
|
|
26
|
+
</body></html>`;
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=html-template.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"html-template.js","sourceRoot":"","sources":["../../../src/pipeline/renderers/html-template.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EACL,iBAAiB,EACjB,oBAAoB,EACpB,sBAAsB,GACvB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAEnD,MAAM,UAAU,uBAAuB,CAAC,KAAoB;IAC1D,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,kBAAkB,CAAC,KAAK,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;IACxE,MAAM,UAAU,GAAG,iBAAiB,CAAC,KAAK,CAAC,CAAC;IAC5C,MAAM,UAAU,GAAG,sBAAsB,CAAC,KAAK,CAAC,CAAC;IACjD,MAAM,QAAQ,GAAG,oBAAoB,CAAC,KAAK,CAAC,CAAC;IAC7C,MAAM,QAAQ,GAAG,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC;IAExC,MAAM,MAAM,GAAG,cAAc;SAC1B,OAAO,CAAC,kBAAkB,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;SACrD,OAAO,CAAC,eAAe,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;SAC1C,OAAO,CAAC,kBAAkB,EAAE,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC,CAAC;IAE3D,OAAO;;;;mCAI0B,KAAK,eAAe,MAAM;;;;IAIzD,UAAU;;EAEZ,MAAM;;eAEO,CAAC;AAChB,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { RenderBackend } from "./types.js";
|
|
2
|
+
export declare function createHyperframesBackend(): RenderBackend;
|
|
3
|
+
export declare function aspectToResolution(ratio: string): {
|
|
4
|
+
width: number;
|
|
5
|
+
height: number;
|
|
6
|
+
};
|
|
7
|
+
export declare function qualityToCrf(quality?: "draft" | "standard" | "high"): number;
|
|
8
|
+
//# sourceMappingURL=hyperframes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hyperframes.d.ts","sourceRoot":"","sources":["../../../src/pipeline/renderers/hyperframes.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,aAAa,EAA+B,MAAM,YAAY,CAAC;AAuB7E,wBAAgB,wBAAwB,IAAI,aAAa,CAiExD;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAQnF;AAED,wBAAgB,YAAY,CAAC,OAAO,GAAE,OAAO,GAAG,UAAU,GAAG,MAAmB,GAAG,MAAM,CAExF"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import { homedir } from "node:os";
|
|
3
|
+
import * as path from "node:path";
|
|
4
|
+
function findChrome() {
|
|
5
|
+
const candidates = [
|
|
6
|
+
process.env.HYPERFRAMES_CHROME_PATH,
|
|
7
|
+
process.env.CHROME_PATH,
|
|
8
|
+
// puppeteer auto-downloaded headless shell
|
|
9
|
+
path.join(homedir(), ".cache", "puppeteer", "chrome-headless-shell", "mac_arm-147.0.7727.56", "chrome-headless-shell-mac_arm", "chrome-headless-shell"),
|
|
10
|
+
// system Chrome / Chromium
|
|
11
|
+
"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome",
|
|
12
|
+
"/Applications/Chromium.app/Contents/MacOS/Chromium",
|
|
13
|
+
"/usr/bin/google-chrome",
|
|
14
|
+
"/usr/bin/chromium",
|
|
15
|
+
"/usr/bin/chromium-browser",
|
|
16
|
+
"C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe",
|
|
17
|
+
];
|
|
18
|
+
for (const c of candidates) {
|
|
19
|
+
if (c && existsSync(c))
|
|
20
|
+
return c;
|
|
21
|
+
}
|
|
22
|
+
return undefined;
|
|
23
|
+
}
|
|
24
|
+
export function createHyperframesBackend() {
|
|
25
|
+
return {
|
|
26
|
+
name: "hyperframes",
|
|
27
|
+
async preflight() {
|
|
28
|
+
const chrome = findChrome();
|
|
29
|
+
if (chrome)
|
|
30
|
+
return { ok: true };
|
|
31
|
+
return {
|
|
32
|
+
ok: false,
|
|
33
|
+
reason: "Chrome not found. Set HYPERFRAMES_CHROME_PATH, or install Chrome " +
|
|
34
|
+
"(macOS: brew install --cask google-chrome · Linux: apt install chromium). " +
|
|
35
|
+
"Run `vibe doctor` for details.",
|
|
36
|
+
};
|
|
37
|
+
},
|
|
38
|
+
async render(options) {
|
|
39
|
+
const pre = await this.preflight();
|
|
40
|
+
if (!pre.ok)
|
|
41
|
+
return { success: false, error: pre.reason };
|
|
42
|
+
const { buildTempProject } = await import("./project-builder.js");
|
|
43
|
+
const { createRenderJob, executeRenderJob } = await import("@hyperframes/producer");
|
|
44
|
+
let project;
|
|
45
|
+
const start = Date.now();
|
|
46
|
+
try {
|
|
47
|
+
project = await buildTempProject(options.projectState);
|
|
48
|
+
}
|
|
49
|
+
catch (err) {
|
|
50
|
+
return {
|
|
51
|
+
success: false,
|
|
52
|
+
error: `Failed to build temp project: ${err instanceof Error ? err.message : String(err)}`,
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
const config = {
|
|
56
|
+
fps: options.fps ?? 30,
|
|
57
|
+
quality: options.quality ?? "standard",
|
|
58
|
+
format: options.format ?? "mp4",
|
|
59
|
+
entryFile: "index.html",
|
|
60
|
+
crf: qualityToCrf(options.quality),
|
|
61
|
+
};
|
|
62
|
+
const job = createRenderJob(config);
|
|
63
|
+
try {
|
|
64
|
+
await executeRenderJob(job, project.dir, options.outputPath, (j, msg) => { options.onProgress?.(j.progress, j.currentStage ?? msg); }, options.signal);
|
|
65
|
+
await project.cleanup();
|
|
66
|
+
return {
|
|
67
|
+
success: true,
|
|
68
|
+
outputPath: options.outputPath,
|
|
69
|
+
durationMs: Date.now() - start,
|
|
70
|
+
framesRendered: job.framesRendered,
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
catch (err) {
|
|
74
|
+
console.error(`[hyperframes] render failed. Temp dir preserved: ${project?.dir}`);
|
|
75
|
+
return { success: false, error: err instanceof Error ? err.message : String(err) };
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
export function aspectToResolution(ratio) {
|
|
81
|
+
switch (ratio) {
|
|
82
|
+
case "16:9": return { width: 1920, height: 1080 };
|
|
83
|
+
case "9:16": return { width: 1080, height: 1920 };
|
|
84
|
+
case "1:1": return { width: 1080, height: 1080 };
|
|
85
|
+
case "4:5": return { width: 1080, height: 1350 };
|
|
86
|
+
default: return { width: 1920, height: 1080 };
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
export function qualityToCrf(quality = "standard") {
|
|
90
|
+
return quality === "draft" ? 28 : quality === "high" ? 18 : 23;
|
|
91
|
+
}
|
|
92
|
+
//# sourceMappingURL=hyperframes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hyperframes.js","sourceRoot":"","sources":["../../../src/pipeline/renderers/hyperframes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAIlC,SAAS,UAAU;IACjB,MAAM,UAAU,GAAG;QACjB,OAAO,CAAC,GAAG,CAAC,uBAAuB;QACnC,OAAO,CAAC,GAAG,CAAC,WAAW;QACvB,2CAA2C;QAC3C,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,QAAQ,EAAE,WAAW,EAAE,uBAAuB,EAAE,uBAAuB,EAC1F,+BAA+B,EAAE,uBAAuB,CAAC;QAC3D,2BAA2B;QAC3B,8DAA8D;QAC9D,oDAAoD;QACpD,wBAAwB;QACxB,mBAAmB;QACnB,2BAA2B;QAC3B,4DAA4D;KAC7D,CAAC;IACF,KAAK,MAAM,CAAC,IAAI,UAAU,EAAE,CAAC;QAC3B,IAAI,CAAC,IAAI,UAAU,CAAC,CAAC,CAAC;YAAE,OAAO,CAAC,CAAC;IACnC,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,MAAM,UAAU,wBAAwB;IACtC,OAAO;QACL,IAAI,EAAE,aAAa;QAEnB,KAAK,CAAC,SAAS;YACb,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;YAC5B,IAAI,MAAM;gBAAE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;YAChC,OAAO;gBACL,EAAE,EAAE,KAAK;gBACT,MAAM,EACJ,mEAAmE;oBACnE,4EAA4E;oBAC5E,gCAAgC;aACnC,CAAC;QACJ,CAAC;QAED,KAAK,CAAC,MAAM,CAAC,OAAsB;YACjC,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,SAAU,EAAE,CAAC;YACpC,IAAI,CAAC,GAAG,CAAC,EAAE;gBAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAG,GAAqC,CAAC,MAAM,EAAE,CAAC;YAE7F,MAAM,EAAE,gBAAgB,EAAE,GAAG,MAAM,MAAM,CAAC,sBAAsB,CAAC,CAAC;YAClE,MAAM,EAAE,eAAe,EAAE,gBAAgB,EAAE,GAAG,MAAM,MAAM,CAAC,uBAAuB,CAAC,CAAC;YAEpF,IAAI,OAAiE,CAAC;YACtE,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;YAEzB,IAAI,CAAC;gBACH,OAAO,GAAG,MAAM,gBAAgB,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;YACzD,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,OAAO;oBACL,OAAO,EAAE,KAAK;oBACd,KAAK,EAAE,iCAAiC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE;iBAC3F,CAAC;YACJ,CAAC;YAED,MAAM,MAAM,GAAiB;gBAC3B,GAAG,EAAE,OAAO,CAAC,GAAG,IAAI,EAAE;gBACtB,OAAO,EAAE,OAAO,CAAC,OAAO,IAAI,UAAU;gBACtC,MAAM,EAAE,OAAO,CAAC,MAAM,IAAI,KAAK;gBAC/B,SAAS,EAAE,YAAY;gBACvB,GAAG,EAAE,YAAY,CAAC,OAAO,CAAC,OAAO,CAAC;aACnC,CAAC;YACF,MAAM,GAAG,GAAG,eAAe,CAAC,MAAM,CAAC,CAAC;YAEpC,IAAI,CAAC;gBACH,MAAM,gBAAgB,CACpB,GAAG,EACH,OAAO,CAAC,GAAG,EACX,OAAO,CAAC,UAAU,EAClB,CAAC,CAAC,EAAE,GAAG,EAAE,EAAE,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,YAAY,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,EACxE,OAAO,CAAC,MAAM,CACf,CAAC;gBACF,MAAM,OAAO,CAAC,OAAO,EAAE,CAAC;gBACxB,OAAO;oBACL,OAAO,EAAE,IAAI;oBACb,UAAU,EAAE,OAAO,CAAC,UAAU;oBAC9B,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK;oBAC9B,cAAc,EAAE,GAAG,CAAC,cAAc;iBACnC,CAAC;YACJ,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,OAAO,CAAC,KAAK,CAAC,oDAAoD,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC;gBAClF,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;YACrF,CAAC;QACH,CAAC;KACF,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,KAAa;IAC9C,QAAQ,KAAK,EAAE,CAAC;QACd,KAAK,MAAM,CAAC,CAAC,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;QAClD,KAAK,MAAM,CAAC,CAAC,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;QAClD,KAAK,KAAK,CAAC,CAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;QAClD,KAAK,KAAK,CAAC,CAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;QAClD,OAAO,CAAC,CAAK,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;IACpD,CAAC;AACH,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,UAAyC,UAAU;IAC9E,OAAO,OAAO,KAAK,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,KAAK,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;AACjE,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { TimelineState } from "@vibeframe/core";
|
|
2
|
+
export interface TempProject {
|
|
3
|
+
dir: string;
|
|
4
|
+
cleanup: () => Promise<void>;
|
|
5
|
+
}
|
|
6
|
+
export declare function buildTempProject(state: TimelineState, projectFileDir?: string): Promise<TempProject>;
|
|
7
|
+
export declare function resolveSourceUrl(url: string, baseDir?: string): string;
|
|
8
|
+
//# sourceMappingURL=project-builder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project-builder.d.ts","sourceRoot":"","sources":["../../../src/pipeline/renderers/project-builder.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAGrD,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9B;AAED,wBAAsB,gBAAgB,CACpC,KAAK,EAAE,aAAa,EACpB,cAAc,CAAC,EAAE,MAAM,GACtB,OAAO,CAAC,WAAW,CAAC,CAwBtB;AAED,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAKtE"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { mkdtemp, mkdir, copyFile, writeFile, rm } from "node:fs/promises";
|
|
2
|
+
import { existsSync } from "node:fs";
|
|
3
|
+
import { tmpdir } from "node:os";
|
|
4
|
+
import * as path from "node:path";
|
|
5
|
+
import { generateCompositionHtml } from "./html-template.js";
|
|
6
|
+
export async function buildTempProject(state, projectFileDir) {
|
|
7
|
+
const dir = await mkdtemp(path.join(tmpdir(), "vibeframe-hf-"));
|
|
8
|
+
const assetsDir = path.join(dir, "assets");
|
|
9
|
+
await mkdir(assetsDir, { recursive: true });
|
|
10
|
+
const copied = new Map();
|
|
11
|
+
for (const source of state.sources) {
|
|
12
|
+
if (copied.has(source.id))
|
|
13
|
+
continue;
|
|
14
|
+
const resolved = resolveSourceUrl(source.url, projectFileDir);
|
|
15
|
+
if (!existsSync(resolved)) {
|
|
16
|
+
throw new Error(`Source file not found: ${resolved} (from source id=${source.id})`);
|
|
17
|
+
}
|
|
18
|
+
const dest = path.join(assetsDir, path.basename(resolved));
|
|
19
|
+
await copyFile(resolved, dest);
|
|
20
|
+
copied.set(source.id, dest);
|
|
21
|
+
}
|
|
22
|
+
const html = generateCompositionHtml(state);
|
|
23
|
+
await writeFile(path.join(dir, "index.html"), html, "utf-8");
|
|
24
|
+
return {
|
|
25
|
+
dir,
|
|
26
|
+
cleanup: () => rm(dir, { recursive: true, force: true }),
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
export function resolveSourceUrl(url, baseDir) {
|
|
30
|
+
if (url.startsWith("file://"))
|
|
31
|
+
return url.slice(7);
|
|
32
|
+
if (path.isAbsolute(url))
|
|
33
|
+
return url;
|
|
34
|
+
if (baseDir)
|
|
35
|
+
return path.resolve(baseDir, url);
|
|
36
|
+
return path.resolve(process.cwd(), url);
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=project-builder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project-builder.js","sourceRoot":"","sources":["../../../src/pipeline/renderers/project-builder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE,EAAE,MAAM,kBAAkB,CAAC;AAC3E,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAElC,OAAO,EAAE,uBAAuB,EAAE,MAAM,oBAAoB,CAAC;AAO7D,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,KAAoB,EACpB,cAAuB;IAEvB,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,eAAe,CAAC,CAAC,CAAC;IAChE,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;IAC3C,MAAM,KAAK,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAE5C,MAAM,MAAM,GAAG,IAAI,GAAG,EAAkB,CAAC;IACzC,KAAK,MAAM,MAAM,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;QACnC,IAAI,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;YAAE,SAAS;QACpC,MAAM,QAAQ,GAAG,gBAAgB,CAAC,MAAM,CAAC,GAAG,EAAE,cAAc,CAAC,CAAC;QAC9D,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC1B,MAAM,IAAI,KAAK,CAAC,0BAA0B,QAAQ,oBAAoB,MAAM,CAAC,EAAE,GAAG,CAAC,CAAC;QACtF,CAAC;QACD,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC;QAC3D,MAAM,QAAQ,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;QAC/B,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;IAC9B,CAAC;IAED,MAAM,IAAI,GAAG,uBAAuB,CAAC,KAAK,CAAC,CAAC;IAC5C,MAAM,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,YAAY,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;IAE7D,OAAO;QACL,GAAG;QACH,OAAO,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;KACzD,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,GAAW,EAAE,OAAgB;IAC5D,IAAI,GAAG,CAAC,UAAU,CAAC,SAAS,CAAC;QAAE,OAAO,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACnD,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE,OAAO,GAAG,CAAC;IACrC,IAAI,OAAO;QAAE,OAAO,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;IAC/C,OAAO,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,GAAG,CAAC,CAAC;AAC1C,CAAC"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Render backend abstraction for the VibeFrame export pipeline.
|
|
3
|
+
*
|
|
4
|
+
* Existing FFmpeg-filter-graph path lives in packages/cli/src/commands/export.ts.
|
|
5
|
+
* New backends (hyperframes, future Remotion bridge) implement RenderBackend
|
|
6
|
+
* to slot in via `vibe export --backend` or YAML `render.backend`.
|
|
7
|
+
*
|
|
8
|
+
* See docs/design/hyperframes-adapter.md for the Hyperframes wiring plan.
|
|
9
|
+
*/
|
|
10
|
+
import type { TimelineState } from "@vibeframe/core";
|
|
11
|
+
export type BackendName = "ffmpeg" | "hyperframes";
|
|
12
|
+
export interface RenderOptions {
|
|
13
|
+
projectState: TimelineState;
|
|
14
|
+
outputPath: string;
|
|
15
|
+
fps?: 24 | 30 | 60;
|
|
16
|
+
quality?: "draft" | "standard" | "high";
|
|
17
|
+
format?: "mp4" | "webm" | "mov";
|
|
18
|
+
onProgress?: (pct: number, stage: string) => void;
|
|
19
|
+
signal?: AbortSignal;
|
|
20
|
+
}
|
|
21
|
+
export interface RenderResult {
|
|
22
|
+
success: boolean;
|
|
23
|
+
outputPath?: string;
|
|
24
|
+
durationMs?: number;
|
|
25
|
+
framesRendered?: number;
|
|
26
|
+
error?: string;
|
|
27
|
+
}
|
|
28
|
+
export interface RenderBackend {
|
|
29
|
+
name: BackendName;
|
|
30
|
+
/** Human-readable check before invocation (e.g. Chrome present, FFmpeg version). */
|
|
31
|
+
preflight?(): Promise<{
|
|
32
|
+
ok: true;
|
|
33
|
+
} | {
|
|
34
|
+
ok: false;
|
|
35
|
+
reason: string;
|
|
36
|
+
}>;
|
|
37
|
+
render(options: RenderOptions): Promise<RenderResult>;
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/pipeline/renderers/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAErD,MAAM,MAAM,WAAW,GAAG,QAAQ,GAAG,aAAa,CAAC;AAEnD,MAAM,WAAW,aAAa;IAC5B,YAAY,EAAE,aAAa,CAAC;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,GAAG,CAAC,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC;IACnB,OAAO,CAAC,EAAE,OAAO,GAAG,UAAU,GAAG,MAAM,CAAC;IACxC,MAAM,CAAC,EAAE,KAAK,GAAG,MAAM,GAAG,KAAK,CAAC;IAChC,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClD,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,WAAW,CAAC;IAClB,oFAAoF;IACpF,SAAS,CAAC,IAAI,OAAO,CAAC;QAAE,EAAE,EAAE,IAAI,CAAA;KAAE,GAAG;QAAE,EAAE,EAAE,KAAK,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACpE,MAAM,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;CACvD"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Render backend abstraction for the VibeFrame export pipeline.
|
|
3
|
+
*
|
|
4
|
+
* Existing FFmpeg-filter-graph path lives in packages/cli/src/commands/export.ts.
|
|
5
|
+
* New backends (hyperframes, future Remotion bridge) implement RenderBackend
|
|
6
|
+
* to slot in via `vibe export --backend` or YAML `render.backend`.
|
|
7
|
+
*
|
|
8
|
+
* See docs/design/hyperframes-adapter.md for the Hyperframes wiring plan.
|
|
9
|
+
*/
|
|
10
|
+
export {};
|
|
11
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/pipeline/renderers/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vibeframe/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.47.1",
|
|
4
4
|
"description": "VibeFrame CLI - natural language video editing from the terminal",
|
|
5
5
|
"private": false,
|
|
6
6
|
"license": "MIT",
|
|
@@ -103,6 +103,7 @@
|
|
|
103
103
|
"dependencies": {
|
|
104
104
|
"@anthropic-ai/sdk": "^0.39.0",
|
|
105
105
|
"@google/generative-ai": "^0.21.0",
|
|
106
|
+
"@hyperframes/producer": "^0.4.4",
|
|
106
107
|
"chalk": "^5.3.0",
|
|
107
108
|
"commander": "^12.0.0",
|
|
108
109
|
"dotenv": "^17.2.3",
|
|
@@ -111,8 +112,8 @@
|
|
|
111
112
|
"openai": "^4.77.0",
|
|
112
113
|
"ora": "^8.0.1",
|
|
113
114
|
"yaml": "^2.3.4",
|
|
114
|
-
"@vibeframe/core": "0.
|
|
115
|
-
"@vibeframe/ai-providers": "0.
|
|
115
|
+
"@vibeframe/core": "0.47.1",
|
|
116
|
+
"@vibeframe/ai-providers": "0.47.1"
|
|
116
117
|
},
|
|
117
118
|
"devDependencies": {
|
|
118
119
|
"@types/node": "^20.11.0",
|