jam-my-stack/src/youtube/thumbify.js

84 lines
2.5 KiB
JavaScript

const youtubedl = require('youtube-dl-exec');
const got = require("got");
const { createWriteStream, existsSync, unlinkSync } = require("fs");
const fs = require('fs').promises;
const { getFiles } = require('./../file-utils');
const { exec } = require('child_process');
async function downloadThumbnail(youtubeid, downloadDir, overlayImg) {
const dlLoc = `${downloadDir}/${youtubeid}.jpg`
if(existsSync(dlLoc)) {
console.log(` -- SKIPPING ${youtubeid}: already downloaded.`)
return
}
console.log(` -- downloading YouTube ${youtubeid} thumb...`)
const fStream = createWriteStream(dlLoc)
const done = new Promise(function(resolve, reject) {
fStream.on('finish', () => {
const child = exec(`convert -resize 700x400 -sampling-factor 4:2:0 -strip -quality 85 -interlace JPEG -format jpg -colorspace sRGB ${dlLoc} +repage +page ${overlayImg} -flatten ${dlLoc}`)
child.on('exit', code => {
if(code != 0) reject(`Mogrify returned non-zero exit code: ${code}`)
resolve()
})
})
youtubedl(`https://www.youtube.com/watch?v=${youtubeid}`, {
getThumb: true,
noWarnings: true
})
.then(url => {
got.stream(url).pipe(fStream)
})
.catch(err => {
// What the fuck. destroy() does not release: https://github.com/nodejs/node/issues/31776
fStream.end()
fStream.destroy()
fStream.on('close', () => {
if(existsSync(dlLoc)) unlinkSync(dlLoc)
reject(err)
})
})
})
return done
}
async function loadPostsWithVideos(postsDirectoryPath) {
const postNames = await getFiles(postsDirectoryPath);
const posts = await Promise.all(
postNames.filter(name => name.endsWith('.md')).map(async fileName => {
const fileContent = await fs.readFile(fileName, 'utf8');
return {
file: fileName,
content: fileContent
}
})
);
return posts
}
async function run(options) {
const { postDir, downloadDir, overlayImg } = options
console.log(`-- Scanning for YouTube embeds in ${postDir}... --`)
const posts = await loadPostsWithVideos(postDir)
for(let post of posts) {
const matches = post.content.matchAll(/\{\{\<\syoutube\s\"?(.+)\"?\s\>\}\}/gi)
for(let youtubeid of matches) {
try {
await downloadThumbnail(youtubeid[1].replace(/\"/g, ""), downloadDir, overlayImg)
} catch(e) {
console.log(`-- error while processing: ${e}`)
}
}
}
console.log("-- DONE scanning for YouTube embeds --")
}
module.exports = {
thumbify: run
}