Create youtube downloader web app

This tutorial will guide you to create your own youtube downloader app in node expressjs with the help of awesome command line utility program called youtube-dl which extracts download links from many video sites including NSFW.
However unlike youtube-dl which has lot more functionality, this app will only extract all video resolutions and restrict itself to youtube url (and its redirects) only.


SOURCE CODE

Now, before starting the tutorial, make sure you've nodejs installed on your window, mac or any linux machine and be sure to check it via following code:

node -vBashCopy

1. Setting up the project

We'll use official scaffolding tool called express generator for this app. So, quickly start by entering into the new directory (name it whatever you want eg: ytdown) and install the generator tool globally using the following command :

npminstall express-generator -gBashCopy

After that, create the new project with handlebars as a default template engine into the working directory

express --hbsBashCopy

And finally do npm install to initiate the project. Run the server using npm start and browse it using http://localhost:3000.

2. Creating the UI

We need two page views for this app. In first page user enter the video url and the second one will list the video link in different resolutions. Here's the code for the two pages:

index.hbs

In this file, /video is the routing url where video link appears.

<headerclass="site-head"><h1class="h2 mb-4 title">Youtube Downloader</h1><p>Download any youtube video in multiple formats and quality with fast download</p></header><divclass="container content-wrap"><divclass="row justify-content-center align-items-start"><divclass="col"><formclass="down-form"name="youtube-download"method="post"action="/video"><inputtype="url"name="url"placeholder="https://www.youtube.com/watch?v=kQW81ty6QFg"requiredclass="form-control form-control-lg"/><buttontype="submit"class="btn btn-success mt-3">Get Links</button></form></div></div></div>HTMLCopy
listvideo.hbs

This file has some extra variables and handlebars statement which output meta information of the video.

<divclass="container content-wrap"><divclass="mb-4"><ahref="/"class="btn btn-secondary">← Back To Homepage</a></div>
{{#if error}}
<p>{{error}}</p>
{{else}}
<divclass="col"><iframewidth="640"height="360"src="https://www.youtube.com/embed/{{meta.id}}"frameborder="0"allowfullscreen></iframe></div><divclass="col-6"><h4class="h5 mb-4 font-weight-bold">Download Links <small>(multiple sizes and formats)</small></h4><ulclass="list-group">
{{#each meta.formats}}
<liclass="list-group-item"><ahref="{{url}}"style="font-size: 12px">{{format_note}}
<divclass="small">Ext: {{ext}} | Size: {{filesize}}</div></a></li>
{{/each}}
</ul></div>
{{/if}}
</div>
HTMLCopy

And here is the modified layout.hbs file which include link to bootstrap framework and some google fonts for styling.

layout.hbs
<!DOCTYPE html><html><head><title>{{title}}</title><linkrel="stylesheet"href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/css/bootstrap.min.css"/><linkrel="stylesheet"href="/stylesheets/style.css"/><linkhref="https://fonts.googleapis.com/css?family=Open+Sans:400,700"rel="stylesheet"><linkhref="https://fonts.googleapis.com/css?family=Bungee+Shade"rel="stylesheet"></head><body>
{{{body}}}
</body></html>
HTMLCopy

Finally some css styling for the app in style.css

body{font-family:'Open Sans', 'Lucida Grande', sans-serif;}::-webkit-input-placeholder{/* Chrome/Opera/Safari */color:rgba(0,0,0,.4)!important;}::-moz-placeholder{/* Firefox 19+ */color:rgba(0,0,0,.4)!important;}:-ms-input-placeholder{/* IE 10+ */color:rgba(0,0,0,.4)!important;}.site-head{padding: 1.4rem 2rem;text-align: center;margin-top: 6rem;}.site-head .title{position: relative;display: inline-block;font-family:'Bungee Shade', cursive;}.site-head .title:before{content:"";position: absolute;width: 70px;height: 6px;background:rgba(144, 232, 24, 1);bottom: -10px;left: 6px;}.content-wrap{padding: 1rem;}.down-form input{border: 2px solid #efefef;}.down-form input:focus{border-color:rgba(104, 202, 24, .4);}CSSCopy

Now, before starting the tutorial, make sure you've nodejs installed on your window, mac or any linux machine and be sure to check it via following code:

node -vBashCopy

1. Setting up the project

We'll use official scaffolding tool called express generator for this app. So, quickly start by entering into the new directory (name it whatever you want eg: ytdown) and install the generator tool globally using the following command :

npminstall express-generator -gBashCopy

After that, create the new project with handlebars as a default template engine into the working directory

express --hbsBashCopy

And finally do npm install to initiate the project. Run the server using npm start and browse it using http://localhost:3000.

2. Creating the UI

We need two page views for this app. In first page user enter the video url and the second one will list the video link in different resolutions. Here's the code for the two pages:

index.hbs

In this file, /video is the routing url where video link appears.

<headerclass="site-head"><h1class="h2 mb-4 title">Youtube Downloader</h1><p>Download any youtube video in multiple formats and quality with fast download</p></header><divclass="container content-wrap"><divclass="row justify-content-center align-items-start"><divclass="col"><formclass="down-form"name="youtube-download"method="post"action="/video"><inputtype="url"name="url"placeholder="https://www.youtube.com/watch?v=kQW81ty6QFg"requiredclass="form-control form-control-lg"/><buttontype="submit"class="btn btn-success mt-3">Get Links</button></form></div></div></div>HTMLCopy
listvideo.hbs

This file has some extra variables and handlebars statement which output meta information of the video.

<divclass="container content-wrap"><divclass="mb-4"><ahref="/"class="btn btn-secondary">← Back To Homepage</a></div>
{{#if error}}
<p>{{error}}</p>
{{else}}
<divclass="col"><iframewidth="640"height="360"src="https://www.youtube.com/embed/{{meta.id}}"frameborder="0"allowfullscreen></iframe></div><divclass="col-6"><h4class="h5 mb-4 font-weight-bold">Download Links <small>(multiple sizes and formats)</small></h4><ulclass="list-group">
{{#each meta.formats}}
<liclass="list-group-item"><ahref="{{url}}"style="font-size: 12px">{{format_note}}
<divclass="small">Ext: {{ext}} | Size: {{filesize}}</div></a></li>
{{/each}}
</ul></div>
{{/if}}
</div>
HTMLCopy

And here is the modified layout.hbs file which include link to bootstrap framework and some google fonts for styling.

layout.hbs
<!DOCTYPE html><html><head><title>{{title}}</title><linkrel="stylesheet"href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/css/bootstrap.min.css"/><linkrel="stylesheet"href="/stylesheets/style.css"/><linkhref="https://fonts.googleapis.com/css?family=Open+Sans:400,700"rel="stylesheet"><linkhref="https://fonts.googleapis.com/css?family=Bungee+Shade"rel="stylesheet"></head><body>
{{{body}}}
</body></html>
HTMLCopy

Finally some css styling for the app in style.css

body{font-family:'Open Sans', 'Lucida Grande', sans-serif;}::-webkit-input-placeholder{/* Chrome/Opera/Safari */color:rgba(0,0,0,.4)!important;}::-moz-placeholder{/* Firefox 19+ */color:rgba(0,0,0,.4)!important;}:-ms-input-placeholder{/* IE 10+ */color:rgba(0,0,0,.4)!important;}.site-head{padding: 1.4rem 2rem;text-align: center;margin-top: 6rem;}.site-head .title{position: relative;display: inline-block;font-family:'Bungee Shade', cursive;}.site-head .title:before{content:"";position: absolute;width: 70px;height: 6px;background:rgba(144, 232, 24, 1);bottom: -10px;left: 6px;}.content-wrap{padding: 1rem;}.down-form input{border: 2px solid #efefef;}.down-form input:focus{border-color:rgba(104, 202, 24, .4);}CSSCopy

Here's the final screenshot of the UI :

3. Creating the endpoints

Basically we need to implement one additional routing endpoints for listvideo.hbs page. So, open the routes/index.js fileand add the following code:

// default endpoint
router.get('/',function(req, res){
res.render('index',{ title:'Youtube Downloader'});// new endpoint});
router.post('/video',function(req, res, next){
res.render('listvideo',{});})
JsCopy

4. Using youtube-dl in the app

Now it's time to integrate youtube-dl into the code and using this is very easy with the help of node youtube-dl wrapper. It will also automatically install youtube-dl if it's not installed on your system.
So, we need to only do this:

npminstall youtube-dl --saveBashCopy

After that, we need to call the method to get the download url via getInfo() method. So edit the previous index.js file to make it look like this:

// ... other code// utility function to convert bytes to human readable.functionbytesToSize(bytes){var sizes =['Bytes','KB','MB','GB','TB'];if(bytes ==0)return'0 Byte';var i =parseInt(Math.floor(Math.log(bytes)/ Math.log(1024)));return Math.round(bytes / Math.pow(1024, i),2)+' '+ sizes[i];};var ytdl =require('youtube-dl');
router.post('/video',function(req, res, next){var url = req.body.url,
formats =[];

ytdl.getInfo(url,['--youtube-skip-dash-manifest'],function(err, info){if(err)return res.render('listvideo',{error:'The link you provided either not a valid url or it is not acceptable'});// push all video formats for download (skipping audio)
info.formats.forEach(function(item){if(item.format_note !=='DASH audio'&& item.filesize){
item.filesize = item.filesize ?bytesToSize(item.filesize):'unknown';
formats.push(item);}});
res.render('listvideo',{meta:{id: info.id, formats: formats}});})})
JsCopy

Ok, done. And now the app is almost completed and working but the thing that is missing is to restrict this app to youtube url only. This is necessary as it will prevent malicious url from users.
We also need to check for youtube redirection and short links which can be easily achievable by making a GET request.
Wrap the above with the following:

// this pattern check for youtube url.var pattern =/^((?:https?:)?\\\\\\\\/\\\\\\\\/)?((?:www|m)\\\\\\\\.)?((?:youtube\\\\\\\\.com|youtu.be))(\\\\\\\\/(?:[\\\\\\\\w\\\\\\\\-]+\\\\\\\\?v=|embed\\\\\\\\/|v\\\\\\\\/)?)([\\\\\\\\w\\\\\\\\-]+)(\\\\\\\\S+)?$/;
router.post('/video',function(req, res, next){
request.get(url,function(err, resp, body){// check if it is valid urlif(pattern.test(resp.request.uri.href)){// .... above code as usual}else{
res.render('listvideo',{error:'The link you provided either not a valid url or it is not acceptable'});}})});
JsCopy

So, finally the tutorial is completed. And there is lot more thing to do like making a nice 404 page, hiding the server ip, video to audio converter if you're planning to running it in production.

Youtube video list PHP script

Introduction

This article will present how to search and display Youtube videos by channel, keywords and other search terms with PHP and Youtube Data API v3.

Using the code

HideCopy Code

//You can see related documentation and compose own request here: https://developers.google.com/youtube/v3/docs/search/list//You must enable Youtube Data API v3 and get API key on Google Developer Console(https://console.developers.google.com)$channelId = 'UCVHFbqXqoYvEWM1Ddxl0QDg';$maxResults = 8;$API_key = '{YOUR_API_KEY}';$video_list = json_decode(file_get_contents('https://www.googleapis.com/youtube/v3/search?order=date&part=snippet&channelId='.$channelId.'&maxResults='.$maxResults.'&key='.$API_key.''));

The success response body contains data with following structure(this is one example file):

{ "kind": "youtube#searchListResponse", "etag": "\\\\\\\\"xmg9xJZuZD438sF4hb-VcBBREXc/m3cPJSo7dQS75OQg_SHGOrwYc9g\\\\\\\\"", "nextPageToken": "CAcQAA", "pageInfo": {  "totalResults": 578,  "resultsPerPage": 7 }, "items": [  {   "kind": "youtube#searchResult",   "etag": "\\\\\\\\"xmg9xJZuZD438sF4hb-VcBBREXc/JzNt_IJbl9HIEbO1dzqa7PP4dvs\\\\\\\\"",   "id": {    "kind": "youtube#video",    "videoId": "1Iw7Tg_afKk"   },   "snippet": {    "publishedAt": "2015-05-20T16:57:25.000Z",    "channelId": "UCVHFbqXqoYvEWM1Ddxl0QDg",    "title": "Android Developer Story: Wooga’s fast iterations on Android and Google Play",    "description": "The speed at which Wooga is able to iterate its live and under development games with the Android and Google Play tools has been key to delivering hits such ...",    "thumbnails": {     "default": {      "url": "https://i.ytimg.com/vi/1Iw7Tg_afKk/default.jpg"     },     "medium": {      "url": "https://i.ytimg.com/vi/1Iw7Tg_afKk/mqdefault.jpg"     },     "high": {      "url": "https://i.ytimg.com/vi/1Iw7Tg_afKk/hqdefault.jpg"     }    },    "channelTitle": "androiddevelopers",    "liveBroadcastContent": "none"   }  },  {   "kind": "youtube#searchResult",   "etag": "\\\\\\\\"xmg9xJZuZD438sF4hb-VcBBREXc/P3sZWlXACXK9x5GWlI8CJ7ynJ2c\\\\\\\\"",   "id": {    "kind": "youtube#playlist",    "playlistId": "PLWz5rJ2EKKc8I9gHTMh5yKkwRRGE8BjbQ"   },   "snippet": {    "publishedAt": "2015-05-08T04:50:37.000Z",    "channelId": "UCVHFbqXqoYvEWM1Ddxl0QDg",    "title": "Android Studio and Tools",    "description": "",    "thumbnails": {     "default": {      "url": "https://i.ytimg.com/vi/K2dodTXARqc/default.jpg"     },     "medium": {      "url": "https://i.ytimg.com/vi/K2dodTXARqc/mqdefault.jpg"     },     "high": {      "url": "https://i.ytimg.com/vi/K2dodTXARqc/hqdefault.jpg"     }    },    "channelTitle": "androiddevelopers",    "liveBroadcastContent": "none"   }  },  {   "kind": "youtube#searchResult",   "etag": "\\\\\\\\"xmg9xJZuZD438sF4hb-VcBBREXc/tkro7_XcVIZsyz68u3JgPcSagq0\\\\\\\\"",   "id": {    "kind": "youtube#video",    "videoId": "MCoh4Pxs_ok"   },   "snippet": {    "publishedAt": "2015-05-05T17:01:12.000Z",    "channelId": "UCVHFbqXqoYvEWM1Ddxl0QDg",    "title": "Android Developer Story: The Hunt increases engagement with material design and Google Play",    "description": "The Hunt has been making great use of material design to enhance engagement with its community, in their style advice and product discovery app. Using beta ...",    "thumbnails": {     "default": {      "url": "https://i.ytimg.com/vi/MCoh4Pxs_ok/default.jpg"     },     "medium": {      "url&