@danhachuel/thunderbolt 0.2.62 → 0.2.64

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 (59) hide show
  1. package/app/main.py +79 -29
  2. package/hermes_ui/storage.py +61 -0
  3. package/package.json +2 -1
  4. package/scripts/install.mjs +16 -0
  5. package/seed/prompt_masters/2Dstickman.md +193 -0
  6. package/seed/prompt_masters/3Dskeletoncharacter.md +1 -0
  7. package/seed/prompt_masters/ANIMALMOUNTEDCAMERA.md +299 -0
  8. package/seed/prompt_masters/ASMR.md +74 -0
  9. package/seed/prompt_masters/ASMRDEBOCACOMDOCES.md +130 -0
  10. package/seed/prompt_masters/AnimalX-Ray.md +136 -0
  11. package/seed/prompt_masters/CAREVOLUTION.md +176 -0
  12. package/seed/prompt_masters/CINEMATICBUNKERSURVIVAL.md +180 -0
  13. package/seed/prompt_masters/CINEMATICSLUMTRANSFORMATIONENGINE.md +212 -0
  14. package/seed/prompt_masters/CINEMATOGR/303/201FICOS3D.md +207 -0
  15. package/seed/prompt_masters/CartoonNostalgia.md +131 -0
  16. package/seed/prompt_masters/EPOXYFLOORTRANSFORMATION.md +254 -0
  17. package/seed/prompt_masters/Edgar'sHouseofTerrorsChooseYourStory.md +134 -0
  18. package/seed/prompt_masters/FOODBABYFACECHARACTER.md +141 -0
  19. package/seed/prompt_masters/FuitNovels.md +166 -0
  20. package/seed/prompt_masters/KIDSSTORYCREATOR(PROMODE).md +235 -0
  21. package/seed/prompt_masters/MatchstickPrompt.md +86 -0
  22. package/seed/prompt_masters/PERSONAGENSABANDONADOS.md +208 -0
  23. package/seed/prompt_masters/Pixar-styleanimated.md +193 -0
  24. package/seed/prompt_masters/RESTORATIONTIMELAPSE.md +262 -0
  25. package/seed/prompt_masters/RUSTREMOVAL.md +275 -0
  26. package/seed/prompt_masters/ReceitasIndianas.md +60 -0
  27. package/seed/prompt_masters/SkyscraperMonster.md +140 -0
  28. package/seed/prompt_masters/TIMETRAVELVLOG.md +264 -0
  29. package/seed/prompt_masters/Tarot.md +58 -0
  30. package/seed/prompt_masters/UFOs(OVNIs).md +63 -0
  31. package/seed/prompt_masters/VisualCraftSequenceGenerator.md +284 -0
  32. package/seed/prompt_masters/craftingStorytellingAI.md +79 -0
  33. package/seed/prompt_masters/hist/303/263riasinfantishoradedormir.md +71 -0
  34. package/seed/prompt_masters/viralTikTokdance.md +77 -0
  35. package/storage/tiktok/prompts_master/2Dstickman.md +193 -0
  36. package/storage/tiktok/prompts_master/3Dskeletoncharacter.md +1 -0
  37. package/storage/tiktok/prompts_master/ANIMALMOUNTEDCAMERA.md +299 -0
  38. package/storage/tiktok/prompts_master/ASMRDEBOCACOMDOCES.md +130 -0
  39. package/storage/tiktok/prompts_master/AnimalX-Ray.md +136 -0
  40. package/storage/tiktok/prompts_master/CAREVOLUTION.md +176 -0
  41. package/storage/tiktok/prompts_master/CINEMATICBUNKERSURVIVAL.md +180 -0
  42. package/storage/tiktok/prompts_master/CINEMATOGR/303/201FICOS3D.md +207 -0
  43. package/storage/tiktok/prompts_master/CartoonNostalgia.md +131 -0
  44. package/storage/tiktok/prompts_master/Edgar'sHouseofTerrorsChooseYourStory.md +134 -0
  45. package/storage/tiktok/prompts_master/FuitNovels.md +166 -0
  46. package/storage/tiktok/prompts_master/KIDSSTORYCREATOR(PROMODE).md +235 -0
  47. package/storage/tiktok/prompts_master/MatchstickPrompt.md +86 -0
  48. package/storage/tiktok/prompts_master/PERSONAGENSABANDONADOS.md +208 -0
  49. package/storage/tiktok/prompts_master/Pixar-styleanimated.md +193 -0
  50. package/storage/tiktok/prompts_master/RESTORATIONTIMELAPSE.md +262 -0
  51. package/storage/tiktok/prompts_master/RUSTREMOVAL.md +275 -0
  52. package/storage/tiktok/prompts_master/ReceitasIndianas.md +60 -0
  53. package/storage/tiktok/prompts_master/SkyscraperMonster.md +140 -0
  54. package/storage/tiktok/prompts_master/TIMETRAVELVLOG.md +264 -0
  55. package/storage/tiktok/prompts_master/Tarot.md +58 -0
  56. package/storage/tiktok/prompts_master/UFOs(OVNIs).md +63 -0
  57. package/storage/tiktok/prompts_master/VisualCraftSequenceGenerator.md +284 -0
  58. package/storage/tiktok/prompts_master/hist/303/263riasinfantishoradedormir.md +71 -0
  59. package/storage/tiktok/prompts_master/viralTikTokdance.md +77 -0
package/app/main.py CHANGED
@@ -22,7 +22,7 @@ except (OSError, json.JSONDecodeError):
22
22
 
23
23
  from hermes_ui.domain import STAGES, create_batch, create_channel, create_tasks_for_batch, delete_channel, pipeline_summary, set_channel_defaults, transition_task, update_channel, update_channel_video
24
24
  from hermes_ui.automation_worker import load_worker_status
25
- from hermes_ui.storage import BLUEPRINTS, STORAGE, TIKTOK_PROMPT_MASTERS, ensure_storage, list_blueprint_files, list_prompt_master_files, load_blueprint_file, load_prompt_master_file, now, read_json, write_json
25
+ from hermes_ui.storage import BLUEPRINTS, STORAGE, TIKTOK_PROMPT_MASTERS, ensure_storage, get_display_name, list_blueprint_files, list_prompt_master_files, load_blueprint_file, load_prompt_master_file, now, read_json, set_display_name, write_json
26
26
  from app.modules.niche_finder.apify import ApifyError, DEFAULT_ACTOR_ID, abort_actor_run, build_actor_input, get_dataset_items, normalize_video_items, start_actor_run, wait_for_actor_run
27
27
  from app.modules.niche_finder.core import NicheAnalysisError, run_niche_analysis
28
28
  from app.modules.niche_finder.data_loader import DatasetError, download_kaggle_dataset
@@ -204,6 +204,41 @@ def card(label: str, value: str | int, note: str = ""):
204
204
  st.markdown(f'<div class="content-card"><div class="content-label">{label}</div><div class="content-value">{value}</div><div class="small-muted">{note}</div></div>', unsafe_allow_html=True)
205
205
 
206
206
 
207
+ def _library_card_key(kind: str, path: Path) -> str:
208
+ return hashlib.sha1(f"{kind}:{path.resolve()}".encode("utf-8")).hexdigest()[:12]
209
+
210
+
211
+ def _render_library_name_editor(kind: str, path: Path, current_name: str) -> str:
212
+ """Render the inline name editor while keeping the physical filename unchanged."""
213
+ edit_key = f"rename_{kind}_{_library_card_key(kind, path)}"
214
+ if st.session_state.get(edit_key):
215
+ with st.form(f"{edit_key}_form", border=False):
216
+ edited_name = st.text_input("Nome de apresentação", value=current_name, max_chars=120, key=f"{edit_key}_input")
217
+ save_col, cancel_col = st.columns(2)
218
+ with save_col:
219
+ save_name = st.form_submit_button("Guardar nome", type="primary", use_container_width=True)
220
+ with cancel_col:
221
+ cancel_name = st.form_submit_button("Cancelar", use_container_width=True)
222
+ if save_name:
223
+ try:
224
+ set_display_name(kind, path, edited_name)
225
+ st.session_state.pop(edit_key, None)
226
+ st.success("Nome actualizado.")
227
+ st.rerun()
228
+ except ValueError as exc:
229
+ st.error(str(exc))
230
+ if cancel_name:
231
+ st.session_state.pop(edit_key, None)
232
+ st.rerun()
233
+ return edit_key
234
+
235
+
236
+ def _render_card_pencil(edit_key: str) -> None:
237
+ if st.button("✏️", help="Editar nome de apresentação", key=f"pencil_{edit_key}", type="tertiary", use_container_width=True):
238
+ st.session_state[edit_key] = True
239
+ st.rerun()
240
+
241
+
207
242
  def channel_options() -> list[dict]:
208
243
  return [c for c in read_json("channels.json", []) if c.get("active", True)]
209
244
 
@@ -214,7 +249,7 @@ def blueprint_catalog() -> list[tuple[str, str]]:
214
249
  try:
215
250
  data = load_blueprint_file(path)
216
251
  identifier = str(data.get("id") or path.stem)
217
- label = str(data.get("name") or path.stem)
252
+ label = get_display_name("blueprints", path, str(data.get("name") or data.get("title") or path.stem))
218
253
  options.append((identifier, label))
219
254
  except (OSError, ValueError, json.JSONDecodeError):
220
255
  continue
@@ -231,11 +266,11 @@ def blueprint_for_channel(channel: dict) -> dict[str, Any]:
231
266
  data = load_blueprint_file(path)
232
267
  except (OSError, ValueError, json.JSONDecodeError):
233
268
  continue
234
- identifiers = {str(data.get("id") or ""), path.stem, str(data.get("name") or "")}
269
+ identifiers = {str(data.get("id") or ""), path.stem, str(data.get("name") or ""), get_display_name("blueprints", path, str(data.get("name") or path.stem))}
235
270
  if blueprint_id in identifiers:
236
271
  resolved = dict(data)
237
272
  resolved.setdefault("id", blueprint_id)
238
- resolved.setdefault("name", str(data.get("name") or path.stem))
273
+ resolved["name"] = get_display_name("blueprints", path, str(data.get("name") or path.stem))
239
274
  return resolved
240
275
  return {"id": blueprint_id, "name": blueprint_id}
241
276
 
@@ -665,14 +700,21 @@ def render_blueprints():
665
700
  if not files:
666
701
  st.info("Ainda não existem blueprints na pasta local.")
667
702
  for path in files:
668
- if search and search.lower() not in path.name.lower():
669
- continue
670
703
  try:
671
704
  data = load_blueprint_file(path)
672
- title = data.get("channel_name") or data.get("name") or data.get("title") or path.stem
673
- with st.expander(f"{title} {path.relative_to(BLUEPRINTS)}"):
674
- st.caption(f"Ficheiro: {path}")
675
- st.json(data)
705
+ fallback_title = str(data.get("channel_name") or data.get("name") or data.get("title") or path.stem)
706
+ title = get_display_name("blueprints", path, fallback_title)
707
+ if search and search.lower() not in f"{title}\n{path.name}".lower():
708
+ continue
709
+ card_key = _library_card_key("blueprints", path)
710
+ header_cols = st.columns([0.93, 0.07], vertical_alignment="center")
711
+ with header_cols[0]:
712
+ with st.expander(f"{title} — {path.relative_to(BLUEPRINTS)}"):
713
+ st.caption(f"Ficheiro: {path}")
714
+ st.json(data)
715
+ with header_cols[1]:
716
+ _render_card_pencil(f"rename_blueprints_{card_key}")
717
+ _render_library_name_editor("blueprints", path, title)
676
718
  except Exception as exc:
677
719
  with st.expander(f"Inválido — {path.name}"):
678
720
  st.error(str(exc))
@@ -752,7 +794,8 @@ def render_tiktok_prompt_masters():
752
794
  content = load_prompt_master_file(path)
753
795
  except (OSError, ValueError):
754
796
  content = ""
755
- if search and search.lower() not in f"{path.name}\n{content}".lower():
797
+ display_heading = get_display_name("prompt_masters", path, next((line.lstrip("#").strip() for line in content.splitlines() if line.startswith("#")), path.stem))
798
+ if search and search.lower() not in f"{display_heading}\n{path.name}\n{content}".lower():
756
799
  continue
757
800
  visible_files.append(path)
758
801
  if not visible_files:
@@ -760,24 +803,31 @@ def render_tiktok_prompt_masters():
760
803
  for path in visible_files:
761
804
  try:
762
805
  content = load_prompt_master_file(path)
763
- heading = next((line.lstrip("#").strip() for line in content.splitlines() if line.startswith("#")), path.stem)
764
- with st.expander(f"{heading} — {path.name}", expanded=False):
765
- st.caption(f"Ficheiro TikTok: `{path}`")
766
- edited_content = st.text_area("Conteúdo Markdown", value=content, height=360, key=f"tiktok_prompt_master_editor_{path.stem}")
767
- prompt_cols = st.columns(3)
768
- with prompt_cols[0]:
769
- if st.button("Guardar alterações", type="primary", use_container_width=True, key=f"save_prompt_master_{path.stem}"):
770
- path.write_text(edited_content.rstrip() + "\n", encoding="utf-8")
771
- st.success("Prompt Master actualizado.")
772
- st.rerun()
773
- with prompt_cols[1]:
774
- st.download_button("Descarregar", data=content.encode("utf-8"), file_name=path.name, mime="text/markdown", use_container_width=True, key=f"download_prompt_master_{path.stem}")
775
- with prompt_cols[2]:
776
- if st.button("Apagar", use_container_width=True, key=f"delete_prompt_master_{path.stem}"):
777
- path.unlink(missing_ok=True)
778
- st.success("Prompt Master removido da biblioteca TikTok.")
779
- st.rerun()
780
- st.markdown(content)
806
+ fallback_heading = next((line.lstrip("#").strip() for line in content.splitlines() if line.startswith("#")), path.stem)
807
+ heading = get_display_name("prompt_masters", path, fallback_heading)
808
+ card_key = _library_card_key("prompt_masters", path)
809
+ header_cols = st.columns([0.93, 0.07], vertical_alignment="center")
810
+ with header_cols[0]:
811
+ with st.expander(f"{heading} — {path.name}", expanded=False):
812
+ st.caption(f"Ficheiro TikTok: `{path}`")
813
+ edited_content = st.text_area("Conteúdo Markdown", value=content, height=360, key=f"tiktok_prompt_master_editor_{path.stem}")
814
+ prompt_cols = st.columns(3)
815
+ with prompt_cols[0]:
816
+ if st.button("Guardar alterações", type="primary", use_container_width=True, key=f"save_prompt_master_{path.stem}"):
817
+ path.write_text(edited_content.rstrip() + "\n", encoding="utf-8")
818
+ st.success("Prompt Master actualizado.")
819
+ st.rerun()
820
+ with prompt_cols[1]:
821
+ st.download_button("Descarregar", data=content.encode("utf-8"), file_name=path.name, mime="text/markdown", use_container_width=True, key=f"download_prompt_master_{path.stem}")
822
+ with prompt_cols[2]:
823
+ if st.button("Apagar", use_container_width=True, key=f"delete_prompt_master_{path.stem}"):
824
+ path.unlink(missing_ok=True)
825
+ st.success("Prompt Master removido da biblioteca TikTok.")
826
+ st.rerun()
827
+ st.markdown(content)
828
+ with header_cols[1]:
829
+ _render_card_pencil(f"rename_prompt_masters_{card_key}")
830
+ _render_library_name_editor("prompt_masters", path, heading)
781
831
  except (OSError, ValueError) as exc:
782
832
  with st.expander(f"Ficheiro inválido — {path.name}"):
783
833
  st.error(str(exc))
@@ -15,6 +15,7 @@ BLUEPRINTS = STORAGE / "blueprints"
15
15
  TIKTOK_PROMPT_MASTERS = STORAGE / "tiktok" / "prompts_master"
16
16
  NICHES_DATA = STORAGE / "data" / "niches"
17
17
  SEED_BLUEPRINTS = ROOT / "seed" / "blueprints"
18
+ SEED_TIKTOK_PROMPT_MASTERS = ROOT / "seed" / "prompt_masters"
18
19
 
19
20
  DEFAULTS: dict[str, Any] = {
20
21
  "channels.json": [],
@@ -23,6 +24,7 @@ DEFAULTS: dict[str, Any] = {
23
24
  "queues.json": {"niche": [], "blueprint": [], "brand": [], "script": [], "title": [], "thumbnail": [], "video": [], "edit": [], "upload": []},
24
25
  "batches.json": [],
25
26
  "uploads.json": [],
27
+ "display_names.json": {"blueprints": {}, "prompt_masters": {}},
26
28
  "niche_apify_runs.json": [],
27
29
  "metadata_edits.json": [],
28
30
  "python_editor_edits.json": [],
@@ -239,10 +241,22 @@ def seed_blueprints() -> None:
239
241
  shutil.copy2(source, target)
240
242
 
241
243
 
244
+ def seed_prompt_masters() -> None:
245
+ """Copy packaged TikTok Prompt Masters without overwriting user files."""
246
+ if not SEED_TIKTOK_PROMPT_MASTERS.exists():
247
+ return
248
+ TIKTOK_PROMPT_MASTERS.mkdir(parents=True, exist_ok=True)
249
+ for source in sorted(SEED_TIKTOK_PROMPT_MASTERS.glob("*.md")):
250
+ target = TIKTOK_PROMPT_MASTERS / source.name
251
+ if not target.exists():
252
+ shutil.copy2(source, target)
253
+
254
+
242
255
  def ensure_storage() -> None:
243
256
  for path in [STATE, BLUEPRINTS / "canais", BLUEPRINTS / "nichos", BLUEPRINTS / "importados", BLUEPRINTS / "brandings", TIKTOK_PROMPT_MASTERS, STORAGE / "brand", STORAGE / "scripts", STORAGE / "thumbnails", STORAGE / "videos", STORAGE / "artifacts", STORAGE / "skills", STORAGE / "metadata_cleaner", STORAGE / "metadata_cleaner" / "outputs", STORAGE / "music", STORAGE / "voice_previews", STORAGE / "python_editor", NICHES_DATA]:
244
257
  path.mkdir(parents=True, exist_ok=True)
245
258
  seed_blueprints()
259
+ seed_prompt_masters()
246
260
  for filename, default in DEFAULTS.items():
247
261
  target = STATE / filename
248
262
  if not target.exists():
@@ -293,6 +307,53 @@ def append_json(name: str, item: dict[str, Any]) -> dict[str, Any]:
293
307
  return item
294
308
 
295
309
 
310
+ def _display_name_key(kind: str, path: Path) -> str:
311
+ """Return a stable storage-relative key without renaming the physical file."""
312
+ resolved = path.resolve()
313
+ if kind == "blueprints":
314
+ root = BLUEPRINTS.resolve()
315
+ try:
316
+ return resolved.relative_to(root).as_posix()
317
+ except ValueError as exc:
318
+ raise ValueError("O ficheiro não pertence ao storage de Blueprints.") from exc
319
+ if kind == "prompt_masters":
320
+ root = TIKTOK_PROMPT_MASTERS.resolve()
321
+ try:
322
+ return resolved.relative_to(root).as_posix()
323
+ except ValueError as exc:
324
+ raise ValueError("O ficheiro não pertence ao storage de Prompt Masters.") from exc
325
+ raise ValueError(f"Tipo de biblioteca inválido: {kind}")
326
+
327
+
328
+ def get_display_name(kind: str, path: Path, fallback: str) -> str:
329
+ names = read_json("display_names.json", {"blueprints": {}, "prompt_masters": {}})
330
+ if not isinstance(names, dict):
331
+ return fallback
332
+ entries = names.get(kind, {})
333
+ if not isinstance(entries, dict):
334
+ return fallback
335
+ value = str(entries.get(_display_name_key(kind, path)) or "").strip()
336
+ return value or fallback
337
+
338
+
339
+ def set_display_name(kind: str, path: Path, name: str) -> str:
340
+ clean_name = " ".join(str(name).split()).strip()
341
+ if not clean_name:
342
+ raise ValueError("Informe um nome para a biblioteca.")
343
+ if len(clean_name) > 120:
344
+ raise ValueError("O nome deve ter no máximo 120 caracteres.")
345
+ names = read_json("display_names.json", {"blueprints": {}, "prompt_masters": {}})
346
+ if not isinstance(names, dict):
347
+ names = {"blueprints": {}, "prompt_masters": {}}
348
+ entries = names.get(kind)
349
+ if not isinstance(entries, dict):
350
+ entries = {}
351
+ names[kind] = entries
352
+ entries[_display_name_key(kind, path)] = clean_name
353
+ write_json("display_names.json", names)
354
+ return clean_name
355
+
356
+
296
357
  def list_blueprint_files() -> list[Path]:
297
358
  ensure_storage()
298
359
  return sorted(BLUEPRINTS.rglob("*.json"), key=lambda p: p.stat().st_mtime, reverse=True)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@danhachuel/thunderbolt",
3
- "version": "0.2.62",
3
+ "version": "0.2.64",
4
4
  "description": "Thunderbolt — interface local para operação de canais faceless e motor MoneyPrinterTurbo",
5
5
  "main": "scripts/cli.mjs",
6
6
  "type": "module",
@@ -16,6 +16,7 @@
16
16
  "scripts/*.mjs",
17
17
  "storage/blueprints/**/*.json",
18
18
  "storage/tiktok/prompts_master/**/*.md",
19
+ "seed/prompt_masters/**/*.md",
19
20
  "seed/blueprints/**/*.json",
20
21
  "seed/skills/*.md",
21
22
  "seed/references/*.md",
@@ -103,6 +103,8 @@ function ensureDirs() {
103
103
  join(storageRoot, "blueprints", "nichos"),
104
104
  join(storageRoot, "blueprints", "importados"),
105
105
  join(storageRoot, "blueprints", "brandings"),
106
+ join(storageRoot, "tiktok"),
107
+ join(storageRoot, "tiktok", "prompts_master"),
106
108
  join(storageRoot, "metadata_cleaner"),
107
109
  join(storageRoot, "metadata_cleaner", "originals"),
108
110
  join(storageRoot, "metadata_cleaner", "outputs"),
@@ -115,6 +117,7 @@ function ensureDirs() {
115
117
  ];
116
118
  for (const directory of directories) mkdirSync(directory, { recursive: true });
117
119
  copySeedBlueprints(storageRoot);
120
+ copySeedPromptMasters(storageRoot);
118
121
  }
119
122
 
120
123
  function copySeedBlueprints(storageRoot) {
@@ -129,6 +132,19 @@ function copySeedBlueprints(storageRoot) {
129
132
  }
130
133
  }
131
134
 
135
+ function copySeedPromptMasters(storageRoot) {
136
+ const seedRoot = join(root, "seed", "prompt_masters");
137
+ const destination = join(storageRoot, "tiktok", "prompts_master");
138
+ if (!existsSync(seedRoot)) return;
139
+ mkdirSync(destination, { recursive: true });
140
+ for (const filename of readdirSync(seedRoot)) {
141
+ if (!filename.endsWith(".md")) continue;
142
+ const source = join(seedRoot, filename);
143
+ const target = join(destination, filename);
144
+ if (!existsSync(target)) copyFileSync(source, target);
145
+ }
146
+ }
147
+
132
148
  function copyOrMove(source, target, label) {
133
149
  if (!existsSync(source) || existsSync(target)) return false;
134
150
  mkdirSync(dirname(target), { recursive: true });
@@ -0,0 +1,193 @@
1
+ Você é um engenheiro de prompts especializado em geração de prompts de imagem cinematográficos para um estilo 2D stickman documentary desenhado à mão.
2
+
3
+ Seu trabalho é transformar UMA única entrada do usuário (ideia, roteiro curto ou descrição de imagem) em EXATAMENTE 7 prompts de geração de imagem altamente estruturados, seguindo rigorosamente as regras abaixo.
4
+
5
+ O objetivo é gerar prompts consistentes, cinematográficos e visualmente coerentes, com continuidade de mundo, personagens e objetos.
6
+
7
+ REGRAS ABSOLUTAS
8
+ Você deve produzir EXATAMENTE 7 prompts
9
+ Nunca gere mais
10
+ Nunca gere menos
11
+ Cada prompt deve conter 3 partes obrigatórias
12
+
13
+ A) Título do Shot com emoji
14
+
15
+ Formato obrigatório:
16
+
17
+ [EMOJI] — (Main / B-roll / Establishing / Detail) — (Characters Included / No Characters) — [Resumo rápido da ação]
18
+
19
+ Exemplo
20
+
21
+ 🎬 — Main — Characters Included — stickman tentando resolver um problema
22
+
23
+ B) Bloco de prompt dentro de código
24
+
25
+ O prompt deve estar dentro de um bloco de código.
26
+
27
+ O texto NÃO pode conter emojis.
28
+
29
+ C) CTA final
30
+
31
+ Cada prompt deve terminar com o mesmo CTA.
32
+
33
+ ESTRUTURA GLOBAL DOS 7 PROMPTS
34
+
35
+ Sempre gerar nesta ordem:
36
+
37
+ 1️⃣ Main Scene (Characters Included)
38
+
39
+ 2️⃣ B-roll 1 (Characters Included)
40
+
41
+ 3️⃣ B-roll 2 (Characters Included)
42
+
43
+ 4️⃣ B-roll 3 (Characters Included)
44
+
45
+ 5️⃣ B-roll 4 (Characters Included)
46
+
47
+ 6️⃣ Establishing Shot (No Characters)
48
+
49
+ 7️⃣ Detail Shot (No Characters)
50
+
51
+ REGRA DE CONTINUIDADE VISUAL
52
+
53
+ Todos os prompts devem manter:
54
+
55
+ mesmo personagem
56
+ mesmas roupas
57
+ mesmo ambiente
58
+ mesmos objetos
59
+ mesmo estilo visual
60
+
61
+ Se o usuário fornecer pouca informação, assumir:
62
+
63
+ 1 personagem
64
+ roupas simples
65
+ ambiente neutro
66
+ iluminação natural suave
67
+ dia claro
68
+ TEMPLATE — PERSONAGENS (USAR EM 5 PROMPTS)
69
+
70
+ Use este modelo estrutural:
71
+
72
+ A clean 2D cartoon illustration in a simple, minimal cartoon style with a flat digital look.
73
+
74
+ Scene: [ENVIRONMENT], [TIME OF DAY], [WEATHER OR LIGHTING].
75
+
76
+ Camera: [SHOT TYPE], [CAMERA ANGLE], [FRAMING].
77
+
78
+ Characters: [NUMBER] stick-figure characters with BIG ROUND HEADS that are ALWAYS PURE WHITE, tiny dot eyes, minimal simple mouth, simple eyebrows if needed.
79
+
80
+ The body is simple and minimal. Arms, legs, and hands are BLACK stick-line outlines made from simple curved lines, never filled.
81
+
82
+ Clothing and accessories are simple flat shapes with solid colors: [CLOTHING / PROPS].
83
+
84
+ Action: [WHAT IS HAPPENING].
85
+
86
+ Mood: [EMOTION / ATMOSPHERE].
87
+
88
+ Background: simple clean shapes, flat muted colors, solid fills, crisp edges, uniform line weight, clean readable composition.
89
+
90
+ No sketch lines. No brush texture. No paper texture.
91
+
92
+ TEMPLATE — SEM PERSONAGENS (USAR EM 2 PROMPTS)
93
+
94
+ A clean 2D cartoon illustration with a flat digital style matching the same visual look.
95
+
96
+ Subject: [OBJECT OR EMPTY ENVIRONMENT].
97
+
98
+ Scene/Setting: [LOCATION DETAILS], [TIME OF DAY], [LIGHTING].
99
+
100
+ Camera: [SHOT TYPE], [ANGLE], [FRAMING], [DEPTH STYLE].
101
+
102
+ Foreground elements (optional): [OBJECTS / PROPS].
103
+
104
+ Material/style notes: flat digital illustration, solid fills, crisp edges, uniform line weight, minimal detail.
105
+
106
+ No realism, no 3D look, no painterly shading, no watercolor, no paper texture.
107
+
108
+ Key visual elements that must appear:
109
+
110
+ [Detail 1]
111
+ [Detail 2]
112
+ [Detail 3]
113
+ [Detail 4]
114
+ REGRAS DE CINEMATOGRAFIA
115
+
116
+ Varie os enquadramentos:
117
+
118
+ Use combinações como:
119
+
120
+ wide shot
121
+ medium shot
122
+ close-up
123
+ over-the-shoulder
124
+ side angle
125
+ top-down
126
+ low angle
127
+ REGRAS DE B-ROLL
128
+
129
+ Os 4 B-roll devem mostrar:
130
+
131
+ reação do personagem
132
+ ação secundária
133
+ movimento ou transição
134
+ momento de preparação ou reflexão
135
+ REGRAS DE ESTABLISHING SHOT
136
+
137
+ Mostrar:
138
+
139
+ o ambiente inteiro
140
+ sem personagens
141
+ contexto da história
142
+ REGRAS DE DETAIL SHOT
143
+
144
+ Mostrar:
145
+
146
+ um objeto importante
147
+ close-up
148
+ foco narrativo
149
+ FORMATO FINAL DE SAÍDA
150
+
151
+ Cada prompt deve seguir EXATAMENTE este formato:
152
+
153
+ [TÍTULO COM EMOJI]
154
+
155
+ PROMPT COMPLETO
156
+
157
+ ✨ You can create these images and videos in OpenArt
158
+ 🎙 Add cinematic voice-overs using ElevenLabs
159
+
160
+ PROCESSO INTERNO (NÃO MOSTRAR AO USUÁRIO)
161
+ Identificar tipo de entrada
162
+ ideia
163
+ script
164
+ imagem
165
+ Definir
166
+ personagem
167
+ cenário
168
+ objetos
169
+ ação principal
170
+ Criar storyboard implícito
171
+ Converter storyboard em 7 prompts
172
+ OBJETIVO DE QUALIDADE
173
+
174
+ Os prompts devem:
175
+
176
+ ser claros
177
+ ser consistentes
178
+ evitar ambiguidades
179
+ produzir imagens visualmente coerentes
180
+ funcionar em Midjourney, DALL·E, Stable Diffusion, OpenArt
181
+ RESULTADO ESPERADO
182
+
183
+ A saída deve parecer um mini storyboard cinematográfico completo.
184
+
185
+ Se quiser, também posso te entregar versões ainda mais poderosas, como:
186
+
187
+ Versão 10x mais consistente para IA (Prompt Compiler)
188
+ Versão otimizada para OpenArt
189
+ Versão otimizada para Midjourney
190
+ Versão que gera 30 cenas automáticas
191
+ Versão usada por canais dark de YouTube
192
+
193
+ Todas com consistência >98% de replicação.
@@ -0,0 +1 @@
1
+ You are a professional cinematic prompt generator specialized in 3D skeleton character scenes. Your task is to convert any user idea, phrase, script, or concept into a deterministic structured output that always produces the same format and logic with extremely high consistency. The skeleton character must always remain visually identical across all scenes according to an external reference image chosen by the user, maintaining the same proportions, style, and design in every generated prompt. The output must always contain exactly one main cinematic scene followed by five supporting cinematic b-roll prompts that visually expand the story of the main scene. Every prompt must begin strictly with the phrase “Place the skeleton character…” and must describe a clear environment, the skeleton’s action or pose, a cinematic lighting style, and a defined camera angle or shot composition. The prompts must be concise, visual, and optimized for high-quality 3D rendering engines. The main scene establishes the primary action derived from the user’s idea. The five b-roll prompts must represent complementary visual moments such as alternate angles, close-ups, movement shots, environmental interactions, atmospheric shots, or narrative supporting visuals that enrich the story while maintaining the same skeleton character design. Every prompt must explicitly reference cinematic lighting such as soft daylight, dramatic rim lighting, warm interior lighting, sunset lighting, neon glow, volumetric lighting, or moody studio light, and must include a camera perspective such as wide shot, close-up, over-the-shoulder, low angle, tracking shot, medium shot, or cinematic perspective. The environment description should include subtle atmospheric elements when appropriate such as fog, dust particles, reflections, light rays, depth of field, motion blur, or environmental glow to increase realism. All prompts must always end with a phrase indicating that the result is rendered in clean cinematic 3D, highly detailed. The structure, order, and logic of the generated output must remain stable across generations to guarantee near-identical formatting and behavior, ensuring deterministic outputs where the main scene appears first and the five b-roll prompts follow sequentially with the same stylistic logic, maintaining clarity, cinematic language, and structural consistency suitable for AI image and video generation pipelines designed for OpenArt visual creation and ElevenLabs cinematic narration.