loopwind 0.9.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/FONTS.md +156 -0
- package/HELPERS_DEMO.md +134 -0
- package/PROJECT_STRUCTURE.md +286 -0
- package/PUBLISHING.md +171 -0
- package/README.md +1020 -0
- package/REGISTRY_SETUP.md +427 -0
- package/SHADCN_INTEGRATION.md +269 -0
- package/TAILWIND.md +228 -0
- package/TEMPLATE_SOURCES.md +363 -0
- package/_dsgn/templates/banner-hero/banner-hero.tsx +57 -0
- package/_dsgn/templates/banner-hero/meta.json +14 -0
- package/_dsgn/templates/composite-card/meta.json +16 -0
- package/_dsgn/templates/composite-card/template.tsx +44 -0
- package/_dsgn/templates/image/meta.json +13 -0
- package/_dsgn/templates/image/template.tsx +28 -0
- package/_dsgn/templates/kitchen-sink/meta.json +13 -0
- package/_dsgn/templates/kitchen-sink/template.tsx +72 -0
- package/_dsgn/templates/qr-card/meta.json +14 -0
- package/_dsgn/templates/qr-card/template.tsx +39 -0
- package/_dsgn/templates/test-parent/child/meta.json +11 -0
- package/_dsgn/templates/test-parent/child/template.tsx +27 -0
- package/_dsgn/templates/test-parent/meta.json +12 -0
- package/_dsgn/templates/test-parent/template.tsx +30 -0
- package/_dsgn/templates/test-sibling/meta.json +11 -0
- package/_dsgn/templates/test-sibling/template.tsx +20 -0
- package/_dsgn/templates/video/.tmp/template-1763421345296.mjs +43 -0
- package/_dsgn/templates/video/.tmp/template-1763421362228.mjs +43 -0
- package/_dsgn/templates/video/.tmp/template-1763421377706.mjs +43 -0
- package/_dsgn/templates/video/meta.json +17 -0
- package/_dsgn/templates/video/template.tsx +48 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +70 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/add.d.ts +6 -0
- package/dist/commands/add.d.ts.map +1 -0
- package/dist/commands/add.js +86 -0
- package/dist/commands/add.js.map +1 -0
- package/dist/commands/default.d.ts +2 -0
- package/dist/commands/default.d.ts.map +1 -0
- package/dist/commands/default.js +69 -0
- package/dist/commands/default.js.map +1 -0
- package/dist/commands/init.d.ts +2 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +75 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/list.d.ts +2 -0
- package/dist/commands/list.d.ts.map +1 -0
- package/dist/commands/list.js +83 -0
- package/dist/commands/list.js.map +1 -0
- package/dist/commands/preview.d.ts +3 -0
- package/dist/commands/preview.d.ts.map +1 -0
- package/dist/commands/preview.js +296 -0
- package/dist/commands/preview.js.map +1 -0
- package/dist/commands/render.d.ts +10 -0
- package/dist/commands/render.d.ts.map +1 -0
- package/dist/commands/render.js +204 -0
- package/dist/commands/render.js.map +1 -0
- package/dist/commands/validate.d.ts +2 -0
- package/dist/commands/validate.d.ts.map +1 -0
- package/dist/commands/validate.js +107 -0
- package/dist/commands/validate.js.map +1 -0
- package/dist/default-templates/AGENTS.md +229 -0
- package/dist/default-templates/image/meta.json +13 -0
- package/dist/default-templates/image/template.d.ts +20 -0
- package/dist/default-templates/image/template.d.ts.map +1 -0
- package/dist/default-templates/image/template.js +18 -0
- package/dist/default-templates/image/template.js.map +1 -0
- package/dist/default-templates/image/template.tsx +20 -0
- package/dist/default-templates/image-template/meta.json +13 -0
- package/dist/default-templates/image-template/template.tsx +19 -0
- package/dist/default-templates/kitchen-sink/meta.json +13 -0
- package/dist/default-templates/kitchen-sink/template.tsx +64 -0
- package/dist/default-templates/page/meta.json +17 -0
- package/dist/default-templates/page/template.tsx +37 -0
- package/dist/default-templates/video/meta.json +17 -0
- package/dist/default-templates/video/template.d.ts +26 -0
- package/dist/default-templates/video/template.d.ts.map +1 -0
- package/dist/default-templates/video/template.js +33 -0
- package/dist/default-templates/video/template.js.map +1 -0
- package/dist/default-templates/video/template.tsx +37 -0
- package/dist/default-templates/video-template/meta.json +17 -0
- package/dist/default-templates/video-template/template.tsx +36 -0
- package/dist/default-templates/website/meta.json +16 -0
- package/dist/default-templates/website/pages/home.tsx +17 -0
- package/dist/default-templates/website/parts/footer.tsx +17 -0
- package/dist/default-templates/website/parts/header.tsx +17 -0
- package/dist/default-templates/website/template.tsx +17 -0
- package/dist/default-templates/website-template/meta.json +16 -0
- package/dist/default-templates/website-template/pages/home.tsx +16 -0
- package/dist/default-templates/website-template/parts/footer.tsx +16 -0
- package/dist/default-templates/website-template/parts/header.tsx +16 -0
- package/dist/default-templates/website-template/template.tsx +16 -0
- package/dist/lib/config.d.ts +34 -0
- package/dist/lib/config.d.ts.map +1 -0
- package/dist/lib/config.js +248 -0
- package/dist/lib/config.js.map +1 -0
- package/dist/lib/constants.d.ts +7 -0
- package/dist/lib/constants.d.ts.map +1 -0
- package/dist/lib/constants.js +12 -0
- package/dist/lib/constants.js.map +1 -0
- package/dist/lib/helpers.d.ts +29 -0
- package/dist/lib/helpers.d.ts.map +1 -0
- package/dist/lib/helpers.js +159 -0
- package/dist/lib/helpers.js.map +1 -0
- package/dist/lib/installer.d.ts +51 -0
- package/dist/lib/installer.d.ts.map +1 -0
- package/dist/lib/installer.js +215 -0
- package/dist/lib/installer.js.map +1 -0
- package/dist/lib/renderer.d.ts +51 -0
- package/dist/lib/renderer.d.ts.map +1 -0
- package/dist/lib/renderer.js +524 -0
- package/dist/lib/renderer.js.map +1 -0
- package/dist/lib/tailwind-config-loader.d.ts +47 -0
- package/dist/lib/tailwind-config-loader.d.ts.map +1 -0
- package/dist/lib/tailwind-config-loader.js +432 -0
- package/dist/lib/tailwind-config-loader.js.map +1 -0
- package/dist/lib/tailwind-detector.d.ts +36 -0
- package/dist/lib/tailwind-detector.d.ts.map +1 -0
- package/dist/lib/tailwind-detector.js +156 -0
- package/dist/lib/tailwind-detector.js.map +1 -0
- package/dist/lib/tailwind.d.ts +8 -0
- package/dist/lib/tailwind.d.ts.map +1 -0
- package/dist/lib/tailwind.js +994 -0
- package/dist/lib/tailwind.js.map +1 -0
- package/dist/lib/template-validator.d.ts +22 -0
- package/dist/lib/template-validator.d.ts.map +1 -0
- package/dist/lib/template-validator.js +174 -0
- package/dist/lib/template-validator.js.map +1 -0
- package/dist/lib/utils.d.ts +44 -0
- package/dist/lib/utils.d.ts.map +1 -0
- package/dist/lib/utils.js +207 -0
- package/dist/lib/utils.js.map +1 -0
- package/dist/lib/version-check.d.ts +16 -0
- package/dist/lib/version-check.d.ts.map +1 -0
- package/dist/lib/version-check.js +88 -0
- package/dist/lib/version-check.js.map +1 -0
- package/dist/lib/video-renderer.d.ts +32 -0
- package/dist/lib/video-renderer.d.ts.map +1 -0
- package/dist/lib/video-renderer.js +226 -0
- package/dist/lib/video-renderer.js.map +1 -0
- package/dist/sdk/index.d.ts +58 -0
- package/dist/sdk/index.d.ts.map +1 -0
- package/dist/sdk/index.js +119 -0
- package/dist/sdk/index.js.map +1 -0
- package/dist/sdk/template.d.ts +40 -0
- package/dist/sdk/template.d.ts.map +1 -0
- package/dist/sdk/template.js +60 -0
- package/dist/sdk/template.js.map +1 -0
- package/dist/types/config.d.ts +62 -0
- package/dist/types/config.d.ts.map +1 -0
- package/dist/types/config.js +47 -0
- package/dist/types/config.js.map +1 -0
- package/dist/types/template.d.ts +79 -0
- package/dist/types/template.d.ts.map +1 -0
- package/dist/types/template.js +2 -0
- package/dist/types/template.js.map +1 -0
- package/examples/nextjs-api/README.md +180 -0
- package/examples/nextjs-api/package.json +21 -0
- package/examples/nextjs-api/pages/api/intro-video.ts +53 -0
- package/examples/nextjs-api/pages/api/og-image.ts +50 -0
- package/netlify.toml +13 -0
- package/package.json +84 -0
- package/patches/satori+0.18.3.patch +13 -0
- package/test-templates/TESTS.md +63 -0
- package/test-templates/_dsgn/templates/absolute-spin/meta.json +7 -0
- package/test-templates/_dsgn/templates/absolute-spin/template.tsx +16 -0
- package/test-templates/_dsgn/templates/animated-intro/.tmp/template-1763468771640.mjs +7 -0
- package/test-templates/_dsgn/templates/animated-intro/meta.json +10 -0
- package/test-templates/_dsgn/templates/animated-intro/template.tsx +23 -0
- package/test-templates/_dsgn/templates/centered-spin/.tmp/template-1763468525386.mjs +7 -0
- package/test-templates/_dsgn/templates/centered-spin/meta.json +7 -0
- package/test-templates/_dsgn/templates/centered-spin/template.tsx +11 -0
- package/test-templates/_dsgn/templates/composite/.tmp/template-1763468815645.mjs +7 -0
- package/test-templates/_dsgn/templates/composite/meta.json +9 -0
- package/test-templates/_dsgn/templates/composite/template.tsx +23 -0
- package/test-templates/_dsgn/templates/easing-test/.tmp/template-1763468824501.mjs +7 -0
- package/test-templates/_dsgn/templates/easing-test/meta.json +7 -0
- package/test-templates/_dsgn/templates/easing-test/template.tsx +47 -0
- package/test-templates/_dsgn/templates/minimal-spin/.tmp/template-1763466364336.mjs +10 -0
- package/test-templates/_dsgn/templates/minimal-spin/.tmp/template-1763466584319.mjs +10 -0
- package/test-templates/_dsgn/templates/minimal-spin/.tmp/template-1763466667797.mjs +10 -0
- package/test-templates/_dsgn/templates/minimal-spin/.tmp/template-1763466746504.mjs +10 -0
- package/test-templates/_dsgn/templates/minimal-spin/.tmp/template-1763466930225.mjs +10 -0
- package/test-templates/_dsgn/templates/minimal-spin/.tmp/template-1763467004552.mjs +10 -0
- package/test-templates/_dsgn/templates/minimal-spin/.tmp/template-1763467060334.mjs +10 -0
- package/test-templates/_dsgn/templates/minimal-spin/.tmp/template-1763467124493.mjs +10 -0
- package/test-templates/_dsgn/templates/minimal-spin/.tmp/template-1763467174690.mjs +10 -0
- package/test-templates/_dsgn/templates/minimal-spin/.tmp/template-1763467359134.mjs +10 -0
- package/test-templates/_dsgn/templates/minimal-spin/.tmp/template-1763467451928.mjs +10 -0
- package/test-templates/_dsgn/templates/minimal-spin/.tmp/template-1763467758275.mjs +10 -0
- package/test-templates/_dsgn/templates/minimal-spin/.tmp/template-1763467985201.mjs +10 -0
- package/test-templates/_dsgn/templates/minimal-spin/.tmp/template-1763468020563.mjs +10 -0
- package/test-templates/_dsgn/templates/minimal-spin/.tmp/template-1763468090428.mjs +10 -0
- package/test-templates/_dsgn/templates/minimal-spin/.tmp/template-1763468211036.mjs +10 -0
- package/test-templates/_dsgn/templates/minimal-spin/.tmp/template-1763468394057.mjs +10 -0
- package/test-templates/_dsgn/templates/minimal-spin/meta.json +7 -0
- package/test-templates/_dsgn/templates/minimal-spin/template.tsx +13 -0
- package/test-templates/_dsgn/templates/no-origin-spin/meta.json +7 -0
- package/test-templates/_dsgn/templates/no-origin-spin/template.tsx +10 -0
- package/test-templates/_dsgn/templates/opacity-test/meta.json +7 -0
- package/test-templates/_dsgn/templates/opacity-test/template.tsx +9 -0
- package/test-templates/_dsgn/templates/qr-code/.tmp/template-1763468758954.mjs +17 -0
- package/test-templates/_dsgn/templates/qr-code/.tmp/template-1763468815672.mjs +17 -0
- package/test-templates/_dsgn/templates/qr-code/meta.json +9 -0
- package/test-templates/_dsgn/templates/qr-code/template.tsx +20 -0
- package/test-templates/_dsgn/templates/rotation-abs-test/meta.json +7 -0
- package/test-templates/_dsgn/templates/rotation-abs-test/template.tsx +15 -0
- package/test-templates/_dsgn/templates/rotation-corner/meta.json +7 -0
- package/test-templates/_dsgn/templates/rotation-corner/template.tsx +12 -0
- package/test-templates/_dsgn/templates/rotation-test/meta.json +7 -0
- package/test-templates/_dsgn/templates/rotation-test/template.tsx +12 -0
- package/test-templates/_dsgn/templates/shake-test/meta.json +7 -0
- package/test-templates/_dsgn/templates/shake-test/template.tsx +12 -0
- package/test-templates/_dsgn/templates/static-image/.tmp/template-1763468746271.mjs +7 -0
- package/test-templates/_dsgn/templates/static-image/meta.json +9 -0
- package/test-templates/_dsgn/templates/static-image/template.tsx +19 -0
- package/test-templates/_dsgn/templates/translate-test/meta.json +7 -0
- package/test-templates/_dsgn/templates/translate-test/template.tsx +9 -0
- package/test-templates/_dsgn/templates/video-loops/.tmp/template-1763468793192.mjs +15 -0
- package/test-templates/_dsgn/templates/video-loops/meta.json +9 -0
- package/test-templates/_dsgn/templates/video-loops/template.tsx +39 -0
- package/test-templates/_dsgn/templates/wrapped-spin/meta.json +7 -0
- package/test-templates/_dsgn/templates/wrapped-spin/template.tsx +17 -0
- package/test-templates/compare-svgs.mjs +30 -0
- package/test-templates/convert-frames.mjs +15 -0
- package/test-templates/debug-rotation.mjs +25 -0
- package/test-templates/run-tests.sh +39 -0
- package/test-templates/test-sdk.mjs +115 -0
- package/website/.astro/settings.json +5 -0
- package/website/.astro/types.d.ts +1 -0
- package/website/README.md +112 -0
- package/website/astro.config.mjs +18 -0
- package/website/dist/_astro/fonts.DHdiHGBO.css +1 -0
- package/website/dist/fonts/index.html +193 -0
- package/website/dist/helpers/index.html +166 -0
- package/website/dist/images/index.html +314 -0
- package/website/dist/index.html +219 -0
- package/website/dist/llm.txt +2448 -0
- package/website/dist/styling/index.html +365 -0
- package/website/dist/templates/index.html +124 -0
- package/website/dist/video/index.html +636 -0
- package/website/package-lock.json +7606 -0
- package/website/package.json +23 -0
- package/website/public/robots.txt +5 -0
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import fs from 'fs/promises';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { fileURLToPath } from 'url';
|
|
4
|
+
import chalk from 'chalk';
|
|
5
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
6
|
+
const __dirname = path.dirname(__filename);
|
|
7
|
+
/**
|
|
8
|
+
* Check if there's a newer version available on npm
|
|
9
|
+
* This is done asynchronously and won't block the CLI
|
|
10
|
+
*/
|
|
11
|
+
export async function checkForUpdates() {
|
|
12
|
+
try {
|
|
13
|
+
// Get current version from package.json
|
|
14
|
+
const packageJsonPath = path.join(__dirname, '../../package.json');
|
|
15
|
+
const packageJson = JSON.parse(await fs.readFile(packageJsonPath, 'utf-8'));
|
|
16
|
+
const currentVersion = packageJson.version;
|
|
17
|
+
// Fetch latest version from npm registry (with timeout)
|
|
18
|
+
const controller = new AbortController();
|
|
19
|
+
const timeout = setTimeout(() => controller.abort(), 3000); // 3 second timeout
|
|
20
|
+
const response = await fetch('https://registry.npmjs.org/loopwind/latest', {
|
|
21
|
+
signal: controller.signal,
|
|
22
|
+
});
|
|
23
|
+
clearTimeout(timeout);
|
|
24
|
+
if (!response.ok) {
|
|
25
|
+
return null; // Silently fail if npm registry is down
|
|
26
|
+
}
|
|
27
|
+
const data = await response.json();
|
|
28
|
+
const latestVersion = data.version;
|
|
29
|
+
// Compare versions (simple semver comparison)
|
|
30
|
+
const isOutdated = compareVersions(currentVersion, latestVersion) < 0;
|
|
31
|
+
return {
|
|
32
|
+
currentVersion,
|
|
33
|
+
latestVersion,
|
|
34
|
+
isOutdated,
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
catch (error) {
|
|
38
|
+
// Silently fail - don't interrupt the user's workflow
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Display update notification if a newer version is available
|
|
44
|
+
*/
|
|
45
|
+
export function displayUpdateNotification(result) {
|
|
46
|
+
if (!result.isOutdated) {
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
console.log();
|
|
50
|
+
console.log(chalk.yellow('┌' + '─'.repeat(60) + '┐'));
|
|
51
|
+
console.log(chalk.yellow('│') + ' '.repeat(60) + chalk.yellow('│'));
|
|
52
|
+
console.log(chalk.yellow('│') +
|
|
53
|
+
' ' +
|
|
54
|
+
chalk.bold('Update available! ') +
|
|
55
|
+
chalk.dim(`${result.currentVersion}`) +
|
|
56
|
+
' → ' +
|
|
57
|
+
chalk.green.bold(`${result.latestVersion}`) +
|
|
58
|
+
' '.repeat(60 - 20 - result.currentVersion.length - result.latestVersion.length - 5) +
|
|
59
|
+
chalk.yellow('│'));
|
|
60
|
+
console.log(chalk.yellow('│') + ' '.repeat(60) + chalk.yellow('│'));
|
|
61
|
+
console.log(chalk.yellow('│') +
|
|
62
|
+
' Run ' +
|
|
63
|
+
chalk.cyan.bold('npm install -g loopwind@latest') +
|
|
64
|
+
' to update' +
|
|
65
|
+
' '.repeat(60 - 45) +
|
|
66
|
+
chalk.yellow('│'));
|
|
67
|
+
console.log(chalk.yellow('│') + ' '.repeat(60) + chalk.yellow('│'));
|
|
68
|
+
console.log(chalk.yellow('└' + '─'.repeat(60) + '┘'));
|
|
69
|
+
console.log();
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Simple semver comparison
|
|
73
|
+
* Returns: -1 if v1 < v2, 0 if v1 === v2, 1 if v1 > v2
|
|
74
|
+
*/
|
|
75
|
+
function compareVersions(v1, v2) {
|
|
76
|
+
const parts1 = v1.split('.').map(Number);
|
|
77
|
+
const parts2 = v2.split('.').map(Number);
|
|
78
|
+
for (let i = 0; i < Math.max(parts1.length, parts2.length); i++) {
|
|
79
|
+
const num1 = parts1[i] || 0;
|
|
80
|
+
const num2 = parts2[i] || 0;
|
|
81
|
+
if (num1 < num2)
|
|
82
|
+
return -1;
|
|
83
|
+
if (num1 > num2)
|
|
84
|
+
return 1;
|
|
85
|
+
}
|
|
86
|
+
return 0;
|
|
87
|
+
}
|
|
88
|
+
//# sourceMappingURL=version-check.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"version-check.js","sourceRoot":"","sources":["../../src/lib/version-check.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { TemplateProps } from '../types/template.js';
|
|
2
|
+
/**
|
|
3
|
+
* Render video frames to a directory
|
|
4
|
+
*/
|
|
5
|
+
export declare function renderVideoFrames(templateName: string, props: TemplateProps, outputDir: string, options?: {
|
|
6
|
+
format?: 'png' | 'svg' | 'jpeg' | 'jpg';
|
|
7
|
+
onProgress?: (frame: number, total: number, phase?: 'svg' | 'convert') => void;
|
|
8
|
+
batchSize?: number;
|
|
9
|
+
}): Promise<{
|
|
10
|
+
totalFrames: number;
|
|
11
|
+
fps: number;
|
|
12
|
+
width: number;
|
|
13
|
+
height: number;
|
|
14
|
+
}>;
|
|
15
|
+
/**
|
|
16
|
+
* Encode SVG frames to MP4 using h264-mp4-encoder (WASM, no ffmpeg required)
|
|
17
|
+
*/
|
|
18
|
+
export declare function encodeFramesToVideo(svgs: string[], outputPath: string, options: {
|
|
19
|
+
fps: number;
|
|
20
|
+
width: number;
|
|
21
|
+
height: number;
|
|
22
|
+
quality?: number;
|
|
23
|
+
onProgress?: (frame: number) => void;
|
|
24
|
+
}): Promise<void>;
|
|
25
|
+
/**
|
|
26
|
+
* Render a video template to MP4 using WASM encoder (works everywhere, no ffmpeg!)
|
|
27
|
+
*/
|
|
28
|
+
export declare function renderVideo(templateName: string, props: TemplateProps, outputPath: string, options?: {
|
|
29
|
+
quality?: number;
|
|
30
|
+
onFrameProgress?: (frame: number, total: number, phase?: 'svg' | 'encode') => void;
|
|
31
|
+
}): Promise<void>;
|
|
32
|
+
//# sourceMappingURL=video-renderer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"video-renderer.d.ts","sourceRoot":"","sources":["../../src/lib/video-renderer.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAI1D;;GAEG;AACH,wBAAsB,iBAAiB,CACrC,YAAY,EAAE,MAAM,EACpB,KAAK,EAAE,aAAa,EACpB,SAAS,EAAE,MAAM,EACjB,OAAO,GAAE;IACP,MAAM,CAAC,EAAE,KAAK,GAAG,KAAK,GAAG,MAAM,GAAG,KAAK,CAAC;IACxC,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,KAAK,GAAG,SAAS,KAAK,IAAI,CAAC;IAC/E,SAAS,CAAC,EAAE,MAAM,CAAC;CACf,GACL,OAAO,CAAC;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CA8H9E;AAED;;GAEG;AACH,wBAAsB,mBAAmB,CACvC,IAAI,EAAE,MAAM,EAAE,EACd,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE;IACP,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACtC,GACA,OAAO,CAAC,IAAI,CAAC,CA2Df;AAED;;GAEG;AACH,wBAAsB,WAAW,CAC/B,YAAY,EAAE,MAAM,EACpB,KAAK,EAAE,aAAa,EACpB,UAAU,EAAE,MAAM,EAClB,OAAO,GAAE;IACP,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,eAAe,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,KAAK,GAAG,QAAQ,KAAK,IAAI,CAAC;CAC/E,GACL,OAAO,CAAC,IAAI,CAAC,CA6Ef"}
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
import { renderToSVG } from './renderer.js';
|
|
2
|
+
import { loadTemplateMeta } from './utils.js';
|
|
3
|
+
import fs from 'fs/promises';
|
|
4
|
+
import path from 'path';
|
|
5
|
+
import HME from 'h264-mp4-encoder';
|
|
6
|
+
import sharp from 'sharp';
|
|
7
|
+
/**
|
|
8
|
+
* Render video frames to a directory
|
|
9
|
+
*/
|
|
10
|
+
export async function renderVideoFrames(templateName, props, outputDir, options = {}) {
|
|
11
|
+
// Default to PNG for video frames (better compression for flat colors/text)
|
|
12
|
+
// JPEG is available as an option but doesn't provide speed benefits
|
|
13
|
+
const { format = 'png', onProgress, batchSize = 40 } = options;
|
|
14
|
+
// Load template metadata
|
|
15
|
+
const meta = await loadTemplateMeta(templateName);
|
|
16
|
+
if (meta.type !== 'video') {
|
|
17
|
+
throw new Error(`Template "${templateName}" is not a video template (type: ${meta.type || 'image'})`);
|
|
18
|
+
}
|
|
19
|
+
if (!meta.video) {
|
|
20
|
+
throw new Error(`Template "${templateName}" is missing video metadata`);
|
|
21
|
+
}
|
|
22
|
+
const { fps, duration } = meta.video;
|
|
23
|
+
const totalFrames = Math.floor(fps * duration);
|
|
24
|
+
// Ensure output directory exists
|
|
25
|
+
await fs.mkdir(outputDir, { recursive: true });
|
|
26
|
+
// Two-phase rendering for better performance:
|
|
27
|
+
// Phase 1: Generate all SVGs (super fast - just string operations)
|
|
28
|
+
// Phase 2: Convert SVGs to PNG/JPEG in batches (parallelized rasterization)
|
|
29
|
+
if (format === 'svg') {
|
|
30
|
+
// For SVG output, just render directly (no conversion needed)
|
|
31
|
+
const svgPromises = [];
|
|
32
|
+
for (let frame = 0; frame < totalFrames; frame++) {
|
|
33
|
+
const progress = frame / (totalFrames - 1);
|
|
34
|
+
const frameProps = { ...props, frame, progress };
|
|
35
|
+
const framePath = path.join(outputDir, `frame-${String(frame).padStart(4, '0')}.svg`);
|
|
36
|
+
svgPromises.push(renderToSVG(templateName, frameProps).then(svg => fs.writeFile(framePath, svg)));
|
|
37
|
+
}
|
|
38
|
+
await Promise.all(svgPromises);
|
|
39
|
+
if (onProgress) {
|
|
40
|
+
onProgress(totalFrames, totalFrames);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
// For PNG/JPEG: First generate all SVGs, then convert in batches
|
|
45
|
+
const svgs = new Array(totalFrames);
|
|
46
|
+
// Generate all SVGs in parallel (very fast - just React rendering to strings)
|
|
47
|
+
if (onProgress) {
|
|
48
|
+
onProgress(0, totalFrames, 'svg');
|
|
49
|
+
}
|
|
50
|
+
const svgPromises = [];
|
|
51
|
+
for (let frame = 0; frame < totalFrames; frame++) {
|
|
52
|
+
const progress = frame / (totalFrames - 1);
|
|
53
|
+
const frameProps = { ...props, frame, progress };
|
|
54
|
+
svgPromises.push(renderToSVG(templateName, frameProps).then(svg => {
|
|
55
|
+
svgs[frame] = svg;
|
|
56
|
+
}));
|
|
57
|
+
}
|
|
58
|
+
await Promise.all(svgPromises);
|
|
59
|
+
if (onProgress) {
|
|
60
|
+
onProgress(totalFrames, totalFrames, 'svg');
|
|
61
|
+
}
|
|
62
|
+
// Convert SVGs to PNG/JPEG in batches
|
|
63
|
+
let completedFrames = 0;
|
|
64
|
+
for (let batchStart = 0; batchStart < totalFrames; batchStart += batchSize) {
|
|
65
|
+
const batchEnd = Math.min(batchStart + batchSize, totalFrames);
|
|
66
|
+
const convertPromises = [];
|
|
67
|
+
for (let frame = batchStart; frame < batchEnd; frame++) {
|
|
68
|
+
const framePath = path.join(outputDir, `frame-${String(frame).padStart(4, '0')}.${format}`);
|
|
69
|
+
const convertPromise = (async () => {
|
|
70
|
+
const svg = svgs[frame];
|
|
71
|
+
if (format === 'jpeg' || format === 'jpg') {
|
|
72
|
+
// Convert SVG string directly to JPEG
|
|
73
|
+
const { Resvg } = await import('@resvg/resvg-js');
|
|
74
|
+
const resvg = new Resvg(svg, {
|
|
75
|
+
fitTo: { mode: 'width', value: meta.size.width },
|
|
76
|
+
});
|
|
77
|
+
const pngData = resvg.render();
|
|
78
|
+
const pngBuffer = pngData.asPng();
|
|
79
|
+
const sharp = (await import('sharp')).default;
|
|
80
|
+
const jpegBuffer = await sharp(pngBuffer).jpeg({ quality: 85 }).toBuffer();
|
|
81
|
+
await fs.writeFile(framePath, jpegBuffer);
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
// Convert SVG string directly to PNG
|
|
85
|
+
const { Resvg } = await import('@resvg/resvg-js');
|
|
86
|
+
const resvg = new Resvg(svg, {
|
|
87
|
+
fitTo: { mode: 'width', value: meta.size.width },
|
|
88
|
+
});
|
|
89
|
+
const pngData = resvg.render();
|
|
90
|
+
const pngBuffer = pngData.asPng();
|
|
91
|
+
await fs.writeFile(framePath, pngBuffer);
|
|
92
|
+
}
|
|
93
|
+
})();
|
|
94
|
+
convertPromises.push(convertPromise);
|
|
95
|
+
}
|
|
96
|
+
await Promise.all(convertPromises);
|
|
97
|
+
completedFrames += convertPromises.length;
|
|
98
|
+
if (onProgress) {
|
|
99
|
+
onProgress(completedFrames, totalFrames, 'convert');
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
return {
|
|
104
|
+
totalFrames,
|
|
105
|
+
fps,
|
|
106
|
+
width: meta.size.width,
|
|
107
|
+
height: meta.size.height,
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Encode SVG frames to MP4 using h264-mp4-encoder (WASM, no ffmpeg required)
|
|
112
|
+
*/
|
|
113
|
+
export async function encodeFramesToVideo(svgs, outputPath, options) {
|
|
114
|
+
const { fps, width, height, quality = 23, onProgress } = options;
|
|
115
|
+
// Step 1: Convert all SVGs to RGBA in parallel batches (memory efficient + fast!)
|
|
116
|
+
const startConversion = Date.now();
|
|
117
|
+
const batchSize = 30; // Process 30 frames at a time to balance speed/memory
|
|
118
|
+
const rgbaFrames = new Array(svgs.length);
|
|
119
|
+
for (let batchStart = 0; batchStart < svgs.length; batchStart += batchSize) {
|
|
120
|
+
const batchEnd = Math.min(batchStart + batchSize, svgs.length);
|
|
121
|
+
const batchPromises = [];
|
|
122
|
+
for (let i = batchStart; i < batchEnd; i++) {
|
|
123
|
+
batchPromises.push(sharp(Buffer.from(svgs[i]))
|
|
124
|
+
.resize(width, height, { fit: 'fill' })
|
|
125
|
+
.ensureAlpha()
|
|
126
|
+
.raw()
|
|
127
|
+
.toBuffer({ resolveWithObject: true })
|
|
128
|
+
.then(({ data }) => {
|
|
129
|
+
rgbaFrames[i] = data;
|
|
130
|
+
}));
|
|
131
|
+
}
|
|
132
|
+
await Promise.all(batchPromises);
|
|
133
|
+
}
|
|
134
|
+
console.log(`RGBA conversion: ${Date.now() - startConversion}ms`);
|
|
135
|
+
// Step 2: Create encoder and add frames sequentially (must be in order)
|
|
136
|
+
const startEncoding = Date.now();
|
|
137
|
+
const encoder = await HME.createH264MP4Encoder();
|
|
138
|
+
encoder.width = width;
|
|
139
|
+
encoder.height = height;
|
|
140
|
+
encoder.frameRate = fps;
|
|
141
|
+
encoder.quantizationParameter = quality; // 0-51, lower = better quality (default: 33)
|
|
142
|
+
encoder.speed = 10; // Speed preset 0-10 (10 = fastest, default: 0)
|
|
143
|
+
encoder.groupOfPictures = fps; // GOP size = 1 second of frames
|
|
144
|
+
encoder.initialize();
|
|
145
|
+
// Add all RGBA frames to encoder (must be sequential)
|
|
146
|
+
for (let i = 0; i < rgbaFrames.length; i++) {
|
|
147
|
+
encoder.addFrameRgba(rgbaFrames[i]);
|
|
148
|
+
if (onProgress) {
|
|
149
|
+
onProgress(i + 1);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
console.log(`H.264 encoding: ${Date.now() - startEncoding}ms`);
|
|
153
|
+
// Finalize encoding
|
|
154
|
+
encoder.finalize();
|
|
155
|
+
// Write output file
|
|
156
|
+
const uint8Array = encoder.FS.readFile(encoder.outputFilename);
|
|
157
|
+
await fs.writeFile(outputPath, uint8Array);
|
|
158
|
+
// Cleanup
|
|
159
|
+
encoder.delete();
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Render a video template to MP4 using WASM encoder (works everywhere, no ffmpeg!)
|
|
163
|
+
*/
|
|
164
|
+
export async function renderVideo(templateName, props, outputPath, options = {}) {
|
|
165
|
+
const { quality = 23, onFrameProgress } = options;
|
|
166
|
+
// Load template metadata
|
|
167
|
+
const meta = await loadTemplateMeta(templateName);
|
|
168
|
+
if (meta.type !== 'video') {
|
|
169
|
+
throw new Error(`Template "${templateName}" is not a video template (type: ${meta.type || 'image'})`);
|
|
170
|
+
}
|
|
171
|
+
if (!meta.video) {
|
|
172
|
+
throw new Error(`Template "${templateName}" is missing video metadata`);
|
|
173
|
+
}
|
|
174
|
+
const { fps, duration } = meta.video;
|
|
175
|
+
const totalFrames = Math.floor(fps * duration);
|
|
176
|
+
const { width, height } = meta.size;
|
|
177
|
+
// Step 1: Generate ALL SVGs in parallel
|
|
178
|
+
const startTotal = Date.now();
|
|
179
|
+
const svgs = new Array(totalFrames);
|
|
180
|
+
const svgPromises = [];
|
|
181
|
+
for (let frame = 0; frame < totalFrames; frame++) {
|
|
182
|
+
const progress = frame / (totalFrames - 1);
|
|
183
|
+
const frameProps = { ...props, frame, progress };
|
|
184
|
+
svgPromises.push(renderToSVG(templateName, frameProps).then(svg => {
|
|
185
|
+
svgs[frame] = svg;
|
|
186
|
+
}));
|
|
187
|
+
}
|
|
188
|
+
await Promise.all(svgPromises);
|
|
189
|
+
// Step 2: Convert ALL SVGs to RGBA in parallel
|
|
190
|
+
const rgbaFrames = new Array(totalFrames);
|
|
191
|
+
const rgbaPromises = [];
|
|
192
|
+
for (let i = 0; i < totalFrames; i++) {
|
|
193
|
+
rgbaPromises.push(sharp(Buffer.from(svgs[i]))
|
|
194
|
+
.resize(width, height, { fit: 'fill' })
|
|
195
|
+
.ensureAlpha()
|
|
196
|
+
.raw()
|
|
197
|
+
.toBuffer({ resolveWithObject: true })
|
|
198
|
+
.then(({ data }) => {
|
|
199
|
+
rgbaFrames[i] = data;
|
|
200
|
+
}));
|
|
201
|
+
}
|
|
202
|
+
await Promise.all(rgbaPromises);
|
|
203
|
+
console.log(`SVG + RGBA: ${Date.now() - startTotal}ms`);
|
|
204
|
+
// Step 3: Encode RGBA frames to H.264
|
|
205
|
+
const startEncoding = Date.now();
|
|
206
|
+
const encoder = await HME.createH264MP4Encoder();
|
|
207
|
+
encoder.width = width;
|
|
208
|
+
encoder.height = height;
|
|
209
|
+
encoder.frameRate = fps;
|
|
210
|
+
encoder.quantizationParameter = quality;
|
|
211
|
+
encoder.speed = 10;
|
|
212
|
+
encoder.groupOfPictures = fps;
|
|
213
|
+
encoder.initialize();
|
|
214
|
+
for (let i = 0; i < rgbaFrames.length; i++) {
|
|
215
|
+
encoder.addFrameRgba(rgbaFrames[i]);
|
|
216
|
+
if (onFrameProgress && i % 10 === 0) {
|
|
217
|
+
onFrameProgress(i, totalFrames, 'encode');
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
encoder.finalize();
|
|
221
|
+
const uint8Array = encoder.FS.readFile(encoder.outputFilename);
|
|
222
|
+
await fs.writeFile(outputPath, uint8Array);
|
|
223
|
+
encoder.delete();
|
|
224
|
+
console.log(`H.264 encoding: ${Date.now() - startEncoding}ms`);
|
|
225
|
+
}
|
|
226
|
+
//# sourceMappingURL=video-renderer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"video-renderer.js","sourceRoot":"","sources":["../../src/lib/video-renderer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import type { TemplateDefinition } from './template.js';
|
|
2
|
+
export { defineTemplate } from './template.js';
|
|
3
|
+
export type { TemplateDefinition } from './template.js';
|
|
4
|
+
/**
|
|
5
|
+
* Render options for image generation
|
|
6
|
+
*/
|
|
7
|
+
export interface RenderImageOptions {
|
|
8
|
+
format?: 'png' | 'jpeg' | 'jpg' | 'webp' | 'svg';
|
|
9
|
+
quality?: number;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Render options for video generation
|
|
13
|
+
*/
|
|
14
|
+
export interface RenderVideoOptions {
|
|
15
|
+
quality?: number;
|
|
16
|
+
onProgress?: (frame: number, total: number, phase?: 'svg' | 'encode') => void;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Render an image from a template definition
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* ```typescript
|
|
23
|
+
* const template = defineTemplate({
|
|
24
|
+
* name: 'og-image',
|
|
25
|
+
* size: { width: 1200, height: 630 },
|
|
26
|
+
* render: ({ tw, title }) => <div style={tw('flex')}>{title}</div>
|
|
27
|
+
* });
|
|
28
|
+
*
|
|
29
|
+
* const png = await renderImage(template, { title: 'Hello World' });
|
|
30
|
+
* // Returns Buffer containing PNG data
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
export declare function renderImage<TProps = any>(template: TemplateDefinition<TProps>, props: TProps, options?: RenderImageOptions): Promise<Buffer>;
|
|
34
|
+
/**
|
|
35
|
+
* Render a video from a template definition
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* ```typescript
|
|
39
|
+
* const template = defineTemplate({
|
|
40
|
+
* name: 'intro-video',
|
|
41
|
+
* type: 'video',
|
|
42
|
+
* size: { width: 1920, height: 1080 },
|
|
43
|
+
* video: { fps: 30, duration: 3 },
|
|
44
|
+
* render: ({ tw, progress, title }) => (
|
|
45
|
+
* <div style={tw('flex items-center justify-center w-full h-full bg-black')}>
|
|
46
|
+
* <h1 style={{ ...tw('text-8xl font-bold text-white'), opacity: progress }}>
|
|
47
|
+
* {title}
|
|
48
|
+
* </h1>
|
|
49
|
+
* </div>
|
|
50
|
+
* )
|
|
51
|
+
* });
|
|
52
|
+
*
|
|
53
|
+
* const mp4 = await renderVideo(template, { title: 'Hello' });
|
|
54
|
+
* // Returns Buffer containing MP4 data
|
|
55
|
+
* ```
|
|
56
|
+
*/
|
|
57
|
+
export declare function renderVideo<TProps = any>(template: TemplateDefinition<TProps>, props: TProps, options?: RenderVideoOptions): Promise<Buffer>;
|
|
58
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/sdk/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAQxD,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,YAAY,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAExD;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,MAAM,CAAC,EAAE,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,MAAM,GAAG,KAAK,CAAC;IACjD,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,KAAK,GAAG,QAAQ,KAAK,IAAI,CAAC;CAC/E;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,WAAW,CAAC,MAAM,GAAG,GAAG,EAC5C,QAAQ,EAAE,kBAAkB,CAAC,MAAM,CAAC,EACpC,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,kBAAuB,GAC/B,OAAO,CAAC,MAAM,CAAC,CA0CjB;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAsB,WAAW,CAAC,MAAM,GAAG,GAAG,EAC5C,QAAQ,EAAE,kBAAkB,CAAC,MAAM,CAAC,EACpC,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,kBAAuB,GAC/B,OAAO,CAAC,MAAM,CAAC,CAoCjB"}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { renderToSVG, renderToPNG, renderToJPEG, renderToWebP } from '../lib/renderer.js';
|
|
2
|
+
import { templateToMeta } from './template.js';
|
|
3
|
+
import { renderVideo as renderVideoInternal } from '../lib/video-renderer.js';
|
|
4
|
+
import fs from 'fs/promises';
|
|
5
|
+
import path from 'path';
|
|
6
|
+
import os from 'os';
|
|
7
|
+
export { defineTemplate } from './template.js';
|
|
8
|
+
/**
|
|
9
|
+
* Render an image from a template definition
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```typescript
|
|
13
|
+
* const template = defineTemplate({
|
|
14
|
+
* name: 'og-image',
|
|
15
|
+
* size: { width: 1200, height: 630 },
|
|
16
|
+
* render: ({ tw, title }) => <div style={tw('flex')}>{title}</div>
|
|
17
|
+
* });
|
|
18
|
+
*
|
|
19
|
+
* const png = await renderImage(template, { title: 'Hello World' });
|
|
20
|
+
* // Returns Buffer containing PNG data
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
export async function renderImage(template, props, options = {}) {
|
|
24
|
+
const { format = 'png', quality = 92 } = options;
|
|
25
|
+
const meta = templateToMeta(template);
|
|
26
|
+
if (meta.type === 'video') {
|
|
27
|
+
throw new Error('Cannot render video template as image. Use renderVideo() instead.');
|
|
28
|
+
}
|
|
29
|
+
// Save template to temp file so we can use the existing renderer
|
|
30
|
+
const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), 'loopwind-sdk-'));
|
|
31
|
+
const templatePath = path.join(tempDir, 'template.tsx');
|
|
32
|
+
const metaPath = path.join(tempDir, 'meta.json');
|
|
33
|
+
try {
|
|
34
|
+
// Write template component to file
|
|
35
|
+
const templateContent = `import React from 'react';
|
|
36
|
+
export default ${template.render.toString()};`;
|
|
37
|
+
await fs.writeFile(templatePath, templateContent);
|
|
38
|
+
// Write meta.json
|
|
39
|
+
await fs.writeFile(metaPath, JSON.stringify(meta, null, 2));
|
|
40
|
+
// Use existing renderer - pass temp dir as template name
|
|
41
|
+
if (format === 'svg') {
|
|
42
|
+
const svg = await renderToSVG(tempDir, props);
|
|
43
|
+
return Buffer.from(svg);
|
|
44
|
+
}
|
|
45
|
+
else if (format === 'jpeg' || format === 'jpg') {
|
|
46
|
+
const buffer = await renderToJPEG(tempDir, props, { quality });
|
|
47
|
+
return buffer;
|
|
48
|
+
}
|
|
49
|
+
else if (format === 'webp') {
|
|
50
|
+
const buffer = await renderToWebP(tempDir, props);
|
|
51
|
+
// Note: renderToWebP doesn't take quality param, uses fixed 90
|
|
52
|
+
return buffer;
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
// PNG
|
|
56
|
+
const buffer = await renderToPNG(tempDir, props);
|
|
57
|
+
return buffer;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
finally {
|
|
61
|
+
// Cleanup temp files
|
|
62
|
+
await fs.rm(tempDir, { recursive: true, force: true });
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Render a video from a template definition
|
|
67
|
+
*
|
|
68
|
+
* @example
|
|
69
|
+
* ```typescript
|
|
70
|
+
* const template = defineTemplate({
|
|
71
|
+
* name: 'intro-video',
|
|
72
|
+
* type: 'video',
|
|
73
|
+
* size: { width: 1920, height: 1080 },
|
|
74
|
+
* video: { fps: 30, duration: 3 },
|
|
75
|
+
* render: ({ tw, progress, title }) => (
|
|
76
|
+
* <div style={tw('flex items-center justify-center w-full h-full bg-black')}>
|
|
77
|
+
* <h1 style={{ ...tw('text-8xl font-bold text-white'), opacity: progress }}>
|
|
78
|
+
* {title}
|
|
79
|
+
* </h1>
|
|
80
|
+
* </div>
|
|
81
|
+
* )
|
|
82
|
+
* });
|
|
83
|
+
*
|
|
84
|
+
* const mp4 = await renderVideo(template, { title: 'Hello' });
|
|
85
|
+
* // Returns Buffer containing MP4 data
|
|
86
|
+
* ```
|
|
87
|
+
*/
|
|
88
|
+
export async function renderVideo(template, props, options = {}) {
|
|
89
|
+
const meta = templateToMeta(template);
|
|
90
|
+
if (meta.type !== 'video') {
|
|
91
|
+
throw new Error('Cannot render image template as video. Use renderImage() instead.');
|
|
92
|
+
}
|
|
93
|
+
if (!meta.video) {
|
|
94
|
+
throw new Error('Template is missing video metadata (fps, duration)');
|
|
95
|
+
}
|
|
96
|
+
// Save template to temp file so we can use the existing renderer
|
|
97
|
+
const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), 'loopwind-sdk-'));
|
|
98
|
+
const templatePath = path.join(tempDir, 'template.tsx');
|
|
99
|
+
const metaPath = path.join(tempDir, 'meta.json');
|
|
100
|
+
const outputPath = path.join(tempDir, 'output.mp4');
|
|
101
|
+
try {
|
|
102
|
+
// Write template component to file
|
|
103
|
+
const templateContent = `import React from 'react';
|
|
104
|
+
export default ${template.render.toString()};`;
|
|
105
|
+
await fs.writeFile(templatePath, templateContent);
|
|
106
|
+
// Write meta.json
|
|
107
|
+
await fs.writeFile(metaPath, JSON.stringify(meta, null, 2));
|
|
108
|
+
// Use existing video renderer
|
|
109
|
+
await renderVideoInternal(tempDir, props, outputPath, options);
|
|
110
|
+
// Read the generated MP4
|
|
111
|
+
const buffer = await fs.readFile(outputPath);
|
|
112
|
+
return buffer;
|
|
113
|
+
}
|
|
114
|
+
finally {
|
|
115
|
+
// Cleanup temp files
|
|
116
|
+
await fs.rm(tempDir, { recursive: true, force: true });
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/sdk/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { TemplateProps, TemplateMeta } from '../types/template.js';
|
|
2
|
+
export interface TemplateDefinition<TProps = any> {
|
|
3
|
+
name: string;
|
|
4
|
+
type?: 'image' | 'video';
|
|
5
|
+
size: {
|
|
6
|
+
width: number;
|
|
7
|
+
height: number;
|
|
8
|
+
};
|
|
9
|
+
video?: {
|
|
10
|
+
fps: number;
|
|
11
|
+
duration: number;
|
|
12
|
+
};
|
|
13
|
+
fonts?: string[];
|
|
14
|
+
render: (props: TProps & TemplateProps) => JSX.Element;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Define a template programmatically for use in serverless environments
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```typescript
|
|
21
|
+
* const ogImage = defineTemplate({
|
|
22
|
+
* name: 'og-image',
|
|
23
|
+
* type: 'image',
|
|
24
|
+
* size: { width: 1200, height: 630 },
|
|
25
|
+
* render: ({ tw, title, description }) => (
|
|
26
|
+
* <div style={tw('flex flex-col w-full h-full bg-white p-12')}>
|
|
27
|
+
* <h1 style={tw('text-6xl font-bold')}>{title}</h1>
|
|
28
|
+
* <p style={tw('text-2xl text-gray-600')}>{description}</p>
|
|
29
|
+
* </div>
|
|
30
|
+
* )
|
|
31
|
+
* });
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
export declare function defineTemplate<TProps = any>(definition: TemplateDefinition<TProps>): TemplateDefinition<TProps>;
|
|
35
|
+
/**
|
|
36
|
+
* Convert a template definition to template metadata
|
|
37
|
+
* @internal
|
|
38
|
+
*/
|
|
39
|
+
export declare function templateToMeta(template: TemplateDefinition): TemplateMeta;
|
|
40
|
+
//# sourceMappingURL=template.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"template.d.ts","sourceRoot":"","sources":["../../src/sdk/template.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAExE,MAAM,WAAW,kBAAkB,CAAC,MAAM,GAAG,GAAG;IAC9C,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC;IACzB,IAAI,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IACxC,KAAK,CAAC,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;IAC1C,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,MAAM,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,aAAa,KAAK,GAAG,CAAC,OAAO,CAAC;CACxD;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,cAAc,CAAC,MAAM,GAAG,GAAG,EACzC,UAAU,EAAE,kBAAkB,CAAC,MAAM,CAAC,GACrC,kBAAkB,CAAC,MAAM,CAAC,CAyB5B;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,kBAAkB,GAAG,YAAY,CAezE"}
|