remotion-claude-agent-demo 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/README.md +160 -0
- package/apps/web/README.md +36 -0
- package/apps/web/env.example +20 -0
- package/apps/web/eslint.config.mjs +18 -0
- package/apps/web/next.config.ts +7 -0
- package/apps/web/package-lock.json +10348 -0
- package/apps/web/package.json +35 -0
- package/apps/web/postcss.config.mjs +7 -0
- package/apps/web/public/file.svg +1 -0
- package/apps/web/public/globe.svg +1 -0
- package/apps/web/public/next.svg +1 -0
- package/apps/web/public/vercel.svg +1 -0
- package/apps/web/public/window.svg +1 -0
- package/apps/web/src/app/.well-known/agent-card.json/route.ts +50 -0
- package/apps/web/src/app/background-tasks/[jobId]/cancel/route.ts +29 -0
- package/apps/web/src/app/events/stream/route.ts +58 -0
- package/apps/web/src/app/favicon.ico +0 -0
- package/apps/web/src/app/globals.css +174 -0
- package/apps/web/src/app/layout.tsx +34 -0
- package/apps/web/src/app/messages/answer/route.ts +57 -0
- package/apps/web/src/app/messages/stream/route.ts +381 -0
- package/apps/web/src/app/page.tsx +358 -0
- package/apps/web/src/app/tasks/[taskId]/cancel/route.ts +24 -0
- package/apps/web/src/app/tasks/[taskId]/route.ts +24 -0
- package/apps/web/src/app/tasks/route.ts +13 -0
- package/apps/web/src/components/chat/agent-blocks.tsx +111 -0
- package/apps/web/src/components/chat/ask-user-question-panel.tsx +172 -0
- package/apps/web/src/components/chat/session-sidebar.tsx +222 -0
- package/apps/web/src/components/chat/subagent-activity-sidebar.tsx +248 -0
- package/apps/web/src/components/chat/tool-blocks.tsx +550 -0
- package/apps/web/src/lib/a2a/activity-store.ts +150 -0
- package/apps/web/src/lib/a2a/client.ts +357 -0
- package/apps/web/src/lib/a2a/sse.ts +19 -0
- package/apps/web/src/lib/a2a/task-store.ts +111 -0
- package/apps/web/src/lib/a2a/types.ts +216 -0
- package/apps/web/src/lib/agent/answer-store.ts +109 -0
- package/apps/web/src/lib/agent/background-delivery.ts +343 -0
- package/apps/web/src/lib/agent/background-tool.ts +78 -0
- package/apps/web/src/lib/agent/background.ts +452 -0
- package/apps/web/src/lib/agent/chat.ts +543 -0
- package/apps/web/src/lib/agent/session-store.ts +26 -0
- package/apps/web/src/lib/chat/types.ts +44 -0
- package/apps/web/src/lib/env.ts +31 -0
- package/apps/web/src/lib/hooks/useA2AChat.ts +863 -0
- package/apps/web/src/lib/state/chat-atoms.ts +52 -0
- package/apps/web/src/lib/workspace.ts +9 -0
- package/apps/web/tsconfig.json +35 -0
- package/bin/remotion-agent.js +451 -0
- package/package.json +34 -0
- package/templates/.claude/CLAUDE.md +95 -0
- package/templates/.claude/README.md +129 -0
- package/templates/.claude/agents/composer-agent.md +188 -0
- package/templates/.claude/agents/crafter.md +181 -0
- package/templates/.claude/agents/creator.md +134 -0
- package/templates/.claude/agents/perceiver.md +92 -0
- package/templates/.claude/settings.json +36 -0
- package/templates/.claude/settings.local.json +39 -0
- package/templates/.claude/skills/agent-browser/SKILL.md +349 -0
- package/templates/.claude/skills/agent-browser/references/authentication.md +188 -0
- package/templates/.claude/skills/agent-browser/references/proxy-support.md +175 -0
- package/templates/.claude/skills/agent-browser/references/session-management.md +181 -0
- package/templates/.claude/skills/agent-browser/references/snapshot-refs.md +186 -0
- package/templates/.claude/skills/agent-browser/references/video-recording.md +162 -0
- package/templates/.claude/skills/agent-browser/templates/authenticated-session.sh +91 -0
- package/templates/.claude/skills/agent-browser/templates/capture-workflow.sh +68 -0
- package/templates/.claude/skills/agent-browser/templates/form-automation.sh +64 -0
- package/templates/.claude/skills/algorithmic-art/LICENSE.txt +202 -0
- package/templates/.claude/skills/algorithmic-art/SKILL.md +405 -0
- package/templates/.claude/skills/algorithmic-art/templates/generator_template.js +223 -0
- package/templates/.claude/skills/algorithmic-art/templates/viewer.html +599 -0
- package/templates/.claude/skills/asset-validator/SKILL.md +376 -0
- package/templates/.claude/skills/audio-video-sync/SKILL.md +219 -0
- package/templates/.claude/skills/bgm-manager/SKILL.md +334 -0
- package/templates/.claude/skills/remotion-best-practices/SKILL.md +45 -0
- package/templates/.claude/skills/remotion-best-practices/rules/3d.md +86 -0
- package/templates/.claude/skills/remotion-best-practices/rules/animations.md +29 -0
- package/templates/.claude/skills/remotion-best-practices/rules/assets/charts-bar-chart.tsx +173 -0
- package/templates/.claude/skills/remotion-best-practices/rules/assets/text-animations-typewriter.tsx +100 -0
- package/templates/.claude/skills/remotion-best-practices/rules/assets/text-animations-word-highlight.tsx +108 -0
- package/templates/.claude/skills/remotion-best-practices/rules/assets.md +78 -0
- package/templates/.claude/skills/remotion-best-practices/rules/audio.md +172 -0
- package/templates/.claude/skills/remotion-best-practices/rules/calculate-metadata.md +104 -0
- package/templates/.claude/skills/remotion-best-practices/rules/can-decode.md +75 -0
- package/templates/.claude/skills/remotion-best-practices/rules/charts.md +58 -0
- package/templates/.claude/skills/remotion-best-practices/rules/compositions.md +141 -0
- package/templates/.claude/skills/remotion-best-practices/rules/display-captions.md +126 -0
- package/templates/.claude/skills/remotion-best-practices/rules/extract-frames.md +229 -0
- package/templates/.claude/skills/remotion-best-practices/rules/fonts.md +152 -0
- package/templates/.claude/skills/remotion-best-practices/rules/get-audio-duration.md +58 -0
- package/templates/.claude/skills/remotion-best-practices/rules/get-video-dimensions.md +68 -0
- package/templates/.claude/skills/remotion-best-practices/rules/get-video-duration.md +58 -0
- package/templates/.claude/skills/remotion-best-practices/rules/gifs.md +138 -0
- package/templates/.claude/skills/remotion-best-practices/rules/images.md +130 -0
- package/templates/.claude/skills/remotion-best-practices/rules/import-srt-captions.md +67 -0
- package/templates/.claude/skills/remotion-best-practices/rules/lottie.md +68 -0
- package/templates/.claude/skills/remotion-best-practices/rules/maps.md +403 -0
- package/templates/.claude/skills/remotion-best-practices/rules/measuring-dom-nodes.md +35 -0
- package/templates/.claude/skills/remotion-best-practices/rules/measuring-text.md +143 -0
- package/templates/.claude/skills/remotion-best-practices/rules/parameters.md +98 -0
- package/templates/.claude/skills/remotion-best-practices/rules/sequencing.md +118 -0
- package/templates/.claude/skills/remotion-best-practices/rules/tailwind.md +11 -0
- package/templates/.claude/skills/remotion-best-practices/rules/text-animations.md +20 -0
- package/templates/.claude/skills/remotion-best-practices/rules/timing.md +179 -0
- package/templates/.claude/skills/remotion-best-practices/rules/transcribe-captions.md +19 -0
- package/templates/.claude/skills/remotion-best-practices/rules/transitions.md +122 -0
- package/templates/.claude/skills/remotion-best-practices/rules/trimming.md +53 -0
- package/templates/.claude/skills/remotion-best-practices/rules/videos.md +171 -0
- package/templates/.claude/skills/remotion-components/SKILL.md +453 -0
- package/templates/.claude/skills/render-config/SKILL.md +290 -0
- package/templates/.claude/skills/script-writer/SKILL.md +59 -0
- package/templates/.claude/skills/style-director/script-writer/SKILL.md +82 -0
- package/templates/.claude/skills/style-director/style-director/SKILL.md +287 -0
- package/templates/.claude/skills/style-director/style-director/references/audience-and-scenarios.md +43 -0
- package/templates/.claude/skills/style-director/style-director/references/interaction-innovation.md +26 -0
- package/templates/.claude/skills/style-director/style-director/references/motion-grammar.md +66 -0
- package/templates/.claude/skills/style-director/style-director/references/quality-checklist.md +29 -0
- package/templates/.claude/skills/style-director/style-director/references/scene-recipes.md +38 -0
- package/templates/.claude/skills/style-director/style-director/references/visual-style-system.md +148 -0
- package/templates/.claude/skills/subtitle-composer/SKILL.md +304 -0
- package/templates/.claude/skills/subtitle-processor/SKILL.md +308 -0
- package/templates/.claude/skills/timeline-generator/SKILL.md +253 -0
- package/templates/.claude/skills/video-preflight-check/SKILL.md +353 -0
- package/templates/.claude/skills/voice-synthesizer/SKILL.md +296 -0
- package/templates/.claude/skills/voice-synthesizer/scripts/synthesize_voice.py +315 -0
- package/templates/.claude/skills/voice-synthesizer/scripts/tts_cli.py +142 -0
- package/templates/.claude/skills/web-design-guidelines/SKILL.md +36 -0
- package/templates/.claude/skills/youtube-downloader/SKILL.md +99 -0
- package/templates/.claude/skills/youtube-downloader/scripts/download_video.py +145 -0
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: get-video-dimensions
|
|
3
|
+
description: Getting the width and height of a video file with Mediabunny
|
|
4
|
+
metadata:
|
|
5
|
+
tags: dimensions, width, height, resolution, size, video
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Getting video dimensions with Mediabunny
|
|
9
|
+
|
|
10
|
+
Mediabunny can extract the width and height of a video file. It works in browser, Node.js, and Bun environments.
|
|
11
|
+
|
|
12
|
+
## Getting video dimensions
|
|
13
|
+
|
|
14
|
+
```tsx
|
|
15
|
+
import { Input, ALL_FORMATS, UrlSource } from "mediabunny";
|
|
16
|
+
|
|
17
|
+
export const getVideoDimensions = async (src: string) => {
|
|
18
|
+
const input = new Input({
|
|
19
|
+
formats: ALL_FORMATS,
|
|
20
|
+
source: new UrlSource(src, {
|
|
21
|
+
getRetryDelay: () => null,
|
|
22
|
+
}),
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
const videoTrack = await input.getPrimaryVideoTrack();
|
|
26
|
+
if (!videoTrack) {
|
|
27
|
+
throw new Error("No video track found");
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return {
|
|
31
|
+
width: videoTrack.displayWidth,
|
|
32
|
+
height: videoTrack.displayHeight,
|
|
33
|
+
};
|
|
34
|
+
};
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Usage
|
|
38
|
+
|
|
39
|
+
```tsx
|
|
40
|
+
const dimensions = await getVideoDimensions("https://remotion.media/video.mp4");
|
|
41
|
+
console.log(dimensions.width); // e.g. 1920
|
|
42
|
+
console.log(dimensions.height); // e.g. 1080
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Using with local files
|
|
46
|
+
|
|
47
|
+
For local files, use `FileSource` instead of `UrlSource`:
|
|
48
|
+
|
|
49
|
+
```tsx
|
|
50
|
+
import { Input, ALL_FORMATS, FileSource } from "mediabunny";
|
|
51
|
+
|
|
52
|
+
const input = new Input({
|
|
53
|
+
formats: ALL_FORMATS,
|
|
54
|
+
source: new FileSource(file), // File object from input or drag-drop
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
const videoTrack = await input.getPrimaryVideoTrack();
|
|
58
|
+
const width = videoTrack.displayWidth;
|
|
59
|
+
const height = videoTrack.displayHeight;
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Using with staticFile in Remotion
|
|
63
|
+
|
|
64
|
+
```tsx
|
|
65
|
+
import { staticFile } from "remotion";
|
|
66
|
+
|
|
67
|
+
const dimensions = await getVideoDimensions(staticFile("video.mp4"));
|
|
68
|
+
```
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: get-video-duration
|
|
3
|
+
description: Getting the duration of a video file in seconds with Mediabunny
|
|
4
|
+
metadata:
|
|
5
|
+
tags: duration, video, length, time, seconds
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Getting video duration with Mediabunny
|
|
9
|
+
|
|
10
|
+
Mediabunny can extract the duration of a video file. It works in browser, Node.js, and Bun environments.
|
|
11
|
+
|
|
12
|
+
## Getting video duration
|
|
13
|
+
|
|
14
|
+
```tsx
|
|
15
|
+
import { Input, ALL_FORMATS, UrlSource } from "mediabunny";
|
|
16
|
+
|
|
17
|
+
export const getVideoDuration = async (src: string) => {
|
|
18
|
+
const input = new Input({
|
|
19
|
+
formats: ALL_FORMATS,
|
|
20
|
+
source: new UrlSource(src, {
|
|
21
|
+
getRetryDelay: () => null,
|
|
22
|
+
}),
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
const durationInSeconds = await input.computeDuration();
|
|
26
|
+
return durationInSeconds;
|
|
27
|
+
};
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Usage
|
|
31
|
+
|
|
32
|
+
```tsx
|
|
33
|
+
const duration = await getVideoDuration("https://remotion.media/video.mp4");
|
|
34
|
+
console.log(duration); // e.g. 10.5 (seconds)
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Using with local files
|
|
38
|
+
|
|
39
|
+
For local files, use `FileSource` instead of `UrlSource`:
|
|
40
|
+
|
|
41
|
+
```tsx
|
|
42
|
+
import { Input, ALL_FORMATS, FileSource } from "mediabunny";
|
|
43
|
+
|
|
44
|
+
const input = new Input({
|
|
45
|
+
formats: ALL_FORMATS,
|
|
46
|
+
source: new FileSource(file), // File object from input or drag-drop
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
const durationInSeconds = await input.computeDuration();
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Using with staticFile in Remotion
|
|
53
|
+
|
|
54
|
+
```tsx
|
|
55
|
+
import { staticFile } from "remotion";
|
|
56
|
+
|
|
57
|
+
const duration = await getVideoDuration(staticFile("video.mp4"));
|
|
58
|
+
```
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: gif
|
|
3
|
+
description: Displaying GIFs, APNG, AVIF and WebP in Remotion
|
|
4
|
+
metadata:
|
|
5
|
+
tags: gif, animation, images, animated, apng, avif, webp
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Using Animated images in Remotion
|
|
9
|
+
|
|
10
|
+
## Basic usage
|
|
11
|
+
|
|
12
|
+
Use `<AnimatedImage>` to display a GIF, APNG, AVIF or WebP image synchronized with Remotion's timeline:
|
|
13
|
+
|
|
14
|
+
```tsx
|
|
15
|
+
import {AnimatedImage, staticFile} from 'remotion';
|
|
16
|
+
|
|
17
|
+
export const MyComposition = () => {
|
|
18
|
+
return <AnimatedImage src={staticFile('animation.gif')} width={500} height={500} />;
|
|
19
|
+
};
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Remote URLs are also supported (must have CORS enabled):
|
|
23
|
+
|
|
24
|
+
```tsx
|
|
25
|
+
<AnimatedImage src="https://example.com/animation.gif" width={500} height={500} />
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Sizing and fit
|
|
29
|
+
|
|
30
|
+
Control how the image fills its container with the `fit` prop:
|
|
31
|
+
|
|
32
|
+
```tsx
|
|
33
|
+
// Stretch to fill (default)
|
|
34
|
+
<AnimatedImage src={staticFile("animation.gif")} width={500} height={300} fit="fill" />
|
|
35
|
+
|
|
36
|
+
// Maintain aspect ratio, fit inside container
|
|
37
|
+
<AnimatedImage src={staticFile("animation.gif")} width={500} height={300} fit="contain" />
|
|
38
|
+
|
|
39
|
+
// Fill container, crop if needed
|
|
40
|
+
<AnimatedImage src={staticFile("animation.gif")} width={500} height={300} fit="cover" />
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Playback speed
|
|
44
|
+
|
|
45
|
+
Use `playbackRate` to control the animation speed:
|
|
46
|
+
|
|
47
|
+
```tsx
|
|
48
|
+
<AnimatedImage src={staticFile("animation.gif")} width={500} height={500} playbackRate={2} /> {/* 2x speed */}
|
|
49
|
+
<AnimatedImage src={staticFile("animation.gif")} width={500} height={500} playbackRate={0.5} /> {/* Half speed */}
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Looping behavior
|
|
53
|
+
|
|
54
|
+
Control what happens when the animation finishes:
|
|
55
|
+
|
|
56
|
+
```tsx
|
|
57
|
+
// Loop indefinitely (default)
|
|
58
|
+
<AnimatedImage src={staticFile("animation.gif")} width={500} height={500} loopBehavior="loop" />
|
|
59
|
+
|
|
60
|
+
// Play once, show final frame
|
|
61
|
+
<AnimatedImage src={staticFile("animation.gif")} width={500} height={500} loopBehavior="pause-after-finish" />
|
|
62
|
+
|
|
63
|
+
// Play once, then clear canvas
|
|
64
|
+
<AnimatedImage src={staticFile("animation.gif")} width={500} height={500} loopBehavior="clear-after-finish" />
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Styling
|
|
68
|
+
|
|
69
|
+
Use the `style` prop for additional CSS (use `width` and `height` props for sizing):
|
|
70
|
+
|
|
71
|
+
```tsx
|
|
72
|
+
<AnimatedImage
|
|
73
|
+
src={staticFile('animation.gif')}
|
|
74
|
+
width={500}
|
|
75
|
+
height={500}
|
|
76
|
+
style={{
|
|
77
|
+
borderRadius: 20,
|
|
78
|
+
position: 'absolute',
|
|
79
|
+
top: 100,
|
|
80
|
+
left: 50,
|
|
81
|
+
}}
|
|
82
|
+
/>
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## Getting GIF duration
|
|
86
|
+
|
|
87
|
+
Use `getGifDurationInSeconds()` from `@remotion/gif` to get the duration of a GIF.
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
npx remotion add @remotion/gif # If project uses npm
|
|
91
|
+
bunx remotion add @remotion/gif # If project uses bun
|
|
92
|
+
yarn remotion add @remotion/gif # If project uses yarn
|
|
93
|
+
pnpm exec remotion add @remotion/gif # If project uses pnpm
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
```tsx
|
|
97
|
+
import {getGifDurationInSeconds} from '@remotion/gif';
|
|
98
|
+
import {staticFile} from 'remotion';
|
|
99
|
+
|
|
100
|
+
const duration = await getGifDurationInSeconds(staticFile('animation.gif'));
|
|
101
|
+
console.log(duration); // e.g. 2.5
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
This is useful for setting the composition duration to match the GIF:
|
|
105
|
+
|
|
106
|
+
```tsx
|
|
107
|
+
import {getGifDurationInSeconds} from '@remotion/gif';
|
|
108
|
+
import {staticFile, CalculateMetadataFunction} from 'remotion';
|
|
109
|
+
|
|
110
|
+
const calculateMetadata: CalculateMetadataFunction = async () => {
|
|
111
|
+
const duration = await getGifDurationInSeconds(staticFile('animation.gif'));
|
|
112
|
+
return {
|
|
113
|
+
durationInFrames: Math.ceil(duration * 30),
|
|
114
|
+
};
|
|
115
|
+
};
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
## Alternative
|
|
119
|
+
|
|
120
|
+
If `<AnimatedImage>` does not work (only supported in Chrome and Firefox), you can use `<Gif>` from `@remotion/gif` instead.
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
npx remotion add @remotion/gif # If project uses npm
|
|
124
|
+
bunx remotion add @remotion/gif # If project uses bun
|
|
125
|
+
yarn remotion add @remotion/gif # If project uses yarn
|
|
126
|
+
pnpm exec remotion add @remotion/gif # If project uses pnpm
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
```tsx
|
|
130
|
+
import {Gif} from '@remotion/gif';
|
|
131
|
+
import {staticFile} from 'remotion';
|
|
132
|
+
|
|
133
|
+
export const MyComposition = () => {
|
|
134
|
+
return <Gif src={staticFile('animation.gif')} width={500} height={500} />;
|
|
135
|
+
};
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
The `<Gif>` component has the same props as `<AnimatedImage>` but only supports GIF files.
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: images
|
|
3
|
+
description: Embedding images in Remotion using the <Img> component
|
|
4
|
+
metadata:
|
|
5
|
+
tags: images, img, staticFile, png, jpg, svg, webp
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Using images in Remotion
|
|
9
|
+
|
|
10
|
+
## The `<Img>` component
|
|
11
|
+
|
|
12
|
+
Always use the `<Img>` component from `remotion` to display images:
|
|
13
|
+
|
|
14
|
+
```tsx
|
|
15
|
+
import { Img, staticFile } from "remotion";
|
|
16
|
+
|
|
17
|
+
export const MyComposition = () => {
|
|
18
|
+
return <Img src={staticFile("photo.png")} />;
|
|
19
|
+
};
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Important restrictions
|
|
23
|
+
|
|
24
|
+
**You MUST use the `<Img>` component from `remotion`.** Do not use:
|
|
25
|
+
|
|
26
|
+
- Native HTML `<img>` elements
|
|
27
|
+
- Next.js `<Image>` component
|
|
28
|
+
- CSS `background-image`
|
|
29
|
+
|
|
30
|
+
The `<Img>` component ensures images are fully loaded before rendering, preventing flickering and blank frames during video export.
|
|
31
|
+
|
|
32
|
+
## Local images with staticFile()
|
|
33
|
+
|
|
34
|
+
Place images in the `public/` folder and use `staticFile()` to reference them:
|
|
35
|
+
|
|
36
|
+
```
|
|
37
|
+
my-video/
|
|
38
|
+
├─ public/
|
|
39
|
+
│ ├─ logo.png
|
|
40
|
+
│ ├─ avatar.jpg
|
|
41
|
+
│ └─ icon.svg
|
|
42
|
+
├─ src/
|
|
43
|
+
├─ package.json
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
```tsx
|
|
47
|
+
import { Img, staticFile } from "remotion";
|
|
48
|
+
|
|
49
|
+
<Img src={staticFile("logo.png")} />
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Remote images
|
|
53
|
+
|
|
54
|
+
Remote URLs can be used directly without `staticFile()`:
|
|
55
|
+
|
|
56
|
+
```tsx
|
|
57
|
+
<Img src="https://example.com/image.png" />
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Ensure remote images have CORS enabled.
|
|
61
|
+
|
|
62
|
+
For animated GIFs, use the `<Gif>` component from `@remotion/gif` instead.
|
|
63
|
+
|
|
64
|
+
## Sizing and positioning
|
|
65
|
+
|
|
66
|
+
Use the `style` prop to control size and position:
|
|
67
|
+
|
|
68
|
+
```tsx
|
|
69
|
+
<Img
|
|
70
|
+
src={staticFile("photo.png")}
|
|
71
|
+
style={{
|
|
72
|
+
width: 500,
|
|
73
|
+
height: 300,
|
|
74
|
+
position: "absolute",
|
|
75
|
+
top: 100,
|
|
76
|
+
left: 50,
|
|
77
|
+
objectFit: "cover",
|
|
78
|
+
}}
|
|
79
|
+
/>
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Dynamic image paths
|
|
83
|
+
|
|
84
|
+
Use template literals for dynamic file references:
|
|
85
|
+
|
|
86
|
+
```tsx
|
|
87
|
+
import { Img, staticFile, useCurrentFrame } from "remotion";
|
|
88
|
+
|
|
89
|
+
const frame = useCurrentFrame();
|
|
90
|
+
|
|
91
|
+
// Image sequence
|
|
92
|
+
<Img src={staticFile(`frames/frame${frame}.png`)} />
|
|
93
|
+
|
|
94
|
+
// Selecting based on props
|
|
95
|
+
<Img src={staticFile(`avatars/${props.userId}.png`)} />
|
|
96
|
+
|
|
97
|
+
// Conditional images
|
|
98
|
+
<Img src={staticFile(`icons/${isActive ? "active" : "inactive"}.svg`)} />
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
This pattern is useful for:
|
|
102
|
+
|
|
103
|
+
- Image sequences (frame-by-frame animations)
|
|
104
|
+
- User-specific avatars or profile images
|
|
105
|
+
- Theme-based icons
|
|
106
|
+
- State-dependent graphics
|
|
107
|
+
|
|
108
|
+
## Getting image dimensions
|
|
109
|
+
|
|
110
|
+
Use `getImageDimensions()` to get the dimensions of an image:
|
|
111
|
+
|
|
112
|
+
```tsx
|
|
113
|
+
import { getImageDimensions, staticFile } from "remotion";
|
|
114
|
+
|
|
115
|
+
const { width, height } = await getImageDimensions(staticFile("photo.png"));
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
This is useful for calculating aspect ratios or sizing compositions:
|
|
119
|
+
|
|
120
|
+
```tsx
|
|
121
|
+
import { getImageDimensions, staticFile, CalculateMetadataFunction } from "remotion";
|
|
122
|
+
|
|
123
|
+
const calculateMetadata: CalculateMetadataFunction = async () => {
|
|
124
|
+
const { width, height } = await getImageDimensions(staticFile("photo.png"));
|
|
125
|
+
return {
|
|
126
|
+
width,
|
|
127
|
+
height,
|
|
128
|
+
};
|
|
129
|
+
};
|
|
130
|
+
```
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: import-srt-captions
|
|
3
|
+
description: Importing .srt subtitle files into Remotion using @remotion/captions
|
|
4
|
+
metadata:
|
|
5
|
+
tags: captions, subtitles, srt, import, parse
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Importing .srt subtitles into Remotion
|
|
9
|
+
|
|
10
|
+
If you have an existing `.srt` subtitle file, you can import it into Remotion using `parseSrt()` from `@remotion/captions`.
|
|
11
|
+
|
|
12
|
+
## Prerequisites
|
|
13
|
+
|
|
14
|
+
First, the @remotion/captions package needs to be installed.
|
|
15
|
+
If it is not installed, use the following command:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npx remotion add @remotion/captions # If project uses npm
|
|
19
|
+
bunx remotion add @remotion/captions # If project uses bun
|
|
20
|
+
yarn remotion add @remotion/captions # If project uses yarn
|
|
21
|
+
pnpm exec remotion add @remotion/captions # If project uses pnpm
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Reading an .srt file
|
|
25
|
+
|
|
26
|
+
Use `staticFile()` to reference an `.srt` file in your `public` folder, then fetch and parse it:
|
|
27
|
+
|
|
28
|
+
```tsx
|
|
29
|
+
import {useState, useEffect, useCallback} from 'react';
|
|
30
|
+
import {AbsoluteFill, staticFile, useDelayRender} from 'remotion';
|
|
31
|
+
import {parseSrt} from '@remotion/captions';
|
|
32
|
+
import type {Caption} from '@remotion/captions';
|
|
33
|
+
|
|
34
|
+
export const MyComponent: React.FC = () => {
|
|
35
|
+
const [captions, setCaptions] = useState<Caption[] | null>(null);
|
|
36
|
+
const {delayRender, continueRender, cancelRender} = useDelayRender();
|
|
37
|
+
const [handle] = useState(() => delayRender());
|
|
38
|
+
|
|
39
|
+
const fetchCaptions = useCallback(async () => {
|
|
40
|
+
try {
|
|
41
|
+
const response = await fetch(staticFile('subtitles.srt'));
|
|
42
|
+
const text = await response.text();
|
|
43
|
+
const {captions: parsed} = parseSrt({input: text});
|
|
44
|
+
setCaptions(parsed);
|
|
45
|
+
continueRender(handle);
|
|
46
|
+
} catch (e) {
|
|
47
|
+
cancelRender(e);
|
|
48
|
+
}
|
|
49
|
+
}, [continueRender, cancelRender, handle]);
|
|
50
|
+
|
|
51
|
+
useEffect(() => {
|
|
52
|
+
fetchCaptions();
|
|
53
|
+
}, [fetchCaptions]);
|
|
54
|
+
|
|
55
|
+
if (!captions) {
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return <AbsoluteFill>{/* Use captions here */}</AbsoluteFill>;
|
|
60
|
+
};
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Remote URLs are also supported - you can `fetch()` a remote file via URL instead of using `staticFile()`.
|
|
64
|
+
|
|
65
|
+
## Using imported captions
|
|
66
|
+
|
|
67
|
+
Once parsed, the captions are in the `Caption` format and can be used with all `@remotion/captions` utilities.
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: lottie
|
|
3
|
+
description: Embedding Lottie animations in Remotion.
|
|
4
|
+
metadata:
|
|
5
|
+
category: Animation
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Using Lottie Animations in Remotion
|
|
9
|
+
|
|
10
|
+
## Prerequisites
|
|
11
|
+
|
|
12
|
+
First, the @remotion/lottie package needs to be installed.
|
|
13
|
+
If it is not, use the following command:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npx remotion add @remotion/lottie # If project uses npm
|
|
17
|
+
bunx remotion add @remotion/lottie # If project uses bun
|
|
18
|
+
yarn remotion add @remotion/lottie # If project uses yarn
|
|
19
|
+
pnpm exec remotion add @remotion/lottie # If project uses pnpm
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Displaying a Lottie file
|
|
23
|
+
|
|
24
|
+
To import a Lottie animation:
|
|
25
|
+
|
|
26
|
+
- Fetch the Lottie asset
|
|
27
|
+
- Wrap the loading process in `delayRender()` and `continueRender()`
|
|
28
|
+
- Save the animation data in a state
|
|
29
|
+
- Render the Lottie animation using the `Lottie` component from the `@remotion/lottie` package
|
|
30
|
+
|
|
31
|
+
```tsx
|
|
32
|
+
import {Lottie, LottieAnimationData} from '@remotion/lottie';
|
|
33
|
+
import {useEffect, useState} from 'react';
|
|
34
|
+
import {cancelRender, continueRender, delayRender} from 'remotion';
|
|
35
|
+
|
|
36
|
+
export const MyAnimation = () => {
|
|
37
|
+
const [handle] = useState(() => delayRender('Loading Lottie animation'));
|
|
38
|
+
|
|
39
|
+
const [animationData, setAnimationData] = useState<LottieAnimationData | null>(null);
|
|
40
|
+
|
|
41
|
+
useEffect(() => {
|
|
42
|
+
fetch('https://assets4.lottiefiles.com/packages/lf20_zyquagfl.json')
|
|
43
|
+
.then((data) => data.json())
|
|
44
|
+
.then((json) => {
|
|
45
|
+
setAnimationData(json);
|
|
46
|
+
continueRender(handle);
|
|
47
|
+
})
|
|
48
|
+
.catch((err) => {
|
|
49
|
+
cancelRender(err);
|
|
50
|
+
});
|
|
51
|
+
}, [handle]);
|
|
52
|
+
|
|
53
|
+
if (!animationData) {
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return <Lottie animationData={animationData} />;
|
|
58
|
+
};
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Styling and animating
|
|
62
|
+
|
|
63
|
+
Lottie supports the `style` prop to allow styles and animations:
|
|
64
|
+
|
|
65
|
+
```tsx
|
|
66
|
+
return <Lottie animationData={animationData} style={{width: 400, height: 400}} />;
|
|
67
|
+
```
|
|
68
|
+
|