@editframe/create 0.44.0 → 0.45.1
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,169 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: editframe-composition
|
|
3
|
+
title: Video Composition
|
|
4
|
+
description: Create video compositions with Editframe using HTML web components or React. Supports video, audio, images, text, captions, transitions, and cloud rendering.
|
|
5
|
+
order: 10
|
|
6
|
+
license: MIT
|
|
7
|
+
metadata:
|
|
8
|
+
author: editframe
|
|
9
|
+
version: "2.0"
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# Video Composition
|
|
13
|
+
|
|
14
|
+
Build video compositions with HTML web components (`<ef-timegroup>`, `<ef-video>`, etc.) or React (`<Timegroup>`, `<Video>`, etc.). Same composition model, same rendering pipeline — pick the syntax that fits your project.
|
|
15
|
+
|
|
16
|
+
Web component attributes use kebab-case (`sourcein`, `auto-init`). React props use camelCase (`sourceIn`, `autoInit`). Each element reference documents both.
|
|
17
|
+
|
|
18
|
+
## Before opening any reference file, answer:
|
|
19
|
+
|
|
20
|
+
**1. HTML or React?**
|
|
21
|
+
- HTML/web components — kebab-case attributes, works in any HTML file
|
|
22
|
+
- React — camelCase props, requires `TimelineRoot` wrapper (see [references/timeline-root.md](references/timeline-root.md))
|
|
23
|
+
|
|
24
|
+
**2. What's the core structure?**
|
|
25
|
+
Every composition is a tree of `ef-timegroup` containers. Pick a mode:
|
|
26
|
+
- `mode="sequence"` — children play one after another (scenes)
|
|
27
|
+
- `mode="fixed"` — children play simultaneously for a set `duration`
|
|
28
|
+
- `mode="contain"` — expands to fit children
|
|
29
|
+
|
|
30
|
+
**3. What does the user need?**
|
|
31
|
+
|
|
32
|
+
| Need | Reference |
|
|
33
|
+
|------|-----------|
|
|
34
|
+
| Arrange clips in sequence | [timegroup](references/timegroup.md), [sequencing](references/sequencing.md) |
|
|
35
|
+
| Animate text | [text](references/text.md), [css-variables](references/css-variables.md) |
|
|
36
|
+
| Video/audio/image | [video](references/video.md), [audio](references/audio.md), [image](references/image.md) |
|
|
37
|
+
| Per-frame canvas animation | [scripting](references/scripting.md) |
|
|
38
|
+
| Scene transitions | [transitions](references/transitions.md) |
|
|
39
|
+
| Captions/subtitles | [captions](references/captions.md) |
|
|
40
|
+
| Export to MP4 | [render-to-video](references/render-to-video.md) or use `editframe-cli` |
|
|
41
|
+
| Cloud rendering | [render-api](references/render-api.md) |
|
|
42
|
+
|
|
43
|
+
**The single gate:** Does the composition have explicit dimensions (`w-[1920px] h-[1080px]` or equivalent) on the root timegroup? If not, the renderer has nothing to frame against — add them before anything else.
|
|
44
|
+
|
|
45
|
+
## Quick Start
|
|
46
|
+
|
|
47
|
+
<!-- html-only -->
|
|
48
|
+
|
|
49
|
+
```html
|
|
50
|
+
<ef-configuration api-host="..." media-engine="local">
|
|
51
|
+
<ef-timegroup mode="sequence" overlap="1s">
|
|
52
|
+
<ef-timegroup mode="fixed" duration="5s" class="absolute w-full h-full">
|
|
53
|
+
<ef-video src="intro.mp4" class="size-full object-cover"></ef-video>
|
|
54
|
+
<ef-text
|
|
55
|
+
split="word"
|
|
56
|
+
class="absolute top-8 left-8 text-white text-4xl font-bold"
|
|
57
|
+
style="animation: 0.6s slide-up both; animation-delay: calc(var(--ef-word-index) * 80ms)"
|
|
58
|
+
>Opening Title</ef-text>
|
|
59
|
+
</ef-timegroup>
|
|
60
|
+
<ef-timegroup mode="fixed" duration="5s" class="absolute w-full h-full">
|
|
61
|
+
<ef-video src="main.mp4" sourcein="10s" sourceout="15s" class="size-full"></ef-video>
|
|
62
|
+
<ef-audio src="music.mp3" volume="0.3"></ef-audio>
|
|
63
|
+
</ef-timegroup>
|
|
64
|
+
</ef-timegroup>
|
|
65
|
+
</ef-configuration>
|
|
66
|
+
<style>
|
|
67
|
+
@keyframes slide-up {
|
|
68
|
+
from { transform: translateY(24px); opacity: 0; }
|
|
69
|
+
to { transform: translateY(0); opacity: 1; }
|
|
70
|
+
}
|
|
71
|
+
</style>
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
<!-- /html-only -->
|
|
75
|
+
|
|
76
|
+
<!-- react-only -->
|
|
77
|
+
|
|
78
|
+
```tsx
|
|
79
|
+
import { Timegroup, Video, Text, Audio } from "@editframe/react";
|
|
80
|
+
|
|
81
|
+
export const MyVideo = () => (
|
|
82
|
+
<Timegroup mode="sequence" overlap="1s" className="w-[1920px] h-[1080px]">
|
|
83
|
+
<Timegroup mode="fixed" duration="5s" className="absolute w-full h-full">
|
|
84
|
+
<Video src="intro.mp4" className="size-full object-cover" />
|
|
85
|
+
<Text
|
|
86
|
+
split="word"
|
|
87
|
+
className="absolute top-8 left-8 text-white text-4xl font-bold"
|
|
88
|
+
style={{ animation: "0.6s slide-up both", animationDelay: "calc(var(--ef-word-index) * 80ms)" }}
|
|
89
|
+
>Opening Title</Text>
|
|
90
|
+
</Timegroup>
|
|
91
|
+
<Timegroup mode="fixed" duration="5s" className="absolute w-full h-full">
|
|
92
|
+
<Video src="main.mp4" sourceIn="10s" sourceOut="15s" className="size-full" />
|
|
93
|
+
<Audio src="music.mp3" volume={0.3} />
|
|
94
|
+
</Timegroup>
|
|
95
|
+
</Timegroup>
|
|
96
|
+
);
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
```css
|
|
100
|
+
@keyframes slide-up {
|
|
101
|
+
from { transform: translateY(24px); opacity: 0; }
|
|
102
|
+
to { transform: translateY(0); opacity: 1; }
|
|
103
|
+
}
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
React requires a `TimelineRoot` wrapper — see [references/timeline-root.md](references/timeline-root.md).
|
|
107
|
+
|
|
108
|
+
<!-- /react-only -->
|
|
109
|
+
|
|
110
|
+
## Duration Units
|
|
111
|
+
|
|
112
|
+
`5s` (seconds) | `1000ms` (milliseconds) | `2m` (minutes)
|
|
113
|
+
|
|
114
|
+
## Getting Started
|
|
115
|
+
|
|
116
|
+
Create a project: `npm create @editframe` (see the `editframe-create` skill)
|
|
117
|
+
|
|
118
|
+
- [references/getting-started.md](references/getting-started.md) — Your first composition
|
|
119
|
+
|
|
120
|
+
## Motion
|
|
121
|
+
|
|
122
|
+
Motion is how compositions become video rather than presentations. These are the primary tools.
|
|
123
|
+
|
|
124
|
+
- [references/text.md](references/text.md) — Word/character splitting, stagger animations, `--ef-stagger-offset`
|
|
125
|
+
- [references/css-variables.md](references/css-variables.md) — `--ef-progress`, `--ef-duration`, time-driven CSS
|
|
126
|
+
- [references/scripting.md](references/scripting.md) — `addFrameTask` for per-frame canvas and procedural animation
|
|
127
|
+
- [references/transitions.md](references/transitions.md) — Crossfades, slides, zoom transitions between scenes
|
|
128
|
+
- [references/r3f.md](references/r3f.md) — React Three Fiber 3D integration
|
|
129
|
+
|
|
130
|
+
## Media Elements
|
|
131
|
+
|
|
132
|
+
- [references/video.md](references/video.md) — Video clips, trimming, effects
|
|
133
|
+
- [references/audio.md](references/audio.md) — Audio, volume
|
|
134
|
+
- [references/image.md](references/image.md) — Static images
|
|
135
|
+
- [references/captions.md](references/captions.md) — Subtitles with word highlighting
|
|
136
|
+
- [references/waveform.md](references/waveform.md) — Audio visualization
|
|
137
|
+
|
|
138
|
+
## Layout & Timing
|
|
139
|
+
|
|
140
|
+
- [references/timegroup.md](references/timegroup.md) — Container, sequencing, scenes
|
|
141
|
+
- [references/sequencing.md](references/sequencing.md) — Sequential scene playback
|
|
142
|
+
- [references/surface.md](references/surface.md) — Mirror another element
|
|
143
|
+
- [references/time-model.md](references/time-model.md) — How time propagates through the tree
|
|
144
|
+
|
|
145
|
+
## Rendering
|
|
146
|
+
|
|
147
|
+
- [references/render-to-video.md](references/render-to-video.md) — Export to MP4 in the browser
|
|
148
|
+
- [references/render-api.md](references/render-api.md) — Render API and custom render data
|
|
149
|
+
- [references/transcription.md](references/transcription.md) — Generate captions with WhisperX
|
|
150
|
+
|
|
151
|
+
See the `editframe-cli` skill for CLI rendering.
|
|
152
|
+
|
|
153
|
+
## React
|
|
154
|
+
|
|
155
|
+
- [references/timeline-root.md](references/timeline-root.md) — Required wrapper for React compositions
|
|
156
|
+
- [references/hooks.md](references/hooks.md) — useTimingInfo, usePanZoomTransform
|
|
157
|
+
- [references/use-media-info.md](references/use-media-info.md) — useMediaInfo hook
|
|
158
|
+
|
|
159
|
+
## Advanced
|
|
160
|
+
|
|
161
|
+
- [references/configuration.md](references/configuration.md) — Media engine and API host
|
|
162
|
+
- [references/server-rendering.md](references/server-rendering.md) — SSR with Next.js/Remix
|
|
163
|
+
- [references/entry-points.md](references/entry-points.md) — Package exports
|
|
164
|
+
- [references/events.md](references/events.md) — Custom event catalog
|
|
165
|
+
- [references/css-parts.md](references/css-parts.md) — Shadow DOM styling
|
|
166
|
+
|
|
167
|
+
## Styling
|
|
168
|
+
|
|
169
|
+
Elements use standard CSS/Tailwind. Position with `absolute`, size with `w-full h-full` or `size-full`.
|
|
@@ -0,0 +1,483 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Audio Element
|
|
3
|
+
description: Audio element for music, voiceover, and sound effects with trim controls, volume adjustment, and loop support in compositions.
|
|
4
|
+
type: reference
|
|
5
|
+
nav:
|
|
6
|
+
parent: "Media"
|
|
7
|
+
priority: 11
|
|
8
|
+
related: ["video", "waveform"]
|
|
9
|
+
api:
|
|
10
|
+
attributes:
|
|
11
|
+
- name: src
|
|
12
|
+
type: string
|
|
13
|
+
required: true
|
|
14
|
+
description: URL or path to audio source
|
|
15
|
+
- name: sourcein
|
|
16
|
+
type: timestring
|
|
17
|
+
description: Absolute start time in source media
|
|
18
|
+
- name: sourceout
|
|
19
|
+
type: timestring
|
|
20
|
+
description: Absolute end time in source media
|
|
21
|
+
- name: trimstart
|
|
22
|
+
type: timestring
|
|
23
|
+
description: Duration to trim from start
|
|
24
|
+
- name: trimend
|
|
25
|
+
type: timestring
|
|
26
|
+
description: Duration to trim from end
|
|
27
|
+
- name: duration
|
|
28
|
+
type: timestring
|
|
29
|
+
description: Override element duration
|
|
30
|
+
- name: volume
|
|
31
|
+
type: number
|
|
32
|
+
default: 1.0
|
|
33
|
+
description: Audio volume (0.0 to 1.0)
|
|
34
|
+
- name: mute
|
|
35
|
+
type: boolean
|
|
36
|
+
default: false
|
|
37
|
+
description: Silence the audio
|
|
38
|
+
- name: fft-size
|
|
39
|
+
type: string
|
|
40
|
+
description: FFT size for waveform visualization (e.g., "256")
|
|
41
|
+
react:
|
|
42
|
+
generate: true
|
|
43
|
+
componentName: Audio
|
|
44
|
+
importPath: "@editframe/react"
|
|
45
|
+
propMapping:
|
|
46
|
+
sourcein: sourceIn
|
|
47
|
+
sourceout: sourceOut
|
|
48
|
+
trimstart: trimStart
|
|
49
|
+
trimend: trimEnd
|
|
50
|
+
fft-size: fftSize
|
|
51
|
+
additionalProps:
|
|
52
|
+
- name: className
|
|
53
|
+
type: string
|
|
54
|
+
description: CSS classes for styling
|
|
55
|
+
nav:
|
|
56
|
+
parent: "Components / Media"
|
|
57
|
+
priority: 11
|
|
58
|
+
related: ["video", "waveform"]
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
<!-- html-only -->
|
|
62
|
+
# ef-audio
|
|
63
|
+
<!-- /html-only -->
|
|
64
|
+
<!-- react-only -->
|
|
65
|
+
# Audio
|
|
66
|
+
<!-- /react-only -->
|
|
67
|
+
|
|
68
|
+
Audio element for music, voiceover, sound effects.
|
|
69
|
+
|
|
70
|
+
<!-- react-only -->
|
|
71
|
+
## Import
|
|
72
|
+
|
|
73
|
+
```tsx
|
|
74
|
+
import { Audio } from "@editframe/react";
|
|
75
|
+
```
|
|
76
|
+
<!-- /react-only -->
|
|
77
|
+
|
|
78
|
+
## Basic Usage
|
|
79
|
+
|
|
80
|
+
<!-- html-only -->
|
|
81
|
+
```html
|
|
82
|
+
<ef-audio src="music.mp3" volume="0.5"></ef-audio>
|
|
83
|
+
```
|
|
84
|
+
<!-- /html-only -->
|
|
85
|
+
<!-- react-only -->
|
|
86
|
+
```tsx
|
|
87
|
+
<Audio src="/assets/music.mp3" />
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## With Volume
|
|
91
|
+
|
|
92
|
+
```tsx
|
|
93
|
+
<Audio src="/assets/music.mp3" volume={0.3} />
|
|
94
|
+
```
|
|
95
|
+
<!-- /react-only -->
|
|
96
|
+
|
|
97
|
+
## Trimming Approaches
|
|
98
|
+
|
|
99
|
+
Two ways to trim audio - choose based on your workflow:
|
|
100
|
+
|
|
101
|
+
<!-- html-only -->
|
|
102
|
+
### Absolute Trimming (sourcein/sourceout)
|
|
103
|
+
<!-- /html-only -->
|
|
104
|
+
<!-- react-only -->
|
|
105
|
+
### Absolute Trimming (sourceIn/sourceOut)
|
|
106
|
+
<!-- /react-only -->
|
|
107
|
+
|
|
108
|
+
Use specific timestamps from source. Best for precise timecodes.
|
|
109
|
+
|
|
110
|
+
<!-- html-only -->
|
|
111
|
+
```html
|
|
112
|
+
<!-- Play seconds 5-10 from source (5s clip) -->
|
|
113
|
+
<ef-audio src="voiceover.mp3" sourcein="5s" sourceout="10s" volume="0.8"></ef-audio>
|
|
114
|
+
```
|
|
115
|
+
<!-- /html-only -->
|
|
116
|
+
<!-- react-only -->
|
|
117
|
+
```tsx
|
|
118
|
+
{/* Play seconds 30-60 from source (30s clip) */}
|
|
119
|
+
<Audio
|
|
120
|
+
src="/assets/song.mp3"
|
|
121
|
+
sourceIn="30s"
|
|
122
|
+
sourceOut="60s"
|
|
123
|
+
volume={0.5}
|
|
124
|
+
/>
|
|
125
|
+
```
|
|
126
|
+
<!-- /react-only -->
|
|
127
|
+
|
|
128
|
+
<!-- html-only -->
|
|
129
|
+
### Relative Trimming (trimstart/trimend)
|
|
130
|
+
<!-- /html-only -->
|
|
131
|
+
<!-- react-only -->
|
|
132
|
+
### Relative Trimming (trimStart/trimEnd)
|
|
133
|
+
<!-- /react-only -->
|
|
134
|
+
|
|
135
|
+
Remove time from start/end. Best for "cut off X seconds" thinking.
|
|
136
|
+
|
|
137
|
+
<!-- html-only -->
|
|
138
|
+
```html
|
|
139
|
+
<!-- Remove 1s from start, 2s from end -->
|
|
140
|
+
<ef-audio src="music.mp3" trimstart="1s" trimend="2s" volume="0.5"></ef-audio>
|
|
141
|
+
```
|
|
142
|
+
<!-- /html-only -->
|
|
143
|
+
<!-- react-only -->
|
|
144
|
+
```tsx
|
|
145
|
+
{/* Remove 1s from start, 2s from end */}
|
|
146
|
+
<Audio
|
|
147
|
+
src="/assets/music.mp3"
|
|
148
|
+
trimStart="1s"
|
|
149
|
+
trimEnd="2s"
|
|
150
|
+
volume={0.5}
|
|
151
|
+
/>
|
|
152
|
+
```
|
|
153
|
+
<!-- /react-only -->
|
|
154
|
+
|
|
155
|
+
**When to use each:**
|
|
156
|
+
<!-- html-only -->
|
|
157
|
+
- `sourcein`/`sourceout` - Working with timecode, precise frame references
|
|
158
|
+
- `trimstart`/`trimend` - UI builders, "how much to cut off" thinking
|
|
159
|
+
<!-- /html-only -->
|
|
160
|
+
<!-- react-only -->
|
|
161
|
+
- `sourceIn`/`sourceOut` - Working with timecode, precise frame references
|
|
162
|
+
- `trimStart`/`trimEnd` - UI builders, "how much to cut off" thinking
|
|
163
|
+
<!-- /react-only -->
|
|
164
|
+
|
|
165
|
+
## Background Music
|
|
166
|
+
|
|
167
|
+
<!-- html-only -->
|
|
168
|
+
```html
|
|
169
|
+
<ef-timegroup mode="fixed" duration="10s">
|
|
170
|
+
<ef-video src="video.mp4" mute class="size-full"></ef-video>
|
|
171
|
+
<ef-audio src="background-music.mp3" volume="0.3"></ef-audio>
|
|
172
|
+
</ef-timegroup>
|
|
173
|
+
```
|
|
174
|
+
<!-- /html-only -->
|
|
175
|
+
<!-- react-only -->
|
|
176
|
+
```tsx
|
|
177
|
+
import { Timegroup, Video, Audio } from "@editframe/react";
|
|
178
|
+
|
|
179
|
+
export const VideoWithMusic = () => {
|
|
180
|
+
return (
|
|
181
|
+
<Timegroup mode="sequence" className="w-[1920px] h-[1080px]">
|
|
182
|
+
{/* Audio spans entire composition */}
|
|
183
|
+
<Audio src="/assets/background-music.mp3" volume={0.2} />
|
|
184
|
+
|
|
185
|
+
<Timegroup mode="fixed" duration="10s" className="absolute w-full h-full">
|
|
186
|
+
<Video src="/assets/clip1.mp4" className="size-full" />
|
|
187
|
+
</Timegroup>
|
|
188
|
+
|
|
189
|
+
<Timegroup mode="fixed" duration="10s" className="absolute w-full h-full">
|
|
190
|
+
<Video src="/assets/clip2.mp4" className="size-full" />
|
|
191
|
+
</Timegroup>
|
|
192
|
+
</Timegroup>
|
|
193
|
+
);
|
|
194
|
+
};
|
|
195
|
+
```
|
|
196
|
+
<!-- /react-only -->
|
|
197
|
+
|
|
198
|
+
## Multiple Audio Tracks
|
|
199
|
+
|
|
200
|
+
<!-- html-only -->
|
|
201
|
+
```html
|
|
202
|
+
<ef-timegroup mode="fixed" duration="5s">
|
|
203
|
+
<ef-video src="video.mp4" mute class="size-full"></ef-video>
|
|
204
|
+
<ef-audio src="music.mp3" volume="0.25"></ef-audio>
|
|
205
|
+
<ef-audio src="voiceover.mp3" volume="0.9"></ef-audio>
|
|
206
|
+
</ef-timegroup>
|
|
207
|
+
```
|
|
208
|
+
<!-- /html-only -->
|
|
209
|
+
<!-- react-only -->
|
|
210
|
+
```tsx
|
|
211
|
+
<Timegroup mode="fixed" duration="10s">
|
|
212
|
+
<Audio src="/assets/music.mp3" volume={0.3} />
|
|
213
|
+
<Audio src="/assets/voiceover.mp3" volume={1.0} />
|
|
214
|
+
<Audio src="/assets/sfx.mp3" volume={0.5} />
|
|
215
|
+
</Timegroup>
|
|
216
|
+
```
|
|
217
|
+
<!-- /react-only -->
|
|
218
|
+
|
|
219
|
+
## Audio with Waveform Visualization
|
|
220
|
+
|
|
221
|
+
<!-- html-only -->
|
|
222
|
+
Combine `ef-audio` with `ef-waveform` for visual feedback:
|
|
223
|
+
|
|
224
|
+
```html live
|
|
225
|
+
<ef-timegroup mode="contain" class="w-[720px] h-[480px] bg-gradient-to-br from-slate-900 to-slate-800">
|
|
226
|
+
<ef-audio id="audio-viz" fft-size="256" src="https://assets.editframe.com/music-bed-1.mp3" volume="0.6"></ef-audio>
|
|
227
|
+
|
|
228
|
+
<div class="flex flex-col items-center justify-center h-full gap-8">
|
|
229
|
+
<h2 class="text-white text-3xl font-bold">Audio Visualization</h2>
|
|
230
|
+
<ef-waveform target="audio-viz" mode="bars" class="text-green-400 w-4/5 h-48"></ef-waveform>
|
|
231
|
+
</div>
|
|
232
|
+
</ef-timegroup>
|
|
233
|
+
```
|
|
234
|
+
<!-- /html-only -->
|
|
235
|
+
<!-- react-only -->
|
|
236
|
+
```tsx
|
|
237
|
+
import { Audio, Waveform } from "@editframe/react";
|
|
238
|
+
|
|
239
|
+
<Timegroup mode="contain" className="absolute w-full h-full">
|
|
240
|
+
<Audio id="my-audio" src="/assets/podcast.mp3" />
|
|
241
|
+
<Waveform
|
|
242
|
+
for="my-audio"
|
|
243
|
+
className="absolute bottom-0 w-full h-24 opacity-50"
|
|
244
|
+
/>
|
|
245
|
+
</Timegroup>
|
|
246
|
+
```
|
|
247
|
+
<!-- /react-only -->
|
|
248
|
+
|
|
249
|
+
<!-- html-only -->
|
|
250
|
+
## Volume Control with Slider
|
|
251
|
+
|
|
252
|
+
Use an HTML range input to control audio volume interactively:
|
|
253
|
+
|
|
254
|
+
```html live
|
|
255
|
+
<ef-timegroup mode="contain" class="w-[720px] h-[480px] bg-gradient-to-br from-purple-900 to-indigo-900">
|
|
256
|
+
<ef-audio id="audio-vol" fft-size="256" src="https://assets.editframe.com/music-bed-1.mp3" volume="0.5"></ef-audio>
|
|
257
|
+
|
|
258
|
+
<div class="flex flex-col items-center justify-center h-full gap-8 p-8">
|
|
259
|
+
<h2 class="text-white text-3xl font-bold">Volume Control</h2>
|
|
260
|
+
<ef-waveform target="audio-vol" mode="roundBars" class="text-cyan-400 w-4/5 h-40"></ef-waveform>
|
|
261
|
+
|
|
262
|
+
<div class="w-96 bg-white/10 backdrop-blur-sm rounded-lg p-6 space-y-4">
|
|
263
|
+
<div class="flex items-center justify-between">
|
|
264
|
+
<label for="volume-slider" class="text-white font-medium">Volume:</label>
|
|
265
|
+
<span id="volume-display" class="text-cyan-400 font-bold text-lg">50%</span>
|
|
266
|
+
</div>
|
|
267
|
+
<input
|
|
268
|
+
type="range"
|
|
269
|
+
id="volume-slider"
|
|
270
|
+
min="0"
|
|
271
|
+
max="100"
|
|
272
|
+
value="50"
|
|
273
|
+
class="w-full h-2 bg-gray-700 rounded-lg appearance-none cursor-pointer"
|
|
274
|
+
/>
|
|
275
|
+
</div>
|
|
276
|
+
</div>
|
|
277
|
+
</ef-timegroup>
|
|
278
|
+
|
|
279
|
+
<script>
|
|
280
|
+
const slider = document.getElementById('volume-slider');
|
|
281
|
+
const display = document.getElementById('volume-display');
|
|
282
|
+
const audio = document.getElementById('audio-vol');
|
|
283
|
+
|
|
284
|
+
slider.addEventListener('input', (e) => {
|
|
285
|
+
const volume = e.target.value / 100;
|
|
286
|
+
audio.volume = volume;
|
|
287
|
+
display.textContent = `${e.target.value}%`;
|
|
288
|
+
});
|
|
289
|
+
</script>
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
## Multiple Audio Tracks Layering
|
|
293
|
+
|
|
294
|
+
Layer background music, sound effects, and voiceover:
|
|
295
|
+
|
|
296
|
+
```html live
|
|
297
|
+
<ef-timegroup mode="contain" class="w-[720px] h-[480px] bg-gradient-to-br from-blue-900 to-purple-900">
|
|
298
|
+
<ef-audio id="track1" fft-size="256" src="https://assets.editframe.com/music-bed-1.mp3" volume="0.3"></ef-audio>
|
|
299
|
+
<ef-audio id="track2" src="https://assets.editframe.com/music-bed-2.mp3" volume="0.2"></ef-audio>
|
|
300
|
+
<ef-audio id="track3" src="https://assets.editframe.com/music-bed-3.mp3" volume="0.25"></ef-audio>
|
|
301
|
+
|
|
302
|
+
<div class="flex flex-col items-center justify-center h-full gap-6 p-8">
|
|
303
|
+
<h2 class="text-white text-3xl font-bold">Three Audio Tracks</h2>
|
|
304
|
+
<ef-waveform target="track1" mode="curve" class="text-pink-400 w-4/5 h-32"></ef-waveform>
|
|
305
|
+
|
|
306
|
+
<div class="w-96 bg-white/10 backdrop-blur-sm rounded-lg p-6 space-y-3">
|
|
307
|
+
<div class="text-white space-y-2">
|
|
308
|
+
<div class="flex justify-between items-center">
|
|
309
|
+
<span class="text-sm">Track 1:</span>
|
|
310
|
+
<span class="text-pink-400 font-bold">30%</span>
|
|
311
|
+
</div>
|
|
312
|
+
<div class="flex justify-between items-center">
|
|
313
|
+
<span class="text-sm">Track 2:</span>
|
|
314
|
+
<span class="text-blue-400 font-bold">20%</span>
|
|
315
|
+
</div>
|
|
316
|
+
<div class="flex justify-between items-center">
|
|
317
|
+
<span class="text-sm">Track 3:</span>
|
|
318
|
+
<span class="text-purple-400 font-bold">25%</span>
|
|
319
|
+
</div>
|
|
320
|
+
</div>
|
|
321
|
+
</div>
|
|
322
|
+
</div>
|
|
323
|
+
</ef-timegroup>
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
## Mute/Unmute Behavior
|
|
327
|
+
|
|
328
|
+
Toggle audio muting with a button:
|
|
329
|
+
|
|
330
|
+
```html live
|
|
331
|
+
<ef-timegroup mode="contain" class="w-[720px] h-[480px] bg-gradient-to-br from-gray-900 to-slate-800">
|
|
332
|
+
<ef-audio id="audio-mute" fft-size="256" src="https://assets.editframe.com/music-bed-1.mp3" volume="0.6" mute="false"></ef-audio>
|
|
333
|
+
|
|
334
|
+
<div class="flex flex-col items-center justify-center h-full gap-8 p-8">
|
|
335
|
+
<h2 class="text-white text-3xl font-bold">Mute Control</h2>
|
|
336
|
+
<ef-waveform target="audio-mute" mode="wave" class="text-yellow-400 w-4/5 h-40"></ef-waveform>
|
|
337
|
+
|
|
338
|
+
<div class="flex gap-4">
|
|
339
|
+
<button
|
|
340
|
+
id="mute-btn"
|
|
341
|
+
class="px-8 py-4 bg-red-600 hover:bg-red-700 text-white font-bold rounded-lg shadow-lg transition-colors"
|
|
342
|
+
>
|
|
343
|
+
Mute
|
|
344
|
+
</button>
|
|
345
|
+
<button
|
|
346
|
+
id="unmute-btn"
|
|
347
|
+
class="px-8 py-4 bg-green-600 hover:bg-green-700 text-white font-bold rounded-lg shadow-lg transition-colors"
|
|
348
|
+
>
|
|
349
|
+
Unmute
|
|
350
|
+
</button>
|
|
351
|
+
</div>
|
|
352
|
+
|
|
353
|
+
<div id="status" class="text-white text-xl font-medium">
|
|
354
|
+
Status: <span id="mute-status" class="text-green-400">Playing</span>
|
|
355
|
+
</div>
|
|
356
|
+
</div>
|
|
357
|
+
</ef-timegroup>
|
|
358
|
+
|
|
359
|
+
<script>
|
|
360
|
+
const audio = document.getElementById('audio-mute');
|
|
361
|
+
const muteBtn = document.getElementById('mute-btn');
|
|
362
|
+
const unmuteBtn = document.getElementById('unmute-btn');
|
|
363
|
+
const status = document.getElementById('mute-status');
|
|
364
|
+
|
|
365
|
+
muteBtn.addEventListener('click', () => {
|
|
366
|
+
audio.mute = true;
|
|
367
|
+
status.textContent = 'Muted';
|
|
368
|
+
status.className = 'text-red-400';
|
|
369
|
+
});
|
|
370
|
+
|
|
371
|
+
unmuteBtn.addEventListener('click', () => {
|
|
372
|
+
audio.mute = false;
|
|
373
|
+
status.textContent = 'Playing';
|
|
374
|
+
status.className = 'text-green-400';
|
|
375
|
+
});
|
|
376
|
+
</script>
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
## FFT Size Effect on Waveform
|
|
380
|
+
|
|
381
|
+
The `fft-size` attribute controls the frequency resolution of the waveform. Higher values provide more detail but use more processing power:
|
|
382
|
+
|
|
383
|
+
```html live
|
|
384
|
+
<ef-timegroup mode="contain" class="w-[720px] h-[480px] bg-gradient-to-br from-emerald-900 to-teal-900">
|
|
385
|
+
<ef-audio id="audio-fft" fft-size="128" src="https://assets.editframe.com/music-bed-1.mp3" volume="0.6"></ef-audio>
|
|
386
|
+
|
|
387
|
+
<div class="flex flex-col items-center justify-center h-full gap-6 p-8">
|
|
388
|
+
<h2 class="text-white text-3xl font-bold">FFT Size Control</h2>
|
|
389
|
+
<ef-waveform target="audio-fft" mode="bars" class="text-emerald-400 w-4/5 h-40"></ef-waveform>
|
|
390
|
+
|
|
391
|
+
<div class="w-96 bg-white/10 backdrop-blur-sm rounded-lg p-6 space-y-4">
|
|
392
|
+
<div class="flex items-center justify-between">
|
|
393
|
+
<label class="text-white font-medium">FFT Size:</label>
|
|
394
|
+
<span id="fft-display" class="text-emerald-400 font-bold text-lg">128</span>
|
|
395
|
+
</div>
|
|
396
|
+
|
|
397
|
+
<div class="flex gap-2">
|
|
398
|
+
<button class="fft-btn flex-1 px-4 py-2 bg-gray-700 hover:bg-gray-600 text-white rounded-lg text-sm transition-colors" data-size="64">64</button>
|
|
399
|
+
<button class="fft-btn flex-1 px-4 py-2 bg-emerald-600 text-white rounded-lg text-sm" data-size="128">128</button>
|
|
400
|
+
<button class="fft-btn flex-1 px-4 py-2 bg-gray-700 hover:bg-gray-600 text-white rounded-lg text-sm transition-colors" data-size="256">256</button>
|
|
401
|
+
<button class="fft-btn flex-1 px-4 py-2 bg-gray-700 hover:bg-gray-600 text-white rounded-lg text-sm transition-colors" data-size="512">512</button>
|
|
402
|
+
<button class="fft-btn flex-1 px-4 py-2 bg-gray-700 hover:bg-gray-600 text-white rounded-lg text-sm transition-colors" data-size="1024">1024</button>
|
|
403
|
+
</div>
|
|
404
|
+
|
|
405
|
+
<p class="text-gray-300 text-xs">
|
|
406
|
+
Higher FFT sizes provide more frequency detail but use more CPU.
|
|
407
|
+
</p>
|
|
408
|
+
</div>
|
|
409
|
+
</div>
|
|
410
|
+
</ef-timegroup>
|
|
411
|
+
|
|
412
|
+
<script>
|
|
413
|
+
const audioFft = document.getElementById('audio-fft');
|
|
414
|
+
const fftDisplay = document.getElementById('fft-display');
|
|
415
|
+
const fftButtons = document.querySelectorAll('.fft-btn');
|
|
416
|
+
|
|
417
|
+
fftButtons.forEach(btn => {
|
|
418
|
+
btn.addEventListener('click', () => {
|
|
419
|
+
const size = btn.dataset.size;
|
|
420
|
+
audioFft.setAttribute('fft-size', size);
|
|
421
|
+
fftDisplay.textContent = size;
|
|
422
|
+
|
|
423
|
+
// Update button styles
|
|
424
|
+
fftButtons.forEach(b => {
|
|
425
|
+
if (b === btn) {
|
|
426
|
+
b.className = 'fft-btn flex-1 px-4 py-2 bg-emerald-600 text-white rounded-lg text-sm';
|
|
427
|
+
} else {
|
|
428
|
+
b.className = 'fft-btn flex-1 px-4 py-2 bg-gray-700 hover:bg-gray-600 text-white rounded-lg text-sm transition-colors';
|
|
429
|
+
}
|
|
430
|
+
});
|
|
431
|
+
});
|
|
432
|
+
});
|
|
433
|
+
</script>
|
|
434
|
+
```
|
|
435
|
+
|
|
436
|
+
**FFT Size Guidelines:**
|
|
437
|
+
- `64` - Low detail, minimal CPU usage
|
|
438
|
+
- `128` - Basic visualization, good performance
|
|
439
|
+
- `256` - Balanced detail and performance (recommended)
|
|
440
|
+
- `512` - High detail, moderate CPU usage
|
|
441
|
+
- `1024` - Maximum detail, higher CPU usage
|
|
442
|
+
<!-- /html-only -->
|
|
443
|
+
|
|
444
|
+
<!-- react-only -->
|
|
445
|
+
## Dynamic Audio List
|
|
446
|
+
|
|
447
|
+
```tsx
|
|
448
|
+
interface AudioTrack {
|
|
449
|
+
id: string;
|
|
450
|
+
src: string;
|
|
451
|
+
volume: number;
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
const tracks: AudioTrack[] = [
|
|
455
|
+
{ id: "music", src: "/assets/music.mp3", volume: 0.3 },
|
|
456
|
+
{ id: "voice", src: "/assets/voice.mp3", volume: 1.0 },
|
|
457
|
+
];
|
|
458
|
+
|
|
459
|
+
<Timegroup mode="sequence" className="w-[800px] h-[500px]">
|
|
460
|
+
{tracks.map((track) => (
|
|
461
|
+
<Audio
|
|
462
|
+
key={track.id}
|
|
463
|
+
id={track.id}
|
|
464
|
+
src={track.src}
|
|
465
|
+
volume={track.volume}
|
|
466
|
+
/>
|
|
467
|
+
))}
|
|
468
|
+
</Timegroup>
|
|
469
|
+
```
|
|
470
|
+
|
|
471
|
+
## Synchronized Audio
|
|
472
|
+
|
|
473
|
+
Audio automatically syncs with the timeline. Use `sourceIn`/`sourceOut` to trim:
|
|
474
|
+
|
|
475
|
+
```tsx
|
|
476
|
+
{/* Play seconds 10-20 from the audio file */}
|
|
477
|
+
<Audio
|
|
478
|
+
src="/assets/long-audio.mp3"
|
|
479
|
+
sourceIn="10s"
|
|
480
|
+
sourceOut="20s"
|
|
481
|
+
/>
|
|
482
|
+
```
|
|
483
|
+
<!-- /react-only -->
|