Skip to content

Instantly share code, notes, and snippets.

@mallendeo
Last active October 1, 2015 03:57
Show Gist options
  • Save mallendeo/876ac5cfb110609a2d6f to your computer and use it in GitHub Desktop.
Save mallendeo/876ac5cfb110609a2d6f to your computer and use it in GitHub Desktop.
Get Youtube download URLs
var request = require('./request')
var vm = require('vm')
var parseString = require('xml2js').parseString
var url = 'https://www.youtube.com/watch?v=si81bIoZRJQ'
var html = ''
request(url).then(function(body) {
html = body
var player = body.match(/html5player-([\w\d\-]+)\\\/html5player(.*?).js/g)
var playerUrl = 'https://s.ytimg.com/yts/jsbin/' + player[0].replace('\\', '')
return request(playerUrl)
}).then(function(player) {
// get the function name
var name = /\.sig\|\|([a-zA-Z0-9$]+)\(/g.exec(player)[1]
var regex = 'function ' + name + '\(.+){.*?};'
var functionContent = new RegExp(regex, 'g').exec(player)[0]
var helperObj = /;([A-Za-z0-9]+?)\./.exec(functionContent)[1]
var helperRegex = 'var ' + helperObj + '={.*?};'
var helperFunction = new RegExp(helperRegex, 'g').exec(player)[0]
var dashmpdUrl = /\"dashmpd\":\"(.*?)\"/g.exec(html)[1]
var signature = /\\\/s\\\/([a-fA-F0-9\.]+)/g.exec(dashmpdUrl)[1]
signature = signature ? signature : ''
var fn = helperFunction + functionContent
+ 'var signature = ' + name
+ '(\'' + signature + '\')'
// eval is evil, so we use a sandbox
var sandbox = { signature: signature }
vm.runInNewContext(fn, sandbox)
dashmpdUrl = dashmpdUrl
.replace(/\/s\\\/([a-fA-F0-9\.]+)/, '\/signature\\\/' + sandbox.signature)
.replace(/\\/g, '')
return request(dashmpdUrl)
}).then(function(xml) {
parseString(xml, function (err, result) {
var mimeTypes = result.MPD.Period[0].AdaptationSet
var formatList = []
mimeTypes.forEach(function(mimeType) {
mimeType.Representation.forEach(function(format) {
formatList.push({
mimeType: mimeType.$.mimeType,
itag: format.$.id,
codecs: format.$.codecs,
audioSamplingRate: format.$.audioSamplingRate || null,
url: format.BaseURL[0]._,
clen: format.BaseURL[0].$['yt:contentLength'],
width: format.$.width || null,
height: format.$.height || null,
})
})
})
console.log(formatList)
})
})
{
"main": "index.js",
"dependencies": {
"bluebird": "~2.10.1",
"xml2js": "~0.4.12"
}
}
var http = require('http')
var https = require('https')
var parse = require('url').parse
var Promise = require('bluebird')
var httpLibs = { 'http:': http, 'https:': https }
module.exports = function(url) {
var parsed = parse(url)
var httpLib = httpLibs[parsed.protocol]
return new Promise(function(resolve, reject) {
if (!httpLib) {
var err = new Error('Invalid URL: ' + url)
reject(err)
return
}
var req = httpLib.get(parsed)
req.on('response', function(res) {
if (res.statusCode !== 200) {
reject(new Error('status code ' + res.statusCode));
return
}
var body = ''
res.setEncoding('utf8')
res.on('data', function(chunk) {
body += chunk
})
res.on('end', function() {
resolve(body)
})
})
req.on('error', reject)
})
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment