primocode 10.10.1 → 10.11.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.
- package/README.md +10 -2
- package/lib/catalogo.js +1 -0
- package/lib/estudio/cena.js +6 -0
- package/lib/estudio/efeitos-fabrica/brilho-varredura.jsx +25 -0
- package/lib/estudio/efeitos-fabrica/cor-inunda.jsx +30 -0
- package/lib/estudio/efeitos-fabrica/mola-com-peso.jsx +28 -0
- package/lib/estudio/efeitos-fabrica/peca-impacto-3d.jsx +37 -0
- package/lib/estudio/efeitos-fabrica/raios-de-luz.jsx +29 -0
- package/lib/estudio/efeitos-fabrica/risco-multilinha.jsx +30 -0
- package/lib/estudio/efeitos.js +21 -4
- package/lib/estudio/index.js +45 -3
- package/lib/estudio/kit/gerativo.jsx +16 -0
- package/lib/estudio/kit/mundo.jsx +11 -5
- package/lib/estudio/kit/natural.js +161 -0
- package/lib/estudio/kit/personagem.jsx +36 -20
- package/lib/estudio/kit/voxel.jsx +129 -64
- package/lib/estudio/kit.js +1 -1
- package/lib/estudio/revisor.js +5 -2
- package/lib/estudio/sem-narracao.js +189 -0
- package/lib/estudio/sons-leves.js +15 -0
- package/package.json +2 -2
- package/skills/motion-de-primeira/SKILL.md +4 -0
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* sem-narracao.js — o vídeo inteiro sem voz: só o motion e os barulhinhos.
|
|
3
|
+
*
|
|
4
|
+
* "Motions sem narração: só o motion e os efeitos sonoros, os barulhinhos."
|
|
5
|
+
* — Joel (14/10/2026)
|
|
6
|
+
*
|
|
7
|
+
* Sem voz não há tempo MEDIDO: cada parte dura o `duracao` (s) que o roteiro
|
|
8
|
+
* deu ou, sem ele, o que o texto da tela pede para ser lido. As palavras ganham
|
|
9
|
+
* tempos repartidos na parte, para as cenas que entram palavra por palavra
|
|
10
|
+
* continuarem entrando. E o som sobe de papel: um efeito leve em cada corte e
|
|
11
|
+
* em cada entrada marcante (sons-leves.js), sem repetir o mesmo em sequência.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
'use strict';
|
|
15
|
+
|
|
16
|
+
const r3 = (x) => Math.round(x * 1000) / 1000;
|
|
17
|
+
|
|
18
|
+
/* O pedido que tira a voz: "sem narração", "sem voz", "sem locução", "só efeito sonoro". */
|
|
19
|
+
const PEDIDO = /\bsem\s+(narra[cç][aã]o|narrador|voz|locu[cç][aã]o)\b|\bs[oó]\s+(o\s+motion\s+e\s+)?(os\s+)?(efeitos?\s+sonoros?|barulhinhos?|sfx)\b/i;
|
|
20
|
+
|
|
21
|
+
/** O vídeo é sem voz? `roteiro.semNarracao` manda (false desliga); sem ele, o pedido. */
|
|
22
|
+
function ativo(roteiro, pedido = '') {
|
|
23
|
+
const r = roteiro || {};
|
|
24
|
+
if (r.semNarracao === true || r.semNarracao === 'true') return true;
|
|
25
|
+
if (r.semNarracao === false || r.semNarracao === 'false') return false;
|
|
26
|
+
return PEDIDO.test(String(pedido || ''));
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/** O que a TELA mostra da parte (é o que se lê; a fala só se não há mais nada). */
|
|
30
|
+
function textoDaTela(pt) {
|
|
31
|
+
if (!pt || typeof pt !== 'object') return '';
|
|
32
|
+
const lista = (x) => (Array.isArray(x) ? x.map((i) => (typeof i === 'string' ? i : (i && (i.texto || i.titulo || i.nome || i.rotulo)) || '')) : []);
|
|
33
|
+
const txt = [pt.titulo, pt.sub, pt.texto, pt.nao, pt.sim, pt.valor, pt.rotulo, pt.autor, ...lista(pt.itens), ...lista(pt.linhas)]
|
|
34
|
+
.filter((x) => x != null && String(x).trim()).join(' ');
|
|
35
|
+
return txt.trim() || String(pt.fala || '').trim();
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/** Quanto a parte fica na tela: `duracao` do roteiro; senão 1,8 s + 0,25 s por palavra, entre 1,5 e 4 s. */
|
|
39
|
+
function duracaoDe(pt) {
|
|
40
|
+
const d = Number(pt && pt.duracao);
|
|
41
|
+
if (d > 0) return Math.max(0.5, Math.min(30, d));
|
|
42
|
+
const n = textoDaTela(pt).split(/\s+/).filter(Boolean).length;
|
|
43
|
+
return Math.max(1.5, Math.min(4, 1.8 + 0.25 * n));
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Os tempos de cada parte, no mesmo formato que a narração devolve
|
|
48
|
+
* ({de, ate, palavras:[{texto, de, ate}]}): partes coladas uma na outra e as
|
|
49
|
+
* palavras repartidas nos primeiros 70% da parte (o resto é o respiro).
|
|
50
|
+
* `falaDe` dá o texto cujas palavras a cena procura (o do compositor).
|
|
51
|
+
*/
|
|
52
|
+
function tempos(partes, { falaDe = textoDaTela } = {}) {
|
|
53
|
+
let t = 0;
|
|
54
|
+
return (partes || []).map((pt) => {
|
|
55
|
+
const dur = duracaoDe(pt);
|
|
56
|
+
const de = r3(t), ate = r3(t + dur);
|
|
57
|
+
const ws = String(falaDe(pt) || textoDaTela(pt) || '').split(/\s+/).filter(Boolean);
|
|
58
|
+
const ini = de + Math.min(0.2, dur * 0.1), janela = dur * 0.7 - (ini - de);
|
|
59
|
+
const passo = janela / Math.max(1, ws.length);
|
|
60
|
+
const palavras = ws.map((w, j) => ({ texto: w, de: r3(ini + j * passo), ate: r3(ini + j * passo + Math.max(0.08, passo * 0.8)) }));
|
|
61
|
+
t += dur;
|
|
62
|
+
return { de, ate, palavras };
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/* Os momentos que pedem som: os CORTES (começo de parte, de batida, de cena)
|
|
67
|
+
e as ENTRADAS marcantes (o ícone, o item, a cena que a IA escreveu). */
|
|
68
|
+
function momentos({ tempos: tps = [], plano = null, partitura = null, cues = [] } = {}) {
|
|
69
|
+
const cortes = [], entradas = [], micros = [], revelas = [];
|
|
70
|
+
const perto = (lista, t, d = 0.3) => lista.some((x) => Math.abs(x - t) < d);
|
|
71
|
+
const corte = (t) => { if (t > 0.3 && !perto(cortes, t)) cortes.push(r3(t)); };
|
|
72
|
+
const entrada = (t) => { if (t != null && t >= 0 && !perto(entradas, t, 0.35) && !perto(cortes, t, 0.2)) entradas.push(r3(t)); };
|
|
73
|
+
for (const t of tps.slice(1)) corte(t.de);
|
|
74
|
+
// A cena escrita pela IA não tem batida: as palavras repartidas na parte são os micros dela.
|
|
75
|
+
for (const tp of tps) for (const pw of tp.palavras || []) if (pw && pw.de != null) micros.push(r3(pw.de));
|
|
76
|
+
const bs = (partitura && partitura.batidas) || [];
|
|
77
|
+
for (const b of bs) corte(b.de);
|
|
78
|
+
// Vídeo de várias cenas (os outros estilos): o começo de cada cena é um corte.
|
|
79
|
+
let acc = 0;
|
|
80
|
+
for (const c of (plano && plano.cenas) || []) { corte(acc); acc += Number(c.duracao) || 0; }
|
|
81
|
+
entrada(tps.length ? tps[0].de + 0.1 : 0.1); // a abertura entra com som
|
|
82
|
+
for (const b of bs) {
|
|
83
|
+
if (b.icone3d && b.icone3d.t != null) entrada(b.icone3d.t);
|
|
84
|
+
for (const l of b.linhas || []) if ((l.papel === 'item' || l.papel === 'numero') && l.t != null) entrada(l.t);
|
|
85
|
+
if (b.comp === 'marca') { entrada(b.de + 0.35); revelas.push(r3(b.de + 0.3)); }
|
|
86
|
+
/* O MICRO (14/10, as referências): cada linha e cada palavra que entra
|
|
87
|
+
faz um som pequeno — é isso que dá a sensação de "tudo tem som". */
|
|
88
|
+
for (const l of b.linhas || []) {
|
|
89
|
+
if (l.t != null) micros.push(r3(l.t));
|
|
90
|
+
for (const pw of l.palavras || []) if (pw && pw.t != null) micros.push(r3(pw.t));
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
for (const c of (plano && plano.cenas) || []) for (const el of c.elementos || []) if (el && el.tipo === 'componente' && el.de != null) entrada(el.de + 0.08);
|
|
94
|
+
const ocupado = [...cortes, ...entradas];
|
|
95
|
+
const mic = [...new Set(micros)].sort((a, b) => a - b).filter((t, i, l) => t > 0.05 && !ocupado.some((x) => Math.abs(x - t) < 0.1) && (i === 0 || t - l[i - 1] >= 0.09));
|
|
96
|
+
return { cortes: cortes.sort((a, b) => a - b), entradas: entradas.sort((a, b) => a - b), micros: mic, revelas, cues: (cues || []).filter((c) => c && c.t != null) };
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// O corte passa com ar; a entrada chega com um toque pequeno. Ordem de rodízio.
|
|
100
|
+
const DO_CORTE = ['swoosh', 'whoosh', 'sopro', 'toque', 'riser'];
|
|
101
|
+
const DA_ENTRADA = ['pop', 'mouse', 'bolha', 'digital', 'clique', 'brilho'];
|
|
102
|
+
// O micro sobe numa escada (ponto1→ponto5) enquanto as coisas entram em sequência, e recomeça na pausa.
|
|
103
|
+
const ESCADA = ['ponto1', 'ponto2', 'ponto3', 'ponto4', 'ponto5'];
|
|
104
|
+
// O whoosh e o sopro antecipam o corte (o ar chega antes da imagem); o riser sobe até ele.
|
|
105
|
+
const ANTES = { whoosh: 0.18, swoosh: 0.12, sopro: 0.3, riser: 1.0, toque: 0 };
|
|
106
|
+
const VOLUME = { swoosh: 0.45, mouse: 0.4, digital: 0.3, tique: 0.3, sub: 0.7, whoosh: 0.5, sopro: 0.6, toque: 0.6, riser: 0.4, pop: 0.42, bolha: 0.45, clique: 0.4, brilho: 0.32 };
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Soma aos efeitos do plano um som leve em cada corte e em cada entrada.
|
|
110
|
+
* `sons` é o mapa nome → arquivo do sons-leves.preparar. Não encosta em som
|
|
111
|
+
* que já existe (0,12 s) e nunca repete o mesmo som duas vezes seguidas.
|
|
112
|
+
*/
|
|
113
|
+
function sonorizar(efeitos, { cortes = [], entradas = [], micros = [], revelas = [], cues = [], sons = {}, duracao = Infinity, volMicro = 0.24 } = {}) {
|
|
114
|
+
const fora = (efeitos || []).slice();
|
|
115
|
+
const eventos = [...cortes.map((t) => ({ t, tipo: 'corte' })), ...entradas.map((t) => ({ t, tipo: 'entrada' }))].sort((a, b) => a.t - b.t);
|
|
116
|
+
const giro = { corte: 0, entrada: 0 };
|
|
117
|
+
let ultimo = null;
|
|
118
|
+
const novos = [];
|
|
119
|
+
for (const ev of eventos) {
|
|
120
|
+
const roda = ev.tipo === 'corte' ? DO_CORTE : DA_ENTRADA;
|
|
121
|
+
let nome = null;
|
|
122
|
+
for (let k = 0; k < roda.length; k++) {
|
|
123
|
+
const n = roda[(giro[ev.tipo] + k) % roda.length];
|
|
124
|
+
if (!sons[n] || n === ultimo) continue;
|
|
125
|
+
// O riser precisa de espaço antes do corte.
|
|
126
|
+
if (n === 'riser' && ev.t < 1.2) continue;
|
|
127
|
+
nome = n; giro[ev.tipo] = (giro[ev.tipo] + k + 1) % roda.length; break;
|
|
128
|
+
}
|
|
129
|
+
if (!nome) continue;
|
|
130
|
+
const t = r3(Math.max(0, ev.t - (ANTES[nome] || 0)));
|
|
131
|
+
if (t > duracao - 0.1) continue;
|
|
132
|
+
if ([...fora, ...novos].some((e) => Math.abs(e.t - t) < 0.12)) continue;
|
|
133
|
+
novos.push({ t, src: sons[nome], volume: VOLUME[nome] || 0.4, som: nome });
|
|
134
|
+
ultimo = nome;
|
|
135
|
+
}
|
|
136
|
+
// A revelação (a marca no fim) ganha o sub por baixo do som da entrada.
|
|
137
|
+
for (const t of revelas) if (sons.sub && t < duracao - 0.1) novos.push({ t: r3(t), src: sons.sub, volume: VOLUME.sub, som: 'sub' });
|
|
138
|
+
// O som que a cena pediu (parte.sons: a IA sabe quando a bolinha chega).
|
|
139
|
+
for (const c of cues) {
|
|
140
|
+
const nome = sons[c.som] ? c.som : (sons.pop ? 'pop' : null);
|
|
141
|
+
if (nome && c.t < duracao - 0.05) novos.push({ t: r3(c.t), src: sons[nome], volume: Number(c.volume) || VOLUME[nome] || 0.35, som: nome, micro: true });
|
|
142
|
+
}
|
|
143
|
+
// Os micros: a escada sobe em sequência e recomeça depois de 0,6 s de pausa; um tique a cada tanto quebra a repetição.
|
|
144
|
+
let degrau = -1, antes = -9;
|
|
145
|
+
for (const t of micros) {
|
|
146
|
+
if (t > duracao - 0.05) continue;
|
|
147
|
+
degrau = t - antes > 0.6 ? 0 : Math.min(ESCADA.length - 1, degrau + 1);
|
|
148
|
+
antes = t;
|
|
149
|
+
const nome = degrau === ESCADA.length - 1 && sons.tique && micros.length > 8 && Math.round(t * 10) % 3 === 0 ? 'tique' : ESCADA[degrau];
|
|
150
|
+
if (!sons[nome] || novos.some((e) => Math.abs(e.t - t) < 0.08)) continue;
|
|
151
|
+
novos.push({ t, src: sons[nome], volume: volMicro, som: nome, micro: true });
|
|
152
|
+
}
|
|
153
|
+
return { efeitos: [...fora, ...novos.map(({ som, ...e }) => e)].sort((a, b) => a.t - b.t), novos };
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/** O plano pronto ganha os barulhinhos (o plano é mudado no lugar). Devolve quantos entraram. */
|
|
157
|
+
function sonorizarPlano(r, { tempos: tps = [], sons = {}, cues = [], comVoz = false } = {}) {
|
|
158
|
+
if (!r || !r.plano) return 0;
|
|
159
|
+
const plano = r.plano;
|
|
160
|
+
plano.audio = plano.audio || {};
|
|
161
|
+
const duracao = (plano.cenas || []).reduce((n, c) => n + (Number(c.duracao) || 0), 0) || Infinity;
|
|
162
|
+
const m = momentos({ tempos: tps, plano, partitura: r.partitura, cues });
|
|
163
|
+
/* Com voz, os cortes e entradas já têm som (gerativo.js): entram só os
|
|
164
|
+
micros e os pedidos pela cena, baixinho, para não brigar com a fala. */
|
|
165
|
+
const s = comVoz
|
|
166
|
+
? sonorizar(plano.audio.efeitos || [], { micros: m.micros, cues: m.cues, sons, duracao, volMicro: 0.14 })
|
|
167
|
+
: sonorizar(plano.audio.efeitos || [], { ...m, sons, duracao });
|
|
168
|
+
plano.audio.efeitos = s.efeitos;
|
|
169
|
+
if (comVoz) return s.novos.length;
|
|
170
|
+
delete plano.audio.narracao;
|
|
171
|
+
/* Sem voz não há o que abrir espaço: a trilha não abaixa entre os cortes
|
|
172
|
+
(o ducking era para a fala, e deixava o vídeo em -17 LUFS). */
|
|
173
|
+
const tr = plano.audio.trilha;
|
|
174
|
+
if (tr && Array.isArray(tr.volumes)) tr.volumes = tr.volumes.map((v) => (v.t > 0.3 && v.v < 0.85 ? { ...v, v: 0.85 } : v));
|
|
175
|
+
return s.novos.length;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/** parte.sons [{t, som, volume}] (t na parte) → no tempo do vídeo. */
|
|
179
|
+
function cuesDe(partes = [], tps = []) {
|
|
180
|
+
const out = [];
|
|
181
|
+
(partes || []).forEach((pt, i) => {
|
|
182
|
+
const de = tps[i] && tps[i].de;
|
|
183
|
+
if (de == null || !pt || !Array.isArray(pt.sons)) return;
|
|
184
|
+
for (const c of pt.sons) if (c && Number.isFinite(Number(c.t))) out.push({ t: r3(de + Number(c.t)), som: String(c.som || 'pop'), volume: c.volume });
|
|
185
|
+
});
|
|
186
|
+
return out;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
module.exports = { cuesDe, ativo, textoDaTela, duracaoDe, tempos, momentos, sonorizar, sonorizarPlano, PEDIDO };
|
|
@@ -40,6 +40,21 @@ const EFEITOS = {
|
|
|
40
40
|
impacto: ['-f', 'lavfi', '-i', "aevalsrc='0.95*sin(2*PI*(62-26*t)*t)*exp(-4.5*t)+0.45*(random(0)*2-1)*exp(-38*t)':s=44100:d=1.1", '-af', 'lowpass=f=2600,volume=1.4'],
|
|
41
41
|
riser: ['-f', 'lavfi', '-i', "aevalsrc='(0.32*sin(2*PI*(170+620*t*t)*t)+0.22*(random(0)*2-1))*pow(t/1.1,2)':s=44100:d=1.1", '-af', 'highpass=f=260,afade=t=out:st=1.04:d=0.06,volume=1.3'],
|
|
42
42
|
pop: ['-f', 'lavfi', '-i', "aevalsrc='0.8*sin(2*PI*(980-640*t)*t)*exp(-28*t)*(1-exp(-700*t))':s=44100:d=0.18"],
|
|
43
|
+
/* OS BARULHINHOS DAS REFERÊNCIAS (14/10, "eu quero meus barulhinhos", com o
|
|
44
|
+
motion1.mp4: 29 sons em 15 s, cada bolinha e cada ponto que aparece faz
|
|
45
|
+
um). Pequenos e secos: o tique da interface, o clique do mouse, o blip
|
|
46
|
+
digital, o swoosh que desce, o sub da revelação e a escada de notas. */
|
|
47
|
+
tique: ['-f', 'lavfi', '-i', "aevalsrc='0.45*sin(2*PI*3200*t)*exp(-140*t)+0.12*(random(0)*2-1)*exp(-220*t)':s=44100:d=0.05", '-af', 'highpass=f=900'],
|
|
48
|
+
mouse: ['-f', 'lavfi', '-i', "aevalsrc='0.6*(random(0)*2-1)*exp(-260*t)+0.45*(random(0)*2-1)*exp(-260*(t-0.07))*gte(t,0.07)':s=44100:d=0.14", '-af', 'bandpass=f=2600:width_type=o:w=1.6,volume=1.6'],
|
|
49
|
+
digital: ['-f', 'lavfi', '-i', "aevalsrc='0.28*sgn(sin(2*PI*(1500+900*gte(t,0.03))*t))*exp(-38*t)':s=44100:d=0.08", '-af', 'lowpass=f=5200'],
|
|
50
|
+
swoosh: ['-f', 'lavfi', '-i', 'anoisesrc=d=0.55:c=white:a=0.8', '-af',
|
|
51
|
+
'bandpass=f=2600:width_type=o:w=3,afade=t=in:st=0:d=0.12:curve=exp,afade=t=out:st=0.12:d=0.43:curve=exp,volume=1.6'],
|
|
52
|
+
sub: ['-f', 'lavfi', '-i', "aevalsrc='0.9*sin(2*PI*(55-20*t)*t)*exp(-3*t)*(1-exp(-300*t))':s=44100:d=1.2", '-af', 'lowpass=f=220,volume=1.5'],
|
|
53
|
+
ponto1: ['-f', 'lavfi', '-i', "aevalsrc='0.55*sin(2*PI*784.0*t)*exp(-34*t)*(1-exp(-900*t))+0.15*sin(2*PI*1568.0*t)*exp(-50*t)':s=44100:d=0.16"],
|
|
54
|
+
ponto2: ['-f', 'lavfi', '-i', "aevalsrc='0.55*sin(2*PI*880.0*t)*exp(-34*t)*(1-exp(-900*t))+0.15*sin(2*PI*1760.0*t)*exp(-50*t)':s=44100:d=0.16"],
|
|
55
|
+
ponto3: ['-f', 'lavfi', '-i', "aevalsrc='0.55*sin(2*PI*987.8*t)*exp(-34*t)*(1-exp(-900*t))+0.15*sin(2*PI*1975.6*t)*exp(-50*t)':s=44100:d=0.16"],
|
|
56
|
+
ponto4: ['-f', 'lavfi', '-i', "aevalsrc='0.55*sin(2*PI*1174.7*t)*exp(-34*t)*(1-exp(-900*t))+0.15*sin(2*PI*2349.4*t)*exp(-50*t)':s=44100:d=0.16"],
|
|
57
|
+
ponto5: ['-f', 'lavfi', '-i', "aevalsrc='0.55*sin(2*PI*1318.5*t)*exp(-34*t)*(1-exp(-900*t))+0.15*sin(2*PI*2637.0*t)*exp(-50*t)':s=44100:d=0.16"],
|
|
43
58
|
};
|
|
44
59
|
|
|
45
60
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "primocode",
|
|
3
|
-
"version": "10.
|
|
3
|
+
"version": "10.11.1",
|
|
4
4
|
"description": "PrimoCode — agente de engenharia com IA e cursor próprio. Requer conta Conecta Primo AI (Premium ou Super). Cria arquivos, roda comandos, controla navegador e desktop: abre apps, clica em botões e ícones pelo nome, digita e usa atalhos.",
|
|
5
5
|
"main": "bin/primocode.js",
|
|
6
6
|
"bin": {
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
},
|
|
9
9
|
"scripts": {
|
|
10
10
|
"start": "node bin/primocode.js",
|
|
11
|
-
"test": "node test/tools.test.js && node test/ui.test.js && node test/entrada.test.js && node test/transparencia.test.js && node test/permissao.test.js && node test/compatibilidade.test.js && node test/skills.test.js && node test/skills-de-fora.test.js && node test/skills-novas.test.js && node test/comandos.test.js && node test/estudio.test.js && node test/voz.test.js && node test/modo.test.js && node test/pasta.test.js && node test/projeto.test.js && node test/nome-projeto.test.js && node test/api-propria.test.js && node test/claude-engine.test.js && node test/codex.test.js && node test/conferir.test.js && node test/catalogo.test.js && node test/desktop.test.js && node test/seta.test.js && node test/effort.test.js && node test/regressao.test.js && node test/memoria-conversa.test.js && node test/repeticao.test.js && node test/casar.test.js && node test/recado.test.js && node test/releitura.test.js && node test/snapshot.test.js && node test/video.test.js && node test/limpeza.test.js && node test/autonomia.test.js && node test/desfazer.test.js && node test/desfazer-git.test.js && node test/referencia.test.js && node test/parar.test.js && node test/continuar.test.js && node test/pipeline.test.js && node test/conta.test.mjs && node test/planos-tela.test.js && node test/nuvem.test.js && node test/prazo.test.js && node test/primeira-vez.test.js && node test/fala.test.js && node test/especialistas.test.js && node test/empurrao.test.js && node test/terminal-novo.test.js && node test/markdown.test.js && node test/coerencia.test.js && node test/contexto.test.js && node test/perigo.test.js && node test/rapidez.test.js && node test/mascotes.test.js && node test/comandos-extra.test.js && node test/offline.test.js && node test/edicao.test.js && node test/composicao.test.js && node test/acervo-site.test.js && node test/impacto.test.js && node test/cinema.test.js && node test/producao.test.js && node test/ende.test.js && node test/capa.test.js && node test/broll.test.js && node test/morfar.test.js && node test/motion.test.js && node test/motion-roteiro.test.js && node test/kit-motion.test.js && node test/gerativo.test.js && node test/gerativo-identidade.test.js && node test/gerativo-moldura.test.js && node test/gerativo-heroi.test.js && node test/gerativo-ambiente.test.js && node test/gerativo-variedade.test.js && node test/hibrido.test.js && node test/batida.test.js && node test/estudio-acervo.test.js && node test/estudio-diretor.test.js && node test/estudio-marca.test.js && node test/estudio-novo-projeto.test.js && node test/estudio-plano.test.js && node test/estudio-slides.test.js && node test/estudio-video.test.js && node test/revisor.test.js && node test/conferencia.test.js && node test/cor.test.js && node test/assinatura.test.js && node test/biblioteca.test.js && node test/mcp.test.js && node test/personas.test.js && node test/efeitos.test.js && node test/auto.test.js && node test/colar.test.js && node test/rolar.test.js && node test/orquestra.test.js && node test/shell-limpo.test.js && node test/editar-remotion.test.js && node test/variacao3d.test.js && node test/portao-skill.test.js && node test/clones.test.js && node test/kokoro.test.js && node test/fluido.test.js && node test/zoom.test.js && node test/personagem.test.js && node test/tela.test.js && node test/margem.test.js && node test/travado.test.js && node test/leitura.test.js && node test/producao-provedores.test.js && node test/broll-frase.test.js && node test/vazamento.test.js && node test/colecao.test.js && node test/mundo.test.js && node test/mcp-procurar.test.js && node test/selecao.test.js && node test/nome-curto.test.js && node test/agents-md.test.js && node test/outra-pasta.test.js && node test/estudio-sem-id.test.js && node test/estudio-objeto-do-site.test.js && node test/cenarios.test.js && node test/movimentos.test.js && node test/gerativo-so-fala.test.js && node test/estilos.test.js && node test/proporcao.test.js && node test/cena.test.js"
|
|
11
|
+
"test": "node test/tools.test.js && node test/ui.test.js && node test/entrada.test.js && node test/transparencia.test.js && node test/permissao.test.js && node test/compatibilidade.test.js && node test/skills.test.js && node test/skills-de-fora.test.js && node test/skills-novas.test.js && node test/comandos.test.js && node test/estudio.test.js && node test/voz.test.js && node test/modo.test.js && node test/pasta.test.js && node test/projeto.test.js && node test/nome-projeto.test.js && node test/api-propria.test.js && node test/claude-engine.test.js && node test/codex.test.js && node test/conferir.test.js && node test/catalogo.test.js && node test/desktop.test.js && node test/seta.test.js && node test/effort.test.js && node test/regressao.test.js && node test/memoria-conversa.test.js && node test/repeticao.test.js && node test/casar.test.js && node test/recado.test.js && node test/releitura.test.js && node test/snapshot.test.js && node test/video.test.js && node test/limpeza.test.js && node test/autonomia.test.js && node test/desfazer.test.js && node test/desfazer-git.test.js && node test/referencia.test.js && node test/parar.test.js && node test/continuar.test.js && node test/pipeline.test.js && node test/conta.test.mjs && node test/planos-tela.test.js && node test/nuvem.test.js && node test/prazo.test.js && node test/primeira-vez.test.js && node test/fala.test.js && node test/especialistas.test.js && node test/empurrao.test.js && node test/terminal-novo.test.js && node test/markdown.test.js && node test/coerencia.test.js && node test/contexto.test.js && node test/perigo.test.js && node test/rapidez.test.js && node test/mascotes.test.js && node test/comandos-extra.test.js && node test/offline.test.js && node test/edicao.test.js && node test/composicao.test.js && node test/acervo-site.test.js && node test/impacto.test.js && node test/cinema.test.js && node test/producao.test.js && node test/ende.test.js && node test/capa.test.js && node test/broll.test.js && node test/morfar.test.js && node test/motion.test.js && node test/motion-roteiro.test.js && node test/kit-motion.test.js && node test/gerativo.test.js && node test/gerativo-identidade.test.js && node test/gerativo-moldura.test.js && node test/gerativo-heroi.test.js && node test/gerativo-ambiente.test.js && node test/gerativo-variedade.test.js && node test/hibrido.test.js && node test/batida.test.js && node test/estudio-acervo.test.js && node test/estudio-diretor.test.js && node test/estudio-marca.test.js && node test/estudio-novo-projeto.test.js && node test/estudio-plano.test.js && node test/estudio-slides.test.js && node test/estudio-video.test.js && node test/revisor.test.js && node test/conferencia.test.js && node test/cor.test.js && node test/assinatura.test.js && node test/biblioteca.test.js && node test/mcp.test.js && node test/personas.test.js && node test/efeitos.test.js && node test/auto.test.js && node test/colar.test.js && node test/rolar.test.js && node test/orquestra.test.js && node test/shell-limpo.test.js && node test/editar-remotion.test.js && node test/variacao3d.test.js && node test/portao-skill.test.js && node test/clones.test.js && node test/kokoro.test.js && node test/fluido.test.js && node test/zoom.test.js && node test/personagem.test.js && node test/tela.test.js && node test/margem.test.js && node test/travado.test.js && node test/leitura.test.js && node test/producao-provedores.test.js && node test/broll-frase.test.js && node test/vazamento.test.js && node test/colecao.test.js && node test/mundo.test.js && node test/mcp-procurar.test.js && node test/selecao.test.js && node test/nome-curto.test.js && node test/agents-md.test.js && node test/outra-pasta.test.js && node test/estudio-sem-id.test.js && node test/estudio-objeto-do-site.test.js && node test/cenarios.test.js && node test/movimentos.test.js && node test/gerativo-so-fala.test.js && node test/estilos.test.js && node test/proporcao.test.js && node test/cena.test.js && node test/sem-narracao.test.js"
|
|
12
12
|
},
|
|
13
13
|
"engines": {
|
|
14
14
|
"node": ">=18.17.0"
|
|
@@ -50,6 +50,7 @@ desenha é você, em React.
|
|
|
50
50
|
`roteiro.estiloVisual` (humor, paleta, display, texto…). Um vídeo, uma
|
|
51
51
|
identidade: 2 chãos, 1 acento, 2 fontes.
|
|
52
52
|
3. `estudio_narrar` com o roteiro: os tempos MEDIDOS de cada fala.
|
|
53
|
+
Sem voz: pule; `semNarracao:true` e `duracao` por parte.
|
|
53
54
|
4. Para cada parte, `write_file` com `path:"componentes/<nome>.jsx"`:
|
|
54
55
|
`export default function Cena({ el, t, fps })`, `t` em segundos desde o
|
|
55
56
|
começo da parte. Em `el.dados`: `titulo`, `fala`, `palavras` (cada uma com
|
|
@@ -61,6 +62,9 @@ desenha é você, em React.
|
|
|
61
62
|
arquivo e mande o roteiro de novo.
|
|
62
63
|
6. `estudio_render`. A voz, a trilha, os sons e o fundo são do Estúdio.
|
|
63
64
|
|
|
65
|
+
**Variedade:** `estudio_midia acao:"efeitos"` antes das cenas; adapte e use
|
|
66
|
+
como `componente`. Uma técnica nova por vídeo. Risco em 2+ linhas: traço por linha.
|
|
67
|
+
|
|
64
68
|
Parte sem `componente` cai no gerativo (a tipografia anima sozinha): é a
|
|
65
69
|
reserva, não o objetivo. Sem imagem é o padrão (foto só se pedirem).
|
|
66
70
|
|