@nodaro/prompts 1.0.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/LICENSE +105 -0
- package/README.md +27 -0
- package/dist/index.cjs +21240 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +3599 -0
- package/dist/index.d.ts +3599 -0
- package/dist/index.js +20854 -0
- package/dist/index.js.map +1 -0
- package/package.json +49 -0
- package/src/__tests__/__snapshots__/prompt-builder-segments.test.ts.snap +65 -0
- package/src/__tests__/action-fx.test.ts +155 -0
- package/src/__tests__/apply-picker-json.test.ts +50 -0
- package/src/__tests__/assemble-image-input.test.ts +248 -0
- package/src/__tests__/assemble-suno-input.test.ts +283 -0
- package/src/__tests__/brand-tokens.test.ts +81 -0
- package/src/__tests__/build-image-prompt-element-injection.test.ts +118 -0
- package/src/__tests__/build-image-prompt-hybrid-format.test.ts +131 -0
- package/src/__tests__/build-image-prompt-mentions.test.ts +809 -0
- package/src/__tests__/build-image-prompt-reference-cap.test.ts +57 -0
- package/src/__tests__/build-image-prompt-reference-numbering.test.ts +237 -0
- package/src/__tests__/build-image-prompt-reference-order.test.ts +313 -0
- package/src/__tests__/camera-motions-from-connections.test.ts +71 -0
- package/src/__tests__/catalog-gapfill.test.ts +53 -0
- package/src/__tests__/character-convergence-image.test.ts +217 -0
- package/src/__tests__/character-default-role-image.test.ts +167 -0
- package/src/__tests__/character-default-role-video.test.ts +168 -0
- package/src/__tests__/character-default-role.test.ts +70 -0
- package/src/__tests__/character-fx.test.ts +200 -0
- package/src/__tests__/entity-prompts-location.test.ts +97 -0
- package/src/__tests__/entity-prompts.test.ts +240 -0
- package/src/__tests__/expand-extra-refs-role.test.ts +50 -0
- package/src/__tests__/factory-presets.test.ts +1045 -0
- package/src/__tests__/factory-snippets.test.ts +68 -0
- package/src/__tests__/framing-multi.test.ts +71 -0
- package/src/__tests__/framing-vantage.test.ts +39 -0
- package/src/__tests__/i18n-entry-completeness.test.ts +269 -0
- package/src/__tests__/identity-lock.test.ts +46 -0
- package/src/__tests__/instrumentation.test.ts +68 -0
- package/src/__tests__/lighting-multi.test.ts +68 -0
- package/src/__tests__/location-convergence-image.test.ts +124 -0
- package/src/__tests__/mention-lock-flag.test.ts +499 -0
- package/src/__tests__/multi-picker-spec.test.ts +71 -0
- package/src/__tests__/music-genre.test.ts +103 -0
- package/src/__tests__/music-mood.test.ts +87 -0
- package/src/__tests__/object-creature-convergence-image.test.ts +105 -0
- package/src/__tests__/parameter-prompt-hint.test.ts +270 -0
- package/src/__tests__/parameter-registry-sync.test.ts +243 -0
- package/src/__tests__/person-age.test.ts +80 -0
- package/src/__tests__/person-analyzer-invariants.test.ts +47 -0
- package/src/__tests__/person-body-axes.test.ts +67 -0
- package/src/__tests__/person-facial-geometry.test.ts +156 -0
- package/src/__tests__/person-regional-aesthetic.test.ts +161 -0
- package/src/__tests__/person-sections.test.ts +18 -0
- package/src/__tests__/picker-analyzer-registry.test.ts +108 -0
- package/src/__tests__/picker-catalogs-project.test.ts +85 -0
- package/src/__tests__/picker-catalogs.test.ts +53 -0
- package/src/__tests__/picker-limits.test.ts +20 -0
- package/src/__tests__/prompt-builder-segments.test.ts +183 -0
- package/src/__tests__/prompt-builder-structured-fields.test.ts +40 -0
- package/src/__tests__/prompt-builder.test.ts +1773 -0
- package/src/__tests__/prompt-wizard-categories.test.ts +31 -0
- package/src/__tests__/provider-prompt-doctrine.test.ts +49 -0
- package/src/__tests__/resolve-prompt-append.test.ts +58 -0
- package/src/__tests__/resolve-prompt.test.ts +44 -0
- package/src/__tests__/role-picker-shared.test.ts +208 -0
- package/src/__tests__/seedance-2-inputs.test.ts +173 -0
- package/src/__tests__/seedance-extend.test.ts +44 -0
- package/src/__tests__/sound-aggregator.test.ts +350 -0
- package/src/__tests__/style-presets.test.ts +34 -0
- package/src/__tests__/temporal-multi.test.ts +74 -0
- package/src/__tests__/transitions.test.ts +213 -0
- package/src/__tests__/video-reference-features.test.ts +41 -0
- package/src/__tests__/video-reference-leading-refs.test.ts +90 -0
- package/src/__tests__/video-reference-resolver.test.ts +233 -0
- package/src/__tests__/video-reference-roles.test.ts +96 -0
- package/src/__tests__/voice-character.test.ts +48 -0
- package/src/__tests__/voice-delivery.test.ts +41 -0
- package/src/__tests__/wardrobe.test.ts +25 -0
- package/src/action-fx.ts +255 -0
- package/src/aesthetic.ts +435 -0
- package/src/assemble-image-input.ts +236 -0
- package/src/assemble-suno-input.ts +147 -0
- package/src/atmosphere.ts +104 -0
- package/src/backdrop.ts +131 -0
- package/src/brand-tokens.ts +154 -0
- package/src/camera-format.ts +76 -0
- package/src/camera-motions.ts +615 -0
- package/src/character-fx.ts +274 -0
- package/src/color-look.ts +103 -0
- package/src/composition-effects.ts +67 -0
- package/src/entity-prompts.ts +231 -0
- package/src/era.ts +292 -0
- package/src/exposure-settings.ts +142 -0
- package/src/factory-presets/generate-image.ts +1644 -0
- package/src/factory-presets/generate-video.ts +1116 -0
- package/src/factory-presets/index.ts +46 -0
- package/src/factory-presets/lottie-overlay.ts +166 -0
- package/src/factory-presets/motion-graphics.ts +350 -0
- package/src/factory-presets/music.ts +734 -0
- package/src/factory-presets/sfx.ts +136 -0
- package/src/factory-presets/shared-image.ts +207 -0
- package/src/factory-presets/switchx.ts +65 -0
- package/src/factory-presets/text.ts +292 -0
- package/src/factory-presets/types.ts +51 -0
- package/src/factory-presets/video-edit.ts +136 -0
- package/src/factory-presets/voice.ts +172 -0
- package/src/factory-presets.ts +2 -0
- package/src/factory-snippets/catalog.ts +105 -0
- package/src/factory-snippets/index.ts +16 -0
- package/src/factory-snippets/types.ts +33 -0
- package/src/framing.ts +634 -0
- package/src/held-prop.ts +187 -0
- package/src/identity-lock.ts +213 -0
- package/src/index.ts +66 -0
- package/src/instrumentation.ts +337 -0
- package/src/lens.ts +59 -0
- package/src/lighting.ts +229 -0
- package/src/loop-subject.ts +276 -0
- package/src/materials.ts +184 -0
- package/src/mood.ts +186 -0
- package/src/music-genre.ts +662 -0
- package/src/music-mood.ts +137 -0
- package/src/object-asset-presets.ts +81 -0
- package/src/parameter-prompt-hint.ts +281 -0
- package/src/person.ts +1368 -0
- package/src/photo-genre.ts +151 -0
- package/src/photographer.ts +612 -0
- package/src/picker-analyzer-registry.ts +374 -0
- package/src/picker-catalogs.ts +858 -0
- package/src/pose.ts +246 -0
- package/src/post-process-effects.ts +94 -0
- package/src/prompt-builder-structured-fields.ts +116 -0
- package/src/prompt-builder.ts +2964 -0
- package/src/prompt-templates.ts +50 -0
- package/src/prompt-wizard-categories.ts +334 -0
- package/src/provider-prompt-doctrine.ts +85 -0
- package/src/render-quality.ts +89 -0
- package/src/resolve-prompt.ts +120 -0
- package/src/seedance-2-inputs.ts +100 -0
- package/src/setting.ts +130 -0
- package/src/sound-aggregator.ts +241 -0
- package/src/style-presets.ts +162 -0
- package/src/style.ts +99 -0
- package/src/styling.ts +585 -0
- package/src/temporal.ts +151 -0
- package/src/transitions.ts +333 -0
- package/src/video-reference-resolver.ts +823 -0
- package/src/voice-character.ts +237 -0
- package/src/voice-delivery.ts +142 -0
- package/src/wardrobe.ts +179 -0
|
@@ -0,0 +1,337 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Instrumentation catalog: instruments (multi-select) + production style +
|
|
3
|
+
* vocal presence. Composed into "[production] [instruments-joined] with [vocalPresence]".
|
|
4
|
+
*
|
|
5
|
+
* `vocalPresence: "instrumental"` is the trigger that the Generate Music
|
|
6
|
+
* (MiniMax) integration uses to flip its `instrumental: true` flag.
|
|
7
|
+
*
|
|
8
|
+
* INSTRUMENTS carries a `category` field used by the picker to render a
|
|
9
|
+
* horizontal tab row mirroring Splice's instrument taxonomy
|
|
10
|
+
* (https://splice.com/sounds/instruments) — Drums / Percussion / Keys /
|
|
11
|
+
* Synth / Guitar / Bass / Brass / Woodwinds / Strings / World.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
export type InstrumentCategory =
|
|
15
|
+
| "drums"
|
|
16
|
+
| "percussion"
|
|
17
|
+
| "keys"
|
|
18
|
+
| "synth"
|
|
19
|
+
| "guitar"
|
|
20
|
+
| "bass"
|
|
21
|
+
| "brass"
|
|
22
|
+
| "woodwinds"
|
|
23
|
+
| "strings"
|
|
24
|
+
| "world"
|
|
25
|
+
| "middle-eastern"
|
|
26
|
+
|
|
27
|
+
export const INSTRUMENT_CATEGORY_ORDER: ReadonlyArray<InstrumentCategory> = [
|
|
28
|
+
"drums", "percussion", "keys", "synth", "guitar", "bass",
|
|
29
|
+
"brass", "woodwinds", "strings", "world", "middle-eastern",
|
|
30
|
+
] as const
|
|
31
|
+
|
|
32
|
+
export const INSTRUMENT_CATEGORY_LABELS: Readonly<Record<InstrumentCategory, string>> = {
|
|
33
|
+
drums: "Drums",
|
|
34
|
+
percussion: "Percussion",
|
|
35
|
+
keys: "Keys",
|
|
36
|
+
synth: "Synth",
|
|
37
|
+
guitar: "Guitar",
|
|
38
|
+
bass: "Bass",
|
|
39
|
+
brass: "Brass",
|
|
40
|
+
woodwinds: "Woodwinds",
|
|
41
|
+
strings: "Strings",
|
|
42
|
+
world: "World",
|
|
43
|
+
"middle-eastern": "Middle Eastern",
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export interface InstrumentationEntry {
|
|
47
|
+
readonly id: string
|
|
48
|
+
readonly label: string
|
|
49
|
+
readonly description: string
|
|
50
|
+
readonly promptHint: string
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export interface CategorizedInstrument extends InstrumentationEntry {
|
|
54
|
+
readonly category: InstrumentCategory
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export const INSTRUMENTS: ReadonlyArray<CategorizedInstrument> = [
|
|
58
|
+
// -------- Drums --------
|
|
59
|
+
{ id: "drums", label: "Drums", description: "Acoustic drum kit", promptHint: "drums", category: "drums" },
|
|
60
|
+
{ id: "drum-machine", label: "Drum Machine", description: "Programmed beats", promptHint: "drum machine", category: "drums" },
|
|
61
|
+
{ id: "808", label: "808", description: "Roland TR-808 bass + kit", promptHint: "808 drums", category: "drums" },
|
|
62
|
+
{ id: "live-drums", label: "Live Drums", description: "Recorded acoustic kit", promptHint: "live drums", category: "drums" },
|
|
63
|
+
{ id: "breakbeats", label: "Breakbeats", description: "Sampled drum loops", promptHint: "breakbeats", category: "drums" },
|
|
64
|
+
{ id: "trap-drums", label: "Trap Drums", description: "Hi-hat rolls + 808", promptHint: "trap drums", category: "drums" },
|
|
65
|
+
|
|
66
|
+
// -------- Percussion --------
|
|
67
|
+
{ id: "bongos", label: "Bongos", description: "Pair of small Cuban drums", promptHint: "bongos", category: "percussion" },
|
|
68
|
+
{ id: "conga", label: "Conga", description: "Tall single-headed drum", promptHint: "conga", category: "percussion" },
|
|
69
|
+
{ id: "djembe", label: "Djembe", description: "Goblet-shaped West African",promptHint: "djembe", category: "percussion" },
|
|
70
|
+
{ id: "timbales", label: "Timbales", description: "Cuban paired metal drums", promptHint: "timbales", category: "percussion" },
|
|
71
|
+
{ id: "tambourine", label: "Tambourine", description: "Hand-shaken jingles", promptHint: "tambourine", category: "percussion" },
|
|
72
|
+
{ id: "shaker", label: "Shaker", description: "Filled rattle", promptHint: "shaker", category: "percussion" },
|
|
73
|
+
{ id: "cowbell", label: "Cowbell", description: "Hand-held cowbell", promptHint: "cowbell", category: "percussion" },
|
|
74
|
+
{ id: "maracas", label: "Maracas", description: "Latin shaker pair", promptHint: "maracas", category: "percussion" },
|
|
75
|
+
{ id: "claves", label: "Claves", description: "Wooden sticks", promptHint: "claves", category: "percussion" },
|
|
76
|
+
{ id: "marimba", label: "Marimba", description: "Wooden mallet keyboard", promptHint: "marimba", category: "percussion" },
|
|
77
|
+
{ id: "vibraphone", label: "Vibraphone", description: "Electric-resonator mallet", promptHint: "vibraphone", category: "percussion" },
|
|
78
|
+
{ id: "xylophone", label: "Xylophone", description: "Wooden mallet, bright", promptHint: "xylophone", category: "percussion" },
|
|
79
|
+
{ id: "glockenspiel", label: "Glockenspiel", description: "High-pitched mallet bells", promptHint: "glockenspiel", category: "percussion" },
|
|
80
|
+
{ id: "timpani", label: "Timpani", description: "Large orchestral kettledrum", promptHint: "timpani", category: "percussion" },
|
|
81
|
+
{ id: "taiko", label: "Taiko", description: "Japanese ensemble drum", promptHint: "taiko", category: "percussion" },
|
|
82
|
+
{ id: "frame-drum", label: "Frame Drum", description: "Shallow round drum", promptHint: "frame drum", category: "percussion" },
|
|
83
|
+
{ id: "cajon", label: "Cajón", description: "Box-shaped Peruvian drum", promptHint: "cajón", category: "percussion" },
|
|
84
|
+
{ id: "darbuka", label: "Darbuka", description: "Middle Eastern goblet drum",promptHint: "darbuka", category: "percussion" },
|
|
85
|
+
|
|
86
|
+
// -------- Keys --------
|
|
87
|
+
{ id: "piano", label: "Piano", description: "Acoustic grand or upright", promptHint: "piano", category: "keys" },
|
|
88
|
+
{ id: "electric-piano", label: "Electric Piano", description: "Rhodes / Wurlitzer-style", promptHint: "electric piano", category: "keys" },
|
|
89
|
+
{ id: "wurlitzer", label: "Wurlitzer", description: "Vintage Wurlitzer EP", promptHint: "Wurlitzer electric piano", category: "keys" },
|
|
90
|
+
{ id: "rhodes", label: "Rhodes", description: "Vintage Rhodes EP", promptHint: "Rhodes electric piano",category: "keys" },
|
|
91
|
+
{ id: "clavinet", label: "Clavinet", description: "Funky Hohner D6", promptHint: "clavinet", category: "keys" },
|
|
92
|
+
{ id: "organ", label: "Organ", description: "Hammond or pipe organ", promptHint: "organ", category: "keys" },
|
|
93
|
+
{ id: "hammond-organ", label: "Hammond B3", description: "Soul / rock B3 organ", promptHint: "Hammond B3 organ", category: "keys" },
|
|
94
|
+
{ id: "pipe-organ", label: "Pipe Organ", description: "Cathedral / church", promptHint: "pipe organ", category: "keys" },
|
|
95
|
+
{ id: "accordion", label: "Accordion", description: "Bellows-driven reed", promptHint: "accordion", category: "keys" },
|
|
96
|
+
{ id: "mellotron", label: "Mellotron", description: "Tape-loop keyboard", promptHint: "mellotron", category: "keys" },
|
|
97
|
+
{ id: "harpsichord", label: "Harpsichord", description: "Plucked-string keyboard", promptHint: "harpsichord", category: "keys" },
|
|
98
|
+
{ id: "celesta", label: "Celesta", description: "Bell-like keyboard", promptHint: "celesta", category: "keys" },
|
|
99
|
+
|
|
100
|
+
// -------- Synth --------
|
|
101
|
+
{ id: "synthesizer", label: "Synthesizer", description: "Analog or digital synth", promptHint: "synthesizer", category: "synth" },
|
|
102
|
+
{ id: "lead-synth", label: "Lead Synth", description: "Cutting melodic synth", promptHint: "lead synth", category: "synth" },
|
|
103
|
+
{ id: "pluck-synth", label: "Pluck Synth", description: "Short, plucked timbre", promptHint: "pluck synth", category: "synth" },
|
|
104
|
+
{ id: "pads", label: "Synth Pads", description: "Sustained synth textures", promptHint: "synth pads", category: "synth" },
|
|
105
|
+
{ id: "arpeggiator", label: "Arpeggiator", description: "Sequenced arp patterns", promptHint: "arpeggiated synth", category: "synth" },
|
|
106
|
+
{ id: "vocoder", label: "Vocoder", description: "Voice-modulated synth", promptHint: "vocoder", category: "synth" },
|
|
107
|
+
{ id: "talkbox", label: "Talkbox", description: "Mouth-shaped synth", promptHint: "talkbox", category: "synth" },
|
|
108
|
+
{ id: "modular-synth", label: "Modular", description: "Patchable analog synth", promptHint: "modular synth", category: "synth" },
|
|
109
|
+
{ id: "fm-synth", label: "FM Synth", description: "Frequency-modulation synth",promptHint: "FM synth", category: "synth" },
|
|
110
|
+
{ id: "wavetable-synth", label: "Wavetable", description: "Wavetable-scanning synth", promptHint: "wavetable synth", category: "synth" },
|
|
111
|
+
{ id: "stab-synth", label: "Stab", description: "Short, percussive chord", promptHint: "synth stab", category: "synth" },
|
|
112
|
+
|
|
113
|
+
// -------- Guitar --------
|
|
114
|
+
{ id: "acoustic-guitar", label: "Acoustic Guitar", description: "Steel- or nylon-strung", promptHint: "acoustic guitar", category: "guitar" },
|
|
115
|
+
{ id: "electric-guitar", label: "Electric Guitar", description: "Solid-body, often distorted", promptHint: "electric guitar", category: "guitar" },
|
|
116
|
+
{ id: "classical-guitar",label: "Classical Guitar",description: "Nylon-string, fingerstyle", promptHint: "classical guitar", category: "guitar" },
|
|
117
|
+
{ id: "12-string-guitar",label: "12-String", description: "Doubled-course strum", promptHint: "12-string guitar", category: "guitar" },
|
|
118
|
+
{ id: "pedal-steel", label: "Pedal Steel", description: "Country sliding steel", promptHint: "pedal steel", category: "guitar" },
|
|
119
|
+
{ id: "lap-steel", label: "Lap Steel", description: "Hawaiian lap-played steel", promptHint: "lap steel", category: "guitar" },
|
|
120
|
+
{ id: "dobro", label: "Dobro", description: "Resonator guitar", promptHint: "dobro resonator", category: "guitar" },
|
|
121
|
+
{ id: "banjo", label: "Banjo", description: "5-string or tenor", promptHint: "banjo", category: "guitar" },
|
|
122
|
+
{ id: "mandolin", label: "Mandolin", description: "Folk / bluegrass", promptHint: "mandolin", category: "guitar" },
|
|
123
|
+
{ id: "ukulele", label: "Ukulele", description: "Soprano-tenor uke", promptHint: "ukulele", category: "guitar" },
|
|
124
|
+
|
|
125
|
+
// -------- Bass --------
|
|
126
|
+
{ id: "bass-guitar", label: "Bass Guitar", description: "Low-end electric bass", promptHint: "bass guitar", category: "bass" },
|
|
127
|
+
{ id: "synth-bass", label: "Synth Bass", description: "Synthesized low end", promptHint: "synth bass", category: "bass" },
|
|
128
|
+
{ id: "sub-bass", label: "Sub Bass", description: "Deep sine sub frequencies", promptHint: "sub bass", category: "bass" },
|
|
129
|
+
{ id: "acoustic-bass", label: "Acoustic Bass", description: "Acoustic bass guitar", promptHint: "acoustic bass", category: "bass" },
|
|
130
|
+
{ id: "upright-bass", label: "Upright Bass", description: "Double bass, jazz-style", promptHint: "upright bass", category: "bass" },
|
|
131
|
+
{ id: "fretless-bass", label: "Fretless Bass", description: "Sliding bass guitar", promptHint: "fretless bass", category: "bass" },
|
|
132
|
+
{ id: "acid-bass", label: "Acid Bass", description: "TB-303 squelch", promptHint: "acid bass", category: "bass" },
|
|
133
|
+
{ id: "wobble-bass", label: "Wobble Bass", description: "LFO-modulated dubstep", promptHint: "wobble bass", category: "bass" },
|
|
134
|
+
{ id: "reese-bass", label: "Reese Bass", description: "Detuned drum-and-bass", promptHint: "Reese bass", category: "bass" },
|
|
135
|
+
|
|
136
|
+
// -------- Brass --------
|
|
137
|
+
{ id: "brass", label: "Brass Section", description: "Trumpet, trombone, etc.", promptHint: "brass section", category: "brass" },
|
|
138
|
+
{ id: "trumpet", label: "Trumpet", description: "Solo trumpet", promptHint: "trumpet", category: "brass" },
|
|
139
|
+
{ id: "trombone", label: "Trombone", description: "Solo trombone", promptHint: "trombone", category: "brass" },
|
|
140
|
+
{ id: "french-horn", label: "French Horn", description: "Mellow brass", promptHint: "french horn", category: "brass" },
|
|
141
|
+
{ id: "tuba", label: "Tuba", description: "Lowest brass", promptHint: "tuba", category: "brass" },
|
|
142
|
+
{ id: "saxophone", label: "Saxophone", description: "Solo or section sax", promptHint: "saxophone", category: "brass" },
|
|
143
|
+
{ id: "flugelhorn", label: "Flugelhorn", description: "Mellow trumpet cousin", promptHint: "flugelhorn", category: "brass" },
|
|
144
|
+
{ id: "cornet", label: "Cornet", description: "Brass band cornet", promptHint: "cornet", category: "brass" },
|
|
145
|
+
{ id: "muted-trumpet", label: "Muted Trumpet", description: "Muted jazz trumpet", promptHint: "muted trumpet", category: "brass" },
|
|
146
|
+
|
|
147
|
+
// -------- Woodwinds --------
|
|
148
|
+
{ id: "flute", label: "Flute", description: "Concert flute", promptHint: "flute", category: "woodwinds" },
|
|
149
|
+
{ id: "clarinet", label: "Clarinet", description: "Solo clarinet", promptHint: "clarinet", category: "woodwinds" },
|
|
150
|
+
{ id: "harmonica", label: "Harmonica", description: "Blues harp", promptHint: "harmonica", category: "woodwinds" },
|
|
151
|
+
{ id: "oboe", label: "Oboe", description: "Reed-driven, plaintive", promptHint: "oboe", category: "woodwinds" },
|
|
152
|
+
{ id: "bassoon", label: "Bassoon", description: "Low double-reed", promptHint: "bassoon", category: "woodwinds" },
|
|
153
|
+
{ id: "english-horn", label: "English Horn", description: "Tenor oboe", promptHint: "english horn", category: "woodwinds" },
|
|
154
|
+
{ id: "piccolo", label: "Piccolo", description: "High flute", promptHint: "piccolo", category: "woodwinds" },
|
|
155
|
+
{ id: "recorder", label: "Recorder", description: "Soft-toned woodwind", promptHint: "recorder", category: "woodwinds" },
|
|
156
|
+
{ id: "pan-flute", label: "Pan Flute", description: "Andean pipe flute", promptHint: "pan flute", category: "woodwinds" },
|
|
157
|
+
|
|
158
|
+
// -------- Strings --------
|
|
159
|
+
{ id: "strings", label: "String Section", description: "Orchestral string section", promptHint: "string section", category: "strings" },
|
|
160
|
+
{ id: "violin", label: "Violin", description: "Solo violin", promptHint: "violin", category: "strings" },
|
|
161
|
+
{ id: "viola", label: "Viola", description: "Solo viola", promptHint: "viola", category: "strings" },
|
|
162
|
+
{ id: "cello", label: "Cello", description: "Solo cello", promptHint: "cello", category: "strings" },
|
|
163
|
+
{ id: "double-bass", label: "Double Bass", description: "Orchestral upright bass", promptHint: "double bass", category: "strings" },
|
|
164
|
+
{ id: "harp", label: "Harp", description: "Concert or folk harp", promptHint: "harp", category: "strings" },
|
|
165
|
+
{ id: "pizzicato-strings",label: "Pizzicato", description: "Plucked strings", promptHint: "pizzicato strings", category: "strings" },
|
|
166
|
+
{ id: "staccato-strings",label: "Staccato", description: "Short, punchy strings", promptHint: "staccato strings", category: "strings" },
|
|
167
|
+
{ id: "fiddle", label: "Fiddle", description: "Folk-style violin", promptHint: "fiddle", category: "strings" },
|
|
168
|
+
|
|
169
|
+
// -------- World --------
|
|
170
|
+
{ id: "sitar", label: "Sitar", description: "Indian long-necked", promptHint: "sitar", category: "world" },
|
|
171
|
+
{ id: "tabla", label: "Tabla", description: "Indian hand drums", promptHint: "tabla", category: "world" },
|
|
172
|
+
{ id: "steel-drum", label: "Steel Drum", description: "Trinidadian steelpan", promptHint: "steel drum", category: "world" },
|
|
173
|
+
{ id: "kalimba", label: "Kalimba", description: "African thumb piano", promptHint: "kalimba", category: "world" },
|
|
174
|
+
{ id: "bagpipes", label: "Bagpipes", description: "Scottish pipes", promptHint: "bagpipes", category: "world" },
|
|
175
|
+
{ id: "didgeridoo", label: "Didgeridoo", description: "Australian wind", promptHint: "didgeridoo", category: "world" },
|
|
176
|
+
{ id: "oud", label: "Oud", description: "Middle Eastern lute", promptHint: "oud", category: "world" },
|
|
177
|
+
{ id: "erhu", label: "Erhu", description: "Chinese 2-string fiddle", promptHint: "erhu", category: "world" },
|
|
178
|
+
{ id: "koto", label: "Koto", description: "Japanese zither", promptHint: "koto", category: "world" },
|
|
179
|
+
{ id: "shakuhachi", label: "Shakuhachi", description: "Japanese end-blown flute", promptHint: "shakuhachi", category: "world" },
|
|
180
|
+
{ id: "shamisen", label: "Shamisen", description: "Japanese 3-string lute", promptHint: "shamisen", category: "world" },
|
|
181
|
+
{ id: "duduk", label: "Duduk", description: "Armenian double-reed", promptHint: "duduk", category: "world" },
|
|
182
|
+
{ id: "balalaika", label: "Balalaika", description: "Russian triangular lute", promptHint: "balalaika", category: "world" },
|
|
183
|
+
{ id: "bouzouki", label: "Bouzouki", description: "Greek long-necked lute", promptHint: "bouzouki", category: "world" },
|
|
184
|
+
{ id: "kora", label: "Kora", description: "West African 21-string", promptHint: "kora", category: "world" },
|
|
185
|
+
{ id: "hang-drum", label: "Hang Drum", description: "Steel hand pan", promptHint: "hang drum", category: "world" },
|
|
186
|
+
|
|
187
|
+
// -------- Middle Eastern --------
|
|
188
|
+
{ id: "kamancheh", label: "Kamancheh", description: "Persian bowed spike fiddle", promptHint: "kamancheh", category: "middle-eastern" },
|
|
189
|
+
{ id: "ney", label: "Ney", description: "Persian/Arabic end-blown reed flute", promptHint: "ney flute", category: "middle-eastern" },
|
|
190
|
+
{ id: "santur", label: "Santur", description: "Persian hammered dulcimer", promptHint: "santur", category: "middle-eastern" },
|
|
191
|
+
] as const
|
|
192
|
+
|
|
193
|
+
export const PRODUCTION_STYLES: ReadonlyArray<InstrumentationEntry> = [
|
|
194
|
+
{ id: "polished", label: "Polished", description: "Pristine, mainstream production", promptHint: "polished production" },
|
|
195
|
+
{ id: "lo-fi", label: "Lo-fi", description: "Warm tape hiss, imperfect", promptHint: "lo-fi production" },
|
|
196
|
+
{ id: "raw", label: "Raw", description: "Unfiltered, live feel", promptHint: "raw production" },
|
|
197
|
+
{ id: "vintage", label: "Vintage", description: "Analog warmth", promptHint: "vintage production" },
|
|
198
|
+
{ id: "modern", label: "Modern", description: "Contemporary digital", promptHint: "modern production" },
|
|
199
|
+
{ id: "minimalist", label: "Minimalist", description: "Sparse, restrained", promptHint: "minimalist production" },
|
|
200
|
+
{ id: "wall-of-sound", label: "Wall of Sound", description: "Dense, layered", promptHint: "wall-of-sound production" },
|
|
201
|
+
{ id: "ambient", label: "Ambient", description: "Atmospheric, reverbed", promptHint: "ambient production" },
|
|
202
|
+
{ id: "garage-band", label: "Garage Band", description: "DIY, basement-tracked", promptHint: "garage band production" },
|
|
203
|
+
{ id: "live-recording", label: "Live", description: "Live concert / room sound", promptHint: "live recording" },
|
|
204
|
+
{ id: "demo-quality", label: "Demo", description: "Rough demo aesthetic", promptHint: "demo quality" },
|
|
205
|
+
{ id: "studio-pristine", label: "Studio Pristine", description: "Hi-fi reference quality", promptHint: "pristine studio production" },
|
|
206
|
+
{ id: "tape-saturated", label: "Tape Saturated", description: "Analog tape warmth + drive", promptHint: "tape-saturated" },
|
|
207
|
+
{ id: "8-bit-retro", label: "8-bit Retro", description: "Lo-bitrate retro game audio", promptHint: "8-bit retro production" },
|
|
208
|
+
] as const
|
|
209
|
+
|
|
210
|
+
export const VOCAL_PRESENCE: ReadonlyArray<InstrumentationEntry> = [
|
|
211
|
+
{ id: "instrumental", label: "Instrumental", description: "No vocals (exclusive)", promptHint: "instrumental, no vocals" },
|
|
212
|
+
{ id: "male-lead", label: "Male Lead", description: "Male lead vocal", promptHint: "male lead vocals" },
|
|
213
|
+
{ id: "female-lead", label: "Female Lead", description: "Female lead vocal", promptHint: "female lead vocals" },
|
|
214
|
+
{ id: "androgynous-lead",label: "Androgynous", description: "Gender-neutral lead", promptHint: "androgynous lead vocals" },
|
|
215
|
+
{ id: "duet", label: "Duet", description: "Two lead vocalists", promptHint: "duet lead vocals" },
|
|
216
|
+
{ id: "choir", label: "Choir", description: "Choral / ensemble vocals", promptHint: "choir vocals" },
|
|
217
|
+
{ id: "gospel-choir", label: "Gospel Choir", description: "Gospel-style choir backing", promptHint: "gospel choir" },
|
|
218
|
+
{ id: "harmony-stack", label: "Harmony Stack", description: "Stacked vocal harmonies", promptHint: "stacked vocal harmonies" },
|
|
219
|
+
{ id: "rapper-lead", label: "Rapper", description: "Rap lead", promptHint: "rap lead vocals" },
|
|
220
|
+
{ id: "spoken-word", label: "Spoken Word", description: "Spoken / poetry over music", promptHint: "spoken word" },
|
|
221
|
+
{ id: "vocal-chops", label: "Vocal Chops", description: "Sliced sample vocals", promptHint: "vocal chops" },
|
|
222
|
+
{ id: "mixed", label: "Mixed", description: "Multiple lead vocalists", promptHint: "mixed lead vocals" },
|
|
223
|
+
] as const
|
|
224
|
+
|
|
225
|
+
/** "instrumental" is mutually exclusive with any other vocal presence —
|
|
226
|
+
* picking it while others are selected clears the others, and picking
|
|
227
|
+
* another while "instrumental" is selected clears it. */
|
|
228
|
+
export const VOCAL_PRESENCE_INSTRUMENTAL_ID = "instrumental"
|
|
229
|
+
|
|
230
|
+
export const SINGING_STYLES: ReadonlyArray<InstrumentationEntry> = [
|
|
231
|
+
{ id: "pop-singing", label: "Pop", description: "Mainstream lead style", promptHint: "pop singing" },
|
|
232
|
+
{ id: "rock-singing", label: "Rock", description: "Rock-style vocal delivery", promptHint: "rock singing" },
|
|
233
|
+
{ id: "operatic", label: "Operatic", description: "Classical opera technique", promptHint: "operatic singing" },
|
|
234
|
+
{ id: "classical-vocals", label: "Classical", description: "Trained classical voice", promptHint: "classical vocals" },
|
|
235
|
+
{ id: "rap", label: "Rap", description: "Rhythmic spoken delivery", promptHint: "rap" },
|
|
236
|
+
{ id: "trap-melodic", label: "Trap (Melodic)", description: "Melodic trap, autotuned", promptHint: "melodic trap singing" },
|
|
237
|
+
{ id: "growl", label: "Growl", description: "Death-metal-style growl", promptHint: "growled vocals" },
|
|
238
|
+
{ id: "scream", label: "Scream", description: "Hardcore / screamed", promptHint: "screamed vocals" },
|
|
239
|
+
{ id: "shout", label: "Shout", description: "Punk / chanted shout", promptHint: "shouted vocals" },
|
|
240
|
+
{ id: "falsetto", label: "Falsetto", description: "High register, light", promptHint: "falsetto" },
|
|
241
|
+
{ id: "head-voice", label: "Head Voice", description: "Resonant high register", promptHint: "head voice" },
|
|
242
|
+
{ id: "chest-voice", label: "Chest Voice", description: "Strong, low register", promptHint: "chest voice" },
|
|
243
|
+
{ id: "belting", label: "Belting", description: "Powerful sustained high", promptHint: "belting" },
|
|
244
|
+
{ id: "crooning", label: "Crooning", description: "Smooth vintage romantic", promptHint: "crooning" },
|
|
245
|
+
{ id: "scat", label: "Scat", description: "Improvised jazz syllables", promptHint: "scat singing" },
|
|
246
|
+
{ id: "yodeling", label: "Yodeling", description: "Alpine register-flip", promptHint: "yodeling" },
|
|
247
|
+
{ id: "throat-singing", label: "Throat Singing", description: "Mongolian / Tuvan overtone", promptHint: "throat singing" },
|
|
248
|
+
{ id: "melismatic", label: "Melismatic", description: "Multi-note runs per syllable", promptHint: "melismatic" },
|
|
249
|
+
{ id: "autotuned", label: "Autotuned", description: "Pitch-corrected, processed", promptHint: "autotuned vocals" },
|
|
250
|
+
{ id: "vocoded", label: "Vocoded", description: "Vocoder-processed vocals", promptHint: "vocoded vocals" },
|
|
251
|
+
{ id: "whisper-singing", label: "Whisper Sing", description: "Hushed, intimate singing", promptHint: "whisper-singing" },
|
|
252
|
+
{ id: "breathy-singing", label: "Breathy", description: "Airy, intimate singing", promptHint: "breathy singing" },
|
|
253
|
+
{ id: "harmonized", label: "Harmonized", description: "Multi-voice harmonies", promptHint: "harmonized vocals" },
|
|
254
|
+
{ id: "chant", label: "Chant", description: "Liturgical / monk chanting", promptHint: "chanted vocals" },
|
|
255
|
+
] as const
|
|
256
|
+
|
|
257
|
+
const INSTRUMENT_BY_ID = new Map(INSTRUMENTS.map((x) => [x.id, x]))
|
|
258
|
+
const PRODUCTION_BY_ID = new Map(PRODUCTION_STYLES.map((x) => [x.id, x]))
|
|
259
|
+
const VOCAL_BY_ID = new Map(VOCAL_PRESENCE.map((x) => [x.id, x]))
|
|
260
|
+
const SINGING_STYLE_BY_ID = new Map(SINGING_STYLES.map((x) => [x.id, x]))
|
|
261
|
+
|
|
262
|
+
export function getInstrument(id: string | undefined): CategorizedInstrument | undefined {
|
|
263
|
+
return id ? INSTRUMENT_BY_ID.get(id) : undefined
|
|
264
|
+
}
|
|
265
|
+
export function getProductionStyle(id: string | undefined): InstrumentationEntry | undefined {
|
|
266
|
+
return id ? PRODUCTION_BY_ID.get(id) : undefined
|
|
267
|
+
}
|
|
268
|
+
export function getVocalPresence(id: string | undefined): InstrumentationEntry | undefined {
|
|
269
|
+
return id ? VOCAL_BY_ID.get(id) : undefined
|
|
270
|
+
}
|
|
271
|
+
export function getSingingStyle(id: string | undefined): InstrumentationEntry | undefined {
|
|
272
|
+
return id ? SINGING_STYLE_BY_ID.get(id) : undefined
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
import { pickIds } from "@nodaro/shared"
|
|
276
|
+
|
|
277
|
+
export function buildInstrumentationHints(data: {
|
|
278
|
+
readonly preText?: string
|
|
279
|
+
readonly postText?: string
|
|
280
|
+
readonly instruments?: ReadonlyArray<string>
|
|
281
|
+
readonly production?: string
|
|
282
|
+
readonly vocalPresence?: string | ReadonlyArray<string>
|
|
283
|
+
readonly singingStyle?: string | ReadonlyArray<string>
|
|
284
|
+
}): string {
|
|
285
|
+
const fragments: string[] = []
|
|
286
|
+
const pre = typeof data.preText === "string" ? data.preText.trim() : ""
|
|
287
|
+
if (pre) fragments.push(pre)
|
|
288
|
+
|
|
289
|
+
const segments: string[] = []
|
|
290
|
+
const prod = getProductionStyle(data.production)
|
|
291
|
+
if (prod) segments.push(prod.promptHint)
|
|
292
|
+
|
|
293
|
+
const insts = (data.instruments ?? [])
|
|
294
|
+
.map((id) => getInstrument(id))
|
|
295
|
+
.filter((x): x is CategorizedInstrument => !!x)
|
|
296
|
+
if (insts.length > 0) segments.push(insts.map((x) => x.promptHint).join(", "))
|
|
297
|
+
|
|
298
|
+
const vocalIds = pickIds(data.vocalPresence)
|
|
299
|
+
const vocalHints = vocalIds
|
|
300
|
+
.map((id) => getVocalPresence(id)?.promptHint)
|
|
301
|
+
.filter((h): h is string => !!h)
|
|
302
|
+
const vocalClause = vocalHints.join(", ")
|
|
303
|
+
|
|
304
|
+
const styleIds = pickIds(data.singingStyle)
|
|
305
|
+
const styleHints = styleIds
|
|
306
|
+
.map((id) => getSingingStyle(id)?.promptHint)
|
|
307
|
+
.filter((h): h is string => !!h)
|
|
308
|
+
const styleClause = styleHints.join(", ")
|
|
309
|
+
|
|
310
|
+
const result: string[] = []
|
|
311
|
+
if (segments.length > 0) result.push(segments.join(" "))
|
|
312
|
+
if (vocalClause) {
|
|
313
|
+
result.push(result.length > 0 ? `with ${vocalClause}` : vocalClause)
|
|
314
|
+
}
|
|
315
|
+
if (styleClause) {
|
|
316
|
+
result.push(result.length > 0 ? `in ${styleClause} style` : `${styleClause} style`)
|
|
317
|
+
}
|
|
318
|
+
if (result.length > 0) fragments.push(result.join(" "))
|
|
319
|
+
|
|
320
|
+
const post = typeof data.postText === "string" ? data.postText.trim() : ""
|
|
321
|
+
if (post) fragments.push(post)
|
|
322
|
+
|
|
323
|
+
return fragments.join(", ")
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
export function isInstrumentalVocal(value: unknown): boolean {
|
|
327
|
+
return pickIds(value).includes(VOCAL_PRESENCE_INSTRUMENTAL_ID)
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
export const INSTRUMENTATION_DEFAULT_DATA: {
|
|
331
|
+
preText?: string
|
|
332
|
+
postText?: string
|
|
333
|
+
instruments?: ReadonlyArray<string>
|
|
334
|
+
production?: string
|
|
335
|
+
vocalPresence?: string | ReadonlyArray<string>
|
|
336
|
+
singingStyle?: string | ReadonlyArray<string>
|
|
337
|
+
} = { instruments: [] }
|
package/src/lens.ts
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Canonical catalog of lens / focal length choices.
|
|
3
|
+
*
|
|
4
|
+
* Optics dimension of a shot — focal length and depth-of-field character. Independent
|
|
5
|
+
* of framing (which captures shot size and composition) and camera motion (which captures
|
|
6
|
+
* how the camera moves). A close-up at 24mm looks completely different from a close-up
|
|
7
|
+
* at 200mm — the lens choice carries that intent.
|
|
8
|
+
*
|
|
9
|
+
* Shared between the picker UI and the prompt-hint injection on both the
|
|
10
|
+
* frontend DAG executor and the backend orchestrator.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
export interface Lens {
|
|
14
|
+
readonly id: string
|
|
15
|
+
readonly label: string
|
|
16
|
+
readonly description: string
|
|
17
|
+
readonly promptHint: string
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export const LENSES: ReadonlyArray<Lens> = [
|
|
21
|
+
{ id: "ultra-wide-14mm", label: "Ultra-wide (14mm)", description: "Extreme wide angle, exaggerated perspective", promptHint: "shot on ultra-wide 14mm lens, exaggerated perspective with strong barrel distortion" },
|
|
22
|
+
{ id: "wide-24mm", label: "Wide (24mm)", description: "Wide field of view, environmental", promptHint: "shot on wide 24mm lens, expansive environmental field of view" },
|
|
23
|
+
{ id: "standard-35mm", label: "Standard (35mm)", description: "Natural perspective, documentary feel", promptHint: "shot on standard 35mm lens, natural perspective with documentary feel" },
|
|
24
|
+
{ id: "normal-50mm", label: "Normal (50mm)", description: "Closest to human eye perception", promptHint: "shot on normal 50mm lens, perspective closest to natural human vision" },
|
|
25
|
+
{ id: "portrait-85mm", label: "Portrait (85mm)", description: "Flattering compression, creamy bokeh", promptHint: "shot on 85mm portrait lens, flattering facial compression with creamy background bokeh" },
|
|
26
|
+
{ id: "telephoto-135mm", label: "Telephoto (135mm)", description: "Compressed depth, isolated subject", promptHint: "shot on 135mm telephoto lens, compressed depth with subject isolated from background" },
|
|
27
|
+
{ id: "super-telephoto-400mm", label: "Super Telephoto (400mm)", description: "Extreme compression, distant subject", promptHint: "shot on super-telephoto 400mm lens, extreme depth compression with subject pulled forward" },
|
|
28
|
+
{ id: "fisheye", label: "Fisheye", description: "Hemispherical 180° distortion", promptHint: "shot on fisheye lens, extreme 180-degree hemispherical distortion with curved horizon" },
|
|
29
|
+
{ id: "anamorphic", label: "Anamorphic", description: "Cinematic widescreen, oval bokeh", promptHint: "anamorphic lens look, cinematic widescreen feel with characteristic oval bokeh and horizontal lens flares" },
|
|
30
|
+
{ id: "macro", label: "Macro", description: "Extreme close-up of small detail", promptHint: "macro lens, extreme close-up revealing fine detail with shallow depth of field" },
|
|
31
|
+
{ id: "probe", label: "Probe Lens", description: "Tube macro — through holes and tight spaces", promptHint: "probe lens shot, tube-lens macro perspective gliding through impossibly tight spaces with extreme close-up depth" },
|
|
32
|
+
{ id: "cctv", label: "CCTV", description: "Security-camera surveillance look", promptHint: "CCTV security camera footage look, high-angle fixed surveillance framing, mild wide-angle distortion, washed contrast and visible video grain" },
|
|
33
|
+
{ id: "tilt-shift", label: "Tilt-shift", description: "Selective focus, miniature effect", promptHint: "tilt-shift lens, selective plane of focus producing a miniature-diorama effect" },
|
|
34
|
+
{ id: "shallow-dof", label: "Shallow DOF", description: "Razor-thin focus, dreamy bokeh", promptHint: "extremely shallow depth of field, razor-thin focal plane with dreamy out-of-focus bokeh" },
|
|
35
|
+
{ id: "canon-k35", label: "Canon K35 Prime", description: "Vintage cinematic, warm gentle skin", promptHint: "shot on a vintage Canon K35 cinema prime, warm gentle skin rendition, low-contrast highlight roll-off, soft dreamy falloff into the bokeh and the unmistakable seventies-era cinematic patina" },
|
|
36
|
+
{ id: "cooke-s4", label: "Cooke S4 Prime", description: "The Cooke look — creamy painterly skin", promptHint: "shot on a Cooke S4 cinema prime, the signature \"Cooke look\" with creamy painterly bokeh, gently rounded out-of-focus highlights and a flattering filmic skin rendition" },
|
|
37
|
+
{ id: "helios-44", label: "Helios 44", description: "Vintage Soviet swirly bokeh", promptHint: "shot on a vintage Soviet Helios 44 lens, the legendary swirly bokeh circling the subject, soft low contrast in the corners and a dreamlike vintage aberration character" },
|
|
38
|
+
{ id: "petzval", label: "Petzval Portrait", description: "Ultra-vintage swirl, dramatic falloff", promptHint: "shot on an ultra-vintage Petzval portrait lens, sharp central focus that falls off rapidly into a swirling, painterly bokeh, dramatic vignetting and a 19th-century daguerreotype-era softness at the edges" },
|
|
39
|
+
] as const
|
|
40
|
+
|
|
41
|
+
const lensById = new Map<string, Lens>(LENSES.map((l) => [l.id, l]))
|
|
42
|
+
|
|
43
|
+
export function getLens(id: string | undefined | null): Lens | undefined {
|
|
44
|
+
if (!id) return undefined
|
|
45
|
+
return lensById.get(id)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export function getLensLabel(id: string | undefined | null, fallback?: string): string {
|
|
49
|
+
const l = getLens(id)
|
|
50
|
+
if (l) return l.label
|
|
51
|
+
if (fallback !== undefined) return fallback
|
|
52
|
+
return (id ?? "").replace(/-/g, " ").replace(/\b\w/g, (c) => c.toUpperCase())
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export function getLensPromptHint(id: string | undefined | null): string {
|
|
56
|
+
return getLens(id)?.promptHint ?? ""
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export const LENS_IDS: ReadonlyArray<string> = LENSES.map((l) => l.id)
|