#!/bin/node var cp = require('child_process'); var { parseStringPromise } = require('xml2js'); var fs = require('fs'); var { URLSearchParams } = require('url'); var axios = require("axios"); var puppeteer = require("puppeteer"); var cheerio = require("cheerio"); var url = process.argv[2]; if (!url) { console.error("no input link!"); process.exit(1); } function getDLURLs(streaminfo, baseURL) { var highestQuality = streaminfo.Representation.pop().$; var toDownload = streaminfo.SegmentTemplate[0]; var urls = []; var time = 0; urls.push(toDownload.$.initialization.replace("$RepresentationID$", highestQuality.id)); toDownload.SegmentTimeline[0].S.forEach(segment => { var repeat = Number(segment.$.r || 0) + 1; for(let i = 0; i < repeat; i++) { urls.push(toDownload.$.media .replace("$RepresentationID$", highestQuality.id) .replace("$Time$", time)); time += Number(segment.$.d); } }); urls = urls.map(url => baseURL + '/' + url); return urls; } async function dlURLs(urls, filename) { var file = fs.createWriteStream(filename); for (let i = 0; i < urls.length; i++) { console.log("downloading " + urls[i] + "..."); var res = await axios({ method: 'get', url: urls[i], responseType: 'arraybuffer' }); file.write(res.data); } file.close(); } (async () => { var browser = await puppeteer.launch(); var page = await browser.newPage(); await page.goto(url, { waitUntil: 'networkidle2' }); var content = await page.content(); await browser.close(); var $ = cheerio.load(content); var src = $("iframe").attr("src"); var res = await axios.get(src); var tokenId = res.data.toString().match(/(? s.$.contentType == 'video'); await dlURLs(getDLURLs(videoStream, baseURL), filename + '.mp4v'); var audioStream = xml.MPD.Period[0].AdaptationSet.find(s => s.$.contentType == 'audio'); await dlURLs(getDLURLs(audioStream, baseURL), filename + '.mp4a'); cp.execSync(`ffmpeg -i ${filename}.mp4v -i ${filename}.mp4a -map 0:0 -map 1:0 ${filename}.mp4`); fs.rmSync(filename + '.mp4v'); fs.rmSync(filename + '.mp4a'); })();