Skip to content

Instantly share code, notes, and snippets.

@makidoll
Last active July 19, 2023 11:53
Show Gist options
  • Save makidoll/93e5ebcd04d9226f63113630c83eebdf to your computer and use it in GitHub Desktop.
Save makidoll/93e5ebcd04d9226f63113630c83eebdf to your computer and use it in GitHub Desktop.
Upscale anime videos with Real CUGAN
// download https://github.com/nihui/realcugan-ncnn-vulkan
// place this script in the same directory
// run `zx upscale-video.js`
const inputVideo = "palutenas-revolting-dinner-1.mp4";
const outputVideo = "palutenas-revolting-dinner-1-x4.mp4";
const scale = 4; // upscale ratio (1/2/3/4, default=2)
const noiseLevel = -1; // denoise level (-1/0/1/2/3, default=-1)
// note: upscaling palutena's revolting dinner 240p x4 with denoising will
// somewhat ruin the output. its probably not noisy, just really low res
async function cleanup(makeFolders) {
await fs.remove("tmp-input");
await fs.remove("tmp-output");
await fs.remove("tmp-in.txt");
if (makeFolders) {
await fs.mkdirp("tmp-input");
await fs.mkdirp("tmp-output");
}
}
(async () => {
await cleanup(true);
// get fps
const fps = Number(
(await $`ffprobe.exe ${inputVideo}`).stderr.match(
/ ([0-9]+(?:\.[0-9]+)?) fps,/,
)[1],
);
const frameTime = fps / 1000;
if (Number.isNaN(fps)) throw new Error("Failed to get fps");
// convert video to frames
await $`ffmpeg.exe -i ${inputVideo} tmp-input/%d.png`;
// upscale frames
await $`./realcugan-ncnn-vulkan.exe -i tmp-input -o tmp-output -s ${scale} -n ${noiseLevel}`;
// convert frames into video
const ffmpegInput = (await fs.readdir("tmp-output"))
.map(n => Number(n.replace(/[^0-9]/g, "")))
.sort((a, b) => a - b)
.map(n => "file 'tmp-output/" + n + ".png'\nduration " + frameTime)
.join("\n");
await fs.writeFile("tmp-in.txt", ffmpegInput);
// re-encode web compatible
await $`ffmpeg.exe -y -f concat -safe 0 -i tmp-in.txt -vf "settb=AVTB,setpts=N/${fps}/TB,fps=${fps}" -c:v libx264 -pix_fmt yuv420p -profile:v baseline -level 3 -preset medium -crf 21 tmp-${outputVideo}`;
// concat audio
// await $`ffmpeg.exe -y -i ${inputVideo} -i tmp-${outputVideo} -c copy -map 1:v:0 -map 0:a:0 ${outputVideo}`;
await $`ffmpeg.exe -y -i ${inputVideo} -i tmp-${outputVideo} -c:v copy -map 1:v:0 -map 0:a:0 -c:a aac ${outputVideo}`;
// cleanup
await fs.remove(`tmp-${outputVideo}`);
await cleanup(false);
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment