reelkit-cli 0.1.0
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 +21 -0
- package/README.md +91 -0
- package/bin/reelkit.mjs +5 -0
- package/package.json +89 -0
- package/skill/SKILL.md +101 -0
- package/skill/THIRD_PARTY.md +20 -0
- package/skill/command.md +5 -0
- package/skill/reference/asset-reuse.md +31 -0
- package/skill/reference/captions.md +57 -0
- package/skill/reference/component-authoring.md +26 -0
- package/skill/reference/kit.md +135 -0
- package/skill/reference/motion-design.md +62 -0
- package/skill/reference/remotion-composition.md +58 -0
- package/skill/reference/scene-treatments.md +35 -0
- package/skill/reference/scriptwriting.md +44 -0
- package/skill/reference/sound-design.md +43 -0
- package/src/agents.ts +103 -0
- package/src/api/client.ts +58 -0
- package/src/cli.ts +91 -0
- package/src/commands/assets.ts +196 -0
- package/src/commands/auth.ts +118 -0
- package/src/commands/build.ts +109 -0
- package/src/commands/init.ts +32 -0
- package/src/commands/install.ts +24 -0
- package/src/commands/plan.ts +45 -0
- package/src/context.ts +21 -0
- package/src/contract/index.ts +157 -0
- package/src/credentials.ts +55 -0
- package/src/open.ts +48 -0
- package/src/pipeline/review.ts +30 -0
- package/src/pipeline/schema.ts +110 -0
- package/src/pipeline/timing.ts +30 -0
- package/src/project/manifest.ts +71 -0
- package/src/project/probe.ts +54 -0
- package/src/project/project.ts +58 -0
- package/src/project/serve.ts +81 -0
- package/src/remotion/Root.tsx +29 -0
- package/src/remotion/kit/Captions.tsx +77 -0
- package/src/remotion/kit/Counter.tsx +18 -0
- package/src/remotion/kit/Entrance.tsx +53 -0
- package/src/remotion/kit/FootageLayer.tsx +10 -0
- package/src/remotion/kit/Icon.tsx +35 -0
- package/src/remotion/kit/KenBurnsImage.tsx +18 -0
- package/src/remotion/kit/Layers.tsx +46 -0
- package/src/remotion/kit/LowerThird.tsx +17 -0
- package/src/remotion/kit/SceneFrame.tsx +19 -0
- package/src/remotion/kit/ScreenOverlay.tsx +15 -0
- package/src/remotion/kit/Sfx.tsx +11 -0
- package/src/remotion/kit/TitleCard.tsx +23 -0
- package/src/remotion/kit/Voiceover.tsx +5 -0
- package/src/remotion/kit/brand-icons.ts +37 -0
- package/src/remotion/kit/docs.ts +98 -0
- package/src/remotion/kit/index.ts +20 -0
- package/src/remotion/kit/media.ts +10 -0
- package/src/remotion/kit/theme.ts +131 -0
- package/src/remotion/types.ts +2 -0
- package/src/render/component-preview.ts +65 -0
- package/src/render/deps.ts +8 -0
- package/src/render/render.ts +67 -0
- package/src/render/validate.ts +191 -0
- package/src/testing/conformance.ts +396 -0
- package/src/testing/fake-api.ts +228 -0
- package/src/testing/fixtures.ts +44 -0
- package/src/ui/CommandView.tsx +18 -0
- package/src/ui/run.tsx +20 -0
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
export function silentWav(durationSec: number, rate = 8000): Uint8Array {
|
|
2
|
+
const dataBytes = Math.round(durationSec * rate) * 2;
|
|
3
|
+
const buf = Buffer.alloc(44 + dataBytes);
|
|
4
|
+
buf.write("RIFF", 0); buf.writeUInt32LE(36 + dataBytes, 4); buf.write("WAVE", 8);
|
|
5
|
+
buf.write("fmt ", 12); buf.writeUInt32LE(16, 16); buf.writeUInt16LE(1, 20); buf.writeUInt16LE(1, 22);
|
|
6
|
+
buf.writeUInt32LE(rate, 24); buf.writeUInt32LE(rate * 2, 28); buf.writeUInt16LE(2, 32); buf.writeUInt16LE(16, 34);
|
|
7
|
+
buf.write("data", 36); buf.writeUInt32LE(dataBytes, 40);
|
|
8
|
+
return new Uint8Array(buf);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export const PIXEL_PNG = new Uint8Array(Buffer.from("iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==", "base64"));
|
|
12
|
+
|
|
13
|
+
// A known-good composition, used as the worked example for composition authors.
|
|
14
|
+
export const FIXTURE_COMPOSITION = `import React from "react";
|
|
15
|
+
import { AbsoluteFill, useVideoConfig } from "remotion";
|
|
16
|
+
import { BgMesh, Captions, FootageLayer, fonts, Grade, Grain, KenBurnsImage, palettes, SceneFrame, Vignette, Voiceover, WordReveal } from "reelkit/kit";
|
|
17
|
+
import type { VideoProps } from "reelkit/kit";
|
|
18
|
+
|
|
19
|
+
const palette = palettes.darkTech;
|
|
20
|
+
|
|
21
|
+
export const Video: React.FC<VideoProps> = ({ manifest, urls }) => {
|
|
22
|
+
const { width } = useVideoConfig();
|
|
23
|
+
return (
|
|
24
|
+
<AbsoluteFill>
|
|
25
|
+
{manifest.footageKey ? <FootageLayer src={urls[manifest.footageKey]} dim={0.2} /> : <BgMesh bg={palette.bg} hero={palette.hero} accent={palette.accent} />}
|
|
26
|
+
{manifest.scenes.map((s, i) => (
|
|
27
|
+
<SceneFrame key={s.id} from={s.startFrame} durationInFrames={s.durationFrames}>
|
|
28
|
+
{s.imageKey ? <KenBurnsImage src={urls[s.imageKey]} direction={i % 2 ? "out" : "in"} /> : null}
|
|
29
|
+
{i === 0 && !manifest.footageKey ? (
|
|
30
|
+
<AbsoluteFill style={{ alignItems: "center", justifyContent: "center", padding: width * 0.08 }}>
|
|
31
|
+
<WordReveal text="Demo video" highlight="Demo" highlightColor={palette.hero} style={{ fontFamily: fonts.display, fontWeight: 800, fontSize: width * 0.1, color: palette.ink }} />
|
|
32
|
+
</AbsoluteFill>
|
|
33
|
+
) : null}
|
|
34
|
+
<Captions words={s.words} />
|
|
35
|
+
{s.voiceoverKey ? <Voiceover src={urls[s.voiceoverKey]} /> : null}
|
|
36
|
+
</SceneFrame>
|
|
37
|
+
))}
|
|
38
|
+
{manifest.footageKey ? null : <Grade color={palette.hero} />}
|
|
39
|
+
<Grain blend="overlay" />
|
|
40
|
+
<Vignette />
|
|
41
|
+
</AbsoluteFill>
|
|
42
|
+
);
|
|
43
|
+
};
|
|
44
|
+
`;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { Box, Text } from "ink";
|
|
3
|
+
import Spinner from "ink-spinner";
|
|
4
|
+
import type { Result } from "../context";
|
|
5
|
+
|
|
6
|
+
export type ViewState = { title: string; lines: string[]; result?: Result };
|
|
7
|
+
|
|
8
|
+
// One command's life on screen: a spinner and its latest progress, then a tick or cross and the summary.
|
|
9
|
+
export const CommandView: React.FC<ViewState> = ({ title, lines, result }) => (
|
|
10
|
+
<Box flexDirection="column">
|
|
11
|
+
<Box>
|
|
12
|
+
{result ? <Text color={result.ok ? "green" : "red"}>{result.ok ? "✔" : "✖"}</Text> : <Text color="cyan"><Spinner type="dots" /></Text>}
|
|
13
|
+
<Text bold> {title}</Text>
|
|
14
|
+
</Box>
|
|
15
|
+
{lines.slice(-6).map((line, i) => <Text key={i} dimColor> {line}</Text>)}
|
|
16
|
+
{result ? <Box marginTop={1}><Text color={result.ok ? undefined : "red"}>{result.summary}</Text></Box> : null}
|
|
17
|
+
</Box>
|
|
18
|
+
);
|
package/src/ui/run.tsx
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { render } from "ink";
|
|
3
|
+
import type { Result } from "../context";
|
|
4
|
+
import { CommandView } from "./CommandView";
|
|
5
|
+
|
|
6
|
+
// Runs a command with its progress drawn by Ink. A thrown error becomes a failed Result, so it is shown like any other.
|
|
7
|
+
export async function runInk(title: string, fn: (log: (line: string) => void) => Promise<Result>): Promise<Result> {
|
|
8
|
+
const lines: string[] = [];
|
|
9
|
+
const app = render(<CommandView title={title} lines={lines} />);
|
|
10
|
+
const draw = (result?: Result) => app.rerender(<CommandView title={title} lines={[...lines]} result={result} />);
|
|
11
|
+
let result: Result;
|
|
12
|
+
try {
|
|
13
|
+
result = await fn((line) => { lines.push(line); draw(); });
|
|
14
|
+
} catch (e) {
|
|
15
|
+
result = { ok: false, summary: e instanceof Error ? e.message : String(e) };
|
|
16
|
+
}
|
|
17
|
+
draw(result);
|
|
18
|
+
app.unmount();
|
|
19
|
+
return result;
|
|
20
|
+
}
|