reelkit-cli 0.8.0 → 0.10.2

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.
Files changed (122) hide show
  1. package/README.md +13 -1
  2. package/package.json +49 -10
  3. package/skill/.claude-plugin/plugin.json +7 -0
  4. package/skill/SKILL.md +44 -19
  5. package/skill/THIRD_PARTY.md +37 -5
  6. package/skill/commands/launch-film.md +1 -1
  7. package/skill/hooks/hooks.json +1 -0
  8. package/skill/hooks/player.ts +278 -0
  9. package/skill/hooks/project.ts +227 -0
  10. package/skill/hooks/register.tsx +533 -0
  11. package/skill/hooks/timeline.ts +218 -0
  12. package/skill/reference/art-styles.md +70 -0
  13. package/skill/reference/backgrounds.md +1 -1
  14. package/skill/reference/brand-motion.md +62 -0
  15. package/skill/reference/clips.md +3 -3
  16. package/skill/reference/component-authoring.md +3 -1
  17. package/skill/reference/continuity.md +5 -5
  18. package/skill/reference/delivery-review.md +40 -0
  19. package/skill/reference/hebrew-rtl.md +3 -4
  20. package/skill/reference/higgsfield-production.md +70 -0
  21. package/skill/reference/{remotion-composition.md → hyperframes-composition.md} +14 -8
  22. package/skill/reference/kit.md +7 -3
  23. package/skill/reference/launch-film.md +13 -9
  24. package/skill/reference/motion-design.md +26 -22
  25. package/skill/reference/sound-design.md +34 -12
  26. package/skill/reference/studio-editing.md +55 -0
  27. package/skill/reference/studio-pane.md +31 -0
  28. package/skill/reference/style-components.md +40 -0
  29. package/skill/reference/style-recipes.md +86 -0
  30. package/skill/reference/styles.md +17 -10
  31. package/skill/reference/three-d.md +8 -7
  32. package/skill/reference/voice-sync.md +1 -1
  33. package/skill/tests/studio.test.ts +111 -0
  34. package/skill/types/index.d.ts +65 -0
  35. package/src/commands/assets.ts +5 -1
  36. package/src/contract/index.ts +1 -1
  37. package/src/hyperframes/Root.tsx +1 -0
  38. package/src/hyperframes/fonts.ts +54 -0
  39. package/src/hyperframes/frame.tsx +46 -0
  40. package/src/hyperframes/host.tsx +38 -0
  41. package/src/{remotion → hyperframes}/kit/Assemble3D.tsx +1 -1
  42. package/src/hyperframes/kit/BrandTransform3D.tsx +12 -0
  43. package/src/{remotion → hyperframes}/kit/BrowserFrame.tsx +1 -1
  44. package/src/{remotion → hyperframes}/kit/Camera.tsx +1 -1
  45. package/src/{remotion → hyperframes}/kit/Captions.tsx +1 -1
  46. package/src/{remotion → hyperframes}/kit/Card3D.tsx +2 -2
  47. package/src/{remotion → hyperframes}/kit/Carry.tsx +1 -1
  48. package/src/{remotion → hyperframes}/kit/ChapterFrame.tsx +1 -1
  49. package/src/{remotion → hyperframes}/kit/ClipLayer.tsx +1 -1
  50. package/src/{remotion → hyperframes}/kit/Counter.tsx +1 -1
  51. package/src/{remotion → hyperframes}/kit/CounterRoll.tsx +1 -1
  52. package/src/{remotion → hyperframes}/kit/Entrance.tsx +1 -1
  53. package/src/{remotion → hyperframes}/kit/FootageLayer.tsx +1 -1
  54. package/src/{remotion → hyperframes}/kit/GlassPanel.tsx +1 -1
  55. package/src/{remotion → hyperframes}/kit/Grounds.tsx +1 -1
  56. package/src/{remotion → hyperframes}/kit/Headline.tsx +1 -1
  57. package/src/{remotion → hyperframes}/kit/Hero3D.tsx +1 -1
  58. package/src/{remotion → hyperframes}/kit/HudOverlay.tsx +1 -1
  59. package/src/{remotion → hyperframes}/kit/ImageLayers.tsx +1 -1
  60. package/src/{remotion → hyperframes}/kit/KenBurnsImage.tsx +1 -1
  61. package/src/{remotion → hyperframes}/kit/KeyedClip.tsx +1 -1
  62. package/src/{remotion → hyperframes}/kit/Layers.tsx +1 -1
  63. package/src/{remotion → hyperframes}/kit/LowerThird.tsx +1 -1
  64. package/src/{remotion → hyperframes}/kit/Music.tsx +1 -1
  65. package/src/{remotion → hyperframes}/kit/NamedCursor.tsx +1 -1
  66. package/src/{remotion → hyperframes}/kit/Orbit3D.tsx +1 -1
  67. package/src/{remotion → hyperframes}/kit/Particles3D.tsx +1 -1
  68. package/src/{remotion → hyperframes}/kit/Place.tsx +1 -1
  69. package/src/{remotion → hyperframes}/kit/PromptBox.tsx +1 -1
  70. package/src/{remotion → hyperframes}/kit/Scene3D.tsx +2 -2
  71. package/src/{remotion → hyperframes}/kit/SceneFrame.tsx +1 -1
  72. package/src/{remotion → hyperframes}/kit/ScreenOverlay.tsx +1 -1
  73. package/src/{remotion → hyperframes}/kit/Sfx.tsx +1 -1
  74. package/src/{remotion → hyperframes}/kit/SoundCues.tsx +1 -1
  75. package/src/{remotion → hyperframes}/kit/TerminalLog.tsx +1 -1
  76. package/src/{remotion → hyperframes}/kit/Text3D.tsx +1 -1
  77. package/src/{remotion → hyperframes}/kit/TextOnImage.tsx +1 -1
  78. package/src/{remotion → hyperframes}/kit/TitleCard.tsx +1 -1
  79. package/src/{remotion → hyperframes}/kit/Voiceover.tsx +1 -1
  80. package/src/{remotion → hyperframes}/kit/Warp3D.tsx +1 -1
  81. package/src/hyperframes/kit/brand-transform.ts +25 -0
  82. package/src/{remotion → hyperframes}/kit/docs.ts +6 -2
  83. package/src/{remotion → hyperframes}/kit/index.ts +3 -0
  84. package/src/{remotion → hyperframes}/kit/sound-cues.ts +1 -1
  85. package/src/{remotion → hyperframes}/kit/sound-kinds.ts +14 -1
  86. package/src/{remotion → hyperframes}/kit/theme.ts +42 -40
  87. package/src/{remotion → hyperframes}/kit/ui-math.ts +1 -1
  88. package/src/hyperframes/math.ts +62 -0
  89. package/src/hyperframes/three.tsx +10 -0
  90. package/src/project/chromakey.ts +1 -1
  91. package/src/project/layers.ts +1 -1
  92. package/src/project/serve.ts +2 -2
  93. package/src/render/component-preview.ts +11 -55
  94. package/src/render/render.ts +62 -64
  95. package/src/render/serve.ts +31 -0
  96. package/src/render/static-check.ts +15 -4
  97. package/src/render/validate.ts +4 -4
  98. package/src/render/word-check.ts +1 -1
  99. package/src/render/worker.ts +71 -0
  100. package/src/testing/fixtures.ts +1 -1
  101. package/src/remotion/Root.tsx +0 -31
  102. /package/src/{remotion → hyperframes}/kit/Icon.tsx +0 -0
  103. /package/src/{remotion → hyperframes}/kit/beat.ts +0 -0
  104. /package/src/{remotion → hyperframes}/kit/bg-math.ts +0 -0
  105. /package/src/{remotion → hyperframes}/kit/brand-icons.ts +0 -0
  106. /package/src/{remotion → hyperframes}/kit/caption-groups.ts +0 -0
  107. /package/src/{remotion → hyperframes}/kit/caption-style.ts +0 -0
  108. /package/src/{remotion → hyperframes}/kit/image-layers-math.ts +0 -0
  109. /package/src/{remotion → hyperframes}/kit/inter-bold-typeface.ts +0 -0
  110. /package/src/{remotion → hyperframes}/kit/media.ts +0 -0
  111. /package/src/{remotion → hyperframes}/kit/motion-math.ts +0 -0
  112. /package/src/{remotion → hyperframes}/kit/music-math.ts +0 -0
  113. /package/src/{remotion → hyperframes}/kit/quiet-three.ts +0 -0
  114. /package/src/{remotion → hyperframes}/kit/sample-text.ts +0 -0
  115. /package/src/{remotion → hyperframes}/kit/scene3d-context.ts +0 -0
  116. /package/src/{remotion → hyperframes}/kit/seeded.ts +0 -0
  117. /package/src/{remotion → hyperframes}/kit/three-fx-math.ts +0 -0
  118. /package/src/{remotion → hyperframes}/kit/three-math.ts +0 -0
  119. /package/src/{remotion → hyperframes}/kit/transition-math.ts +0 -0
  120. /package/src/{remotion → hyperframes}/kit/ui-theme.ts +0 -0
  121. /package/src/{remotion → hyperframes}/kit/word-anchor.ts +0 -0
  122. /package/src/{remotion → hyperframes}/types.ts +0 -0
@@ -0,0 +1,71 @@
1
+ // Internal subprocess: HyperFrames owns capture, encoding and audio mixing.
2
+ import { execFile } from "node:child_process";
3
+ import { cp, mkdir, mkdtemp, rm, writeFile, readFile } from "node:fs/promises";
4
+ import { tmpdir } from "node:os";
5
+ import { join, extname } from "node:path";
6
+ import { promisify } from "node:util";
7
+ import { createCaptureSession, initializeSession, captureFrame, closeCaptureSession, encodeFramesFromDir, processCompositionAudio, muxVideoWithAudio, applyFaststart, type AudioElement } from "@hyperframes/engine";
8
+ import { serveComposition } from "./serve";
9
+ import type { VideoProps } from "../hyperframes/types";
10
+ import type { AudioRecord } from "../hyperframes/frame";
11
+ import type { RenderOptions } from "./render";
12
+
13
+ const run = promisify(execFile);
14
+ const input = JSON.parse(await readFile(process.argv[2]!, "utf8")) as { dir: string; props: VideoProps; mode: "stills" | "video"; output: string; frames: number[]; options?: RenderOptions; chromePath?: string };
15
+ const m = input.props.manifest, fps = { num: m.fps, den: 1 };
16
+ const work = await mkdtemp(join(tmpdir(), "reelkit-capture-"));
17
+ const server = await serveComposition(input.dir);
18
+ let session: Awaited<ReturnType<typeof createCaptureSession>> | undefined;
19
+ try {
20
+ session = await createCaptureSession(server.url.replace(/\/$/, ""), work, { width: m.width, height: m.height, fps, format: "png", compositionDurationSeconds: m.totalFrames / m.fps }, async (page) => {
21
+ await page.evaluate(async () => { await (window as unknown as { __reelkitReady: Promise<void> }).__reelkitReady; });
22
+ }, { chromePath: input.chromePath, forceScreenshot: true, useDrawElement: false, staticFrameDedup: false, enableBrowserPool: false, browserGpuMode: input.options?.uses3D ? "software" : "auto" });
23
+ await initializeSession(session);
24
+ await session.page.evaluate(async () => { await (window as unknown as { __reelkitReady: Promise<void> }).__reelkitReady; });
25
+ const frames = input.mode === "stills" ? input.frames : Array.from({ length: m.totalFrames }, (_, i) => i);
26
+ for (const frame of frames) {
27
+ if (!Number.isInteger(frame) || frame < 0 || frame >= m.totalFrames) throw new Error(`Frame ${frame} is outside the composition.`);
28
+ const captured = await captureFrame(session, frame, frame / m.fps);
29
+ if (input.mode === "stills") await cp(captured.path, join(input.output, `still-${frame}.png`));
30
+ }
31
+ if (input.mode === "video") {
32
+ const silent = join(work, "silent.mp4");
33
+ const encoded = await encodeFramesFromDir(work, "frame_%06d.png", silent, { fps, width: m.width, height: m.height, codec: "h264", pixelFormat: "yuv420p", quality: input.options?.crf ?? 18, preset: "fast" });
34
+ if (!encoded.success) throw new Error(encoded.error ?? "HyperFrames encoding failed.");
35
+ const records = input.options?.silent ? [] : await session.page.evaluate(() => [...(window as unknown as { __reelkitAudio: Map<string, AudioRecord> }).__reelkitAudio.values()]);
36
+ const audio: AudioElement[] = [];
37
+ const localSources = new Map<string, string>();
38
+ for (const record of records) {
39
+ let src = localSources.get(record.src);
40
+ if (!src) {
41
+ const response = await fetch(record.src); if (!response.ok) throw new Error(`Audio source returned ${response.status}.`);
42
+ src = join(work, `source-${localSources.size}${extname(new URL(record.src).pathname) || ".media"}`);
43
+ await writeFile(src, new Uint8Array(await response.arrayBuffer())); localSources.set(record.src, src);
44
+ }
45
+ const info = JSON.parse((await run("ffprobe", ["-v", "error", "-show_format", "-of", "json", src])).stdout) as { format: { duration: string } };
46
+ let end = Math.min(record.end, record.start + Number(info.format.duration) - record.mediaStart);
47
+ if (record.loop) {
48
+ const looped = join(work, `loop-${audio.length}.wav`);
49
+ await run("ffmpeg", ["-y", "-v", "error", "-stream_loop", "-1", "-i", src, "-t", String(record.end - record.start + record.mediaStart), "-vn", looped]);
50
+ src = looped; end = record.end;
51
+ }
52
+ if (end <= record.start) continue;
53
+ const keys = [...new Map(record.volumeKeyframes.map((k) => [k.time, k])).values()].sort((a, b) => a.time - b.time);
54
+ audio.push({ ...record, src, end, volumeKeyframes: keys.length ? keys : undefined });
55
+ }
56
+ if (audio.length) {
57
+ const mixed = join(work, "audio.m4a");
58
+ const result = await processCompositionAudio(audio, work, join(work, "audio-work"), mixed, m.totalFrames / m.fps);
59
+ if (!result.success) throw new Error(result.error ?? "HyperFrames audio mixing failed.");
60
+ const muxed = await muxVideoWithAudio(silent, mixed, input.output, undefined, { audioCodec: "aac" });
61
+ if (!muxed.success) throw new Error(muxed.error ?? "HyperFrames audio mux failed.");
62
+ } else {
63
+ await mkdir(join(work, "faststart"));
64
+ const result = await applyFaststart(silent, input.output);
65
+ if (!result.success) throw new Error(result.error ?? "Faststart failed.");
66
+ }
67
+ }
68
+ } finally {
69
+ if (session) await closeCaptureSession(session);
70
+ await server.close(); await rm(work, { recursive: true, force: true });
71
+ }
@@ -12,7 +12,7 @@ export const PIXEL_PNG = new Uint8Array(Buffer.from("iVBORw0KGgoAAAANSUhEUgAAAAE
12
12
 
13
13
  // A known-good composition, used as the worked example for composition authors.
14
14
  export const FIXTURE_COMPOSITION = `import React from "react";
15
- import { AbsoluteFill, useVideoConfig } from "remotion";
15
+ import { AbsoluteFill, useVideoConfig } from "reelkit/frame";
16
16
  import { BgMesh, Captions, FootageLayer, fonts, Grade, Grain, KenBurnsImage, palettes, SceneFrame, Vignette, Voiceover, WordReveal } from "reelkit/kit";
17
17
  import type { VideoProps } from "reelkit/kit";
18
18
 
@@ -1,31 +0,0 @@
1
- import React from "react";
2
- import { Composition } from "remotion";
3
- import { ManifestContext, UrlsContext } from "./kit/media";
4
- import type { VideoProps } from "./types";
5
-
6
- const EMPTY: VideoProps = { manifest: { fps: 30, width: 1080, height: 1920, totalFrames: 1, scenes: [] }, urls: {} };
7
-
8
- export const makeRoot = (Video: React.FC<VideoProps>): React.FC => {
9
- const WithMedia: React.FC<VideoProps> = (props) => (
10
- <UrlsContext.Provider value={props.urls}>
11
- <ManifestContext.Provider value={props.manifest}>
12
- <Video {...props} />
13
- </ManifestContext.Provider>
14
- </UrlsContext.Provider>
15
- );
16
- return () => (
17
- <Composition
18
- id="Video"
19
- component={WithMedia as unknown as React.FC<Record<string, unknown>>}
20
- durationInFrames={1}
21
- fps={30}
22
- width={1080}
23
- height={1920}
24
- defaultProps={EMPTY as unknown as Record<string, unknown>}
25
- calculateMetadata={({ props }) => {
26
- const m = (props as unknown as VideoProps).manifest;
27
- return { durationInFrames: m.totalFrames, fps: m.fps, width: m.width, height: m.height };
28
- }}
29
- />
30
- );
31
- };
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes