videowright 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 +91 -0
- package/dist/cli/argv.d.ts +28 -0
- package/dist/cli/argv.d.ts.map +1 -0
- package/dist/cli/argv.js +115 -0
- package/dist/cli/argv.js.map +1 -0
- package/dist/cli/bin.d.ts +7 -0
- package/dist/cli/bin.d.ts.map +1 -0
- package/dist/cli/bin.js +10 -0
- package/dist/cli/bin.js.map +1 -0
- package/dist/cli/dev.d.ts +19 -0
- package/dist/cli/dev.d.ts.map +1 -0
- package/dist/cli/dev.js +104 -0
- package/dist/cli/dev.js.map +1 -0
- package/dist/cli/discover.d.ts +29 -0
- package/dist/cli/discover.d.ts.map +1 -0
- package/dist/cli/discover.js +104 -0
- package/dist/cli/discover.js.map +1 -0
- package/dist/cli/discover_project.d.ts +29 -0
- package/dist/cli/discover_project.d.ts.map +1 -0
- package/dist/cli/discover_project.js +108 -0
- package/dist/cli/discover_project.js.map +1 -0
- package/dist/cli/errors.d.ts +10 -0
- package/dist/cli/errors.d.ts.map +1 -0
- package/dist/cli/errors.js +13 -0
- package/dist/cli/errors.js.map +1 -0
- package/dist/cli/ffmpeg.d.ts +57 -0
- package/dist/cli/ffmpeg.d.ts.map +1 -0
- package/dist/cli/ffmpeg.js +122 -0
- package/dist/cli/ffmpeg.js.map +1 -0
- package/dist/cli/index.d.ts +7 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +152 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/playwright_check.d.ts +44 -0
- package/dist/cli/playwright_check.d.ts.map +1 -0
- package/dist/cli/playwright_check.js +20 -0
- package/dist/cli/playwright_check.js.map +1 -0
- package/dist/cli/prompt.d.ts +13 -0
- package/dist/cli/prompt.d.ts.map +1 -0
- package/dist/cli/prompt.js +47 -0
- package/dist/cli/prompt.js.map +1 -0
- package/dist/cli/render.d.ts +60 -0
- package/dist/cli/render.d.ts.map +1 -0
- package/dist/cli/render.js +471 -0
- package/dist/cli/render.js.map +1 -0
- package/dist/cli/script_cmd.d.ts +26 -0
- package/dist/cli/script_cmd.d.ts.map +1 -0
- package/dist/cli/script_cmd.js +88 -0
- package/dist/cli/script_cmd.js.map +1 -0
- package/dist/cli/time_shim.d.ts +44 -0
- package/dist/cli/time_shim.d.ts.map +1 -0
- package/dist/cli/time_shim.js +390 -0
- package/dist/cli/time_shim.js.map +1 -0
- package/dist/cli/ts_loader.d.ts +28 -0
- package/dist/cli/ts_loader.d.ts.map +1 -0
- package/dist/cli/ts_loader.js +95 -0
- package/dist/cli/ts_loader.js.map +1 -0
- package/dist/cli/vite_helpers.d.ts +62 -0
- package/dist/cli/vite_helpers.d.ts.map +1 -0
- package/dist/cli/vite_helpers.js +273 -0
- package/dist/cli/vite_helpers.js.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +14 -0
- package/dist/index.js.map +1 -0
- package/dist/player/hash_router.d.ts +23 -0
- package/dist/player/hash_router.d.ts.map +1 -0
- package/dist/player/hash_router.js +49 -0
- package/dist/player/hash_router.js.map +1 -0
- package/dist/player/hud.d.ts +33 -0
- package/dist/player/hud.d.ts.map +1 -0
- package/dist/player/hud.js +357 -0
- package/dist/player/hud.js.map +1 -0
- package/dist/player/index.d.ts +123 -0
- package/dist/player/index.d.ts.map +1 -0
- package/dist/player/index.js +848 -0
- package/dist/player/index.js.map +1 -0
- package/dist/player/input.d.ts +14 -0
- package/dist/player/input.d.ts.map +1 -0
- package/dist/player/input.js +90 -0
- package/dist/player/input.js.map +1 -0
- package/dist/player/slot.d.ts +22 -0
- package/dist/player/slot.d.ts.map +1 -0
- package/dist/player/slot.js +43 -0
- package/dist/player/slot.js.map +1 -0
- package/dist/player/transitions/cut.d.ts +7 -0
- package/dist/player/transitions/cut.d.ts.map +1 -0
- package/dist/player/transitions/cut.js +9 -0
- package/dist/player/transitions/cut.js.map +1 -0
- package/dist/player/transitions/fade.d.ts +7 -0
- package/dist/player/transitions/fade.d.ts.map +1 -0
- package/dist/player/transitions/fade.js +18 -0
- package/dist/player/transitions/fade.js.map +1 -0
- package/dist/player/transitions/index.d.ts +4 -0
- package/dist/player/transitions/index.d.ts.map +1 -0
- package/dist/player/transitions/index.js +4 -0
- package/dist/player/transitions/index.js.map +1 -0
- package/dist/player/transitions/slide.d.ts +6 -0
- package/dist/player/transitions/slide.d.ts.map +1 -0
- package/dist/player/transitions/slide.js +35 -0
- package/dist/player/transitions/slide.js.map +1 -0
- package/dist/script/index.d.ts +2 -0
- package/dist/script/index.d.ts.map +1 -0
- package/dist/script/index.js +2 -0
- package/dist/script/index.js.map +1 -0
- package/dist/script/script.d.ts +10 -0
- package/dist/script/script.d.ts.map +1 -0
- package/dist/script/script.js +41 -0
- package/dist/script/script.js.map +1 -0
- package/dist/segment/SegmentRunner.d.ts +52 -0
- package/dist/segment/SegmentRunner.d.ts.map +1 -0
- package/dist/segment/SegmentRunner.js +187 -0
- package/dist/segment/SegmentRunner.js.map +1 -0
- package/dist/segment/defineConfig.d.ts +6 -0
- package/dist/segment/defineConfig.d.ts.map +1 -0
- package/dist/segment/defineConfig.js +7 -0
- package/dist/segment/defineConfig.js.map +1 -0
- package/dist/segment/defineSegment.d.ts +7 -0
- package/dist/segment/defineSegment.d.ts.map +1 -0
- package/dist/segment/defineSegment.js +25 -0
- package/dist/segment/defineSegment.js.map +1 -0
- package/dist/segment/index.d.ts +5 -0
- package/dist/segment/index.d.ts.map +1 -0
- package/dist/segment/index.js +4 -0
- package/dist/segment/index.js.map +1 -0
- package/dist/timeline/index.d.ts +73 -0
- package/dist/timeline/index.d.ts.map +1 -0
- package/dist/timeline/index.js +142 -0
- package/dist/timeline/index.js.map +1 -0
- package/dist/timeline/loadAudioTrack.d.ts +18 -0
- package/dist/timeline/loadAudioTrack.d.ts.map +1 -0
- package/dist/timeline/loadAudioTrack.js +44 -0
- package/dist/timeline/loadAudioTrack.js.map +1 -0
- package/dist/timeline/loadVoiceover.d.ts +18 -0
- package/dist/timeline/loadVoiceover.d.ts.map +1 -0
- package/dist/timeline/loadVoiceover.js +38 -0
- package/dist/timeline/loadVoiceover.js.map +1 -0
- package/dist/timeline/resolveTiming.d.ts +28 -0
- package/dist/timeline/resolveTiming.d.ts.map +1 -0
- package/dist/timeline/resolveTiming.js +63 -0
- package/dist/timeline/resolveTiming.js.map +1 -0
- package/dist/timeline/validateTiming.d.ts +29 -0
- package/dist/timeline/validateTiming.d.ts.map +1 -0
- package/dist/timeline/validateTiming.js +62 -0
- package/dist/timeline/validateTiming.js.map +1 -0
- package/dist/types.d.ts +216 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +6 -0
- package/dist/types.js.map +1 -0
- package/package.json +47 -0
- package/skill/SKILL.md +64 -0
- package/skill/assets/hello_world/PLAN.md +31 -0
- package/skill/assets/hello_world/README.md +27 -0
- package/skill/assets/hello_world/audio/audio_plan.md +14 -0
- package/skill/assets/hello_world/segments/hello_intro.ts +69 -0
- package/skill/assets/hello_world/segments/hello_outro.ts +71 -0
- package/skill/assets/hello_world/timeline.ts +15 -0
- package/skill/assets/hello_world/voiceover_script/script.md +10 -0
- package/skill/assets/install/package.json +10 -0
- package/skill/assets/install/tsconfig.json +23 -0
- package/skill/assets/styles/editorial-mono/STYLE.md +124 -0
- package/skill/assets/styles/editorial-mono/brand.md +85 -0
- package/skill/assets/styles/editorial-mono/reference/animations.jsx +752 -0
- package/skill/assets/styles/editorial-mono/reference/scenes.html +563 -0
- package/skill/assets/styles/editorial-mono/sample/bullet.ts +101 -0
- package/skill/assets/styles/editorial-mono/sample/content.ts +104 -0
- package/skill/assets/styles/editorial-mono/sample/cta.ts +113 -0
- package/skill/assets/styles/editorial-mono/sample/feature.ts +111 -0
- package/skill/assets/styles/editorial-mono/sample/grid.ts +97 -0
- package/skill/assets/styles/editorial-mono/sample/kinetic.ts +96 -0
- package/skill/assets/styles/editorial-mono/sample/section.ts +101 -0
- package/skill/assets/styles/editorial-mono/sample/stat.ts +128 -0
- package/skill/assets/styles/editorial-mono/sample/title.ts +97 -0
- package/skill/assets/styles/editorial-mono/sample/ui-showcase.ts +159 -0
- package/skill/assets/styles/editorial-mono/tokens.css +44 -0
- package/skill/assets/styles/iso-diagram/STYLE.md +109 -0
- package/skill/assets/styles/iso-diagram/brand.md +32 -0
- package/skill/assets/styles/iso-diagram/reference/animations.jsx +673 -0
- package/skill/assets/styles/iso-diagram/reference/scenes.html +427 -0
- package/skill/assets/styles/iso-diagram/sample/bullet.ts +144 -0
- package/skill/assets/styles/iso-diagram/sample/content.ts +192 -0
- package/skill/assets/styles/iso-diagram/sample/cta.ts +162 -0
- package/skill/assets/styles/iso-diagram/sample/feature.ts +205 -0
- package/skill/assets/styles/iso-diagram/sample/grid.ts +181 -0
- package/skill/assets/styles/iso-diagram/sample/kinetic.ts +102 -0
- package/skill/assets/styles/iso-diagram/sample/section.ts +149 -0
- package/skill/assets/styles/iso-diagram/sample/stat.ts +164 -0
- package/skill/assets/styles/iso-diagram/sample/title.ts +173 -0
- package/skill/assets/styles/iso-diagram/sample/ui-showcase.ts +162 -0
- package/skill/assets/styles/iso-diagram/tokens.css +40 -0
- package/skill/assets/styles/motion-engineering/STYLE.md +106 -0
- package/skill/assets/styles/motion-engineering/brand.md +29 -0
- package/skill/assets/styles/motion-engineering/reference/animations.jsx +673 -0
- package/skill/assets/styles/motion-engineering/reference/scenes.html +513 -0
- package/skill/assets/styles/motion-engineering/sample/bullet.ts +176 -0
- package/skill/assets/styles/motion-engineering/sample/content.ts +228 -0
- package/skill/assets/styles/motion-engineering/sample/cta.ts +209 -0
- package/skill/assets/styles/motion-engineering/sample/feature.ts +299 -0
- package/skill/assets/styles/motion-engineering/sample/grid.ts +190 -0
- package/skill/assets/styles/motion-engineering/sample/kinetic.ts +159 -0
- package/skill/assets/styles/motion-engineering/sample/section.ts +196 -0
- package/skill/assets/styles/motion-engineering/sample/stat.ts +230 -0
- package/skill/assets/styles/motion-engineering/sample/title.ts +219 -0
- package/skill/assets/styles/motion-engineering/sample/ui-showcase.ts +267 -0
- package/skill/assets/styles/motion-engineering/tokens.css +40 -0
- package/skill/assets/styles/neon-terminal/STYLE.md +105 -0
- package/skill/assets/styles/neon-terminal/brand.md +27 -0
- package/skill/assets/styles/neon-terminal/reference/animations.jsx +673 -0
- package/skill/assets/styles/neon-terminal/reference/scenes.html +387 -0
- package/skill/assets/styles/neon-terminal/sample/bullet.ts +113 -0
- package/skill/assets/styles/neon-terminal/sample/content.ts +117 -0
- package/skill/assets/styles/neon-terminal/sample/cta.ts +131 -0
- package/skill/assets/styles/neon-terminal/sample/feature.ts +112 -0
- package/skill/assets/styles/neon-terminal/sample/grid.ts +128 -0
- package/skill/assets/styles/neon-terminal/sample/kinetic.ts +105 -0
- package/skill/assets/styles/neon-terminal/sample/section.ts +96 -0
- package/skill/assets/styles/neon-terminal/sample/stat.ts +123 -0
- package/skill/assets/styles/neon-terminal/sample/title.ts +122 -0
- package/skill/assets/styles/neon-terminal/sample/ui-showcase.ts +127 -0
- package/skill/assets/styles/neon-terminal/tokens.css +39 -0
- package/skill/assets/styles/risograph/STYLE.md +110 -0
- package/skill/assets/styles/risograph/brand.md +26 -0
- package/skill/assets/styles/risograph/reference/animations.jsx +673 -0
- package/skill/assets/styles/risograph/reference/scenes.html +403 -0
- package/skill/assets/styles/risograph/sample/bullet.ts +124 -0
- package/skill/assets/styles/risograph/sample/content.ts +135 -0
- package/skill/assets/styles/risograph/sample/cta.ts +149 -0
- package/skill/assets/styles/risograph/sample/feature.ts +152 -0
- package/skill/assets/styles/risograph/sample/grid.ts +123 -0
- package/skill/assets/styles/risograph/sample/kinetic.ts +125 -0
- package/skill/assets/styles/risograph/sample/section.ts +130 -0
- package/skill/assets/styles/risograph/sample/stat.ts +145 -0
- package/skill/assets/styles/risograph/sample/title.ts +132 -0
- package/skill/assets/styles/risograph/sample/ui-showcase.ts +147 -0
- package/skill/assets/styles/risograph/tokens.css +39 -0
- package/skill/assets/styles/swiss-console/STYLE.md +107 -0
- package/skill/assets/styles/swiss-console/brand.md +37 -0
- package/skill/assets/styles/swiss-console/reference/animations.jsx +673 -0
- package/skill/assets/styles/swiss-console/reference/scenes.html +420 -0
- package/skill/assets/styles/swiss-console/sample/bullet.ts +122 -0
- package/skill/assets/styles/swiss-console/sample/content.ts +137 -0
- package/skill/assets/styles/swiss-console/sample/cta.ts +109 -0
- package/skill/assets/styles/swiss-console/sample/feature.ts +163 -0
- package/skill/assets/styles/swiss-console/sample/grid.ts +145 -0
- package/skill/assets/styles/swiss-console/sample/kinetic.ts +117 -0
- package/skill/assets/styles/swiss-console/sample/section.ts +127 -0
- package/skill/assets/styles/swiss-console/sample/stat.ts +148 -0
- package/skill/assets/styles/swiss-console/sample/title.ts +148 -0
- package/skill/assets/styles/swiss-console/sample/ui-showcase.ts +198 -0
- package/skill/assets/styles/swiss-console/tokens.css +39 -0
- package/skill/install/INSTALL.md +400 -0
- package/skill/references/audio/audio_plan.md +199 -0
- package/skill/references/audio/build.md +208 -0
- package/skill/references/audio/cue_template.md +219 -0
- package/skill/references/audio/ffmpeg_cookbook.md +267 -0
- package/skill/references/audio/music/music.md +171 -0
- package/skill/references/audio/music/providers/elevenlabs.md +170 -0
- package/skill/references/audio/music/providers/manual.md +140 -0
- package/skill/references/audio/music/providers/openverse.md +265 -0
- package/skill/references/audio/sfx/providers/elevenlabs.md +152 -0
- package/skill/references/audio/sfx/providers/manual.md +117 -0
- package/skill/references/audio/sfx/providers/openverse.md +243 -0
- package/skill/references/audio/sfx/sfx.md +149 -0
- package/skill/references/audio/styles.md +102 -0
- package/skill/references/audio/sync.md +237 -0
- package/skill/references/audio/voiceover/animation_sync.md +142 -0
- package/skill/references/audio/voiceover/provider_script.md +153 -0
- package/skill/references/audio/voiceover/providers/elevenlabs.md +288 -0
- package/skill/references/audio/voiceover/providers/manual.md +100 -0
- package/skill/references/audio/voiceover/script_writing.md +100 -0
- package/skill/references/audio/voiceover/style_intake.md +56 -0
- package/skill/references/audio/voiceover/sync_algorithm.md +167 -0
- package/skill/references/audio/voiceover.md +296 -0
- package/skill/references/audio.md +135 -0
- package/skill/references/authoring_segment.md +446 -0
- package/skill/references/create_or_edit_video.md +232 -0
- package/skill/references/dev_server.md +157 -0
- package/skill/references/export.md +145 -0
- package/skill/references/new_video.md +117 -0
- package/skill/references/project_structure.md +144 -0
- package/skill/references/setup.md +109 -0
- package/skill/references/setup_new_style.md +158 -0
- package/skill/references/styles.md +154 -0
- package/skill/references/testing.md +115 -0
- package/skill/references/types.md +240 -0
- package/src/cli/entry/components/copy_button.ts +42 -0
- package/src/cli/entry/components/download_modal.ts +204 -0
- package/src/cli/entry/components/empty_state.ts +55 -0
- package/src/cli/entry/components/hide_hud_tab.ts +37 -0
- package/src/cli/entry/components/icons.ts +31 -0
- package/src/cli/entry/components/top_bar.ts +69 -0
- package/src/cli/entry/components/video_card.ts +57 -0
- package/src/cli/entry/dev_frame.ts +189 -0
- package/src/cli/entry/entry_index.ts +16 -0
- package/src/cli/entry/entry_video.ts +24 -0
- package/src/cli/entry/index.html +12 -0
- package/src/cli/entry/parse_slug.ts +14 -0
- package/src/cli/entry/render.html +17 -0
- package/src/cli/entry/render_entry.ts +121 -0
- package/src/cli/entry/styles/base.css +45 -0
- package/src/cli/entry/styles/components.css +605 -0
- package/src/cli/entry/styles/tokens.css +44 -0
- package/src/cli/entry/video.html +22 -0
- package/src/cli/entry/views/homepage.ts +66 -0
- package/src/cli/entry/views/video_view.ts +286 -0
- package/src/cli/entry/virtual.d.ts +8 -0
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
# Background Music
|
|
2
|
+
|
|
3
|
+
## When this is loaded
|
|
4
|
+
|
|
5
|
+
You were routed here from [audio.md](../../audio.md) because the user wants to add background music to their video. This reference covers sourcing, approving, and managing music assets.
|
|
6
|
+
|
|
7
|
+
## Overview
|
|
8
|
+
|
|
9
|
+
Each music asset is a slug-named folder under `audio/originals/music/`. Music assets are immutable once used in a rendered track. The agent sources them (BYO, ElevenLabs, or Openverse), gets user approval, then references them in the audio plan as cues with volume curves and ducking.
|
|
10
|
+
|
|
11
|
+
## Sourcing decision
|
|
12
|
+
|
|
13
|
+
Ask the user how they want to source background music. Always ask when starting a new sourcing job, even if existing music in the project used a specific source -- don't assume continuity with prior assets.
|
|
14
|
+
|
|
15
|
+
> How would you like to source background music?
|
|
16
|
+
>
|
|
17
|
+
> 1. **Bring your own** -- drop an audio file (mp3/wav) into the project and I will set it up.
|
|
18
|
+
> 2. **Generate with ElevenLabs** -- describe the music you want and I will generate it via the ElevenLabs Music Generation API. **Requires a paid plan and API key.**
|
|
19
|
+
> 3. **Search Openverse** -- search for freely-licensed music online. No API key required, free to use.
|
|
20
|
+
|
|
21
|
+
Based on the answer, load the appropriate provider reference:
|
|
22
|
+
|
|
23
|
+
- **BYO** -- load [providers/manual.md](providers/manual.md)
|
|
24
|
+
- **ElevenLabs** -- load [providers/elevenlabs.md](providers/elevenlabs.md)
|
|
25
|
+
- **Openverse** -- load [providers/openverse.md](providers/openverse.md)
|
|
26
|
+
|
|
27
|
+
## Folder structure
|
|
28
|
+
|
|
29
|
+
```
|
|
30
|
+
audio/originals/music/
|
|
31
|
+
uplift_piano/
|
|
32
|
+
audio.mp3 # source audio (immutable after approval)
|
|
33
|
+
music.ts # typed metadata with rich notes
|
|
34
|
+
generate.sh # only for ElevenLabs-sourced music
|
|
35
|
+
tense_synth/
|
|
36
|
+
audio.mp3
|
|
37
|
+
music.ts
|
|
38
|
+
generate.sh
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Slug naming
|
|
42
|
+
|
|
43
|
+
Music folders use short, semantic, snake_case names that describe the track's character:
|
|
44
|
+
|
|
45
|
+
- `uplift_piano`
|
|
46
|
+
- `tense_synth`
|
|
47
|
+
- `calm_ambient`
|
|
48
|
+
- `energetic_percussion`
|
|
49
|
+
- `corporate_upbeat`
|
|
50
|
+
|
|
51
|
+
The slug should convey the mood/instrument at a glance. Avoid generic names like `music_1` or `track_a`.
|
|
52
|
+
|
|
53
|
+
## `music.ts` metadata
|
|
54
|
+
|
|
55
|
+
Each music asset has a typed metadata file. The `notes` field is the key differentiator from SFX -- it should contain rich musical detail:
|
|
56
|
+
|
|
57
|
+
```ts
|
|
58
|
+
import type { MusicAsset } from "videowright";
|
|
59
|
+
|
|
60
|
+
export const music: MusicAsset = {
|
|
61
|
+
name: "Uplift piano",
|
|
62
|
+
description: "Solo piano, gentle build to optimistic resolution",
|
|
63
|
+
length_s: 64.2,
|
|
64
|
+
source: "elevenlabs",
|
|
65
|
+
notes: `
|
|
66
|
+
BPM: 95
|
|
67
|
+
Key: C major
|
|
68
|
+
Mood: hopeful, restrained
|
|
69
|
+
Structure: ambient intro 0-8s, theme enters 8s, build 22-34s, beat drops at 34.2s, gentle outro 50s+
|
|
70
|
+
Loops: cleanly at the bar boundary (every ~10.1s after 8s)
|
|
71
|
+
`,
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
export default music;
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Fields:
|
|
78
|
+
|
|
79
|
+
| Field | Required | Description |
|
|
80
|
+
|---|---|---|
|
|
81
|
+
| `name` | Yes | Human-readable name for display and reference. |
|
|
82
|
+
| `description` | Yes | One-line summary of the track's character. |
|
|
83
|
+
| `length_s` | Yes | Duration in seconds, measured via ffprobe. Round to 1 decimal place. |
|
|
84
|
+
| `source` | Yes | `"elevenlabs"`, `"user"`, or `"openverse"`. Records provenance. |
|
|
85
|
+
| `notes` | Yes (strongly encouraged) | Free-text musical detail. See "What to capture in notes" below. |
|
|
86
|
+
|
|
87
|
+
If the `MusicAsset` type is not yet exported from videowright, use an inline type annotation or `any` -- the shape is what matters.
|
|
88
|
+
|
|
89
|
+
### What to capture in notes
|
|
90
|
+
|
|
91
|
+
The `notes` field is free text. There are no structured fields for BPM, key, or mood -- instead, mix any useful detail freely. Common things worth noting:
|
|
92
|
+
|
|
93
|
+
- **BPM** -- critical for beat-aligned visuals
|
|
94
|
+
- **Key** -- useful if combining with other musical elements
|
|
95
|
+
- **Mood** -- helps the agent choose volume curves and placement
|
|
96
|
+
- **Structure** -- timestamps of sections (intro, build, drop, outro). Essential for slicing and ducking.
|
|
97
|
+
- **Loop points** -- where the track loops cleanly, if applicable
|
|
98
|
+
- **Beat positions** -- where notable rhythmic events land (useful as sync anchors)
|
|
99
|
+
- **Instrument palette** -- what instruments are present
|
|
100
|
+
- **Frequency range** -- if the track is mostly low-end, high-end, or full-spectrum
|
|
101
|
+
|
|
102
|
+
Not all fields apply to every track. Write what is useful. Even brief notes ("ambient, no strong beat, loops after 8s") are better than nothing.
|
|
103
|
+
|
|
104
|
+
## Approval UX
|
|
105
|
+
|
|
106
|
+
After a music asset is sourced (file in place, `music.ts` written), present it for approval:
|
|
107
|
+
|
|
108
|
+
1. **Print a clickable absolute `file://` link** to the audio file:
|
|
109
|
+
|
|
110
|
+
```
|
|
111
|
+
Listen to the music track:
|
|
112
|
+
file:///absolute/path/to/audio/originals/music/uplift_piano/audio.mp3
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
2. **Prompt with exactly two options:**
|
|
116
|
+
|
|
117
|
+
> 1. **Approve** -- lock this asset for use in the audio plan.
|
|
118
|
+
> 2. **Discard and request changes** -- delete this asset and try again.
|
|
119
|
+
|
|
120
|
+
3. **On Approve:**
|
|
121
|
+
- The asset is locked. Its folder and contents must not be modified or deleted.
|
|
122
|
+
- Proceed to integrate it into the audio plan (see "Integration into audio plan" below).
|
|
123
|
+
|
|
124
|
+
4. **On Discard:**
|
|
125
|
+
- Delete the entire asset folder:
|
|
126
|
+
```bash
|
|
127
|
+
rm -rf audio/originals/music/<slug>/
|
|
128
|
+
```
|
|
129
|
+
- Ask: "What should change about this music?"
|
|
130
|
+
- Take feedback and re-source (loop back to the provider flow).
|
|
131
|
+
|
|
132
|
+
### Pre-use deletion only
|
|
133
|
+
|
|
134
|
+
A music folder can only be deleted if it has **never been used** in a rendered track. Once a track references it (via a plan snapshot), deletion would corrupt the snapshot. If the user asks to delete a used asset, refuse and explain which track(s) reference it.
|
|
135
|
+
|
|
136
|
+
## Integration into audio plan
|
|
137
|
+
|
|
138
|
+
After approval, the music is ready to be referenced in `audio/audio_plan.md` as a cue. See [../cue_template.md](../cue_template.md) for the cue format.
|
|
139
|
+
|
|
140
|
+
Typical music cue:
|
|
141
|
+
|
|
142
|
+
```
|
|
143
|
+
### Cue 1 -- Background music
|
|
144
|
+
Source: audio/originals/music/uplift_piano/
|
|
145
|
+
Slice: 0-45.0
|
|
146
|
+
Place at: 0.0
|
|
147
|
+
Volume: 100% from 0s, ramps to 15% over 2.8-3.0s (VO starts at 3.0s), 15% from 3.0-22.0s, ramps to 50% over 22.0-22.3s (animation beat), ramps to 15% over 23.5-23.7s, 15% from 23.7-40.0s, ramps to 80% over 40.0-40.2s (outro), fade out 43.0-45.0s
|
|
148
|
+
Fades: fade in 0-0.5s, fade out 43.0-45.0s
|
|
149
|
+
Notes: Music bed throughout. Ducked under all VO segments. Rises during visual-only transitions and outro.
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
Key points:
|
|
153
|
+
- `Source:` points to the music folder.
|
|
154
|
+
- `Volume:` expresses the full ducking curve explicitly. The agent writes the actual levels at each point in time -- no opaque "duck under VO" directives. See [../styles.md](../styles.md) for level guidance.
|
|
155
|
+
- Music typically spans most or all of the video. Use `Slice:` to trim if the track is longer than needed.
|
|
156
|
+
- Ducking ramps should be ~0.2s (see [../styles.md](../styles.md)).
|
|
157
|
+
- If the track has a strong beat, align visual transitions to beat boundaries where possible (compute from BPM in notes).
|
|
158
|
+
|
|
159
|
+
## One track or many?
|
|
160
|
+
|
|
161
|
+
For most product/demo videos (30s-3min), **one music track** is sufficient. The ducking curve provides enough variation. Multiple tracks increase complexity -- only use them if the video has distinct tonal sections requiring genuinely different music.
|
|
162
|
+
|
|
163
|
+
## Edge cases
|
|
164
|
+
|
|
165
|
+
| Situation | Behavior |
|
|
166
|
+
|---|---|
|
|
167
|
+
| Music is shorter than the video | Use `aloop` in ffmpeg to loop it. Note loop points in `music.ts` notes. See [../ffmpeg_cookbook.md](../ffmpeg_cookbook.md). |
|
|
168
|
+
| Music is much longer than the video | Use `Slice:` in the cue to take only the needed portion. |
|
|
169
|
+
| User wants music but no VO | Music plays at full level throughout. No ducking needed. Volume curve is simple: fade in, hold at 100%, fade out. |
|
|
170
|
+
| User wants to swap music after a track is built | Source a new music asset in a new slug folder, approve it, update the audio plan cues to reference the new slug, rebuild the track. |
|
|
171
|
+
| User provides a copyrighted track | Agent does not police copyright. Note in `music.ts` notes if the user mentions licensing (e.g., "Licensed via Epidemic Sound"). |
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
# ElevenLabs Music Generation
|
|
2
|
+
|
|
3
|
+
## When this is loaded
|
|
4
|
+
|
|
5
|
+
The user chose ElevenLabs to generate background music. This reference covers the Music Generation API endpoint, prompt-writing tips, and the `generate.sh` template.
|
|
6
|
+
|
|
7
|
+
## Prerequisites
|
|
8
|
+
|
|
9
|
+
- `ELEVENLABS_API_KEY` set in `.env` at the project root. The key must have **Music Generation** permission enabled.
|
|
10
|
+
- If the user does not have an API key, guide them through setup: see [../../voiceover/providers/elevenlabs.md](../../voiceover/providers/elevenlabs.md) (Step 2: Get the API key). The same key works for TTS, STT, SFX, and Music.
|
|
11
|
+
|
|
12
|
+
## Cost notice
|
|
13
|
+
|
|
14
|
+
> **Cost notice:** ElevenLabs charges credits for music generation. Longer tracks cost more credits. A 60-second track typically costs 2,000-5,000 credits depending on complexity. Check your remaining quota at https://elevenlabs.io/app/subscription before generating.
|
|
15
|
+
|
|
16
|
+
## API endpoint
|
|
17
|
+
|
|
18
|
+
**Endpoint:** `POST https://api.elevenlabs.io/v1/music-generation`
|
|
19
|
+
|
|
20
|
+
**Request body:**
|
|
21
|
+
|
|
22
|
+
```json
|
|
23
|
+
{
|
|
24
|
+
"text": "<prompt describing the desired music>",
|
|
25
|
+
"duration_seconds": 60,
|
|
26
|
+
"prompt_influence": 0.5
|
|
27
|
+
}
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
| Field | Required | Description |
|
|
31
|
+
|---|---|---|
|
|
32
|
+
| `text` | Yes | Natural-language description of the music. See prompt-writing tips below. |
|
|
33
|
+
| `duration_seconds` | No | Target duration in seconds. If omitted, the API chooses (usually 30s). Recommended: specify to match your video length. |
|
|
34
|
+
| `prompt_influence` | No | 0.0-1.0. Higher values follow the prompt more literally; lower values give more creative freedom. 0.5 is a good starting point for music. |
|
|
35
|
+
|
|
36
|
+
**Response:** The API returns raw audio bytes (mp3) directly in the response body.
|
|
37
|
+
|
|
38
|
+
## `generate.sh` template
|
|
39
|
+
|
|
40
|
+
Write this script to `audio/originals/music/<slug>/generate.sh` for reproducibility:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
#!/bin/bash
|
|
44
|
+
# Generated Music: <name>
|
|
45
|
+
# Prompt: <the exact prompt used>
|
|
46
|
+
# Duration: <duration_seconds>s
|
|
47
|
+
# Prompt influence: <prompt_influence>
|
|
48
|
+
|
|
49
|
+
set -euo pipefail
|
|
50
|
+
|
|
51
|
+
# Load API key from .env
|
|
52
|
+
if [ -f .env ]; then
|
|
53
|
+
export $(grep -v '^#' .env | xargs)
|
|
54
|
+
fi
|
|
55
|
+
|
|
56
|
+
if [ -z "${ELEVENLABS_API_KEY:-}" ]; then
|
|
57
|
+
echo "Error: ELEVENLABS_API_KEY not set. Add it to .env" >&2
|
|
58
|
+
exit 1
|
|
59
|
+
fi
|
|
60
|
+
|
|
61
|
+
SLUG="<slug>"
|
|
62
|
+
OUTPUT_DIR="audio/originals/music/${SLUG}"
|
|
63
|
+
mkdir -p "${OUTPUT_DIR}"
|
|
64
|
+
|
|
65
|
+
curl -X POST "https://api.elevenlabs.io/v1/music-generation" \
|
|
66
|
+
-H "xi-api-key: ${ELEVENLABS_API_KEY}" \
|
|
67
|
+
-H "Content-Type: application/json" \
|
|
68
|
+
-d '{
|
|
69
|
+
"text": "<prompt>",
|
|
70
|
+
"duration_seconds": <duration>,
|
|
71
|
+
"prompt_influence": <influence>
|
|
72
|
+
}' \
|
|
73
|
+
--output "${OUTPUT_DIR}/audio.mp3"
|
|
74
|
+
|
|
75
|
+
echo "Music saved to ${OUTPUT_DIR}/audio.mp3"
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Make the script executable: `chmod +x generate.sh`.
|
|
79
|
+
|
|
80
|
+
**Important:** Run `generate.sh` from the **video folder** (the directory containing `timeline.ts`) so that relative paths resolve correctly.
|
|
81
|
+
|
|
82
|
+
## Prompt-writing tips
|
|
83
|
+
|
|
84
|
+
Music generation prompts benefit from structure. Include these dimensions:
|
|
85
|
+
|
|
86
|
+
### Specify genre and instruments
|
|
87
|
+
- Good: "Ambient electronic with soft piano chords and warm synth pads"
|
|
88
|
+
- Bad: "Background music"
|
|
89
|
+
|
|
90
|
+
### Describe mood and energy arc
|
|
91
|
+
- Good: "Starts minimal and hopeful, builds gradually, reaches an optimistic peak at 30s, then settles into a gentle outro"
|
|
92
|
+
- Bad: "Happy music"
|
|
93
|
+
|
|
94
|
+
### Mention tempo and rhythm
|
|
95
|
+
- Good: "Moderate tempo around 90-100 BPM, light percussion, no heavy drums"
|
|
96
|
+
- Bad: "Not too fast"
|
|
97
|
+
|
|
98
|
+
### Describe the use case
|
|
99
|
+
- Good: "Background music for a product demo video. Needs to sit behind voiceover without competing. Should feel professional and modern."
|
|
100
|
+
- Bad: "Music for a video"
|
|
101
|
+
|
|
102
|
+
### Useful descriptors for product/demo videos
|
|
103
|
+
|
|
104
|
+
| Dimension | Good choices |
|
|
105
|
+
|---|---|
|
|
106
|
+
| Genre | ambient, corporate, indie electronic, lo-fi, minimal, cinematic |
|
|
107
|
+
| Instruments | piano, synth pads, soft guitar, muted percussion, strings, bells |
|
|
108
|
+
| Mood | professional, optimistic, calm, confident, innovative, warm |
|
|
109
|
+
| Energy | low-energy, mid-energy, building, steady, dynamic |
|
|
110
|
+
| Avoid | aggressive drums, heavy bass drops, distorted guitars, vocals |
|
|
111
|
+
|
|
112
|
+
### Duration guidance
|
|
113
|
+
|
|
114
|
+
Match the music duration to your video:
|
|
115
|
+
- Request slightly longer than needed (add 5-10s buffer). You can slice in the audio plan.
|
|
116
|
+
- For videos with intro + content + outro: request the full duration so you get a natural arc.
|
|
117
|
+
- For looping backgrounds: request at least one full musical phrase (usually 16-32s at standard tempos) so the loop point sounds clean.
|
|
118
|
+
|
|
119
|
+
## Post-generation workflow
|
|
120
|
+
|
|
121
|
+
After the curl command succeeds:
|
|
122
|
+
|
|
123
|
+
1. **Verify the file exists and is non-empty:**
|
|
124
|
+
```bash
|
|
125
|
+
ls -la audio/originals/music/<slug>/audio.mp3
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
2. **Measure duration via ffprobe:**
|
|
129
|
+
```bash
|
|
130
|
+
ffprobe -v error -show_entries format=duration \
|
|
131
|
+
-of default=noprint_wrappers=1:nokey=1 \
|
|
132
|
+
audio/originals/music/<slug>/audio.mp3
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
3. **Ask the user to listen and describe the track.** Before writing metadata, ask the user to play the track and report:
|
|
136
|
+
- BPM (can often be inferred from the prompt's requested tempo; otherwise ask the user to estimate)
|
|
137
|
+
- Key (if discernible)
|
|
138
|
+
- Structure (where sections change, where the energy peaks)
|
|
139
|
+
- Any notable moments (beat drops, transitions, loop points)
|
|
140
|
+
|
|
141
|
+
4. **Write `music.ts`** with rich metadata (see [../music.md](../music.md) for the shape). Set `source: "elevenlabs"`. Include all observed musical details in the `notes` field.
|
|
142
|
+
|
|
143
|
+
5. **Trigger the approval UX** (see [../music.md](../music.md) -- Approval UX section).
|
|
144
|
+
|
|
145
|
+
## Iteration on discard
|
|
146
|
+
|
|
147
|
+
If the user discards and requests changes:
|
|
148
|
+
|
|
149
|
+
1. Delete the folder: `rm -rf audio/originals/music/<slug>/`
|
|
150
|
+
2. Ask what should change about the music.
|
|
151
|
+
3. Adjust the prompt based on feedback. Common adjustments:
|
|
152
|
+
- "Too energetic" -- add "calm", "minimal", "ambient", reduce tempo
|
|
153
|
+
- "Too boring" -- add "building", "dynamic", increase tempo, add percussion
|
|
154
|
+
- "Wrong mood" -- change mood descriptors entirely
|
|
155
|
+
- "Too short" -- increase `duration_seconds`
|
|
156
|
+
- "Instruments are wrong" -- specify desired instruments, explicitly exclude unwanted ones ("no drums", "no vocals")
|
|
157
|
+
- "Needs a stronger ending" -- describe the outro in the prompt ("resolves to a clear final chord")
|
|
158
|
+
4. Re-run with the updated prompt. Write a new `generate.sh` reflecting the new parameters.
|
|
159
|
+
|
|
160
|
+
## Troubleshooting
|
|
161
|
+
|
|
162
|
+
| Issue | Resolution |
|
|
163
|
+
|---|---|
|
|
164
|
+
| 401 Unauthorized | Check `ELEVENLABS_API_KEY` in `.env`. Ensure the key has Music Generation permission. |
|
|
165
|
+
| 422 Unprocessable Entity | Prompt may be problematic. Keep prompts 20-500 characters. Avoid special characters. |
|
|
166
|
+
| Empty or 0-byte response | API may have failed silently. Retry. If persistent, try a shorter duration or different prompt. |
|
|
167
|
+
| Generated music does not match prompt | Increase `prompt_influence` (try 0.6-0.8). Be more specific about instruments and mood. |
|
|
168
|
+
| Music has vocals/singing | Add "instrumental only, no vocals, no singing" to the prompt. |
|
|
169
|
+
| Rate limited (429) | Wait and retry. Check quota at https://elevenlabs.io/app/subscription. |
|
|
170
|
+
| Track is shorter than requested | The API may cap duration. Try requesting in smaller segments or accept the shorter track. |
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
# Manual Music (Bring Your Own)
|
|
2
|
+
|
|
3
|
+
## When this is loaded
|
|
4
|
+
|
|
5
|
+
The user has their own music audio file and wants to add it to the project. This is the BYO path from [../music.md](../music.md).
|
|
6
|
+
|
|
7
|
+
## Overview
|
|
8
|
+
|
|
9
|
+
The manual flow takes a user-provided music file, places it in the correct folder, gathers rich metadata, and presents it for approval. No API calls needed.
|
|
10
|
+
|
|
11
|
+
## Step 1: Set up the folder
|
|
12
|
+
|
|
13
|
+
Choose a slug name for this music track. The slug should describe the track's character in short snake_case:
|
|
14
|
+
|
|
15
|
+
- `uplift_piano`
|
|
16
|
+
- `calm_ambient`
|
|
17
|
+
- `energetic_corporate`
|
|
18
|
+
- `dark_synth_intro`
|
|
19
|
+
|
|
20
|
+
Create the directory:
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
mkdir -p audio/originals/music/<slug>/
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Step 2: Get the audio file
|
|
27
|
+
|
|
28
|
+
Ask the user for the file. Two options:
|
|
29
|
+
|
|
30
|
+
1. **File path.** The user provides a path to an existing file. Copy it into the folder:
|
|
31
|
+
```bash
|
|
32
|
+
cp /path/to/their/file.mp3 audio/originals/music/<slug>/audio.mp3
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
2. **Drop-in.** Ask the user to place the file directly:
|
|
36
|
+
> Place your music file at `audio/originals/music/<slug>/audio.mp3` (or `audio.wav`).
|
|
37
|
+
|
|
38
|
+
### Supported formats
|
|
39
|
+
|
|
40
|
+
- MP3 and WAV are standard. Both work with ffmpeg.
|
|
41
|
+
- Other formats (M4A, OGG, FLAC, AIFF) are also accepted by ffmpeg.
|
|
42
|
+
- No specific sample rate or bitrate requirements.
|
|
43
|
+
|
|
44
|
+
## Step 3: Gather metadata
|
|
45
|
+
|
|
46
|
+
Music metadata should be richer than SFX. Ask the user:
|
|
47
|
+
|
|
48
|
+
> I need details about this music track. Please share as much as you know:
|
|
49
|
+
>
|
|
50
|
+
> 1. **Name** -- a short descriptive name (e.g., "Uplift piano")
|
|
51
|
+
> 2. **Description** -- one sentence summary (e.g., "Solo piano, gentle build to optimistic resolution")
|
|
52
|
+
> 3. **Notes** -- any musical detail you know. Helpful things to include:
|
|
53
|
+
> - BPM (tempo)
|
|
54
|
+
> - Key (e.g., C major, A minor)
|
|
55
|
+
> - Mood (e.g., hopeful, tense, calm)
|
|
56
|
+
> - Structure (e.g., "intro 0-8s, main theme 8-30s, outro 30-40s")
|
|
57
|
+
> - Loop points (where it loops cleanly, if applicable)
|
|
58
|
+
> - Instrument palette
|
|
59
|
+
> - Licensing info (if relevant)
|
|
60
|
+
>
|
|
61
|
+
> Even partial info is useful -- I will ask follow-up questions if needed.
|
|
62
|
+
|
|
63
|
+
### Agent-observed details
|
|
64
|
+
|
|
65
|
+
After the user provides their info, the agent should also note any additional observations in `notes`:
|
|
66
|
+
|
|
67
|
+
- If BPM was not provided, ask the user to estimate or measure it after listening
|
|
68
|
+
- Ask the user about any structural transitions (energy changes, instrument entrances)
|
|
69
|
+
- Ask whether the track has a clean ending or fades out
|
|
70
|
+
- Ask whether it loops well
|
|
71
|
+
|
|
72
|
+
Combine user-provided info and agent observations into the `notes` field.
|
|
73
|
+
|
|
74
|
+
## Step 4: Measure duration
|
|
75
|
+
|
|
76
|
+
Use ffprobe to get the exact length:
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
ffprobe -v error -show_entries format=duration \
|
|
80
|
+
-of default=noprint_wrappers=1:nokey=1 \
|
|
81
|
+
audio/originals/music/<slug>/audio.mp3
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Round to 1 decimal place for `length_s`.
|
|
85
|
+
|
|
86
|
+
## Step 5: Write `music.ts`
|
|
87
|
+
|
|
88
|
+
Create `audio/originals/music/<slug>/music.ts`:
|
|
89
|
+
|
|
90
|
+
```ts
|
|
91
|
+
import type { MusicAsset } from "videowright";
|
|
92
|
+
|
|
93
|
+
export const music: MusicAsset = {
|
|
94
|
+
name: "<name from user>",
|
|
95
|
+
description: "<description from user>",
|
|
96
|
+
length_s: <measured duration>,
|
|
97
|
+
source: "user",
|
|
98
|
+
notes: `
|
|
99
|
+
<combined notes from user + agent observations>
|
|
100
|
+
`,
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
export default music;
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
Set `source: "user"` to record that this was a BYO asset.
|
|
107
|
+
|
|
108
|
+
There is no `generate.sh` for BYO assets.
|
|
109
|
+
|
|
110
|
+
## Step 6: Trigger approval UX
|
|
111
|
+
|
|
112
|
+
Follow the approval flow from [../music.md](../music.md):
|
|
113
|
+
|
|
114
|
+
1. Print the clickable `file://` link to the audio file.
|
|
115
|
+
2. Prompt: Approve or Discard and request changes.
|
|
116
|
+
3. On Approve: asset is locked, ready for use in the audio plan.
|
|
117
|
+
4. On Discard: delete the folder, ask what to change, loop back.
|
|
118
|
+
|
|
119
|
+
For BYO assets, "discard and request changes" means the user needs to provide a different file. Ask them to supply a different track.
|
|
120
|
+
|
|
121
|
+
## Expected folder state after approval
|
|
122
|
+
|
|
123
|
+
```
|
|
124
|
+
audio/originals/music/<slug>/
|
|
125
|
+
audio.mp3 # user-provided audio (immutable after approval)
|
|
126
|
+
music.ts # typed metadata with rich notes
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
No `generate.sh` for BYO assets.
|
|
130
|
+
|
|
131
|
+
## Edge cases
|
|
132
|
+
|
|
133
|
+
| Situation | Behavior |
|
|
134
|
+
|---|---|
|
|
135
|
+
| Track has vocals | Warn that vocals may conflict with voiceover. Suggest an instrumental version if available, or note that heavy ducking will be needed. |
|
|
136
|
+
| Track is very short (< 10s) | May need looping. Note loop-ability in `notes`. See [../../ffmpeg_cookbook.md](../../ffmpeg_cookbook.md) for `aloop`. |
|
|
137
|
+
| Track is very long (> 5min) | Fine -- the audio plan will use `Slice:` to take only the needed portion. |
|
|
138
|
+
| User does not know BPM/key | That is fine. BPM is optional -- ask the user to estimate if needed. Key is optional. Write what is known. |
|
|
139
|
+
| User mentions licensing/attribution | Record in `notes` (e.g., "Licensed via Artlist, attribution required in credits"). The agent does not enforce licensing. |
|
|
140
|
+
| User wants to replace after approval | Cannot edit in place. Source a new version in a new slug folder and update audio plan cues. |
|