@vargai/sdk 0.1.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/.env.example +24 -0
- package/CLAUDE.md +118 -0
- package/HIGGSFIELD_REWRITE_SUMMARY.md +300 -0
- package/README.md +231 -0
- package/SKILLS.md +157 -0
- package/STRUCTURE.md +92 -0
- package/TEST_RESULTS.md +122 -0
- package/action/captions/SKILL.md +170 -0
- package/action/captions/index.ts +169 -0
- package/action/edit/SKILL.md +235 -0
- package/action/edit/index.ts +437 -0
- package/action/image/SKILL.md +140 -0
- package/action/image/index.ts +105 -0
- package/action/sync/SKILL.md +136 -0
- package/action/sync/index.ts +145 -0
- package/action/transcribe/SKILL.md +179 -0
- package/action/transcribe/index.ts +210 -0
- package/action/video/SKILL.md +116 -0
- package/action/video/index.ts +125 -0
- package/action/voice/SKILL.md +125 -0
- package/action/voice/index.ts +136 -0
- package/biome.json +33 -0
- package/bun.lock +842 -0
- package/cli/commands/find.ts +58 -0
- package/cli/commands/help.ts +70 -0
- package/cli/commands/list.ts +49 -0
- package/cli/commands/run.ts +237 -0
- package/cli/commands/which.ts +66 -0
- package/cli/discover.ts +66 -0
- package/cli/index.ts +33 -0
- package/cli/runner.ts +65 -0
- package/cli/types.ts +49 -0
- package/cli/ui.ts +185 -0
- package/index.ts +75 -0
- package/lib/README.md +144 -0
- package/lib/ai-sdk/fal.ts +106 -0
- package/lib/ai-sdk/replicate.ts +107 -0
- package/lib/elevenlabs.ts +382 -0
- package/lib/fal.ts +467 -0
- package/lib/ffmpeg.ts +467 -0
- package/lib/fireworks.ts +235 -0
- package/lib/groq.ts +246 -0
- package/lib/higgsfield/MIGRATION.md +308 -0
- package/lib/higgsfield/README.md +273 -0
- package/lib/higgsfield/example.ts +228 -0
- package/lib/higgsfield/index.ts +241 -0
- package/lib/higgsfield/soul.ts +262 -0
- package/lib/higgsfield.ts +176 -0
- package/lib/remotion/SKILL.md +823 -0
- package/lib/remotion/cli.ts +115 -0
- package/lib/remotion/functions.ts +283 -0
- package/lib/remotion/index.ts +19 -0
- package/lib/remotion/templates.ts +73 -0
- package/lib/replicate.ts +304 -0
- package/output.txt +1 -0
- package/package.json +42 -0
- package/pipeline/cookbooks/SKILL.md +285 -0
- package/pipeline/cookbooks/remotion-video.md +585 -0
- package/pipeline/cookbooks/round-video-character.md +337 -0
- package/pipeline/cookbooks/talking-character.md +59 -0
- package/scripts/produce-menopause-campaign.sh +202 -0
- package/service/music/SKILL.md +229 -0
- package/service/music/index.ts +296 -0
- package/test-import.ts +7 -0
- package/test-services.ts +97 -0
- package/tsconfig.json +29 -0
- package/utilities/s3.ts +147 -0
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createComposition,
|
|
3
|
+
getCompositionsList,
|
|
4
|
+
render,
|
|
5
|
+
renderStill,
|
|
6
|
+
} from "./functions";
|
|
7
|
+
|
|
8
|
+
// cli
|
|
9
|
+
export async function cli() {
|
|
10
|
+
const args = process.argv.slice(2);
|
|
11
|
+
const command = args[0];
|
|
12
|
+
|
|
13
|
+
if (!command || command === "help") {
|
|
14
|
+
console.log(`
|
|
15
|
+
usage:
|
|
16
|
+
bun run lib/remotion.ts <command> [args]
|
|
17
|
+
|
|
18
|
+
commands:
|
|
19
|
+
create <name> setup composition directory
|
|
20
|
+
compositions <root-file.tsx> list all compositions
|
|
21
|
+
render <root-file.tsx> <comp-id> <output.mp4> render video
|
|
22
|
+
still <root-file.tsx> <comp-id> <frame> <out.png> render still frame
|
|
23
|
+
help show this help
|
|
24
|
+
|
|
25
|
+
examples:
|
|
26
|
+
bun run lib/remotion/index.ts create MyVideo
|
|
27
|
+
bun run lib/remotion/index.ts compositions lib/remotion/compositions/MyVideo.root.tsx
|
|
28
|
+
bun run lib/remotion/index.ts render lib/remotion/compositions/MyVideo.root.tsx Demo output.mp4
|
|
29
|
+
bun run lib/remotion/index.ts still lib/remotion/compositions/MyVideo.root.tsx Demo 30 frame.png
|
|
30
|
+
|
|
31
|
+
requirements:
|
|
32
|
+
remotion and @remotion/cli must be installed
|
|
33
|
+
bun install remotion @remotion/cli
|
|
34
|
+
`);
|
|
35
|
+
process.exit(0);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
try {
|
|
39
|
+
switch (command) {
|
|
40
|
+
case "create": {
|
|
41
|
+
const name = args[1];
|
|
42
|
+
|
|
43
|
+
if (!name) {
|
|
44
|
+
throw new Error("composition name is required");
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
await createComposition({ name });
|
|
48
|
+
console.log("\ncomposition setup complete!");
|
|
49
|
+
break;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
case "compositions": {
|
|
53
|
+
const entryPoint = args[1];
|
|
54
|
+
|
|
55
|
+
if (!entryPoint) {
|
|
56
|
+
throw new Error("entry point is required");
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const compositions = await getCompositionsList(entryPoint);
|
|
60
|
+
|
|
61
|
+
console.log("\navailable compositions:");
|
|
62
|
+
for (const comp of compositions) {
|
|
63
|
+
console.log(
|
|
64
|
+
` ${comp.id}: ${comp.width}x${comp.height} @ ${comp.fps}fps (${comp.durationInFrames} frames)`,
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
break;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
case "render": {
|
|
71
|
+
const entryPoint = args[1];
|
|
72
|
+
const compositionId = args[2];
|
|
73
|
+
const outputPath = args[3];
|
|
74
|
+
|
|
75
|
+
if (!entryPoint || !compositionId || !outputPath) {
|
|
76
|
+
throw new Error(
|
|
77
|
+
"entryPoint, compositionId, and outputPath are required",
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
await render({ entryPoint, compositionId, outputPath });
|
|
82
|
+
break;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
case "still": {
|
|
86
|
+
const entryPoint = args[1];
|
|
87
|
+
const compositionId = args[2];
|
|
88
|
+
const frameArg = args[3];
|
|
89
|
+
const outputPath = args[4];
|
|
90
|
+
|
|
91
|
+
if (!entryPoint || !compositionId || !frameArg || !outputPath) {
|
|
92
|
+
throw new Error(
|
|
93
|
+
"entryPoint, compositionId, frame, and outputPath are required",
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const frame = Number.parseInt(frameArg, 10);
|
|
98
|
+
if (Number.isNaN(frame)) {
|
|
99
|
+
throw new Error("frame must be a valid number");
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
await renderStill(entryPoint, compositionId, frame, outputPath);
|
|
103
|
+
break;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
default:
|
|
107
|
+
console.error(`unknown command: ${command}`);
|
|
108
|
+
console.log("run 'bun run lib/remotion.ts help' for usage");
|
|
109
|
+
process.exit(1);
|
|
110
|
+
}
|
|
111
|
+
} catch (error) {
|
|
112
|
+
console.error("[remotion] error:", error);
|
|
113
|
+
process.exit(1);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { bundle } from "@remotion/bundler";
|
|
4
|
+
import { getCompositions, renderMedia } from "@remotion/renderer";
|
|
5
|
+
import { getCompositionTemplate, getRootTemplate } from "./templates";
|
|
6
|
+
|
|
7
|
+
export interface RenderOptions {
|
|
8
|
+
entryPoint: string;
|
|
9
|
+
compositionId: string;
|
|
10
|
+
outputPath: string;
|
|
11
|
+
props?: Record<string, unknown>;
|
|
12
|
+
concurrency?: number;
|
|
13
|
+
frameRange?: [number, number];
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface CompositionInfo {
|
|
17
|
+
id: string;
|
|
18
|
+
width: number;
|
|
19
|
+
height: number;
|
|
20
|
+
fps: number;
|
|
21
|
+
durationInFrames: number;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface CreateCompositionOptions {
|
|
25
|
+
name: string;
|
|
26
|
+
dir?: string;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export interface CreateCompositionResult {
|
|
30
|
+
compositionPath: string;
|
|
31
|
+
rootPath: string;
|
|
32
|
+
compositionsDir: string;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* create composition directory structure and template files
|
|
37
|
+
*
|
|
38
|
+
* flow:
|
|
39
|
+
* 1. ensure lib/remotion/compositions/ exists
|
|
40
|
+
* 2. create template composition tsx file
|
|
41
|
+
* 3. create template root tsx file with registerRoot
|
|
42
|
+
* 4. files are ready to customize
|
|
43
|
+
*/
|
|
44
|
+
export async function createComposition(
|
|
45
|
+
options: CreateCompositionOptions,
|
|
46
|
+
): Promise<CreateCompositionResult> {
|
|
47
|
+
const { name, dir } = options;
|
|
48
|
+
|
|
49
|
+
// use provided dir or default to lib/remotion/compositions
|
|
50
|
+
const compositionsDir =
|
|
51
|
+
dir || join(process.cwd(), "lib/remotion/compositions");
|
|
52
|
+
|
|
53
|
+
// ensure directory exists
|
|
54
|
+
if (!existsSync(compositionsDir)) {
|
|
55
|
+
mkdirSync(compositionsDir, { recursive: true });
|
|
56
|
+
console.log(`[remotion] created directory: ${compositionsDir}`);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const compositionPath = join(compositionsDir, `${name}.tsx`);
|
|
60
|
+
const rootPath = join(compositionsDir, `${name}.root.tsx`);
|
|
61
|
+
|
|
62
|
+
// create template composition file
|
|
63
|
+
const compositionTemplate = getCompositionTemplate(name);
|
|
64
|
+
|
|
65
|
+
// create template root file
|
|
66
|
+
const rootTemplate = getRootTemplate(name);
|
|
67
|
+
|
|
68
|
+
// write files
|
|
69
|
+
writeFileSync(compositionPath, compositionTemplate);
|
|
70
|
+
writeFileSync(rootPath, rootTemplate);
|
|
71
|
+
|
|
72
|
+
console.log(`[remotion] created composition: ${compositionPath}`);
|
|
73
|
+
console.log(`[remotion] created root: ${rootPath}`);
|
|
74
|
+
console.log(`\n[remotion] next steps:`);
|
|
75
|
+
console.log(` 1. mkdir -p lib/remotion/public`);
|
|
76
|
+
console.log(` 2. cp media/video.mp4 media/audio.mp3 lib/remotion/public/`);
|
|
77
|
+
console.log(` 3. edit composition to use staticFile("filename.ext")`);
|
|
78
|
+
console.log(
|
|
79
|
+
` 4. bun run lib/remotion/index.ts render ${rootPath} ${name} output.mp4`,
|
|
80
|
+
);
|
|
81
|
+
|
|
82
|
+
return {
|
|
83
|
+
compositionPath,
|
|
84
|
+
rootPath,
|
|
85
|
+
compositionsDir,
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* render a composition to video file
|
|
91
|
+
*
|
|
92
|
+
* flow:
|
|
93
|
+
* 1. bundle the remotion project using webpack
|
|
94
|
+
* 2. get composition metadata (verify it exists)
|
|
95
|
+
* 3. render each frame using chrome headless
|
|
96
|
+
* 4. encode frames to video using ffmpeg
|
|
97
|
+
* 5. save final video to outputPath
|
|
98
|
+
*
|
|
99
|
+
* this is the main rendering function that converts
|
|
100
|
+
* react components into actual video files
|
|
101
|
+
*/
|
|
102
|
+
export async function render(options: RenderOptions): Promise<string> {
|
|
103
|
+
const {
|
|
104
|
+
entryPoint,
|
|
105
|
+
compositionId,
|
|
106
|
+
outputPath,
|
|
107
|
+
props = {},
|
|
108
|
+
concurrency,
|
|
109
|
+
frameRange,
|
|
110
|
+
} = options;
|
|
111
|
+
|
|
112
|
+
if (!entryPoint || !compositionId || !outputPath) {
|
|
113
|
+
throw new Error("entryPoint, compositionId, and outputPath are required");
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
if (!existsSync(entryPoint)) {
|
|
117
|
+
throw new Error(`entry point not found: ${entryPoint}`);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
console.log(`[remotion] bundling ${entryPoint}...`);
|
|
121
|
+
|
|
122
|
+
// step 1: bundle project with webpack
|
|
123
|
+
const bundleLocation = await bundle({
|
|
124
|
+
entryPoint,
|
|
125
|
+
webpackOverride: (config) => config,
|
|
126
|
+
publicDir: join(process.cwd(), "lib/remotion/public"),
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
console.log("[remotion] getting composition info...");
|
|
130
|
+
|
|
131
|
+
// step 2: extract composition metadata
|
|
132
|
+
const compositions = await getCompositions(bundleLocation, {
|
|
133
|
+
inputProps: props,
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
// verify composition exists
|
|
137
|
+
const composition = compositions.find((c) => c.id === compositionId);
|
|
138
|
+
if (!composition) {
|
|
139
|
+
throw new Error(
|
|
140
|
+
`composition '${compositionId}' not found. available: ${compositions
|
|
141
|
+
.map((c) => c.id)
|
|
142
|
+
.join(", ")}`,
|
|
143
|
+
);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
console.log(
|
|
147
|
+
`[remotion] rendering ${composition.id} (${composition.durationInFrames} frames @ ${composition.fps}fps)...`,
|
|
148
|
+
);
|
|
149
|
+
|
|
150
|
+
// step 3-5: render frames and encode to video
|
|
151
|
+
// - launches chrome headless to render each frame
|
|
152
|
+
// - uses ffmpeg to encode frames into h264 video
|
|
153
|
+
// - displays progress as it renders
|
|
154
|
+
await renderMedia({
|
|
155
|
+
composition,
|
|
156
|
+
serveUrl: bundleLocation,
|
|
157
|
+
codec: "h264",
|
|
158
|
+
outputLocation: outputPath,
|
|
159
|
+
inputProps: props,
|
|
160
|
+
concurrency: concurrency || undefined,
|
|
161
|
+
frameRange: frameRange || undefined,
|
|
162
|
+
onProgress: ({ progress, renderedFrames, encodedFrames }) => {
|
|
163
|
+
console.log(
|
|
164
|
+
`[remotion] progress: ${(progress * 100).toFixed(
|
|
165
|
+
1,
|
|
166
|
+
)}% | rendered: ${renderedFrames} | encoded: ${encodedFrames}`,
|
|
167
|
+
);
|
|
168
|
+
},
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
console.log(`[remotion] saved to ${outputPath}`);
|
|
172
|
+
return outputPath;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* render a single frame from composition as image
|
|
177
|
+
*
|
|
178
|
+
* flow:
|
|
179
|
+
* 1. bundle the remotion project
|
|
180
|
+
* 2. get composition metadata
|
|
181
|
+
* 3. render specified frame number using chrome
|
|
182
|
+
* 4. save as png/jpeg image
|
|
183
|
+
*
|
|
184
|
+
* useful for creating thumbnails or previews
|
|
185
|
+
*/
|
|
186
|
+
export async function renderStill(
|
|
187
|
+
entryPoint: string,
|
|
188
|
+
compositionId: string,
|
|
189
|
+
frame: number,
|
|
190
|
+
outputPath: string,
|
|
191
|
+
props?: Record<string, unknown>,
|
|
192
|
+
): Promise<string> {
|
|
193
|
+
if (!entryPoint || !compositionId || !outputPath) {
|
|
194
|
+
throw new Error("entryPoint, compositionId, and outputPath are required");
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
if (!existsSync(entryPoint)) {
|
|
198
|
+
throw new Error(`entry point not found: ${entryPoint}`);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
console.log(`[remotion] bundling ${entryPoint}...`);
|
|
202
|
+
|
|
203
|
+
// step 1: bundle project
|
|
204
|
+
const bundleLocation = await bundle({
|
|
205
|
+
entryPoint,
|
|
206
|
+
webpackOverride: (config) => config,
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
console.log("[remotion] getting composition info...");
|
|
210
|
+
|
|
211
|
+
// step 2: get composition metadata
|
|
212
|
+
const compositions = await getCompositions(bundleLocation, {
|
|
213
|
+
inputProps: props || {},
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
const composition = compositions.find((c) => c.id === compositionId);
|
|
217
|
+
if (!composition) {
|
|
218
|
+
throw new Error(
|
|
219
|
+
`composition '${compositionId}' not found. available: ${compositions
|
|
220
|
+
.map((c) => c.id)
|
|
221
|
+
.join(", ")}`,
|
|
222
|
+
);
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
console.log(`[remotion] rendering frame ${frame}...`);
|
|
226
|
+
|
|
227
|
+
// dynamic import to avoid loading unless needed
|
|
228
|
+
const { renderStill: renderStillFrame } = await import("@remotion/renderer");
|
|
229
|
+
|
|
230
|
+
// step 3-4: render single frame and save as image
|
|
231
|
+
await renderStillFrame({
|
|
232
|
+
composition,
|
|
233
|
+
serveUrl: bundleLocation,
|
|
234
|
+
output: outputPath,
|
|
235
|
+
frame,
|
|
236
|
+
inputProps: props || {},
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
console.log(`[remotion] saved to ${outputPath}`);
|
|
240
|
+
return outputPath;
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* get list of compositions from entry point
|
|
244
|
+
*
|
|
245
|
+
* flow:
|
|
246
|
+
* 1. bundle the remotion project using webpack
|
|
247
|
+
* 2. extract composition metadata (id, dimensions, fps, duration)
|
|
248
|
+
* 3. return array of composition info
|
|
249
|
+
*
|
|
250
|
+
* useful for listing available compositions before rendering
|
|
251
|
+
*/
|
|
252
|
+
|
|
253
|
+
export async function getCompositionsList(
|
|
254
|
+
entryPoint: string,
|
|
255
|
+
): Promise<CompositionInfo[]> {
|
|
256
|
+
if (!existsSync(entryPoint)) {
|
|
257
|
+
throw new Error(`entry point not found: ${entryPoint}`);
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
console.log("[remotion] bundling compositions...");
|
|
261
|
+
|
|
262
|
+
// step 1: bundle project with webpack (creates serve url)
|
|
263
|
+
const bundleLocation = await bundle({
|
|
264
|
+
entryPoint,
|
|
265
|
+
webpackOverride: (config) => config,
|
|
266
|
+
});
|
|
267
|
+
|
|
268
|
+
console.log("[remotion] fetching compositions...");
|
|
269
|
+
|
|
270
|
+
// step 2: extract composition metadata from bundle
|
|
271
|
+
const compositions = await getCompositions(bundleLocation, {
|
|
272
|
+
inputProps: {},
|
|
273
|
+
});
|
|
274
|
+
|
|
275
|
+
// step 3: map to simple info objects
|
|
276
|
+
return compositions.map((comp) => ({
|
|
277
|
+
id: comp.id,
|
|
278
|
+
width: comp.width,
|
|
279
|
+
height: comp.height,
|
|
280
|
+
fps: comp.fps,
|
|
281
|
+
durationInFrames: comp.durationInFrames,
|
|
282
|
+
}));
|
|
283
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* remotion wrapper for programmatic video creation
|
|
5
|
+
* requires @remotion/cli and remotion packages
|
|
6
|
+
*
|
|
7
|
+
* usage: bun run lib/remotion/index.ts <command> <args>
|
|
8
|
+
*
|
|
9
|
+
* simplified workflow:
|
|
10
|
+
* 1. create composition with: bun run lib/remotion/index.ts create <name>
|
|
11
|
+
* 2. copy media files to lib/remotion/public/
|
|
12
|
+
* 3. customize composition files (use staticFile() for media paths)
|
|
13
|
+
* 4. render with: bun run lib/remotion/index.ts render <root.tsx> <id> <output.mp4>
|
|
14
|
+
*/
|
|
15
|
+
import { cli } from "./cli";
|
|
16
|
+
|
|
17
|
+
if (import.meta.main) {
|
|
18
|
+
cli();
|
|
19
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* remotion composition templates
|
|
3
|
+
* used by createComposition to generate starter files
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export function getCompositionTemplate(name: string): string {
|
|
7
|
+
return `import React from "react";
|
|
8
|
+
import {
|
|
9
|
+
AbsoluteFill,
|
|
10
|
+
OffthreadVideo,
|
|
11
|
+
Audio,
|
|
12
|
+
Img,
|
|
13
|
+
useCurrentFrame,
|
|
14
|
+
useVideoConfig,
|
|
15
|
+
interpolate,
|
|
16
|
+
staticFile,
|
|
17
|
+
} from "remotion";
|
|
18
|
+
|
|
19
|
+
export const ${name}: React.FC = () => {
|
|
20
|
+
const frame = useCurrentFrame();
|
|
21
|
+
const { fps } = useVideoConfig();
|
|
22
|
+
|
|
23
|
+
// TODO: customize your composition
|
|
24
|
+
// Example: const video = staticFile("video.mp4");
|
|
25
|
+
// Example: const audio = staticFile("audio.mp3");
|
|
26
|
+
|
|
27
|
+
return (
|
|
28
|
+
<AbsoluteFill style={{ backgroundColor: "black" }}>
|
|
29
|
+
{/* Add your content here */}
|
|
30
|
+
<div
|
|
31
|
+
style={{
|
|
32
|
+
display: "flex",
|
|
33
|
+
alignItems: "center",
|
|
34
|
+
justifyContent: "center",
|
|
35
|
+
fontSize: 60,
|
|
36
|
+
color: "white",
|
|
37
|
+
}}
|
|
38
|
+
>
|
|
39
|
+
Frame {frame}
|
|
40
|
+
</div>
|
|
41
|
+
</AbsoluteFill>
|
|
42
|
+
);
|
|
43
|
+
};
|
|
44
|
+
`;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export function getRootTemplate(name: string): string {
|
|
48
|
+
return `import React from "react";
|
|
49
|
+
import { Composition, registerRoot } from "remotion";
|
|
50
|
+
import { ${name} } from "./${name}";
|
|
51
|
+
|
|
52
|
+
// TODO: configure your composition settings
|
|
53
|
+
const fps = 30;
|
|
54
|
+
const durationInFrames = 150; // 5 seconds at 30fps
|
|
55
|
+
const width = 1920;
|
|
56
|
+
const height = 1080;
|
|
57
|
+
|
|
58
|
+
registerRoot(() => {
|
|
59
|
+
return (
|
|
60
|
+
<>
|
|
61
|
+
<Composition
|
|
62
|
+
id="${name}"
|
|
63
|
+
component={${name}}
|
|
64
|
+
durationInFrames={durationInFrames}
|
|
65
|
+
fps={fps}
|
|
66
|
+
width={width}
|
|
67
|
+
height={height}
|
|
68
|
+
/>
|
|
69
|
+
</>
|
|
70
|
+
);
|
|
71
|
+
});
|
|
72
|
+
`;
|
|
73
|
+
}
|