primocode 10.13.0 → 10.14.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 (196) hide show
  1. package/README.md +66 -12
  2. package/bin/primocode.js +148 -8
  3. package/lib/act.js +56 -3
  4. package/lib/catalogo.js +12 -1
  5. package/lib/config.js +1 -0
  6. package/lib/estudio/cota.js +157 -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 +290 -0
  165. package/lib/estudio/effectcraft.js +152 -0
  166. package/lib/estudio/exportar.js +181 -0
  167. package/lib/estudio/index.js +97 -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 +72 -0
  179. package/lib/headless.js +71 -0
  180. package/lib/hooks.js +72 -0
  181. package/lib/limites.js +100 -0
  182. package/lib/local/cerebro.json +398 -12
  183. package/lib/local/entrada.js +46 -2
  184. package/lib/marca-kit.js +312 -0
  185. package/lib/mcp.js +286 -6
  186. package/lib/perigo.js +31 -3
  187. package/lib/planos.js +49 -19
  188. package/lib/preparar.js +111 -0
  189. package/lib/retomar.js +55 -0
  190. package/lib/sandbox.js +197 -0
  191. package/lib/skills.js +3 -1
  192. package/lib/tools.js +13 -4
  193. package/lib/ui.js +1 -1
  194. package/package.json +4 -2
  195. package/skills/after-effects/SKILL.md +52 -0
  196. package/skills/maquina-de-motion/SKILL.md +84 -0
@@ -0,0 +1,74 @@
1
+ """Rastreia os 4 cantos do vídeo (quadrado) na tela do monitor, quadro a quadro, na gravação do celular (IMG_5439, retrato 4K).
2
+ Adaptado da Shelby ep. 2: o próprio master é o molde (template matching por escala para achar o quadrado no quadro de
3
+ referência, depois ECC em homografia a cada quadro, partindo do vizinho). Antes do play (t < OFF) a tela mostra o quadro 0 parado.
4
+ Saída: cantos.json {t: {"q": [[x,y] TL, TR, BR, BL], "cc": correlação}} em px do quadro do celular (2160×3840).
5
+ Uso (dentro de transicao/): python -P rastreio.py T0 T1"""
6
+ import cv2, json, sys, numpy as np
7
+ import json as _json, os as _os
8
+ CFG = _json.load(open(_os.path.join(_os.path.dirname(_os.path.abspath(__file__)), "config.json"), encoding="utf-8"))
9
+ sys.stdout.reconfigure(encoding="utf-8")
10
+ T0, T1 = float(sys.argv[1]), float(sys.argv[2])
11
+ import os
12
+ OFF = float(open("off_video.txt").read()) if os.path.exists("off_video.txt") else float(open("off.txt").read())
13
+ TREF = 0.5 # quadro 0 parado na tela (antes do play): trava a 0,987 e o rastreio segue para a frente
14
+ ESC = 0.5 # meia resolução do celular (1080×1920)
15
+ cel = cv2.VideoCapture(CFG["celular"]); FPS = cel.get(cv2.CAP_PROP_FPS)
16
+ mas = cv2.VideoCapture(CFG["master"]); FPSM = mas.get(cv2.CAP_PROP_FPS)
17
+ MW, MH = 1080, 1080
18
+ def carrega(cap, n, s):
19
+ fr = []
20
+ for _ in range(n):
21
+ ok, f = cap.read(); assert ok
22
+ fr.append(f if s == 1 else cv2.resize(f, None, fx=s, fy=s, interpolation=cv2.INTER_AREA))
23
+ return fr
24
+ QC = carrega(cel, int(T1 * FPS) + 2, ESC)
25
+ QM = carrega(mas, int(max(0.1, T1 - OFF) * FPSM) + 3, 1)
26
+ print("celular", QC[0].shape, "master", QM[0].shape, "fps", FPS, FPSM)
27
+ def prep(f, s):
28
+ g = cv2.cvtColor(f, cv2.COLOR_BGR2GRAY).astype(np.float32)
29
+ g = cv2.resize(g, None, fx=s, fy=s, interpolation=cv2.INTER_AREA)
30
+ g = np.log1p(g); g = cv2.GaussianBlur(g, (0, 0), 1.0)
31
+ return (g - g.mean()) / (g.std() + 1e-6)
32
+ def master_em(tc):
33
+ return QM[min(len(QM) - 1, int(round(max(0.0, tc - OFF) * FPSM)))]
34
+ fc = QC[int(round(TREF * FPS))]; gc = prep(fc, 1.0); fm = master_em(TREF)
35
+ melhor = None
36
+ for alt in np.linspace(0.16, 0.36, 81): # lado do quadrado / altura do quadro do celular
37
+ h = int(gc.shape[0] * alt); w = h
38
+ tm = prep(cv2.resize(fm, (w * 2, h * 2)), 0.5)
39
+ r = cv2.matchTemplate(gc, tm, cv2.TM_CCOEFF_NORMED); _, v, _, p = cv2.minMaxLoc(r)
40
+ if melhor is None or v > melhor[0]: melhor = (v, alt, p, w, h)
41
+ v, alt, (x0, y0), w, h = melhor
42
+ print(f"busca: correlação {v:.3f}, lado {alt:.3f} da altura, canto ({x0},{y0}), {w}×{h}")
43
+ crit = (cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 60, 1e-5)
44
+ def ecc(gcel, fmas, Hm):
45
+ gm = prep(fmas, 1.0)
46
+ q = cv2.perspectiveTransform(np.float32([[[0, 0]], [[MW, 0]], [[MW, MH]], [[0, MH]]]), Hm).reshape(-1, 2)
47
+ x0, y0 = np.maximum(0, q.min(0) - 40).astype(int); x1, y1 = np.minimum(gcel.shape[::-1], q.max(0) + 40).astype(int)
48
+ T = np.float64([[1, 0, -x0], [0, 1, -y0], [0, 0, 1]]); Hc = T @ Hm
49
+ crop = np.ascontiguousarray(gcel[y0:y1, x0:x1]).astype(np.float32)
50
+ W = np.linalg.inv(Hc); W = (W / W[2, 2]).astype(np.float32)
51
+ try:
52
+ cc, W = cv2.findTransformECC(crop, gm.astype(np.float32), W, cv2.MOTION_HOMOGRAPHY, crit, None, 3)
53
+ except cv2.error as e:
54
+ print("ECC:", str(e)[-120:]); return Hm, -1.0
55
+ return np.linalg.inv(T) @ np.linalg.inv(W.astype(np.float64)), float(cc)
56
+ H0 = np.float64([[w / MW, 0, x0], [0, h / MH, y0], [0, 0, 1]])
57
+ Href, cc = ecc(gc, fm, H0); print("ECC referência:", round(cc, 3))
58
+ out = {}
59
+ def canto(Hm):
60
+ q = cv2.perspectiveTransform(np.float32([[[0, 0]], [[MW, 0]], [[MW, MH]], [[0, MH]]]), Hm).reshape(-1, 2) / ESC
61
+ return q.round(2).tolist()
62
+ iref = int(round(TREF * FPS))
63
+ for passo, fim in ((-1, int(T0 * FPS)), (1, int(T1 * FPS))): # para trás até T0, para a frente até T1
64
+ Hm = Href.copy(); i = iref
65
+ while (i >= fim) if passo < 0 else (i <= fim):
66
+ g = prep(QC[i], 1.0)
67
+ Hn, c = ecc(g, master_em(i / FPS), Hm)
68
+ dq = np.abs(np.array(canto(Hn)) - np.array(canto(Hm))).max()
69
+ if c > 0.6 and dq < 60: Hm = Hn
70
+ out[round(i / FPS, 4)] = {"q": canto(Hm), "cc": round(c, 3), "dq": round(float(dq), 1)}
71
+ if i % 15 == 0: print(f"{i / FPS:6.2f} s cc {c:.3f} dq {dq:.1f} TL {out[round(i / FPS, 4)]['q'][0]}")
72
+ i += passo
73
+ json.dump(dict(sorted(out.items())), open("cantos.json", "w"), indent=0)
74
+ print("ok", len(out), "quadros")
@@ -0,0 +1,18 @@
1
+ """Deslocamento entre a gravação do celular (o monitor tocando a recriação) e o master: tempo do master = tempo do celular − OFF.
2
+ Copiado da Shelby ep. 2 (07-videos/projetos/2026-10-12-shelby-ep2-take-unico/transicao/sincronia.py): envelope de onset
3
+ a 22 kHz para o grosso, correlação do sinal filtrado a 48 kHz numa janela de 8 s para o fino. Rodar dentro de transicao/."""
4
+ import sys, numpy as np, librosa, scipy.signal as ss
5
+ sys.stdout.reconfigure(encoding="utf-8")
6
+ cel, sr = librosa.load("celular-48k.wav", sr=22050, mono=True, duration=30)
7
+ mas, _ = librosa.load("master-audio.wav", sr=22050, mono=True, duration=30)
8
+ h = 128
9
+ ec, em = librosa.onset.onset_strength(y=cel, sr=sr, hop_length=h), librosa.onset.onset_strength(y=mas, sr=sr, hop_length=h)
10
+ c = ss.correlate(ec - ec.mean(), em - em.mean(), mode="full"); lag = (np.argmax(c) - (len(em) - 1)) * h / sr
11
+ print("grosso:", round(lag, 3), "s pico", round(c.max() / (np.linalg.norm(ec - ec.mean()) * np.linalg.norm(em - em.mean())), 2))
12
+ cel48, _ = librosa.load("celular-48k.wav", sr=48000, mono=True, offset=max(0, lag + 2), duration=8)
13
+ mas48, _ = librosa.load("master-audio.wav", sr=48000, mono=True, offset=2, duration=8)
14
+ b, a = ss.butter(4, [300, 4000], "bandpass", fs=48000); x, y = ss.lfilter(b, a, cel48), ss.lfilter(b, a, mas48)
15
+ c2 = ss.correlate(x, y, mode="full"); k = np.argmax(np.abs(c2)) - (len(y) - 1)
16
+ fino = max(0, lag + 2) - 2 + k / 48000
17
+ print("fino: OFF =", round(fino, 4), "s")
18
+ open("off.txt", "w").write(f"{fino:.4f}\n")
@@ -0,0 +1,530 @@
1
+ /* cenas.jsx — recriação do edit "Pinterest em estilo SaaS" do @illdari (01, DZSYzoDM_Sc)
2
+ ---------------------------------------------------------------------------------
3
+ Monta do zero, num projeto novo, a comp RECRIACAO (1080×1080, 30 qps, 11,53 s). O original é 720×720:
4
+ todas as medidas foram multiplicadas por 1,5. A ideia do edit: uma forma vira a próxima, sem corte.
5
+
6
+ 0,00–1,53 PERGUNTA fundo preto com brilho vermelho; a frase sai do desfoque, anda devagar e sai
7
+ palavra por palavra; o "?" se solta, sobe girando em 3D.
8
+ 1,53–2,47 LOGO o fundo vira branco em 6 quadros (no grave); o "?" vira o logo do Pinterest com
9
+ espessura (giro tipo moeda); anel rosado; o logo encolhe num ponto vermelho.
10
+ 2,47–4,47 BUSCA o ponto estica na barra de busca (rebote de 3%), clareia e o texto se digita;
11
+ a mão arrasta um print de moodboard até a barra, com a câmera aproximando.
12
+ 4,47–7,10 PILHA a pilha de 6 cards abre em leque 3D; a mão passa por cima (efeito Dock);
13
+ os cards da esquerda apagam; clique em salvar.
14
+ 7,10–8,77 DESTAQUE o card escuro sai da pilha, endireita e cresce; reflexo azul cruza; encolhe.
15
+ 8,77–9,87 QUADRO corte seco para a grade escura com o card no meio; aproxima e apaga.
16
+ 9,93–11,0 ASSINATURA a nossa marca sai do desfoque com brilho e pulsa nas batidas.
17
+
18
+ COMO USAR
19
+ - Troque os textos no bloco TEXTOS (frase, busca, abas, chips) e a marca final em MARCA.
20
+ - File > Scripts > Run Script File… e escolha este arquivo: cria o projeto, salva em
21
+ ae/pinterest-saas.aep e grava os eventos de som em audio/eventos.json.
22
+ - Assets em assets/ (feitos por assets/fazer_assets.py): logo do Pinterest (glifo oficial do Simple Icons),
23
+ mãos em luva, moodboard.
24
+ */
25
+ (function () {
26
+
27
+ // ================================================================ TEXTOS (trocáveis)
28
+ var TEXTOS = {
29
+ p1: 'Sem', p2: 'inspiração', interrogacao: '?',
30
+ busca: 'Buscar no Pinterest',
31
+ abas: ['Pins', 'Pastas', 'Colagens'],
32
+ lista: ['Rascunho', 'Fazendo', 'Revisão', 'Pronto'],
33
+ chips: [['Pendente', '#F5A524'], ['Em andamento', '#3B82F6'], ['Enviado', '#A855F7'], ['Sucesso', '#22C55E'], ['Falhou', '#EF4444'], ['Expirado', '#9CA3AF']],
34
+ chipCentro: 'Clube'
35
+ };
36
+ var MARCA = 'play'; // marca final: um círculo com o "play" (troque por um PNG seu em assets/ e mude marcaFinal())
37
+
38
+ // ================================================================ pastas
39
+ var BASE = (typeof RECR_BASE !== 'undefined') ? new Folder(RECR_BASE) : File($.fileName).parent.parent;
40
+ var ASSETS = BASE.fsName + '/assets/';
41
+ var W = 1080, H = 1080, FPS = 30, DUR = 346 / 30;
42
+ function F(f) { return f / FPS; }
43
+
44
+ // ================================================================ ajudantes
45
+ function rgb(h) { h = h.replace('#', ''); return [parseInt(h.substr(0, 2), 16) / 255, parseInt(h.substr(2, 2), 16) / 255, parseInt(h.substr(4, 2), 16) / 255]; }
46
+ function nEase(p) {
47
+ var t = p.propertyValueType;
48
+ if (t == PropertyValueType.TwoD) return 2;
49
+ if (t == PropertyValueType.ThreeD) return 3;
50
+ return 1;
51
+ }
52
+ // K(prop, [[t, valor, influênciaEntrada, influênciaSaída], …]); influência -1 = linear; padrão 33
53
+ function K(p, arr) {
54
+ var i, k, e, n = nEase(p);
55
+ for (i = 0; i < arr.length; i++) arr[i][0] = Math.round(arr[i][0] * FPS) / FPS; // chaves na grade de quadros
56
+ for (i = 0; i < arr.length; i++) p.setValueAtTime(arr[i][0], arr[i][1]);
57
+ for (i = 0; i < arr.length; i++) {
58
+ k = p.nearestKeyIndex(arr[i][0]);
59
+ var ei = arr[i].length > 2 ? arr[i][2] : 33, eo = arr[i].length > 3 ? arr[i][3] : ei;
60
+ if (ei === 'a') { // 'a' = curva automática contínua (velocidade sem degrau)
61
+ p.setTemporalContinuousAtKey(k, true); p.setTemporalAutoBezierAtKey(k, true);
62
+ if (p.isSpatial && p.matchName == 'ADBE Position') { p.setSpatialAutoBezierAtKey(k, false); p.setSpatialContinuousAtKey(k, false); }
63
+ continue;
64
+ }
65
+ var ie = [], oe = [];
66
+ for (e = 0; e < n; e++) { ie.push(new KeyframeEase(0, Math.max(0.1, ei))); oe.push(new KeyframeEase(0, Math.max(0.1, eo))); }
67
+ p.setTemporalEaseAtKey(k, ie, oe);
68
+ if (ei < 0 || eo < 0) p.setInterpolationTypeAtKey(k, ei < 0 ? KeyframeInterpolationType.LINEAR : KeyframeInterpolationType.BEZIER, eo < 0 ? KeyframeInterpolationType.LINEAR : KeyframeInterpolationType.BEZIER);
69
+ if (p.isSpatial && p.matchName == 'ADBE Position') {
70
+ p.setSpatialAutoBezierAtKey(k, false); p.setSpatialContinuousAtKey(k, false);
71
+ var z = (p.value.length == 3) ? [0, 0, 0] : [0, 0];
72
+ p.setSpatialTangentsAtKey(k, z, z);
73
+ }
74
+ }
75
+ }
76
+ function T(L) { return L.property('ADBE Transform Group'); }
77
+ function P(L) { return T(L).property('ADBE Position'); }
78
+ function S(L) { return T(L).property('ADBE Scale'); }
79
+ function R(L) { return T(L).property('ADBE Rotate Z'); }
80
+ function O(L) { return T(L).property('ADBE Opacity'); }
81
+ function A(L) { return T(L).property('ADBE Anchor Point'); }
82
+ function fx(L, mn) { return L.property('ADBE Effect Parade').addProperty(mn); }
83
+ function blur(L) { var e = fx(L, 'ADBE Gaussian Blur 2'); e.property('ADBE Gaussian Blur 2-0003').setValue(0); /* sem repetir borda: o desfoque some suave (com 1, PNG vira caixa) */ return L.property('ADBE Effect Parade').property(e.name).property('ADBE Gaussian Blur 2-0001'); }
84
+ function NUL(comp, nome, pos) { var L = comp.layers.addNull(); L.name = nome; A(L).setValue([0, 0]); P(L).setValue(pos); L.enabled = true; return L; }
85
+ function solid(comp, nome, cor, w, h) { var L = comp.layers.addSolid(rgb(cor), nome, w || comp.width, h || comp.height, 1); return L; }
86
+ function img(comp, arq) {
87
+ var it = app.project.importFile(new ImportOptions(new File(arq)));
88
+ it.parentFolder = PASTA;
89
+ return comp.layers.add(it);
90
+ }
91
+ function shape(comp, nome) { var L = comp.layers.addShape(); L.name = nome; return L; }
92
+ function grupo(L, nome) { var g = L.property('ADBE Root Vectors Group').addProperty('ADBE Vector Group'); g.name = nome; return g; }
93
+ function cont(L, nome) { return L.property('ADBE Root Vectors Group').property(nome).property('ADBE Vectors Group'); }
94
+ function addRect(L, gn, w, h, r) { var g = grupo(L, gn); var rc = cont(L, gn).addProperty('ADBE Vector Shape - Rect'); rc.property('ADBE Vector Rect Size').setValue([w, h]); rc.property('ADBE Vector Rect Roundness').setValue(r); return gn; }
95
+ function addEllipse(L, gn, w, h, pos) { grupo(L, gn); var el = cont(L, gn).addProperty('ADBE Vector Shape - Ellipse'); el.property('ADBE Vector Ellipse Size').setValue([w, h]); if (pos) el.property('ADBE Vector Ellipse Position').setValue(pos); return gn; }
96
+ function addFill(L, gn, cor) { var f = cont(L, gn).addProperty('ADBE Vector Graphic - Fill'); f.property('ADBE Vector Fill Color').setValue(rgb(cor)); return f; }
97
+ function addStroke(L, gn, cor, w) { var s = cont(L, gn).addProperty('ADBE Vector Graphic - Stroke'); s.property('ADBE Vector Stroke Color').setValue(rgb(cor)); s.property('ADBE Vector Stroke Width').setValue(w); return s; }
98
+ function rectProp(L, gn, mn) { return cont(L, gn).property('ADBE Vector Shape - Rect').property(mn); }
99
+ function TX(comp, s, fonte, tam, cor, pos, just, track) {
100
+ var L = comp.layers.addText(s);
101
+ var tp = L.property('ADBE Text Properties').property('ADBE Text Document');
102
+ var d = tp.value;
103
+ d.resetCharStyle(); d.font = fonte; d.fontSize = tam; d.applyFill = true; d.fillColor = rgb(cor); d.applyStroke = false;
104
+ d.tracking = track || 0;
105
+ tp.setValue(d);
106
+ d = tp.value; d.justification = just || ParagraphJustification.LEFT_JUSTIFY; tp.setValue(d);
107
+ P(L).setValue(pos);
108
+ return L;
109
+ }
110
+ function setLeading(L, lead) { var tp = L.property('ADBE Text Properties').property('ADBE Text Document'); var d = tp.value; d.autoLeading = false; d.leading = lead; tp.setValue(d); }
111
+ function caixa(L, t) { return L.sourceRectAtTime(t || 0, false); } // {left, top, width, height} em coordenadas da camada
112
+ // animador de texto: esconde o que não foi "digitado" (opacidade 0 e 10 px abaixo). base: 1 caracteres, 3 palavras
113
+ function digita(L, base, chaves, desloc, indice) {
114
+ var an = L.property('ADBE Text Properties').property('ADBE Text Animators').addProperty('ADBE Text Animator');
115
+ an.name = 'digita';
116
+ an.property('ADBE Text Animator Properties').addProperty('ADBE Text Opacity').setValue(0);
117
+ if (desloc) L.property('ADBE Text Properties').property('ADBE Text Animators').property('digita').property('ADBE Text Animator Properties').addProperty('ADBE Text Position 3D').setValue([0, desloc, 0]);
118
+ var sel = L.property('ADBE Text Properties').property('ADBE Text Animators').property('digita').property('ADBE Text Selectors').addProperty('ADBE Text Selector');
119
+ var adv = sel.property('ADBE Text Range Advanced');
120
+ adv.property('ADBE Text Range Type2').setValue(base);
121
+ if (base == 3 || indice) {
122
+ adv.property('ADBE Text Range Units').setValue(2); // índice (palavra/letra 1, 2, 3…)
123
+ sel.property('ADBE Text Index End').setValue(999);
124
+ K(sel.property('ADBE Text Index Start'), chaves);
125
+ } else {
126
+ K(sel.property('ADBE Text Percent Start'), chaves);
127
+ }
128
+ }
129
+ function mb(L) { L.motionBlur = true; }
130
+
131
+ function R3(L, eixo) { return T(L).property(eixo == 'x' ? 'ADBE Rotate X' : 'ADBE Rotate Y'); }
132
+ function circ(comp, nome, d, cor, pos) { var L = shape(comp, nome); addEllipse(L, 'o', d, d); addFill(L, 'o', cor); if (pos) P(L).setValue(pos); return L; }
133
+ function rr(comp, nome, w, h, r, cor, pos) { var L = shape(comp, nome); addRect(L, 'r', w, h, r); addFill(L, 'r', cor); if (pos) P(L).setValue(pos); return L; }
134
+ function sombra(L, op, dist, suave) {
135
+ var e = fx(L, 'ADBE Drop Shadow'); var n = e.name;
136
+ L.property('ADBE Effect Parade').property(n).property('ADBE Drop Shadow-0002').setValue(op);
137
+ L.property('ADBE Effect Parade').property(n).property('ADBE Drop Shadow-0003').setValue(180);
138
+ L.property('ADBE Effect Parade').property(n).property('ADBE Drop Shadow-0004').setValue(dist);
139
+ L.property('ADBE Effect Parade').property(n).property('ADBE Drop Shadow-0005').setValue(suave);
140
+ }
141
+
142
+ // ================================================================ projeto
143
+ app.newProject();
144
+ var proj = app.project;
145
+ var PASTA = proj.items.addFolder('assets');
146
+ var COMPS = proj.items.addFolder('cenas');
147
+ function novaComp(nome, w, h) { var c = proj.items.addComp(nome, w || W, h || H, 1, DUR, FPS); c.parentFolder = COMPS; c.motionBlur = true; c.shutterAngle = 360; c.shutterPhase = -180; c.motionBlurSamplesPerFrame = 16; return c; }
148
+ var EVENTOS = [];
149
+ function ev(t, kind, pan, v) { EVENTOS.push({ t: Math.round(t * 1000) / 1000, kind: kind, pan: pan || 0, v: v || 0.7 }); }
150
+
151
+ // ================================================================ CARDS (precomps 300×330)
152
+ function cardComp(nome, tipo) {
153
+ var c = novaComp(nome, 300, 330);
154
+ var escuro = (tipo == 'escuro' || tipo == 'preto' || tipo == 'gradiente');
155
+ var corFundo = '#FFFFFF';
156
+ if (tipo == 'escuro') corFundo = '#0D0D0F';
157
+ if (tipo == 'preto') corFundo = '#050505';
158
+ if (tipo == 'gradiente') corFundo = '#15161C';
159
+ var base = rr(c, 'card', 296, 326, 34, corFundo, [150, 165]);
160
+ if (!escuro) { var s = cont(base, 'r').addProperty('ADBE Vector Graphic - Stroke'); s.property('ADBE Vector Stroke Color').setValue(rgb('#E3E3E8')); s.property('ADBE Vector Stroke Width').setValue(2); }
161
+ var i, L;
162
+ if (tipo == 'lista') {
163
+ var cores = ['#C7C7CC', '#F5A524', '#3B82F6', '#22C55E'];
164
+ for (i = 0; i < 4; i++) {
165
+ var y = 82 + i * 52;
166
+ L = shape(c, 'marca' + i); addEllipse(L, 'o', 18, 18); addStroke(L, 'o', '#C7C7CC', 2.5); P(L).setValue([40, y]);
167
+ circ(c, 'ponto' + i, 12, cores[i], [72, y]);
168
+ var tx = TX(c, TEXTOS.lista[i], 'SFProText-Medium', 17, cores[i] == '#C7C7CC' ? '#8E8E93' : cores[i], [88, y + 6]);
169
+ }
170
+ rr(c, 'barra', 220, 10, 5, '#F0F0F3', [150, 300]);
171
+ } else if (tipo == 'escuro') {
172
+ // chips de status em 3 linhas, com o chip da marca no meio
173
+ var linhas = [[0, 1], [2, -1, 3], [4, 5]];
174
+ for (var l = 0; l < 3; l++) {
175
+ var itens = linhas[l], larg = [], tot = 0, k;
176
+ for (k = 0; k < itens.length; k++) { var nm = itens[k] < 0 ? TEXTOS.chipCentro : TEXTOS.chips[itens[k]][0]; larg.push(nm.length * 7.4 + 34); tot += larg[k] + 8; }
177
+ var x0 = 150 - tot / 2 + 4;
178
+ for (k = 0; k < itens.length; k++) {
179
+ var cor = itens[k] < 0 ? '#E8C547' : TEXTOS.chips[itens[k]][1];
180
+ var nome2 = itens[k] < 0 ? TEXTOS.chipCentro : TEXTOS.chips[itens[k]][0];
181
+ var cx = x0 + larg[k] / 2, cy = 120 + l * 44;
182
+ var ch = rr(c, 'chip' + l + k, larg[k], 30, 15, '#16161A', [cx, cy]);
183
+ var st2 = cont(ch, 'r').addProperty('ADBE Vector Graphic - Stroke'); st2.property('ADBE Vector Stroke Color').setValue(rgb(cor)); st2.property('ADBE Vector Stroke Width').setValue(1.5);
184
+ circ(c, 'chipdot' + l + k, 7, cor, [cx - larg[k] / 2 + 13, cy]);
185
+ TX(c, nome2, 'SFProText-Medium', 12, cor, [cx - larg[k] / 2 + 22, cy + 4]);
186
+ x0 += larg[k] + 8;
187
+ }
188
+ }
189
+ } else if (tipo == 'relogio') {
190
+ TX(c, '24', 'SFProDisplay-Bold', 150, '#111111', [150, 215], ParagraphJustification.CENTER_JUSTIFY);
191
+ rr(c, 'faixa', 240, 8, 4, '#E5E5EA', [150, 270]);
192
+ } else if (tipo == 'preto') {
193
+ circ(c, 'disco', 150, '#1C1C1E', [150, 150]);
194
+ circ(c, 'centro', 46, '#2C2C2E', [150, 150]);
195
+ rr(c, 'linha', 200, 8, 4, '#2C2C2E', [150, 270]);
196
+ } else if (tipo == 'grafico') {
197
+ for (i = 0; i < 6; i++) { var hh = [60, 110, 80, 150, 120, 170][i]; rr(c, 'col' + i, 26, hh, 8, i == 5 ? '#3B82F6' : '#DCE6FB', [55 + i * 38, 270 - hh / 2]); }
198
+ TX(c, '+38%', 'SFProDisplay-Semibold', 34, '#111111', [36, 70]);
199
+ } else if (tipo == 'gradiente') {
200
+ var g = solid(c, 'luz', '#2A3AFF', 300, 330);
201
+ var rp = fx(g, 'ADBE Ramp');
202
+ g.property('ADBE Effect Parade').property(rp.name).property('ADBE Ramp-0001').setValue([60, 40]);
203
+ g.property('ADBE Effect Parade').property(rp.name).property('ADBE Ramp-0002').setValue(rgb('#5B6CFF'));
204
+ g.property('ADBE Effect Parade').property(rp.name).property('ADBE Ramp-0003').setValue([260, 320]);
205
+ g.property('ADBE Effect Parade').property(rp.name).property('ADBE Ramp-0004').setValue(rgb('#0A0A12'));
206
+ var mt = rr(c, 'molde', 296, 326, 34, '#FFFFFF', [150, 165]); g.moveAfter(mt); g.setTrackMatte(mt, TrackMatteType.ALPHA);
207
+ }
208
+ base.moveToEnd();
209
+ return c;
210
+ }
211
+
212
+ var CARD_TIPOS = ['lista', 'grafico', 'relogio', 'escuro', 'preto', 'gradiente'];
213
+ var CARDS = [];
214
+ for (var ci = 0; ci < 6; ci++) CARDS.push(cardComp('card-' + (ci + 1) + '-' + CARD_TIPOS[ci], CARD_TIPOS[ci]));
215
+ var DESTAQUE = 3; // o card escuro (com os chips) é o que vai ser salvo
216
+
217
+ // ================================================================ PILHA (leque 3D com câmera própria)
218
+ var PIL = novaComp('PILHA');
219
+ var MAO_X = []; // posição x (na tela) de cada card, para a mão passar por cima
220
+ (function () {
221
+ var c = PIL;
222
+ var cam = c.layers.addCamera('cam', [540, 540]);
223
+ var zoom = cam.property('ADBE Camera Options Group').property('ADBE Camera Zoom').value;
224
+ P(cam).setValue([540, 540, -zoom]);
225
+ // brilho rosa embaixo da pilha (aparece quando os cards da esquerda apagam)
226
+ var glow = circ(c, 'brilho rosa', 520, '#F3A5D8', [560, 640]); S(glow).setValue([140, 60]);
227
+ K(blur(glow), [[0, 120]]); K(O(glow), [[5.87, 0], [6.10, 38]]);
228
+ // placeholder cinza que nasce do nada e vira o primeiro card
229
+ var ph = rr(c, 'placeholder', 296, 326, 34, '#EDEDF0', [360, 540]);
230
+ ph.threeDLayer = true;
231
+ K(S(ph), [[4.47, [60, 60, 60], 33, 10], [4.67, [112, 112, 112], 85, 33]]);
232
+ K(O(ph), [[4.47, 0], [4.53, 100], [4.75, 100], [4.85, 0]]);
233
+ ph.inPoint = 4.45; ph.outPoint = 4.9;
234
+ var Ls = [];
235
+ for (var i = 5; i >= 0; i--) {
236
+ var L = c.layers.add(CARDS[i]); L.name = 'card-' + (i + 1); L.threeDLayer = true; mb(L);
237
+ var x = 360 + i * 58, z = i * 55;
238
+ MAO_X[i] = x;
239
+ var t0 = 4.60 + i * F(2);
240
+ K(P(L), [[t0, [360, 540, 0], 33, 10], [t0 + F(12), [x, 540, z], 85, 33]]);
241
+ R3(L, 'y').setValue(18); S(L).setValue([112, 112, 112]); // borda direita para a frente: o card da esquerda cobre o seguinte
242
+ K(O(L), [[4.58 + i * F(1), 0], [4.62 + i * F(1), 100]]);
243
+ L.inPoint = 4.55;
244
+ Ls[i] = L;
245
+ }
246
+ // efeito Dock: o card sob a mão sobe (z −40) e cresce 8%; os vizinhos 4%
247
+ var HOVER = [4.97, 5.17, 5.37, 5.57];
248
+ for (i = 0; i < 4; i++) {
249
+ var L2 = Ls[i], th = HOVER[i], x2 = MAO_X[i], z2 = i * 55;
250
+ var fim = (i == DESTAQUE) ? 7.0 : th + 0.32;
251
+ K(T(L2).property('ADBE Position'), [[4.60 + i * F(2), [360, 540, 0], 33, 10], [4.60 + i * F(2) + F(12), [x2, 540, z2], 85, 33],
252
+ [th, [x2, 540, z2], 50, 50], [th + F(6), [x2, 525, z2 - 40], 70, 50], [fim, [x2, 525, z2 - 40], 50, 50], [fim + F(6), [x2, 540, z2], 70, 50]]);
253
+ K(S(L2), [[th, [112, 112, 112], 50, 50], [th + F(6), [121, 121, 121], 70, 50], [fim, [121, 121, 121], 50, 50], [fim + F(6), [112, 112, 112], 70, 50]]);
254
+ ev(th, 'toque', -0.4 + i * 0.25, 0.35);
255
+ }
256
+ // cards da esquerda apagam (cinza) quando a mão chega ao card escuro
257
+ for (i = 0; i < DESTAQUE; i++) {
258
+ var tn = fx(Ls[i], 'ADBE Tint');
259
+ Ls[i].property('ADBE Effect Parade').property(tn.name).property('ADBE Tint-0001').setValue(rgb('#3A3A3E'));
260
+ Ls[i].property('ADBE Effect Parade').property(tn.name).property('ADBE Tint-0002').setValue(rgb('#A6A6AB'));
261
+ K(Ls[i].property('ADBE Effect Parade').property(tn.name).property('ADBE Tint-0003'), [[5.87 + i * F(2), 0], [6.07 + i * F(2), 100]]);
262
+ }
263
+ // botões do card escuro: salvar (vira selo azul no clique), compartilhar, buscar
264
+ var bt = [];
265
+ for (i = 0; i < 3; i++) {
266
+ var b = circ(c, 'botao-' + i, 34, i == 0 ? '#FFFFFF' : '#2A2A2E', [0, 0]);
267
+ b.threeDLayer = true; b.parent = Ls[DESTAQUE]; P(b).setValue([258, 40 + i * 44, -1]);
268
+ K(O(b), [[5.62 + i * F(2), 0], [5.75 + i * F(2), 100]]);
269
+ bt.push(b);
270
+ }
271
+ var selo = circ(c, 'selo azul', 40, '#2F97E1', [0, 0]); selo.threeDLayer = true; selo.parent = Ls[DESTAQUE];
272
+ P(selo).setValue([258, 40, -2]);
273
+ K(S(selo), [[6.98, [0, 0, 100], 33, 10], [7.08, [115, 115, 100], 60, 60], [7.16, [100, 100, 100], 60, 33]]);
274
+ ev(6.95, 'clique', 0.3, 0.7); ev(7.02, 'selo', 0.3, 0.6);
275
+ // o card destaque some da pilha quando a cópia 2D assume (7,10)
276
+ K(O(Ls[DESTAQUE]), [[4.58 + DESTAQUE * F(1), 0], [4.62 + DESTAQUE * F(1), 100], [7.10, 100, -1, -1], [7.13, 0]]);
277
+ ev(4.47, 'card', 0, 0.6); ev(4.62, 'carta', 0, 0.6);
278
+ })();
279
+
280
+ // ================================================================ PALCO (cena branca inteira; a câmera é a âncora/escala da camada)
281
+ var PAL = novaComp('PALCO');
282
+ var BAR_Y = 540;
283
+ (function () {
284
+ var c = PAL;
285
+ // barra de busca (null BARRA: sobe para y 307 quando a pilha abre)
286
+ var NB = NUL(c, 'BARRA', [540, BAR_Y]);
287
+ K(P(NB), [[4.40, [540, 540], 50, 10], [5.00, [540, 307], 85, 33]]);
288
+ var barra = rr(c, 'barra', 144, 117, 58.5, '#C30B20', [0, 0]); barra.parent = NB; P(barra).setValue([0, 0]); mb(barra);
289
+ barra.inPoint = 2.45;
290
+ // estica 144→753 em 8 q (ease-out), rebote para 730 em 4 q
291
+ K(rectProp(barra, 'r', 'ADBE Vector Rect Size'), [[2.47, [144, 117], 33, 8], [2.73, [753, 117], 92, 30], [2.87, [730, 117], 70, 33]]);
292
+ K(cont(barra, 'r').property('ADBE Vector Graphic - Fill').property('ADBE Vector Fill Color'), [[2.47, rgb('#C30B20'), 33, 40], [2.58, rgb('#FFFFFF'), 70, 33]]);
293
+ var stb = cont(barra, 'r').addProperty('ADBE Vector Graphic - Stroke');
294
+ K(cont(barra, 'r').property('ADBE Vector Graphic - Stroke').property('ADBE Vector Stroke Color'), [[2.55, rgb('#E8505F')], [2.90, rgb('#CFCFD4')]]);
295
+ K(cont(barra, 'r').property('ADBE Vector Graphic - Stroke').property('ADBE Vector Stroke Width'), [[2.50, 0], [2.58, 8], [2.90, 3]]);
296
+ K(blur(barra), [[2.47, 20, 33, 10], [2.73, 0, 85, 33]]);
297
+ sombra(barra, 40, 10, 30);
298
+ var lupa = shape(c, 'lupa'); addEllipse(lupa, 'o', 30, 30, [-4, -4]); addStroke(lupa, 'o', '#3A3A3C', 4);
299
+ grupo(lupa, 'cabo'); var cb = cont(lupa, 'cabo').addProperty('ADBE Vector Shape - Rect'); cb.property('ADBE Vector Rect Size').setValue([14, 5]); cb.property('ADBE Vector Rect Position').setValue([14, 14]);
300
+ addFill(lupa, 'cabo', '#3A3A3C');
301
+ lupa.property('ADBE Root Vectors Group').property('cabo').property('ADBE Vector Transform Group').property('ADBE Vector Rotation').setValue(45);
302
+ lupa.parent = NB; P(lupa).setValue([-318, 0]);
303
+ K(O(lupa), [[2.72, 0], [2.86, 100]]);
304
+ var tx = TX(c, TEXTOS.busca, 'SFProText-Regular', 38, '#2C2C2E', [0, 0]); tx.parent = NB; P(tx).setValue([-282, 13]);
305
+ digita(tx, 1, [[2.63, 0, -1, -1], [2.95, 100, -1, -1]]);
306
+ var camI = shape(c, 'icone camera'); addRect(camI, 'r', 40, 30, 8); addStroke(camI, 'r', '#3A3A3C', 3.5);
307
+ addEllipse(camI, 'l', 13, 13); addStroke(camI, 'l', '#3A3A3C', 3.5);
308
+ camI.parent = NB; P(camI).setValue([322, 0]);
309
+ K(O(camI), [[2.72, 0], [2.86, 100], [4.30, 100], [4.38, 0]]);
310
+ // faixa rosa de "soltar aqui" (recortada pela barra: track matte numa cópia da barra)
311
+ var faixa = rr(c, 'faixa rosa', 240, 117, 0, '#F7C9D6', [0, 0]); faixa.parent = NB;
312
+ K(P(faixa), [[4.10, [-420, 0]], [4.30, [420, 0]]]); K(blur(faixa), [[4.1, 30]]);
313
+ faixa.inPoint = 4.08; faixa.outPoint = 4.32;
314
+ var molde = rr(c, 'molde barra', 730, 117, 58.5, '#FFFFFF', [0, 0]); molde.parent = NB; P(molde).setValue([0, 0]);
315
+ molde.inPoint = 4.08; molde.outPoint = 4.32;
316
+ faixa.moveAfter(molde); faixa.setTrackMatte(molde, TrackMatteType.ALPHA);
317
+ ev(2.47, 'morph', 0, 0.7); ev(2.63, 'digita', -0.3, 0.45); ev(4.12, 'brilho', 0, 0.4);
318
+
319
+ // print de moodboard arrastado pela mão (3,20–4,47) e que vira miniatura na barra
320
+ var pr = img(c, ASSETS + 'moodboard.png'); pr.name = 'print moodboard'; mb(pr);
321
+ var e0 = 250 / 900 * 100;
322
+ K(P(pr), [[3.20, [1320, 600], 33, 8], [3.60, [835, 588], 90, 50], [4.00, [828, 582], 'a'], [4.30, [832, 586], 50, 40], [4.45, [862, 540], 80, 33]]);
323
+ K(R(pr), [[3.20, 14, 33, 8], [3.60, 4, 90, 50], [3.85, -2, 'a'], [4.10, 3, 'a'], [4.30, 0, 50, 40]]);
324
+ K(S(pr), [[4.30, [e0, e0], 50, 30], [4.45, [7.5, 7.5], 80, 33]]);
325
+ sombra(pr, 45, 14, 30);
326
+ pr.inPoint = 3.18;
327
+ // a miniatura fica na barra (filha da barra depois de pousar): cópia parada
328
+ var mini = img(c, ASSETS + 'moodboard.png'); mini.name = 'miniatura'; mini.parent = NB; P(mini).setValue([322, 0]); S(mini).setValue([7.5, 7.5]);
329
+ mini.inPoint = 4.45; pr.outPoint = 4.46;
330
+ var mao = img(c, ASSETS + 'mao-agarra.png'); mao.name = 'mao agarrando'; mb(mao);
331
+ mao.parent = pr; P(mao).setValue([450, 140]); S(mao).setValue([30 / e0 * 100, 30 / e0 * 100]); // 180 px na tela
332
+ K(O(mao), [[4.28, 100], [4.38, 0]]);
333
+ mao.inPoint = 3.18; mao.outPoint = 4.4;
334
+ sombra(mao, 35, 10, 24);
335
+ ev(3.20, 'carry', 0.6, 0.7); ev(4.40, 'pouso', 0.3, 0.6);
336
+
337
+ // pilha 3D
338
+ var lp = c.layers.add(PIL); lp.name = 'PILHA'; lp.inPoint = 4.45; mb(lp);
339
+ P(lp).setValue([540, 613 - 540 + 540]);
340
+ // mão que aponta: passa pela pilha da esquerda para a direita e clica em salvar
341
+ var ma = img(c, ASSETS + 'mao-aponta.png'); ma.name = 'mao apontando'; mb(ma);
342
+ var em = 26;
343
+ S(ma).setValue([em, em]); A(ma).setValue([258, 60]); // ponta do indicador
344
+ K(P(ma), [[4.50, [620, 600], 33, 10], [4.80, [360, 690], 'a'], [4.97, [380, 660], 'a'], [5.17, [440, 668], 'a'], [5.37, [500, 668], 'a'], [5.57, [560, 660], 'a'],
345
+ [5.90, [600, 600], 'a'], [6.40, [638, 520], 'a'], [6.85, [650, 478], 50, 50], [7.05, [648, 480], 50, 50]]);
346
+ K(S(ma), [[6.90, [em, em], 50, 50], [6.95, [em * 0.85, em * 0.85], 50, 50], [7.02, [em, em], 50, 50]]);
347
+ K(O(ma), [[4.50, 0], [4.60, 100], [7.10, 100], [7.25, 0]]);
348
+ ma.inPoint = 4.48; ma.outPoint = 7.3;
349
+ sombra(ma, 35, 10, 24);
350
+
351
+ // tudo o que fica para trás quando o card destaque sai (7,10–7,30): desfoca e some
352
+ var fora = [barra, lupa, tx, camI, mini, lp, ma];
353
+ for (var i = 0; i < fora.length; i++) {
354
+ var bp = (fora[i] == barra) ? barra.property('ADBE Effect Parade').property(1).property(1) : blur(fora[i]);
355
+ if (fora[i] == barra) { bp.setValueAtTime(7.10, 0); bp.setValueAtTime(7.30, 40); }
356
+ else K(bp, [[7.10, 0, 33, 10], [7.30, 40, 85, 33]]);
357
+ var op = O(fora[i]);
358
+ if (op.numKeys == 0) K(op, [[7.10, 100], [7.30, 0]]);
359
+ else { op.setValueAtTime(7.10, 100); op.setValueAtTime(7.30, 0); }
360
+ }
361
+ // card destaque (cópia 2D do card escuro): endireita, cresce, reflexo azul, encolhe acelerando
362
+ var dq = c.layers.add(CARDS[DESTAQUE]); dq.name = 'card destaque'; dq.threeDLayer = true; mb(dq);
363
+ dq.inPoint = 7.10; dq.outPoint = 8.80;
364
+ K(P(dq), [[7.10, [560, 600, 0], 33, 10], [7.63, [540, 540, 0], 90, 33]]);
365
+ K(S(dq), [[7.10, [118, 118, 118], 33, 10], [7.63, [168, 168, 168], 90, 40], [8.00, [172, 172, 172], 40, 85], [8.73, [146, 146, 146], 10, 33]]);
366
+ K(R(dq), [[7.10, -8, 33, 10], [7.63, 0, 90, 33]]);
367
+ K(R3(dq, 'x'), [[7.10, 15, 33, 10], [7.63, 0, 90, 33]]);
368
+ sombra(dq, 45, 20, 50);
369
+ var sd = circ(c, 'selo destaque', 40, '#2F97E1', [0, 0]); sd.threeDLayer = true; sd.parent = dq; P(sd).setValue([258, 40, -1]);
370
+ sd.inPoint = 7.10; sd.outPoint = 8.80;
371
+ // reflexo azul: luz radial que cruza o card do canto superior direito ao inferior esquerdo (recortada pelo card)
372
+ var rf = solid(c, 'reflexo azul', '#000000', 300, 330); rf.threeDLayer = true; rf.parent = dq; P(rf).setValue([150, 165, -0.5]);
373
+ var rp = fx(rf, 'ADBE Ramp'); var rpn = rp.name;
374
+ rf.property('ADBE Effect Parade').property(rpn).property('ADBE Ramp-0005').setValue(2); // radial
375
+ rf.property('ADBE Effect Parade').property(rpn).property('ADBE Ramp-0002').setValue(rgb('#2F95FF'));
376
+ rf.property('ADBE Effect Parade').property(rpn).property('ADBE Ramp-0004').setValue(rgb('#000000'));
377
+ K(rf.property('ADBE Effect Parade').property(rpn).property('ADBE Ramp-0001'), [[7.58, [360, -40]], [7.92, [-60, 380]]]);
378
+ K(rf.property('ADBE Effect Parade').property(rpn).property('ADBE Ramp-0003'), [[7.58, [600, -40]], [7.92, [180, 380]]]);
379
+ rf.blendingMode = BlendingMode.ADD;
380
+ var mc = rr(c, 'molde destaque', 296, 326, 34, '#FFFFFF', [0, 0]); mc.threeDLayer = true; mc.parent = dq; P(mc).setValue([150, 165, -0.6]);
381
+ rf.moveBefore(dq); mc.moveBefore(rf); rf.setTrackMatte(mc, TrackMatteType.ALPHA);
382
+ rf.inPoint = mc.inPoint = 7.55; rf.outPoint = mc.outPoint = 7.95;
383
+ sd.moveBefore(mc);
384
+ ev(7.10, 'sobe', 0.2, 0.7); ev(7.60, 'brilho', 0, 0.55); ev(8.00, 'encolhe', 0, 0.5);
385
+ // fundo branco
386
+ var bg = solid(c, 'fundo branco', '#FFFFFF'); bg.moveToEnd();
387
+ })();
388
+
389
+ // ================================================================ GRADE escura (8,77–9,87)
390
+ var GR = novaComp('GRADE');
391
+ (function () {
392
+ var c = GR;
393
+ var bg = solid(c, 'fundo', '#000000');
394
+ var P0 = [540, 583], passo = 370;
395
+ for (var gy = -2; gy <= 2; gy++) for (var gx = -2; gx <= 2; gx++) {
396
+ if (gx == 0 && gy == 0) continue;
397
+ rr(c, 'tile ' + gx + ',' + gy, 330, 330, 44, '#151517', [P0[0] + gx * passo, P0[1] + gy * passo]);
398
+ }
399
+ var cd = c.layers.add(CARDS[DESTAQUE]); cd.name = 'card no quadro'; P(cd).setValue(P0); S(cd).setValue([108, 98]);
400
+ var contorno = shape(c, 'contorno branco'); addRect(contorno, 'r', 326, 326, 46); addStroke(contorno, 'r', '#FFFFFF', 3); P(contorno).setValue(P0);
401
+ var sd = circ(c, 'selo', 40, '#2F97E1', [P0[0] + 120, P0[1] - 125]);
402
+ var topo = rr(c, 'barra abas', 1080, 120, 0, '#000000', [540, 30]);
403
+ var X = [470, 560, 680];
404
+ for (var i = 0; i < 3; i++) TX(c, TEXTOS.abas[i], 'SFProText-Medium', 26, i == 0 ? '#FFFFFF' : '#BDBDC2', [X[i], 52], ParagraphJustification.CENTER_JUSTIFY);
405
+ rr(c, 'sublinhado', 50, 4, 2, '#FFFFFF', [X[0], 66]);
406
+ bg.moveToEnd();
407
+ })();
408
+
409
+ // ================================================================ RECRIACAO (comp final)
410
+ var M = proj.items.addComp('RECRIACAO', W, H, 1, DUR, FPS);
411
+ M.motionBlur = true; M.shutterAngle = 360; M.shutterPhase = -180; M.motionBlurSamplesPerFrame = 16;
412
+ var fundo = solid(M, 'fundo preto', '#000000');
413
+ // brilho vermelho escuro no canto de baixo à direita (desfoque sem repetir borda, senão vira caixa)
414
+ var brilho = circ(M, 'brilho vermelho', 1300, '#4A0000', [1060, 1180]);
415
+ var gb = blur(brilho); gb.setValue(320);
416
+ O(brilho).setValue(85);
417
+
418
+ // ---- frase: sai do desfoque (12 q), anda 90 px para a esquerda, sai palavra por palavra
419
+ var FR = NUL(M, 'FRASE', [540, 540]);
420
+ K(P(FR), [[0.10, [570, 540], -1, -1], [1.00, [480, 540], -1, -1]]);
421
+ var t1 = TX(M, TEXTOS.p1 + ' ', 'SFProDisplay-Semibold', 97, '#FFFFFF', [0, 0], ParagraphJustification.LEFT_JUSTIFY, -20);
422
+ var t2 = TX(M, TEXTOS.p2, 'SFProDisplay-Semibold', 97, '#FFFFFF', [0, 0], ParagraphJustification.LEFT_JUSTIFY, -20);
423
+ var t3 = TX(M, TEXTOS.interrogacao, 'SFProDisplay-Semibold', 97, '#D80007', [0, 0], ParagraphJustification.LEFT_JUSTIFY, -20);
424
+ var w1 = caixa(t1).width + 18, w2 = caixa(t2).width + 4, w3 = caixa(t3).width, tot = w1 + w2 + w3;
425
+ t1.parent = FR; t2.parent = FR;
426
+ P(t1).setValue([-tot / 2, 30]); P(t2).setValue([-tot / 2 + w1, 30]);
427
+ var palavras = [[t1, 0.17, 1.00], [t2, 0.17, 1.07]];
428
+ for (var i = 0; i < 2; i++) {
429
+ var L = palavras[i][0], te = palavras[i][1], ts = palavras[i][2];
430
+ var p0 = P(L).value;
431
+ K(O(L), [[te, 0, 33, 10], [te + F(12), 100, 85, 33], [ts, 100, 33, 33], [ts + F(8), 0, 33, 33]]);
432
+ K(blur(L), [[te, 25, 33, 10], [te + F(12), 0, 85, 33], [ts, 0, 60, 10], [ts + F(8), 30, 85, 33]]);
433
+ K(P(L), [[ts, p0, 60, 10], [ts + F(8), [p0[0] - 60, p0[1]], 85, 33]]);
434
+ mb(L);
435
+ }
436
+ ev(0.17, 'texto', 0, 0.5); ev(1.0, 'texto-sai', -0.3, 0.45);
437
+ // "?": entra 7 q depois, se solta em 1,00 s, sobe e gira em 3D (Y 0→180°) crescendo; em 1,47 vira o logo
438
+ t3.threeDLayer = true; mb(t3);
439
+ var off = -tot / 2 + w1 + w2 + w3 / 2 + 34; // centro do "?" em relação à frase (34 px de respiro)
440
+ A(t3).setValue([w3 / 2, -30]);
441
+ K(P(t3), [[0.10, [570 + off, 540, 0], -1, -1], [1.00, [480 + off, 540, 0], 40, 30], [1.20, [748, 468, 0], 'a'],
442
+ [1.30, [638, 390, 0], 'a'], [1.40, [520, 390, 0], 'a'], [1.47, [505, 420, 0], 'a'], [1.55, [508, 470, 0], 50, 33]]);
443
+ K(O(t3), [[0.23, 0], [0.23 + F(8), 100]]);
444
+ K(blur(t3), [[0.23, 25, 33, 10], [0.23 + F(8), 0, 85, 33], [1.40, 0, 33, 33], [1.55, 5, 33, 33]]);
445
+ K(S(t3), [[1.00, [100, 100, 100], 50, 30], [1.55, [260, 260, 260], 60, 33]]);
446
+ K(R3(t3, 'y'), [[1.00, 0, 50, 20], [1.55, 45, 60, 33]]);
447
+ t3.outPoint = 1.56;
448
+ ev(1.02, 'sobe', 0.4, 0.6);
449
+
450
+ // ---- clarão: preto → branco em 6 quadros lineares, no grave
451
+ var flash = solid(M, 'clarao branco', '#FFFFFF');
452
+ K(O(flash), [[1.53, 0, -1, -1], [1.73, 100, -1, -1]]);
453
+ flash.inPoint = 1.50;
454
+ ev(1.53, 'flash', 0, 0.8);
455
+
456
+ // ---- logo do Pinterest com espessura (giro tipo moeda), 240 px; anel; encolhe num ponto
457
+ var cam = M.layers.addCamera('camera', [540, 540]);
458
+ var zm = cam.property('ADBE Camera Options Group').property('ADBE Camera Zoom').value;
459
+ P(cam).setValue([540, 540, -zm]);
460
+ var LG = img(M, ASSETS + 'pinterest-logo.png'); LG.name = 'logo pinterest'; LG.threeDLayer = true; mb(LG);
461
+ var EL = 240 / 512 * 100;
462
+ K(P(LG), [[1.55, [508, 470, 0], 'a'], [1.60, [512, 560, 0], 'a'], [1.70, [522, 572, 0], 'a'], [1.80, [540, 548, 0], 'a'], [2.0, [540, 540, 0], 50, 33]]);
463
+ K(S(LG), [[1.55, [EL * 0.68, EL * 0.68, EL * 0.68], 33, 10], [1.60, [EL * 1.05, EL * 1.05, EL * 1.05], 'a'], [1.80, [EL, EL, EL], 50, 50],
464
+ [2.20, [EL, EL, EL], 50, 10], [2.47, [EL * 0.6, EL * 0.6, EL * 0.6], -1, 33]]);
465
+ K(R3(LG, 'y'), [[1.55, -45, 33, 10], [1.85, 0, 88, 33]]);
466
+ K(blur(LG), [[1.55, 8, 33, 10], [1.85, 0, 85, 33], [2.20, 0, 33, 33], [2.47, 22, -1, 33]]);
467
+ LG.inPoint = 1.54; LG.outPoint = 2.48;
468
+ // espessura: 8 cópias escuras atrás (z +3…+24), filhas do logo
469
+ for (var k = 1; k <= 8; k++) {
470
+ var ld = img(M, ASSETS + 'pinterest-lado.png'); ld.name = 'espessura ' + k; ld.threeDLayer = true;
471
+ ld.parent = LG; P(ld).setValue([256, 256, k * 6]); S(ld).setValue([99, 99, 100]); A(ld).setValue([256, 256, 0]);
472
+ ld.inPoint = 1.54; ld.outPoint = 2.2; ld.moveAfter(LG);
473
+ }
474
+ var anel = shape(M, 'anel rosado'); addEllipse(anel, 'o', 324, 324); addStroke(anel, 'o', '#F5C6CF', 6); P(anel).setValue([540, 540]);
475
+ K(S(anel), [[1.87, [90, 90], 33, 33], [2.07, [110, 110], 33, 33]]);
476
+ K(O(anel), [[1.87, 0], [1.95, 100], [2.07, 0]]);
477
+ anel.inPoint = 1.85; anel.outPoint = 2.1;
478
+ ev(1.87, 'anel', 0, 0.45); ev(2.23, 'encolhe', 0, 0.5);
479
+
480
+ // ---- palco branco (barra, mão, pilha, destaque) com a câmera: âncora = ponto focado, escala = zoom
481
+ var lP = M.layers.add(PAL); lP.name = 'PALCO'; lP.inPoint = F(74); lP.outPoint = 8.77; mb(lP);
482
+ K(A(lP), [[3.20, [540, 540], 33, 8], [3.60, [575, 552], 'a'], [4.00, [610, 562], 'a'], [4.30, [618, 564], 40, 30], [4.47, [540, 540], 75, 33]]);
483
+ K(S(lP), [[3.20, [100, 100], 33, 8], [3.60, [138, 138], 'a'], [4.00, [160, 160], 'a'], [4.30, [166, 166], 40, 30], [4.47, [100, 100], 75, 33]]);
484
+ K(blur(lP), [[4.30, 0, 33, 33], [4.37, 8, 33, 33], [4.44, 0, 33, 33]]);
485
+
486
+ // ---- corte seco para a grade escura; aproxima devagar e apaga
487
+ var lG = M.layers.add(GR); lG.name = 'GRADE'; lG.inPoint = 8.77; lG.outPoint = 9.90;
488
+ K(S(lG), [[8.77, [100, 100], -1, -1], [9.50, [106, 106], -1, 60]]);
489
+ K(P(lG), [[8.77, [540, 540], -1, -1], [9.50, [540, 560], -1, 60]]);
490
+ var apaga = solid(M, 'apaga', '#000000'); apaga.inPoint = 9.45; K(O(apaga), [[9.50, 0], [9.87, 100]]);
491
+ ev(8.77, 'tranco', 0, 0.6); ev(9.50, 'sai', 0, 0.4);
492
+
493
+ // ---- marca final: sai do desfoque com brilho; pulsa (desfoque + tremida de 2 q) nas batidas
494
+ var mk = shape(M, 'marca final');
495
+ addEllipse(mk, 'aro', 170, 170); addStroke(mk, 'aro', '#FFFFFF', 16);
496
+ grupo(mk, 'play');
497
+ var tri = cont(mk, 'play').addProperty('ADBE Vector Shape - Star');
498
+ tri.property('ADBE Vector Star Type').setValue(2); tri.property('ADBE Vector Star Points').setValue(3);
499
+ tri.property('ADBE Vector Star Outer Radius').setValue(46); tri.property('ADBE Vector Star Outer Roundess').setValue(30);
500
+ addFill(mk, 'play', '#FFFFFF');
501
+ mk.property('ADBE Root Vectors Group').property('play').property('ADBE Vector Transform Group').property('ADBE Vector Rotation').setValue(90);
502
+ mk.property('ADBE Root Vectors Group').property('play').property('ADBE Vector Transform Group').property('ADBE Vector Position').setValue([8, 0]);
503
+ P(mk).setValue([540, 540]); S(mk).setValue([180, 180]); mk.inPoint = 9.92; mk.outPoint = 10.97;
504
+ var PULSOS = [10.40, 10.50, 10.60, 10.77, 10.93];
505
+ var kb = [[9.93, 60, 33, 10], [10.23, 0, 85, 33]];
506
+ for (i = 0; i < PULSOS.length; i++) { kb.push([PULSOS[i] - F(1), 0, -1, -1]); kb.push([PULSOS[i], 25, -1, -1]); kb.push([PULSOS[i] + F(2), 0, -1, -1]); }
507
+ K(blur(mk), kb);
508
+ K(O(mk), [[9.93, 0], [9.93 + F(9), 100], [10.50 - F(1), 100, -1, -1], [10.50, 0, -1, -1], [10.50 + F(1), 100, -1, -1], [10.60, 100, -1, -1], [10.60 + F(1), 0, -1, -1], [10.60 + F(2), 100, -1, -1]]);
509
+ var gl = fx(mk, 'ADBE Glo2');
510
+ mk.property('ADBE Effect Parade').property(gl.name).property('ADBE Glo2-0003').setValue(60);
511
+ mk.property('ADBE Effect Parade').property(gl.name).property('ADBE Glo2-0004').setValue(1.5);
512
+ var pul = '[' + PULSOS.join(',') + ']';
513
+ P(mk).expression = 'var p=' + pul + ',on=0;for(var i=0;i<p.length;i++){if(time>=p[i]-0.034&&time<p[i]+0.067)on=1;}on?value+[random(-14,14),random(-10,10)]:value';
514
+ ev(9.93, 'logo', 0, 0.7);
515
+ for (i = 0; i < PULSOS.length; i++) ev(PULSOS[i], 'glitch', 0, 0.35);
516
+
517
+ // ordem (de cima para baixo): marca, apaga, grade, palco, anel, logo, espessura, câmera, clarão, frase, brilho, fundo
518
+ mk.moveToBeginning();
519
+ fundo.moveToEnd(); brilho.moveBefore(fundo);
520
+
521
+ // ================================================================ salvar e eventos de som
522
+ EVENTOS.sort(function (a, b) { return a.t - b.t; });
523
+ var out = new File(BASE.fsName + '/audio/eventos.json');
524
+ out.encoding = 'UTF-8'; out.open('w');
525
+ var linhas = [];
526
+ for (i = 0; i < EVENTOS.length; i++) { var e = EVENTOS[i]; linhas.push('{"t": ' + e.t + ', "kind": "' + e.kind + '", "pan": ' + (Math.round(e.pan * 100) / 100) + ', "v": ' + e.v + '}'); }
527
+ out.write('{"dur": ' + Math.round(DUR * 1000) / 1000 + ', "events": [\n' + linhas.join(',\n') + '\n]}\n'); out.close();
528
+ proj.save(new File(BASE.fsName + '/ae/pinterest-saas.aep'));
529
+ return 'ok: ' + M.numLayers + ' camadas, ' + EVENTOS.length + ' eventos';
530
+ })();