primocode 8.18.1 → 8.19.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.
- package/bin/primocode.js +5 -2
- package/package.json +1 -1
- package/studio/ferramentas/corte.md +19 -5
- package/studio/web/js/player.js +42 -6
package/bin/primocode.js
CHANGED
|
@@ -522,8 +522,11 @@ const RE_DESCOBRIR = /\b(pesquis|busca|procur|descubr|investig|analis|leia|estud
|
|
|
522
522
|
const RE_CRIAR_DEPOIS = /\b(cri[ae]|faz|faça|mont[ae]|ger[ae]|escrev[ae]|produz|desenvolv)\w*/i;
|
|
523
523
|
|
|
524
524
|
/** "baixa/exporta o vídeo" resolvido na hora, sem gastar modelo. */
|
|
525
|
-
|
|
526
|
-
|
|
525
|
+
// "me manda o vídeo", "quero pra mandar no zap", "gera o arquivo" — a lista
|
|
526
|
+
// era curta e o pedido sai de muitos jeitos. Fora dela, o pedido virava
|
|
527
|
+
// tarefa de agente: gasto de API para abrir uma URL que o CLI já sabe.
|
|
528
|
+
const RE_BAIXAR = /\b(baixa\w*|exporta\w*|download|salva\w*|grava\w*|me manda|manda(r)? (o|a|esse|essa)|gera(r)? o arquivo|em mp4|pra mandar|arquivo do)\b/i;
|
|
529
|
+
const RE_PECA_STUDIO = /\b(v[ií]deo|mp4|mp3|apresenta[çc][ãa]o|slides?|reels?|anima[çc][ãa]o|filme)\b/i;
|
|
527
530
|
|
|
528
531
|
async function baixarCriacaoDireto(texto) {
|
|
529
532
|
if (!(RE_BAIXAR.test(texto) && RE_PECA_STUDIO.test(texto))) return false;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "primocode",
|
|
3
|
-
"version": "8.
|
|
3
|
+
"version": "8.19.0",
|
|
4
4
|
"description": "PrimoCode — agente de engenharia com IA e cursor próprio. Modelos grátis. 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": {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# CORTE — vídeo
|
|
2
2
|
|
|
3
3
|
No lugar de CapCut, Premiere e After Effects. Modelo `cena`, com `duracao` em cada
|
|
4
|
-
cena, trilha sonora, transições e
|
|
4
|
+
cena, trilha sonora, transições e download em `.mp4`.
|
|
5
5
|
|
|
6
6
|
<!-- O EXEMPLO FICA NO COMEÇO DE PROPÓSITO: quando o plano de tokens é
|
|
7
7
|
apertado, o agente recebe só os primeiros ~3500 caracteres desta spec. Um
|
|
@@ -269,11 +269,25 @@ play/pausa, linha do tempo clicável com marca por cena, tempo, volume e **Grava
|
|
|
269
269
|
|
|
270
270
|
`K` toca e pausa · `M` corta o som · `→` `←` pulam cena · `F` tela cheia · `Escape` para.
|
|
271
271
|
|
|
272
|
-
##
|
|
272
|
+
## Baixar o vídeo como arquivo
|
|
273
273
|
|
|
274
|
-
O botão **
|
|
275
|
-
começo, para
|
|
276
|
-
|
|
274
|
+
O botão **Baixar MP4** no player faz tudo sozinho: pede a permissão de captura, toca
|
|
275
|
+
do começo, para no fim e baixa. Sai `.mp4` (H.264/AAC, que toca em qualquer lugar) nos
|
|
276
|
+
navegadores que sabem gravar MP4; onde não sabem, sai `.webm`.
|
|
277
|
+
|
|
278
|
+
**Se o usuário pedir o arquivo do vídeo** — "baixa", "exporta", "me manda em mp4",
|
|
279
|
+
"quero mandar no WhatsApp" — abra o player já em modo de gravação:
|
|
280
|
+
|
|
281
|
+
```
|
|
282
|
+
open_in_browser → http://localhost:7777/v/<id>#gravar
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
A âncora `#gravar` dispara o download assim que a página abre; o usuário só confirma a
|
|
286
|
+
permissão de captura. **Não** use `write_file` para criar `.mp4`, e **nunca** chame
|
|
287
|
+
ffmpeg: o vídeo já nasce pronto aqui, e escrever um `.mp4` com write_file produz um
|
|
288
|
+
arquivo de texto com nome de vídeo — já aconteceu.
|
|
289
|
+
|
|
290
|
+
Para o melhor resultado, entre em tela cheia (`F`) antes de gravar.
|
|
277
291
|
|
|
278
292
|
O export normal (`/api/arquivos/<id>/export`) devolve um `.html` autônomo com a
|
|
279
293
|
mídia embutida — abre offline em qualquer navegador e toca igual.
|
package/studio/web/js/player.js
CHANGED
|
@@ -337,7 +337,7 @@
|
|
|
337
337
|
'<div class="tp-tempo" id="tp-total">00:00</div>' +
|
|
338
338
|
'<button class="tp-btn pequeno" id="tp-som" title="Mudo (M)"></button>' +
|
|
339
339
|
'<input class="tp-vol" id="tp-vol" type="range" min="0" max="100" value="70">' +
|
|
340
|
-
'<button class="tp-btn texto" id="tp-gravar" title="
|
|
340
|
+
'<button class="tp-btn texto primo" id="tp-gravar" title="Baixar este vídeo como arquivo">Baixar MP4</button>';
|
|
341
341
|
document.body.appendChild(transporte);
|
|
342
342
|
|
|
343
343
|
document.getElementById("tp-tocar").onclick = function () { tocando ? pausar() : tocar(); };
|
|
@@ -393,14 +393,47 @@
|
|
|
393
393
|
iniciarGravacao();
|
|
394
394
|
}
|
|
395
395
|
|
|
396
|
+
/* O melhor formato que este navegador sabe gravar.
|
|
397
|
+
*
|
|
398
|
+
* A ordem importa: H.264 com AAC é o MP4 que toca em qualquer lugar —
|
|
399
|
+
* WhatsApp, Instagram, PowerPoint, TV. AV1 em MP4 é MP4 de verdade mas ainda
|
|
400
|
+
* não toca em tudo, então vem depois. O webm é o último recurso: abre em
|
|
401
|
+
* navegador e pouco mais.
|
|
402
|
+
*/
|
|
403
|
+
var FORMATOS = [
|
|
404
|
+
"video/mp4;codecs=avc1.42E01E,mp4a.40.2",
|
|
405
|
+
"video/mp4;codecs=avc1,mp4a.40.2",
|
|
406
|
+
"video/mp4;codecs=avc1",
|
|
407
|
+
"video/mp4",
|
|
408
|
+
"video/webm;codecs=vp9,opus",
|
|
409
|
+
"video/webm",
|
|
410
|
+
];
|
|
411
|
+
|
|
412
|
+
function escolherFormato() {
|
|
413
|
+
for (var i = 0; i < FORMATOS.length; i++) {
|
|
414
|
+
if (MediaRecorder.isTypeSupported(FORMATOS[i])) return FORMATOS[i];
|
|
415
|
+
}
|
|
416
|
+
return "video/webm";
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
function gravaMp4() { return /mp4/.test(escolherFormato()); }
|
|
420
|
+
|
|
396
421
|
function iniciarGravacao() {
|
|
397
422
|
if (!navigator.mediaDevices || !navigator.mediaDevices.getDisplayMedia) {
|
|
398
423
|
return aviso("este navegador não grava a tela", 3000);
|
|
399
424
|
}
|
|
400
425
|
// audio:true deixa o usuário marcar "compartilhar áudio da aba" — é assim
|
|
401
426
|
// que a narração falada entra na gravação
|
|
427
|
+
// preferCurrentTab tira o passo de escolher a janela: o Chrome já vem
|
|
428
|
+
// com ESTA aba selecionada, então baixar vira um clique e um "permitir"
|
|
429
|
+
// em vez de um clique, uma escolha e um "permitir".
|
|
402
430
|
navigator.mediaDevices.getDisplayMedia({
|
|
403
431
|
video: { frameRate: 30 }, audio: true,
|
|
432
|
+
preferCurrentTab: true, selfBrowserSurface: "include",
|
|
433
|
+
}).catch(function () {
|
|
434
|
+
// Navegador que não conhece preferCurrentTab recusa o pedido inteiro:
|
|
435
|
+
// repete sem as opções novas em vez de falhar.
|
|
436
|
+
return navigator.mediaDevices.getDisplayMedia({ video: { frameRate: 30 }, audio: true });
|
|
404
437
|
}).then(function (fluxo) {
|
|
405
438
|
fluxoTela = fluxo;
|
|
406
439
|
var faixas = fluxo.getVideoTracks();
|
|
@@ -410,11 +443,14 @@
|
|
|
410
443
|
}
|
|
411
444
|
var misto = new MediaStream(faixas);
|
|
412
445
|
pedacos = [];
|
|
413
|
-
// MP4 primeiro,
|
|
414
|
-
//
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
446
|
+
// MP4 primeiro, e testando os codecs NOMEADOS antes do genérico.
|
|
447
|
+
//
|
|
448
|
+
// Testar só "video/mp4" perdia MP4 em navegador que existe: o Chrome
|
|
449
|
+
// responde false para o nome solto e true para
|
|
450
|
+
// "video/mp4;codecs=avc1.42E01E,mp4a.40.2". Quem pediu MP4 recebia
|
|
451
|
+
// webm à toa. A lista vai do mais compatível (H.264 + AAC, que toca em
|
|
452
|
+
// tudo) para o menos, e só cai no webm quando não há MP4 nenhum.
|
|
453
|
+
var tipo = escolherFormato();
|
|
418
454
|
gravador = new MediaRecorder(misto, { mimeType: tipo, videoBitsPerSecond: 8000000 });
|
|
419
455
|
gravador.ondataavailable = function (ev) { if (ev.data.size) pedacos.push(ev.data); };
|
|
420
456
|
gravador.onstop = baixarGravacao;
|