vibeeditor-render 0.3.0 → 0.3.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/cli/sistema.js ADDED
@@ -0,0 +1,158 @@
1
+ // Integração com o sistema, para ninguém precisar abrir o Vibe Render na mão a cada vez que liga o computador:
2
+ // · início automático: sobe junto com o login (Windows: pasta Inicializar; Mac: LaunchAgent; Linux: autostart),
3
+ // minimizado e sem perguntar nada — o pareamento já fica salvo na pasta de dados;
4
+ // · link vibe-render://abrir: o botão "Abrir o Vibe Render" do site chama este link e o navegador pergunta
5
+ // "Abrir Vibe Render?" (Windows: registro do usuário; Linux: x-scheme-handler; Mac: um app pequeno em
6
+ // ~/Applications feito com o osacompile).
7
+ // Tudo fica na conta do usuário (nada de administrador) e cada passo que falhar só é pulado.
8
+ "use strict";
9
+ const fs = require("node:fs");
10
+ const os = require("node:os");
11
+ const path = require("node:path");
12
+ const {spawnSync} = require("node:child_process");
13
+
14
+ const PROTOCOLO = "vibe-render";
15
+ const COMANDO = "npx -y vibeeditor-render@latest --sem-atalho --segundo-plano";
16
+
17
+ const rodar = (cmd, args) => spawnSync(cmd, args, {encoding: "utf8", windowsHide: true});
18
+
19
+ /** pasta especial do Windows (Startup, Desktop…), já com OneDrive e nome traduzido */
20
+ function pastaWindows(qual) {
21
+ const r = rodar("powershell.exe", ["-NoProfile", "-NonInteractive", "-Command", `[Environment]::GetFolderPath('${qual}')`]);
22
+ const p = String(r.stdout || "").trim();
23
+ return r.status === 0 && p ? p : null;
24
+ }
25
+
26
+ /** onde fica o arquivo do início automático em cada sistema */
27
+ function arquivoInicio(plataforma = process.platform, casa = os.homedir(), env = process.env) {
28
+ if (plataforma === "win32") {
29
+ const startup = pastaWindows("Startup") || path.join(env.APPDATA || path.join(casa, "AppData", "Roaming"), "Microsoft", "Windows", "Start Menu", "Programs", "Startup");
30
+ return path.join(startup, "Vibe Render.cmd");
31
+ }
32
+ if (plataforma === "darwin") return path.join(casa, "Library", "LaunchAgents", "br.com.vibeeditor.render.plist");
33
+ return path.join(env.XDG_CONFIG_HOME || path.join(casa, ".config"), "autostart", "vibeeditor-render.desktop");
34
+ }
35
+
36
+ /** conteúdo do arquivo do início automático (minimizado, sem pausa no fim) */
37
+ function conteudoInicio(plataforma = process.platform, dirDados = "") {
38
+ if (plataforma === "win32") return `@echo off\r\nstart "Vibe Render" /min cmd /c "${COMANDO}"\r\n`;
39
+ if (plataforma === "darwin") {
40
+ const log = path.join(dirDados, "inicio.log");
41
+ return `<?xml version="1.0" encoding="UTF-8"?>
42
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
43
+ <plist version="1.0">
44
+ <dict>
45
+ <key>Label</key><string>br.com.vibeeditor.render</string>
46
+ <key>ProgramArguments</key>
47
+ <array><string>/bin/bash</string><string>-lc</string><string>${COMANDO}</string></array>
48
+ <key>RunAtLoad</key><true/>
49
+ <key>StandardOutPath</key><string>${log}</string>
50
+ <key>StandardErrorPath</key><string>${log}</string>
51
+ </dict>
52
+ </plist>
53
+ `;
54
+ }
55
+ return `[Desktop Entry]
56
+ Type=Application
57
+ Name=Vibe Render
58
+ Comment=Exporta os vídeos do Editor IA neste computador
59
+ Exec=bash -lc "${COMANDO}"
60
+ Terminal=false
61
+ X-GNOME-Autostart-enabled=true
62
+ `;
63
+ }
64
+
65
+ function ligarInicio({dirDados}) {
66
+ const arq = arquivoInicio();
67
+ fs.mkdirSync(path.dirname(arq), {recursive: true});
68
+ fs.writeFileSync(arq, conteudoInicio(process.platform, dirDados), {mode: 0o644});
69
+ return arq;
70
+ }
71
+
72
+ function desligarInicio() {
73
+ const arq = arquivoInicio();
74
+ const tinha = fs.existsSync(arq);
75
+ fs.rmSync(arq, {force: true});
76
+ return tinha;
77
+ }
78
+
79
+ const inicioLigado = () => fs.existsSync(arquivoInicio());
80
+
81
+ /** o link vibe-render://abrir chama este iniciador (Windows/Linux); abre visível, mas sem segurar a janela */
82
+ function registrarProtocolo({dirDados}) {
83
+ if (process.platform === "win32") {
84
+ const iniciador = path.join(dirDados, "abrir.cmd");
85
+ fs.writeFileSync(iniciador, `@echo off\r\nstart "Vibe Render" cmd /c "npx -y vibeeditor-render@latest --sem-atalho"\r\n`);
86
+ const chave = `HKCU\\Software\\Classes\\${PROTOCOLO}`;
87
+ const passos = [
88
+ ["add", chave, "/ve", "/d", "URL:Vibe Render", "/f"],
89
+ ["add", chave, "/v", "URL Protocol", "/d", "", "/f"],
90
+ ["add", `${chave}\\shell\\open\\command`, "/ve", "/d", `"${iniciador}" "%1"`, "/f"],
91
+ ];
92
+ for (const p of passos) {
93
+ const r = rodar("reg.exe", p);
94
+ if (r.status !== 0) throw new Error(`não consegui registrar o link (${String(r.stderr || r.stdout).trim()})`);
95
+ }
96
+ return `${PROTOCOLO}:// → ${iniciador}`;
97
+ }
98
+ if (process.platform === "darwin") {
99
+ // app de AppleScript que recebe o link e sobe o Vibe Render em segundo plano
100
+ const app = path.join(os.homedir(), "Applications", "Vibe Render.app");
101
+ fs.mkdirSync(path.dirname(app), {recursive: true});
102
+ const log = path.join(dirDados, "abrir.log");
103
+ const script = [
104
+ "on open location u",
105
+ ` do shell script "/bin/bash -lc 'nohup ${COMANDO.replace("--segundo-plano", "")} > \\"${log}\\" 2>&1 &'"`,
106
+ "end open location",
107
+ "on run",
108
+ ` do shell script "/bin/bash -lc 'nohup ${COMANDO.replace("--segundo-plano", "")} > \\"${log}\\" 2>&1 &'"`,
109
+ "end run",
110
+ ];
111
+ fs.rmSync(app, {recursive: true, force: true});
112
+ const r = rodar("osacompile", ["-o", app, ...script.flatMap((l) => ["-e", l])]);
113
+ if (r.status !== 0) throw new Error(`osacompile falhou (${String(r.stderr).trim()})`);
114
+ const plist = path.join(app, "Contents", "Info.plist");
115
+ for (const a of [
116
+ "Add :CFBundleIdentifier string br.com.vibeeditor.render.link",
117
+ "Add :CFBundleURLTypes array", "Add :CFBundleURLTypes:0 dict",
118
+ "Add :CFBundleURLTypes:0:CFBundleURLName string Vibe Render",
119
+ "Add :CFBundleURLTypes:0:CFBundleURLSchemes array",
120
+ `Add :CFBundleURLTypes:0:CFBundleURLSchemes:0 string ${PROTOCOLO}`,
121
+ ]) rodar("/usr/libexec/PlistBuddy", ["-c", a, plist]);
122
+ rodar("/System/Library/Frameworks/CoreServices.framework/Frameworks/LaunchServices.framework/Support/lsregister", ["-f", app]);
123
+ return `${PROTOCOLO}:// → ${app}`;
124
+ }
125
+ const apps = path.join(process.env.XDG_DATA_HOME || path.join(os.homedir(), ".local", "share"), "applications");
126
+ fs.mkdirSync(apps, {recursive: true});
127
+ const desk = path.join(apps, "vibeeditor-render-link.desktop");
128
+ fs.writeFileSync(desk, `[Desktop Entry]
129
+ Type=Application
130
+ Name=Vibe Render
131
+ Exec=bash -lc "npx -y vibeeditor-render@latest --sem-atalho" %u
132
+ Terminal=true
133
+ NoDisplay=true
134
+ MimeType=x-scheme-handler/${PROTOCOLO};
135
+ `);
136
+ rodar("xdg-mime", ["default", "vibeeditor-render-link.desktop", `x-scheme-handler/${PROTOCOLO}`]);
137
+ return `${PROTOCOLO}:// → ${desk}`;
138
+ }
139
+
140
+ /** liga tudo de uma vez; devolve o que deu certo e o que foi pulado (com o motivo) */
141
+ function integrar({dirDados, inicio = true}) {
142
+ const feito = [], pulado = [];
143
+ try {
144
+ feito.push(`link ${registrarProtocolo({dirDados})}`);
145
+ } catch (e) {
146
+ pulado.push(`link vibe-render:// (${e.message})`);
147
+ }
148
+ if (inicio) {
149
+ try {
150
+ feito.push(`início automático em ${ligarInicio({dirDados})}`);
151
+ } catch (e) {
152
+ pulado.push(`início automático (${e.message})`);
153
+ }
154
+ }
155
+ return {feito, pulado};
156
+ }
157
+
158
+ module.exports = {integrar, ligarInicio, desligarInicio, inicioLigado, registrarProtocolo, arquivoInicio, conteudoInicio, PROTOCOLO, COMANDO};
@@ -8,7 +8,9 @@
8
8
  // vibeeditor-render --pasta <dir> muda a pasta onde os vídeos são salvos (fica guardada)
9
9
  // vibeeditor-render --voicestudio <url> endereço do VoiceStudio deste computador (fica guardado)
10
10
  // vibeeditor-render desparear desliga este computador da conta
11
- // vibeeditor-render atalho (re)cria o atalho "Vibe Render" na área de trabalho
11
+ // vibeeditor-render atalho (re)cria o atalho "Vibe Render", o link vibe-render:// e o início automático
12
+ // vibeeditor-render sem-inicio-automatico não abre mais junto com o computador
13
+ // vibeeditor-render --segundo-plano como o início automático chama: minimizado, sem perguntar nada
12
14
  "use strict";
13
15
  const fs = require("node:fs");
14
16
  const os = require("node:os");
@@ -20,6 +22,8 @@ const PACOTE = require("../package.json");
20
22
  const VERSAO = PACOTE.version;
21
23
  const RAIZ = path.join(__dirname, "..");
22
24
  const SITE = "https://plat.vibeeditor.com.br/editor/render";
25
+ const sistema = require("./sistema");
26
+ const VERSAO_INTEGRACAO = 1; // sobe quando o que sistema.integrar() faz mudar
23
27
 
24
28
  // ------------------------------------------------------------------ terminal
25
29
 
@@ -38,7 +42,8 @@ ${negrito("Vibe Render")} ${cinza(`v${VERSAO}`)} · exporta os vídeos do Editor
38
42
  ${azul("npx vibeeditor-render@latest --pasta \"C:\\Videos\"")} muda a pasta dos vídeos
39
43
  ${azul("npx vibeeditor-render@latest --voicestudio http://127.0.0.1:3900")} endereço do VoiceStudio (voz clonada)
40
44
  ${azul("npx vibeeditor-render@latest desparear")} desliga este computador da sua conta
41
- ${azul("npx vibeeditor-render@latest atalho")} cria o atalho na área de trabalho
45
+ ${azul("npx vibeeditor-render@latest atalho")} atalho, botão "Abrir" do site e início junto com o computador
46
+ ${azul("npx vibeeditor-render@latest sem-inicio-automatico")} não abre mais junto com o computador
42
47
 
43
48
  Deixe a janela aberta enquanto exporta. Para fechar: Ctrl+C.
44
49
  Ajuda: ${SITE}
@@ -46,7 +51,7 @@ Ajuda: ${SITE}
46
51
  }
47
52
 
48
53
  function lerArgs(argv) {
49
- const a = {comando: null, codigo: null, pasta: null, voicestudio: null, semAtalho: false};
54
+ const a = {comando: null, codigo: null, pasta: null, voicestudio: null, semAtalho: false, segundoPlano: false};
50
55
  for (let i = 0; i < argv.length; i++) {
51
56
  const v = argv[i];
52
57
  if (v === "--codigo" || v === "-c") a.codigo = argv[++i] || "";
@@ -56,6 +61,7 @@ function lerArgs(argv) {
56
61
  else if (v === "--voicestudio") a.voicestudio = argv[++i] || "";
57
62
  else if (v.startsWith("--voicestudio=")) a.voicestudio = v.slice(14);
58
63
  else if (v === "--sem-atalho") a.semAtalho = true;
64
+ else if (v === "--segundo-plano") a.segundoPlano = true;
59
65
  else if (v === "--versao" || v === "-v" || v === "--version") a.comando = "versao";
60
66
  else if (v === "--ajuda" || v === "-h" || v === "--help") a.comando = "ajuda";
61
67
  else if (!v.startsWith("-") && !a.comando) a.comando = v;
@@ -204,7 +210,7 @@ async function principal() {
204
210
  const args = lerArgs(process.argv.slice(2));
205
211
  if (args.comando === "versao") return dizer(VERSAO);
206
212
  if (args.comando === "ajuda") return ajuda();
207
- if (args.comando && !["desparear", "atalho"].includes(args.comando)) throw new Error(`não conheço o comando "${args.comando}". Veja: npx vibeeditor-render --ajuda`);
213
+ if (args.comando && !["desparear", "atalho", "sem-inicio-automatico"].includes(args.comando)) throw new Error(`não conheço o comando "${args.comando}". Veja: npx vibeeditor-render --ajuda`);
208
214
 
209
215
  const [maior] = process.versions.node.split(".").map(Number);
210
216
  if (maior < 20) throw new Error(`o Vibe Render precisa do Node.js 20 ou mais novo (este computador tem ${process.version}). Atualize em https://nodejs.org`);
@@ -228,7 +234,18 @@ async function principal() {
228
234
  }
229
235
  if (args.comando === "atalho") {
230
236
  const a = criarAtalho();
231
- return dizer(a ? `${verde("✓")} Atalho criado: ${a}` : "Atalho só no Windows e no Mac. Aqui, rode: npx vibeeditor-render@latest");
237
+ dizer(a ? `${verde("✓")} Atalho criado: ${a}` : "Atalho na área de trabalho só no Windows e no Mac.");
238
+ config = {...config, semInicio: false};
239
+ const r = sistema.integrar({dirDados: dados});
240
+ for (const f of r.feito) dizer(`${verde("✓")} ${f}`);
241
+ for (const p of r.pulado) dizer(`${ambar("!")} Pulei: ${p}`);
242
+ config = {...config, atalhoCriado: true, integrado: VERSAO_INTEGRACAO}; gravarConfig();
243
+ return;
244
+ }
245
+ if (args.comando === "sem-inicio-automatico") {
246
+ const tinha = sistema.desligarInicio();
247
+ config = {...config, semInicio: true, integrado: VERSAO_INTEGRACAO}; gravarConfig();
248
+ return dizer(tinha ? `${verde("✓")} O Vibe Render não abre mais junto com o computador. Para voltar: npx vibeeditor-render@latest atalho` : "O início automático já estava desligado.");
232
249
  }
233
250
  if (args.pasta) {
234
251
  config = {...config, dirSaida: path.resolve(args.pasta)}; gravarConfig();
@@ -243,7 +260,7 @@ async function principal() {
243
260
  const {PORTAS} = require("../core/config");
244
261
  const outra = await jaAberto(PORTAS);
245
262
  if (outra) {
246
- dizer(`${ambar("!")} O Vibe Render já está aberto em outra janela (porta ${outra}). Use aquela.`);
263
+ if (!args.segundoPlano) dizer(`${ambar("!")} O Vibe Render já está aberto em outra janela (porta ${outra}). Use aquela.`);
247
264
  return;
248
265
  }
249
266
 
@@ -262,6 +279,15 @@ async function principal() {
262
279
  mostrarArquivo, log, voiceStudio: args.voicestudio || null,
263
280
  });
264
281
 
282
+ // link vibe-render:// (botão "Abrir" do site) e início junto com o computador: uma vez por versão da
283
+ // integração, também para quem já abria pelo atalho antigo (que passa --sem-atalho)
284
+ if (config.integrado !== VERSAO_INTEGRACAO) {
285
+ const r = sistema.integrar({dirDados: dados, inicio: !config.semInicio});
286
+ if (r.feito.length) dizer(`${verde("✓")} Daqui para a frente o Vibe Render abre sozinho junto com o computador, e o site consegue abri-lo pelo botão. ${cinza("(para desligar: npx vibeeditor-render@latest sem-inicio-automatico)")}`);
287
+ for (const p of r.pulado) log("integração pulada:", p);
288
+ config = {...config, integrado: VERSAO_INTEGRACAO}; gravarConfig();
289
+ }
290
+
265
291
  // atalho na área de trabalho, uma vez (quem abriu pelo atalho passa --sem-atalho)
266
292
  if (!args.semAtalho && !config.atalhoCriado) {
267
293
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vibeeditor-render",
3
- "version": "0.3.0",
3
+ "version": "0.3.1",
4
4
  "description": "Vibe Render: exporta os vídeos do Editor IA (vibeeditor.com.br) no seu computador, com Remotion + Chrome Headless Shell.",
5
5
  "keywords": [
6
6
  "vibeeditor",