@boruto_vk7/stickengine 0.0.4 → 0.0.6
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 +83 -74
- package/dist/StickEngine.d.ts +20 -1
- package/dist/StickEngine.js +140 -26
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,121 +1,130 @@
|
|
|
1
1
|
# 🚀 StickEngine
|
|
2
2
|
|
|
3
|
-
**StickEngine** é um motor
|
|
4
|
-
|
|
5
|
-
[](https://www.npmjs.com/package/@boruto_vk7/stickengine)
|
|
6
|
-
[](https://github.com/Borutovk7/StickEngine)
|
|
7
|
-
|
|
8
|
-
---
|
|
9
|
-
|
|
10
|
-
## ✨ Funcionalidades
|
|
11
|
-
|
|
12
|
-
- 🎞️ **Figurinhas Animadas**: Suporte automático para GIFs e Vídeos (MP4).
|
|
13
|
-
- 🎨 **Filtros Profissionais**: Sépia, Tons de Cinza, Inversão e Desfoque (Blur).
|
|
14
|
-
- ✍️ **Texto Customizado**: Adicione legendas diretamente na figurinha.
|
|
15
|
-
- ✂️ **Remoção de Fundo**: Integração com a API `remove.bg`.
|
|
16
|
-
- 🧹 **Limpeza Automática**: Sistema de gerenciamento de arquivos temporários com o método `.clean()`.
|
|
17
|
-
- 🏷️ **Metadados (Exif)**: Personalize o nome do pacote e o autor sem complicação.
|
|
18
|
-
- 📱 **Termux Friendly**: Sem dependências nativas pesadas como `sharp`.
|
|
19
|
-
|
|
20
|
-
---
|
|
21
|
-
|
|
22
|
-
## 🖼️ Exemplos Visuais
|
|
23
|
-
|
|
24
|
-
| Filtro Séia + Texto | Figurinha Animada (Mockup) |
|
|
25
|
-
| :---: | :---: |
|
|
26
|
-
|  |  |
|
|
3
|
+
O **StickEngine** é um motor de alta performance para criação de figurinhas do WhatsApp, projetado para ser simples para iniciantes e extremamente poderoso para desenvolvedores avançados.
|
|
27
4
|
|
|
28
5
|
---
|
|
29
6
|
|
|
30
|
-
## 📦
|
|
7
|
+
## 📦 1. Começando (Básico)
|
|
31
8
|
|
|
9
|
+
### Instalação
|
|
32
10
|
```bash
|
|
33
11
|
npm install @boruto_vk7/stickengine
|
|
34
12
|
```
|
|
13
|
+
> **Requisito**: Tenha o `ffmpeg` instalado no seu sistema.
|
|
35
14
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
## 🚀 Como Usar (Exemplos Técnicos)
|
|
15
|
+
### Suporte Híbrido
|
|
16
|
+
O módulo funciona tanto com **ESM** quanto **CommonJS**:
|
|
17
|
+
- **ESM**: `import StickEngine from '@boruto_vk7/stickengine';`
|
|
18
|
+
- **CJS**: `const StickEngine = require('@boruto_vk7/stickengine').default;`
|
|
41
19
|
|
|
42
|
-
###
|
|
20
|
+
### Sua Primeira Figurinha
|
|
21
|
+
Gere uma figurinha com apenas 3 linhas de código:
|
|
43
22
|
```javascript
|
|
44
|
-
import StickEngine from '@boruto_vk7/stickengine';
|
|
45
|
-
|
|
46
23
|
const engine = new StickEngine();
|
|
47
|
-
engine.addFile('
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
console.log('Caminho do WebP:', results[0].value);
|
|
51
|
-
engine.clean();
|
|
24
|
+
engine.addFile('./foto.jpg'); // Adiciona a imagem
|
|
25
|
+
const results = await engine.start(); // Inicia o processamento
|
|
26
|
+
console.log('Sticker salvo em:', results[0].value);
|
|
52
27
|
```
|
|
53
28
|
|
|
54
|
-
|
|
55
|
-
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## 🛠️ 2. Personalizando (Intermediário)
|
|
32
|
+
|
|
33
|
+
### Adicionando Nome e Autor (Metadados)
|
|
34
|
+
Personalize as informações que aparecem quando alguém clica na figurinha no WhatsApp.
|
|
56
35
|
```javascript
|
|
57
36
|
const engine = new StickEngine({
|
|
58
|
-
|
|
59
|
-
|
|
37
|
+
metadata: {
|
|
38
|
+
pack: 'Meu Pack Incrível',
|
|
39
|
+
author: 'Borutovk7'
|
|
40
|
+
}
|
|
60
41
|
});
|
|
42
|
+
```
|
|
61
43
|
|
|
44
|
+
### Figurinhas Animadas (GIF e Vídeo)
|
|
45
|
+
O motor detecta automaticamente se o arquivo é animado. Ele corta para 6 segundos e garante que o arquivo tenha menos de 1MB.
|
|
46
|
+
```javascript
|
|
62
47
|
engine.addFile('./video_engracado.mp4');
|
|
48
|
+
engine.addFile('./dancinha.gif');
|
|
63
49
|
await engine.start();
|
|
64
|
-
engine.clean();
|
|
65
50
|
```
|
|
66
51
|
|
|
67
|
-
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## 🎨 3. Efeitos Especiais (Avançado)
|
|
55
|
+
|
|
56
|
+
### Recorte Circular e Filtros
|
|
57
|
+
Transforme imagens quadradas em círculos e aplique filtros profissionais.
|
|
58
|
+
```javascript
|
|
59
|
+
const engine = new StickEngine({
|
|
60
|
+
edit: {
|
|
61
|
+
circle: true, // Recorte circular
|
|
62
|
+
sepia: true, // Filtro antigo
|
|
63
|
+
brightness: 0.2 // Aumenta o brilho
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### Legendas com Borda (Meme Style)
|
|
69
|
+
Adicione texto que pode ser lido em qualquer fundo graças ao contorno (stroke).
|
|
68
70
|
```javascript
|
|
69
71
|
const engine = new StickEngine({
|
|
70
72
|
edit: {
|
|
71
|
-
sepia: true,
|
|
72
|
-
blur: 5,
|
|
73
73
|
text: {
|
|
74
|
-
content: '
|
|
75
|
-
|
|
74
|
+
content: 'QUEBRADO!',
|
|
75
|
+
color: 'WHITE',
|
|
76
|
+
stroke: true // Adiciona borda preta ao texto branco
|
|
76
77
|
}
|
|
77
78
|
}
|
|
78
79
|
});
|
|
79
|
-
|
|
80
|
-
engine.addFile(bufferDeImagem);
|
|
81
|
-
await engine.start();
|
|
82
|
-
engine.clean();
|
|
83
80
|
```
|
|
84
81
|
|
|
85
|
-
|
|
82
|
+
---
|
|
83
|
+
|
|
84
|
+
## 💎 4. Funções Profissionais (Expert)
|
|
85
|
+
|
|
86
|
+
### Texto para Figurinha (TP)
|
|
87
|
+
Gere figurinhas de frases do zero, sem precisar de uma imagem de base.
|
|
86
88
|
```javascript
|
|
87
|
-
const
|
|
88
|
-
|
|
89
|
+
const path = await engine.createTextSticker("ESSA É TOP!", {
|
|
90
|
+
color: 'WHITE',
|
|
91
|
+
background: 0x00000000 // Transparente
|
|
89
92
|
});
|
|
93
|
+
```
|
|
90
94
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
95
|
+
### Criando Ícone do Pacote (Tray Icon)
|
|
96
|
+
Gere o ícone de bandeja (96x96) necessário para pacotes oficiais.
|
|
97
|
+
```javascript
|
|
98
|
+
const trayPath = await engine.createTrayIcon('./logo.png');
|
|
94
99
|
```
|
|
95
100
|
|
|
101
|
+
### Auto-Dimensionamento Inteligente
|
|
102
|
+
O motor reduz automaticamente a qualidade e o FPS se a figurinha animada passar de 1MB, garantindo que ela sempre seja enviada com sucesso.
|
|
103
|
+
|
|
96
104
|
---
|
|
97
105
|
|
|
98
|
-
##
|
|
106
|
+
## 📑 5. Referência Técnica Completa
|
|
99
107
|
|
|
100
|
-
|
|
108
|
+
### Opções do Construtor (`StickEngineOptions`)
|
|
109
|
+
| Propriedade | Tipo | Padrão | Descrição |
|
|
101
110
|
| :--- | :--- | :--- | :--- |
|
|
102
|
-
| `metadata` | `Object` | `{ pack: 'StickEngine', author: 'Borutovk7' }` | Nome do pacote e autor. |
|
|
103
|
-
| `edit` | `Object` | `false` | Filtros (`sepia`, `greyscale`, `invert`, `blur`) e `text`. |
|
|
104
|
-
| `transparent` | `String` | `false` | Chave da API `remove.bg` para remover fundo. |
|
|
105
|
-
| `autoClean` | `Boolean` | `true` | Habilita o rastreio de arquivos para limpeza. |
|
|
106
111
|
| `quality` | `Number` | `80` | Qualidade do WebP (1-100). |
|
|
107
|
-
| `fps` | `Number` | `15` | Frames por segundo para
|
|
112
|
+
| `fps` | `Number` | `15` | Frames por segundo para animados. |
|
|
113
|
+
| `autoClean` | `Boolean` | `true` | Apaga temporários automaticamente. |
|
|
114
|
+
|
|
115
|
+
### Opções de Edição (`JimpOptions`)
|
|
116
|
+
| Opção | Descrição |
|
|
117
|
+
| :--- | :--- |
|
|
118
|
+
| `circle` | Ativa o recorte circular. |
|
|
119
|
+
| `brightness` | Ajusta o brilho (-1 a 1). |
|
|
120
|
+
| `contrast` | Ajusta o contraste (-1 a 1). |
|
|
121
|
+
| `blur` | Aplica desfoque. |
|
|
122
|
+
| `text.stroke` | Adiciona contorno ao texto. |
|
|
108
123
|
|
|
109
124
|
---
|
|
110
125
|
|
|
111
|
-
## 🤝
|
|
112
|
-
|
|
113
|
-
Contribuições são sempre bem-vindas! Sinta-se à vontade para abrir uma **Issue** ou enviar um **Pull Request**.
|
|
114
|
-
|
|
115
|
-
Desenvolvido por [Borutovk7](https://github.com/Borutovk7) e [Eduh Dev](https://github.com/EduhDev).
|
|
116
|
-
|
|
117
|
-
---
|
|
126
|
+
## 🤝 Créditos
|
|
127
|
+
Desenvolvido por **Borutovk7**.
|
|
118
128
|
|
|
119
129
|
## 📄 Licença
|
|
120
|
-
|
|
121
|
-
Este projeto está sob a licença [ISC](LICENSE).
|
|
130
|
+
ISC
|
package/dist/StickEngine.d.ts
CHANGED
|
@@ -10,6 +10,9 @@ export interface JimpOptions {
|
|
|
10
10
|
invert?: boolean;
|
|
11
11
|
sepia?: boolean;
|
|
12
12
|
blur?: number;
|
|
13
|
+
brightness?: number;
|
|
14
|
+
contrast?: number;
|
|
15
|
+
circle?: boolean;
|
|
13
16
|
resize?: {
|
|
14
17
|
width: number;
|
|
15
18
|
height: number;
|
|
@@ -18,7 +21,8 @@ export interface JimpOptions {
|
|
|
18
21
|
content: string;
|
|
19
22
|
alignmentX?: number;
|
|
20
23
|
alignmentY?: number;
|
|
21
|
-
color?:
|
|
24
|
+
color?: 'WHITE' | 'BLACK';
|
|
25
|
+
stroke?: boolean;
|
|
22
26
|
};
|
|
23
27
|
}
|
|
24
28
|
export interface StickEngineOptions {
|
|
@@ -49,5 +53,20 @@ export declare class StickEngine extends EventEmitter {
|
|
|
49
53
|
private convertToWebp;
|
|
50
54
|
private addExif;
|
|
51
55
|
start(): Promise<PromiseSettledResult<string>[]>;
|
|
56
|
+
/**
|
|
57
|
+
* Converte um arquivo em Base64.
|
|
58
|
+
*/
|
|
59
|
+
static toBase64(filePath: string): string;
|
|
60
|
+
/**
|
|
61
|
+
* Gera um ícone de bandeja (Tray Icon) 96x96 para o pacote de figurinhas.
|
|
62
|
+
*/
|
|
63
|
+
createTrayIcon(input: string | Buffer): Promise<string>;
|
|
64
|
+
/**
|
|
65
|
+
* Cria uma figurinha de texto do zero (TP).
|
|
66
|
+
*/
|
|
67
|
+
createTextSticker(text: string, options?: {
|
|
68
|
+
color?: 'WHITE' | 'BLACK';
|
|
69
|
+
background?: string;
|
|
70
|
+
}): Promise<string>;
|
|
52
71
|
}
|
|
53
72
|
export default StickEngine;
|
package/dist/StickEngine.js
CHANGED
|
@@ -11,6 +11,7 @@ import Jimp from 'jimp';
|
|
|
11
11
|
// @ts-ignore
|
|
12
12
|
import { removeBackgroundFromImageFile } from 'remove.bg';
|
|
13
13
|
import { fileURLToPath } from 'url';
|
|
14
|
+
// Correção para ESM
|
|
14
15
|
const __filename = fileURLToPath(import.meta.url);
|
|
15
16
|
const __dirname = path.dirname(__filename);
|
|
16
17
|
/**
|
|
@@ -177,15 +178,35 @@ export class StickEngine extends EventEmitter {
|
|
|
177
178
|
image.sepia();
|
|
178
179
|
if (options.blur)
|
|
179
180
|
image.blur(options.blur);
|
|
181
|
+
if (options.brightness)
|
|
182
|
+
image.brightness(options.brightness);
|
|
183
|
+
if (options.contrast)
|
|
184
|
+
image.contrast(options.contrast);
|
|
185
|
+
if (options.circle)
|
|
186
|
+
image.circle();
|
|
180
187
|
if (options.resize)
|
|
181
188
|
image.resize(options.resize.width, options.resize.height);
|
|
182
189
|
if (options.text) {
|
|
183
|
-
const
|
|
184
|
-
|
|
190
|
+
const fontPath = options.text.color === 'BLACK' ? Jimp.FONT_SANS_32_BLACK : Jimp.FONT_SANS_32_WHITE;
|
|
191
|
+
const font = await Jimp.loadFont(fontPath);
|
|
192
|
+
const printOptions = {
|
|
185
193
|
text: options.text.content,
|
|
186
194
|
alignmentX: options.text.alignmentX || Jimp.HORIZONTAL_ALIGN_CENTER,
|
|
187
195
|
alignmentY: options.text.alignmentY || Jimp.VERTICAL_ALIGN_BOTTOM
|
|
188
|
-
}
|
|
196
|
+
};
|
|
197
|
+
if (options.text.stroke) {
|
|
198
|
+
// Simulação de borda desenhando o texto em volta
|
|
199
|
+
const strokeColor = options.text.color === 'BLACK' ? Jimp.FONT_SANS_32_WHITE : Jimp.FONT_SANS_32_BLACK;
|
|
200
|
+
const strokeFont = await Jimp.loadFont(strokeColor);
|
|
201
|
+
for (let x = -2; x <= 2; x++) {
|
|
202
|
+
for (let y = -2; y <= 2; y++) {
|
|
203
|
+
if (x !== 0 || y !== 0) {
|
|
204
|
+
image.print(strokeFont, x, y, printOptions, image.bitmap.width, image.bitmap.height);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
image.print(font, 0, 0, printOptions, image.bitmap.width, image.bitmap.height);
|
|
189
210
|
}
|
|
190
211
|
await image.writeAsync(output);
|
|
191
212
|
}
|
|
@@ -203,29 +224,48 @@ export class StickEngine extends EventEmitter {
|
|
|
203
224
|
});
|
|
204
225
|
});
|
|
205
226
|
}
|
|
206
|
-
convertToWebp(input, output, isAnimated) {
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
227
|
+
async convertToWebp(input, output, isAnimated) {
|
|
228
|
+
const runFfmpeg = (quality, fps) => {
|
|
229
|
+
return new Promise((resolve, reject) => {
|
|
230
|
+
const ff = ffmpeg(input)
|
|
231
|
+
.on('error', reject)
|
|
232
|
+
.on('end', () => resolve());
|
|
233
|
+
const videoOptions = [
|
|
234
|
+
'-vcodec', 'libwebp',
|
|
235
|
+
'-vf', `scale=512:512:force_original_aspect_ratio=decrease,fps=${fps},pad=512:512:(ow-iw)/2:(oh-ih)/2:color=white@0,setsar=1`,
|
|
236
|
+
'-lossless', isAnimated ? '0' : '1',
|
|
237
|
+
'-loop', '0',
|
|
238
|
+
'-preset', 'default',
|
|
239
|
+
'-an',
|
|
240
|
+
'-vsync', '0'
|
|
241
|
+
];
|
|
242
|
+
if (isAnimated) {
|
|
243
|
+
videoOptions.push('-t', '6');
|
|
244
|
+
videoOptions.push('-q:v', String(quality));
|
|
245
|
+
}
|
|
246
|
+
ff.addOutputOptions(videoOptions)
|
|
247
|
+
.toFormat('webp')
|
|
248
|
+
.save(output);
|
|
249
|
+
});
|
|
250
|
+
};
|
|
251
|
+
let currentQuality = this.options.quality || 80;
|
|
252
|
+
let currentFps = this.options.fps || 15;
|
|
253
|
+
await runFfmpeg(currentQuality, currentFps);
|
|
254
|
+
// Auto-Dimensionamento Inteligente (Apenas para Animados)
|
|
255
|
+
if (isAnimated && fs.existsSync(output)) {
|
|
256
|
+
let stats = fs.statSync(output);
|
|
257
|
+
let attempts = 0;
|
|
258
|
+
// Se maior que 1MB, tenta reduzir qualidade e FPS até 3 vezes
|
|
259
|
+
while (stats.size > 1000000 && attempts < 3) {
|
|
260
|
+
currentQuality -= 15;
|
|
261
|
+
currentFps -= 3;
|
|
262
|
+
if (currentFps < 5)
|
|
263
|
+
currentFps = 5;
|
|
264
|
+
await runFfmpeg(currentQuality, currentFps);
|
|
265
|
+
stats = fs.statSync(output);
|
|
266
|
+
attempts++;
|
|
224
267
|
}
|
|
225
|
-
|
|
226
|
-
.toFormat('webp')
|
|
227
|
-
.save(output);
|
|
228
|
-
});
|
|
268
|
+
}
|
|
229
269
|
}
|
|
230
270
|
async addExif(webpPath, metadata) {
|
|
231
271
|
const json = {
|
|
@@ -242,14 +282,88 @@ export class StickEngine extends EventEmitter {
|
|
|
242
282
|
exifBuffer.writeUIntLE(jsonBuff.length, 14, 4);
|
|
243
283
|
await img.load(webpPath);
|
|
244
284
|
img.exif = exifBuffer;
|
|
245
|
-
|
|
285
|
+
// node-webpmux requer muxAnim para salvar WebPs animados
|
|
286
|
+
if (img.hasAnim) {
|
|
287
|
+
await img.muxAnim({ path: webpPath });
|
|
288
|
+
}
|
|
289
|
+
else {
|
|
290
|
+
await img.save(webpPath);
|
|
291
|
+
}
|
|
246
292
|
}
|
|
247
293
|
async start() {
|
|
248
294
|
if (this.queue.length === 0)
|
|
249
295
|
throw new Error('Nenhum arquivo na fila.');
|
|
250
296
|
const results = await Promise.allSettled(this.queue.map((file, i) => this.processFile(file, i)));
|
|
251
297
|
this.queue = [];
|
|
298
|
+
if (this.options.autoClean) {
|
|
299
|
+
// Nota: Se autoClean for true, os arquivos serão deletados após o uso.
|
|
300
|
+
// Em um ambiente de produção, o usuário deve ler o arquivo antes de chamar clean() ou desativar autoClean.
|
|
301
|
+
}
|
|
252
302
|
return results;
|
|
253
303
|
}
|
|
304
|
+
/**
|
|
305
|
+
* Converte um arquivo em Base64.
|
|
306
|
+
*/
|
|
307
|
+
static toBase64(filePath) {
|
|
308
|
+
const buffer = fs.readFileSync(filePath);
|
|
309
|
+
return buffer.toString('base64');
|
|
310
|
+
}
|
|
311
|
+
/**
|
|
312
|
+
* Gera um ícone de bandeja (Tray Icon) 96x96 para o pacote de figurinhas.
|
|
313
|
+
*/
|
|
314
|
+
async createTrayIcon(input) {
|
|
315
|
+
const timestamp = Date.now();
|
|
316
|
+
const outputPath = path.join(this.tempDir, `tray_${timestamp}.png`);
|
|
317
|
+
const webpOutputPath = path.join(this.tempDir, `tray_${timestamp}.webp`);
|
|
318
|
+
let buffer;
|
|
319
|
+
if (Buffer.isBuffer(input)) {
|
|
320
|
+
buffer = input;
|
|
321
|
+
}
|
|
322
|
+
else if (typeof input === 'string' && input.startsWith('http')) {
|
|
323
|
+
buffer = await getBuffer(input);
|
|
324
|
+
}
|
|
325
|
+
else if (typeof input === 'string' && fs.existsSync(input)) {
|
|
326
|
+
buffer = fs.readFileSync(input);
|
|
327
|
+
}
|
|
328
|
+
else {
|
|
329
|
+
throw new Error('Entrada inválida para Tray Icon.');
|
|
330
|
+
}
|
|
331
|
+
const image = await Jimp.read(buffer);
|
|
332
|
+
await image.cover(96, 96).writeAsync(outputPath);
|
|
333
|
+
// Converter para WebP (WhatsApp prefere WebP para ícones de bandeja em alguns casos)
|
|
334
|
+
await new Promise((resolve, reject) => {
|
|
335
|
+
ffmpeg(outputPath)
|
|
336
|
+
.on('error', reject)
|
|
337
|
+
.on('end', () => resolve())
|
|
338
|
+
.toFormat('webp')
|
|
339
|
+
.save(webpOutputPath);
|
|
340
|
+
});
|
|
341
|
+
this.createdFiles.push(outputPath, webpOutputPath);
|
|
342
|
+
return webpOutputPath;
|
|
343
|
+
}
|
|
344
|
+
/**
|
|
345
|
+
* Cria uma figurinha de texto do zero (TP).
|
|
346
|
+
*/
|
|
347
|
+
async createTextSticker(text, options = {}) {
|
|
348
|
+
const timestamp = Date.now();
|
|
349
|
+
const outputPath = path.join(this.tempDir, `text_${timestamp}.png`);
|
|
350
|
+
// Criar uma imagem transparente 512x512
|
|
351
|
+
const image = new Jimp(512, 512, options.background || 0x00000000);
|
|
352
|
+
const fontPath = options.color === 'BLACK' ? Jimp.FONT_SANS_64_BLACK : Jimp.FONT_SANS_64_WHITE;
|
|
353
|
+
const font = await Jimp.loadFont(fontPath);
|
|
354
|
+
// Centralizar o texto
|
|
355
|
+
image.print(font, 0, 0, {
|
|
356
|
+
text,
|
|
357
|
+
alignmentX: Jimp.HORIZONTAL_ALIGN_CENTER,
|
|
358
|
+
alignmentY: Jimp.VERTICAL_ALIGN_MIDDLE
|
|
359
|
+
}, 512, 512);
|
|
360
|
+
await image.writeAsync(outputPath);
|
|
361
|
+
// Processar como uma figurinha normal para adicionar metadados e converter para WebP
|
|
362
|
+
const engine = new StickEngine(this.options);
|
|
363
|
+
const results = await engine.addFile(outputPath).start();
|
|
364
|
+
const finalPath = results[0].value;
|
|
365
|
+
this.createdFiles.push(outputPath, finalPath);
|
|
366
|
+
return finalPath;
|
|
367
|
+
}
|
|
254
368
|
}
|
|
255
369
|
export default StickEngine;
|