Files
radio-scraper/index.js
2021-03-01 16:54:03 -07:00

101 lines
2.8 KiB
JavaScript

const spawn = require('child_process').spawn
const fs = require('fs')
const youtubedl = require('youtube-dl-exec')
const tmp = require('tmp')
const STREAM_URL = "https://www.youtube.com/henrikomagnifico/live"
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 = ''
tesseract.stdout.on('data', (data) => {
recognizedString += data;
})
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))