I'm writing a youtube video downloader. Let's use this video as an example:
https://www.youtube.com/watch?v=_UbDeqPdUek
When researching how to grab a YouTube video's url, I came across a snippet of code right here on stackoverflow:
(function() {
return ytplayer.config.args.adaptive_fmts
.split(',')
.map(item => item
.split('&')
.reduce((prev, curr) => (curr = curr.split('='),
Object.assign(prev, { [curr[0]]: decodeURIComponent(curr[1]) })
), {})
)
.reduce((prev, curr) => Object.assign(prev, {
[curr.quality_label || curr.type]: curr
}), {});
})();
Execute this in the chrome dev console on the youtube url above, and you'll see that it will spew forth an object with information, including video urls.
The 'url' property within the '720p' property, is the following:
https://r2---sn-5hne6nlk.googlevideo.com/videoplayback?mn=sn-5hne6nlk&ip=92.111.133.132&mm=31&sparams=clen%2Cdur%2Cei%2Cgir%2Cid%2Cinitcwndbps%2Cip%2Cipbits%2Citag%2Ckeepalive%2Clmt%2Cmime%2Cmm%2Cmn%2Cms%2Cmv%2Cpl%2Crequiressl%2Csource%2Cexpire&itag=247&mime=video%2Fwebm&dur=250.800&id=o-AEgCrHyMCCJXgH39WmxsSwNs01bFa3BDVFEIzgAyrthL&mv=m&pl=18&mt=1500667926&requiressl=yes&ms=au&expire=1500689653&initcwndbps=1997500&keepalive=yes&key=yt6&ei=lWByWcWwI4Th1gKa2aDoCg&signature=596BF2603202A1BC60493C8263928FB365A14B2A.92D082149A543786BA5C29A547A8F78DE9346F95&source=youtube&clen=47937010&gir=yes&ipbits=0&lmt=1449652247373936
When I paste this url into a chrome tab, it starts playing the video in a barebones window. You can use this link to download the video. The problem is, the video has no sound!
When I use keepvid to download the video, it will have the following url on the 720p download button:
https://r17---sn-o097znll.googlevideo.com/videoplayback?lmt=1470986968011625&mt=1500670510&dur=250.891&itag=22&ipbits=0&ms=au&sparams=dur%2Cei%2Cid%2Cip%2Cipbits%2Citag%2Clmt%2Cmime%2Cmm%2Cmn%2Cms%2Cmv%2Cpl%2Cratebypass%2Crequiressl%2Csource%2Cexpire&ei=pWpyWZ75BZyf1gLf6rXQCA&id=o-AMPIR2-sd--NM8eDZyPKMqOu1B5qqSkBd1brw-H44ARx&pl=24&mn=sn-o097znll&mm=31&source=youtube&signature=6F5B6D2EFCF5CD600D9B12C984A19DBA58AC6A7E.CC2EE5E63809D4C9A07BB2C194328C7825015976&ratebypass=yes&mv=m&mime=video%2Fmp4&ip=159.253.144.86&requiressl=yes&key=yt6&expire=1500692229&title=Cubs+Meet+Adult+Tiger+For+The+First+Time+-+Tigers+About+The+House+-+BBC
The differences between both urls (and the query params) are small. But the fact is that keepvid's url works better than mine:
- It spews up the file as a download, rather than playing it in the browser.
- It has sound.
For all of your convenience, here are the url-decoded, formatted versions of these urls, with the parameters alphabetically ordered.
My url which I got from the js snippet above, with sound not working:
https://r2---sn-5hne6nlk.googlevideo.com/videoplayback
clen=47937010
dur=250.800
ei=lWByWcWwI4Th1gKa2aDoCg
expire=1500689653
gir=yes
id=o-AEgCrHyMCCJXgH39WmxsSwNs01bFa3BDVFEIzgAyrthL
initcwndbps=1997500
ip=92.111.133.132
ipbits=0
itag=247
keepalive=yes
key=yt6
lmt=1449652247373936
mime=video/webm
mm=31
mn=sn-5hne6nlk
ms=au
mt=1500667926
mv=m
pl=18
requiressl=yes
signature=596BF2603202A1BC60493C8263928FB365A14B2A.92D082149A543786BA5C29A547A8F78DE9346F95
source=youtube
sparams=clen,dur,ei,gir,id,initcwndbps,ip,ipbits,itag,keepalive,lmt,mime,mm,mn,ms,mv,pl,requiressl,source,expire
The url which I got from keepvid, with sound working:
https://r17---sn-o097znll.googlevideo.com/videoplayback
dur=250.891
ei=pWpyWZ75BZyf1gLf6rXQCA
expire=1500692229
id=o-AMPIR2-sd--NM8eDZyPKMqOu1B5qqSkBd1brw-H44ARx
ip=159.253.144.86
ipbits=0
itag=22
key=yt6
lmt=1470986968011625
mime=video/mp4
mm=31
mn=sn-o097znll
ms=au
mt=1500670510
mv=m
pl=24
ratebypass=yes
requiressl=yes
signature=6F5B6D2EFCF5CD600D9B12C984A19DBA58AC6A7E.CC2EE5E63809D4C9A07BB2C194328C7825015976
source=youtube
sparams=dur,ei,id,ip,ipbits,itag,lmt,mime,mm,mn,ms,mv,pl,ratebypass,requiressl,source,expire
title=Cubs Meet Adult Tiger For The First Time - Tigers About The House - BBC
As you can see, the urls/parameters are very similar. But how does keepvid manage to produce a file url that has the sound working, while my js snippet craps out on me without audio?
The urls have a signature as a parameter. This is likely the signature for (some of the) query parameters itself. Changing something small in a parameter (delete it, or change its value), results in the url getting access denied. This makes it hard to experiment with it.
The js snippet simply accesses an online variable and digs the video info from it. But what's the snippet missing that's causing its urls to refer to soundless videos?
Can anybody help me to programmatically obtain a url just like keepvid's, which will result in a downloaded file with working audio?
[Update]
I've just learned you can grab video info like such:
http://youtube.com/get_video_info?video_id=_UbDeqPdUek
It yields a big file with loads of info, that I haven't figured out how to parse yet.
I must be on the right path, because this is how youtube-dl is doing it. And that program works flawlessly.
I suppose I could simply reverse engineer youtube-dl (costs time). Or even call it from my C# program using Process (makes me dependent on it).
But that still leaves me with the question of how a person would figure this out on their own, if no help was available?