youtube-terminal
Version:
Stream YouTube videos as ascii art in the terminal!
70 lines (58 loc) • 1.89 kB
JavaScript
var ffmpeg = require('./ffmpeg')
var through2 = require('through2')
var TokenBucket = require('limiter').TokenBucket
var asciiPixels = require('ascii-pixels')
var ChopStream = require('chop-stream')
var charm = require('charm')
function ThrottleStream (chunksPerSecond) {
var bucket = new TokenBucket(chunksPerSecond, chunksPerSecond, 'second', null)
return through2(function (chunk, _, next) {
bucket.removeTokens(1, function (err) {
next(err, chunk)
})
})
}
function AsciiStream (frameWidth, frameHeight, options) {
return through2(function (frameData, _, next) {
var imageData = {
data: frameData,
width: frameWidth,
height: frameHeight,
format: 'RGB24'
}
// convert to ascii art
var ascii = asciiPixels(imageData, options)
next(null, ascii)
})
}
function TerminalStream () {
var term = charm(process)
term.removeAllListeners('^C')
term.on('^C', function () {
term.cursor(true).end()
process.exit()
})
term.reset()
term.cursor(false)
return through2(function (text, _, next) {
var boldText = '\u001B[1m' + text + '\u001B[22m'
term.erase('screen').position(0, 0).write(boldText)
next()
}).on('end', function () {
term.cursor(true).end()
})
}
// render video as ascii characters
module.exports = function (video, options) {
// set the dimensions for the scaled video
var frameWidth = Math.round(options.width)
var frameHeight = Math.round(video.height / (video.width / frameWidth))
var frameBytes = frameWidth * frameHeight * 3 // rgb24
ffmpeg
.rawImageStream(video.url, options)
.pipe(new ChopStream(frameBytes))
.pipe(new ThrottleStream(options.fps))
.pipe(new AsciiStream(frameWidth, frameHeight, options))
.pipe(new TerminalStream())
.resume() // TODO: makes TerminalStream end (should probably be a writable/output stream instead)
}