wizz-method 2.17.2 → 2.18.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 (41) hide show
  1. package/THIRD-PARTY-NOTICES.md +12 -0
  2. package/package.json +1 -1
  3. package/skills-registry.yaml +24 -6
  4. package/src/core-skills/_shared/handoff-protocol.md +3 -1
  5. package/src/modules/wizz/_shared/despacho-barato.md +1 -1
  6. package/src/modules/wizz/_shared/model-ladder.md +10 -0
  7. package/src/modules/wizz/_shared/video-pipeline.md +10 -0
  8. package/src/modules/wizz/agents/wizz-maestro/SKILL.md +1 -1
  9. package/src/modules/wizz/agents/wizz-social/SKILL.md +2 -0
  10. package/src/modules/wizz/agents/wizz-social/customize.toml +10 -0
  11. package/src/modules/wizz/subagents/codex/wizz-exec-standard.toml +1 -1
  12. package/src/modules/wizz/subagents/codex/wizz-exec-strong.toml +1 -1
  13. package/src/modules/wizz/subagents/gemini/wizz-exec-standard.md +1 -1
  14. package/src/modules/wizz/subagents/gemini/wizz-exec-strong.md +1 -1
  15. package/src/modules/wizz/subagents/opencode/wizz-exec-standard.md +1 -1
  16. package/src/modules/wizz/subagents/opencode/wizz-exec-strong.md +1 -1
  17. package/src/modules/wizz/subagents/spec.yaml +6 -6
  18. package/src/modules/wizz/subagents/wizz-exec-standard.md +1 -1
  19. package/src/modules/wizz/subagents/wizz-exec-strong.md +1 -1
  20. package/src/skills-lib/wizz-hook-extractor/LICENSE +21 -0
  21. package/src/skills-lib/wizz-hook-extractor/SKILL.md +56 -0
  22. package/src/skills-lib/wizz-hook-extractor/references/examples.md +59 -0
  23. package/src/skills-lib/wizz-hook-extractor/references/formulas.md +136 -0
  24. package/src/skills-lib/wizz-hook-extractor/scripts/read-post.sh +83 -0
  25. package/src/skills-lib/wizz-ig-profile-optimizer/LICENSE +21 -0
  26. package/src/skills-lib/wizz-ig-profile-optimizer/SKILL.md +74 -0
  27. package/src/skills-lib/wizz-ig-profile-optimizer/scripts/capture-profile.sh +41 -0
  28. package/src/skills-lib/wizz-ig-profile-optimizer/scripts/limits.mjs +82 -0
  29. package/src/skills-lib/wizz-router/references/routing-table-flat.md +3 -1
  30. package/src/skills-lib/wizz-video-effects/SKILL.md +1 -0
  31. package/src/skills-lib/wizz-video-styles/SKILL.md +9 -3
  32. package/src/skills-lib/wizz-video-styles/data/recipes.json +33 -1
  33. package/src/skills-lib/wizz-video-styles/data/references.json +175 -0
  34. package/src/skills-lib/wizz-video-styles/data/styles.json +55 -0
  35. package/src/skills-lib/wizz-video-styles/references/generated-prompts.md +60 -0
  36. package/src/skills-lib/wizz-video-styles/references/measured-patterns.md +2 -0
  37. package/src/skills-lib/wizz-video-styles/references/style-picker.md +5 -3
  38. package/src/skills-lib/wizz-video-styles/references/styles/tipografia-cinetica.md +68 -0
  39. package/src/skills-lib/wizz-video-styles/scripts/analyze.sh +2 -1
  40. package/src/skills-lib/wizz-video-styles/scripts/beat_grid.py +68 -0
  41. package/src/skills-lib/wizz-video-styles/scripts/references.mjs +264 -0
@@ -3393,5 +3393,180 @@
3393
3393
  "on_cuts": "0/2"
3394
3394
  },
3395
3395
  "lufs": "-14.4"
3396
+ },
3397
+ {
3398
+ "id": "5EoO5413dBY",
3399
+ "url": "https://www.youtube.com/watch?v=5EoO5413dBY",
3400
+ "channel": "mexicat",
3401
+ "views": "120706",
3402
+ "nicho": "i",
3403
+ "idioma": "en",
3404
+ "style": "tipografia-cinetica",
3405
+ "estilo_visual": "Clipe musical renderizado em código (three.js): fundo preto, uma palavra ou verso gigante por batida sobre cenas 3D (buraco negro, criatura, torre, grade em perspectiva), HUD de interface e formulários de papel",
3406
+ "motion_transicoes": "Troca de cena no downbeat, texto entra palavra a palavra no tempo da voz, câmera orbita objetos 3D, bloom e grão de filme, texto curvado em volta de objetos",
3407
+ "legenda": "A letra É o visual: palavra-chave gigante (sans bold ou serifa) + verso pequeno em mono no canto; nunca legenda embaixo",
3408
+ "hook_0_3s": "Linhas de código de terminal e uma palavra laranja enorme ('AGI') já no primeiro verso",
3409
+ "paleta": "preto, laranja incandescente, branco/creme; um respiro em papel bege",
3410
+ "tipografia": "sans grotesca pesada (Archivo), mono (IBM Plex Mono), serifa itálica (Cormorant) e fonte de traço único",
3411
+ "ritmo": {
3412
+ "cuts_per_10s": 3.57,
3413
+ "shot_median_s": 0.27
3414
+ },
3415
+ "musica": {
3416
+ "guess": "continua",
3417
+ "ratio": 0.326,
3418
+ "impressão": "heurística de áudio; nome da faixa não confirmado"
3419
+ },
3420
+ "sfx": {
3421
+ "counts": {
3422
+ "pop_click": 0,
3423
+ "whoosh": 29,
3424
+ "impact_low": 0
3425
+ },
3426
+ "per_10s": 1.85,
3427
+ "on_cuts": "5/56"
3428
+ },
3429
+ "lufs": "-15.5",
3430
+ "formato": "16:9 (horizontal); adaptar para 9:16"
3431
+ },
3432
+ {
3433
+ "id": "FOMWS5pChuA",
3434
+ "url": "https://www.youtube.com/watch?v=FOMWS5pChuA",
3435
+ "channel": "Ninh Truong",
3436
+ "views": "243944",
3437
+ "nicho": "i",
3438
+ "idioma": "en",
3439
+ "style": "tipografia-cinetica",
3440
+ "estilo_visual": "Lyric video em tipografia cinética: palavras da letra montadas como objetos num mundo 2D (mapa de ruas visto de cima, nuvens, rádio), fundo verde-petróleo",
3441
+ "motion_transicoes": "Câmera viaja e gira pelo mapa seguindo o verso, palavras dobram em 3D e se encaixam nas ruas, poucas trocas de cena (plano contínuo)",
3442
+ "legenda": "A letra é o visual: verso inteiro, palavras de pesos e tamanhos misturados, palavra-chave em destaque de cor",
3443
+ "hook_0_3s": "Letra 'I' gigante no escuro, depois o verso se monta em blocos",
3444
+ "paleta": "verde-petróleo escuro, verde-menta, coral/salmão de acento, cinza nas cenas de céu",
3445
+ "tipografia": "sans condensada em caixa alta misturada com sans fina e script; pesos alternados no mesmo verso",
3446
+ "ritmo": {
3447
+ "cuts_per_10s": 0.63,
3448
+ "shot_median_s": 9.92
3449
+ },
3450
+ "musica": {
3451
+ "guess": "continua",
3452
+ "ratio": 0.218,
3453
+ "impressão": "heurística de áudio; nome da faixa não confirmado"
3454
+ },
3455
+ "sfx": {
3456
+ "counts": {
3457
+ "pop_click": 0,
3458
+ "whoosh": 2,
3459
+ "impact_low": 0
3460
+ },
3461
+ "per_10s": 0.63,
3462
+ "on_cuts": "0/2"
3463
+ },
3464
+ "lufs": "-15.9",
3465
+ "formato": "16:9 (horizontal); adaptar para 9:16"
3466
+ },
3467
+ {
3468
+ "id": "Kt8vGm8_ekQ",
3469
+ "url": "https://www.youtube.com/watch?v=Kt8vGm8_ekQ",
3470
+ "channel": "PixelValet",
3471
+ "views": "928526",
3472
+ "nicho": "h",
3473
+ "idioma": "en",
3474
+ "style": "tipografia-cinetica",
3475
+ "estilo_visual": "Uma palavra por cena (emoções) no centro de um fundo de cor chapada; cada palavra é animada pelo significado dela (PAIN quebra, CHEERFUL pula em arco, LIGHT acende)",
3476
+ "motion_transicoes": "Uma bolinha guia passa de cena em cena; troca de fundo a cada palavra; a letra se deforma conforme o sentido",
3477
+ "legenda": "Sem legenda; a palavra é o único elemento",
3478
+ "hook_0_3s": "Fundo roxo, bolinha e a primeira palavra se desenhando",
3479
+ "paleta": "cores chapadas que mudam por emoção (roxo, amarelo, azul, verde, vermelho, cinza escuro)",
3480
+ "tipografia": "sans geométrica, uma família só, variando peso e espaçamento",
3481
+ "ritmo": {
3482
+ "cuts_per_10s": 0.68,
3483
+ "shot_median_s": 7.29
3484
+ },
3485
+ "musica": {
3486
+ "guess": "sem",
3487
+ "ratio": 0.021,
3488
+ "impressão": "heurística de áudio; nome da faixa não confirmado"
3489
+ },
3490
+ "sfx": {
3491
+ "counts": {
3492
+ "pop_click": 0,
3493
+ "whoosh": 78,
3494
+ "impact_low": 16
3495
+ },
3496
+ "per_10s": 21.18,
3497
+ "on_cuts": "1/3"
3498
+ },
3499
+ "lufs": "-22.5",
3500
+ "formato": "16:9 (horizontal); adaptar para 9:16"
3501
+ },
3502
+ {
3503
+ "id": "9ngNySFSWWU",
3504
+ "url": "https://www.youtube.com/watch?v=9ngNySFSWWU",
3505
+ "channel": "PiXeL ARTWORKS",
3506
+ "views": "1215529",
3507
+ "nicho": "d",
3508
+ "idioma": "en",
3509
+ "style": "tipografia-cinetica",
3510
+ "estilo_visual": "Texto pequeno branco no centro de fundo preto, alternando com fundo branco de papel; nada além do texto",
3511
+ "motion_transicoes": "Corte seco a cada frase no ritmo da narração/batida; palavras trocam de lugar e de caixa; sem objetos",
3512
+ "legenda": "O texto é a narração escrita, uma frase curta por vez",
3513
+ "hook_0_3s": "Logo do estúdio, depois 'fine good? ok' no preto",
3514
+ "paleta": "preto, branco, um vermelho só na abertura",
3515
+ "tipografia": "sans neutra pequena com tracking largo",
3516
+ "ritmo": {
3517
+ "cuts_per_10s": 4.62,
3518
+ "shot_median_s": 1.54
3519
+ },
3520
+ "musica": {
3521
+ "guess": "sem",
3522
+ "ratio": 0.0,
3523
+ "impressão": "heurística de áudio; nome da faixa não confirmado"
3524
+ },
3525
+ "sfx": {
3526
+ "counts": {
3527
+ "pop_click": 0,
3528
+ "whoosh": 44,
3529
+ "impact_low": 78
3530
+ },
3531
+ "per_10s": 28.2,
3532
+ "on_cuts": "16/20"
3533
+ },
3534
+ "lufs": "-8.9",
3535
+ "formato": "16:9 (horizontal); adaptar para 9:16"
3536
+ },
3537
+ {
3538
+ "id": "A0CKFb24MJ8",
3539
+ "url": "https://www.youtube.com/watch?v=A0CKFb24MJ8",
3540
+ "channel": "Cinthya Studios",
3541
+ "views": "353630",
3542
+ "nicho": "d",
3543
+ "idioma": "en",
3544
+ "style": "tipografia-cinetica",
3545
+ "estilo_visual": "Promo em tipografia cinética: palavras em caixa alta condensada que preenchem a tela, algumas com vídeo de cidade dentro das letras",
3546
+ "motion_transicoes": "Corte na batida, palavras escalam e deslizam, texto vira máscara de vídeo, ícone animado no fim",
3547
+ "legenda": "O texto é a mensagem de venda; uma ou duas palavras por vez",
3548
+ "hook_0_3s": "'CONVERT' em condensada preta no branco, inverte pra fundo preto",
3549
+ "paleta": "preto, branco, azul e vermelho só no logo final",
3550
+ "tipografia": "sans condensada em caixa alta (estilo Bebas), pesos variando",
3551
+ "ritmo": {
3552
+ "cuts_per_10s": 5.54,
3553
+ "shot_median_s": 1.32
3554
+ },
3555
+ "musica": {
3556
+ "guess": "continua",
3557
+ "ratio": 0.176,
3558
+ "impressão": "heurística de áudio; nome da faixa não confirmado"
3559
+ },
3560
+ "sfx": {
3561
+ "counts": {
3562
+ "pop_click": 0,
3563
+ "whoosh": 0,
3564
+ "impact_low": 46
3565
+ },
3566
+ "per_10s": 19.6,
3567
+ "on_cuts": "9/13"
3568
+ },
3569
+ "lufs": "-10.7",
3570
+ "formato": "16:9 (horizontal); adaptar para 9:16"
3396
3571
  }
3397
3572
  ]
@@ -722,5 +722,60 @@
722
722
  "url": "https://www.youtube.com/shorts/zKJSyVJB_yE"
723
723
  }
724
724
  ]
725
+ },
726
+ "tipografia-cinetica": {
727
+ "n": 5,
728
+ "nichos": [
729
+ "d",
730
+ "h",
731
+ "i"
732
+ ],
733
+ "langs": [
734
+ "en"
735
+ ],
736
+ "views_max": 1215529,
737
+ "views_median": 353630,
738
+ "cuts_per_10s": [
739
+ 0.63,
740
+ 3.57,
741
+ 5.54
742
+ ],
743
+ "shot_median_s": 1.54,
744
+ "music": {
745
+ "continua": 3,
746
+ "fraca": 0,
747
+ "sem": 2
748
+ },
749
+ "sfx_on_cuts": [
750
+ 31,
751
+ 94
752
+ ],
753
+ "top": [
754
+ {
755
+ "channel": "PiXeL ARTWORKS",
756
+ "views": "1215529",
757
+ "url": "https://www.youtube.com/watch?v=9ngNySFSWWU"
758
+ },
759
+ {
760
+ "channel": "PixelValet",
761
+ "views": "928526",
762
+ "url": "https://www.youtube.com/watch?v=Kt8vGm8_ekQ"
763
+ },
764
+ {
765
+ "channel": "Cinthya Studios",
766
+ "views": "353630",
767
+ "url": "https://www.youtube.com/watch?v=A0CKFb24MJ8"
768
+ },
769
+ {
770
+ "channel": "Ninh Truong",
771
+ "views": "243944",
772
+ "url": "https://www.youtube.com/watch?v=FOMWS5pChuA"
773
+ },
774
+ {
775
+ "channel": "mexicat",
776
+ "views": "120706",
777
+ "url": "https://www.youtube.com/watch?v=5EoO5413dBY"
778
+ }
779
+ ]
725
780
  }
726
781
  }
@@ -0,0 +1,60 @@
1
+ # Generated-video prompts, by catalogue style
2
+
3
+ Fifteen prompts picked from [awesome-opus5-5-videos](https://github.com/yihui-dev/awesome-opus5-5-videos) (513 entries in its `data/videos.json`, MIT, checked on 2026-10-10): videos that a model wrote as code (canvas, SVG, three.js) and that went viral. Each line says what the prompt asks for, in our words; the full prompt and the video are at the links. The prompts belong to their creators: link to them, quote at most a phrase, never paste the whole prompt into a project or a skill.
4
+
5
+ This page is a fixed sample. For current videos, and to skip the ones a project already used, run `node scripts/references.mjs pick --style <key>`.
6
+
7
+ Use this page **after** the style is chosen ([style-picker.md](style-picker.md)), to see how others briefed a model for that look. These are not measured references: none of them enter `data/references.json` unless one is measured with `scripts/analyze.sh`.
8
+
9
+ ## How a generated piece runs in the Method
10
+
11
+ - **HyperFrames draws, Remotion assembles** (`_shared/video-pipeline.md`, wizz module). A prompt that asks for "one HTML file with the music" becomes: scenes drawn silent in HyperFrames, assembled in Remotion with the audio.
12
+ - **Timing is measured, never guessed.** Words from `ctc-align`; cuts on the downbeats from [`scripts/beat_grid.py`](../scripts/beat_grid.py). Several prompts below ask for a "120 BPM grid" by hand; the script gives the real grid of the actual song.
13
+ - **Recompose for 9:16** when the original was square or horizontal: keyword in the upper-middle, nothing important in the bottom 20 %.
14
+
15
+ ## Kinetic typography and lyric video ([card](styles/tipografia-cinetica.md))
16
+
17
+ | Prompt | What it asks | Links |
18
+ |---|---|---|
19
+ | anabology · Claude Pop remake | Reimagine a whole pop song's video end to end with the same audio, every lyric represented on screen, free to go abstract. | [post](https://x.com/anabology/status/2103534482930491441) · [video](https://skillry.dev/ai-videos/opus-5-5/anabology-491441) |
20
+ | doubleunplussed · music video "like P(doom)" | Music video in the P(doom) style for another song, with references and lore instead of literal lyrics ("tokens" becomes a stochastic parrot). | [post](https://x.com/doubleunplussed/status/2103697580421181894) · [video](https://skillry.dev/ai-videos/opus-5-5/doubleunplussed-181894) |
21
+ | ParanoidAmerica · evil pizza parlour | A full music video synced to a `lyrics.txt`, one continuous camera journey through a place, collage plus ballpoint-pen look. | [post](https://x.com/ParanoidAmerica/status/2103570879619686717) · [video](https://skillry.dev/ai-videos/opus-5-5/paranoidamerica-686717) |
22
+ | twoclipping · wordmark launch film | A one-word brand built in one continuous take to a 120 BPM song with a drop and a breakdown; every scene grows out of the previous one, nothing fades or cuts. | [post](https://x.com/twoclipping/status/2103835273813496100) · [video](https://skillry.dev/ai-videos/opus-5-5/twoclipping-496100) |
23
+
24
+ ## Motion editorial and product UI ([card](styles/motion-editorial.md))
25
+
26
+ | Prompt | What it asks | Links |
27
+ |---|---|---|
28
+ | twoclipping · one shape, many UI states | One element morphs through 8 to 12 UI states (button, loader, player, chart), a cursor drives each change, springs, cut on a 120 BPM grid. | [post](https://x.com/twoclipping/status/2103273003555402193) · [video](https://skillry.dev/ai-videos/opus-5-5/twoclipping-402193) |
29
+ | verbove · product story in one canvas | The same morphing-shape idea as strict rules: one `draw(t)` function, real UI and real data, something on every beat, exports in 1:1, 16:9 and 9:16. | [post](https://x.com/verbove/status/2103483957266268381) · [video](https://skillry.dev/ai-videos/opus-5-5/verbove-268381) |
30
+ | AnnaCher · promo from the product's own UI | Same structure built from the real product UI, one accent colour, last frame equals the first so it loops; a long banned list (glows, particles, bouncy easing). | [post](https://x.com/AnnaCher___/status/2103571096549433425) · [video](https://skillry.dev/ai-videos/opus-5-5/annacher-433425) |
31
+ | jhylee95 · launch video | Research the product, hook in the first second, distinct beats for proof, every cut and hit retimed until it lands on a beat or drop. | [post](https://x.com/jhylee95/status/2103604431627452427) · [video](https://skillry.dev/ai-videos/opus-5-5/jhylee95-452427) |
32
+ | twoclipping · minimal launch with real footage | 10 bars at 120 BPM, one idea per shot, masked type reveals and match cuts over the owner's real vertical clips; no placeholder cards. | [post](https://x.com/twoclipping/status/2102554209166000267) · [video](https://skillry.dev/ai-videos/opus-5-5/twoclipping-000267) |
33
+ | Mounnna · logo reveal | Logo drawn as a wireframe, low-poly shards fly in and assemble it, then the icon background and the typed brand name. A 3 to 5 s sting for the CTA. | [post](https://x.com/Mounnna/status/2103802871934497266) · [video](https://skillry.dev/ai-videos/opus-5-5/mounnna-497266) |
34
+
35
+ ## Animated explainer ([card](styles/explicador-animado.md))
36
+
37
+ | Prompt | What it asks | Links |
38
+ |---|---|---|
39
+ | alex_prompter · 30 s business explainer | Five scenes: the customer's problem, what you do, how it works in 3 steps, one proof point, your name. The simplest brief that works. | [post](https://x.com/alex_prompter/status/2103499977632997524) · [video](https://skillry.dev/ai-videos/opus-5-5/alex-prompter-997524) |
40
+ | emollick · recursion | Explain one idea where each explanation switches to a radically different visual style; self-referential and fast. | [post](https://x.com/emollick/status/2103688362960019567) · [video](https://skillry.dev/ai-videos/opus-5-5/emollick-019567) |
41
+ | koldo2k · infinite zoom loop | A looping camera flight from landscape to landscape through vintage objects, collage and halftone look, film grain. | [post](https://x.com/koldo2k/status/2103129343253778767) · [video](https://skillry.dev/ai-videos/opus-5-5/koldo2k-778767) |
42
+
43
+ ## Whiteboard ([card](styles/quadro-branco.md))
44
+
45
+ | Prompt | What it asks | Links |
46
+ |---|---|---|
47
+ | tak3sh8 · hand-drawn physics | Hand-drawn whiteboard animation of a hard concept, then a second prompt turning it into an MP4 with narration. | [post](https://x.com/tak3sh8/status/2103667481139441895) · [video](https://skillry.dev/ai-videos/opus-5-5/tak3sh8-441895) |
48
+
49
+ ## Fast meme ([card](styles/meme-rapido.md))
50
+
51
+ | Prompt | What it asks | Links |
52
+ |---|---|---|
53
+ | kloss_xyz · 9:16 brain rot | A chaotic vertical video generated in Python and rendered with ffmpeg, with motion and sound design, told from the model's point of view. | [post](https://x.com/kloss_xyz/status/2103664956482941143) · [video](https://skillry.dev/ai-videos/opus-5-5/kloss-xyz-941143) |
54
+
55
+ ## What the good ones share
56
+
57
+ - **Inputs first.** The strongest prompts open with an `<inputs>` block: ask for the real product, the real UI states, the real data, the brand colour and the song before drawing anything.
58
+ - **A banned list.** Glows, particle bursts, RGB split, camera shake, bouncy easing: naming what not to do does more than adjectives.
59
+ - **One rule for continuity.** "One shape, never cut" or "every scene is made out of the previous one" gives the piece its identity.
60
+ - **The beat as the clock.** Every change lands on a beat or a drop. Here that clock comes from `beat_grid.py`, not from a hand-typed BPM.
@@ -2,6 +2,8 @@
2
2
 
3
3
  Set measured on 2026-10-04: **99 public shorts**, 46 in English and 53 in Brazilian Portuguese, 8 niche groups (9 to 16 per group), views from 23,718 to 107,324,401 (median 608,820). Per-style numbers live in [`data/styles.json`](../data/styles.json) and at the top of each card; this page keeps only what holds across styles. Method and limits: [research-method.md](research-method.md).
4
4
 
5
+ Added on 2026-10-10: 5 kinetic typography and lyric videos (style `tipografia-cinetica`, all 16:9, a 9th niche group: music). They are in the per-style numbers and their card, but not in the cross-style aggregates below, which still describe the 99 vertical shorts.
6
+
5
7
  ## Sound effects are rare
6
8
 
7
9
  | | Cuts with a sound effect on them |
@@ -7,6 +7,7 @@ The material decides which styles are **possible**. Niche and goal only rank the
7
7
  | What the project has | Possible styles |
8
8
  |---|---|
9
9
  | Voice only (own recording or TTS), no one on camera | [motion-editorial](styles/motion-editorial.md), [explicador-animado](styles/explicador-animado.md), [meme-rapido](styles/meme-rapido.md) |
10
+ | A song with its lyrics, or a voice-over or slogan with no footage at all | [tipografia-cinetica](styles/tipografia-cinetica.md) (the words are the image; scenes generated in code) |
10
11
  | Voice + app/site screens | [motion-editorial](styles/motion-editorial.md) (screenshots in a phone card), [camera-no-setup](styles/camera-no-setup.md) (film the screen), [meme-rapido](styles/meme-rapido.md) |
11
12
  | A person on camera talking, nothing else | [talking-head-legenda](styles/talking-head-legenda.md) |
12
13
  | A person on camera + headlines, articles, charts, b-roll | [talking-head-cards](styles/talking-head-cards.md) (face bubble over full-screen b-roll is a variant) |
@@ -31,18 +32,19 @@ From [`data/references.json`](../data/references.json): the styles measured in e
31
32
  | dev / AI / build in public (EN) | meme-rapido (8.8M), camera-no-setup (8.1M), talking-head-legenda (5.4M), quadro-branco (4.4M), motion-editorial (0.83M), talking-head-cards (0.82M), podcast-clip (0.48M) |
32
33
  | dev / AI / tech business (BR) | quadro-branco (1.1M), talking-head-cards (0.41M), talking-head-legenda (0.26M), meme-rapido (0.23M), camera-no-setup (0.11M) |
33
34
  | personal finance / investing | podcast-clip (1.2M), talking-head-cards (1.2M), talking-head-legenda (0.77M) |
34
- | product / SaaS / marketing / business / law | desafio-numero (20.9M), talking-head-legenda (9.8M), camera-no-setup (0.53M), podcast-clip (0.33M), quadro-branco (0.15M), talking-head-cards (0.09M) |
35
+ | product / SaaS / marketing / business / law | desafio-numero (20.9M), talking-head-legenda (9.8M), tipografia-cinetica (1.2M), camera-no-setup (0.53M), podcast-clip (0.33M), quadro-branco (0.15M), talking-head-cards (0.09M) |
35
36
  | health / fitness / nutrition | explicador-animado (33.4M), podcast-clip (9.8M), quadro-branco (0.61M), macro-asmr (0.54M), talking-head-cards (0.43M), desafio-numero (0.22M) |
36
37
  | food / recipes / lifestyle / travel | desafio-numero (107M), pov-vlog (8.7M), macro-asmr (7.7M), tour (1.05M) |
37
38
  | beauty / fashion / local services (clinic, salon, architecture, real estate) | macro-asmr (10.6M), talking-head-legenda (3.8M), talking-head-cards (2.0M), pov-vlog (1.4M), tour (0.37M) |
38
- | education / science / comedy | experimento (49M), explicador-animado (4.7M), esquete (2.9M), talking-head-cards (2.2M), talking-head-legenda (1.7M) |
39
+ | education / science / comedy | experimento (49M), explicador-animado (4.7M), esquete (2.9M), talking-head-cards (2.2M), talking-head-legenda (1.7M), tipografia-cinetica (0.93M) |
40
+ | music / artists / lyric videos | tipografia-cinetica (0.24M) |
39
41
 
40
42
  BR local services (clinic, salon, law, architecture), BR travel and BR sales/marketing were filled with a second pass (300k to 10.6M views). Still thin: BR software/SaaS proper (only sales/marketing found), real-estate agents in BR, and every niche has 9 to 16 references, not hundreds. When a niche is missing, pick by material and by the closest niche, and say the reference is borrowed.
41
43
 
42
44
  ## 3. Goal → tie-breaker
43
45
 
44
46
  - **Saves and comments (teach, explain a system):** motion-editorial, explicador-animado, quadro-branco, talking-head-cards.
45
- - **Reach and shares (curiosity, humour):** desafio-numero, experimento, meme-rapido, esquete, pov-vlog.
47
+ - **Reach and shares (curiosity, humour):** desafio-numero, experimento, meme-rapido, esquete, pov-vlog, tipografia-cinetica (music and manifestos).
46
48
  - **Trust and authority (a person the audience should know):** talking-head-legenda, podcast-clip, camera-no-setup.
47
49
  - **Desire for a product:** macro-asmr, desafio-numero, camera-no-setup.
48
50
 
@@ -0,0 +1,68 @@
1
+ # Kinetic typography and lyric video (mexicat P(doom), PixelValet, Ninh Truong)
2
+
3
+ Measured on 5 shorts (en) in: product / SaaS / marketing / business / law, education / science / comedy, music / artists / lyric videos.
4
+
5
+ ## Measured
6
+
7
+ | Metric | Value |
8
+ |---|---|
9
+ | Reach (views) | max 1,215,529 · median 353,630 |
10
+ | Cuts per 10 s | min 0.63 · median 3.57 · max 5.54 |
11
+ | Median scene length | 1.54 s |
12
+ | Music bed (continuous / faint / none) | 3 / 0 / 2 |
13
+ | Cuts with a sound effect on them | 31/94 (33%) |
14
+
15
+ Cuts come from scene detection (it undercounts overlays and cards); music and SFX from an audio heuristic that classifies type, never names the sound ([../research-method.md](../research-method.md)).
16
+
17
+ ## Material it needs
18
+
19
+ An audio track with words: a song with its lyrics, or a voice-over with its script. Nobody on camera, no footage. Everything is generated (HyperFrames, three.js, canvas). Word timing from ctc-align; a beat grid when there is music.
20
+
21
+ ## When it fits
22
+
23
+ Music releases and lyric videos, manifestos, a strong opinion read aloud, brand promos built on a slogan, poetry. Shares and rewatches; weak for teaching step by step.
24
+
25
+ ## Recipe
26
+
27
+ **Look**
28
+
29
+ - The words ARE the image: one keyword huge in the frame, the rest of the line small. No caption strip at the bottom.
30
+ - Plain background (black, or a flat colour that changes per section) or one generated world the camera travels through (a map, a grid in perspective, a 3D object the line wraps around).
31
+ - Each word is animated by what it means: PAIN breaks, CHEERFUL bounces, LIGHT lights up, a word curves around the object it names.
32
+ - Code-rendered pieces add film treatment: bloom, halation, grain, a thin HUD in mono.
33
+
34
+ **Palette:** Dark base (#0A0A0A or a deep teal #0F3B3A) plus ONE glowing accent (orange #FF6A1A in P(doom), coral in Maps) and off-white text. Flat-colour variant: one saturated background per word or section, text in white or ink.
35
+
36
+ **Typography:** Two or three families with high contrast: a heavy grotesk or condensed caps for the keyword (Archivo Black, Bebas Neue), a mono for small lines and HUD (IBM Plex Mono), optionally a serif italic for a soft word (Cormorant Garamond). Mix weights inside the same line.
37
+
38
+ **Motion**
39
+
40
+ - Words enter on the syllable they are sung or spoken (forced alignment, never guessed); the keyword lands on the beat.
41
+ - Scene changes snap to the downbeat. P(doom) changes every ~0.3 s at peaks; the calm variant is a single continuous camera move for a whole verse.
42
+ - The camera moves through the type (push, orbit, travel across a map) instead of the text sliding over a still frame.
43
+ - Hold the last word of a line a beat longer before it leaves.
44
+
45
+ **Captions:** None separate: the type is the caption. Keep the full line readable somewhere (small, mono, corner) when the keyword alone would lose the sense.
46
+
47
+ **Hook (0 to 3 s):** The first sung or spoken word, huge, in the accent colour, landing on the first downbeat (0 to 1 s). No logo intro.
48
+
49
+ **CTA:** The title or slogan locked up big and still for 1 to 2 s, the accent lit; one small line (artist, handle, link) under it.
50
+
51
+ **Music:** The track itself is the whole soundtrack. Lyric videos: song at full level, no extra bed. Voice-over promos: a beat-driven bed under the voice.
52
+
53
+ **SFX:** Song-driven pieces: almost none (5 of 56 cuts in P(doom), 0 of 2 in Maps). Promo variant: hits on every word change (9/13 and 16/20 cuts), which the heuristic partly confuses with the kick. Never add whooshes over a song.
54
+
55
+ ## Do not
56
+
57
+ - Karaoke subtitles at the bottom over a static background: that is a lyric 'overlay', not this style.
58
+ - Guessing word timing by ear; align it (ctc-align) and snap scenes to the beat grid.
59
+ - More than one accent colour, or a different font for every word.
60
+ - Shipping 16:9: every measured reference is horizontal; recompose for 9:16 with the keyword in the upper-middle and nothing in the bottom 20%.
61
+
62
+ ## Watch before editing
63
+
64
+ - [PiXeL ARTWORKS](https://www.youtube.com/watch?v=9ngNySFSWWU) · 1,215,529 views
65
+ - [PixelValet](https://www.youtube.com/watch?v=Kt8vGm8_ekQ) · 928,526 views
66
+ - [Cinthya Studios](https://www.youtube.com/watch?v=A0CKFb24MJ8) · 353,630 views
67
+ - [Ninh Truong](https://www.youtube.com/watch?v=FOMWS5pChuA) · 243,944 views
68
+ - [mexicat](https://www.youtube.com/watch?v=5EoO5413dBY) · 120,706 views
@@ -9,7 +9,8 @@ id="$1"; out="$2"
9
9
  [[ "$id" =~ ^[A-Za-z0-9_-]{11}$ ]] || { echo "id inválido: $id" >&2; exit 2; }
10
10
  mkdir -p "$out"; cd "$out"
11
11
  f="./$id" # prefixo ./ : ID que começa com hífen não vira opção do ffmpeg
12
- trap 'rm -f "$f.wav" "$f.mp4"' EXIT
12
+ # .part: a first download that fails (HTTP 403) leaves it behind before the android fallback runs.
13
+ trap 'rm -f "$f.wav" "$f.mp4" "$f".*.part' EXIT
13
14
  # Python with librosa + numpy: set VIDEO_STYLES_PY to a venv python, or python3 must have them.
14
15
  PY="${VIDEO_STYLES_PY:-python3}"
15
16
  "$PY" -c "import librosa, numpy" 2>/dev/null || { echo "precisa de librosa e numpy: pip install librosa numpy (ou VIDEO_STYLES_PY=/caminho/do/python)" >&2; exit 2; }
@@ -0,0 +1,68 @@
1
+ """Beat grid of a song: tempo, beats and downbeats, so scene cuts can snap to the music.
2
+
3
+ Usage: python3 beat_grid.py <audio_file> [--meter 4] [--fps 30] > grid.json
4
+
5
+ Prints JSON: {"bpm", "meter", "duration_s", "beats": [s...], "downbeats": [s...],
6
+ "downbeat_frames": [frame...]}. Needs librosa + numpy (same Python as analyze.sh;
7
+ set VIDEO_STYLES_PY and call it with that interpreter).
8
+
9
+ Downbeats are estimated, not detected: of the `meter` possible phases, the one
10
+ whose beats carry the most low-frequency onset energy is taken as beat 1. Check
11
+ two or three of them by ear before cutting a whole film on the grid.
12
+ """
13
+
14
+ import argparse
15
+ import json
16
+ import sys
17
+
18
+ import librosa
19
+ import numpy as np
20
+
21
+ HOP = 512
22
+ LOW_HZ = 150
23
+
24
+
25
+ def downbeat_phase(y_perc, sr, beat_frames, meter):
26
+ spec = np.abs(librosa.stft(y_perc, hop_length=HOP))
27
+ freqs = librosa.fft_frequencies(sr=sr)
28
+ low_energy = spec[freqs < LOW_HZ].sum(axis=0)
29
+ at_beats = low_energy[np.minimum(beat_frames, len(low_energy) - 1)]
30
+ scores = [at_beats[phase::meter].mean() if len(at_beats[phase::meter]) else 0.0 for phase in range(meter)]
31
+ return int(np.argmax(scores))
32
+
33
+
34
+ def beat_grid(path, meter, fps):
35
+ y, sr = librosa.load(path, sr=22050, mono=True)
36
+ _, y_perc = librosa.effects.hpss(y)
37
+ _, beat_frames = librosa.beat.beat_track(y=y_perc, sr=sr, hop_length=HOP)
38
+ if len(beat_frames) < meter:
39
+ sys.exit(f"too few beats found in {path}: {len(beat_frames)} (is there a steady rhythm?)")
40
+ beats = librosa.frames_to_time(beat_frames, sr=sr, hop_length=HOP)
41
+ phase = downbeat_phase(y_perc, sr, beat_frames, meter)
42
+ downbeats = beats[phase::meter]
43
+ return {
44
+ # librosa's tempo and single beat intervals are quantised to the hop; the slope of a
45
+ # line fitted through every beat time averages that out.
46
+ "bpm": round(60.0 / float(np.polyfit(np.arange(len(beats)), beats, 1)[0]), 3),
47
+ "meter": meter,
48
+ "duration_s": round(len(y) / sr, 3),
49
+ "beats": [round(float(t), 3) for t in beats],
50
+ "downbeats": [round(float(t), 3) for t in downbeats],
51
+ "downbeat_frames": [int(round(t * fps)) for t in downbeats],
52
+ }
53
+
54
+
55
+ def main():
56
+ parser = argparse.ArgumentParser(description=__doc__.split("\n")[0])
57
+ parser.add_argument("audio")
58
+ parser.add_argument("--meter", type=int, default=4)
59
+ parser.add_argument("--fps", type=int, default=30)
60
+ args = parser.parse_args()
61
+ if args.meter < 2 or args.fps < 1:
62
+ sys.exit("--meter must be >= 2 and --fps >= 1")
63
+ json.dump(beat_grid(args.audio, args.meter, args.fps), sys.stdout, indent=1)
64
+ print()
65
+
66
+
67
+ if __name__ == "__main__":
68
+ main()