forked from onetrickwolf/gif-to-webm-please
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathhandler.js
138 lines (130 loc) · 3.49 KB
/
handler.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
"use strict";
const fs = require("fs");
const https = require("https");
const { spawnSync } = require("child_process");
const { randomUUID } = require("crypto");
module.exports.gif2webm = async (event, context, callback) => {
// let gif = 'https://static-cdn.jtvnw.net/emoticons/v2/emotesv2_447df256f3b1412b9fa0dfd3e9b6d84c/default/dark/3.0';
let gif = event.queryStringParameters?.gif;
if (gif === undefined) {
return {
statusCode: 400,
headers: { "Content-Type": "text/plain" },
body: "Required query params missing.",
};
}
let gif_path = `/tmp/${randomUUID()}.gif`;
let webm_path = `/tmp/${randomUUID()}.webm`;
// TODO: making https.get a promise within a lambda sucks, was trying avoid libraries but this could be easier to read
// TODO: open up cors for every response
const promise = new Promise(function (resolve, reject) {
https
.get(gif, (res) => {
if (res.statusCode !== 200) {
resolve({
statusCode: 404,
headers: { "Content-Type": "text/plain" },
body: "GIF does not exist",
});
} else {
const writeStream = fs.createWriteStream(gif_path);
res.pipe(writeStream);
writeStream.on("finish", () => {
writeStream.close();
if (exists(gif_path)) {
console.info("GIF Download Completed");
convert(resolve, reject);
} else {
resolve({
statusCode: 404,
headers: { "Content-Type": "text/plain" },
body: "GIF could not be downloaded",
});
}
});
}
})
.on("error", (err) => {
console.error(err.message);
resolve({
statusCode: err.statusCode || 500,
headers: { "Content-Type": "text/plain" },
body: err.message,
});
});
});
function exists(filePath) {
if (fs.existsSync(filePath)) {
const stats = fs.statSync(filePath);
const fileSizeInBytes = stats.size;
if (fileSizeInBytes > 0) {
console.info(
`${filePath} exists and is ${fileSizeInBytes} bytes in size`
);
return true;
} else {
console.error(`${filePath} exists but is 0 bytes in size`);
return false;
}
} else {
console.error(`${filePath} does not exist`);
return false;
}
}
function convert(resolve, reject) {
const ffmpeg = spawnSync(
"/opt/bin/ffmpeg",
[
"-y",
"-i",
gif_path,
"-c:v",
"libvpx",
"-qmin",
"0",
"-qmax",
"18",
"-crf",
"9",
"-b:v",
"1400K",
"-quality",
"good",
"-cpu-used",
"0",
"-auto-alt-ref",
"0",
"-pix_fmt",
"yuva420p",
"-an",
"-sn",
"-vsync",
"cfr",
webm_path,
],
{
// stdio: ['ignore', 1, 2]
}
);
if (exists(webm_path)) {
const image = fs.readFileSync(webm_path);
const response = {
statusCode: 200,
headers: {
"Content-Type": "video/webm",
"Access-Control-Allow-Origin": "*",
},
body: image.toString("base64"),
isBase64Encoded: true,
};
resolve(response);
} else {
resolve({
statusCode: 500,
headers: { "Content-Type": "text/plain" },
body: "WebM conversion failed",
});
}
}
return promise;
};