@shibam/sticker-maker 1.3.0-rc6 → 1.3.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/package.json +1 -1
- package/readme.md +5 -5
- package/src/lib/ToWebp.js +17 -8
- package/src/lib/textOnGif.js +1 -1
- package/src/lib/textOnImg.js +1 -1
- package/src/lib/toGif.js +3 -3
- package/src/lib/toPng.js +23 -0
- package/src/lib/utils.js +1 -1
package/package.json
CHANGED
package/readme.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @shibam/sticker-maker
|
|
2
2
|
|
|
3
|
-
`@shibam/sticker-maker` is a lightweight utility library designed for converting images and videos into stickers while allowing customization of metadata. you have to download ffmpeg
|
|
3
|
+
`@shibam/sticker-maker` is a lightweight utility library designed for converting images and videos into stickers while allowing customization of metadata. you have to download ffmpeg dependency. It supports various input types and ensures high-quality sticker conversion. This module has minimal dependencies, ensuring efficient performance. If you encounter any issues, please feel free to open an issue. However, please check if a similar issue has already been reported before creating a new one. Happy Coding (≧▽≦).
|
|
4
4
|
|
|
5
5
|
# Sticker Class
|
|
6
6
|
|
|
@@ -20,10 +20,10 @@ Here's how you can use the `Sticker` class:
|
|
|
20
20
|
```typescript
|
|
21
21
|
import fs from "fs";
|
|
22
22
|
import { Readable } from "stream";
|
|
23
|
-
import
|
|
23
|
+
import Sticker, { StickerTypes } from "@shibam/sticker-maker";
|
|
24
24
|
|
|
25
25
|
// Example 1: Create a new sticker instance and convert to buffer
|
|
26
|
-
const sticker = new Sticker("path/to/image.png", {
|
|
26
|
+
const sticker = new Sticker("path/to/image.png", {// input can be file path or buffer or stream
|
|
27
27
|
pack: "My Sticker Pack",
|
|
28
28
|
author: "Shibam",
|
|
29
29
|
id: "123467890",
|
|
@@ -41,7 +41,7 @@ try {
|
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
// Example 2: Create a new sticker instance and convert to file
|
|
44
|
-
const sticker2 = new Sticker("path/to/another/image.png", {
|
|
44
|
+
const sticker2 = new Sticker("path/to/another/image.png", {// input can be file path or buffer or stream
|
|
45
45
|
pack: "Another Sticker Pack",
|
|
46
46
|
author: "John Doe",
|
|
47
47
|
id: "987654321",
|
|
@@ -81,7 +81,7 @@ Converts input data to a Buffer containing the converted sticker content.
|
|
|
81
81
|
Converts input data and writes the converted sticker to a file at `outputPath`.
|
|
82
82
|
|
|
83
83
|
|
|
84
|
-
|
|
84
|
+
# `extractMetaData(data: Buffer): Promise<any>`
|
|
85
85
|
|
|
86
86
|
Extracts metadata from `data` and returns the extracted information.
|
|
87
87
|
|
package/src/lib/ToWebp.js
CHANGED
|
@@ -4,6 +4,7 @@ import fs from 'fs-extra'
|
|
|
4
4
|
import os from 'os'
|
|
5
5
|
import path from 'path'
|
|
6
6
|
import toGif from './toGif.js'
|
|
7
|
+
import toPng from './toPng.js'
|
|
7
8
|
import TextOnImg from './textOnImg.js'
|
|
8
9
|
|
|
9
10
|
const exec = promisify(execFile)
|
|
@@ -11,7 +12,7 @@ const textOnImg = new TextOnImg()
|
|
|
11
12
|
|
|
12
13
|
export default async function ToWebp(buffer, metaInfo, mimeExt, mimeType) {
|
|
13
14
|
const timestamp = Date.now()
|
|
14
|
-
const inputPath = path.join(os.tmpdir(), `input_${timestamp}
|
|
15
|
+
const inputPath = path.join(os.tmpdir(), `input_${timestamp}.png`)
|
|
15
16
|
const outputPath = path.join(os.tmpdir(), `output_${timestamp}.webp`)
|
|
16
17
|
|
|
17
18
|
try {
|
|
@@ -27,17 +28,22 @@ export default async function ToWebp(buffer, metaInfo, mimeExt, mimeType) {
|
|
|
27
28
|
} else if (metaInfo.text) {
|
|
28
29
|
processedData = await textOnImg.drawText(buffer, metaInfo.text)
|
|
29
30
|
currentExt = 'png'
|
|
31
|
+
} else {
|
|
32
|
+
processedData = await toPng(buffer, mimeExt)
|
|
33
|
+
currentExt = 'png'
|
|
30
34
|
}
|
|
31
35
|
|
|
32
36
|
await fs.writeFile(inputPath, processedData)
|
|
33
37
|
|
|
34
38
|
let videoFilter = ''
|
|
35
39
|
if (metaInfo.type === 'CIRCLE') {
|
|
36
|
-
videoFilter =
|
|
40
|
+
videoFilter =
|
|
41
|
+
"scale=512:512:force_original_aspect_ratio=increase,crop=512:512,format=rgba,geq=r='r(X,Y)':g='g(X,Y)':b='b(X,Y)':a='if(lte((X-256)*(X-256)+(Y-256)*(Y-256),65536),255,0)'"
|
|
37
42
|
} else if (metaInfo.type === 'SQUARE') {
|
|
38
|
-
videoFilter =
|
|
43
|
+
videoFilter = "scale=512:512:force_original_aspect_ratio=decrease"
|
|
39
44
|
} else {
|
|
40
|
-
videoFilter =
|
|
45
|
+
videoFilter =
|
|
46
|
+
"scale=512:512:force_original_aspect_ratio=decrease,pad=512:512:(ow-iw)/2:(oh-ih)/2:color=0x00000000"
|
|
41
47
|
}
|
|
42
48
|
|
|
43
49
|
const ffmpegArgs = ['-y', '-i', inputPath, '-vf', videoFilter]
|
|
@@ -47,9 +53,12 @@ export default async function ToWebp(buffer, metaInfo, mimeExt, mimeType) {
|
|
|
47
53
|
}
|
|
48
54
|
|
|
49
55
|
ffmpegArgs.push(
|
|
50
|
-
'-c:v',
|
|
51
|
-
'
|
|
52
|
-
'-
|
|
56
|
+
'-c:v',
|
|
57
|
+
'libwebp',
|
|
58
|
+
'-quality',
|
|
59
|
+
String(metaInfo.quality || 90),
|
|
60
|
+
'-lossless',
|
|
61
|
+
'0',
|
|
53
62
|
outputPath
|
|
54
63
|
)
|
|
55
64
|
|
|
@@ -58,4 +67,4 @@ export default async function ToWebp(buffer, metaInfo, mimeExt, mimeType) {
|
|
|
58
67
|
} finally {
|
|
59
68
|
await Promise.all([fs.remove(inputPath), fs.remove(outputPath)]).catch(() => {})
|
|
60
69
|
}
|
|
61
|
-
}
|
|
70
|
+
}
|
package/src/lib/textOnGif.js
CHANGED
|
@@ -77,7 +77,7 @@ export default class TextOnGif {
|
|
|
77
77
|
const [width, height] = stdout.trim().split('x').map(Number)
|
|
78
78
|
if (!width || !height) throw new Error('Invalid GIF dimensions')
|
|
79
79
|
|
|
80
|
-
const fontSize = Math.floor(height /
|
|
80
|
+
const fontSize = Math.floor(height / 8)
|
|
81
81
|
const lineHeight = fontSize * 1.2
|
|
82
82
|
const lines = this.wrapText(text, this.maxCharsPerLine)
|
|
83
83
|
|
package/src/lib/textOnImg.js
CHANGED
|
@@ -77,7 +77,7 @@ export default class TextOnImg {
|
|
|
77
77
|
const [width, height] = stdout.trim().split('x').map(Number)
|
|
78
78
|
if (!width || !height) throw new Error('Invalid image dimensions')
|
|
79
79
|
|
|
80
|
-
const fontSize = Math.floor(height /
|
|
80
|
+
const fontSize = Math.floor(height / 7)
|
|
81
81
|
const lineHeight = fontSize * 1.2
|
|
82
82
|
const lines = this.wrapText(text, this.maxCharsPerLine)
|
|
83
83
|
|
package/src/lib/toGif.js
CHANGED
|
@@ -17,9 +17,9 @@ export default async function videoToGif(buffer, extType, type, text = '') {
|
|
|
17
17
|
try {
|
|
18
18
|
await fs.writeFile(inputPath, buffer)
|
|
19
19
|
const vf = type === 'SQUARE'
|
|
20
|
-
?
|
|
21
|
-
:
|
|
22
|
-
await exec('ffmpeg', ['-y', '-i', inputPath, '-vf', vf, '-t', '
|
|
20
|
+
? "scale=320:-1:flags=lanczos,fps=10,crop=min(iw\\,ih):min(iw\\,ih)"
|
|
21
|
+
: "scale=320:-1:flags=lanczos,fps=10"
|
|
22
|
+
await exec('ffmpeg', ['-y', '-i', inputPath, '-vf', vf, '-t', '6', '-loop', '0', '-f', 'gif', outputPath])
|
|
23
23
|
let result = await fs.readFile(outputPath)
|
|
24
24
|
if (text) result = await textOnGif.drawText(result, text)
|
|
25
25
|
return result
|
package/src/lib/toPng.js
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { promisify } from 'util'
|
|
2
|
+
import { execFile } from 'child_process'
|
|
3
|
+
import fs from 'fs-extra'
|
|
4
|
+
import os from 'os'
|
|
5
|
+
import path from 'path'
|
|
6
|
+
const exec = promisify(execFile)
|
|
7
|
+
|
|
8
|
+
export default async function toPng(buffer, mimeExt) {
|
|
9
|
+
if (mimeExt === 'png') return buffer
|
|
10
|
+
const timestamp = Date.now()
|
|
11
|
+
const inputPath = path.join(os.tmpdir(), `input_${timestamp}.${mimeExt}`)
|
|
12
|
+
const outputPath = path.join(os.tmpdir(), `output_${timestamp}.png`)
|
|
13
|
+
try {
|
|
14
|
+
await fs.writeFile(inputPath, buffer)
|
|
15
|
+
await exec('ffmpeg', ['-y', '-i', inputPath, outputPath])
|
|
16
|
+
const result = await fs.readFile(outputPath)
|
|
17
|
+
return result
|
|
18
|
+
} catch (err) {
|
|
19
|
+
throw new Error(`Failed to convert to PNG: ${err.message}`)
|
|
20
|
+
} finally {
|
|
21
|
+
await Promise.all([fs.remove(inputPath), fs.remove(outputPath)]).catch(() => {})
|
|
22
|
+
}
|
|
23
|
+
}
|
package/src/lib/utils.js
CHANGED
|
@@ -20,7 +20,7 @@ export default class Utils {
|
|
|
20
20
|
}
|
|
21
21
|
getQuality(data) {
|
|
22
22
|
const bytes = Buffer.from(data).length / 1024
|
|
23
|
-
return bytes > 4096 ?
|
|
23
|
+
return bytes > 4096 ? 70 : bytes > 3072 ? 80 : bytes > 2048 ? 85 : 90
|
|
24
24
|
}
|
|
25
25
|
async getMimeType(data) {
|
|
26
26
|
try {
|