dev-toolkit-cli 1.0.3 → 1.0.5

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/lib/bash.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { exec } from "child_process";
2
- import { resolutionMapping } from "./constants.js";
3
2
  import { CommanderError } from "commander";
3
+ import * as os from "os";
4
4
  export const execAsync = (command) => new Promise((resolve, reject) => {
5
5
  exec(command, (error, stdout, stderr) => {
6
6
  if (error)
@@ -25,33 +25,125 @@ export async function check_dependencies(dependencies = globalDependencies) {
25
25
  throw new CommanderError(1, "missing_dependencies", missing_dependencies.map((dep) => `'${dep}'`).join(", "));
26
26
  }
27
27
  }
28
- async function getBestEncoder() {
28
+ // Cache para não termos que detectar a GPU toda vez que formos comprimir um vídeo
29
+ let cachedGpuType = null;
30
+ /**
31
+ * Detecta a GPU instalada na máquina rodando comandos nativos do SO.
32
+ */
33
+ async function detectGPU() {
34
+ if (cachedGpuType)
35
+ return cachedGpuType; // Retorna do cache se já sabemos
36
+ const platform = os.platform();
29
37
  try {
30
- const { stdout } = (await execAsync("ffmpeg -encoders"));
31
- // Lista de prioridade de encoders de hardware para H.264
32
- if (stdout.includes("h264_nvenc"))
33
- return "h264_nvenc"; // NVIDIA
34
- if (stdout.includes("h264_amf"))
35
- return "h264_amf"; // AMD
36
- if (stdout.includes("h264_qsv"))
37
- return "h264_qsv"; // Intel
38
- if (stdout.includes("h264_videotoolbox"))
39
- return "h264_videotoolbox"; // Apple Silicon
40
- return "libx264"; // Fallback para CPU
38
+ // Se for Mac, assume VideoToolbox (Aceleração nativa da Apple)
39
+ if (platform === "darwin") {
40
+ cachedGpuType = "mac";
41
+ return cachedGpuType;
42
+ }
43
+ let output = "";
44
+ // Se for Windows, usa o WMIC para listar as placas de vídeo
45
+ if (platform === "win32") {
46
+ const stdout = await execAsync("wmic path win32_VideoController get name");
47
+ output = stdout.toLowerCase();
48
+ }
49
+ // Se for Linux, usa o lspci para listar os hardwares PCI
50
+ else if (platform === "linux") {
51
+ const stdout = await execAsync("lspci");
52
+ output = stdout.toLowerCase();
53
+ }
54
+ // Analisa a saída dos comandos para descobrir a marca
55
+ if (output.includes("nvidia")) {
56
+ cachedGpuType = "nvidia";
57
+ }
58
+ else if (output.includes("amd") || output.includes("radeon")) {
59
+ cachedGpuType = "amd";
60
+ }
61
+ else if (output.includes("intel")) {
62
+ cachedGpuType = "intel";
63
+ }
64
+ else {
65
+ cachedGpuType = "cpu"; // Fallback se não identificar nada
66
+ }
41
67
  }
42
- catch {
43
- return "libx264";
68
+ catch (error) {
69
+ if (error instanceof Error)
70
+ console.warn("⚠️ Aviso: Falha ao detectar GPU. Usando CPU por segurança.", error.message);
71
+ cachedGpuType = "cpu";
44
72
  }
73
+ return cachedGpuType;
45
74
  }
46
75
  export async function ffmpeg_video_compress(input, output, resolution = "480p", forceResolution) {
76
+ // Exemplo de mapeamento (ajuste para bater com o seu código original)
77
+ const resolutionMapping = {
78
+ "4320p": { w: 7680, h: 4320 }, // 8K
79
+ "2160p": { w: 3840, h: 2160 }, // 4K
80
+ "1440p": { w: 2560, h: 1440 }, // Quad HD
81
+ "1080p": { w: 1920, h: 1080 }, // Full HD
82
+ "720p": { w: 1280, h: 720 }, // HD
83
+ "480p": { w: 854, h: 480 }, // SD (WVGA)
84
+ "360p": { w: 640, h: 360 }, // nHD
85
+ "240p": { w: 426, h: 240 }, // WQVGA
86
+ };
47
87
  const { w, h } = resolutionMapping[resolution];
48
- const encoder = await getBestEncoder();
49
- console.log("Compressing video using: ", encoder);
50
- // Nota: Encoders de GPU não suportam todos os mesmos parâmetros de CPU.
51
- // Usamos -pix_fmt yuv420p para garantir compatibilidade universal.
52
- const filter = forceResolution ? `-s ${w}x${h}` : `-filter:v scale=-1:${h}`;
53
- return execAsync(`ffmpeg -i "${input}" ${filter} -c:v ${encoder} -pix_fmt yuv420p -acodec copy -y "${output}"`);
88
+ // 1. Detecta a GPU automaticamente
89
+ const gpu = await detectGPU();
90
+ // 2. Mapeia os Encoders com base no hardware detectado
91
+ const encoders = {
92
+ nvidia: "-c:v h264_nvenc -preset p4",
93
+ amd: "-c:v h264_amf",
94
+ intel: "-c:v h264_qsv",
95
+ mac: "-c:v h264_videotoolbox",
96
+ cpu: "-c:v libx264 -preset fast",
97
+ };
98
+ const vcodec = encoders[gpu] || encoders.cpu;
99
+ const hwaccel = gpu === "cpu" ? "" : "-hwaccel auto";
100
+ // 3. Define o filtro de resolução
101
+ const scaleFilter = forceResolution
102
+ ? `-s ${w}x${h}`
103
+ : `-filter:v scale=-1:${h}`;
104
+ // 4. Monta e executa o comando FFmpeg
105
+ const command = `ffmpeg ${hwaccel} -i "${input}" ${scaleFilter} ${vcodec} -acodec copy -y "${output}"`;
106
+ console.log("Converting using: ", vcodec);
107
+ return execAsync(command);
54
108
  }
109
+ // async function getBestEncoder(): Promise<string> {
110
+ // try {
111
+ // const { stdout } = (await execAsync("ffmpeg -encoders")) as {
112
+ // stdout: string;
113
+ // };
114
+ // // Prioridade para AMD (Windows: amf | Linux: vaapi)
115
+ // if (stdout.includes("h264_amf")) return "h264_amf";
116
+ // if (stdout.includes("h264_vaapi")) return "h264_vaapi";
117
+ // // Outros hardwares
118
+ // if (stdout.includes("h264_nvenc")) return "h264_nvenc";
119
+ // if (stdout.includes("h264_qsv")) return "h264_qsv";
120
+ // if (stdout.includes("h264_videotoolbox")) return "h264_videotoolbox";
121
+ // return "libx264"; // Fallback
122
+ // } catch {
123
+ // return "libx264";
124
+ // }
125
+ // }
126
+ // export async function ffmpeg_video_compress(
127
+ // input: string,
128
+ // output: string,
129
+ // resolution: Resolution = "480p",
130
+ // forceResolution?: boolean,
131
+ // ) {
132
+ // const { w, h } = resolutionMapping[resolution];
133
+ // const encoder = await getBestEncoder();
134
+ // // No VA-API (Linux), o redimensionamento deve ser feito via hardware para máxima performance
135
+ // let filter = forceResolution ? `scale=${w}:${h}` : `scale=-1:${h}`;
136
+ // if (encoder === "h264_vaapi") {
137
+ // // Adiciona upload para hardware se usar vaapi
138
+ // filter = `format=nv12,hwupload,scale_vaapi=w=${forceResolution ? w : -1}:h=${h}`;
139
+ // }
140
+ // const vaapiOpts =
141
+ // encoder === "h264_vaapi" ? "-vaapi_device /dev/dri/renderD128" : "";
142
+ // console.log("Compressing video using: ", encoder);
143
+ // return execAsync(
144
+ // `ffmpeg ${vaapiOpts} -i "${input}" -vf "${filter}" -c:v ${encoder} -pix_fmt yuv420p -acodec copy -y "${output}"`,
145
+ // );
146
+ // }
55
147
  // export async function ffmpeg_video_compress(
56
148
  // input: string,
57
149
  // output: string,
@@ -1 +1 @@
1
- {"version":3,"file":"bash.js","sourceRoot":"","sources":["../../src/lib/bash.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"bash.js","sourceRoot":"","sources":["../../src/lib/bash.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dev-toolkit-cli",
3
- "version": "1.0.3",
3
+ "version": "1.0.5",
4
4
  "repository": "https://github.com/daviinacio/dev-toolkit",
5
5
  "author": "Davi Inácio <aazz6850@gmail.com>",
6
6
  "license": "MIT",
package/src/lib/bash.ts CHANGED
@@ -1,8 +1,10 @@
1
1
  import { exec } from "child_process";
2
2
  import { Resolution, resolutionMapping } from "./constants.js";
3
3
  import { CommanderError } from "commander";
4
+ import { promisify } from "util";
5
+ import * as os from "os";
4
6
 
5
- export const execAsync = (command: string) =>
7
+ export const execAsync = (command: string): Promise<string> =>
6
8
  new Promise((resolve, reject) => {
7
9
  exec(command, (error, stdout, stderr) => {
8
10
  if (error) reject(new Error(stderr));
@@ -33,23 +35,61 @@ export async function check_dependencies(dependencies = globalDependencies) {
33
35
  );
34
36
  }
35
37
  }
38
+ type GpuType = "nvidia" | "amd" | "intel" | "mac" | "cpu";
39
+
40
+ // Cache para não termos que detectar a GPU toda vez que formos comprimir um vídeo
41
+ let cachedGpuType: GpuType | null = null;
42
+
43
+ /**
44
+ * Detecta a GPU instalada na máquina rodando comandos nativos do SO.
45
+ */
46
+ async function detectGPU(): Promise<GpuType> {
47
+ if (cachedGpuType) return cachedGpuType; // Retorna do cache se já sabemos
48
+
49
+ const platform = os.platform();
36
50
 
37
- async function getBestEncoder(): Promise<string> {
38
51
  try {
39
- const { stdout } = (await execAsync("ffmpeg -encoders")) as {
40
- stdout: string;
41
- };
42
-
43
- // Lista de prioridade de encoders de hardware para H.264
44
- if (stdout.includes("h264_nvenc")) return "h264_nvenc"; // NVIDIA
45
- if (stdout.includes("h264_amf")) return "h264_amf"; // AMD
46
- if (stdout.includes("h264_qsv")) return "h264_qsv"; // Intel
47
- if (stdout.includes("h264_videotoolbox")) return "h264_videotoolbox"; // Apple Silicon
48
-
49
- return "libx264"; // Fallback para CPU
50
- } catch {
51
- return "libx264";
52
+ // Se for Mac, assume VideoToolbox (Aceleração nativa da Apple)
53
+ if (platform === "darwin") {
54
+ cachedGpuType = "mac";
55
+ return cachedGpuType;
56
+ }
57
+
58
+ let output = "";
59
+
60
+ // Se for Windows, usa o WMIC para listar as placas de vídeo
61
+ if (platform === "win32") {
62
+ const stdout = await execAsync(
63
+ "wmic path win32_VideoController get name",
64
+ );
65
+ output = stdout.toLowerCase();
66
+ }
67
+ // Se for Linux, usa o lspci para listar os hardwares PCI
68
+ else if (platform === "linux") {
69
+ const stdout = await execAsync("lspci");
70
+ output = stdout.toLowerCase();
71
+ }
72
+
73
+ // Analisa a saída dos comandos para descobrir a marca
74
+ if (output.includes("nvidia")) {
75
+ cachedGpuType = "nvidia";
76
+ } else if (output.includes("amd") || output.includes("radeon")) {
77
+ cachedGpuType = "amd";
78
+ } else if (output.includes("intel")) {
79
+ cachedGpuType = "intel";
80
+ } else {
81
+ cachedGpuType = "cpu"; // Fallback se não identificar nada
82
+ }
83
+ } catch (error) {
84
+ if (error instanceof Error)
85
+ console.warn(
86
+ "⚠️ Aviso: Falha ao detectar GPU. Usando CPU por segurança.",
87
+ error.message,
88
+ );
89
+ cachedGpuType = "cpu";
52
90
  }
91
+
92
+ return cachedGpuType;
53
93
  }
54
94
 
55
95
  export async function ffmpeg_video_compress(
@@ -58,20 +98,94 @@ export async function ffmpeg_video_compress(
58
98
  resolution: Resolution = "480p",
59
99
  forceResolution?: boolean,
60
100
  ) {
101
+ // Exemplo de mapeamento (ajuste para bater com o seu código original)
102
+ const resolutionMapping: { [key in Resolution]: { w: number; h: number } } = {
103
+ "4320p": { w: 7680, h: 4320 }, // 8K
104
+ "2160p": { w: 3840, h: 2160 }, // 4K
105
+ "1440p": { w: 2560, h: 1440 }, // Quad HD
106
+ "1080p": { w: 1920, h: 1080 }, // Full HD
107
+ "720p": { w: 1280, h: 720 }, // HD
108
+ "480p": { w: 854, h: 480 }, // SD (WVGA)
109
+ "360p": { w: 640, h: 360 }, // nHD
110
+ "240p": { w: 426, h: 240 }, // WQVGA
111
+ };
112
+
61
113
  const { w, h } = resolutionMapping[resolution];
62
- const encoder = await getBestEncoder();
63
114
 
64
- console.log("Compressing video using: ", encoder);
115
+ // 1. Detecta a GPU automaticamente
116
+ const gpu = await detectGPU();
117
+
118
+ // 2. Mapeia os Encoders com base no hardware detectado
119
+ const encoders = {
120
+ nvidia: "-c:v h264_nvenc -preset p4",
121
+ amd: "-c:v h264_amf",
122
+ intel: "-c:v h264_qsv",
123
+ mac: "-c:v h264_videotoolbox",
124
+ cpu: "-c:v libx264 -preset fast",
125
+ };
65
126
 
66
- // Nota: Encoders de GPU não suportam todos os mesmos parâmetros de CPU.
67
- // Usamos -pix_fmt yuv420p para garantir compatibilidade universal.
68
- const filter = forceResolution ? `-s ${w}x${h}` : `-filter:v scale=-1:${h}`;
127
+ const vcodec = encoders[gpu] || encoders.cpu;
128
+ const hwaccel = gpu === "cpu" ? "" : "-hwaccel auto";
69
129
 
70
- return execAsync(
71
- `ffmpeg -i "${input}" ${filter} -c:v ${encoder} -pix_fmt yuv420p -acodec copy -y "${output}"`,
72
- );
130
+ // 3. Define o filtro de resolução
131
+ const scaleFilter = forceResolution
132
+ ? `-s ${w}x${h}`
133
+ : `-filter:v scale=-1:${h}`;
134
+
135
+ // 4. Monta e executa o comando FFmpeg
136
+ const command = `ffmpeg ${hwaccel} -i "${input}" ${scaleFilter} ${vcodec} -acodec copy -y "${output}"`;
137
+
138
+ console.log("Converting using: ", vcodec);
139
+
140
+ return execAsync(command);
73
141
  }
74
142
 
143
+ // async function getBestEncoder(): Promise<string> {
144
+ // try {
145
+ // const { stdout } = (await execAsync("ffmpeg -encoders")) as {
146
+ // stdout: string;
147
+ // };
148
+
149
+ // // Prioridade para AMD (Windows: amf | Linux: vaapi)
150
+ // if (stdout.includes("h264_amf")) return "h264_amf";
151
+ // if (stdout.includes("h264_vaapi")) return "h264_vaapi";
152
+
153
+ // // Outros hardwares
154
+ // if (stdout.includes("h264_nvenc")) return "h264_nvenc";
155
+ // if (stdout.includes("h264_qsv")) return "h264_qsv";
156
+ // if (stdout.includes("h264_videotoolbox")) return "h264_videotoolbox";
157
+
158
+ // return "libx264"; // Fallback
159
+ // } catch {
160
+ // return "libx264";
161
+ // }
162
+ // }
163
+
164
+ // export async function ffmpeg_video_compress(
165
+ // input: string,
166
+ // output: string,
167
+ // resolution: Resolution = "480p",
168
+ // forceResolution?: boolean,
169
+ // ) {
170
+ // const { w, h } = resolutionMapping[resolution];
171
+ // const encoder = await getBestEncoder();
172
+
173
+ // // No VA-API (Linux), o redimensionamento deve ser feito via hardware para máxima performance
174
+ // let filter = forceResolution ? `scale=${w}:${h}` : `scale=-1:${h}`;
175
+ // if (encoder === "h264_vaapi") {
176
+ // // Adiciona upload para hardware se usar vaapi
177
+ // filter = `format=nv12,hwupload,scale_vaapi=w=${forceResolution ? w : -1}:h=${h}`;
178
+ // }
179
+
180
+ // const vaapiOpts =
181
+ // encoder === "h264_vaapi" ? "-vaapi_device /dev/dri/renderD128" : "";
182
+
183
+ // console.log("Compressing video using: ", encoder);
184
+
185
+ // return execAsync(
186
+ // `ffmpeg ${vaapiOpts} -i "${input}" -vf "${filter}" -c:v ${encoder} -pix_fmt yuv420p -acodec copy -y "${output}"`,
187
+ // );
188
+ // }
75
189
  // export async function ffmpeg_video_compress(
76
190
  // input: string,
77
191
  // output: string,