motionrender 0.0.0-stage → 0.2.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.
Files changed (203) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +61 -2
  3. package/blocks/badge.json +68 -0
  4. package/blocks/big-stat.json +240 -0
  5. package/blocks/cta-end.json +283 -0
  6. package/blocks/feature-list.json +286 -0
  7. package/blocks/footage.json +43 -0
  8. package/blocks/fx-background-swap.json +170 -0
  9. package/blocks/fx-before-after.json +212 -0
  10. package/blocks/fx-captions.json +34 -0
  11. package/blocks/fx-chat.json +368 -0
  12. package/blocks/fx-checklist.json +609 -0
  13. package/blocks/fx-clone-wall.json +181 -0
  14. package/blocks/fx-color-pop.json +92 -0
  15. package/blocks/fx-command-bridge.json +358 -0
  16. package/blocks/fx-counter-hero.json +206 -0
  17. package/blocks/fx-cta-card.json +337 -0
  18. package/blocks/fx-day-to-night.json +174 -0
  19. package/blocks/fx-duo-title.json +245 -0
  20. package/blocks/fx-duotone.json +95 -0
  21. package/blocks/fx-extruded-title.json +309 -0
  22. package/blocks/fx-gallery.json +239 -0
  23. package/blocks/fx-glass-cards.json +921 -0
  24. package/blocks/fx-glitch-title.json +373 -0
  25. package/blocks/fx-grade-look.json +91 -0
  26. package/blocks/fx-highlighter.json +53 -0
  27. package/blocks/fx-icon-orbit.json +2694 -0
  28. package/blocks/fx-lens-flare.json +325 -0
  29. package/blocks/fx-letterbox.json +105 -0
  30. package/blocks/fx-light-leak.json +140 -0
  31. package/blocks/fx-map-journey.json +443 -0
  32. package/blocks/fx-neon-outline.json +743 -0
  33. package/blocks/fx-notifications.json +456 -0
  34. package/blocks/fx-progress-ring.json +143 -0
  35. package/blocks/fx-pull-out.json +68 -0
  36. package/blocks/fx-punch-in.json +81 -0
  37. package/blocks/fx-rgb-flash.json +166 -0
  38. package/blocks/fx-shake-hit.json +120 -0
  39. package/blocks/fx-split-reveal.json +110 -0
  40. package/blocks/fx-spotlight.json +1383 -0
  41. package/blocks/fx-stats-split.json +500 -0
  42. package/blocks/fx-step-tracker.json +528 -0
  43. package/blocks/fx-sticker-freeze.json +584 -0
  44. package/blocks/fx-strike-rewrite.json +79 -0
  45. package/blocks/fx-ticker.json +179 -0
  46. package/blocks/fx-timeline.json +1287 -0
  47. package/blocks/fx-tracked-label.json +167 -0
  48. package/blocks/fx-typewriter-quote.json +164 -0
  49. package/blocks/handle.json +43 -0
  50. package/blocks/icon-row.json +404 -0
  51. package/blocks/image-caption.json +248 -0
  52. package/blocks/lower-third.json +106 -0
  53. package/blocks/phone-mockup.json +459 -0
  54. package/blocks/progress-bar.json +51 -0
  55. package/blocks/quote.json +347 -0
  56. package/blocks/section-title.json +240 -0
  57. package/blocks/split-screen.json +283 -0
  58. package/blocks/stat-grid.json +315 -0
  59. package/blocks/steps.json +266 -0
  60. package/blocks/title-hero.json +287 -0
  61. package/dist/builder.d.ts +1 -0
  62. package/dist/builder.js +169 -0
  63. package/dist/cli.js +9301 -0
  64. package/dist/fonts/LICENSE-Inter.txt +93 -0
  65. package/dist/fonts/inter-cyrillic-ext-opsz-italic.woff2 +0 -0
  66. package/dist/fonts/inter-cyrillic-ext-opsz-normal.woff2 +0 -0
  67. package/dist/fonts/inter-cyrillic-opsz-italic.woff2 +0 -0
  68. package/dist/fonts/inter-cyrillic-opsz-normal.woff2 +0 -0
  69. package/dist/fonts/inter-greek-ext-opsz-italic.woff2 +0 -0
  70. package/dist/fonts/inter-greek-ext-opsz-normal.woff2 +0 -0
  71. package/dist/fonts/inter-greek-opsz-italic.woff2 +0 -0
  72. package/dist/fonts/inter-greek-opsz-normal.woff2 +0 -0
  73. package/dist/fonts/inter-latin-ext-opsz-italic.woff2 +0 -0
  74. package/dist/fonts/inter-latin-ext-opsz-normal.woff2 +0 -0
  75. package/dist/fonts/inter-latin-opsz-italic.woff2 +0 -0
  76. package/dist/fonts/inter-latin-opsz-normal.woff2 +0 -0
  77. package/dist/fonts/inter-vietnamese-opsz-italic.woff2 +0 -0
  78. package/dist/fonts/inter-vietnamese-opsz-normal.woff2 +0 -0
  79. package/dist/index.d.ts +2 -0
  80. package/dist/index.js +2330 -0
  81. package/dist/player.d.ts +1 -0
  82. package/dist/player.js +80 -0
  83. package/dist/react.d.ts +1 -0
  84. package/dist/react.js +140 -0
  85. package/dist/runtime/canvas-runtime.js +261 -0
  86. package/dist/runtime/lottie_light_canvas.min.js +1 -0
  87. package/dist/runtime/text-layout.js +50 -0
  88. package/dist/sfx/click.wav +0 -0
  89. package/dist/sfx/ding.wav +0 -0
  90. package/dist/sfx/pop.wav +0 -0
  91. package/dist/sfx/riser.wav +0 -0
  92. package/dist/sfx/thump.wav +0 -0
  93. package/dist/sfx/tick.wav +0 -0
  94. package/dist/sfx/whoosh.wav +0 -0
  95. package/dist/types/packages/ai/src/assets.d.ts +26 -0
  96. package/dist/types/packages/ai/src/batch.d.ts +19 -0
  97. package/dist/types/packages/ai/src/compose.d.ts +34 -0
  98. package/dist/types/packages/ai/src/history.d.ts +37 -0
  99. package/dist/types/packages/ai/src/image.d.ts +19 -0
  100. package/dist/types/packages/ai/src/index.d.ts +13 -0
  101. package/dist/types/packages/ai/src/json.d.ts +2 -0
  102. package/dist/types/packages/ai/src/narrate.d.ts +63 -0
  103. package/dist/types/packages/ai/src/patch.d.ts +15 -0
  104. package/dist/types/packages/ai/src/project.d.ts +27 -0
  105. package/dist/types/packages/ai/src/prompt.d.ts +30 -0
  106. package/dist/types/packages/ai/src/providers.d.ts +109 -0
  107. package/dist/types/packages/ai/src/template.d.ts +80 -0
  108. package/dist/types/packages/ai/src/voiceover.d.ts +49 -0
  109. package/dist/types/packages/animation/src/index.d.ts +27 -0
  110. package/dist/types/packages/assets/src/cache.d.ts +26 -0
  111. package/dist/types/packages/assets/src/index.d.ts +8 -0
  112. package/dist/types/packages/builder/src/index.d.ts +270 -0
  113. package/dist/types/packages/cli/src/ai-studio-page.d.ts +1 -0
  114. package/dist/types/packages/cli/src/ai-studio.d.ts +35 -0
  115. package/dist/types/packages/cli/src/ai.d.ts +3 -0
  116. package/dist/types/packages/cli/src/args.d.ts +9 -0
  117. package/dist/types/packages/cli/src/blocks-cli.d.ts +3 -0
  118. package/dist/types/packages/cli/src/blocks.d.ts +50 -0
  119. package/dist/types/packages/cli/src/build.d.ts +1 -0
  120. package/dist/types/packages/cli/src/dev-page.d.ts +1 -0
  121. package/dist/types/packages/cli/src/dev.d.ts +13 -0
  122. package/dist/types/packages/cli/src/index.d.ts +2 -0
  123. package/dist/types/packages/cli/src/init.d.ts +10 -0
  124. package/dist/types/packages/cli/src/serve.d.ts +2 -0
  125. package/dist/types/packages/cli/src/studio.d.ts +36 -0
  126. package/dist/types/packages/cli/src/templates.d.ts +63 -0
  127. package/dist/types/packages/cli/src/thumbnail.d.ts +20 -0
  128. package/dist/types/packages/cli/src/track.d.ts +35 -0
  129. package/dist/types/packages/cli/src/worker.d.ts +13 -0
  130. package/dist/types/packages/contracts/src/index.d.ts +377 -0
  131. package/dist/types/packages/core/src/audio.d.ts +14 -0
  132. package/dist/types/packages/core/src/distributed.d.ts +50 -0
  133. package/dist/types/packages/core/src/index.d.ts +63 -0
  134. package/dist/types/packages/core/src/media.d.ts +11 -0
  135. package/dist/types/packages/core/src/review.d.ts +29 -0
  136. package/dist/types/packages/ffmpeg/src/index.d.ts +68 -0
  137. package/dist/types/packages/graphics/src/fonts.d.ts +3 -0
  138. package/dist/types/packages/graphics/src/index.d.ts +121 -0
  139. package/dist/types/packages/graphics/src/runtime.d.ts +10 -0
  140. package/dist/types/packages/jobs/src/env.d.ts +78 -0
  141. package/dist/types/packages/jobs/src/handlers.d.ts +17 -0
  142. package/dist/types/packages/jobs/src/index.d.ts +5 -0
  143. package/dist/types/packages/jobs/src/input.d.ts +18 -0
  144. package/dist/types/packages/jobs/src/queue.d.ts +70 -0
  145. package/dist/types/packages/jobs/src/redis.d.ts +42 -0
  146. package/dist/types/packages/player/src/bundle.d.ts +4 -0
  147. package/dist/types/packages/player/src/canvas-runtime.d.ts +11 -0
  148. package/dist/types/packages/player/src/index.d.ts +29 -0
  149. package/dist/types/packages/react/src/index.d.ts +76 -0
  150. package/dist/types/packages/renderer/src/index.d.ts +35 -0
  151. package/dist/types/packages/renderer/src/pool.d.ts +7 -0
  152. package/dist/types/packages/renderer/src/video.d.ts +9 -0
  153. package/dist/types/packages/schema/src/captions.d.ts +24 -0
  154. package/dist/types/packages/schema/src/expression.d.ts +1 -0
  155. package/dist/types/packages/schema/src/index.d.ts +1213 -0
  156. package/dist/types/packages/schema/src/variables.d.ts +115 -0
  157. package/dist/types/packages/storage/src/index.d.ts +78 -0
  158. package/dist/types/packages/timeline/src/index.d.ts +104 -0
  159. package/package.json +78 -4
  160. package/skills/ove/SKILL.md +356 -0
  161. package/skills/ove-ai-compose/SKILL.md +36 -0
  162. package/skills/ove-batch-videos/SKILL.md +23 -0
  163. package/skills/ove-code-video/SKILL.md +68 -0
  164. package/skills/ove-effects/SKILL.md +65 -0
  165. package/skills/ove-make-reel/SKILL.md +30 -0
  166. package/skills/ove-voiceover-captions/SKILL.md +31 -0
  167. package/studio/assets/index-CzOvWv9w.css +1 -0
  168. package/studio/assets/index-J_fvKgng.js +11 -0
  169. package/studio/index.html +16 -0
  170. package/templates/case-study/composition.json +358 -0
  171. package/templates/case-study/template.json +8 -0
  172. package/templates/event-invite/composition.json +245 -0
  173. package/templates/event-invite/template.json +8 -0
  174. package/templates/explainer-square/composition.json +1335 -0
  175. package/templates/explainer-square/template.json +13 -0
  176. package/templates/keynote-wide/composition.json +1458 -0
  177. package/templates/keynote-wide/template.json +13 -0
  178. package/templates/launch-wide/composition.json +1306 -0
  179. package/templates/launch-wide/template.json +13 -0
  180. package/templates/product-card/composition.json +196 -0
  181. package/templates/product-card/data.example.json +5 -0
  182. package/templates/product-card/template.json +8 -0
  183. package/templates/product-wide/composition.json +1609 -0
  184. package/templates/product-wide/template.json +14 -0
  185. package/templates/quote-card/composition.json +123 -0
  186. package/templates/quote-card/template.json +8 -0
  187. package/templates/sale-promo/composition.json +290 -0
  188. package/templates/sale-promo/template.json +8 -0
  189. package/templates/showcase-tall/composition.json +1646 -0
  190. package/templates/showcase-tall/template.json +14 -0
  191. package/templates/slideshow/composition.json +167 -0
  192. package/templates/slideshow/template.json +8 -0
  193. package/templates/social-reel/composition.json +252 -0
  194. package/templates/social-reel/template.json +8 -0
  195. package/templates/starter/assets/logo.svg +4 -0
  196. package/templates/starter/composition.json +84 -0
  197. package/templates/story-tall/composition.json +1379 -0
  198. package/templates/story-tall/template.json +13 -0
  199. package/themes/espresso.json +15 -0
  200. package/themes/midnight.json +15 -0
  201. package/themes/neon.json +15 -0
  202. package/themes/paper.json +15 -0
  203. package/themes/signal.json +15 -0
@@ -0,0 +1,63 @@
1
+ import { outputFormats, type Composition } from '../../schema/src/index.js';
2
+ import { type X264Preset } from '../../ffmpeg/src/index.js';
3
+ export * from '../../schema/src/index.js';
4
+ export * from '../../timeline/src/index.js';
5
+ export { planAudio } from './audio.js';
6
+ export { masterAudio, measureMix, measureLoudness, sfxFile } from './audio.js';
7
+ export { cacheRoot, cacheUsage, cleanCache, type CacheUsage } from '../../assets/src/index.js';
8
+ export { reviewComposition, type ReviewIssue, type ReviewResult, type ReviewOptions } from './review.js';
9
+ export { measureMedia, attachCaptions, prepareComposition, captionTrack } from './media.js';
10
+ export * from './distributed.js';
11
+ export { createRenderer, renderFrames, defaultConcurrency, launchBrowser, describeBrowser, browserInstallHint, type Renderer } from '../../renderer/src/index.js';
12
+ export { x264Presets, defaultPreset, checkFfmpeg, requiredEncoders, ffmpegPath, ffprobePath, type X264Preset } from '../../ffmpeg/src/index.js';
13
+ export type OutputFormat = typeof outputFormats[number];
14
+ export type LoadedComposition = {
15
+ composition: Composition;
16
+ baseDir: string;
17
+ };
18
+ export declare function loadCompositionFile(path: string, values?: Record<string, unknown>): Promise<LoadedComposition>;
19
+ export type RenderProgress = {
20
+ frame: number;
21
+ rendered: number;
22
+ total: number;
23
+ };
24
+ export type RenderMediaOptions = {
25
+ output: string;
26
+ baseDir?: string;
27
+ /** Run the composition's code layers (JavaScript). Only for compositions you trust. */
28
+ allowCode?: boolean;
29
+ /** Overrides the composition's export settings. When format is left out it follows the output's extension, then export.format. */
30
+ format?: OutputFormat;
31
+ codec?: 'h264' | 'h265';
32
+ transparent?: boolean;
33
+ /** Overrides export.crf / bitrate / audioBitrate / scale / loudness. */ crf?: number;
34
+ bitrate?: string;
35
+ audioBitrate?: string;
36
+ scale?: number;
37
+ loudness?: number;
38
+ /** false renders without the composition's motion blur, for quick drafts. */ motionBlur?: boolean;
39
+ /** First and last frame to render, inclusive. Defaults to the whole composition. */
40
+ frameRange?: [number, number];
41
+ concurrency?: number;
42
+ preset?: X264Preset;
43
+ onProgress?: (progress: RenderProgress) => void;
44
+ signal?: AbortSignal;
45
+ /** false renders silent video; distributed chunks use this and the audio is mixed once when they are joined. */
46
+ audio?: boolean;
47
+ };
48
+ export type RenderMediaResult = {
49
+ output: string;
50
+ format: OutputFormat;
51
+ frames: number;
52
+ durationSeconds: number;
53
+ };
54
+ export declare const formatForOutput: (output: string, fallback: OutputFormat) => OutputFormat;
55
+ export declare function renderMedia(composition: Composition, options: RenderMediaOptions): Promise<RenderMediaResult>;
56
+ export type RenderStillOptions = {
57
+ frame?: number;
58
+ output?: string;
59
+ baseDir?: string;
60
+ transparent?: boolean;
61
+ allowCode?: boolean;
62
+ };
63
+ export declare function renderStill(composition: Composition, options?: RenderStillOptions): Promise<Buffer>;
@@ -0,0 +1,11 @@
1
+ import { type Composition, type MediaInfo, type CaptionCue } from '../../schema/src/index.js';
2
+ type Measured = {
3
+ duration: number;
4
+ sounds: [number, number][];
5
+ };
6
+ export declare function measureSource(source: string): Promise<Measured>;
7
+ export declare function measureMedia(raw: any, baseDir: string, fps?: any): Promise<Record<string, MediaInfo>>;
8
+ export declare function attachCaptions(composition: Composition, baseDir: string): Promise<Composition>;
9
+ export declare function captionTrack(composition: Composition): CaptionCue[];
10
+ export declare function prepareComposition(raw: unknown, values?: Record<string, unknown>, baseDir?: string): Promise<Composition>;
11
+ export {};
@@ -0,0 +1,29 @@
1
+ import type { Composition } from '../../schema/src/index.js';
2
+ export type ReviewIssue = {
3
+ severity: 'error' | 'warning' | 'info';
4
+ code: string;
5
+ message: string;
6
+ frame?: number;
7
+ layer?: string;
8
+ };
9
+ export type ReviewResult = {
10
+ issues: ReviewIssue[];
11
+ sheet: Buffer;
12
+ sheetFrames: number[];
13
+ sampledFrames: number;
14
+ loudness?: {
15
+ integrated: number;
16
+ truePeak: number;
17
+ };
18
+ };
19
+ export type ReviewOptions = {
20
+ allowCode?: boolean;
21
+ baseDir?: string;
22
+ every?: number;
23
+ sheetFrames?: number;
24
+ columns?: number;
25
+ concurrency?: number;
26
+ audio?: boolean;
27
+ onProgress?: (done: number, total: number) => void;
28
+ };
29
+ export declare function reviewComposition(composition: Composition, options?: ReviewOptions): Promise<ReviewResult>;
@@ -0,0 +1,68 @@
1
+ export declare const x264Presets: readonly ["ultrafast", "superfast", "veryfast", "faster", "fast", "medium", "slow", "slower", "veryslow"];
2
+ export type X264Preset = typeof x264Presets[number];
3
+ export type EncodeOptions = {
4
+ preset?: X264Preset;
5
+ };
6
+ export declare const defaultPreset: X264Preset;
7
+ export type Mp4Encoder = {
8
+ write(frame: Buffer): Promise<void>;
9
+ finish(): Promise<void>;
10
+ abort(): void;
11
+ };
12
+ export type Encoder = Mp4Encoder;
13
+ export declare const ffmpegPath: () => string;
14
+ export declare const ffprobePath: () => string;
15
+ export type AudioClip = {
16
+ source: string;
17
+ start: number;
18
+ duration: number;
19
+ trim?: number;
20
+ rate?: number;
21
+ loop?: boolean;
22
+ volume?: number;
23
+ fadeIn?: number;
24
+ fadeOut?: number;
25
+ envelope?: [number, number][];
26
+ };
27
+ export declare function envelopeExpression(points: [number, number][]): string;
28
+ export type AudioMix = {
29
+ clips: AudioClip[];
30
+ durationSeconds: number;
31
+ offsetSeconds?: number;
32
+ gainDb?: number;
33
+ };
34
+ export declare function audioMixArgs(mix: AudioMix | undefined, audioCodec?: string[]): string[];
35
+ export declare const sfxRecipes: Record<string, string[]>;
36
+ export declare const sfxArgs: (name: string, output: string) => string[];
37
+ export type VideoFormat = 'mp4' | 'webm' | 'mov' | 'gif';
38
+ export type QualityOptions = {
39
+ crf?: number;
40
+ bitrate?: string;
41
+ audioBitrate?: string;
42
+ };
43
+ export type VideoEncodeOptions = EncodeOptions & QualityOptions & {
44
+ format?: VideoFormat;
45
+ codec?: 'h264' | 'h265';
46
+ transparent?: boolean;
47
+ };
48
+ export declare function encodeMp4(framesPattern: string, fps: number, output: string, audio?: AudioMix, options?: VideoEncodeOptions): Promise<void>;
49
+ export declare function createEncoder(fps: number, output: string, audio?: AudioMix, options?: VideoEncodeOptions): Encoder;
50
+ export declare const createMp4Encoder: (fps: number, output: string, audio?: AudioMix, options?: EncodeOptions & {
51
+ codec?: "h264" | "h265";
52
+ }) => Mp4Encoder;
53
+ export declare function concatSegments(segments: string[], listFile: string, output: string, audio?: AudioMix, options?: Pick<VideoEncodeOptions, 'format' | 'audioBitrate'>): Promise<void>;
54
+ export type ExtractOptions = {
55
+ fps: number;
56
+ maxWidth: number;
57
+ maxHeight: number;
58
+ durationSeconds?: number;
59
+ startSeconds?: number;
60
+ };
61
+ export declare function extractFrames(source: string, outDir: string, options: ExtractOptions): Promise<void>;
62
+ export declare const requiredEncoders: Record<string, string[]>;
63
+ export declare function checkFfmpeg(): Promise<{
64
+ version: string;
65
+ missing: Record<string, string[]>;
66
+ }>;
67
+ export declare function hasAudioStream(path: string): Promise<boolean>;
68
+ export declare function probe(path: string): Promise<string>;
@@ -0,0 +1,3 @@
1
+ import { type FontSpec } from './index.js';
2
+ export declare function builtinFontDir(): string;
3
+ export declare const builtinFonts: () => Promise<FontSpec[]>;
@@ -0,0 +1,121 @@
1
+ import type { EvaluatedLayer } from '../../timeline/src/index.js';
2
+ import { type CaptionCue } from '../../schema/src/index.js';
3
+ export type CaptionWordState = {
4
+ text: string;
5
+ state: 0 | 1 | 2;
6
+ emphasis?: boolean;
7
+ };
8
+ export type DrawOperation = {
9
+ kind: 'text' | 'image' | 'video' | 'captions' | 'rect' | 'circle' | 'path' | 'group' | 'html' | 'lottie' | 'shader' | 'code' | 'react';
10
+ layer: EvaluatedLayer;
11
+ children?: DrawOperation[];
12
+ frameKey?: string;
13
+ fontPrefix?: string;
14
+ fontStack?: string;
15
+ spanStacks?: string[];
16
+ caption?: {
17
+ words: CaptionWordState[];
18
+ } | null;
19
+ vars?: Record<string, string | number>;
20
+ mediaTime?: number;
21
+ };
22
+ export declare const toDrawOperations: (layers: EvaluatedLayer[]) => DrawOperation[];
23
+ export declare const flattenLayers: (layers: readonly any[]) => any[];
24
+ export declare const flattenOperations: (operations: readonly DrawOperation[]) => DrawOperation[];
25
+ export declare const htmlReferences: (layer: {
26
+ html?: string;
27
+ css?: string;
28
+ }) => string[];
29
+ export declare const collectCodeSources: (layers: readonly any[]) => string[];
30
+ /** True when any layer runs the composition's own JavaScript. */
31
+ export declare const hasCodeLayers: (layers: readonly any[]) => boolean;
32
+ /** True when any layer is a React component (its markup can name any image asset the composition declares). */
33
+ export declare const hasReactLayers: (layers: readonly any[]) => boolean;
34
+ export declare const collectLottieSources: (layers: readonly any[]) => string[];
35
+ export declare const collectImageSources: (layers: readonly any[]) => string[];
36
+ export type TextLayoutOptions = {
37
+ fontSize: number;
38
+ maxWidth?: number;
39
+ maxLines?: number;
40
+ minFontSize?: number;
41
+ };
42
+ export type TextLayout = {
43
+ lines: string[];
44
+ fontSize: number;
45
+ truncated: boolean;
46
+ };
47
+ export type TextSpan = {
48
+ text: string;
49
+ fontSize?: number;
50
+ [style: string]: unknown;
51
+ };
52
+ export type RichLayout = {
53
+ lines: {
54
+ runs: {
55
+ text: string;
56
+ span: number;
57
+ kind: 'word' | 'space';
58
+ size: number;
59
+ width: number;
60
+ }[];
61
+ width: number;
62
+ }[];
63
+ scale: number;
64
+ truncated: boolean;
65
+ };
66
+ export type TextNote = {
67
+ id: string;
68
+ kind: 'text' | 'captions';
69
+ x0: number;
70
+ y0: number;
71
+ x1: number;
72
+ y1: number;
73
+ size: number;
74
+ baseSize: number;
75
+ alpha: number;
76
+ color: string;
77
+ truncated: boolean;
78
+ shrunk: boolean;
79
+ text: string;
80
+ words: number;
81
+ };
82
+ export type FrameReport = {
83
+ texts: TextNote[];
84
+ thumb: {
85
+ width: number;
86
+ height: number;
87
+ pixels: number[];
88
+ };
89
+ };
90
+ export type FontSpec = {
91
+ family: string;
92
+ src: string;
93
+ url: string;
94
+ weight: number | string;
95
+ style: string;
96
+ unicodeRange?: string;
97
+ };
98
+ export declare const builtinFontFaces: {
99
+ family: string;
100
+ file: string;
101
+ weight: string;
102
+ style: 'normal' | 'italic';
103
+ unicodeRange: string;
104
+ }[];
105
+ export declare const fontStack: (family: string) => string;
106
+ export declare const cssFont: (layer: {
107
+ fontStyle?: string;
108
+ fontWeight?: number | string;
109
+ fontFamily: string;
110
+ }, fontSize: number) => string;
111
+ export declare function captionAt(layer: {
112
+ cues?: CaptionCue[];
113
+ maxWords: number;
114
+ mode: string;
115
+ offset?: number;
116
+ dropFillers?: boolean;
117
+ emphasis?: string[];
118
+ }, seconds: number): {
119
+ words: CaptionWordState[];
120
+ } | null;
121
+ export declare const prepareOperations: (operations: DrawOperation[], fps?: number) => DrawOperation[];
@@ -0,0 +1,10 @@
1
+ import type { TextLayoutOptions, TextLayout, TextSpan, RichLayout } from './index.js';
2
+ /** layoutText and layoutRich, as source. */
3
+ export declare const textLayoutSource: string;
4
+ /** The Lottie player as source; it defines a global `lottie` when run as a script. */
5
+ export declare const lottieSource: string;
6
+ export declare const lottiePlayerPath: () => string;
7
+ /** The whole page runtime: text layout followed by createCanvasRuntime(canvas, measurePath). */
8
+ export declare const canvasRuntimeSource: string;
9
+ export declare const layoutText: (text: string, options: TextLayoutOptions, measure: (text: string, fontSize: number) => number) => TextLayout;
10
+ export declare const layoutRich: (spans: TextSpan[], options: TextLayoutOptions, measure: (text: string, span: TextSpan, fontSize: number) => number) => RichLayout;
@@ -0,0 +1,78 @@
1
+ import { type AiProvider, type ComposeOptions, type ComposeResult, type NarrateOptions, type NarrateResult, type RevisionMeta } from '../../ai/src/index.js';
2
+ import { type Composition } from '../../core/src/index.js';
3
+ import type { FsProjectStore, Principal, StoredAsset } from '../../storage/src/index.js';
4
+ /** How a job names, finds and describes files. The local implementation maps names to folders on disk; a worker maps them to a scratch folder. */
5
+ export interface JobPaths {
6
+ /** A path inside the requester's space (relative values resolve from `base`). */
7
+ resolve(value: string, label: string, base?: string): string;
8
+ /** `project/path` style name of a file, as shown to people. */
9
+ relative(file: string): string;
10
+ urlFor(file: string): string;
11
+ /** The project a file belongs to. */
12
+ idOf(file: string): string;
13
+ projectDir(value: unknown, brief: string): string;
14
+ fileInside(value: unknown, label: string): string;
15
+ /** What a job reports about a file it made. */
16
+ resultFile(file: string): {
17
+ file: string;
18
+ relative: string;
19
+ url: string;
20
+ };
21
+ readJson(file: string): Promise<any>;
22
+ loadForRender(file: string): Promise<{
23
+ raw: any;
24
+ composition: Composition;
25
+ baseDir: string;
26
+ }>;
27
+ writeComposition(file: string, composition: Composition, meta?: RevisionMeta): Promise<void>;
28
+ }
29
+ /** Work the job code does not own: picking a template and drawing a thumbnail depend on files that ship with the command line. */
30
+ export type JobCapabilities = {
31
+ composeSmart(provider: AiProvider, options: ComposeOptions, mode: {
32
+ full?: boolean;
33
+ }): Promise<ComposeResult & {
34
+ template?: string;
35
+ source?: Record<string, unknown>;
36
+ }>;
37
+ narrateSmart(provider: AiProvider, composed: {
38
+ template?: string;
39
+ }, options: NarrateOptions & {
40
+ brief: string;
41
+ composition: NonNullable<NarrateOptions['composition']>;
42
+ }): Promise<NarrateResult>;
43
+ makeThumbnail(raw: any, values: Record<string, unknown>, baseDir: string, options: {
44
+ frame?: number;
45
+ title?: string;
46
+ width?: number;
47
+ }): Promise<{
48
+ png: Buffer;
49
+ frame: number;
50
+ width: number;
51
+ height: number;
52
+ }>;
53
+ };
54
+ export type JobEnv = {
55
+ who: Principal;
56
+ paths: JobPaths;
57
+ /** The AI provider, or the reason there is none. */
58
+ provider(): AiProvider;
59
+ /** Who made a revision, for the history. */
60
+ providerInfo(): {
61
+ provider?: string;
62
+ model?: string;
63
+ };
64
+ capabilities: JobCapabilities;
65
+ /** The pictures, video and audio a project holds. */
66
+ assets(projectId: string): Promise<StoredAsset[]>;
67
+ /** Only where people may name files anywhere on their own machine (the local studio). Hosted use leaves it out, and jobs that need it refuse. */
68
+ local?: {
69
+ inputFile(value: unknown, label: string, extensions: string[]): string;
70
+ };
71
+ };
72
+ /** Paths for the folder store: every name is resolved inside the principal's space. */
73
+ export declare function createFsPaths(store: FsProjectStore, who: Principal, info?: () => {
74
+ provider?: string;
75
+ model?: string;
76
+ }): JobPaths;
77
+ /** Files you already have may be anywhere on disk, but only the kinds the job uses: audio is sent to the provider, rows are read as data. */
78
+ export declare function localInputFile(value: unknown, label: string, extensions: string[]): string;
@@ -0,0 +1,17 @@
1
+ import type { JobEnv } from './env.js';
2
+ import type { JobSpec } from './queue.js';
3
+ type Input = Record<string, unknown>;
4
+ export declare function createHandlers(env: JobEnv): {
5
+ compose: (input: Input) => JobSpec;
6
+ refine: (input: Input) => JobSpec;
7
+ import: (input: Input) => JobSpec;
8
+ render: (input: Input) => JobSpec;
9
+ thumbnail: (input: Input) => JobSpec;
10
+ review: (input: Input) => JobSpec;
11
+ narrate: (input: Input) => JobSpec;
12
+ transcribe: (input: Input) => JobSpec;
13
+ image: (input: Input) => JobSpec;
14
+ batch: (input: Input) => JobSpec;
15
+ };
16
+ export type Handlers = ReturnType<typeof createHandlers>;
17
+ export {};
@@ -0,0 +1,5 @@
1
+ export * from './input.js';
2
+ export * from './queue.js';
3
+ export * from './env.js';
4
+ export * from './handlers.js';
5
+ export * from './redis.js';
@@ -0,0 +1,18 @@
1
+ import type { BatchSettings } from '../../ai/src/index.js';
2
+ export declare const textOf: (value: unknown, label: string) => string;
3
+ export declare const optionalText: (value: unknown) => string | undefined;
4
+ export declare const boolOf: (value: unknown) => value is true | "true" | "on";
5
+ export declare function numberIn(value: unknown, fallback: number, label: string, min: number, max: number): number;
6
+ export declare function optionalNumber(value: unknown, label: string, min: number, max: number): number | undefined;
7
+ export declare function integerIn(value: unknown, fallback: number, label: string, min: number, max: number): number;
8
+ /** The canvas from the same presets the CLI uses, so a page and a command produce the same shape. */
9
+ export declare function canvasFor(input?: Record<string, unknown>): {
10
+ kind: string;
11
+ width: number;
12
+ height: number;
13
+ durationSeconds: number;
14
+ fps: number;
15
+ };
16
+ /** A folder name that is safe on Windows and POSIX, used when the page leaves the folder blank. */
17
+ export declare function folderName(value: string): string;
18
+ export declare function renderSettings(input: Record<string, unknown>): BatchSettings;
@@ -0,0 +1,70 @@
1
+ import type { Job, JobKind } from '../../contracts/src/index.js';
2
+ import type { Principal } from '../../storage/src/index.js';
3
+ import type { JobEnv } from './env.js';
4
+ /** What a handler gives back: the kind of job and the work to do, reporting progress as it goes. */
5
+ export type JobSpec = {
6
+ kind: JobKind;
7
+ run: (progress: (message: string) => void) => Promise<unknown>;
8
+ };
9
+ /** A job as a description, so it can wait in a queue, cross to another process, and be run there: what to do, with what, for whom. */
10
+ export type JobRequest = {
11
+ kind: JobKind;
12
+ input: Record<string, unknown>;
13
+ who: Principal;
14
+ };
15
+ /** Does the work for a request, reporting progress as it goes, and gives the result. */
16
+ export type JobRunner = (request: JobRequest, progress: (message: string) => void) => Promise<unknown>;
17
+ /** Jobs that draw frames (and so need Chromium and run user compositions) are kept apart from jobs that only talk to the AI. */
18
+ export type JobClass = 'render' | 'ai';
19
+ export declare const jobClass: (kind: JobKind) => JobClass;
20
+ export interface JobQueue {
21
+ enqueue(request: JobRequest): Promise<Job>;
22
+ /** A job, only for the person who asked for it. */
23
+ get(id: string, who: Principal): Promise<Job | undefined>;
24
+ recent(who: Principal): Promise<Job[]>;
25
+ /** Called with a copy of each of this person's jobs when it is added, starts, reports, or ends. Returns a function that stops listening. */
26
+ subscribe(who: Principal, listener: (job: Job) => void): () => void;
27
+ close?(): Promise<void>;
28
+ }
29
+ /** Builds the handlers for one person and checks a request with them, which refuses a bad request straight away (before it is queued). */
30
+ export declare function createJobRunner(makeEnv: (who: Principal) => JobEnv): {
31
+ /** Throws the same Error the handler would, without running anything. */
32
+ validate(request: JobRequest): void;
33
+ run: JobRunner;
34
+ };
35
+ /** One job at a time, in this process, forgotten on restart. A hosted setup puts a durable queue behind the same interface. */
36
+ export declare class InProcessQueue implements JobQueue {
37
+ private runner;
38
+ private redact;
39
+ private entries;
40
+ private waiting;
41
+ private listeners;
42
+ private running;
43
+ private nextId;
44
+ /** `redact` cleans a failure message before anyone sees it (a hosted setup removes server paths). */
45
+ constructor(runner: JobRunner, redact?: (message: string) => string);
46
+ enqueue(request: JobRequest): Promise<Job>;
47
+ get(id: string, who: Principal): Promise<{
48
+ messages: string[];
49
+ id: string;
50
+ kind: "image" | "compose" | "refine" | "import" | "thumbnail" | "render" | "review" | "narrate" | "transcribe" | "batch";
51
+ status: "error" | "done" | "queued" | "running";
52
+ result?: unknown;
53
+ error?: string | undefined;
54
+ startedAt?: number | undefined;
55
+ endedAt?: number | undefined;
56
+ } | undefined>;
57
+ recent(who: Principal): Promise<{
58
+ messages: string[];
59
+ id: string;
60
+ kind: "image" | "compose" | "refine" | "import" | "thumbnail" | "render" | "review" | "narrate" | "transcribe" | "batch";
61
+ status: "error" | "done" | "queued" | "running";
62
+ result?: unknown;
63
+ error?: string | undefined;
64
+ startedAt?: number | undefined;
65
+ endedAt?: number | undefined;
66
+ }[]>;
67
+ subscribe(who: Principal, listener: (job: Job) => void): () => void;
68
+ private emit;
69
+ private pump;
70
+ }
@@ -0,0 +1,42 @@
1
+ import { type ConnectionOptions } from 'bullmq';
2
+ import type { Job } from '../../contracts/src/index.js';
3
+ import type { Principal } from '../../storage/src/index.js';
4
+ import { type JobClass, type JobQueue, type JobRequest } from './queue.js';
5
+ export declare const queueName: (cls: JobClass) => string;
6
+ export declare class RedisQueue implements JobQueue {
7
+ private connection;
8
+ private redact;
9
+ private queues;
10
+ private events;
11
+ private listeners;
12
+ constructor(connection: ConnectionOptions, redact?: (message: string) => string);
13
+ enqueue(request: JobRequest): Promise<Job>;
14
+ get(id: string, who: Principal): Promise<{
15
+ id: string;
16
+ kind: "image" | "compose" | "refine" | "import" | "thumbnail" | "render" | "review" | "narrate" | "transcribe" | "batch";
17
+ status: "error" | "done" | "queued" | "running";
18
+ messages: string[];
19
+ result?: unknown;
20
+ error?: string | undefined;
21
+ startedAt?: number | undefined;
22
+ endedAt?: number | undefined;
23
+ } | undefined>;
24
+ recent(who: Principal): Promise<{
25
+ id: string;
26
+ kind: "image" | "compose" | "refine" | "import" | "thumbnail" | "render" | "review" | "narrate" | "transcribe" | "batch";
27
+ status: "error" | "done" | "queued" | "running";
28
+ messages: string[];
29
+ result?: unknown;
30
+ error?: string | undefined;
31
+ startedAt?: number | undefined;
32
+ endedAt?: number | undefined;
33
+ }[]>;
34
+ subscribe(who: Principal, listener: (job: Job) => void): () => void;
35
+ private listening;
36
+ /** One event stream per lane, started when the first person subscribes; each event is turned into the job as it now is and sent to its owner. */
37
+ private listen;
38
+ private toJob;
39
+ close(): Promise<void>;
40
+ }
41
+ /** BullMQ's connection settings from a redis:// address (redis://:password@host:6379/0). */
42
+ export declare function redisConnection(url: string): ConnectionOptions;
@@ -0,0 +1,4 @@
1
+ export declare function bundlePlayer(options?: {
2
+ outfile?: string;
3
+ minify?: boolean;
4
+ }): Promise<string>;
@@ -0,0 +1,11 @@
1
+ // The canvas drawing runtime, generated at build time from packages/graphics/runtime/*.js (see bundle.ts), so the Player draws
2
+ // with exactly the code the renderer uses.
3
+ declare module 'ove:canvas-runtime' {
4
+ export type CanvasRuntime = {
5
+ canvas: HTMLCanvasElement;
6
+ images: Map<string, HTMLImageElement>;
7
+ load(sources: Record<string, string>, fonts: { family: string; src: string; url: string; weight: number | string; style: string; unicodeRange?: string }[], lotties?: Record<string, unknown>, codes?: Record<string, { url?: string; text?: string }>): Promise<void>;
8
+ draw(payload: { width: number; height: number; background?: unknown; transparent?: boolean; grain?: number; frame?: number; operations: unknown[]; videoFrames?: Record<string, string> }, drawables?: Map<string, CanvasImageSource>): Promise<void>;
9
+ };
10
+ export function createCanvasRuntime(canvas: HTMLCanvasElement, measurePath: SVGPathElement): CanvasRuntime;
11
+ }
@@ -0,0 +1,29 @@
1
+ /// <reference path="./canvas-runtime.d.ts" />
2
+ import { type Composition, type MediaInfo } from '../../schema/src/index.js';
3
+ export type PlayerEvent = 'frame' | 'play' | 'pause' | 'ended' | 'error';
4
+ export type PlayerOptions = {
5
+ /** A composition as JSON (variables are resolved with `values`) or an already loaded one. */ composition: unknown;
6
+ values?: Record<string, unknown>;
7
+ /** Measured audio and video for compositions that time scenes from their media ({{media[...]}}), from measureMedia in open-video-engine. */ media?: Record<string, MediaInfo>;
8
+ /** Where relative media paths in the composition are resolved from, usually the composition file's URL. Defaults to the page URL. */ assetBase?: string | URL;
9
+ /** Where the built-in Inter font files are served from. Defaults to the `fonts` folder next to the Player script (the package ships it in `dist/fonts`). */ fontBase?: string | URL;
10
+ /** Where the built-in sound effects (sfx:…) are served from. Defaults to the `sfx` folder next to the Player script. */ sfxBase?: string | URL;
11
+ /** Lets the composition's code layers run in this page. They execute the composition's JavaScript with the page's full powers, so pass true only for compositions you wrote or trust. */ allowCode?: boolean;
12
+ controls?: boolean;
13
+ loop?: boolean;
14
+ autoplay?: boolean; /** 0–1, multiplies every sound. */
15
+ volume?: number;
16
+ };
17
+ export type Player = {
18
+ readonly element: HTMLElement;
19
+ readonly composition: Composition;
20
+ readonly frame: number;
21
+ readonly playing: boolean;
22
+ play(): Promise<void>;
23
+ pause(): void;
24
+ seek(frame: number): Promise<void>;
25
+ setValues(values: Record<string, unknown>): Promise<void>;
26
+ on(event: PlayerEvent, listener: (detail: any) => void): () => void;
27
+ destroy(): void;
28
+ };
29
+ export declare function createPlayer(container: HTMLElement, options: PlayerOptions): Promise<Player>;