From c41b0bbb11b06544d696656b9ef441604b6b28c1 Mon Sep 17 00:00:00 2001 From: liam4 Date: Thu, 1 Jun 2017 16:17:46 -0300 Subject: YouTube downloader --- src/downloaders.js | 36 ++++++++++++++++++++++++++++++++++++ src/loop-play.js | 14 ++++++-------- src/play.js | 31 +++++++++++++++++++++++++++---- 3 files changed, 69 insertions(+), 12 deletions(-) create mode 100644 src/downloaders.js diff --git a/src/downloaders.js b/src/downloaders.js new file mode 100644 index 0000000..527f67d --- /dev/null +++ b/src/downloaders.js @@ -0,0 +1,36 @@ +const fs = require('fs') +const fetch = require('node-fetch') +const promisifyProcess = require('./promisify-process') +const tempy = require('tempy') + +const { spawn } = require('child_process') +const { promisify } = require('util') + +const writeFile = promisify(fs.writeFile) +const rename = promisify(fs.rename) + +function makeHTTPDownloader() { + return function(arg, out) { + return fetch(arg) + .then(response => response.buffer()) + .then(buffer => writeFile(out, buffer)) + } +} + +function makeYouTubeDownloader() { + return function(arg, out) { + const tempDir = tempy.directory() + + const opts = [ + '--extract-audio', + '--audio-format', 'wav', + '--output', tempDir + '/dl.%(ext)s', + arg + ] + + return promisifyProcess(spawn('youtube-dl', opts), false) + .then(() => rename(tempDir + '/dl.wav', out)) + } +} + +module.exports = {makeHTTPDownloader, makeYouTubeDownloader} diff --git a/src/loop-play.js b/src/loop-play.js index 560ac63..50bca80 100644 --- a/src/loop-play.js +++ b/src/loop-play.js @@ -12,7 +12,7 @@ const sanitize = require('sanitize-filename') const writeFile = promisify(fs.writeFile) -module.exports = async function loopPlay(fn, playArgs = []) { +module.exports = async function loopPlay(picker, downloader, playArgs = []) { // Looping play function. Takes one argument, the "pick" function, // which returns a track to play. Preemptively downloads the next // track while the current one is playing for seamless continuation @@ -21,22 +21,20 @@ module.exports = async function loopPlay(fn, playArgs = []) { // used as arguments to the `play` process (before the file name). async function downloadNext() { - const picked = fn() + const picked = picker() if (picked == null) { return false } - const [ title, href ] = picked - console.log(`Downloading ${title}..\n${href}`) + const [ title, downloaderArg ] = picked + console.log(`Downloading ${title}..\nDownloader arg: ${downloaderArg}`) const tempDir = tempy.directory() const wavFile = tempDir + `/.${sanitize(title)}.wav` - const downloadFile = tempDir + '/.dl-' + path.basename(href) + const downloadFile = tempDir + '/.dl-' + path.basename(downloaderArg) - const res = await fetch(href) - const buffer = await res.buffer() - await writeFile(downloadFile, buffer) + await downloader(downloaderArg, downloadFile) try { await convert(downloadFile, wavFile) diff --git a/src/play.js b/src/play.js index 0ffe996..38b05d5 100755 --- a/src/play.js +++ b/src/play.js @@ -7,6 +7,8 @@ const fs = require('fs') const { promisify } = require('util') const loopPlay = require('./loop-play') const processArgv = require('./process-argv') + +const downloaders = require('./downloaders') const pickers = require('./pickers') const { @@ -22,6 +24,7 @@ readFile('./playlist.json', 'utf-8') let curPlaylist = playlist let pickerType = 'shuffle' + let downloaderType = 'http' let playOpts = [] // WILL play says whether the user has forced playback via an argument. @@ -132,14 +135,21 @@ readFile('./playlist.json', 'utf-8') 'np': util => util.alias('-no-play'), '-picker': function(util) { - // --picker + // --picker // Selects the mode that the song to play is picked. - // This should be used after finishing modifying the active - // playlist. + // See pickers.js. pickerType = util.nextArg() }, + '-downloader': function(util) { + // --downloader + // Selects the mode that songs will be downloaded with. + // See downloaders.js. + + downloaderType = util.nextArg() + }, + '-play-opts': function(util) { // --play-opts // Sets command line options passed to the `play` command. @@ -165,9 +175,22 @@ readFile('./playlist.json', 'utf-8') picker = pickers.makeOrderedPlaylistPicker(curPlaylist) } else { console.error("Invalid picker type: " + pickerType) + return + } + + let downloader + if (downloaderType === 'http') { + console.log("Using HTTP downloader.") + downloader = downloaders.makeHTTPDownloader() + } else if (downloaderType === 'youtube') { + console.log("Using YouTube downloader.") + downloader = downloaders.makeYouTubeDownloader() + } else { + console.error("Invalid downloader type: " + downloaderType) + return } - return loopPlay(picker, playOpts) + return loopPlay(picker, downloader, playOpts) } else { return curPlaylist } -- cgit 1.3.0-6-gf8a5