Last active
September 6, 2023 00:37
-
-
Save sawaYch/dec742791404e87ed2932325fe41484a to your computer and use it in GitHub Desktop.
batch convert webp to webm, maybe useful for converting Whatsapp sticker to Telegram.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
require webp & libwebp, see https://developers.google.com/speed/webp/download | |
run: | |
cd working_dir # suppose working dir contains all webp that u want to convert | |
node ./convert.js # wait for it until done | |
*/ | |
const child = require("child_process"); | |
const fs = require("fs"); | |
const path = require("path"); | |
const util = require("util"); | |
const readdir = util.promisify(fs.readdir); | |
const exec = util.promisify(child.exec); | |
const terminateWithError = (error = "[fatal] error") => { | |
console.log(error); | |
process.exit(1); | |
}; | |
const converter = (filenames) => { | |
const filename = filenames.shift(); | |
const nameWithoutExt = filename.replace(".webp", ""); | |
const frames = path.resolve(process.cwd(), "frames"); | |
if (fs.existsSync(frames)) fs.rmdirSync(frames, { recursive: true }); | |
fs.mkdirSync(frames); | |
process.chdir("frames"); | |
console.log("[info]", process.cwd()); | |
console.log("[info]", `anim_dump ../${filename}`); | |
exec(`anim_dump ../${filename}`) | |
.then(() => { | |
process.chdir(".."); | |
console.log("[info]", process.cwd()); | |
const command = `webpmux -info ./${filename}`; | |
console.log("[info]", command); | |
return exec(command); | |
}) | |
.then(({ stdout, stderr }) => { | |
if (stderr) return Promise.reject(stderr); | |
const isAnimation = stdout.match(/Features present: animation/) !== null; | |
if (!isAnimation) | |
return Promise.reject("This is not an animated webp file"); | |
const firstLine = stdout.match(/1:.+[\r]?\n/g); | |
if (!firstLine) return; | |
const frameLength = firstLine[0].split(/\s+/g)[6]; | |
console.log('frame length', frameLength) | |
const framerate = 11;//Math.round(1000 / frameLength); // frames/second | |
const dump = path.resolve(frames, "dump_%04d.png"); | |
const command = `ffmpeg -framerate ${framerate} -i "${dump}" -crf 0 -b:v 0.8M -b:a 124K "${nameWithoutExt}.webm" -y`; | |
console.log("[info]", command); | |
return exec(command); | |
}) | |
.then(({ stdout, stderr }) => { | |
if (/error/gm.test(stderr)) return Promise.reject(stderr); | |
fs.rmdirSync(frames, { recursive: true }); | |
if (filenames.length != 0) converter(filenames); | |
console.log("[info] Success!\n"); | |
}) | |
.catch((err) => { | |
terminateWithError(`[fatal] ${err}`); | |
fs.rmdirSync(frames, { recursive: true }); | |
}); | |
}; | |
const getWebFiles = async () => { | |
let fileName; | |
try { | |
fileName = await readdir("./"); | |
} catch (err) { | |
console.log(err); | |
} | |
return fileName.filter((it) => it.endsWith(".webp")); | |
}; | |
getWebFiles().then((filenames) => { | |
converter(filenames); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment