@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.
Files changed (150) hide show
  1. package/LICENSE +105 -0
  2. package/README.md +27 -0
  3. package/dist/index.cjs +21240 -0
  4. package/dist/index.cjs.map +1 -0
  5. package/dist/index.d.cts +3599 -0
  6. package/dist/index.d.ts +3599 -0
  7. package/dist/index.js +20854 -0
  8. package/dist/index.js.map +1 -0
  9. package/package.json +49 -0
  10. package/src/__tests__/__snapshots__/prompt-builder-segments.test.ts.snap +65 -0
  11. package/src/__tests__/action-fx.test.ts +155 -0
  12. package/src/__tests__/apply-picker-json.test.ts +50 -0
  13. package/src/__tests__/assemble-image-input.test.ts +248 -0
  14. package/src/__tests__/assemble-suno-input.test.ts +283 -0
  15. package/src/__tests__/brand-tokens.test.ts +81 -0
  16. package/src/__tests__/build-image-prompt-element-injection.test.ts +118 -0
  17. package/src/__tests__/build-image-prompt-hybrid-format.test.ts +131 -0
  18. package/src/__tests__/build-image-prompt-mentions.test.ts +809 -0
  19. package/src/__tests__/build-image-prompt-reference-cap.test.ts +57 -0
  20. package/src/__tests__/build-image-prompt-reference-numbering.test.ts +237 -0
  21. package/src/__tests__/build-image-prompt-reference-order.test.ts +313 -0
  22. package/src/__tests__/camera-motions-from-connections.test.ts +71 -0
  23. package/src/__tests__/catalog-gapfill.test.ts +53 -0
  24. package/src/__tests__/character-convergence-image.test.ts +217 -0
  25. package/src/__tests__/character-default-role-image.test.ts +167 -0
  26. package/src/__tests__/character-default-role-video.test.ts +168 -0
  27. package/src/__tests__/character-default-role.test.ts +70 -0
  28. package/src/__tests__/character-fx.test.ts +200 -0
  29. package/src/__tests__/entity-prompts-location.test.ts +97 -0
  30. package/src/__tests__/entity-prompts.test.ts +240 -0
  31. package/src/__tests__/expand-extra-refs-role.test.ts +50 -0
  32. package/src/__tests__/factory-presets.test.ts +1045 -0
  33. package/src/__tests__/factory-snippets.test.ts +68 -0
  34. package/src/__tests__/framing-multi.test.ts +71 -0
  35. package/src/__tests__/framing-vantage.test.ts +39 -0
  36. package/src/__tests__/i18n-entry-completeness.test.ts +269 -0
  37. package/src/__tests__/identity-lock.test.ts +46 -0
  38. package/src/__tests__/instrumentation.test.ts +68 -0
  39. package/src/__tests__/lighting-multi.test.ts +68 -0
  40. package/src/__tests__/location-convergence-image.test.ts +124 -0
  41. package/src/__tests__/mention-lock-flag.test.ts +499 -0
  42. package/src/__tests__/multi-picker-spec.test.ts +71 -0
  43. package/src/__tests__/music-genre.test.ts +103 -0
  44. package/src/__tests__/music-mood.test.ts +87 -0
  45. package/src/__tests__/object-creature-convergence-image.test.ts +105 -0
  46. package/src/__tests__/parameter-prompt-hint.test.ts +270 -0
  47. package/src/__tests__/parameter-registry-sync.test.ts +243 -0
  48. package/src/__tests__/person-age.test.ts +80 -0
  49. package/src/__tests__/person-analyzer-invariants.test.ts +47 -0
  50. package/src/__tests__/person-body-axes.test.ts +67 -0
  51. package/src/__tests__/person-facial-geometry.test.ts +156 -0
  52. package/src/__tests__/person-regional-aesthetic.test.ts +161 -0
  53. package/src/__tests__/person-sections.test.ts +18 -0
  54. package/src/__tests__/picker-analyzer-registry.test.ts +108 -0
  55. package/src/__tests__/picker-catalogs-project.test.ts +85 -0
  56. package/src/__tests__/picker-catalogs.test.ts +53 -0
  57. package/src/__tests__/picker-limits.test.ts +20 -0
  58. package/src/__tests__/prompt-builder-segments.test.ts +183 -0
  59. package/src/__tests__/prompt-builder-structured-fields.test.ts +40 -0
  60. package/src/__tests__/prompt-builder.test.ts +1773 -0
  61. package/src/__tests__/prompt-wizard-categories.test.ts +31 -0
  62. package/src/__tests__/provider-prompt-doctrine.test.ts +49 -0
  63. package/src/__tests__/resolve-prompt-append.test.ts +58 -0
  64. package/src/__tests__/resolve-prompt.test.ts +44 -0
  65. package/src/__tests__/role-picker-shared.test.ts +208 -0
  66. package/src/__tests__/seedance-2-inputs.test.ts +173 -0
  67. package/src/__tests__/seedance-extend.test.ts +44 -0
  68. package/src/__tests__/sound-aggregator.test.ts +350 -0
  69. package/src/__tests__/style-presets.test.ts +34 -0
  70. package/src/__tests__/temporal-multi.test.ts +74 -0
  71. package/src/__tests__/transitions.test.ts +213 -0
  72. package/src/__tests__/video-reference-features.test.ts +41 -0
  73. package/src/__tests__/video-reference-leading-refs.test.ts +90 -0
  74. package/src/__tests__/video-reference-resolver.test.ts +233 -0
  75. package/src/__tests__/video-reference-roles.test.ts +96 -0
  76. package/src/__tests__/voice-character.test.ts +48 -0
  77. package/src/__tests__/voice-delivery.test.ts +41 -0
  78. package/src/__tests__/wardrobe.test.ts +25 -0
  79. package/src/action-fx.ts +255 -0
  80. package/src/aesthetic.ts +435 -0
  81. package/src/assemble-image-input.ts +236 -0
  82. package/src/assemble-suno-input.ts +147 -0
  83. package/src/atmosphere.ts +104 -0
  84. package/src/backdrop.ts +131 -0
  85. package/src/brand-tokens.ts +154 -0
  86. package/src/camera-format.ts +76 -0
  87. package/src/camera-motions.ts +615 -0
  88. package/src/character-fx.ts +274 -0
  89. package/src/color-look.ts +103 -0
  90. package/src/composition-effects.ts +67 -0
  91. package/src/entity-prompts.ts +231 -0
  92. package/src/era.ts +292 -0
  93. package/src/exposure-settings.ts +142 -0
  94. package/src/factory-presets/generate-image.ts +1644 -0
  95. package/src/factory-presets/generate-video.ts +1116 -0
  96. package/src/factory-presets/index.ts +46 -0
  97. package/src/factory-presets/lottie-overlay.ts +166 -0
  98. package/src/factory-presets/motion-graphics.ts +350 -0
  99. package/src/factory-presets/music.ts +734 -0
  100. package/src/factory-presets/sfx.ts +136 -0
  101. package/src/factory-presets/shared-image.ts +207 -0
  102. package/src/factory-presets/switchx.ts +65 -0
  103. package/src/factory-presets/text.ts +292 -0
  104. package/src/factory-presets/types.ts +51 -0
  105. package/src/factory-presets/video-edit.ts +136 -0
  106. package/src/factory-presets/voice.ts +172 -0
  107. package/src/factory-presets.ts +2 -0
  108. package/src/factory-snippets/catalog.ts +105 -0
  109. package/src/factory-snippets/index.ts +16 -0
  110. package/src/factory-snippets/types.ts +33 -0
  111. package/src/framing.ts +634 -0
  112. package/src/held-prop.ts +187 -0
  113. package/src/identity-lock.ts +213 -0
  114. package/src/index.ts +66 -0
  115. package/src/instrumentation.ts +337 -0
  116. package/src/lens.ts +59 -0
  117. package/src/lighting.ts +229 -0
  118. package/src/loop-subject.ts +276 -0
  119. package/src/materials.ts +184 -0
  120. package/src/mood.ts +186 -0
  121. package/src/music-genre.ts +662 -0
  122. package/src/music-mood.ts +137 -0
  123. package/src/object-asset-presets.ts +81 -0
  124. package/src/parameter-prompt-hint.ts +281 -0
  125. package/src/person.ts +1368 -0
  126. package/src/photo-genre.ts +151 -0
  127. package/src/photographer.ts +612 -0
  128. package/src/picker-analyzer-registry.ts +374 -0
  129. package/src/picker-catalogs.ts +858 -0
  130. package/src/pose.ts +246 -0
  131. package/src/post-process-effects.ts +94 -0
  132. package/src/prompt-builder-structured-fields.ts +116 -0
  133. package/src/prompt-builder.ts +2964 -0
  134. package/src/prompt-templates.ts +50 -0
  135. package/src/prompt-wizard-categories.ts +334 -0
  136. package/src/provider-prompt-doctrine.ts +85 -0
  137. package/src/render-quality.ts +89 -0
  138. package/src/resolve-prompt.ts +120 -0
  139. package/src/seedance-2-inputs.ts +100 -0
  140. package/src/setting.ts +130 -0
  141. package/src/sound-aggregator.ts +241 -0
  142. package/src/style-presets.ts +162 -0
  143. package/src/style.ts +99 -0
  144. package/src/styling.ts +585 -0
  145. package/src/temporal.ts +151 -0
  146. package/src/transitions.ts +333 -0
  147. package/src/video-reference-resolver.ts +823 -0
  148. package/src/voice-character.ts +237 -0
  149. package/src/voice-delivery.ts +142 -0
  150. package/src/wardrobe.ts +179 -0
@@ -0,0 +1,292 @@
1
+ import type { FactoryPreset } from "./types.js"
2
+
3
+ export const LLM_CHAT_PRESETS: readonly FactoryPreset[] = [
4
+ // ── Assistants ───────────────────────────────────────────────────────────
5
+ {
6
+ id: "llm-chat/concise-assistant",
7
+ name: "Concise Assistant",
8
+ description: "Short, direct answers.",
9
+ group: "Assistants",
10
+ data: {
11
+ systemPrompt: "You are a concise assistant. Answer in 1-3 sentences. No preamble.",
12
+ temperature: 0.3,
13
+ },
14
+ },
15
+ {
16
+ id: "llm-chat/brainstorm",
17
+ name: "Brainstorm / Ideas",
18
+ description: "10 diverse ideas, high variety.",
19
+ group: "Assistants",
20
+ data: {
21
+ systemPrompt:
22
+ "You are a creative brainstorming partner. Given a topic, return a numbered list of 10 diverse, original ideas. No preamble, no explanations.",
23
+ temperature: 1,
24
+ },
25
+ },
26
+
27
+ // ── Writing & Marketing ──────────────────────────────────────────────────
28
+ {
29
+ id: "llm-chat/copywriter",
30
+ name: "Copywriter / Headlines",
31
+ description: "Punchy marketing copy.",
32
+ group: "Writing & Marketing",
33
+ data: {
34
+ systemPrompt:
35
+ "You are an expert direct-response copywriter. Write punchy, persuasive, benefit-led copy. When asked for headlines, return 5 distinct options as a list.",
36
+ temperature: 0.8,
37
+ },
38
+ },
39
+ {
40
+ id: "llm-chat/social-caption",
41
+ name: "Social Caption + Hashtags",
42
+ description: "Caption then hashtags.",
43
+ group: "Writing & Marketing",
44
+ data: {
45
+ systemPrompt:
46
+ "Write one engaging social-media caption for the user's topic, then on a new line add 8-12 relevant hashtags. Match a modern, friendly tone.",
47
+ temperature: 0.8,
48
+ },
49
+ },
50
+ {
51
+ id: "llm-chat/seo-metadata",
52
+ name: "SEO Metadata",
53
+ description: "Title, meta, keywords.",
54
+ group: "Writing & Marketing",
55
+ data: {
56
+ systemPrompt:
57
+ "Generate SEO metadata for the user's topic: a title (<=60 chars), a meta description (<=155 chars), and 8 keywords. Label each section.",
58
+ temperature: 0.4,
59
+ },
60
+ },
61
+ {
62
+ id: "llm-chat/rewrite-tone",
63
+ name: "Rewrite / Tone Shifter",
64
+ description: "Restyle text, keep meaning.",
65
+ group: "Writing & Marketing",
66
+ data: {
67
+ systemPrompt:
68
+ "Rewrite the user's text in the requested tone (e.g. formal, casual, friendly, confident). Preserve the meaning. Return only the rewrite.",
69
+ temperature: 0.5,
70
+ },
71
+ },
72
+ {
73
+ id: "llm-chat/script-writer",
74
+ name: "Script / Storyboard Writer",
75
+ description: "Shot-by-shot video script.",
76
+ group: "Writing & Marketing",
77
+ data: {
78
+ systemPrompt:
79
+ "You are a short-form video scriptwriter. Turn the user's idea into a shot-by-shot script. For each shot give: Scene, Visual, Voiceover. Keep it tight and production-ready.",
80
+ temperature: 0.7,
81
+ },
82
+ },
83
+
84
+ // ── Utility ──────────────────────────────────────────────────────────────
85
+ {
86
+ id: "llm-chat/prompt-enhancer",
87
+ name: "Prompt Enhancer",
88
+ description: "Idea → rich image prompt.",
89
+ group: "Utility",
90
+ data: {
91
+ systemPrompt:
92
+ "Expand the user's short idea into a single rich, vivid image-generation prompt covering subject, setting, lighting, composition, lens and style. Return only the prompt, no preamble.",
93
+ temperature: 0.8,
94
+ },
95
+ },
96
+ {
97
+ id: "llm-chat/translator",
98
+ name: "Translator",
99
+ description: "Translate, preserve tone.",
100
+ group: "Utility",
101
+ data: {
102
+ systemPrompt:
103
+ "Translate the user's text into the requested target language, preserving tone and meaning. Return only the translation.",
104
+ temperature: 0.2,
105
+ },
106
+ },
107
+ {
108
+ id: "llm-chat/summarizer",
109
+ name: "Summarizer (TL;DR)",
110
+ description: "3-5 bullet summary.",
111
+ group: "Utility",
112
+ data: {
113
+ systemPrompt: "Summarize the user's text into 3-5 concise bullet points capturing the key takeaways. No preamble.",
114
+ temperature: 0.2,
115
+ },
116
+ },
117
+ {
118
+ id: "llm-chat/qa-context",
119
+ name: "Q&A over Context",
120
+ description: "Grounded answers only.",
121
+ group: "Utility",
122
+ data: {
123
+ systemPrompt:
124
+ "Answer the user's question using ONLY the provided context. If the answer is not in the context, say you don't know rather than guessing.",
125
+ temperature: 0.1,
126
+ },
127
+ },
128
+
129
+ // ── Structured Output ────────────────────────────────────────────────────
130
+ {
131
+ id: "llm-chat/json-extractor",
132
+ name: "JSON Extractor",
133
+ description: "Returns strict JSON only.",
134
+ group: "Structured Output",
135
+ data: {
136
+ systemPrompt:
137
+ "Extract the requested fields and return ONLY valid minified JSON. No prose, no code fences.",
138
+ temperature: 0,
139
+ },
140
+ },
141
+ {
142
+ id: "llm-chat/classifier",
143
+ name: "Classifier / Sentiment",
144
+ description: "Returns one label.",
145
+ group: "Structured Output",
146
+ data: {
147
+ systemPrompt:
148
+ "Classify the user's input. Return ONLY a single label from the allowed set (default: positive / neutral / negative). No explanation.",
149
+ temperature: 0,
150
+ },
151
+ },
152
+ ]
153
+
154
+ export const GENERATE_SCRIPT_PRESETS: readonly FactoryPreset[] = [
155
+ // ── By Format ────────────────────────────────────────────────────────────
156
+ {
157
+ id: "generate-script/yt-short",
158
+ name: "YouTube Short / Hook",
159
+ description: "Punchy, hook-first, ~30s.",
160
+ group: "By Format",
161
+ data: { tone: "energetic, punchy, hook-first", sceneCount: 5, targetLength: 30, structure: "freeform" },
162
+ },
163
+ {
164
+ id: "generate-script/explainer",
165
+ name: "Explainer (how-to)",
166
+ description: "Clear 8-step walkthrough.",
167
+ group: "By Format",
168
+ data: { tone: "clear, friendly, educational", sceneCount: 8, targetLength: 90, structure: "8-step" },
169
+ },
170
+ {
171
+ id: "generate-script/ad-spot",
172
+ name: "Ad / Commercial Spot",
173
+ description: "Persuasive 30s spot.",
174
+ group: "By Format",
175
+ data: { tone: "persuasive, upbeat, benefit-led", sceneCount: 4, targetLength: 30, structure: "freeform" },
176
+ },
177
+ {
178
+ id: "generate-script/product-demo",
179
+ name: "Product Demo VO",
180
+ description: "Confident feature walkthrough.",
181
+ group: "By Format",
182
+ data: { tone: "confident, informative", sceneCount: 6, targetLength: 60, structure: "freeform" },
183
+ },
184
+ {
185
+ id: "generate-script/listicle",
186
+ name: "Listicle (Top 5)",
187
+ description: "Snappy countdown.",
188
+ group: "By Format",
189
+ data: { tone: "engaging, energetic", sceneCount: 6, targetLength: 60, structure: "freeform" },
190
+ },
191
+ {
192
+ id: "generate-script/ugc-ad",
193
+ name: "UGC Ad (Hook–Show–Proof–Opinion)",
194
+ description: "Selfie-style product testimonial.",
195
+ group: "By Format",
196
+ data: {
197
+ tone: "casual, authentic, conversational",
198
+ sceneCount: 4,
199
+ targetLength: 30,
200
+ structure: "freeform",
201
+ styleGuide:
202
+ "Selfie-style UGC testimonial for {product}. Structure: Hook (stop the scroll) → Show (the product in real use) → Proof (a concrete result or detail) → Opinion (a genuine personal take). A real person sharing a real opinion — first-person, natural, unpolished. Short spoken sentences for clean lip-sync; no salesy voiceover.",
203
+ },
204
+ },
205
+
206
+ // ── Long-Form & Narrative ────────────────────────────────────────────────
207
+ {
208
+ id: "generate-script/podcast-outline",
209
+ name: "Podcast Outline",
210
+ description: "Conversational episode beats.",
211
+ group: "Long-Form & Narrative",
212
+ data: { tone: "conversational, curious", sceneCount: 10, targetLength: 600, structure: "freeform" },
213
+ },
214
+ {
215
+ id: "generate-script/trailer-narration",
216
+ name: "Trailer Narration",
217
+ description: "Dramatic voiceover beats.",
218
+ group: "Long-Form & Narrative",
219
+ data: { tone: "dramatic, epic", sceneCount: 6, targetLength: 60, structure: "freeform" },
220
+ },
221
+ {
222
+ id: "generate-script/story-beats",
223
+ name: "Story Beats",
224
+ description: "Emotional narrative arc.",
225
+ group: "Long-Form & Narrative",
226
+ data: { tone: "narrative, emotional", sceneCount: 8, targetLength: 120, structure: "8-step" },
227
+ },
228
+ ]
229
+
230
+ export const IMAGE_TO_TEXT_PRESETS: readonly FactoryPreset[] = [
231
+ // ── Accessibility & SEO ──────────────────────────────────────────────────
232
+ {
233
+ id: "image-to-text/alt-text",
234
+ name: "Alt Text",
235
+ description: "Accessible, ≤125 chars.",
236
+ group: "Accessibility & SEO",
237
+ data: { detailLevel: "brief", customPrompt: "Write concise alt text for this image for accessibility, under 125 characters. Describe only what is essential." },
238
+ },
239
+ {
240
+ id: "image-to-text/seo-caption",
241
+ name: "SEO Caption",
242
+ description: "Caption + keywords.",
243
+ group: "Accessibility & SEO",
244
+ data: { detailLevel: "detailed", customPrompt: "Write an SEO-friendly caption for this image, then list 8 relevant keywords." },
245
+ },
246
+ {
247
+ id: "image-to-text/social-caption",
248
+ name: "Social Caption",
249
+ description: "Caption + hashtags.",
250
+ group: "Accessibility & SEO",
251
+ data: { detailLevel: "detailed", customPrompt: "Write an engaging social-media caption for this image, then 8-12 relevant hashtags." },
252
+ },
253
+
254
+ // ── Extraction ───────────────────────────────────────────────────────────
255
+ {
256
+ id: "image-to-text/ocr",
257
+ name: "Extract Text (OCR)",
258
+ description: "Return only visible text.",
259
+ group: "Extraction",
260
+ data: { detailLevel: "structured", customPrompt: "Extract and return ONLY the text visible in this image, preserving line breaks. No commentary." },
261
+ },
262
+ {
263
+ id: "image-to-text/tags",
264
+ name: "Tags / Keywords",
265
+ description: "Comma-separated tags.",
266
+ group: "Extraction",
267
+ data: { detailLevel: "brief", customPrompt: "List 10-15 descriptive tags for this image, comma-separated. No sentences." },
268
+ },
269
+ {
270
+ id: "image-to-text/product-desc",
271
+ name: "Product Description",
272
+ description: "E-commerce copy from a photo.",
273
+ group: "Extraction",
274
+ data: { detailLevel: "detailed", customPrompt: "Write a compelling e-commerce product description based on this product image." },
275
+ },
276
+
277
+ // ── Creative ─────────────────────────────────────────────────────────────
278
+ {
279
+ id: "image-to-text/scene-description",
280
+ name: "Detailed Description",
281
+ description: "Vivid prose description.",
282
+ group: "Creative",
283
+ data: { detailLevel: "detailed", customPrompt: "Provide a vivid, comprehensive description of this image: subjects, setting, lighting, mood and composition, in flowing prose." },
284
+ },
285
+ {
286
+ id: "image-to-text/reverse-prompt",
287
+ name: "Reverse Prompt",
288
+ description: "Image → text-to-image prompt.",
289
+ group: "Creative",
290
+ data: { detailLevel: "detailed", customPrompt: "Describe this image as a detailed text-to-image generation prompt: subject, style, lighting, composition and lens. Return only the prompt." },
291
+ },
292
+ ]
@@ -0,0 +1,51 @@
1
+ export interface FactoryPreset {
2
+ /** Stable slug "<nodeType>/<kebab-name>" — used as a React key and in exports. */
3
+ readonly id: string
4
+ readonly name: string
5
+ readonly description?: string
6
+ /** Optional folder/section label this preset is grouped under in the picker.
7
+ * Presets sharing a `group` render together; "variants of one idea" (e.g. the
8
+ * character-sheet family) are simply siblings in the same group. */
9
+ readonly group?: string
10
+ /** How the group renders: a collapsible "folder" (default) or a flat "section"
11
+ * label. Taken from the first preset that opens the group. */
12
+ readonly groupKind?: "folder" | "section"
13
+ /** Capture-shaped config (no label / fieldMappings / runtime keys). */
14
+ readonly data: Readonly<Record<string, unknown>>
15
+ }
16
+
17
+ /** A render-ready bucket of factory presets sharing one `group` (or the leading
18
+ * ungrouped bucket, `group: null`). Produced by {@link groupFactoryPresets}. */
19
+ export interface FactoryPresetGroup<T> {
20
+ /** Stable key for React + collapse state ("__root__" for the ungrouped bucket). */
21
+ readonly key: string
22
+ /** Group label, or null for the ungrouped bucket. */
23
+ readonly group: string | null
24
+ readonly groupKind: "folder" | "section"
25
+ readonly presets: T[]
26
+ }
27
+
28
+ /**
29
+ * Bucket an ordered list of presets by their `group` field for rendering. Groups
30
+ * appear in first-appearance order; presets keep their array order within a
31
+ * group; ungrouped presets collect into a single leading `null` bucket. Pure and
32
+ * UI-agnostic (operates on anything carrying `group`/`groupKind`) so the config
33
+ * panel dropdown reuses it and it stays unit-testable.
34
+ */
35
+ export function groupFactoryPresets<
36
+ T extends { group?: string; groupKind?: "folder" | "section" },
37
+ >(presets: readonly T[]): FactoryPresetGroup<T>[] {
38
+ const buckets: FactoryPresetGroup<T>[] = []
39
+ const byKey = new Map<string, FactoryPresetGroup<T>>()
40
+ for (const p of presets) {
41
+ const key = p.group ?? "__root__"
42
+ let bucket = byKey.get(key)
43
+ if (!bucket) {
44
+ bucket = { key, group: p.group ?? null, groupKind: p.groupKind ?? "folder", presets: [] }
45
+ byKey.set(key, bucket)
46
+ buckets.push(bucket)
47
+ }
48
+ bucket.presets.push(p)
49
+ }
50
+ return buckets
51
+ }
@@ -0,0 +1,136 @@
1
+ import type { FactoryPreset } from "./types.js"
2
+
3
+ export const VIDEO_TO_VIDEO_PRESETS: readonly FactoryPreset[] = [
4
+ {
5
+ id: "video-to-video/anime",
6
+ name: "Anime Restyle",
7
+ description: "2D cel-shaded anime look.",
8
+ group: "Restyle Looks",
9
+ data: { provider: "wan", prompt: "Restyle this video as a 2D cel-shaded anime: vibrant colors, clean linework, expressive cel shading. Preserve the original motion, composition, and timing.", negativePrompt: "photorealistic, blurry, distorted, flickering" },
10
+ },
11
+ {
12
+ id: "video-to-video/claymation",
13
+ name: "Claymation",
14
+ description: "Tactile stop-motion clay.",
15
+ group: "Restyle Looks",
16
+ data: { provider: "wan", prompt: "Restyle as tactile stop-motion claymation with plasticine textures and subtle fingerprints. Keep the original motion and framing.", negativePrompt: "photorealistic, smooth, flickering" },
17
+ },
18
+ {
19
+ id: "video-to-video/cyberpunk-neon",
20
+ name: "Cyberpunk Neon",
21
+ description: "Rain-slicked neon city look.",
22
+ group: "Restyle Looks",
23
+ data: { provider: "wan", prompt: "Restyle with a neon cyberpunk aesthetic: rain-slicked surfaces, glowing magenta and cyan lighting, moody atmosphere. Preserve the original motion.", negativePrompt: "daylight, flat lighting, blurry, distorted" },
24
+ },
25
+ {
26
+ id: "video-to-video/oil-painting",
27
+ name: "Oil Painting",
28
+ description: "Moving painterly brushwork.",
29
+ group: "Restyle Looks",
30
+ data: { provider: "wan", prompt: "Restyle as a moving oil painting with visible brushstrokes, rich impasto texture, and painterly color. Keep the original motion and composition.", negativePrompt: "photorealistic, flat, blurry, flickering" },
31
+ },
32
+ {
33
+ id: "video-to-video/pixar-3d",
34
+ name: "3D Animated",
35
+ description: "Polished CG film look.",
36
+ group: "Restyle Looks",
37
+ data: { provider: "wan", prompt: "Restyle as a polished 3D animated film: soft global illumination, expressive characters, clean stylized surfaces. Preserve the original motion and timing.", negativePrompt: "photorealistic, lowres, distorted, flickering" },
38
+ },
39
+ {
40
+ id: "video-to-video/watercolor",
41
+ name: "Watercolor",
42
+ description: "Flowing washes on paper.",
43
+ group: "Restyle Looks",
44
+ data: { provider: "wan", prompt: "Restyle as a flowing watercolor animation with soft washes, bleeding edges, and visible paper texture. Keep the original motion and composition.", negativePrompt: "photorealistic, harsh edges, blurry, flickering" },
45
+ },
46
+ ]
47
+
48
+ export const ADD_CAPTIONS_PRESETS: readonly FactoryPreset[] = [
49
+ {
50
+ id: "add-captions/clean-subtitles",
51
+ name: "Clean Subtitles",
52
+ description: "Classic bottom subtitles.",
53
+ group: "Caption Styles",
54
+ data: { style: "subtitle", position: "bottom", fontSize: 32, color: "#FFFFFF", autoTranscribe: true },
55
+ },
56
+ {
57
+ id: "add-captions/tiktok-bold",
58
+ name: "TikTok Bold",
59
+ description: "Big centered word-by-word.",
60
+ group: "Caption Styles",
61
+ data: { style: "tiktok-words", position: "center", fontSize: 72, color: "#FFFFFF", autoTranscribe: true },
62
+ },
63
+ {
64
+ id: "add-captions/karaoke",
65
+ name: "Karaoke Highlight",
66
+ description: "Words fill as spoken.",
67
+ group: "Caption Styles",
68
+ data: { style: "karaoke", position: "bottom", fontSize: 56, color: "#FFFFFF", autoTranscribe: true },
69
+ },
70
+ {
71
+ id: "add-captions/word-pop",
72
+ name: "Word Pop",
73
+ description: "Each word pops in.",
74
+ group: "Caption Styles",
75
+ data: { style: "word-pop", position: "center", fontSize: 64, color: "#FFE600", autoTranscribe: true },
76
+ },
77
+ {
78
+ id: "add-captions/bouncy",
79
+ name: "Bouncy Captions",
80
+ description: "Energetic bouncing words.",
81
+ group: "Caption Styles",
82
+ data: { style: "bouncy", position: "bottom", fontSize: 64, color: "#FFFFFF", autoTranscribe: true },
83
+ },
84
+ {
85
+ id: "add-captions/word-highlight",
86
+ name: "Word Highlight",
87
+ description: "Active word highlighted.",
88
+ group: "Caption Styles",
89
+ data: { style: "word-highlight", position: "bottom", fontSize: 48, color: "#00E5FF", autoTranscribe: true },
90
+ },
91
+ {
92
+ id: "add-captions/top-banner",
93
+ name: "Top Banner",
94
+ description: "Subtitles along the top.",
95
+ group: "Caption Styles",
96
+ data: { style: "subtitle", position: "top", fontSize: 36, color: "#FFFFFF", autoTranscribe: true },
97
+ },
98
+ ]
99
+
100
+ export const COMBINE_VIDEOS_PRESETS: readonly FactoryPreset[] = [
101
+ {
102
+ id: "combine-videos/seamless-join",
103
+ name: "Seamless Join (One-Shot)",
104
+ description: "Jump-free join for scene-extension / start-end-frame clips.",
105
+ group: "Joins & Transitions",
106
+ data: { transition: "cut", transitionDuration: 0.5, audioMode: "crossfade", audioCrossfadeCurve: "equal-power", trimEndFrames: 4, trimStartFrames: 3 },
107
+ },
108
+ {
109
+ id: "combine-videos/hard-cut",
110
+ name: "Hard Cut",
111
+ description: "Instant switch, no blend. Fastest.",
112
+ group: "Joins & Transitions",
113
+ data: { transition: "cut", audioMode: "keep", trimStartFrames: 0, trimEndFrames: 0 },
114
+ },
115
+ {
116
+ id: "combine-videos/crossfade",
117
+ name: "Crossfade",
118
+ description: "Smooth alpha cross-fade between clips.",
119
+ group: "Joins & Transitions",
120
+ data: { transition: "fade", transitionDuration: 0.7, audioMode: "crossfade", audioCrossfadeCurve: "equal-power" },
121
+ },
122
+ {
123
+ id: "combine-videos/dissolve",
124
+ name: "Dissolve",
125
+ description: "Grainy organic blend for memory beats.",
126
+ group: "Joins & Transitions",
127
+ data: { transition: "dissolve", transitionDuration: 1, audioMode: "crossfade", audioCrossfadeCurve: "equal-power" },
128
+ },
129
+ {
130
+ id: "combine-videos/fade-through-black",
131
+ name: "Fade Through Black",
132
+ description: "Dip to black between scenes.",
133
+ group: "Joins & Transitions",
134
+ data: { transition: "dip-to-black", transitionDuration: 1, audioMode: "crossfade", audioCrossfadeCurve: "equal-power" },
135
+ },
136
+ ]
@@ -0,0 +1,172 @@
1
+ import type { FactoryPreset } from "./types.js"
2
+
3
+ export const TEXT_TO_SPEECH_PRESETS: readonly FactoryPreset[] = [
4
+ // ── Narration ────────────────────────────────────────────────────────────
5
+ {
6
+ id: "text-to-speech/narrator-calm",
7
+ name: "Calm Narrator",
8
+ description: "Even, measured narration.",
9
+ group: "Narration",
10
+ data: { speed: 1, stability: 0.6, similarityBoost: 0.75, style: 0 },
11
+ },
12
+ {
13
+ id: "text-to-speech/audiobook",
14
+ name: "Audiobook",
15
+ description: "Warm, steady, slightly slower.",
16
+ group: "Narration",
17
+ data: { speed: 0.95, stability: 0.75, similarityBoost: 0.8, style: 0.1 },
18
+ },
19
+ {
20
+ id: "text-to-speech/documentary",
21
+ name: "Documentary",
22
+ description: "Measured delivery with gravitas.",
23
+ group: "Narration",
24
+ data: { speed: 0.95, stability: 0.78, similarityBoost: 0.85, style: 0.25 },
25
+ },
26
+ {
27
+ id: "text-to-speech/news-anchor",
28
+ name: "News Anchor",
29
+ description: "Neutral, authoritative, even pace.",
30
+ group: "Narration",
31
+ data: { speed: 1, stability: 0.7, similarityBoost: 0.8, style: 0.2 },
32
+ },
33
+ {
34
+ id: "text-to-speech/explainer",
35
+ name: "Explainer / Tutorial",
36
+ description: "Clear, friendly, mid-pace.",
37
+ group: "Narration",
38
+ data: { speed: 1, stability: 0.55, similarityBoost: 0.75, style: 0.3 },
39
+ },
40
+
41
+ // ── Advertising & Hype ───────────────────────────────────────────────────
42
+ {
43
+ id: "text-to-speech/commercial",
44
+ name: "Commercial Read",
45
+ description: "Energetic, persuasive, punchy.",
46
+ group: "Advertising & Hype",
47
+ data: { speed: 1.05, stability: 0.48, similarityBoost: 0.75, style: 0.6 },
48
+ },
49
+ {
50
+ id: "text-to-speech/hype",
51
+ name: "Hype / High-Energy",
52
+ description: "Fast, excited, dynamic.",
53
+ group: "Advertising & Hype",
54
+ data: { speed: 1.15, stability: 0.25, similarityBoost: 0.7, style: 0.8 },
55
+ },
56
+
57
+ // ── Conversational & Calm ────────────────────────────────────────────────
58
+ {
59
+ id: "text-to-speech/podcast-host",
60
+ name: "Podcast Host",
61
+ description: "Natural, casual, conversational.",
62
+ group: "Conversational & Calm",
63
+ data: { speed: 1.05, stability: 0.45, similarityBoost: 0.75, style: 0.4 },
64
+ },
65
+ {
66
+ id: "text-to-speech/character",
67
+ name: "Character / Storyteller",
68
+ description: "Expressive, dramatic range.",
69
+ group: "Conversational & Calm",
70
+ data: { speed: 1, stability: 0.3, similarityBoost: 0.7, style: 0.7 },
71
+ },
72
+ {
73
+ id: "text-to-speech/meditation",
74
+ name: "Meditation / ASMR",
75
+ description: "Very slow, soft, soothing.",
76
+ group: "Conversational & Calm",
77
+ data: { speed: 0.8, stability: 0.85, similarityBoost: 0.75, style: 0 },
78
+ },
79
+ ]
80
+
81
+ export const VOICE_DESIGN_PRESETS: readonly FactoryPreset[] = [
82
+ // ── Narration & Character ────────────────────────────────────────────────
83
+ {
84
+ id: "voice-design/trailer-narrator",
85
+ name: "Movie-Trailer Narrator",
86
+ description: "Deep, dramatic, commanding.",
87
+ group: "Narration & Character",
88
+ data: { voiceDescription: "A deep, powerful male movie-trailer narrator with dramatic gravitas and a slow, commanding delivery." },
89
+ },
90
+ {
91
+ id: "voice-design/audiobook-female",
92
+ name: "Warm Female Audiobook",
93
+ description: "Soothing, clear, intimate.",
94
+ group: "Narration & Character",
95
+ data: { voiceDescription: "A warm, soothing female audiobook narrator with clear articulation and a gentle, intimate tone." },
96
+ },
97
+ {
98
+ id: "voice-design/old-wizard",
99
+ name: "Old Wizard",
100
+ description: "Gravelly, wise, theatrical.",
101
+ group: "Narration & Character",
102
+ data: { voiceDescription: "A gravelly, wise old wizard with a deep raspy voice and a slow, theatrical cadence." },
103
+ },
104
+ {
105
+ id: "voice-design/noir-detective",
106
+ name: "Noir Detective",
107
+ description: "Raspy, smoky, brooding.",
108
+ group: "Narration & Character",
109
+ data: { voiceDescription: "A raspy, world-weary noir detective with a low, smoky, brooding voice." },
110
+ },
111
+ {
112
+ id: "voice-design/meditation-guide",
113
+ name: "Meditation Guide",
114
+ description: "Calm, soft, breathy.",
115
+ group: "Narration & Character",
116
+ data: { voiceDescription: "A calm, soft-spoken meditation guide with a slow, breathy, reassuring delivery." },
117
+ },
118
+
119
+ // ── Professional & Assistant ─────────────────────────────────────────────
120
+ {
121
+ id: "voice-design/hype-announcer",
122
+ name: "Energetic Hype",
123
+ description: "Fast, excited, punchy.",
124
+ group: "Professional & Assistant",
125
+ data: { voiceDescription: "An energetic young hype announcer: fast-paced, excited and punchy." },
126
+ },
127
+ {
128
+ id: "voice-design/friendly-assistant",
129
+ name: "Friendly Assistant",
130
+ description: "Bright, clear, approachable.",
131
+ group: "Professional & Assistant",
132
+ data: { voiceDescription: "A bright, friendly, professional virtual-assistant voice, clear and approachable." },
133
+ },
134
+ {
135
+ id: "voice-design/corporate-ivr",
136
+ name: "Corporate IVR",
137
+ description: "Neutral, articulate, pro.",
138
+ group: "Professional & Assistant",
139
+ data: { voiceDescription: "A neutral, clear corporate phone-system voice, articulate and professional." },
140
+ },
141
+ ]
142
+
143
+ export const VOICE_CHANGER_PRESETS: readonly FactoryPreset[] = [
144
+ {
145
+ id: "voice-changer/faithful",
146
+ name: "Faithful (Natural)",
147
+ description: "Preserves original delivery.",
148
+ group: "Revoice Styles",
149
+ data: { stability: 0.4, similarityBoost: 0.85, style: 0, removeBackgroundNoise: false },
150
+ },
151
+ {
152
+ id: "voice-changer/clean-stable",
153
+ name: "Clean & Stable",
154
+ description: "Smooth, consistent, denoised.",
155
+ group: "Revoice Styles",
156
+ data: { stability: 0.8, similarityBoost: 0.8, style: 0, removeBackgroundNoise: true },
157
+ },
158
+ {
159
+ id: "voice-changer/expressive",
160
+ name: "Expressive",
161
+ description: "Amplifies the delivery.",
162
+ group: "Revoice Styles",
163
+ data: { stability: 0.3, similarityBoost: 0.7, style: 0.45, removeBackgroundNoise: false },
164
+ },
165
+ {
166
+ id: "voice-changer/studio-clean",
167
+ name: "Studio Clean",
168
+ description: "Broadcast-ready, denoised.",
169
+ group: "Revoice Styles",
170
+ data: { stability: 0.65, similarityBoost: 0.85, style: 0, removeBackgroundNoise: true },
171
+ },
172
+ ]
@@ -0,0 +1,2 @@
1
+ // Barrel kept so `@nodaro/shared`'s `./factory-presets.js` import path is unchanged.
2
+ export * from "./factory-presets/index.js"