get most of bash script into node

This commit is contained in:
Mikah Chapman
2021-03-01 16:54:03 -07:00
parent b44ad9c362
commit 87e2f87302
3 changed files with 810 additions and 18 deletions

112
index.js
View File

@@ -1,22 +1,100 @@
const spawn = require('child_process').spawn;
const spawn = require('child_process').spawn
const fs = require('fs')
const youtubedl = require('youtube-dl-exec')
const tmp = require('tmp')
function readFromRegion(frame: Buffer, x: int, y: int, width: int, height: int) {
const convert = spawn('convert', ['-', '-negate', '-crop', `${width}x${height}+${x}+${y}`, '-'])
const result = new Buffer(512 * 1024)
let resultSize = 0
const STREAM_URL = "https://www.youtube.com/henrikomagnifico/live"
convert.stdout.on('data', (data) => {
if (data.length + resultSize > result.length) {
// Buffer not big enough
} else {
resultSize += data.length
data.copy(result)
}
});
function readText(tmpfile, charWhitelist) {
return new Promise((resolve, reject) => {
const tesseract = charWhitelist ? spawn('tesseract', [tmpfile.name, '-', '-c', `tessedit_char_whitelist="${charWhitelist}`]) : spawn('tesseract', [tmpfile.name, '-'])
let recognizedString = ''
convert.on('exit', (code) => {
tesseract.stdout.on('data', (data) => {
recognizedString += data;
})
});
convert.stdin.write(frame)
tesseract.on('exit', (code) => {
tmpfile.removeCallback()
if (code !== 0) {
reject()
} else {
resolve(recognizedString)
}
})
})
}
function thresholdImage(image, threshold) {
}
function getRegion(frame, x, y, width, height) { // Returns Promise<Buffer>
console.log("retrieving region")
const threshold = "15%"
return new Promise(function (resolve, reject) {
const tmpFile = tmp.fileSync()
const convert = spawn('convert', [`png:${frame.name}`, '-negate', '-crop', `${width}x${height}+${x}+${y}`, '-white-threshold', threshold, `png:${tmpFile.name}`])
convert.stderr.on('data', data => console.error(data.toString()))
convert.on('exit', (code) => {
if (code !== 0) {
reject()
} else {
console.log("got region", tmpFile.name)
resolve(tmpFile);
}
});
});
}
function getFrame(url) {
return new Promise((resolve, reject) => { // Returns Promise<Buffer>
const frameFile = tmp.fileSync()
const ffmpeg = spawn('ffmpeg', ['-i', url, '-y', '-f', 'image2', '-c:v', 'png', '-frames:v', '1', frameFile.name])
ffmpeg.stderr.on('data', data => console.error(data.toString()))
ffmpeg.on('exit', (code) => {
if (code !== 0) {
reject()
} else {
console.log("got frame", frameFile.name)
resolve(frameFile)
}
})
});
}
function getYoutubeStream() {
return new Promise((resolve, reject) => {
youtubedl(STREAM_URL, {
dumpJson: true,
format: "best"
}).then(output => resolve(output.url))
.catch(err => reject(err))
})
}
getYoutubeStream()
.then(url => getFrame(url))
.then(frame => {
let title = '',
album = '',
duration = ''
const titlePromise = getRegion(frame, 432, 906, 1487, 54).then(titleRegion => readText(titleRegion))
const albumPromise = getRegion(frame, 440, 957, 1487, 32).then(albumRegion => readText(albumRegion))
const durationPromise = getRegion(frame, 0, 1028, 235, 34).then(durationRegion => readText(durationRegion, "1234567890:/"))
console.log("waiting for processors")
Promise.all([titlePromise, albumPromise, durationPromise]).then(values => {
frame.removeCallback()
title = values[0].trim()
album = values[1].trim()
duration = values[2].trim()
console.log(`${album}: ${title} (${duration})`)
}).catch(err => console.error(err))
}).catch(err => console.error(err))