@editframe/create 0.44.0 → 0.45.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/dist/index.js +16 -28
- package/dist/index.js.map +1 -1
- package/dist/skills/editframe-brand-video-generator/README.md +155 -0
- package/dist/skills/editframe-brand-video-generator/SKILL.md +207 -0
- package/dist/skills/editframe-brand-video-generator/references/brand-examples.md +178 -0
- package/dist/skills/editframe-brand-video-generator/references/color-psychology.md +227 -0
- package/dist/skills/editframe-brand-video-generator/references/composition-patterns.md +383 -0
- package/dist/skills/editframe-brand-video-generator/references/editing.md +66 -0
- package/dist/skills/editframe-brand-video-generator/references/emotional-arcs.md +496 -0
- package/dist/skills/editframe-brand-video-generator/references/genre-selection.md +135 -0
- package/dist/skills/editframe-brand-video-generator/references/transition-styles.md +611 -0
- package/dist/skills/editframe-brand-video-generator/references/typography-personalities.md +326 -0
- package/dist/skills/editframe-brand-video-generator/references/video-archetypes.md +86 -0
- package/dist/skills/editframe-brand-video-generator/references/video-fundamentals.md +169 -0
- package/dist/skills/editframe-brand-video-generator/references/visual-metaphors.md +50 -0
- package/dist/skills/editframe-composition/SKILL.md +169 -0
- package/dist/skills/editframe-composition/references/audio.md +483 -0
- package/dist/skills/editframe-composition/references/captions.md +844 -0
- package/dist/skills/editframe-composition/references/composition-model.md +73 -0
- package/dist/skills/editframe-composition/references/configuration.md +403 -0
- package/dist/skills/editframe-composition/references/css-parts.md +105 -0
- package/dist/skills/editframe-composition/references/css-variables.md +640 -0
- package/dist/skills/editframe-composition/references/entry-points.md +810 -0
- package/dist/skills/editframe-composition/references/events.md +499 -0
- package/dist/skills/editframe-composition/references/getting-started.md +259 -0
- package/dist/skills/editframe-composition/references/hooks.md +234 -0
- package/dist/skills/editframe-composition/references/image.md +241 -0
- package/dist/skills/editframe-composition/references/r3f.md +580 -0
- package/dist/skills/editframe-composition/references/render-api.md +484 -0
- package/dist/skills/editframe-composition/references/render-strategies.md +119 -0
- package/dist/skills/editframe-composition/references/render-to-video.md +1101 -0
- package/dist/skills/editframe-composition/references/scripting.md +606 -0
- package/dist/skills/editframe-composition/references/sequencing.md +116 -0
- package/dist/skills/editframe-composition/references/server-rendering.md +753 -0
- package/dist/skills/editframe-composition/references/surface.md +329 -0
- package/dist/skills/editframe-composition/references/text.md +627 -0
- package/dist/skills/editframe-composition/references/time-model.md +99 -0
- package/dist/skills/editframe-composition/references/timegroup-modes.md +102 -0
- package/dist/skills/editframe-composition/references/timegroup.md +457 -0
- package/dist/skills/editframe-composition/references/timeline-root.md +398 -0
- package/dist/skills/editframe-composition/references/transcription.md +47 -0
- package/dist/skills/editframe-composition/references/transitions.md +608 -0
- package/dist/skills/editframe-composition/references/use-media-info.md +357 -0
- package/dist/skills/editframe-composition/references/video.md +506 -0
- package/dist/skills/editframe-composition/references/waveform.md +327 -0
- package/dist/skills/editframe-editor-gui/SKILL.md +152 -0
- package/dist/skills/editframe-editor-gui/references/active-root-temporal.md +657 -0
- package/dist/skills/editframe-editor-gui/references/canvas.md +947 -0
- package/dist/skills/editframe-editor-gui/references/controls.md +366 -0
- package/dist/skills/editframe-editor-gui/references/dial.md +756 -0
- package/dist/skills/editframe-editor-gui/references/editor-toolkit.md +587 -0
- package/dist/skills/editframe-editor-gui/references/filmstrip.md +460 -0
- package/dist/skills/editframe-editor-gui/references/fit-scale.md +772 -0
- package/dist/skills/editframe-editor-gui/references/focus-overlay.md +561 -0
- package/dist/skills/editframe-editor-gui/references/hierarchy.md +544 -0
- package/dist/skills/editframe-editor-gui/references/overlay-item.md +634 -0
- package/dist/skills/editframe-editor-gui/references/overlay-layer.md +429 -0
- package/dist/skills/editframe-editor-gui/references/pan-zoom.md +568 -0
- package/dist/skills/editframe-editor-gui/references/pause.md +397 -0
- package/dist/skills/editframe-editor-gui/references/play.md +370 -0
- package/dist/skills/editframe-editor-gui/references/preview.md +391 -0
- package/dist/skills/editframe-editor-gui/references/resizable-box.md +749 -0
- package/dist/skills/editframe-editor-gui/references/scrubber.md +588 -0
- package/dist/skills/editframe-editor-gui/references/thumbnail-strip.md +566 -0
- package/dist/skills/editframe-editor-gui/references/time-display.md +492 -0
- package/dist/skills/editframe-editor-gui/references/timeline-ruler.md +489 -0
- package/dist/skills/editframe-editor-gui/references/timeline.md +604 -0
- package/dist/skills/editframe-editor-gui/references/toggle-loop.md +618 -0
- package/dist/skills/editframe-editor-gui/references/toggle-play.md +526 -0
- package/dist/skills/editframe-editor-gui/references/transform-handles.md +924 -0
- package/dist/skills/editframe-editor-gui/references/trim-handles.md +725 -0
- package/dist/skills/editframe-editor-gui/references/workbench.md +453 -0
- package/dist/skills/editframe-motion-design/SKILL.md +101 -0
- package/dist/skills/editframe-motion-design/references/0-editframe.md +299 -0
- package/dist/skills/editframe-motion-design/references/1-intent.md +201 -0
- package/dist/skills/editframe-motion-design/references/2-physics-model.md +405 -0
- package/dist/skills/editframe-motion-design/references/3-attention.md +350 -0
- package/dist/skills/editframe-motion-design/references/4-process.md +418 -0
- package/dist/skills/editframe-vite-plugin/SKILL.md +75 -0
- package/dist/skills/editframe-vite-plugin/references/file-api.md +111 -0
- package/dist/skills/editframe-vite-plugin/references/getting-started.md +96 -0
- package/dist/skills/editframe-vite-plugin/references/jit-transcoding.md +91 -0
- package/dist/skills/editframe-vite-plugin/references/local-assets.md +75 -0
- package/dist/skills/editframe-vite-plugin/references/visual-testing.md +136 -0
- package/dist/skills/editframe-webhooks/SKILL.md +126 -0
- package/dist/skills/editframe-webhooks/references/events.md +382 -0
- package/dist/skills/editframe-webhooks/references/getting-started.md +232 -0
- package/dist/skills/editframe-webhooks/references/security.md +418 -0
- package/dist/skills/editframe-webhooks/references/testing.md +409 -0
- package/dist/skills/editframe-webhooks/references/troubleshooting.md +457 -0
- package/dist/templates/html/AGENTS.md +13 -0
- package/dist/templates/react/AGENTS.md +13 -0
- package/dist/utils.js +15 -16
- package/dist/utils.js.map +1 -1
- package/package.json +1 -1
- package/tsdown.config.ts +4 -0
- package/dist/detectAgent.js +0 -89
- package/dist/detectAgent.js.map +0 -1
|
@@ -0,0 +1,566 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Thumbnail Strip Element
|
|
3
|
+
description: Video thumbnail strip that generates and displays preview frames at regular intervals along the composition timeline.
|
|
4
|
+
type: reference
|
|
5
|
+
nav:
|
|
6
|
+
parent: "Timeline"
|
|
7
|
+
priority: 21
|
|
8
|
+
api:
|
|
9
|
+
attributes:
|
|
10
|
+
- name: target
|
|
11
|
+
type: string
|
|
12
|
+
required: true
|
|
13
|
+
description: ID of target video or root timegroup element
|
|
14
|
+
- name: targetElement
|
|
15
|
+
type: Element
|
|
16
|
+
description: Direct reference to target element (alternative to target)
|
|
17
|
+
- name: thumbnail-height
|
|
18
|
+
type: number
|
|
19
|
+
default: 24
|
|
20
|
+
description: Height of thumbnails in pixels
|
|
21
|
+
- name: thumbnail-spacing-px
|
|
22
|
+
type: number
|
|
23
|
+
default: 48
|
|
24
|
+
description: Spacing between thumbnail centers in pixels
|
|
25
|
+
- name: pixels-per-ms
|
|
26
|
+
type: number
|
|
27
|
+
description: Zoom level (overrides timeline context)
|
|
28
|
+
- name: use-intrinsic-duration
|
|
29
|
+
type: boolean
|
|
30
|
+
default: false
|
|
31
|
+
description: Use source duration instead of trimmed duration
|
|
32
|
+
react:
|
|
33
|
+
generate: true
|
|
34
|
+
componentName: ThumbnailStrip
|
|
35
|
+
importPath: "@editframe/react"
|
|
36
|
+
propMapping:
|
|
37
|
+
thumbnail-height: thumbnailHeight
|
|
38
|
+
thumbnail-spacing-px: thumbnailSpacingPx
|
|
39
|
+
pixels-per-ms: pixelsPerMs
|
|
40
|
+
use-intrinsic-duration: useIntrinsicDuration
|
|
41
|
+
additionalProps:
|
|
42
|
+
- name: className
|
|
43
|
+
type: string
|
|
44
|
+
description: CSS classes for styling
|
|
45
|
+
nav:
|
|
46
|
+
parent: "Tools"
|
|
47
|
+
priority: 46
|
|
48
|
+
related: ["timeline", "filmstrip", "video"]
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
<!-- html-only -->
|
|
52
|
+
# ef-thumbnail-strip
|
|
53
|
+
<!-- /html-only -->
|
|
54
|
+
<!-- react-only -->
|
|
55
|
+
# ThumbnailStrip
|
|
56
|
+
<!-- /react-only -->
|
|
57
|
+
|
|
58
|
+
Visual thumbnail strip showing preview frames from video or timegroup elements. Automatically generates and displays thumbnails at regular intervals along the timeline.
|
|
59
|
+
|
|
60
|
+
<!-- react-only -->
|
|
61
|
+
## Import
|
|
62
|
+
|
|
63
|
+
```tsx
|
|
64
|
+
import { ThumbnailStrip } from "@editframe/react";
|
|
65
|
+
```
|
|
66
|
+
<!-- /react-only -->
|
|
67
|
+
|
|
68
|
+
## Basic Usage
|
|
69
|
+
|
|
70
|
+
<!-- html-only -->
|
|
71
|
+
Thumbnail strip for a video element.
|
|
72
|
+
|
|
73
|
+
```html live
|
|
74
|
+
<ef-timegroup mode="contain" class="w-[720px] h-[480px] bg-black" id="thumb-demo">
|
|
75
|
+
<ef-video src="https://assets.editframe.com/bars-n-tone.mp4" class="size-full object-contain"></ef-video>
|
|
76
|
+
</ef-timegroup>
|
|
77
|
+
<div class="mt-4 h-[48px] bg-gray-900 rounded-lg overflow-auto">
|
|
78
|
+
<ef-thumbnail-strip target="thumb-demo" thumbnail-height="48"></ef-thumbnail-strip>
|
|
79
|
+
</div>
|
|
80
|
+
<div class="mt-2 flex gap-2">
|
|
81
|
+
<ef-controls target="thumb-demo">
|
|
82
|
+
<ef-toggle-play class="px-3 py-1 bg-blue-600 text-white rounded"></ef-toggle-play>
|
|
83
|
+
</ef-controls>
|
|
84
|
+
</div>
|
|
85
|
+
```
|
|
86
|
+
<!-- /html-only -->
|
|
87
|
+
<!-- react-only -->
|
|
88
|
+
```tsx
|
|
89
|
+
import { ThumbnailStrip, Video } from "@editframe/react";
|
|
90
|
+
|
|
91
|
+
<div className="h-12 bg-gray-900 relative">
|
|
92
|
+
<ThumbnailStrip target="video-1" />
|
|
93
|
+
</div>
|
|
94
|
+
|
|
95
|
+
<Video id="video-1" src="/video.mp4" className="size-full" />
|
|
96
|
+
```
|
|
97
|
+
<!-- /react-only -->
|
|
98
|
+
|
|
99
|
+
## Adjustable Thumbnail Size
|
|
100
|
+
|
|
101
|
+
Control thumbnail height while maintaining aspect ratio.
|
|
102
|
+
|
|
103
|
+
<!-- html-only -->
|
|
104
|
+
```html live
|
|
105
|
+
<ef-timegroup mode="contain" class="w-[720px] h-[480px] bg-black" id="size-demo">
|
|
106
|
+
<ef-video src="https://assets.editframe.com/bars-n-tone.mp4" class="size-full object-contain"></ef-video>
|
|
107
|
+
</ef-timegroup>
|
|
108
|
+
<div class="mt-4 space-y-2">
|
|
109
|
+
<div class="text-white text-sm">24px height:</div>
|
|
110
|
+
<div class="h-[24px] bg-gray-900 rounded-lg overflow-auto">
|
|
111
|
+
<ef-thumbnail-strip target="size-demo" thumbnail-height="24"></ef-thumbnail-strip>
|
|
112
|
+
</div>
|
|
113
|
+
<div class="text-white text-sm mt-4">48px height:</div>
|
|
114
|
+
<div class="h-[48px] bg-gray-900 rounded-lg overflow-auto">
|
|
115
|
+
<ef-thumbnail-strip target="size-demo" thumbnail-height="48"></ef-thumbnail-strip>
|
|
116
|
+
</div>
|
|
117
|
+
</div>
|
|
118
|
+
```
|
|
119
|
+
<!-- /html-only -->
|
|
120
|
+
<!-- react-only -->
|
|
121
|
+
```tsx
|
|
122
|
+
<ThumbnailStrip
|
|
123
|
+
target="video-1"
|
|
124
|
+
thumbnailHeight={64}
|
|
125
|
+
thumbnailSpacingPx={80}
|
|
126
|
+
className="h-16"
|
|
127
|
+
/>
|
|
128
|
+
```
|
|
129
|
+
<!-- /react-only -->
|
|
130
|
+
|
|
131
|
+
## Thumbnail Spacing
|
|
132
|
+
|
|
133
|
+
Control spacing between thumbnails.
|
|
134
|
+
|
|
135
|
+
<!-- html-only -->
|
|
136
|
+
```html live
|
|
137
|
+
<ef-timegroup mode="contain" class="w-[720px] h-[480px] bg-black" id="spacing-demo">
|
|
138
|
+
<ef-video src="https://assets.editframe.com/bars-n-tone.mp4" class="size-full object-contain"></ef-video>
|
|
139
|
+
</ef-timegroup>
|
|
140
|
+
<div class="mt-4 space-y-2">
|
|
141
|
+
<div class="text-white text-sm">Dense spacing (24px):</div>
|
|
142
|
+
<div class="h-[48px] bg-gray-900 rounded-lg overflow-auto">
|
|
143
|
+
<ef-thumbnail-strip
|
|
144
|
+
target="spacing-demo"
|
|
145
|
+
thumbnail-height="48"
|
|
146
|
+
thumbnail-spacing-px="24"
|
|
147
|
+
></ef-thumbnail-strip>
|
|
148
|
+
</div>
|
|
149
|
+
<div class="text-white text-sm mt-4">Wide spacing (96px):</div>
|
|
150
|
+
<div class="h-[48px] bg-gray-900 rounded-lg overflow-auto">
|
|
151
|
+
<ef-thumbnail-strip
|
|
152
|
+
target="spacing-demo"
|
|
153
|
+
thumbnail-height="48"
|
|
154
|
+
thumbnail-spacing-px="96"
|
|
155
|
+
></ef-thumbnail-strip>
|
|
156
|
+
</div>
|
|
157
|
+
</div>
|
|
158
|
+
```
|
|
159
|
+
<!-- /html-only -->
|
|
160
|
+
|
|
161
|
+
## Timeline Integration
|
|
162
|
+
|
|
163
|
+
<!-- html-only -->
|
|
164
|
+
Thumbnails automatically integrate with timeline zoom and scroll.
|
|
165
|
+
|
|
166
|
+
```html live
|
|
167
|
+
<ef-timegroup mode="contain" class="w-[720px] h-[480px] bg-black" id="timeline-thumbs">
|
|
168
|
+
<ef-video src="https://assets.editframe.com/bars-n-tone.mp4" class="size-full object-contain"></ef-video>
|
|
169
|
+
</ef-timegroup>
|
|
170
|
+
<div class="mt-4 h-[350px] bg-gray-900 rounded-lg overflow-hidden">
|
|
171
|
+
<ef-timeline target="timeline-thumbs"></ef-timeline>
|
|
172
|
+
</div>
|
|
173
|
+
<div class="mt-2 text-white text-sm">
|
|
174
|
+
Thumbnails automatically appear in video tracks. Zoom in to see more detail.
|
|
175
|
+
</div>
|
|
176
|
+
```
|
|
177
|
+
<!-- /html-only -->
|
|
178
|
+
<!-- react-only -->
|
|
179
|
+
ThumbnailStrip is typically used inside Timeline:
|
|
180
|
+
|
|
181
|
+
```tsx
|
|
182
|
+
import { Timeline, Timegroup, Video } from "@editframe/react";
|
|
183
|
+
|
|
184
|
+
<Timeline className="w-full h-96" />
|
|
185
|
+
|
|
186
|
+
<Timegroup mode="sequence" className="w-[1920px] h-[1080px]">
|
|
187
|
+
<Video src="/video.mp4" />
|
|
188
|
+
</Timegroup>
|
|
189
|
+
```
|
|
190
|
+
<!-- /react-only -->
|
|
191
|
+
|
|
192
|
+
<!-- html-only -->
|
|
193
|
+
## Timegroup Thumbnails
|
|
194
|
+
|
|
195
|
+
Generate thumbnails from entire compositions, not just video.
|
|
196
|
+
|
|
197
|
+
```html live
|
|
198
|
+
<ef-timegroup mode="sequence" class="w-[720px] h-[480px] bg-black" id="comp-thumbs">
|
|
199
|
+
<ef-timegroup class="flex items-center justify-center">
|
|
200
|
+
<ef-video src="https://assets.editframe.com/bars-n-tone.mp4" sourcein="0s" sourceout="2s" class="absolute inset-0 size-full object-contain"></ef-video>
|
|
201
|
+
<h1 class="text-white text-6xl font-bold bg-blue-600 p-6 rounded relative">One</h1>
|
|
202
|
+
</ef-timegroup>
|
|
203
|
+
<ef-timegroup class="flex items-center justify-center">
|
|
204
|
+
<ef-video src="https://assets.editframe.com/bars-n-tone.mp4" sourcein="5s" sourceout="7s" class="absolute inset-0 size-full object-contain"></ef-video>
|
|
205
|
+
<h1 class="text-white text-6xl font-bold bg-purple-600 p-6 rounded relative">Two</h1>
|
|
206
|
+
</ef-timegroup>
|
|
207
|
+
</ef-timegroup>
|
|
208
|
+
<div class="mt-4 h-[60px] bg-gray-900 rounded-lg overflow-auto">
|
|
209
|
+
<ef-thumbnail-strip target="comp-thumbs" thumbnail-height="60"></ef-thumbnail-strip>
|
|
210
|
+
</div>
|
|
211
|
+
```
|
|
212
|
+
<!-- /html-only -->
|
|
213
|
+
<!-- react-only -->
|
|
214
|
+
## Target Video Element
|
|
215
|
+
|
|
216
|
+
Generate thumbnails for a specific video:
|
|
217
|
+
|
|
218
|
+
```tsx
|
|
219
|
+
import { ThumbnailStrip, Video } from "@editframe/react";
|
|
220
|
+
|
|
221
|
+
<div className="space-y-2">
|
|
222
|
+
<div className="h-16 bg-gray-900 rounded">
|
|
223
|
+
<ThumbnailStrip
|
|
224
|
+
target="main-video"
|
|
225
|
+
thumbnailHeight={48}
|
|
226
|
+
thumbnailSpacingPx={64}
|
|
227
|
+
/>
|
|
228
|
+
</div>
|
|
229
|
+
|
|
230
|
+
<Video
|
|
231
|
+
id="main-video"
|
|
232
|
+
src="/video.mp4"
|
|
233
|
+
className="w-full aspect-video"
|
|
234
|
+
/>
|
|
235
|
+
</div>
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
## Target Timegroup
|
|
239
|
+
|
|
240
|
+
Generate thumbnails for a composition:
|
|
241
|
+
|
|
242
|
+
```tsx
|
|
243
|
+
import { ThumbnailStrip, Timegroup, Video, Text } from "@editframe/react";
|
|
244
|
+
|
|
245
|
+
<div className="h-12 bg-gray-900">
|
|
246
|
+
<ThumbnailStrip target="composition" />
|
|
247
|
+
</div>
|
|
248
|
+
|
|
249
|
+
<Timegroup id="composition" mode="contain" className="w-[1920px] h-[1080px]">
|
|
250
|
+
<Video src="/background.mp4" className="size-full" />
|
|
251
|
+
<Text className="absolute top-20 left-20 text-6xl text-white">
|
|
252
|
+
Title
|
|
253
|
+
</Text>
|
|
254
|
+
</Timegroup>
|
|
255
|
+
```
|
|
256
|
+
<!-- /react-only -->
|
|
257
|
+
|
|
258
|
+
## Custom Zoom
|
|
259
|
+
|
|
260
|
+
Control thumbnail density:
|
|
261
|
+
|
|
262
|
+
<!-- html-only -->
|
|
263
|
+
For standalone use, provide explicit `pixels-per-ms` attribute.
|
|
264
|
+
<!-- /html-only -->
|
|
265
|
+
<!-- react-only -->
|
|
266
|
+
```tsx
|
|
267
|
+
import { useState } from "react";
|
|
268
|
+
import { ThumbnailStrip, Video } from "@editframe/react";
|
|
269
|
+
|
|
270
|
+
export const ZoomableThumbnails = () => {
|
|
271
|
+
const [zoom, setZoom] = useState(0.04);
|
|
272
|
+
|
|
273
|
+
return (
|
|
274
|
+
<div>
|
|
275
|
+
<input
|
|
276
|
+
type="range"
|
|
277
|
+
min="0.01"
|
|
278
|
+
max="0.2"
|
|
279
|
+
step="0.01"
|
|
280
|
+
value={zoom}
|
|
281
|
+
onChange={(e) => setZoom(parseFloat(e.target.value))}
|
|
282
|
+
className="w-full mb-2"
|
|
283
|
+
/>
|
|
284
|
+
|
|
285
|
+
<div className="h-12 bg-gray-900">
|
|
286
|
+
<ThumbnailStrip
|
|
287
|
+
target="video-1"
|
|
288
|
+
pixelsPerMs={zoom}
|
|
289
|
+
/>
|
|
290
|
+
</div>
|
|
291
|
+
|
|
292
|
+
<Video id="video-1" src="/video.mp4" />
|
|
293
|
+
</div>
|
|
294
|
+
);
|
|
295
|
+
};
|
|
296
|
+
```
|
|
297
|
+
<!-- /react-only -->
|
|
298
|
+
|
|
299
|
+
## Intrinsic Duration
|
|
300
|
+
|
|
301
|
+
<!-- html-only -->
|
|
302
|
+
By default, thumbnails show the trimmed region of video:
|
|
303
|
+
- `trimstart="2s"` means thumbnails start at 2 seconds into source
|
|
304
|
+
- Duration matches effective video duration
|
|
305
|
+
|
|
306
|
+
Set `use-intrinsic-duration` to show entire source file regardless of trim.
|
|
307
|
+
<!-- /html-only -->
|
|
308
|
+
<!-- react-only -->
|
|
309
|
+
Use source video duration instead of trimmed duration:
|
|
310
|
+
|
|
311
|
+
```tsx
|
|
312
|
+
import { ThumbnailStrip, Video } from "@editframe/react";
|
|
313
|
+
|
|
314
|
+
<ThumbnailStrip
|
|
315
|
+
target="trimmed-video"
|
|
316
|
+
useIntrinsicDuration
|
|
317
|
+
className="h-12"
|
|
318
|
+
/>
|
|
319
|
+
|
|
320
|
+
<Video
|
|
321
|
+
id="trimmed-video"
|
|
322
|
+
src="/video.mp4"
|
|
323
|
+
trimStart="5s"
|
|
324
|
+
trimEnd="10s"
|
|
325
|
+
/>
|
|
326
|
+
```
|
|
327
|
+
<!-- /react-only -->
|
|
328
|
+
|
|
329
|
+
<!-- react-only -->
|
|
330
|
+
## With Direct Element Reference
|
|
331
|
+
|
|
332
|
+
Pass element reference directly:
|
|
333
|
+
|
|
334
|
+
```tsx
|
|
335
|
+
import { useRef, useEffect, useState } from "react";
|
|
336
|
+
import { ThumbnailStrip, Video } from "@editframe/react";
|
|
337
|
+
|
|
338
|
+
export const RefBasedThumbnails = () => {
|
|
339
|
+
const videoRef = useRef<HTMLVideoElement>(null);
|
|
340
|
+
const [videoElement, setVideoElement] = useState<Element | null>(null);
|
|
341
|
+
|
|
342
|
+
useEffect(() => {
|
|
343
|
+
if (videoRef.current) {
|
|
344
|
+
setVideoElement(videoRef.current);
|
|
345
|
+
}
|
|
346
|
+
}, []);
|
|
347
|
+
|
|
348
|
+
return (
|
|
349
|
+
<div>
|
|
350
|
+
<div className="h-12 bg-gray-900 mb-2">
|
|
351
|
+
<ThumbnailStrip targetElement={videoElement} />
|
|
352
|
+
</div>
|
|
353
|
+
|
|
354
|
+
<Video ref={videoRef} src="/video.mp4" />
|
|
355
|
+
</div>
|
|
356
|
+
);
|
|
357
|
+
};
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
## Styled Thumbnails
|
|
361
|
+
|
|
362
|
+
Customize appearance with CSS variables:
|
|
363
|
+
|
|
364
|
+
```tsx
|
|
365
|
+
<ThumbnailStrip
|
|
366
|
+
target="video-1"
|
|
367
|
+
className="h-16 bg-gradient-to-b from-gray-900 to-gray-800"
|
|
368
|
+
style={{
|
|
369
|
+
'--ef-thumbnail-gap': '4px',
|
|
370
|
+
'--ef-color-bg-inset': 'rgba(100, 100, 100, 0.3)',
|
|
371
|
+
'--ef-color-border-subtle': 'rgba(150, 150, 150, 0.5)',
|
|
372
|
+
} as React.CSSProperties}
|
|
373
|
+
/>
|
|
374
|
+
```
|
|
375
|
+
<!-- /react-only -->
|
|
376
|
+
|
|
377
|
+
## Features
|
|
378
|
+
|
|
379
|
+
**Lazy loading** — Only generates thumbnails for visible region as you scroll.
|
|
380
|
+
|
|
381
|
+
**Viewport virtualization** — Efficiently handles timelines of any length.
|
|
382
|
+
|
|
383
|
+
**Smart caching** — Caches generated thumbnails and reuses them when possible.
|
|
384
|
+
|
|
385
|
+
**Adaptive spacing** — Maintains consistent visual spacing at all zoom levels.
|
|
386
|
+
|
|
387
|
+
**Frame-accurate** — Aligns thumbnails to frame boundaries for precision.
|
|
388
|
+
|
|
389
|
+
**Video support** — Extracts thumbnails directly from video files.
|
|
390
|
+
|
|
391
|
+
**Timegroup support** — Renders composition snapshots with all layers.
|
|
392
|
+
|
|
393
|
+
**Automatic aspect ratio** — Thumbnails match target element dimensions.
|
|
394
|
+
|
|
395
|
+
## Target Types
|
|
396
|
+
|
|
397
|
+
<!-- html-only -->
|
|
398
|
+
**Video elements** (`ef-video`):
|
|
399
|
+
<!-- /html-only -->
|
|
400
|
+
<!-- react-only -->
|
|
401
|
+
**Video elements**:
|
|
402
|
+
<!-- /react-only -->
|
|
403
|
+
- Extracts frames directly from video file
|
|
404
|
+
- Fast batch extraction
|
|
405
|
+
- Respects video trim settings
|
|
406
|
+
|
|
407
|
+
<!-- html-only -->
|
|
408
|
+
**Root timegroups** (top-level `ef-timegroup`):
|
|
409
|
+
<!-- /html-only -->
|
|
410
|
+
<!-- react-only -->
|
|
411
|
+
**Root timegroups**:
|
|
412
|
+
<!-- /react-only -->
|
|
413
|
+
- Renders entire composition to thumbnails
|
|
414
|
+
- Includes all layers (video, text, images)
|
|
415
|
+
- Lower resolution rendering for performance
|
|
416
|
+
|
|
417
|
+
## How It Works
|
|
418
|
+
|
|
419
|
+
The thumbnail strip uses different strategies based on target type:
|
|
420
|
+
|
|
421
|
+
**For videos:**
|
|
422
|
+
1. Uses `ThumbnailExtractor` for batch frame extraction
|
|
423
|
+
2. Decodes video to access raw frames
|
|
424
|
+
3. Caches extracted frames for reuse
|
|
425
|
+
4. Supports source time translation for trimmed videos
|
|
426
|
+
|
|
427
|
+
**For timegroups:**
|
|
428
|
+
1. Creates off-screen render clone of composition
|
|
429
|
+
2. Seeks to each timestamp and captures canvas
|
|
430
|
+
3. Generates at low resolution (0.25x scale) for performance
|
|
431
|
+
4. Reuses clone for subsequent thumbnail batches
|
|
432
|
+
|
|
433
|
+
## Thumbnail Positioning
|
|
434
|
+
|
|
435
|
+
Thumbnails use a stable grid system:
|
|
436
|
+
- Grid is anchored in timeline space (not viewport space)
|
|
437
|
+
- Scrolls naturally with timeline content
|
|
438
|
+
- On zoom, grid snaps to keep thumbnails near viewport edges
|
|
439
|
+
- Prevents visual slipping during zoom operations
|
|
440
|
+
|
|
441
|
+
Spacing between thumbnails is consistent at all zoom levels, but more thumbnails become visible as you zoom in.
|
|
442
|
+
|
|
443
|
+
## Performance Optimization
|
|
444
|
+
|
|
445
|
+
**Batch extraction** — Videos extract multiple frames in one pass.
|
|
446
|
+
|
|
447
|
+
**Viewport culling** — Only renders thumbnails in visible area plus buffer.
|
|
448
|
+
|
|
449
|
+
**Canvas pooling** — Reuses canvas elements across renders.
|
|
450
|
+
|
|
451
|
+
**Abort on scroll** — Cancels in-flight captures when viewport changes.
|
|
452
|
+
|
|
453
|
+
**Nearest neighbor** — Shows nearby cached thumbnails while loading exact frame.
|
|
454
|
+
|
|
455
|
+
<!-- react-only -->
|
|
456
|
+
```tsx
|
|
457
|
+
{/* Efficiently handles long videos */}
|
|
458
|
+
<ThumbnailStrip
|
|
459
|
+
target="long-video"
|
|
460
|
+
thumbnailSpacingPx={100}
|
|
461
|
+
className="h-12"
|
|
462
|
+
/>
|
|
463
|
+
|
|
464
|
+
<Video id="long-video" src="/10-minute-video.mp4" />
|
|
465
|
+
```
|
|
466
|
+
<!-- /react-only -->
|
|
467
|
+
|
|
468
|
+
## Trimmed Videos
|
|
469
|
+
|
|
470
|
+
<!-- html-only -->
|
|
471
|
+
By default, thumbnails show the trimmed region of video:
|
|
472
|
+
- `trimstart="2s"` means thumbnails start at 2 seconds into source
|
|
473
|
+
- Duration matches effective video duration
|
|
474
|
+
|
|
475
|
+
Set `use-intrinsic-duration` to show entire source file regardless of trim.
|
|
476
|
+
<!-- /html-only -->
|
|
477
|
+
<!-- react-only -->
|
|
478
|
+
ThumbnailStrip respects video trim settings by default. Use `useIntrinsicDuration` to show the full source file regardless of trim.
|
|
479
|
+
<!-- /react-only -->
|
|
480
|
+
|
|
481
|
+
## Timeline Context
|
|
482
|
+
|
|
483
|
+
When used inside a timeline, the strip automatically:
|
|
484
|
+
- Reads zoom level from timeline context
|
|
485
|
+
- Synchronizes with timeline scroll position
|
|
486
|
+
- Updates viewport window as timeline scrolls
|
|
487
|
+
- Respects timeline state without explicit binding
|
|
488
|
+
|
|
489
|
+
<!-- html-only -->
|
|
490
|
+
For standalone use, provide explicit `pixels-per-ms` attribute.
|
|
491
|
+
<!-- /html-only -->
|
|
492
|
+
<!-- react-only -->
|
|
493
|
+
For standalone use, provide explicit `pixelsPerMs` prop.
|
|
494
|
+
<!-- /react-only -->
|
|
495
|
+
|
|
496
|
+
## CSS Custom Properties
|
|
497
|
+
|
|
498
|
+
Customize appearance:
|
|
499
|
+
|
|
500
|
+
```css
|
|
501
|
+
ef-thumbnail-strip {
|
|
502
|
+
--ef-thumbnail-gap: 2px;
|
|
503
|
+
--ef-color-bg-inset: rgba(100, 100, 100, 0.3);
|
|
504
|
+
--ef-color-border-subtle: rgba(150, 150, 150, 0.5);
|
|
505
|
+
--ef-color-error: #ef4444;
|
|
506
|
+
}
|
|
507
|
+
```
|
|
508
|
+
|
|
509
|
+
## Error States
|
|
510
|
+
|
|
511
|
+
The component shows error messages for:
|
|
512
|
+
- No target specified
|
|
513
|
+
- Target element not found
|
|
514
|
+
- Invalid target type (must be video or root timegroup)
|
|
515
|
+
|
|
516
|
+
<!-- html-only -->
|
|
517
|
+
Example error: "Invalid target: 'ef-text' must be ef-video or root ef-timegroup"
|
|
518
|
+
<!-- /html-only -->
|
|
519
|
+
<!-- react-only -->
|
|
520
|
+
```tsx
|
|
521
|
+
<div className="space-y-2">
|
|
522
|
+
{/* No target specified */}
|
|
523
|
+
<ThumbnailStrip className="h-12 bg-gray-900" />
|
|
524
|
+
|
|
525
|
+
{/* Invalid target type */}
|
|
526
|
+
<ThumbnailStrip target="not-a-video" className="h-12 bg-gray-900" />
|
|
527
|
+
</div>
|
|
528
|
+
```
|
|
529
|
+
<!-- /react-only -->
|
|
530
|
+
|
|
531
|
+
<!-- html-only -->
|
|
532
|
+
## Usage in Timeline
|
|
533
|
+
|
|
534
|
+
Thumbnails are automatically rendered in video and timegroup tracks when inside `ef-timeline`. The timeline manages thumbnail strip lifecycle and positioning.
|
|
535
|
+
|
|
536
|
+
For custom track implementations, use `ef-thumbnail-strip` directly and manage zoom/scroll context.
|
|
537
|
+
<!-- /html-only -->
|
|
538
|
+
|
|
539
|
+
<!-- react-only -->
|
|
540
|
+
## Multi-Video Timeline
|
|
541
|
+
|
|
542
|
+
Each video track gets its own thumbnail strip:
|
|
543
|
+
|
|
544
|
+
```tsx
|
|
545
|
+
import { Timeline, Timegroup, Video } from "@editframe/react";
|
|
546
|
+
|
|
547
|
+
<Timeline className="w-full h-96" />
|
|
548
|
+
|
|
549
|
+
<Timegroup mode="contain" className="w-[1920px] h-[1080px]">
|
|
550
|
+
{/* Each video appears as a separate track with thumbnails */}
|
|
551
|
+
<Video src="/video1.mp4" className="absolute top-0 left-0 w-full h-1/2" />
|
|
552
|
+
<Video src="/video2.mp4" className="absolute bottom-0 left-0 w-full h-1/2" />
|
|
553
|
+
</Timegroup>
|
|
554
|
+
```
|
|
555
|
+
|
|
556
|
+
## Notes
|
|
557
|
+
|
|
558
|
+
- ThumbnailStrip targets either `ef-video` or root `ef-timegroup` elements
|
|
559
|
+
- Automatically generates thumbnails for visible viewport area
|
|
560
|
+
- Uses efficient batch extraction for videos
|
|
561
|
+
- Canvas rendering for timegroups at low resolution
|
|
562
|
+
- Thumbnails align to frame boundaries for accuracy
|
|
563
|
+
- Spacing adapts to zoom level
|
|
564
|
+
- Shows placeholder while thumbnails load
|
|
565
|
+
- Cache persists for smooth scrubbing
|
|
566
|
+
<!-- /react-only -->
|