primocode 10.13.0 → 10.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (195) hide show
  1. package/README.md +66 -12
  2. package/bin/primocode.js +148 -8
  3. package/lib/act.js +48 -1
  4. package/lib/catalogo.js +12 -1
  5. package/lib/config.js +1 -0
  6. package/lib/estudio/cota.js +150 -0
  7. package/lib/estudio/dados/projetos/clube-ad5.json +105 -0
  8. package/lib/estudio/dados/projetos/clube-ae-sem-memoria.json +107 -0
  9. package/lib/estudio/dados/projetos/clube-agent.json +120 -0
  10. package/lib/estudio/dados/projetos/clube-antes-e-agora.json +86 -0
  11. package/lib/estudio/dados/projetos/clube-apresentando-clube.json +110 -0
  12. package/lib/estudio/dados/projetos/clube-bluevisa.json +106 -0
  13. package/lib/estudio/dados/projetos/clube-caught-in-the-fire.json +127 -0
  14. package/lib/estudio/dados/projetos/clube-chat-cliente-satisfeito.json +98 -0
  15. package/lib/estudio/dados/projetos/clube-chatgpt-anuncios.json +120 -0
  16. package/lib/estudio/dados/projetos/clube-claude-dj.json +140 -0
  17. package/lib/estudio/dados/projetos/clube-claude-mcp.json +142 -0
  18. package/lib/estudio/dados/projetos/clube-cleanui.json +106 -0
  19. package/lib/estudio/dados/projetos/clube-clinica-take-unico.json +128 -0
  20. package/lib/estudio/dados/projetos/clube-clinica.json +104 -0
  21. package/lib/estudio/dados/projetos/clube-clube-opener.json +125 -0
  22. package/lib/estudio/dados/projetos/clube-clube.json +108 -0
  23. package/lib/estudio/dados/projetos/clube-codigo.json +101 -0
  24. package/lib/estudio/dados/projetos/clube-distilbook.json +104 -0
  25. package/lib/estudio/dados/projetos/clube-drive-upload.json +115 -0
  26. package/lib/estudio/dados/projetos/clube-dub.json +119 -0
  27. package/lib/estudio/dados/projetos/clube-enxovaly.json +105 -0
  28. package/lib/estudio/dados/projetos/clube-fecha7.json +118 -0
  29. package/lib/estudio/dados/projetos/clube-filatov.json +128 -0
  30. package/lib/estudio/dados/projetos/clube-frame.json +108 -0
  31. package/lib/estudio/dados/projetos/clube-glass.json +118 -0
  32. package/lib/estudio/dados/projetos/clube-letra-em-apps.json +84 -0
  33. package/lib/estudio/dados/projetos/clube-letra-globo-3d.json +111 -0
  34. package/lib/estudio/dados/projetos/clube-letra-nos-apps.json +146 -0
  35. package/lib/estudio/dados/projetos/clube-letra-seis-mundos.json +100 -0
  36. package/lib/estudio/dados/projetos/clube-lula-3.json +146 -0
  37. package/lib/estudio/dados/projetos/clube-morph.json +119 -0
  38. package/lib/estudio/dados/projetos/clube-motion-designer.json +115 -0
  39. package/lib/estudio/dados/projetos/clube-motion-pacote.json +112 -0
  40. package/lib/estudio/dados/projetos/clube-movimento.json +103 -0
  41. package/lib/estudio/dados/projetos/clube-not-like-us.json +117 -0
  42. package/lib/estudio/dados/projetos/clube-pinterest-inspiracao.json +86 -0
  43. package/lib/estudio/dados/projetos/clube-pixel-e-tinta.json +108 -0
  44. package/lib/estudio/dados/projetos/clube-ponte.json +118 -0
  45. package/lib/estudio/dados/projetos/clube-processo-edit-tonal.json +126 -0
  46. package/lib/estudio/dados/projetos/clube-processo-motion-100-ia.json +109 -0
  47. package/lib/estudio/dados/projetos/clube-promo.json +114 -0
  48. package/lib/estudio/dados/projetos/clube-proposito.json +115 -0
  49. package/lib/estudio/dados/projetos/clube-rankhog.json +128 -0
  50. package/lib/estudio/dados/projetos/clube-recursao.json +116 -0
  51. package/lib/estudio/dados/projetos/clube-revelar.json +118 -0
  52. package/lib/estudio/dados/projetos/clube-robo.json +125 -0
  53. package/lib/estudio/dados/projetos/clube-shelby-ep2.json +144 -0
  54. package/lib/estudio/dados/projetos/clube-shelby.json +97 -0
  55. package/lib/estudio/dados/projetos/clube-solar-eclipse.json +96 -0
  56. package/lib/estudio/dados/projetos/clube-soldier.json +128 -0
  57. package/lib/estudio/dados/projetos/clube-som-de-cena.json +108 -0
  58. package/lib/estudio/dados/projetos/clube-spotify-candidatura.json +112 -0
  59. package/lib/estudio/dados/projetos/clube-tda-app.json +118 -0
  60. package/lib/estudio/dados/projetos/clube-tda-ia.json +75 -0
  61. package/lib/estudio/dados/projetos/clube-telegram-chat.json +118 -0
  62. package/lib/estudio/dados/projetos/clube-telegram-ilha.json +106 -0
  63. package/lib/estudio/dados/projetos/clube-tennessee-nike.json +132 -0
  64. package/lib/estudio/dados/projetos/clube-tudo-se-move.json +112 -0
  65. package/lib/estudio/dados/projetos/clube-uiad.json +107 -0
  66. package/lib/estudio/dados/projetos/clube-viralgrow.json +108 -0
  67. package/lib/estudio/dados/projetos/clube-whose-side.json +140 -0
  68. package/lib/estudio/dados/projetos/clube-youtube-inscrever.json +108 -0
  69. package/lib/estudio/dados/projetos/elementos-do-site-em-movimento.json +49 -0
  70. package/lib/estudio/dados/projetos/explainer-narrado.json +51 -0
  71. package/lib/estudio/dados/projetos/lancamento-de-produto.json +51 -0
  72. package/lib/estudio/dados/projetos/motion-so-com-sons.json +50 -0
  73. package/lib/estudio/dados/projetos/titulo-em-after-effects.json +51 -0
  74. package/lib/estudio/dados/projetos/tour-de-saas.json +50 -0
  75. package/lib/estudio/dados/projetos-ae/antes-e-agora/ae/cenas.jsx +733 -0
  76. package/lib/estudio/dados/projetos-ae/antes-e-agora/assets/fazer_assets.py +88 -0
  77. package/lib/estudio/dados/projetos-ae/letra-em-apps/ae/cenas.jsx +402 -0
  78. package/lib/estudio/dados/projetos-ae/letra-em-apps/assets/preparar_assets.py +17 -0
  79. package/lib/estudio/dados/projetos-ae/letra-em-apps/assets/svg_para_ae.py +25 -0
  80. package/lib/estudio/dados/projetos-ae/letra-nos-apps/BRIEF-AGENTES.md +31 -0
  81. package/lib/estudio/dados/projetos-ae/letra-nos-apps/README.md +53 -0
  82. package/lib/estudio/dados/projetos-ae/letra-nos-apps/ROTEIRO-CENAS.md +69 -0
  83. package/lib/estudio/dados/projetos-ae/letra-nos-apps/ae/A-agenda.jsx +148 -0
  84. package/lib/estudio/dados/projetos-ae/letra-nos-apps/ae/B-docs.jsx +174 -0
  85. package/lib/estudio/dados/projetos-ae/letra-nos-apps/ae/C-alttab.jsx +113 -0
  86. package/lib/estudio/dados/projetos-ae/letra-nos-apps/ae/D-spotify.jsx +118 -0
  87. package/lib/estudio/dados/projetos-ae/letra-nos-apps/ae/E-notas.jsx +146 -0
  88. package/lib/estudio/dados/projetos-ae/letra-nos-apps/ae/F-jornal1.jsx +144 -0
  89. package/lib/estudio/dados/projetos-ae/letra-nos-apps/ae/G-google.jsx +153 -0
  90. package/lib/estudio/dados/projetos-ae/letra-nos-apps/ae/H-mapa.jsx +176 -0
  91. package/lib/estudio/dados/projetos-ae/letra-nos-apps/ae/I-imagens.jsx +132 -0
  92. package/lib/estudio/dados/projetos-ae/letra-nos-apps/ae/J-jornal2.jsx +191 -0
  93. package/lib/estudio/dados/projetos-ae/letra-nos-apps/ae/K-maps.jsx +184 -0
  94. package/lib/estudio/dados/projetos-ae/letra-nos-apps/ae/camera-movimentos.jsx +48 -0
  95. package/lib/estudio/dados/projetos-ae/letra-nos-apps/ae/camera.jsx +57 -0
  96. package/lib/estudio/dados/projetos-ae/letra-nos-apps/ae/card-spotify.jsx +98 -0
  97. package/lib/estudio/dados/projetos-ae/letra-nos-apps/ae/digitar.jsx +38 -0
  98. package/lib/estudio/dados/projetos-ae/letra-nos-apps/ae/jornal-comum.jsx +196 -0
  99. package/lib/estudio/dados/projetos-ae/letra-nos-apps/ae/letra.jsx +23 -0
  100. package/lib/estudio/dados/projetos-ae/letra-nos-apps/ae/letra_automatica.py +83 -0
  101. package/lib/estudio/dados/projetos-ae/letra-nos-apps/ae/montagem.jsx +74 -0
  102. package/lib/estudio/dados/projetos-ae/letra-nos-apps/ae/w-agenda/render_html.py +13 -0
  103. package/lib/estudio/dados/projetos-ae/letra-nos-apps/ae/w-agenda/util.jsx +162 -0
  104. package/lib/estudio/dados/projetos-ae/letra-nos-apps/ae/w-midia-comum.jsx +114 -0
  105. package/lib/estudio/dados/projetos-ae/letra-nos-apps/ae/wg-util.jsx +360 -0
  106. package/lib/estudio/dados/projetos-ae/letra-nos-apps/assets/F-jornal1/render_html.py +13 -0
  107. package/lib/estudio/dados/projetos-ae/letra-nos-apps/assets/render_w-midia.py +26 -0
  108. package/lib/estudio/dados/projetos-ae/letra-nos-apps/assets/w-midia-ferramentas/inclin.py +30 -0
  109. package/lib/estudio/dados/projetos-ae/letra-nos-apps/assets/w-midia-ferramentas/medir_d.py +36 -0
  110. package/lib/estudio/dados/projetos-ae/letra-nos-apps/assets/w-midia-ferramentas/medir_e.py +27 -0
  111. package/lib/estudio/dados/projetos-ae/letra-nos-apps/camera/ajustar_movimentos.py +61 -0
  112. package/lib/estudio/dados/projetos-ae/letra-nos-apps/camera/ancorar.py +74 -0
  113. package/lib/estudio/dados/projetos-ae/letra-nos-apps/camera/assar.py +47 -0
  114. package/lib/estudio/dados/projetos-ae/letra-nos-apps/camera/camera3d_jornal.py +172 -0
  115. package/lib/estudio/dados/projetos-ae/letra-nos-apps/camera/comparar.py +32 -0
  116. package/lib/estudio/dados/projetos-ae/letra-nos-apps/camera/dados_ae_jornal.py +46 -0
  117. package/lib/estudio/dados/projetos-ae/letra-nos-apps/camera/folha_contato.py +28 -0
  118. package/lib/estudio/dados/projetos-ae/letra-nos-apps/camera/homografia_jornal.py +74 -0
  119. package/lib/estudio/dados/projetos-ae/letra-nos-apps/camera/integrar.py +44 -0
  120. package/lib/estudio/dados/projetos-ae/letra-nos-apps/camera/medir_quadro_a_quadro.py +32 -0
  121. package/lib/estudio/dados/projetos-ae/letra-nos-apps/camera/mesa_2d.py +64 -0
  122. package/lib/estudio/dados/projetos-ae/letra-nos-apps/camera/plot_cenas.py +11 -0
  123. package/lib/estudio/dados/projetos-ae/letra-nos-apps/camera/retificar_quadros.py +38 -0
  124. package/lib/estudio/dados/projetos-ae/letra-nos-apps/camera/w-agenda/assar_ab.py +52 -0
  125. package/lib/estudio/dados/projetos-ae/letra-nos-apps/camera/w-agenda/medir_ab.py +59 -0
  126. package/lib/estudio/dados/projetos-ae/letra-nos-apps/camera/wg_ajustar_h.py +111 -0
  127. package/lib/estudio/dados/projetos-ae/letra-nos-apps/camera/wg_corrige_cam.py +17 -0
  128. package/lib/estudio/dados/projetos-ae/letra-nos-apps/camera/wg_ecc_cadeia.py +80 -0
  129. package/lib/estudio/dados/projetos-ae/letra-nos-apps/camera/wg_finalizar_cam.py +65 -0
  130. package/lib/estudio/dados/projetos-ae/letra-nos-apps/camera/wg_mosaico.py +61 -0
  131. package/lib/estudio/dados/projetos-ae/letra-nos-apps/guia-do-metodo/tutorial-lyric-edit-interfaces/01-gramatica-e-roteiro.md +55 -0
  132. package/lib/estudio/dados/projetos-ae/letra-nos-apps/guia-do-metodo/tutorial-lyric-edit-interfaces/02-camera.md +66 -0
  133. package/lib/estudio/dados/projetos-ae/letra-nos-apps/guia-do-metodo/tutorial-lyric-edit-interfaces/03-montagem-no-ae.md +50 -0
  134. package/lib/estudio/dados/projetos-ae/letra-nos-apps/guia-do-metodo/tutorial-lyric-edit-interfaces/04-render-e-conferencia.md +43 -0
  135. package/lib/estudio/dados/projetos-ae/letra-nos-apps/guia-do-metodo/tutorial-lyric-edit-interfaces/05-abertura-celular-mergulho.md +43 -0
  136. package/lib/estudio/dados/projetos-ae/letra-nos-apps/guia-do-metodo/tutorial-lyric-edit-interfaces.md +42 -0
  137. package/lib/estudio/dados/projetos-ae/letra-nos-apps/transicao/atraso_imagem.py +31 -0
  138. package/lib/estudio/dados/projetos-ae/letra-nos-apps/transicao/fundo.py +56 -0
  139. package/lib/estudio/dados/projetos-ae/letra-nos-apps/transicao/juntar.py +45 -0
  140. package/lib/estudio/dados/projetos-ae/letra-nos-apps/transicao/montar.py +177 -0
  141. package/lib/estudio/dados/projetos-ae/letra-nos-apps/transicao/rastreio.py +74 -0
  142. package/lib/estudio/dados/projetos-ae/letra-nos-apps/transicao/sincronia.py +18 -0
  143. package/lib/estudio/dados/projetos-ae/pinterest-inspiracao/ae/cenas.jsx +530 -0
  144. package/lib/estudio/dados/projetos-ae/pinterest-inspiracao/assets/fazer_assets.py +107 -0
  145. package/lib/estudio/dados/projetos-ae/processo-motion-100-ia/assets/pessoas/figurinha.py +46 -0
  146. package/lib/estudio/dados/projetos-ae/processo-motion-100-ia/comp-a/BRIEF-A.md +83 -0
  147. package/lib/estudio/dados/projetos-ae/processo-motion-100-ia/comp-a/audio.py +179 -0
  148. package/lib/estudio/dados/projetos-ae/processo-motion-100-ia/comp-a/confere.py +20 -0
  149. package/lib/estudio/dados/projetos-ae/processo-motion-100-ia/comp-a/dados/tempo-parte1.js +1 -0
  150. package/lib/estudio/dados/projetos-ae/processo-motion-100-ia/comp-a/dados/tempo-parte2.js +1 -0
  151. package/lib/estudio/dados/projetos-ae/processo-motion-100-ia/comp-a/gerar_emojis.py +11 -0
  152. package/lib/estudio/dados/projetos-ae/processo-motion-100-ia/comp-a/img/filmes/_indice.js +122 -0
  153. package/lib/estudio/dados/projetos-ae/processo-motion-100-ia/comp-a/js/base.js +380 -0
  154. package/lib/estudio/dados/projetos-ae/processo-motion-100-ia/comp-a/js/main.js +86 -0
  155. package/lib/estudio/dados/projetos-ae/processo-motion-100-ia/comp-a/js/p1a.js +169 -0
  156. package/lib/estudio/dados/projetos-ae/processo-motion-100-ia/comp-a/js/p1b.js +455 -0
  157. package/lib/estudio/dados/projetos-ae/processo-motion-100-ia/comp-a/js/p1c.js +389 -0
  158. package/lib/estudio/dados/projetos-ae/processo-motion-100-ia/comp-a/js/p2.js +379 -0
  159. package/lib/estudio/dados/projetos-ae/processo-motion-100-ia/comp-a/video.py +62 -0
  160. package/lib/estudio/dados/projetos-ae/processo-motion-100-ia/take-unico/README.md +65 -0
  161. package/lib/estudio/dados/projetos-ae/processo-motion-100-ia/take-unico/oraculo_take.py +137 -0
  162. package/lib/estudio/dados/projetos-ae/processo-motion-100-ia/take-unico/render_take.py +388 -0
  163. package/lib/estudio/dados/projetos-ae/processo-motion-100-ia/take-unico/take.js +235 -0
  164. package/lib/estudio/editor.js +285 -0
  165. package/lib/estudio/effectcraft.js +152 -0
  166. package/lib/estudio/exportar.js +181 -0
  167. package/lib/estudio/index.js +90 -2
  168. package/lib/estudio/kit-ae/base.jsx +1146 -0
  169. package/lib/estudio/kit-ae/cenas.jsx +395 -0
  170. package/lib/estudio/kit-ae/primitivas.jsx +911 -0
  171. package/lib/estudio/maquina-diretor.js +393 -0
  172. package/lib/estudio/maquina-elementos.js +134 -0
  173. package/lib/estudio/maquina-layout.js +198 -0
  174. package/lib/estudio/maquina-som.js +478 -0
  175. package/lib/estudio/maquina-trilha.js +160 -0
  176. package/lib/estudio/maquina-voz.js +429 -0
  177. package/lib/estudio/maquina.js +516 -0
  178. package/lib/estudio/projetos.js +60 -0
  179. package/lib/headless.js +71 -0
  180. package/lib/hooks.js +72 -0
  181. package/lib/local/cerebro.json +398 -12
  182. package/lib/local/entrada.js +46 -2
  183. package/lib/marca-kit.js +309 -0
  184. package/lib/mcp.js +286 -6
  185. package/lib/perigo.js +31 -3
  186. package/lib/planos.js +47 -19
  187. package/lib/preparar.js +111 -0
  188. package/lib/retomar.js +55 -0
  189. package/lib/sandbox.js +197 -0
  190. package/lib/skills.js +3 -1
  191. package/lib/tools.js +13 -4
  192. package/lib/ui.js +1 -1
  193. package/package.json +4 -2
  194. package/skills/after-effects/SKILL.md +52 -0
  195. package/skills/maquina-de-motion/SKILL.md +84 -0
@@ -0,0 +1,196 @@
1
+ // =====================================================================
2
+ // Ajudantes das cenas do jornal (F-jornal1 e J-jornal2) — recriação @subzmotion "On My Way"
3
+ // ES3. Carregar com $.evalFile depois de definir JP (pasta do projeto, com barra no fim).
4
+ //
5
+ // Rig (medido no original, ver camera/camera3d_jornal.py):
6
+ // - SEM camada de câmera: a câmera padrão da comp 1080 (zoom 1500) é a mesma que o autor usou;
7
+ // - null 3D "PLANO" com Posição e Rotação X/Y/Z quadro a quadro (o jornal é o plano z=0 dele);
8
+ // todas as camadas do jornal são filhas 3D do PLANO, em unidades do plano (1 un. = 1 px da tela
9
+ // no primeiro quadro da cena, quando a página está de frente);
10
+ // - "MESA" é uma camada 2D (como a do autor) com semelhança quadro a quadro (posição/escala/giro)
11
+ // medida na madeira do original; embaixo, um sólido de fundo escuro.
12
+ // Ajuste fino: mexa nas chaves do PLANO (enquadramento) ou nas posições das camadas no plano.
13
+ // =====================================================================
14
+ function J_lerJSON(c) { var f = new File(c); f.encoding = "UTF-8"; f.open("r"); var s = f.read(); f.close(); return eval("(" + s + ")"); }
15
+ function J_pasta(nome, mae) {
16
+ var pr = app.project;
17
+ for (var i = 1; i <= pr.numItems; i++) { var it = pr.item(i); if (it instanceof FolderItem && it.name == nome) return it; }
18
+ var f = pr.items.addFolder(nome); if (mae) f.parentFolder = mae; return f;
19
+ }
20
+ function J_apagaItem(nome) {
21
+ var pr = app.project;
22
+ for (var i = pr.numItems; i >= 1; i--) { var it = pr.item(i); if (it.name == nome && !(it instanceof FolderItem)) it.remove(); }
23
+ }
24
+ function J_importar(caminho, fold) {
25
+ var pr = app.project, f = File(caminho);
26
+ for (var i = 1; i <= pr.numItems; i++) { var it = pr.item(i); if (it instanceof FootageItem && it.file && it.file.fsName == f.fsName) return it; }
27
+ var it2 = pr.importFile(new ImportOptions(f)); if (fold) it2.parentFolder = fold; return it2;
28
+ }
29
+ function J_comp(nome, w, h, fold) {
30
+ J_apagaItem(nome);
31
+ var c = app.project.items.addComp(nome, w, h, 1, 814 / 24, 24); if (fold) c.parentFolder = fold; return c;
32
+ }
33
+ function J_tr(L) { return L.property("ADBE Transform Group"); }
34
+ // filho 3D do PLANO, em coordenadas do plano
35
+ function J_filho(L, plano, anchor, pos, esc, rotZ) {
36
+ L.threeDLayer = true;
37
+ L.setParentWithJump(plano);
38
+ var t = J_tr(L);
39
+ t.property("ADBE Anchor Point").setValue([anchor[0], anchor[1], 0]);
40
+ t.property("ADBE Position").setValue([pos[0], pos[1], pos[2] || 0]);
41
+ if (esc != null) t.property("ADBE Scale").setValue([esc, esc, 100]);
42
+ t.property("ADBE Orientation").setValue([0, 0, 0]);
43
+ t.property("ADBE Rotate X").setValue(0); t.property("ADBE Rotate Y").setValue(0);
44
+ t.property("ADBE Rotate Z").setValue(rotZ || 0);
45
+ L.motionBlur = true;
46
+ return L;
47
+ }
48
+ // null 3D PLANO com as chaves do JSON ([t, px, py, pz, rx, ry, rz] por quadro)
49
+ function J_plano(comp, D) {
50
+ var n = comp.layers.addNull(comp.duration); n.name = "PLANO (jornal 3D)"; n.label = 1; n.threeDLayer = true;
51
+ var t = J_tr(n); t.property("ADBE Anchor Point").setValue([0, 0, 0]);
52
+ var ts = [], ps = [], rx = [], ry = [], rz = [], i, k;
53
+ for (i = 0; i < D.plano.length; i++) { k = D.plano[i]; ts.push(k[0]); ps.push([k[1], k[2], k[3]]); rx.push(k[4]); ry.push(k[5]); rz.push(k[6]); }
54
+ t.property("ADBE Position").setValuesAtTimes(ts, ps);
55
+ t.property("ADBE Rotate X").setValuesAtTimes(ts, rx);
56
+ t.property("ADBE Rotate Y").setValuesAtTimes(ts, ry);
57
+ t.property("ADBE Rotate Z").setValuesAtTimes(ts, rz);
58
+ var props = [t.property("ADBE Position"), t.property("ADBE Rotate X"), t.property("ADBE Rotate Y"), t.property("ADBE Rotate Z")];
59
+ for (var p = 0; p < props.length; p++) for (i = 1; i <= props[p].numKeys; i++) props[p].setInterpolationTypeAtKey(i, KeyframeInterpolationType.LINEAR, KeyframeInterpolationType.LINEAR);
60
+ // posição sem curva espacial (as chaves são quadro a quadro)
61
+ var pp = t.property("ADBE Position");
62
+ for (i = 1; i <= pp.numKeys; i++) { pp.setSpatialAutoBezierAtKey(i, false); pp.setSpatialContinuousAtKey(i, false); }
63
+ n.enabled = false;
64
+ return n;
65
+ }
66
+ // MESA: textura 2x2 espelhada numa pré-comp; camada 2D com semelhança por quadro.
67
+ // ret = retângulo da mesa na tela do quadro de referência [x0, y0, x1, y1].
68
+ function J_mesa(comp, D, imgItem, ret, fold, nomeTex, rep, tint) {
69
+ rep = rep || 2;
70
+ var W = imgItem.width * rep, H = imgItem.height * rep;
71
+ var tex = J_comp(nomeTex, W, H, fold);
72
+ for (var a = 0; a < rep; a++) for (var b = 0; b < rep; b++) {
73
+ var L = tex.layers.add(imgItem); var t = J_tr(L);
74
+ t.property("ADBE Anchor Point").setValue([imgItem.width / 2, imgItem.height / 2]);
75
+ t.property("ADBE Position").setValue([imgItem.width * (a + 0.5), imgItem.height * (b + 0.5)]);
76
+ t.property("ADBE Scale").setValue([(a % 2) ? -100 : 100, (b % 2) ? -100 : 100]);
77
+ }
78
+ var M = comp.layers.add(tex); M.name = "MESA (2D)"; M.motionBlur = true;
79
+ if (tint) { M.property("ADBE Effect Parade").addProperty("ADBE Tint"); M.property("ADBE Effect Parade").property(1).property(3).setValue(tint); } // tira saturação (cor do original)
80
+ var tm = J_tr(M);
81
+ var kx = (ret[2] - ret[0]) / W, ky = (ret[3] - ret[1]) / H, cx = (ret[0] + ret[2]) / 2, cy = (ret[1] + ret[3]) / 2;
82
+ tm.property("ADBE Anchor Point").setValue([W / 2, H / 2]);
83
+ var ts = [], ps = [], ss = [], rs = [], i, S, s, th;
84
+ for (i = 0; i < D.mesa.length; i++) {
85
+ S = D.mesa[i][1]; // [a, b, tx, c, d, ty] (tela no ref -> tela no quadro)
86
+ s = Math.sqrt(Math.abs(S[0] * S[4] - S[1] * S[3])); th = Math.atan2(S[3], S[0]) * 180 / Math.PI;
87
+ ts.push(D.mesa[i][0]);
88
+ ps.push([S[0] * cx + S[1] * cy + S[2], S[3] * cx + S[4] * cy + S[5]]);
89
+ ss.push([s * kx * 100, s * ky * 100]); rs.push(th);
90
+ }
91
+ tm.property("ADBE Position").setValuesAtTimes(ts, ps);
92
+ tm.property("ADBE Scale").setValuesAtTimes(ts, ss);
93
+ tm.property("ADBE Rotate Z").setValuesAtTimes(ts, rs);
94
+ var pr = [tm.property("ADBE Position"), tm.property("ADBE Scale"), tm.property("ADBE Rotate Z")];
95
+ for (var p = 0; p < pr.length; p++) for (i = 1; i <= pr[p].numKeys; i++) pr[p].setInterpolationTypeAtKey(i, KeyframeInterpolationType.LINEAR, KeyframeInterpolationType.LINEAR);
96
+ var pp = tm.property("ADBE Position"); for (i = 1; i <= pp.numKeys; i++) { pp.setSpatialAutoBezierAtKey(i, false); pp.setSpatialContinuousAtKey(i, false); }
97
+ return M;
98
+ }
99
+ // Foto numa pré-comp do tamanho do quadro (unidades do plano), cobrindo, com empurrão lento (nada parado)
100
+ function J_compFoto(nome, item, w, h, fold, foco, empurra) {
101
+ var c = J_comp(nome, Math.round(w), Math.round(h), fold);
102
+ c.bgColor = [0.1, 0.1, 0.11];
103
+ var L = c.layers.add(item); var t = J_tr(L);
104
+ var k = Math.max(w / item.width, h / item.height) * 100;
105
+ foco = foco || [0.5, 0.5];
106
+ t.property("ADBE Anchor Point").setValue([item.width * foco[0], item.height * foco[1]]);
107
+ t.property("ADBE Position").setValue([w / 2, h / 2]);
108
+ var e = empurra || 0.05;
109
+ t.property("ADBE Scale").setValuesAtTimes([0, 34], [[k * 1.02, k * 1.02], [k * (1.02 + e * 4), k * (1.02 + e * 4)]]);
110
+ L.motionBlur = false;
111
+ return c;
112
+ }
113
+ // Encaixe provisório (sólido cinza + nome), 1080x1080
114
+ function J_encaixeProvisorio(nome, fold) {
115
+ var c = J_comp(nome, 1080, 1080, fold);
116
+ var s = c.layers.addSolid([0.42, 0.42, 0.44], "cinza", 1080, 1080, 1, c.duration);
117
+ var tl = c.layers.addText(nome); var td = tl.property("ADBE Text Properties").property("ADBE Text Document");
118
+ var d = td.value; d.fontSize = 90; d.fillColor = [1, 1, 1]; d.justification = ParagraphJustification.CENTER_JUSTIFY; td.setValue(d);
119
+ J_tr(tl).property("ADBE Position").setValue([540, 560]);
120
+ var g = c.layers.addShape(); g.name = "grade"; // cruz de referência para conferir encaixe
121
+ var gr = g.property("ADBE Root Vectors Group");
122
+ var r = gr.addProperty("ADBE Vector Shape - Rect"); r.property("ADBE Vector Rect Size").setValue([1040, 1040]);
123
+ var st = gr.addProperty("ADBE Vector Graphic - Stroke"); st.property("ADBE Vector Stroke Width").setValue(8); st.property("ADBE Vector Stroke Color").setValue([1, 0.85, 0.2]);
124
+ J_tr(g).property("ADBE Position").setValue([540, 540]);
125
+ return c;
126
+ }
127
+ // Digitação com quebra opcional: seps[i] = o que vem depois da palavra i ("" , " " ou "\r")
128
+ function J_digitar(lay, palavras, inicios, fim, seps, fica) {
129
+ function arr(a, str) { var s = [], i; for (i = 0; i < a.length; i++) s.push(str ? ('"' + String(a[i]).replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/\r/g, "\\r") + '"') : a[i]); return "[" + s.join(",") + "]"; }
130
+ var ex = [
131
+ "var P = " + arr(palavras, true) + ";",
132
+ "var S = " + arr(seps, true) + ";",
133
+ "var T = " + arr(inicios, false) + ";",
134
+ "var FIM = " + fim + ", FICA = " + (fica == null ? 0.25 : fica) + ";",
135
+ "var txt = '', ativo = false, i, n;",
136
+ "for (i = 0; i < P.length; i++) {",
137
+ " var w = P[i] + S[i];",
138
+ " var a = T[i], b = (i < P.length - 1) ? T[i + 1] : FIM;",
139
+ " if (time < a) break;",
140
+ " n = Math.floor((time - a) / Math.max(b - a, thisComp.frameDuration) * P[i].length) + 1;",
141
+ " n = Math.min(n, w.length); txt += w.substr(0, n); if (n < w.length) { ativo = true; break; }",
142
+ "}",
143
+ "if (time >= T[0] && (ativo || time < FIM + FICA)) txt += '|';",
144
+ "txt;"
145
+ ].join("\n");
146
+ lay.property("ADBE Text Properties").property("ADBE Text Document").expression = ex;
147
+ return lay;
148
+ }
149
+ // Manchete 3D digitada: ajusta corpo e escala horizontal para caber em (larg x altura de maiúscula)
150
+ // linhas = [{t:"TEXTO", cap: altura, larg: max}] (uma camada por linha); x, base = canto da 1ª letra e linha de base no plano.
151
+ function J_manchete(comp, plano, nome, texto, fonte, x, base, cap, larg, hsMin, cor) {
152
+ var L = comp.layers.addText(texto); L.name = nome;
153
+ var td = L.property("ADBE Text Properties").property("ADBE Text Document");
154
+ var d = td.value;
155
+ d.font = fonte; d.fontSize = 100; d.fillColor = cor || [0.075, 0.07, 0.065]; d.applyFill = true; d.applyStroke = false;
156
+ d.justification = ParagraphJustification.LEFT_JUSTIFY; d.tracking = 0; d.horizontalScale = 1; // 1 = 100% (não é pixel)
157
+ td.setValue(d);
158
+ // mede: altura da maiúscula com "H" e largura do texto inteiro (corpo 100)
159
+ d = td.value; d.text = "H"; td.setValue(d);
160
+ var rH = L.sourceRectAtTime(0, false);
161
+ d = td.value; d.text = texto; td.setValue(d);
162
+ var rT = L.sourceRectAtTime(0, false);
163
+ var capR = rH.height / 100; // altura da maiúscula por unidade de corpo
164
+ var corpo = cap / capR, hs = 100;
165
+ var w = rT.width * corpo / 100;
166
+ if (w > larg) { hs = Math.max(hsMin || 72, 100 * larg / w); w = w * hs / 100; }
167
+ if (w > larg) { corpo = corpo * larg / w; }
168
+ // o AE limita o corpo do texto: acima de 1000 px, o resto vai na escala da camada
169
+ var esc = 100, corpoReal = corpo;
170
+ if (corpo > 1000) { esc = corpo / 10; corpo = 1000; }
171
+ d = td.value; d.fontSize = corpo; d.horizontalScale = hs / 100; td.setValue(d);
172
+ J_filho(L, plano, [0, 0], [x, base, -2], esc, 0);
173
+ return { layer: L, corpo: corpoReal, hs: hs, capR: capR, esc: esc };
174
+ }
175
+ // remove sólidos e nulls órfãos (sobram quando o gerador roda de novo)
176
+ function J_limpaSolidos() {
177
+ var pr = app.project, n = 0;
178
+ for (var i = pr.numItems; i >= 1; i--) {
179
+ var it = pr.item(i);
180
+ if (it instanceof FootageItem && it.mainSource instanceof SolidSource && it.usedIn.length == 0) { it.remove(); n++; }
181
+ }
182
+ return n;
183
+ }
184
+
185
+ // Tempos de digitação: tempo cantado de cada palavra (ae/letra.json) + atraso medido no original para aquele
186
+ // campo (o autor digita um pouco depois da voz), preso entre o início visível da digitação e o fim.
187
+ function J_tempos(cantados, atraso, ini, fim) {
188
+ var out = [], i, t, n = cantados.length;
189
+ for (i = 0; i < n; i++) {
190
+ t = cantados[i] + atraso;
191
+ t = Math.max(t, ini + i * 0.06); t = Math.min(t, fim - (n - i) * 0.06);
192
+ if (i > 0) t = Math.max(t, out[i - 1] + 0.06);
193
+ out.push(Math.round(t * 1000) / 1000);
194
+ }
195
+ return out;
196
+ }
@@ -0,0 +1,23 @@
1
+ // =====================================================================
2
+ // Textos de letra da recriação: lidos de ae/letra.json (preenchido pelo autor).
3
+ // LETRA(id) -> {texto, palavras[], canta_em[]}; usa "texto" se preenchido, senão "reserva".
4
+ // A digitação divide o texto em palavras pelos espaços e usa os tempos "canta_em" do slot
5
+ // (se o texto colado tiver mais palavras que tempos, as extras entram espaçadas pelo último intervalo).
6
+ // Uso (ES3): $.evalFile(P + "ae/letra.jsx"); var s = LETRA("A1"); DIGITAR(camada, s.palavras, s.tempos, fim, {...});
7
+ // =====================================================================
8
+ var LETRA_P = (function () { try { return File($.fileName).parent.parent.fsName.replace(/\\/g, "/") + "/"; } catch (e) { return File.decode("<HOME>/Documents/Cria%C3%A7%C3%A3o%20de%20conteudo/07-videos/projetos/2026-10-17-subzmotion-recriacao/"); } })(); // pasta do projeto = a pasta acima de ae/ (rodar com $.evalFile)
9
+ var LETRA_DADOS = null;
10
+ function LETRA(id) {
11
+ if (!LETRA_DADOS) { var f = new File(LETRA_P + "ae/letra.json"); f.encoding = "UTF-8"; f.open("r"); LETRA_DADOS = eval("(" + f.read() + ")"); f.close(); }
12
+ var s = null, i;
13
+ for (i = 0; i < LETRA_DADOS.slots.length; i++) if (LETRA_DADOS.slots[i].id == id) s = LETRA_DADOS.slots[i];
14
+ if (!s) throw new Error("slot de letra inexistente: " + id);
15
+ var txt = (s.texto && s.texto.replace(/\s/g, "") !== "") ? s.texto : s.reserva;
16
+ var pal = txt.replace(/^\s+|\s+$/g, "").split(/\s+/), passo = 0.3;
17
+ // com a letra colada, letra_automatica.py grava o instante de cada palavra em "tempos_texto"
18
+ var t = (txt == s.texto && s.tempos_texto && s.tempos_texto.length) ? s.tempos_texto.slice(0) : s.canta_em.slice(0);
19
+ for (var k = 0; k < t.length; k++) if (t[k] === null) t[k] = (k ? t[k - 1] + passo : s.canta_em[0]);
20
+ if (t.length >= 2) passo = t[t.length - 1] - t[t.length - 2];
21
+ while (t.length < pal.length) t.push((t.length ? t[t.length - 1] : 0) + passo);
22
+ return { id: id, texto: txt, palavras: pal, tempos: t.slice(0, pal.length), preenchido: txt == s.texto };
23
+ }
@@ -0,0 +1,83 @@
1
+ """Distribui um bloco de texto colado (a letra inteira, copiada do Google/Spotify) nos 31 campos do letra.json.
2
+
3
+ Ninguém precisa saber qual frase vai onde: o script transcreve o áudio do trecho (faster-whisper, tempo por palavra),
4
+ casa as palavras transcritas com as do texto colado, dá a cada palavra colada o instante em que é cantada e
5
+ põe em cada campo as palavras cantadas na janela de tempo dele. A lista do Spotify (D1–D9) usa as quebras de linha
6
+ do texto colado: D1 = a linha antes da 1ª cantada no trecho, D2–D9 = as linhas seguintes.
7
+ O script não imprime o texto: só quantas palavras caíram em cada campo e quantas o original tinha.
8
+
9
+ Uso: cole o texto em ae/LETRA-COMPLETA.txt e rode python -P ae/letra_automatica.py (áudio: audio/musica.wav ou audio/musica-original.wav)
10
+ --teste usa a própria transcrição como texto colado (para conferir o encaixe sem texto nenhum).
11
+ """
12
+ import json, os, re, sys, difflib
13
+ sys.stdout.reconfigure(encoding="utf-8")
14
+ AQUI = os.path.dirname(os.path.abspath(__file__)); RAIZ = os.path.dirname(AQUI)
15
+ TESTE = "--teste" in sys.argv
16
+
17
+ # Janelas de cada campo (s): palavras cantadas em [ini, fim) vão para o campo. Caixa alta quando o original usa.
18
+ JANELAS = [("A1", 0.0, 1.52), ("A2", 1.52, 2.36), ("A3", 2.36, 2.80), ("B1", 2.80, 4.16), ("B2", 4.16, 4.94),
19
+ ("E2", 8.34, 9.54), ("E3", 9.54, 10.52), ("F1", 10.52, 12.56), ("F2", 12.56, 14.04), ("F3", 14.04, 15.18),
20
+ ("F4", 15.18, 16.54), ("G1", 16.54, 17.54), ("G2", 17.54, 18.78), ("H1", 18.78, 20.64), ("H2", 20.64, 22.38),
21
+ ("I1", 22.38, 23.58), ("J1", 24.95, 28.06), ("K1", 28.06, 28.84), ("K2", 28.84, 31.64), ("K4", 31.64, 99)]
22
+ CAIXA_ALTA = {"A3", "B2", "E2", "E3", "F1", "F2", "F3", "F4", "G1", "H1", "H2", "J1", "K1", "K3"}
23
+ INICIAL_MAIUSCULA = {"G2", "I1", "I2", "K2", "K4"} # no original esses campos começam com maiúscula mesmo no meio do verso
24
+
25
+ def norm(w): return re.sub(r"[^a-z0-9]", "", w.lower().replace("’", "'").replace("'", ""))
26
+
27
+ def transcrever():
28
+ from faster_whisper import WhisperModel
29
+ m = WhisperModel("large-v3", device="cuda", compute_type="float16")
30
+ audio = next(p for p in (os.path.join(RAIZ, "audio", n) for n in ("musica.wav", "musica-original.wav")) if os.path.exists(p))
31
+ segs, _ = m.transcribe(audio, language=None, word_timestamps=True, condition_on_previous_text=False) # idioma detectado
32
+ return [(w.word.strip(), w.start) for s in segs for w in (s.words or [])]
33
+
34
+ ditas = transcrever()
35
+ if TESTE:
36
+ linhas = [" ".join(w for w, _ in ditas[i:i + 6]) for i in range(0, len(ditas), 6)]
37
+ else:
38
+ bruto = open(os.path.join(AQUI, "LETRA-COMPLETA.txt"), encoding="utf-8").read()
39
+ linhas = [l.strip() for l in bruto.splitlines() if l.strip() and not l.strip().startswith("#") and not re.match(r"^\[.*\]$", l.strip())]
40
+ coladas = [] # (palavra como está, índice da linha)
41
+ for li, l in enumerate(linhas):
42
+ for w in l.split(): coladas.append((w, li))
43
+
44
+ a = [norm(w) for w, _ in coladas]; b = [norm(w) for w, _ in ditas]
45
+ sm = difflib.SequenceMatcher(None, a, b, autojunk=False)
46
+ tempo = [None] * len(coladas)
47
+ for blk in sm.get_matching_blocks():
48
+ for k in range(blk.size): tempo[blk.a + k] = ditas[blk.b + k][1]
49
+ casadas = [i for i, t in enumerate(tempo) if t is not None]
50
+ if len(casadas) < 0.5 * len(ditas):
51
+ print(f"AVISO: só {len(casadas)} de {len(ditas)} palavras cantadas casaram. O texto colado é mesmo desta música?")
52
+ i0, i1 = casadas[0], casadas[-1]
53
+ for i in range(i0, i1 + 1): # palavras do meio sem par ganham tempo interpolado
54
+ if tempo[i] is None:
55
+ p = max(j for j in casadas if j < i); q = min(j for j in casadas if j > i)
56
+ tempo[i] = tempo[p] + (tempo[q] - tempo[p]) * (i - p) / (q - p)
57
+
58
+ d = json.load(open(os.path.join(AQUI, "letra.json"), encoding="utf-8")); slots = {s["id"]: s for s in d["slots"]}
59
+ def por_janela(ini, fim): return [i for i in range(i0, i1 + 1) if ini <= tempo[i] < fim]
60
+ res = {}
61
+ for sid, ini, fim in JANELAS: res[sid] = por_janela(ini, fim)
62
+ res["I2"] = res["I1"] + por_janela(23.58, 24.95) # título do vídeo = busca + as palavras grifadas
63
+ res["K3"] = res["K2"][-2:] # rótulo do pino 2 = 2 últimas palavras da busca
64
+ # Spotify: linha antes da 1ª cantada + 8 linhas seguintes; D5/D6 = linhas cantadas em 4,94–7,36 e 7,36–8,34
65
+ l0 = coladas[i0][1]
66
+ for k in range(9):
67
+ li = l0 - 1 + k; res[f"D{k + 1}"] = [i for i, (_, l) in enumerate(coladas) if l == li]
68
+ for sid, idx in res.items():
69
+ s = slots[sid]; txt = " ".join(coladas[i][0] for i in idx)
70
+ if sid in INICIAL_MAIUSCULA and txt: txt = txt[0].upper() + txt[1:]
71
+ s["texto"] = txt.upper() if sid in CAIXA_ALTA else txt
72
+ s["tempos_texto"] = [round(tempo[i], 3) for i in idx if tempo[i] is not None] if not sid.startswith("D") or sid in ("D5", "D6") else []
73
+ if sid == "J1" and s["tempos_texto"] and s["tempos_texto"][0] < s["canta_em"][0] - 0.1: s["tempos_texto"][0] = s["canta_em"][0]
74
+ if sid in ("D5", "D6"): # karaokê usa o instante de cada palavra da linha
75
+ s["tempos_texto"] = [round(tempo[i], 3) if tempo[i] is not None else None for i in idx]
76
+ if TESTE:
77
+ for s in d["slots"]: s["texto"] = ""; s.pop("tempos_texto", None)
78
+ else:
79
+ json.dump(d, open(os.path.join(AQUI, "letra.json"), "w", encoding="utf-8"), ensure_ascii=False, indent=1)
80
+ print(f"{len(casadas)} de {len(ditas)} palavras cantadas casaram com o texto colado")
81
+ print("campo palavras (colado / original)")
82
+ for s in d["slots"]:
83
+ n = len(res.get(s["id"], [])); print(f" {s['id']:3s} {n:2d} / {s['palavras']}" + ("" if abs(n - s["palavras"]) <= 1 else " <- conferir"))
@@ -0,0 +1,74 @@
1
+ // =====================================================================
2
+ // Montagem final da recriação (On My Way do @subzmotion)
3
+ // 1. importa os projetos dos agentes (cenas-w-*.aep)
4
+ // 2. troca cada camada cuja fonte é a comp provisória "ENCAIXE <id>" pela comp real "CENA <id>"
5
+ // (replaceSource mantém transformação, máscara e animação do encaixe)
6
+ // 3. monta a comp principal: as cenas em sequência, cada uma visível só no seu trecho
7
+ // (o tempo interno de toda cena = tempo do vídeo, então não há deslocamento), + música
8
+ // 4. motion blur ligado em todas as comps com o mesmo obturador
9
+ // Rodar com eval.run num envio só, com o projeto montagem.aep aberto (ou vazio).
10
+ // =====================================================================
11
+ var MONT = MONT || {};
12
+ MONT.P = (function () { try { return File($.fileName).parent.parent.fsName.replace(/\\/g, "/") + "/"; } catch (e) { return File.decode("<HOME>/Documents/Cria%C3%A7%C3%A3o%20de%20conteudo/07-videos/projetos/2026-10-17-subzmotion-recriacao/"); } })(); // pasta do projeto = a pasta acima de ae/ (rodar com $.evalFile)
13
+ MONT.CENAS = [
14
+ ["A-agenda", 0.00, 2.62], ["B-docs", 2.62, 4.95], ["C-alttab", 4.95, 6.04], ["D-spotify", 6.04, 8.05],
15
+ ["E-notas", 8.05, 10.80], ["F-jornal1", 10.80, 16.62], ["G-google", 16.62, 18.95], ["H-mapa", 18.95, 22.30],
16
+ ["I-imagens", 22.30, 24.62], ["J-jornal2", 24.62, 28.00], ["K-maps", 28.00, 814 / 24]
17
+ ];
18
+ MONT.OBTURADOR = 90; // graus; o autor tem rastro ~1/4 do deslocamento do quadro (medido no Love Story)
19
+ MONT.AMOSTRAS = 16;
20
+
21
+ MONT.acharComp = function (nome) {
22
+ var achados = [];
23
+ for (var i = 1; i <= app.project.numItems; i++) { var it = app.project.item(i); if (it instanceof CompItem && it.name == nome) achados.push(it); }
24
+ return achados;
25
+ };
26
+ MONT.importar = function () {
27
+ var nomes = ["cenas-w-agenda.aep", "cenas-w-midia.aep", "cenas-w-jornal.aep", "cenas-w-google.aep"], log = [];
28
+ for (var i = 0; i < nomes.length; i++) {
29
+ var f = new File(MONT.P + "ae/" + nomes[i]);
30
+ if (!f.exists) { log.push("FALTA " + nomes[i]); continue; }
31
+ app.project.importFile(new ImportOptions(f)); log.push("importado " + nomes[i]);
32
+ }
33
+ return log;
34
+ };
35
+ MONT.trocarEncaixes = function () {
36
+ var log = [], i, j, k;
37
+ for (i = 1; i <= app.project.numItems; i++) {
38
+ var c = app.project.item(i);
39
+ if (!(c instanceof CompItem)) continue;
40
+ for (j = 1; j <= c.numLayers; j++) {
41
+ var L = c.layer(j);
42
+ if (!(L.source instanceof CompItem)) continue;
43
+ var n = L.source.name;
44
+ if (n.indexOf("ENCAIXE ") !== 0) continue;
45
+ var id = n.substr(8), reais = MONT.acharComp("CENA " + id);
46
+ if (reais.length === 0) { log.push(c.name + ": sem CENA " + id); continue; }
47
+ L.replaceSource(reais[0], false); log.push(c.name + ": encaixe " + id + " trocado");
48
+ }
49
+ }
50
+ return log;
51
+ };
52
+ MONT.blur = function () {
53
+ for (var i = 1; i <= app.project.numItems; i++) {
54
+ var c = app.project.item(i);
55
+ if (!(c instanceof CompItem)) continue;
56
+ c.motionBlur = true; c.shutterAngle = MONT.OBTURADOR; c.shutterPhase = -MONT.OBTURADOR / 2;
57
+ c.motionBlurSamplesPerFrame = MONT.AMOSTRAS; c.motionBlurAdaptiveSampleLimit = 128;
58
+ }
59
+ };
60
+ MONT.principal = function () {
61
+ var antigas = MONT.acharComp("MAIN recriacao On My Way");
62
+ for (var a = 0; a < antigas.length; a++) antigas[a].remove();
63
+ var main = app.project.items.addComp("MAIN recriacao On My Way", 1080, 1080, 1, 814 / 24, 24), log = [];
64
+ for (var i = 0; i < MONT.CENAS.length; i++) {
65
+ var id = MONT.CENAS[i][0], c = MONT.acharComp("CENA " + id);
66
+ if (c.length === 0) { log.push("sem CENA " + id); continue; }
67
+ var L = main.layers.add(c[0]); L.startTime = 0; L.inPoint = MONT.CENAS[i][1]; L.outPoint = MONT.CENAS[i][2];
68
+ L.motionBlur = false; // a câmera e o blur moram dentro de cada cena
69
+ log.push("cena " + id + " " + MONT.CENAS[i][1] + "-" + MONT.CENAS[i][2]);
70
+ }
71
+ var musica = app.project.importFile(new ImportOptions(new File(MONT.P + "audio/musica-original.wav")));
72
+ var M = main.layers.add(musica); M.name = "MUSICA (referencia interna)"; M.startTime = 0;
73
+ return log;
74
+ };
@@ -0,0 +1,13 @@
1
+ """Tira PNG das interfaces (HTML -> Playwright). Uso: render_html.py arquivo.html parte saida.png [escala] [largura altura]"""
2
+ import sys, pathlib
3
+ from playwright.sync_api import sync_playwright
4
+ html, parte, saida = sys.argv[1], sys.argv[2], sys.argv[3]; esc = float(sys.argv[4]) if len(sys.argv) > 4 else 3
5
+ W = int(sys.argv[5]) if len(sys.argv) > 5 else 1080; H = int(sys.argv[6]) if len(sys.argv) > 6 else 1080
6
+ url = pathlib.Path(html).resolve().as_uri() + "?parte=" + parte
7
+ with sync_playwright() as p:
8
+ b = p.chromium.launch()
9
+ pg = b.new_page(viewport={"width": W, "height": H}, device_scale_factor=esc)
10
+ pg.goto(url); pg.wait_for_timeout(400)
11
+ pg.screenshot(path=saida, omit_background=True)
12
+ b.close()
13
+ print("ok", saida)
@@ -0,0 +1,162 @@
1
+ // =====================================================================
2
+ // Ajudantes dos geradores A-agenda.jsx e B-docs.jsx (agente w-agenda, 17/10). ES3.
3
+ // Tudo que é "mundo" vira filho do CAM com setParentWithJump (sem compensação) e posição em coordenadas do mundo.
4
+ // =====================================================================
5
+ function U_comp(nome) {
6
+ for (var i = 1; i <= app.project.numItems; i++) {
7
+ var it = app.project.item(i);
8
+ if (it instanceof CompItem && it.name == nome) return it;
9
+ }
10
+ return null;
11
+ }
12
+ function U_novaComp(nome) {
13
+ var velha = U_comp(nome); if (velha) velha.remove();
14
+ var c = app.project.items.addComp(nome, 1080, 1080, 1, 814 / 24, 24);
15
+ c.bgColor = [0, 0, 0]; c.motionBlur = true; c.shutterAngle = 90; c.shutterPhase = -45;
16
+ c.motionBlurSamplesPerFrame = 16; c.motionBlurAdaptiveSampleLimit = 256;
17
+ return c;
18
+ }
19
+ function U_importar(caminho) {
20
+ var f = new File(caminho);
21
+ for (var i = 1; i <= app.project.numItems; i++) {
22
+ var it = app.project.item(i);
23
+ if (it instanceof FootageItem && it.file && it.file.fsName == f.fsName) { it.replace(f); return it; }
24
+ }
25
+ return app.project.importFile(new ImportOptions(f));
26
+ }
27
+ function U_pai(L, pai) { if (pai) L.setParentWithJump(pai); return L; }
28
+ function U_tr(L) { return L.property("ADBE Transform Group"); }
29
+ // PNG de interface feito a 3x do mundo (3240 px): 33,333% no centro do mundo
30
+ function U_png(comp, item, nome, pai, centro, escala) {
31
+ var L = comp.layers.add(item); L.name = nome; U_pai(L, pai);
32
+ var tr = U_tr(L);
33
+ tr.property("ADBE Anchor Point").setValue([item.width / 2, item.height / 2]);
34
+ tr.property("ADBE Position").setValue(centro || [540, 540]);
35
+ var e = (escala === undefined) ? 100 / 3 : escala; tr.property("ADBE Scale").setValue([e, e]);
36
+ tr.property("ADBE Rotate Z").setValue(0);
37
+ L.motionBlur = true; L.quality = LayerQuality.BEST;
38
+ return L;
39
+ }
40
+ // camada de forma com origem no mundo (posição 0,0 no espaço do pai CAM)
41
+ function U_forma(comp, nome, pai) {
42
+ var L = comp.layers.addShape(); L.name = nome; U_pai(L, pai);
43
+ var tr = U_tr(L);
44
+ tr.property("ADBE Anchor Point").setValue([0, 0]); tr.property("ADBE Position").setValue([0, 0]);
45
+ tr.property("ADBE Scale").setValue([100, 100]); tr.property("ADBE Rotate Z").setValue(0);
46
+ L.motionBlur = true;
47
+ return L;
48
+ }
49
+ function U_cor(c) { return [c[0] / 255, c[1] / 255, c[2] / 255]; }
50
+ // retângulo preenchido (x0,y0)-(x1,y1) com arredondamento r
51
+ function U_ret(L, nome, x0, y0, x1, y1, r, cor) {
52
+ var g = L.property("ADBE Root Vectors Group").addProperty("ADBE Vector Group"); g.name = nome;
53
+ var c = g.property("ADBE Vectors Group");
54
+ var re = c.addProperty("ADBE Vector Shape - Rect");
55
+ re.property("ADBE Vector Rect Size").setValue([x1 - x0, y1 - y0]);
56
+ re.property("ADBE Vector Rect Position").setValue([(x0 + x1) / 2, (y0 + y1) / 2]);
57
+ re.property("ADBE Vector Rect Roundness").setValue(r);
58
+ var fi = L.property("ADBE Root Vectors Group").property(nome).property("ADBE Vectors Group").addProperty("ADBE Vector Graphic - Fill");
59
+ fi.property("ADBE Vector Fill Color").setValue(U_cor(cor));
60
+ return L.property("ADBE Root Vectors Group").property(nome);
61
+ }
62
+ // elipse (centro, diâmetro) com preenchimento ou traço
63
+ function U_elipse(L, nome, cx, cy, d, cor, traco) {
64
+ var g = L.property("ADBE Root Vectors Group").addProperty("ADBE Vector Group"); g.name = nome;
65
+ var c = g.property("ADBE Vectors Group");
66
+ var el = c.addProperty("ADBE Vector Shape - Ellipse");
67
+ el.property("ADBE Vector Ellipse Size").setValue([d, d]);
68
+ el.property("ADBE Vector Ellipse Position").setValue([cx, cy]);
69
+ var gg = L.property("ADBE Root Vectors Group").property(nome).property("ADBE Vectors Group");
70
+ if (traco) {
71
+ var st = gg.addProperty("ADBE Vector Graphic - Stroke");
72
+ st.property("ADBE Vector Stroke Color").setValue(U_cor(cor));
73
+ st.property("ADBE Vector Stroke Width").setValue(traco);
74
+ } else {
75
+ var fi = gg.addProperty("ADBE Vector Graphic - Fill");
76
+ fi.property("ADBE Vector Fill Color").setValue(U_cor(cor));
77
+ }
78
+ return L.property("ADBE Root Vectors Group").property(nome);
79
+ }
80
+ // polilinha aberta (lista de pontos) com traço
81
+ function U_linha(L, nome, pts, cor, traco, fechada) {
82
+ var g = L.property("ADBE Root Vectors Group").addProperty("ADBE Vector Group"); g.name = nome;
83
+ var c = g.property("ADBE Vectors Group");
84
+ var p = c.addProperty("ADBE Vector Shape - Group");
85
+ var s = new Shape(); s.vertices = pts; s.closed = !!fechada;
86
+ p.property("ADBE Vector Shape").setValue(s);
87
+ var gg = L.property("ADBE Root Vectors Group").property(nome).property("ADBE Vectors Group");
88
+ var st = gg.addProperty("ADBE Vector Graphic - Stroke");
89
+ st.property("ADBE Vector Stroke Color").setValue(U_cor(cor));
90
+ st.property("ADBE Vector Stroke Width").setValue(traco);
91
+ st.property("ADBE Vector Stroke Line Cap").setValue(2); // redondo
92
+ st.property("ADBE Vector Stroke Line Join").setValue(2);
93
+ return L.property("ADBE Root Vectors Group").property(nome);
94
+ }
95
+ // texto de ponto alinhado à esquerda; pos = início da linha de base no mundo
96
+ function U_texto(comp, nome, txt, pai, pos, fonte, tam, cor, track, just) {
97
+ var L = comp.layers.addText(txt); L.name = nome; U_pai(L, pai);
98
+ var tp = L.property("ADBE Text Properties").property("ADBE Text Document");
99
+ var d = tp.value;
100
+ d.resetCharStyle(); d.resetParagraphStyle();
101
+ d.text = txt; d.font = fonte; d.fontSize = tam; d.applyFill = true; d.fillColor = U_cor(cor); d.applyStroke = false;
102
+ d.tracking = track || 0; d.justification = just || ParagraphJustification.LEFT_JUSTIFY;
103
+ tp.setValue(d);
104
+ var tr = U_tr(L);
105
+ tr.property("ADBE Anchor Point").setValue([0, 0]); tr.property("ADBE Position").setValue(pos);
106
+ tr.property("ADBE Scale").setValue([100, 100]); tr.property("ADBE Rotate Z").setValue(0);
107
+ L.motionBlur = true;
108
+ return L;
109
+ }
110
+ // chaves lineares [[t, v], ...]
111
+ function U_chaves(prop, lista) {
112
+ var ts = [], vs = [], i;
113
+ for (i = 0; i < lista.length; i++) { ts.push(lista[i][0]); vs.push(lista[i][1]); }
114
+ prop.setValuesAtTimes(ts, vs);
115
+ for (i = 1; i <= prop.numKeys; i++) prop.setInterpolationTypeAtKey(i, KeyframeInterpolationType.LINEAR, KeyframeInterpolationType.LINEAR);
116
+ }
117
+ function U_seguras(prop, lista) { // chaves HOLD (troca seca)
118
+ var ts = [], vs = [], i;
119
+ for (i = 0; i < lista.length; i++) { ts.push(lista[i][0]); vs.push(lista[i][1]); }
120
+ prop.setValuesAtTimes(ts, vs);
121
+ for (i = 1; i <= prop.numKeys; i++) prop.setInterpolationTypeAtKey(i, KeyframeInterpolationType.HOLD, KeyframeInterpolationType.HOLD);
122
+ }
123
+ // efeito Preencher (cor animável) numa camada; lista = [[t, [r,g,b]], ...] em 0-255
124
+ function U_preencher(L, lista) {
125
+ L.property("ADBE Effect Parade").addProperty("ADBE Fill");
126
+ var fx = L.property("ADBE Effect Parade").property(L.property("ADBE Effect Parade").numProperties);
127
+ var cor = fx.property("ADBE Fill-0002");
128
+ if (lista.length == 1) { cor.setValue(U_cor(lista[0][1])); return fx; }
129
+ var l2 = []; for (var i = 0; i < lista.length; i++) l2.push([lista[i][0], U_cor(lista[i][1])]);
130
+ U_chaves(cor, l2);
131
+ return fx;
132
+ }
133
+ function U_f(q) { return q / 24; } // quadro -> segundos
134
+ function U_ler(caminho) { var f = new File(caminho); f.encoding = "UTF-8"; f.open("r"); var s = f.read(); f.close(); return eval("(" + s + ")"); }
135
+ // Digitacao quadro a quadro copiada do original: C[k] = quantas letras o original mostra no quadro F0+k
136
+ // (contadas com espacos e pontuacao), LO = tamanho de cada palavra do original, CUR = trechos [de, ate] (quadros)
137
+ // em que o cursor aparece (o original pisca: 8 quadros aceso, 8 apagado). O texto colado e casado palavra a
138
+ // palavra com o original, entao pontuacao ou tamanho um pouco diferente nao desalinha a digitacao.
139
+ // Nenhum texto do original fica aqui: so contagens.
140
+ function U_digitarQuadros(lay, texto, C, F0, LO, CUR) {
141
+ function arr(a) { var s = [], i; for (i = 0; i < a.length; i++) s.push(a[i] instanceof Array ? arr(a[i]) : a[i]); return "[" + s.join(",") + "]"; }
142
+ var esc = String(texto).replace(/\\/g, "\\\\").replace(/"/g, '\\"');
143
+ var ex = [
144
+ 'var T = "' + esc + '", C = ' + arr(C) + ', F0 = ' + F0 + ', LO = ' + arr(LO) + ', CUR = ' + arr(CUR) + ';',
145
+ "var W = T.split(' '), f = Math.round(time / thisComp.frameDuration), k = f - F0;",
146
+ "var n0 = (k < 0) ? 0 : ((k >= C.length) ? 99999 : C[k]);",
147
+ "var out = '', rest = n0, i;",
148
+ "if (n0 >= 99999) out = T; else {",
149
+ " for (i = 0; i < LO.length && i < W.length; i++) {",
150
+ " if (rest <= 0) break;",
151
+ " var take = Math.min(rest, LO[i]);",
152
+ " out += W[i].substr(0, (take >= LO[i]) ? W[i].length : Math.min(take, W[i].length));",
153
+ " rest -= LO[i];",
154
+ " if (rest > 0 && i < W.length - 1) { out += ' '; rest -= 1; }",
155
+ " }",
156
+ "}",
157
+ "var cur = false; for (i = 0; i < CUR.length; i++) if (f >= CUR[i][0] && f <= CUR[i][1]) cur = true;",
158
+ "out + (cur ? '|' : '');"
159
+ ].join("\n");
160
+ lay.property("ADBE Text Properties").property("ADBE Text Document").expression = ex;
161
+ return lay;
162
+ }