dev-toolkit-cli 1.1.1 → 1.1.2
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/actions/action-compress.js +8 -8
- package/bin/actions/action-compress.js.map +1 -1
- package/bin/lib/bash.js +121 -27
- package/bin/lib/bash.js.map +1 -1
- package/bin/lib/constants.js +8 -32
- package/bin/lib/constants.js.map +1 -1
- package/package.json +1 -1
- package/src/actions/action-compress.ts +8 -15
- package/src/lib/bash.ts +143 -31
- package/src/lib/constants.ts +12 -35
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import fs from "fs/promises";
|
|
2
2
|
import mime from "mime";
|
|
3
3
|
import { getFolderFiles, replaceFilenameExtension, } from "../lib/utils/index.js";
|
|
4
|
-
import { check_dependencies, ffmpeg_image_to_webp,
|
|
4
|
+
import { check_dependencies, ffmpeg_image_to_webp, ffmpeg_video_to_webm, } from "../lib/bash.js";
|
|
5
5
|
export const FileType = ["image", "video"];
|
|
6
6
|
const unsupportedFormats = {
|
|
7
7
|
image: ["image/webp", "image/gif", "image/svg+xml"],
|
|
@@ -13,7 +13,7 @@ export async function file(pathname, { verbose, type, resolution, force, horizon
|
|
|
13
13
|
console.warn("⚠️ Ignoring already compressed files");
|
|
14
14
|
if (horizontal)
|
|
15
15
|
console.warn("⚠️ Forcing horizontal aspect ratio 16x9");
|
|
16
|
-
let verbose_title = "";
|
|
16
|
+
// let verbose_title = "";
|
|
17
17
|
const filePathList = await getFolderFiles(pathname, true);
|
|
18
18
|
for (let filePath of filePathList) {
|
|
19
19
|
const mimetype = mime.getType(filePath);
|
|
@@ -28,14 +28,14 @@ export async function file(pathname, { verbose, type, resolution, force, horizon
|
|
|
28
28
|
.split("/")
|
|
29
29
|
.slice(1, 1 + verbose)
|
|
30
30
|
.join("/");
|
|
31
|
-
if (title !== verbose_title)
|
|
32
|
-
|
|
33
|
-
verbose_title = title;
|
|
31
|
+
// if (title !== verbose_title)
|
|
32
|
+
// console.log(`Compressing ${fileType} at:`, title);
|
|
33
|
+
// verbose_title = title;
|
|
34
34
|
try {
|
|
35
35
|
if (fileType === "image")
|
|
36
36
|
await compressImage(filePath);
|
|
37
37
|
else if (fileType === "video")
|
|
38
|
-
await compressVideo(filePath
|
|
38
|
+
await compressVideo(filePath);
|
|
39
39
|
}
|
|
40
40
|
catch (err) {
|
|
41
41
|
if (verbose > 10)
|
|
@@ -50,8 +50,8 @@ async function compressImage(filePath) {
|
|
|
50
50
|
await ffmpeg_image_to_webp(filePath, replaceFilenameExtension(filePath, "webp"));
|
|
51
51
|
await fs.rm(filePath);
|
|
52
52
|
}
|
|
53
|
-
async function compressVideo(filePath
|
|
54
|
-
await
|
|
53
|
+
async function compressVideo(filePath) {
|
|
54
|
+
await ffmpeg_video_to_webm(filePath, replaceFilenameExtension(filePath, "webm"));
|
|
55
55
|
await fs.rm(filePath);
|
|
56
56
|
}
|
|
57
57
|
//# sourceMappingURL=action-compress.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"action-compress.js","sourceRoot":"","sources":["../../src/actions/action-compress.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,aAAa,CAAC;AAC7B,OAAO,IAAI,MAAM,MAAM,CAAC;AAIxB,OAAO,EAKL,cAAc,EAGd,wBAAwB,GACzB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,kBAAkB,EAClB,oBAAoB,EACpB,
|
|
1
|
+
{"version":3,"file":"action-compress.js","sourceRoot":"","sources":["../../src/actions/action-compress.ts"],"names":[],"mappings":"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"}
|
package/bin/lib/bash.js
CHANGED
|
@@ -27,9 +27,6 @@ export async function check_dependencies(dependencies = globalDependencies) {
|
|
|
27
27
|
}
|
|
28
28
|
// Cache para não termos que detectar a GPU toda vez que formos comprimir um vídeo
|
|
29
29
|
let cachedGpuType = null;
|
|
30
|
-
/**
|
|
31
|
-
* Detecta a GPU instalada na máquina rodando comandos nativos do SO.
|
|
32
|
-
*/
|
|
33
30
|
async function detectGPU() {
|
|
34
31
|
if (cachedGpuType)
|
|
35
32
|
return cachedGpuType;
|
|
@@ -60,47 +57,144 @@ async function detectGPU() {
|
|
|
60
57
|
}
|
|
61
58
|
return cachedGpuType;
|
|
62
59
|
}
|
|
63
|
-
export async function
|
|
64
|
-
const resolutionMapping = {
|
|
65
|
-
"4320p": { w: 7680, h: 4320 }, // 8K
|
|
66
|
-
"2160p": { w: 3840, h: 2160 }, // 4K
|
|
67
|
-
"1440p": { w: 2560, h: 1440 }, // Quad HD
|
|
68
|
-
"1080p": { w: 1920, h: 1080 }, // Full HD
|
|
69
|
-
"720p": { w: 1280, h: 720 }, // HD
|
|
70
|
-
"480p": { w: 854, h: 480 }, // SD (WVGA)
|
|
71
|
-
"360p": { w: 640, h: 360 }, // nHD
|
|
72
|
-
"240p": { w: 426, h: 240 }, // WQVGA
|
|
73
|
-
};
|
|
74
|
-
const { w, h } = resolutionMapping[resolution];
|
|
60
|
+
export async function ffmpeg_video_to_webm(input, output) {
|
|
75
61
|
const gpu = await detectGPU();
|
|
76
62
|
const isLinux = os.platform() === "linux";
|
|
77
|
-
//
|
|
63
|
+
// 1. Mapeia os Encoders VP9 para usar as GPUs
|
|
78
64
|
const encoders = {
|
|
79
65
|
nvidia: "-c:v vp9_nvenc -preset p4",
|
|
80
66
|
amd: isLinux ? "-c:v vp9_vaapi" : "-c:v vp9_amf",
|
|
81
67
|
intel: isLinux ? "-c:v vp9_vaapi" : "-c:v vp9_qsv",
|
|
82
|
-
mac: "-c:v libvpx-vp9 -row-mt 1 -cpu-used 4",
|
|
68
|
+
mac: "-c:v libvpx-vp9 -row-mt 1 -cpu-used 4", // Fallback (Mac não expõe VP9 nativo no FFmpeg)
|
|
83
69
|
cpu: "-c:v libvpx-vp9 -row-mt 1 -cpu-used 4",
|
|
84
70
|
};
|
|
85
71
|
const vcodec = encoders[gpu] || encoders.cpu;
|
|
86
|
-
let hwaccel =
|
|
72
|
+
let hwaccel = "";
|
|
87
73
|
let videoFilter = "";
|
|
74
|
+
// 2. Lógica VA-API (Linux) para manter todo o fluxo de frames na GPU
|
|
88
75
|
if (isLinux && (gpu === "amd" || gpu === "intel")) {
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
76
|
+
// Estas flags transferem a decodificação para a GPU e mantêm os frames na memória de vídeo
|
|
77
|
+
hwaccel =
|
|
78
|
+
"-hwaccel vaapi -hwaccel_device /dev/dri/renderD128 -hwaccel_output_format vaapi";
|
|
79
|
+
// Como não vamos mudar a resolução, o filtro apenas formata e sobe para a GPU caso o input não venha em formato compatível
|
|
80
|
+
videoFilter = `-vf "format=nv12,hwupload"`;
|
|
93
81
|
}
|
|
94
|
-
else {
|
|
95
|
-
|
|
82
|
+
else if (gpu === "nvidia" || gpu === "amd" || gpu === "intel") {
|
|
83
|
+
hwaccel = "-hwaccel auto";
|
|
96
84
|
}
|
|
97
|
-
//
|
|
85
|
+
// 3. Áudio para WebM
|
|
98
86
|
const acodec = "-c:a libopus -b:a 128k";
|
|
99
|
-
//
|
|
100
|
-
const command = `ffmpeg ${hwaccel} -i "${input}" ${videoFilter} ${vcodec} ${acodec} -f webm -y "${output}"`;
|
|
87
|
+
// 4. Monta o comando (removido o -s e -filter:v de redimensionamento)
|
|
88
|
+
const command = `ffmpeg ${hwaccel} -i "${input}" ${videoFilter ? videoFilter : ""} ${vcodec} ${acodec} -f webm -y "${output}"`;
|
|
89
|
+
console.log(`Compressing video [${gpu}]:`, input);
|
|
101
90
|
return execAsync(command);
|
|
102
91
|
}
|
|
92
|
+
// /**
|
|
93
|
+
// * Detecta a GPU instalada na máquina rodando comandos nativos do SO.
|
|
94
|
+
// */
|
|
95
|
+
// async function detectGPU(): Promise<GpuType> {
|
|
96
|
+
// if (cachedGpuType) return cachedGpuType;
|
|
97
|
+
// const platform = os.platform();
|
|
98
|
+
// try {
|
|
99
|
+
// if (platform === "darwin") return (cachedGpuType = "mac");
|
|
100
|
+
// let output = "";
|
|
101
|
+
// if (platform === "win32") {
|
|
102
|
+
// const stdout = await execAsync(
|
|
103
|
+
// "wmic path win32_VideoController get name",
|
|
104
|
+
// );
|
|
105
|
+
// output = stdout.toLowerCase();
|
|
106
|
+
// } else if (platform === "linux") {
|
|
107
|
+
// const stdout = await execAsync("lspci");
|
|
108
|
+
// output = stdout.toLowerCase();
|
|
109
|
+
// }
|
|
110
|
+
// if (output.includes("nvidia")) cachedGpuType = "nvidia";
|
|
111
|
+
// else if (output.includes("amd") || output.includes("radeon"))
|
|
112
|
+
// cachedGpuType = "amd";
|
|
113
|
+
// else if (output.includes("intel")) cachedGpuType = "intel";
|
|
114
|
+
// else cachedGpuType = "cpu";
|
|
115
|
+
// } catch (error) {
|
|
116
|
+
// cachedGpuType = "cpu";
|
|
117
|
+
// }
|
|
118
|
+
// return cachedGpuType;
|
|
119
|
+
// }
|
|
120
|
+
// export async function ffmpeg_video_compress_webm(
|
|
121
|
+
// input: string,
|
|
122
|
+
// output: string,
|
|
123
|
+
// resolution: Resolution = "480p",
|
|
124
|
+
// forceResolution?: boolean,
|
|
125
|
+
// ) {
|
|
126
|
+
// const { w, h } = resolutionMapping[resolution];
|
|
127
|
+
// const gpu = await detectGPU();
|
|
128
|
+
// const isLinux = os.platform() === "linux";
|
|
129
|
+
// // 1. Mapeia os Encoders para o codec VP9
|
|
130
|
+
// const encoders = {
|
|
131
|
+
// nvidia: "-c:v vp9_nvenc -preset p4",
|
|
132
|
+
// // Removemos o vp9_vaapi da AMD no Linux, caindo para a CPU (libvpx-vp9)
|
|
133
|
+
// amd: isLinux ? "-c:v libvpx-vp9 -row-mt 1 -cpu-used 4" : "-c:v vp9_amf",
|
|
134
|
+
// intel: isLinux ? "-c:v vp9_vaapi" : "-c:v vp9_qsv", // Intel costuma suportar melhor vp9_vaapi, mas pode dar o mesmo erro dependendo da geração
|
|
135
|
+
// mac: "-c:v libvpx-vp9 -row-mt 1 -cpu-used 4",
|
|
136
|
+
// cpu: "-c:v libvpx-vp9 -row-mt 1 -cpu-used 4",
|
|
137
|
+
// };
|
|
138
|
+
// const vcodec = encoders[gpu] || encoders.cpu;
|
|
139
|
+
// // 2. Só ativamos o hwaccel se NÃO formos usar a CPU (libvpx-vp9)
|
|
140
|
+
// // Como a AMD no Linux agora usa libvpx-vp9, ela entra na regra de desativar o hwaccel para encode
|
|
141
|
+
// const isUsingCpuEncoder = vcodec.includes("libvpx");
|
|
142
|
+
// let hwaccel = isUsingCpuEncoder ? "" : "-hwaccel auto";
|
|
143
|
+
// let videoFilter = "";
|
|
144
|
+
// // 3. Lógica específica VA-API (agora só ativada se a Intel for usar hardware)
|
|
145
|
+
// if (isLinux && !isUsingCpuEncoder && gpu === "intel") {
|
|
146
|
+
// hwaccel = "-vaapi_device /dev/dri/renderD128";
|
|
147
|
+
// videoFilter = forceResolution
|
|
148
|
+
// ? `-vf "scale=${w}:${h},format=nv12,hwupload"`
|
|
149
|
+
// : `-vf "scale=-1:${h},format=nv12,hwupload"`;
|
|
150
|
+
// } else {
|
|
151
|
+
// // Escala normal via CPU (necessária para o libvpx-vp9)
|
|
152
|
+
// videoFilter = forceResolution ? `-s ${w}x${h}` : `-filter:v scale=-1:${h}`;
|
|
153
|
+
// }
|
|
154
|
+
// // O vídeo WebM necessita de codecs de áudio específicos como o Opus
|
|
155
|
+
// const acodec = "-c:a libopus -b:a 128k";
|
|
156
|
+
// // A flag '-f webm' força explicitamente a criação de um contentor de vídeo WebM
|
|
157
|
+
// const command = `ffmpeg ${hwaccel} -i "${input}" ${videoFilter} ${vcodec} ${acodec} -f webm -y "${output}"`;
|
|
158
|
+
// return execAsync(command);
|
|
159
|
+
// }
|
|
160
|
+
// export async function ffmpeg_video_compress_mp4(
|
|
161
|
+
// input: string,
|
|
162
|
+
// output: string, // Certifique-se de que o arquivo termina com .mp4
|
|
163
|
+
// resolution: Resolution = "480p",
|
|
164
|
+
// forceResolution?: boolean,
|
|
165
|
+
// ) {
|
|
166
|
+
// const { w, h } = resolutionMapping[resolution];
|
|
167
|
+
// const gpu = await detectGPU();
|
|
168
|
+
// const isLinux = os.platform() === "linux";
|
|
169
|
+
// // 1. Mapeia os Encoders para H.264 (Suporte quase universal em GPUs)
|
|
170
|
+
// const encoders = {
|
|
171
|
+
// nvidia: "-c:v h264_nvenc -preset p4",
|
|
172
|
+
// amd: isLinux ? "-c:v h264_vaapi" : "-c:v h264_amf",
|
|
173
|
+
// intel: isLinux ? "-c:v h264_vaapi" : "-c:v h264_qsv",
|
|
174
|
+
// mac: "-c:v h264_videotoolbox",
|
|
175
|
+
// cpu: "-c:v libx264 -preset fast",
|
|
176
|
+
// };
|
|
177
|
+
// const vcodec = encoders[gpu] || encoders.cpu;
|
|
178
|
+
// let hwaccel = gpu === "cpu" ? "" : "-hwaccel auto";
|
|
179
|
+
// let videoFilter = "";
|
|
180
|
+
// // 2. Lógica VA-API para AMD/Intel no Linux
|
|
181
|
+
// if (isLinux && (gpu === "amd" || gpu === "intel")) {
|
|
182
|
+
// hwaccel = "-vaapi_device /dev/dri/renderD128";
|
|
183
|
+
// // O VA-API precisa que os frames subam para a GPU no formato NV12
|
|
184
|
+
// videoFilter = forceResolution
|
|
185
|
+
// ? `-vf "scale=${w}:${h},format=nv12,hwupload"`
|
|
186
|
+
// : `-vf "scale=-1:${h},format=nv12,hwupload"`;
|
|
187
|
+
// } else {
|
|
188
|
+
// videoFilter = forceResolution ? `-s ${w}x${h}` : `-filter:v scale=-1:${h}`;
|
|
189
|
+
// }
|
|
190
|
+
// // 3. Áudio padrão para MP4 (AAC) para evitar problemas de compatibilidade
|
|
191
|
+
// const acodec = "-c:a aac -b:a 128k";
|
|
192
|
+
// // 4. Monta e executa o comando forçando o container MP4
|
|
193
|
+
// const command = `ffmpeg ${hwaccel} -i "${input}" ${videoFilter} ${vcodec} ${acodec} -f mp4 -y "${output}"`;
|
|
194
|
+
// return execAsync(command);
|
|
195
|
+
// }
|
|
103
196
|
export async function ffmpeg_image_to_webp(input, output) {
|
|
197
|
+
console.log(`Compressing image:`, input);
|
|
104
198
|
return execAsync(`ffmpeg -i "${input}" -c:v libwebp "${output}"`);
|
|
105
199
|
}
|
|
106
200
|
//# sourceMappingURL=bash.js.map
|
package/bin/lib/bash.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bash.js","sourceRoot":"","sources":["../../src/lib/bash.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAErC,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAE3C,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AAEzB,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,OAAe,EAAmB,EAAE,CAC5D,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;IAC9B,IAAI,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE;QACtC,IAAI,KAAK;YAAE,MAAM,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;;YAChC,OAAO,CAAC,MAAM,CAAC,CAAC;IACvB,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEL,MAAM,kBAAkB,GAAG,CAAC,QAAQ,CAAC,CAAC;AAEtC,KAAK,UAAU,gBAAgB,CAAC,UAAkB;IAChD,OAAO,SAAS,CAAC,GAAG,UAAU,KAAK,CAAC;SACjC,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC;SAChB,KAAK,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,CAAC;AACxB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,YAAY,GAAG,kBAAkB;IACxE,MAAM,oBAAoB,GAAG,EAAE,CAAC;IAEhC,KAAK,IAAI,GAAG,IAAI,YAAY,EAAE,CAAC;QAC7B,IAAI,CAAC,CAAC,MAAM,gBAAgB,CAAC,GAAG,CAAC,CAAC;YAAE,oBAAoB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACrE,CAAC;IAED,IAAI,oBAAoB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACpC,MAAM,IAAI,cAAc,CACtB,CAAC,EACD,sBAAsB,EACtB,oBAAoB,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,GAAG,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CACzD,CAAC;IACJ,CAAC;AACH,CAAC;AAID,kFAAkF;AAClF,IAAI,aAAa,GAAmB,IAAI,CAAC;AAEzC
|
|
1
|
+
{"version":3,"file":"bash.js","sourceRoot":"","sources":["../../src/lib/bash.ts"],"names":[],"mappings":"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"}
|
package/bin/lib/constants.js
CHANGED
|
@@ -1,36 +1,12 @@
|
|
|
1
1
|
export const resolutionMapping = {
|
|
2
|
-
"4320p": {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
},
|
|
6
|
-
"
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
},
|
|
10
|
-
"1440p": {
|
|
11
|
-
w: 2560,
|
|
12
|
-
h: 1440,
|
|
13
|
-
},
|
|
14
|
-
"1080p": {
|
|
15
|
-
w: 1920,
|
|
16
|
-
h: 1080,
|
|
17
|
-
},
|
|
18
|
-
"720p": {
|
|
19
|
-
w: 1280,
|
|
20
|
-
h: 720,
|
|
21
|
-
},
|
|
22
|
-
"480p": {
|
|
23
|
-
w: 854,
|
|
24
|
-
h: 480,
|
|
25
|
-
},
|
|
26
|
-
"360p": {
|
|
27
|
-
w: 640,
|
|
28
|
-
h: 360,
|
|
29
|
-
},
|
|
30
|
-
"240p": {
|
|
31
|
-
w: 426,
|
|
32
|
-
h: 240,
|
|
33
|
-
},
|
|
2
|
+
"4320p": { w: 7680, h: 4320 }, // 8K
|
|
3
|
+
"2160p": { w: 3840, h: 2160 }, // 4K
|
|
4
|
+
"1440p": { w: 2560, h: 1440 }, // Quad HD
|
|
5
|
+
"1080p": { w: 1920, h: 1080 }, // Full HD
|
|
6
|
+
"720p": { w: 1280, h: 720 }, // HD
|
|
7
|
+
"480p": { w: 854, h: 480 }, // SD (WVGA)
|
|
8
|
+
"360p": { w: 640, h: 360 }, // nHD
|
|
9
|
+
"240p": { w: 426, h: 240 }, // WQVGA
|
|
34
10
|
};
|
|
35
11
|
export const Resolution = [
|
|
36
12
|
"4320p",
|
package/bin/lib/constants.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/lib/constants.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,iBAAiB,
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/lib/constants.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,iBAAiB,GAE1B;IACF,OAAO,EAAE,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE,KAAK;IACpC,OAAO,EAAE,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE,KAAK;IACpC,OAAO,EAAE,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE,UAAU;IACzC,OAAO,EAAE,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE,UAAU;IACzC,MAAM,EAAE,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,GAAG,EAAE,EAAE,KAAK;IAClC,MAAM,EAAE,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,EAAE,YAAY;IACxC,MAAM,EAAE,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,EAAE,MAAM;IAClC,MAAM,EAAE,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,EAAE,QAAQ;CACrC,CAAC;AAEF,MAAM,CAAC,MAAM,UAAU,GAAG;IACxB,OAAO;IACP,OAAO;IACP,OAAO;IACP,OAAO;IACP,MAAM;IACN,MAAM;IACN,MAAM;IACN,MAAM;CACE,CAAC"}
|
package/package.json
CHANGED
|
@@ -17,7 +17,7 @@ import {
|
|
|
17
17
|
import {
|
|
18
18
|
check_dependencies,
|
|
19
19
|
ffmpeg_image_to_webp,
|
|
20
|
-
|
|
20
|
+
ffmpeg_video_to_webm,
|
|
21
21
|
} from "../lib/bash.js";
|
|
22
22
|
|
|
23
23
|
export const FileType = ["image", "video"] as const;
|
|
@@ -48,7 +48,7 @@ export async function file(
|
|
|
48
48
|
if (force) console.warn("⚠️ Ignoring already compressed files");
|
|
49
49
|
if (horizontal) console.warn("⚠️ Forcing horizontal aspect ratio 16x9");
|
|
50
50
|
|
|
51
|
-
let verbose_title = "";
|
|
51
|
+
// let verbose_title = "";
|
|
52
52
|
|
|
53
53
|
const filePathList = await getFolderFiles(pathname, true);
|
|
54
54
|
|
|
@@ -68,15 +68,14 @@ export async function file(
|
|
|
68
68
|
.slice(1, 1 + verbose)
|
|
69
69
|
.join("/");
|
|
70
70
|
|
|
71
|
-
if (title !== verbose_title)
|
|
72
|
-
|
|
71
|
+
// if (title !== verbose_title)
|
|
72
|
+
// console.log(`Compressing ${fileType} at:`, title);
|
|
73
73
|
|
|
74
|
-
verbose_title = title;
|
|
74
|
+
// verbose_title = title;
|
|
75
75
|
|
|
76
76
|
try {
|
|
77
77
|
if (fileType === "image") await compressImage(filePath);
|
|
78
|
-
else if (fileType === "video")
|
|
79
|
-
await compressVideo(filePath, resolution, horizontal);
|
|
78
|
+
else if (fileType === "video") await compressVideo(filePath);
|
|
80
79
|
} catch (err) {
|
|
81
80
|
if (verbose > 10) console.error(" Error compressing", err);
|
|
82
81
|
else console.error(" Error compressing", `"${filePath}"`);
|
|
@@ -94,16 +93,10 @@ async function compressImage(filePath: string) {
|
|
|
94
93
|
await fs.rm(filePath);
|
|
95
94
|
}
|
|
96
95
|
|
|
97
|
-
async function compressVideo(
|
|
98
|
-
|
|
99
|
-
resolution: Resolution,
|
|
100
|
-
force?: boolean,
|
|
101
|
-
) {
|
|
102
|
-
await ffmpeg_video_compress_webm(
|
|
96
|
+
async function compressVideo(filePath: string) {
|
|
97
|
+
await ffmpeg_video_to_webm(
|
|
103
98
|
filePath,
|
|
104
99
|
replaceFilenameExtension(filePath, "webm"),
|
|
105
|
-
resolution,
|
|
106
|
-
force,
|
|
107
100
|
);
|
|
108
101
|
await fs.rm(filePath);
|
|
109
102
|
}
|
package/src/lib/bash.ts
CHANGED
|
@@ -41,9 +41,6 @@ type GpuType = "nvidia" | "amd" | "intel" | "mac" | "cpu";
|
|
|
41
41
|
// Cache para não termos que detectar a GPU toda vez que formos comprimir um vídeo
|
|
42
42
|
let cachedGpuType: GpuType | null = null;
|
|
43
43
|
|
|
44
|
-
/**
|
|
45
|
-
* Detecta a GPU instalada na máquina rodando comandos nativos do SO.
|
|
46
|
-
*/
|
|
47
44
|
async function detectGPU(): Promise<GpuType> {
|
|
48
45
|
if (cachedGpuType) return cachedGpuType;
|
|
49
46
|
const platform = os.platform();
|
|
@@ -73,59 +70,174 @@ async function detectGPU(): Promise<GpuType> {
|
|
|
73
70
|
return cachedGpuType;
|
|
74
71
|
}
|
|
75
72
|
|
|
76
|
-
export async function
|
|
73
|
+
export async function ffmpeg_video_to_webm(
|
|
77
74
|
input: string,
|
|
78
|
-
output: string,
|
|
79
|
-
resolution: Resolution = "480p",
|
|
80
|
-
forceResolution?: boolean,
|
|
75
|
+
output: string, // O arquivo deve terminar em .webm
|
|
81
76
|
) {
|
|
82
|
-
const resolutionMapping: { [key in Resolution]: { w: number; h: number } } = {
|
|
83
|
-
"4320p": { w: 7680, h: 4320 }, // 8K
|
|
84
|
-
"2160p": { w: 3840, h: 2160 }, // 4K
|
|
85
|
-
"1440p": { w: 2560, h: 1440 }, // Quad HD
|
|
86
|
-
"1080p": { w: 1920, h: 1080 }, // Full HD
|
|
87
|
-
"720p": { w: 1280, h: 720 }, // HD
|
|
88
|
-
"480p": { w: 854, h: 480 }, // SD (WVGA)
|
|
89
|
-
"360p": { w: 640, h: 360 }, // nHD
|
|
90
|
-
"240p": { w: 426, h: 240 }, // WQVGA
|
|
91
|
-
};
|
|
92
|
-
|
|
93
|
-
const { w, h } = resolutionMapping[resolution];
|
|
94
77
|
const gpu = await detectGPU();
|
|
95
78
|
const isLinux = os.platform() === "linux";
|
|
96
79
|
|
|
97
|
-
//
|
|
80
|
+
// 1. Mapeia os Encoders VP9 para usar as GPUs
|
|
98
81
|
const encoders = {
|
|
99
82
|
nvidia: "-c:v vp9_nvenc -preset p4",
|
|
100
83
|
amd: isLinux ? "-c:v vp9_vaapi" : "-c:v vp9_amf",
|
|
101
84
|
intel: isLinux ? "-c:v vp9_vaapi" : "-c:v vp9_qsv",
|
|
102
|
-
mac: "-c:v libvpx-vp9 -row-mt 1 -cpu-used 4",
|
|
85
|
+
mac: "-c:v libvpx-vp9 -row-mt 1 -cpu-used 4", // Fallback (Mac não expõe VP9 nativo no FFmpeg)
|
|
103
86
|
cpu: "-c:v libvpx-vp9 -row-mt 1 -cpu-used 4",
|
|
104
87
|
};
|
|
105
88
|
|
|
106
89
|
const vcodec = encoders[gpu] || encoders.cpu;
|
|
107
90
|
|
|
108
|
-
let hwaccel =
|
|
91
|
+
let hwaccel = "";
|
|
109
92
|
let videoFilter = "";
|
|
110
93
|
|
|
94
|
+
// 2. Lógica VA-API (Linux) para manter todo o fluxo de frames na GPU
|
|
111
95
|
if (isLinux && (gpu === "amd" || gpu === "intel")) {
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
96
|
+
// Estas flags transferem a decodificação para a GPU e mantêm os frames na memória de vídeo
|
|
97
|
+
hwaccel =
|
|
98
|
+
"-hwaccel vaapi -hwaccel_device /dev/dri/renderD128 -hwaccel_output_format vaapi";
|
|
99
|
+
// Como não vamos mudar a resolução, o filtro apenas formata e sobe para a GPU caso o input não venha em formato compatível
|
|
100
|
+
videoFilter = `-vf "format=nv12,hwupload"`;
|
|
101
|
+
} else if (gpu === "nvidia" || gpu === "amd" || gpu === "intel") {
|
|
102
|
+
hwaccel = "-hwaccel auto";
|
|
118
103
|
}
|
|
119
104
|
|
|
120
|
-
//
|
|
105
|
+
// 3. Áudio para WebM
|
|
121
106
|
const acodec = "-c:a libopus -b:a 128k";
|
|
122
107
|
|
|
123
|
-
//
|
|
124
|
-
const command = `ffmpeg ${hwaccel} -i "${input}" ${videoFilter} ${vcodec} ${acodec} -f webm -y "${output}"`;
|
|
108
|
+
// 4. Monta o comando (removido o -s e -filter:v de redimensionamento)
|
|
109
|
+
const command = `ffmpeg ${hwaccel} -i "${input}" ${videoFilter ? videoFilter : ""} ${vcodec} ${acodec} -f webm -y "${output}"`;
|
|
110
|
+
|
|
111
|
+
console.log(`Compressing video [${gpu}]:`, input);
|
|
125
112
|
|
|
126
113
|
return execAsync(command);
|
|
127
114
|
}
|
|
128
115
|
|
|
116
|
+
// /**
|
|
117
|
+
// * Detecta a GPU instalada na máquina rodando comandos nativos do SO.
|
|
118
|
+
// */
|
|
119
|
+
// async function detectGPU(): Promise<GpuType> {
|
|
120
|
+
// if (cachedGpuType) return cachedGpuType;
|
|
121
|
+
// const platform = os.platform();
|
|
122
|
+
|
|
123
|
+
// try {
|
|
124
|
+
// if (platform === "darwin") return (cachedGpuType = "mac");
|
|
125
|
+
|
|
126
|
+
// let output = "";
|
|
127
|
+
// if (platform === "win32") {
|
|
128
|
+
// const stdout = await execAsync(
|
|
129
|
+
// "wmic path win32_VideoController get name",
|
|
130
|
+
// );
|
|
131
|
+
// output = stdout.toLowerCase();
|
|
132
|
+
// } else if (platform === "linux") {
|
|
133
|
+
// const stdout = await execAsync("lspci");
|
|
134
|
+
// output = stdout.toLowerCase();
|
|
135
|
+
// }
|
|
136
|
+
|
|
137
|
+
// if (output.includes("nvidia")) cachedGpuType = "nvidia";
|
|
138
|
+
// else if (output.includes("amd") || output.includes("radeon"))
|
|
139
|
+
// cachedGpuType = "amd";
|
|
140
|
+
// else if (output.includes("intel")) cachedGpuType = "intel";
|
|
141
|
+
// else cachedGpuType = "cpu";
|
|
142
|
+
// } catch (error) {
|
|
143
|
+
// cachedGpuType = "cpu";
|
|
144
|
+
// }
|
|
145
|
+
// return cachedGpuType;
|
|
146
|
+
// }
|
|
147
|
+
|
|
148
|
+
// export async function ffmpeg_video_compress_webm(
|
|
149
|
+
// input: string,
|
|
150
|
+
// output: string,
|
|
151
|
+
// resolution: Resolution = "480p",
|
|
152
|
+
// forceResolution?: boolean,
|
|
153
|
+
// ) {
|
|
154
|
+
// const { w, h } = resolutionMapping[resolution];
|
|
155
|
+
// const gpu = await detectGPU();
|
|
156
|
+
// const isLinux = os.platform() === "linux";
|
|
157
|
+
|
|
158
|
+
// // 1. Mapeia os Encoders para o codec VP9
|
|
159
|
+
// const encoders = {
|
|
160
|
+
// nvidia: "-c:v vp9_nvenc -preset p4",
|
|
161
|
+
// // Removemos o vp9_vaapi da AMD no Linux, caindo para a CPU (libvpx-vp9)
|
|
162
|
+
// amd: isLinux ? "-c:v libvpx-vp9 -row-mt 1 -cpu-used 4" : "-c:v vp9_amf",
|
|
163
|
+
// intel: isLinux ? "-c:v vp9_vaapi" : "-c:v vp9_qsv", // Intel costuma suportar melhor vp9_vaapi, mas pode dar o mesmo erro dependendo da geração
|
|
164
|
+
// mac: "-c:v libvpx-vp9 -row-mt 1 -cpu-used 4",
|
|
165
|
+
// cpu: "-c:v libvpx-vp9 -row-mt 1 -cpu-used 4",
|
|
166
|
+
// };
|
|
167
|
+
|
|
168
|
+
// const vcodec = encoders[gpu] || encoders.cpu;
|
|
169
|
+
|
|
170
|
+
// // 2. Só ativamos o hwaccel se NÃO formos usar a CPU (libvpx-vp9)
|
|
171
|
+
// // Como a AMD no Linux agora usa libvpx-vp9, ela entra na regra de desativar o hwaccel para encode
|
|
172
|
+
// const isUsingCpuEncoder = vcodec.includes("libvpx");
|
|
173
|
+
// let hwaccel = isUsingCpuEncoder ? "" : "-hwaccel auto";
|
|
174
|
+
// let videoFilter = "";
|
|
175
|
+
|
|
176
|
+
// // 3. Lógica específica VA-API (agora só ativada se a Intel for usar hardware)
|
|
177
|
+
// if (isLinux && !isUsingCpuEncoder && gpu === "intel") {
|
|
178
|
+
// hwaccel = "-vaapi_device /dev/dri/renderD128";
|
|
179
|
+
// videoFilter = forceResolution
|
|
180
|
+
// ? `-vf "scale=${w}:${h},format=nv12,hwupload"`
|
|
181
|
+
// : `-vf "scale=-1:${h},format=nv12,hwupload"`;
|
|
182
|
+
// } else {
|
|
183
|
+
// // Escala normal via CPU (necessária para o libvpx-vp9)
|
|
184
|
+
// videoFilter = forceResolution ? `-s ${w}x${h}` : `-filter:v scale=-1:${h}`;
|
|
185
|
+
// }
|
|
186
|
+
|
|
187
|
+
// // O vídeo WebM necessita de codecs de áudio específicos como o Opus
|
|
188
|
+
// const acodec = "-c:a libopus -b:a 128k";
|
|
189
|
+
|
|
190
|
+
// // A flag '-f webm' força explicitamente a criação de um contentor de vídeo WebM
|
|
191
|
+
// const command = `ffmpeg ${hwaccel} -i "${input}" ${videoFilter} ${vcodec} ${acodec} -f webm -y "${output}"`;
|
|
192
|
+
|
|
193
|
+
// return execAsync(command);
|
|
194
|
+
// }
|
|
195
|
+
|
|
196
|
+
// export async function ffmpeg_video_compress_mp4(
|
|
197
|
+
// input: string,
|
|
198
|
+
// output: string, // Certifique-se de que o arquivo termina com .mp4
|
|
199
|
+
// resolution: Resolution = "480p",
|
|
200
|
+
// forceResolution?: boolean,
|
|
201
|
+
// ) {
|
|
202
|
+
// const { w, h } = resolutionMapping[resolution];
|
|
203
|
+
// const gpu = await detectGPU();
|
|
204
|
+
// const isLinux = os.platform() === "linux";
|
|
205
|
+
|
|
206
|
+
// // 1. Mapeia os Encoders para H.264 (Suporte quase universal em GPUs)
|
|
207
|
+
// const encoders = {
|
|
208
|
+
// nvidia: "-c:v h264_nvenc -preset p4",
|
|
209
|
+
// amd: isLinux ? "-c:v h264_vaapi" : "-c:v h264_amf",
|
|
210
|
+
// intel: isLinux ? "-c:v h264_vaapi" : "-c:v h264_qsv",
|
|
211
|
+
// mac: "-c:v h264_videotoolbox",
|
|
212
|
+
// cpu: "-c:v libx264 -preset fast",
|
|
213
|
+
// };
|
|
214
|
+
|
|
215
|
+
// const vcodec = encoders[gpu] || encoders.cpu;
|
|
216
|
+
|
|
217
|
+
// let hwaccel = gpu === "cpu" ? "" : "-hwaccel auto";
|
|
218
|
+
// let videoFilter = "";
|
|
219
|
+
|
|
220
|
+
// // 2. Lógica VA-API para AMD/Intel no Linux
|
|
221
|
+
// if (isLinux && (gpu === "amd" || gpu === "intel")) {
|
|
222
|
+
// hwaccel = "-vaapi_device /dev/dri/renderD128";
|
|
223
|
+
// // O VA-API precisa que os frames subam para a GPU no formato NV12
|
|
224
|
+
// videoFilter = forceResolution
|
|
225
|
+
// ? `-vf "scale=${w}:${h},format=nv12,hwupload"`
|
|
226
|
+
// : `-vf "scale=-1:${h},format=nv12,hwupload"`;
|
|
227
|
+
// } else {
|
|
228
|
+
// videoFilter = forceResolution ? `-s ${w}x${h}` : `-filter:v scale=-1:${h}`;
|
|
229
|
+
// }
|
|
230
|
+
|
|
231
|
+
// // 3. Áudio padrão para MP4 (AAC) para evitar problemas de compatibilidade
|
|
232
|
+
// const acodec = "-c:a aac -b:a 128k";
|
|
233
|
+
|
|
234
|
+
// // 4. Monta e executa o comando forçando o container MP4
|
|
235
|
+
// const command = `ffmpeg ${hwaccel} -i "${input}" ${videoFilter} ${vcodec} ${acodec} -f mp4 -y "${output}"`;
|
|
236
|
+
|
|
237
|
+
// return execAsync(command);
|
|
238
|
+
// }
|
|
239
|
+
|
|
129
240
|
export async function ffmpeg_image_to_webp(input: string, output: string) {
|
|
241
|
+
console.log(`Compressing image:`, input);
|
|
130
242
|
return execAsync(`ffmpeg -i "${input}" -c:v libwebp "${output}"`);
|
|
131
243
|
}
|
package/src/lib/constants.ts
CHANGED
|
@@ -1,37 +1,15 @@
|
|
|
1
|
-
export const resolutionMapping
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
},
|
|
6
|
-
"
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
},
|
|
10
|
-
"
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
},
|
|
14
|
-
"1080p": {
|
|
15
|
-
w: 1920,
|
|
16
|
-
h: 1080,
|
|
17
|
-
},
|
|
18
|
-
"720p": {
|
|
19
|
-
w: 1280,
|
|
20
|
-
h: 720,
|
|
21
|
-
},
|
|
22
|
-
"480p": {
|
|
23
|
-
w: 854,
|
|
24
|
-
h: 480,
|
|
25
|
-
},
|
|
26
|
-
"360p": {
|
|
27
|
-
w: 640,
|
|
28
|
-
h: 360,
|
|
29
|
-
},
|
|
30
|
-
"240p": {
|
|
31
|
-
w: 426,
|
|
32
|
-
h: 240,
|
|
33
|
-
},
|
|
34
|
-
} as const;
|
|
1
|
+
export const resolutionMapping: {
|
|
2
|
+
[key in Resolution]: { w: number; h: number };
|
|
3
|
+
} = {
|
|
4
|
+
"4320p": { w: 7680, h: 4320 }, // 8K
|
|
5
|
+
"2160p": { w: 3840, h: 2160 }, // 4K
|
|
6
|
+
"1440p": { w: 2560, h: 1440 }, // Quad HD
|
|
7
|
+
"1080p": { w: 1920, h: 1080 }, // Full HD
|
|
8
|
+
"720p": { w: 1280, h: 720 }, // HD
|
|
9
|
+
"480p": { w: 854, h: 480 }, // SD (WVGA)
|
|
10
|
+
"360p": { w: 640, h: 360 }, // nHD
|
|
11
|
+
"240p": { w: 426, h: 240 }, // WQVGA
|
|
12
|
+
};
|
|
35
13
|
|
|
36
14
|
export const Resolution = [
|
|
37
15
|
"4320p",
|
|
@@ -43,5 +21,4 @@ export const Resolution = [
|
|
|
43
21
|
"360p",
|
|
44
22
|
"240p",
|
|
45
23
|
] as const;
|
|
46
|
-
|
|
47
24
|
export type Resolution = (typeof Resolution)[number];
|