@ibaraki-douji/anime4k-gif
Version:
Upscale GIFs using Anime4kCPP
76 lines (65 loc) • 2.55 kB
text/typescript
import Anime4k = require('@ibaraki-douji/anime4k')
import { Options } from '@ibaraki-douji/anime4k/lib/types';
import path = require("path");
import { tmpdir } from "os";
import { mkdirSync, writeFileSync } from 'fs';
import { spawn, spawnSync } from 'child_process';
export = class Waifu2XGIF {
public readonly inputPath: string;
public readonly outputPath: string;
public readonly up: any;
public endBuffer: Buffer;
public end = false;
constructor (inp: string | Buffer, out: string, options: Options = {}) {
if (typeof inp == "string") this.inputPath = path.resolve(inp);
else {
this.inputPath = path.resolve(tmpdir(), generate(50) + ".gif");
writeFileSync(this.inputPath, inp as Buffer);
}
if (options.outputAsBuffer) {
this.outputPath = path.resolve(tmpdir(), generate(50) + ".gif");
} else {
this.outputPath = path.resolve(out);
}
const vidTmp = path.resolve(tmpdir(), generate(50) + ".mp4");
const outTmp = path.resolve(tmpdir(), generate(50) + ".mp4");
spawnSync("ffmpeg", [
"-y",
"-i", this.inputPath,
"-pix_fmt", "yuv420p",
"-c:v", "h264",
"-movflags", "+faststart",
"-filter:v", "crop='floor(in_w/2)*2:floor(in_h/2)*2'",
vidTmp
])
this.up = Anime4k.upscale(vidTmp, outTmp, options);
this.up.process.on("close", () => {
this.endBuffer = this.up.endBuffer;
spawnSync("ffmpeg", [
"-y",
"-i", outTmp,
"-c:v", "gif",
"-pix_fmt", "bgra",
this.outputPath
])
this.end = true;
})
}
public static upscale(inp: string | Buffer, out: string, options?: Options) {
return new Waifu2XGIF(inp, out, options);
}
public static listGPUs() {
return Anime4k.listGPUs();
}
public finishedPromise() {
return new Promise<void>(res => {
let x = setInterval(() => {
if (this.end) {
clearInterval(x);
res();
}
}, 100);
});
}
}
const generate=(length)=>{const alphabet="AZERTYUIOPQSDFGHJKLMWXCVBNazertyuiopqsdfghjklmwxcvbn123456789";let end="";for(let i=0;i<length;i++)end+=alphabet[Math.floor(Math.random()*alphabet.length)];return end}