primocode 9.10.0 → 10.0.9
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.
- package/README.md +30 -6
- package/bin/primocode.js +169 -342
- package/lib/act.js +360 -39
- package/lib/browser.js +105 -4
- package/lib/casar.js +108 -0
- package/lib/catalogo.js +6 -2
- package/lib/claude-engine.js +38 -17
- package/lib/codex-engine.js +27 -9
- package/lib/config.js +10 -3
- package/lib/cursor.js +10 -1
- package/lib/entrada.js +77 -11
- package/lib/estudio/cinema.js +27 -9
- package/lib/estudio/diretor.js +21 -1
- package/lib/estudio/ende.js +16 -5
- package/lib/estudio/estilo.js +66 -0
- package/lib/estudio/gerativo.js +1453 -0
- package/lib/estudio/glifos.js +215 -0
- package/lib/estudio/hibrido.js +165 -0
- package/lib/estudio/index.js +284 -53
- package/lib/estudio/kit/base.jsx +285 -0
- package/lib/estudio/kit/gerativo.jsx +980 -0
- package/lib/estudio/kit/index.jsx +13 -0
- package/lib/estudio/kit/marca.jsx +741 -0
- package/lib/estudio/kit/tres.jsx +308 -0
- package/lib/estudio/kit/vox.jsx +357 -0
- package/lib/estudio/kit.js +78 -0
- package/lib/estudio/lancamento.js +441 -0
- package/lib/estudio/motion.js +2 -5
- package/lib/estudio/plano.js +28 -3
- package/lib/estudio/referencias.js +105 -0
- package/lib/estudio/remotion.js +139 -51
- package/lib/estudio/ritmo.js +77 -0
- package/lib/estudio/sons-leves.js +38 -1
- package/lib/estudio/variedade.js +105 -0
- package/lib/estudio/vox.js +414 -0
- package/lib/fala.js +1 -94
- package/lib/mcp.js +156 -0
- package/lib/personas.js +67 -0
- package/lib/pipeline.js +55 -56
- package/lib/repeticao.js +3 -1
- package/lib/skills.js +44 -2
- package/lib/snapshot.js +111 -0
- package/lib/tools.js +100 -22
- package/lib/ui.js +50 -8
- package/lib/video/analise.js +89 -0
- package/lib/video/auto.js +329 -0
- package/lib/video/camadas.js +207 -0
- package/lib/video/cli.js +74 -0
- package/lib/video/delta.js +90 -0
- package/lib/video/edits.js +379 -0
- package/lib/video/filters.js +280 -0
- package/lib/video/fx3d/Camadas.jsx +64 -0
- package/lib/video/fx3d/Objetos.jsx +128 -0
- package/lib/video/fx3d/Root.jsx +18 -0
- package/lib/video/fx3d/modelos.jsx +304 -0
- package/lib/video/fx3d.js +108 -0
- package/lib/video/gerados.js +119 -0
- package/lib/video/objetos.js +111 -0
- package/lib/video/ops-fx.js +453 -0
- package/lib/video/ops.js +347 -0
- package/lib/video/paralelo.js +50 -0
- package/lib/video/pedido.js +191 -0
- package/lib/video/projeto.js +133 -0
- package/lib/video/rastrear.js +95 -0
- package/lib/video/rastro.js +276 -0
- package/lib/video/render.js +274 -0
- package/lib/video/texto.js +144 -0
- package/lib/video/timeline.js +318 -0
- package/lib/video/transcript.js +124 -0
- package/lib/voz.js +75 -223
- package/package.json +2 -3
- package/skills/motion-de-primeira/SKILL.md +5 -5
- package/studio/narrar.py +10 -7
- package/studio/rastrear.py +399 -0
- package/studio/texto.py +208 -0
- package/voz/primo_voz/__main__.py +96 -236
- package/voz/primo_voz/transcrever.py +31 -1
- package/app/ansi.js +0 -55
- package/app/app.css +0 -500
- package/app/app.js +0 -1017
- package/app/icone.svg +0 -6
- package/app/index.html +0 -220
- package/app/primo-marca.js +0 -192
- package/lib/app.js +0 -615
- package/lib/icone.js +0 -263
- package/lib/instalar-app.js +0 -231
- package/lib/painel.js +0 -291
- package/voz/primo_voz/desperta.py +0 -195
- package/voz/primo_voz/orbe.py +0 -406
package/lib/estudio/cinema.js
CHANGED
|
@@ -34,7 +34,7 @@ const tokens = (t) => String(t || '').normalize('NFD').replace(/[̀-ͯ]/g, '').t
|
|
|
34
34
|
/** Quanto tempo um texto precisa ficar na tela para ser lido. Nunca menos que
|
|
35
35
|
0,3 s por palavra: a regra de legibilidade do /brag (Arthur, 28/09). */
|
|
36
36
|
const nPalavras = (t) => String(t || '').split(/\s+/).filter(Boolean).length;
|
|
37
|
-
const
|
|
37
|
+
const leituraCheia = (t) => Math.max(0.55 + 0.22 * nPalavras(t), 0.3 * nPalavras(t));
|
|
38
38
|
|
|
39
39
|
/** A fala desta parte (o que a voz diz): a "fala", ou os textos da tela. */
|
|
40
40
|
/* A voz lê EXATAMENTE o que está na tela, na ordem da tela ("a narração tem
|
|
@@ -94,12 +94,23 @@ function quando(textos, palavras, dur, t0 = 0.25) {
|
|
|
94
94
|
});
|
|
95
95
|
}
|
|
96
96
|
|
|
97
|
-
function montarCinema({ roteiro, largura = 1920, altura = 1080, tempos = [], narracao = null, sons = {}, trilha = null, fotos = [], fortes = {} }) {
|
|
97
|
+
function montarCinema({ roteiro, largura = 1920, altura = 1080, tempos = [], narracao = null, sons = {}, trilha = null, fotos = [], fortes = {}, ritmoLeitura = 1 }) {
|
|
98
|
+
/* O tempo de ler cada texto, escalado: o cinema puro dá o tempo inteiro
|
|
99
|
+
(1); o híbrido, que tem b-roll trocando por baixo e texto curto, dá
|
|
100
|
+
pouco mais da metade — senão a cena espera muito depois da voz. */
|
|
101
|
+
const leitura = (t) => leituraCheia(t) * ritmoLeitura;
|
|
98
102
|
const partes = (roteiro && roteiro.partes) || [];
|
|
99
103
|
if (!partes.length) return { ok: false, error: 'o roteiro veio sem partes.' };
|
|
100
104
|
const marca = roteiro.marca || {};
|
|
101
|
-
|
|
102
|
-
|
|
105
|
+
/* O destaque é o da MARCA: sem gradiente declarado, a cor de destaque dela
|
|
106
|
+
vira o gradiente (antes caía no roxo da Paris em toda marca). */
|
|
107
|
+
const corD = marca.cores && /^#[0-9a-f]{6}$/i.test(marca.cores.destaque || '') ? marca.cores.destaque : null;
|
|
108
|
+
const grad = marca.gradiente && marca.gradiente.length >= 2 ? marca.gradiente : corD ? [corD, corD] : ['#2E81ED', '#9567DB'];
|
|
109
|
+
/* O cinema é ESCURO: o texto é branco. Marca de fundo claro (a Anthropic é
|
|
110
|
+
branca) deixava o texto invisível — o fundo dela só vale se for escuro. */
|
|
111
|
+
const luz = (h) => { const n = parseInt(String(h).slice(1), 16); return ((n >> 16 & 255) * 0.299 + (n >> 8 & 255) * 0.587 + (n & 255) * 0.114) / 255; };
|
|
112
|
+
const fundoMarca = marca.cores && /^#[0-9a-f]{6}$/i.test(marca.cores.fundo || '') ? marca.cores.fundo : null;
|
|
113
|
+
const PRETO = fundoMarca && luz(fundoMarca) < 0.25 ? fundoMarca : '#07070A';
|
|
103
114
|
const BRANCO = '#F5F5F7';
|
|
104
115
|
const DEST = grad[1];
|
|
105
116
|
const F = { titulo: (marca.fontes && marca.fontes.titulo) || 'Inter', texto: (marca.fontes && marca.fontes.texto) || 'Inter' };
|
|
@@ -279,12 +290,19 @@ function montarCinema({ roteiro, largura = 1920, altura = 1080, tempos = [], nar
|
|
|
279
290
|
vol(t, 0.3);
|
|
280
291
|
for (let a = 0; a < dur; a += 1.2) pFoto(els, foto(), a, Math.min(dur, a + 1.2), { veu: 0.45 });
|
|
281
292
|
textosDaParte.forEach((x, k) => {
|
|
282
|
-
|
|
293
|
+
/* O valor pode vir com prefixo e unidade: "até 30% mais barato", "+120
|
|
294
|
+
marcas", "2,5x mais rápido". O contador sobe só a parte numérica e
|
|
295
|
+
mantém o resto em volta (contar.antes / contar.depois). */
|
|
296
|
+
const mv = String(x).match(/^((?:at[ée]|mais de|\+|-)?\s*)(\d+(?:[.,]\d+)?)(\s?(?:%|x|mil|mi|bi|k|h|s|min)?)\s+(.*)$/i);
|
|
297
|
+
const m = mv ? [x, mv[2], mv[4]] : null;
|
|
283
298
|
if (k === 0 && p.antes) { pTexto(els, x, inicios[k], fimDe(k), { max: base * 0.08, peso: 700, pal: palDo(x) }); return; }
|
|
284
299
|
if (!m) { pTexto(els, x, inicios[k], fimDe(k), { pal: palDo(x) }); return; }
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
300
|
+
// O número inteiro numa linha: "ATÉ 30%" em pé quebrava em duas, por cima do rótulo.
|
|
301
|
+
const larguraNum = String(mv[1] + m[1] + mv[3]).length * 0.8; // serifa larga: 0,62 ainda quebrava
|
|
302
|
+
const tam = Math.round(Math.min(deitado ? H * 0.24 : W * 0.3, (W0 * 0.96) / Math.max(1, larguraNum)));
|
|
303
|
+
const casas = /[.,]/.test(m[1]) ? 1 : 0;
|
|
304
|
+
els.push({ tipo: 'texto', texto: mv[1] + m[1] + mv[3], fonte: F.titulo, peso: 800, tamanho: tam, cor: BRANCO, x: M, y: Math.round(H * 0.5 - tam * 0.75), largura: W0, alinhamento: 'center',
|
|
305
|
+
de: inicios[k], ate: fimDe(k), contar: { ate: Number(m[1].replace(',', '.')), dur: 0.6, casas, antes: mv[1].toUpperCase(), depois: mv[3] }, gradienteTexto: undefined,
|
|
288
306
|
anima: { opacidade: [{ t: 0, v: 0 }, { t: 0.25, v: 1 }], escala: [{ t: 0, v: 0.92 }, { t: 0.6, v: 1, e: 'saida' }] } });
|
|
289
307
|
pTexto(els, m[2], inicios[k] + 0.1, fimDe(k), { y: H * 0.5 + tam * 0.3, max: base * 0.085, peso: 700, cor: DEST });
|
|
290
308
|
});
|
|
@@ -398,4 +416,4 @@ function montarCinema({ roteiro, largura = 1920, altura = 1080, tempos = [], nar
|
|
|
398
416
|
};
|
|
399
417
|
}
|
|
400
418
|
|
|
401
|
-
module.exports = { montarCinema, falaDe, paraFala, quando, leitura };
|
|
419
|
+
module.exports = { montarCinema, falaDe, paraFala, quando, leitura: leituraCheia };
|
package/lib/estudio/diretor.js
CHANGED
|
@@ -62,6 +62,26 @@ function precisaDeProducao(texto) {
|
|
|
62
62
|
return { producao: false };
|
|
63
63
|
}
|
|
64
64
|
|
|
65
|
+
/* Editar a GRAVAÇÃO da pessoa não é produzir vídeo do zero: aí o caminho é o
|
|
66
|
+
editor por linha do tempo (`primocode video`, lib/video/), não o roteiro. */
|
|
67
|
+
const PEDE_EDICAO = /\b(edit[ae]r?|edi[cç][aã]o|cort[ae]r?|legend[ae]r?|tir[ae]r?\s+(o|os)\s+sil[eê]ncios?)\b[\s\S]{0,80}\b(grava[cç][aã]o|meu\s+v[ií]deo|esse\s+v[ií]deo|este\s+v[ií]deo|[\w-]+\.(mp4|mov|mkv|webm|m4v))\b|\b[\w-]+\.(mp4|mov|mkv|webm|m4v)\b[\s\S]{0,80}\b(edit|cort|legend|sil[eê]nci)/i;
|
|
68
|
+
|
|
69
|
+
/* Os pedidos de EFEITO sobre a gravação (lib/video/ops-fx.js): fundo, camadas,
|
|
70
|
+
estalo, objeto na mão, legenda na cabeça. Falam da pessoa ("me", "minha
|
|
71
|
+
mão"), não do arquivo — por isso não casavam com a regra de cima. */
|
|
72
|
+
const PEDE_EFEITO = /\b(tir[ae]r?|remov\w*|troc\w*)\s+(o\s+)?fundo\b|\bsepar\w*\s+em\s+camadas\b|\bestal\w*\s+(o\s+)?dedo\b|\b(logo|objeto)\b[\s\S]{0,40}\bm[aã]os?\b|\bjunt\w*\s+as\s+m[aã]os\b|\blegenda\b[\s\S]{0,40}\b(azul|vermelh|verde|amarel|rosa|roxa|branc|cabe[cç]a|em cima|embaixo)/i;
|
|
73
|
+
|
|
74
|
+
/* "edite: /Users/…/Fototeca do Photo Booth/…/Filme em 30-09-2026 às 23.56.mov": o caminho
|
|
75
|
+
do Photo Booth tem mais de 80 caracteres, e o pedido ia para o Estúdio de
|
|
76
|
+
motion — que tratava a gravação como b-roll (01/10). Verbo de editar + um
|
|
77
|
+
arquivo de vídeo em qualquer lugar da frase é edição. */
|
|
78
|
+
const EDITA_ARQUIVO = /\b(edit\w*|edi[cç][aã]o|p[oõ]e\s+(ele\s+)?pra\s+editar)\b[\s\S]*\.(mp4|mov|mkv|webm|m4v)\b|\.(mp4|mov|mkv|webm|m4v)\b[\s\S]*\b(edit\w*|edi[cç][aã]o)\b/i;
|
|
79
|
+
|
|
80
|
+
function precisaDeEdicao(texto) {
|
|
81
|
+
const t = String(texto || '');
|
|
82
|
+
return PEDE_EDICAO.test(t) || PEDE_EFEITO.test(t) || EDITA_ARQUIVO.test(t);
|
|
83
|
+
}
|
|
84
|
+
|
|
65
85
|
// ── 2. as decisões que não são do modelo ─────────────────────────────────
|
|
66
86
|
|
|
67
87
|
/**
|
|
@@ -293,7 +313,7 @@ function pauta(plano) {
|
|
|
293
313
|
}
|
|
294
314
|
|
|
295
315
|
module.exports = {
|
|
296
|
-
precisaDeProducao, vozPara, ritmoPara,
|
|
316
|
+
precisaDeProducao, precisaDeEdicao, vozPara, ritmoPara,
|
|
297
317
|
normalizarPlano, extrairJSON, planejar, pauta,
|
|
298
318
|
DIRETOR, REVISAO,
|
|
299
319
|
};
|
package/lib/estudio/ende.js
CHANGED
|
@@ -60,13 +60,18 @@ function lerLista(html) {
|
|
|
60
60
|
}).filter((f) => f.titulo && f.segundos > 0);
|
|
61
61
|
}
|
|
62
62
|
|
|
63
|
-
/** A faixa que cobre o vídeo e mais combina com o clima. Nenhuma cobre: null.
|
|
64
|
-
|
|
63
|
+
/** A faixa que cobre o vídeo e mais combina com o clima. Nenhuma cobre: null.
|
|
64
|
+
* Com `semente`, sorteia entre as 5 melhores que não estão em `evitar` e não
|
|
65
|
+
* têm voz nas tags — "não repetir a mesma faixa em todo vídeo" (30/09). */
|
|
66
|
+
function escolher(faixas, { clima = 'neutro', segundos = 0, semente = null, evitar = [] } = {}) {
|
|
65
67
|
const palavras = CLIMAS[clima] || CLIMAS.neutro;
|
|
66
68
|
const nota = (f) => f.tags.reduce((n, t) => n + palavras.filter((p) => t.includes(p)).length, 0);
|
|
67
69
|
const cabem = (faixas || []).filter((f) => f.segundos >= segundos);
|
|
68
70
|
if (!cabem.length) return null;
|
|
69
|
-
return cabem.reduce((a, b) => (nota(b) > nota(a) ? b : a));
|
|
71
|
+
if (semente == null) return cabem.reduce((a, b) => (nota(b) > nota(a) ? b : a));
|
|
72
|
+
const semVoz = cabem.filter((f) => !f.tags.some((t) => /vocal|singing|voice|rap\b|song/.test(t)) && !evitar.includes(f.id));
|
|
73
|
+
const pool = (semVoz.length ? semVoz : cabem).slice().sort((a, b) => nota(b) - nota(a)).slice(0, 5);
|
|
74
|
+
return pool[Math.abs(Number(semente) | 0) % pool.length];
|
|
70
75
|
}
|
|
71
76
|
|
|
72
77
|
async function buscarPadrao(url) {
|
|
@@ -93,8 +98,14 @@ function provedor({ buscar = buscarPadrao, baixar, pasta = 'midia' } = {}) {
|
|
|
93
98
|
const salvar = baixar || baixarEm(pasta);
|
|
94
99
|
return {
|
|
95
100
|
nome: 'ende', tipo: 'musica',
|
|
96
|
-
async gerar({ clima, segundos = 0 } = {}) {
|
|
97
|
-
|
|
101
|
+
async gerar({ clima, segundos = 0, genero = null, semente = null, evitar = [] } = {}) {
|
|
102
|
+
// O GÊNERO (ende.app/en/genres/<genero>): jazz, lofi, funk, ambient… — escolhido pelo assunto.
|
|
103
|
+
const url = genero ? 'https://ende.app/en/genres/' + encodeURIComponent(genero) : LISTA;
|
|
104
|
+
let faixas = [];
|
|
105
|
+
// A página do gênero falhou: a busca geral (que, sem rede, lança — e a corrente cai no próximo provedor).
|
|
106
|
+
if (genero) { try { faixas = lerLista(await buscar(url)); } catch { faixas = []; } }
|
|
107
|
+
if (!faixas.length) faixas = lerLista(await buscar(LISTA));
|
|
108
|
+
const faixa = escolher(faixas, { clima, segundos, semente, evitar });
|
|
98
109
|
if (!faixa) return null;
|
|
99
110
|
const meta = {
|
|
100
111
|
fonte: faixa.pagina, titulo: faixa.titulo, autor: 'Sascha Ende',
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* estilo.js — qual estilo de vídeo um roteiro vira.
|
|
3
|
+
*
|
|
4
|
+
* gerativo O MOTION: sem template, a tipografia é o filme, numa linha do tempo
|
|
5
|
+
* contínua sorteada do roteiro (gerativo.js). É o que "motion" e
|
|
6
|
+
* "animação" pedem, e o que o modo "sem referências" usa.
|
|
7
|
+
* motion o motion antigo: o protagonista 3D que se deforma (motion.js),
|
|
8
|
+
* só pelo nome (classico, limpo).
|
|
9
|
+
* vox explainer editorial: tinta sobre papel, os oito dispositivos VOX (vox.js)
|
|
10
|
+
* marca brand reveal: o brilho, o vetor, a marca cromada, o padrão (lancamento.js)
|
|
11
|
+
* lancamento filme de lançamento de produto: cartões, painel, calendário, mural (lancamento.js)
|
|
12
|
+
* impacto anúncio: corte a cada batida (impacto.js)
|
|
13
|
+
* cinema filme de marca premium com fotos reais (cinema.js)
|
|
14
|
+
* hibrido O PADRÃO do vídeo: o cinema com o kit por cima — foto e vídeo reais
|
|
15
|
+
* que não param, e o motion por cima (hibrido.js)
|
|
16
|
+
* composicao a composição antiga, uma cena por parte (composicao.js)
|
|
17
|
+
*
|
|
18
|
+
* Quem manda, em ordem: o estilo que o AGENTE pediu; o do roteiro (a menos
|
|
19
|
+
* que o pedido diga motion); o que o pedido descreve; e o motion.
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
'use strict';
|
|
23
|
+
|
|
24
|
+
const ESTILOS = ['hibrido', 'gerativo', 'motion', 'vox', 'marca', 'lancamento', 'impacto', 'cinema', 'composicao'];
|
|
25
|
+
// Nomes que o modelo usa para os mesmos estilos.
|
|
26
|
+
/* "motion" agora é o GERATIVO ("não pode ter template", 29–30/09); o motion
|
|
27
|
+
antigo segue pelo nome "classico" (e "limpo", o nome mais antigo dele). */
|
|
28
|
+
const APELIDOS = { motion: 'gerativo', generativo: 'gerativo', kinetic: 'gerativo', cinetico: 'gerativo', 'cinético': 'gerativo',
|
|
29
|
+
tipografico: 'gerativo', 'tipográfico': 'gerativo', animacao: 'gerativo', 'animação': 'gerativo',
|
|
30
|
+
classico: 'motion', 'clássico': 'motion', 'motion-classico': 'motion', motion3d: 'motion',
|
|
31
|
+
absurdo: 'hibrido', misto: 'hibrido', mix: 'hibrido', 'híbrido': 'hibrido', limpo: 'motion', explainer: 'vox', editorial: 'vox', brand: 'marca', branding: 'marca', 'brand-reveal': 'marca', launch: 'lancamento', 'lançamento': 'lancamento', produto: 'lancamento' };
|
|
32
|
+
|
|
33
|
+
const PEDE_MOTION = /\bmotion\b|anima[çc][ãa]o|animad[oa]/i;
|
|
34
|
+
const PEDE_VOX = /\bvox\b|explica|explainer|document[aá]rio|editorial|hist[oó]ria d[aoe]s?\b/i;
|
|
35
|
+
const PEDE_MARCA = /\bbrand|identidade visual|revela[çc][ãa]o d[ae] marca|\blogo(tipo|marca)?\b|vinheta de marca/i;
|
|
36
|
+
const PEDE_LANCAMENTO = /lan[çc]amento|\blaunch|\bsaas\b|produto novo|apresenta(ndo|r|ção d[oe]) (o |a )?(app|produto|plataforma|ferramenta)/i;
|
|
37
|
+
const PEDE_IMPACTO = /an[uú]nci|reels?|divulg|promo|lan[çc]a|vend|campanha|convite|inscri/i;
|
|
38
|
+
|
|
39
|
+
const normal = (e) => {
|
|
40
|
+
const x = String(e || '').trim().toLowerCase();
|
|
41
|
+
if (!x) return null;
|
|
42
|
+
const n = APELIDOS[x] || x;
|
|
43
|
+
return ESTILOS.includes(n) ? n : null;
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
function escolherEstilo({ pedido = '', agente = null, roteiro = null } = {}) {
|
|
47
|
+
const pedidoAgente = normal(agente);
|
|
48
|
+
if (pedidoAgente) return pedidoAgente;
|
|
49
|
+
const doRoteiro = normal(roteiro);
|
|
50
|
+
/* Pedir MOTION (ou animação) é pedir o gerativo — antes do vox, da marca e
|
|
51
|
+
do lançamento, que são leiaute fixo ("não pode ter template", 30/09). */
|
|
52
|
+
if (doRoteiro && !(doRoteiro !== 'gerativo' && PEDE_MOTION.test(pedido))) return doRoteiro;
|
|
53
|
+
if (PEDE_MOTION.test(pedido)) return 'gerativo';
|
|
54
|
+
if (PEDE_VOX.test(pedido)) return 'vox';
|
|
55
|
+
if (PEDE_MARCA.test(pedido)) return 'marca';
|
|
56
|
+
if (PEDE_LANCAMENTO.test(pedido)) return 'lancamento';
|
|
57
|
+
/* Anúncio, reels e o resto: o HÍBRIDO. "Um mix da versão antiga (o reels
|
|
58
|
+
da imersão, no cinema) e da última (o kit) — absurdo, que nem parece
|
|
59
|
+
que foi IA" (29/09). O impacto segue existindo, se pedido pelo nome. */
|
|
60
|
+
return 'hibrido';
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/** Os estilos que usam os efeitos leves e a trilha do ende.app (os de motion, não os de corte). */
|
|
64
|
+
const LEVES = new Set(['gerativo', 'motion', 'vox', 'marca', 'lancamento']);
|
|
65
|
+
|
|
66
|
+
module.exports = { escolherEstilo, ESTILOS, LEVES, PEDE_MOTION };
|