From 13ec7f5c5408c787e8e424a79ffeea281b044b6f Mon Sep 17 00:00:00 2001 From: liam4 Date: Fri, 21 Jul 2017 21:51:47 -0300 Subject: Update download-playlist to work with Playlist 2.0 --- src/download-playlist.js | 66 +++++++++++++++++++++++++++++++++++------------- 1 file changed, 49 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/src/download-playlist.js b/src/download-playlist.js index 0b5ea58..87d60c3 100755 --- a/src/download-playlist.js +++ b/src/download-playlist.js @@ -8,9 +8,10 @@ const sanitize = require('sanitize-filename') const promisifyProcess = require('./promisify-process') const { - isGroup, isTrack, flattenPlaylist, updatePlaylistFormat + isGroup, isTrack, flattenGrouplike, updatePlaylistFormat } = require('./playlist-utils') +const { getDownloaderFor, makePowerfulDownloader } = require('./downloaders') const { promisify } = require('util') const { spawn } = require('child_process') @@ -23,7 +24,7 @@ const writeFile = promisify(fs.writeFile) async function downloadCrawl(topPlaylist, initialOutPath = './out/') { let doneCount = 0 - let total = flattenPlaylist(topPlaylist).length + let total = flattenGrouplike(topPlaylist).items.length const status = function() { const percent = Math.trunc(doneCount / total * 10000) / 100 @@ -50,12 +51,15 @@ async function downloadCrawl(topPlaylist, initialOutPath = './out/') { for (let item of groupContents) { if (isGroup(item)) { // TODO: Not sure if this is the best way to pick the next out dir. - const out = outPath + sanitize(item[0]) + '/' + const out = outPath + sanitize(item.name) + '/' - outPlaylist.push([item[0], await recursive(item[1], out)]) + outPlaylist.push({ + name: item.name, + items: await recursive(item.items, out) + }) } else if (isTrack(item)) { - const base = sanitize(path.basename(item[0], path.extname(item[0]))) - const out = outPath + sanitize(base) + '.mp3' + const base = path.basename(item.name, path.extname(item.name)) + const targetFile = outPath + sanitize(base) + '.mp3' // If we've already downloaded a file at some point in previous time, // there's no need to download it again! @@ -72,24 +76,50 @@ async function downloadCrawl(topPlaylist, initialOutPath = './out/') { }) if (match) { - console.log(`\x1b[32;2mAlready downloaded: ${out}\x1b[0m`) - outPlaylist.push([item[0], outPath + match]) + console.log(`\x1b[32;2mAlready downloaded: ${targetFile}\x1b[0m`) + outPlaylist.push({name: item.name, downloaderArg: outPath + match}) doneCount++ status() continue } - console.log(`\x1b[2mDownloading: ${item[0]} - ${item[1]}\x1b[0m`) + console.log( + `\x1b[2mDownloading: ${item.name} - ${item.downloaderArg}` + + ` => ${targetFile}\x1b[0m` + ) + + const downloader = makePowerfulDownloader( + getDownloaderFor(item.downloaderArg) + ) + + const outputtedFile = await downloader(item.downloaderArg) + + let ffmpegSuccess = false + + try { + await promisifyProcess(spawn('ffmpeg', [ + '-i', outputtedFile, - console.log(out) + // A bug (in ffmpeg or macOS; not this) makes it necessary to have + // these options on macOS, otherwise the outputted file length is + // wrong. + '-write_xing', '0', - await promisifyProcess(spawn('mpv', [ - '--no-audio-display', - item[1], '-o', out, - '-oac', 'libmp3lame' - ])) + targetFile + ]), false) + + ffmpegSuccess = true + } catch(err) { + console.error( + `\x1b[33;1mFFmpeg failed (item skipped): ${item.name}\x1b[0m` + ) + } + + if (ffmpegSuccess) { + console.log('Added:', item.name) + outPlaylist.push({name: item.name, downloaderArg: targetFile}) + } - outPlaylist.push([item[0], out]) doneCount++ status() @@ -99,7 +129,7 @@ async function downloadCrawl(topPlaylist, initialOutPath = './out/') { return outPlaylist } - return recursive(topPlaylist.items, initialOutPath) + return {items: await recursive(topPlaylist.items, initialOutPath)} } async function main(args) { @@ -120,6 +150,8 @@ async function main(args) { process.exit(0) } +module.exports = main + if (require.main === module) { main(process.argv.slice(2)) .catch(err => console.error(err)) -- cgit 1.3.0-6-gf8a5