Skip to content

Commit

Permalink
Why even one needs to have an API key for YouTube search?! (#32)
Browse files Browse the repository at this point in the history
  • Loading branch information
vishaltelangre authored Jul 26, 2020
1 parent 6ebca09 commit 2e25181
Show file tree
Hide file tree
Showing 10 changed files with 1,116 additions and 730 deletions.
22 changes: 22 additions & 0 deletions .github/workflows/npm-publish.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# This workflow will run tests using node and then publish a package to GitHub Packages when a release is created
# For more information see: https://help.github.com/actions/language-and-framework-guides/publishing-nodejs-packages

name: Node.js Package

on:
release:
types: [created]

jobs:
publish-npm:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v1
with:
node-version: 12
registry-url: https://registry.npmjs.org/
- run: yarn
- run: yarn publish
env:
NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}}
19 changes: 1 addition & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

Download music from saavn.com, gaana.com, etc.


[![npm](https://img.shields.io/npm/v/music-dl.svg?style=plastic)](https://www.npmjs.com/package/music-dl) [![npm](https://img.shields.io/npm/dt/music-dl.svg?style=plastic)](https://www.npmjs.com/package/music-dl) [![npm](https://img.shields.io/github/license/vishaltelangre/music-dl.svg?style=plastic)](LICENSE.txt)

### See it in action!
Expand All @@ -15,7 +14,6 @@ With ID3 tags!

![id3-tags.png](https://user-images.githubusercontent.com/876195/27254951-4508b762-53b1-11e7-84e1-f5addc2953fa.png)


**NOTE:** Currently, it only supports saavn.com and gaana.com,
but there will be support to download from other sites as well
in future.
Expand All @@ -41,7 +39,6 @@ Usage:
music-dl [OPTIONS] URL_OF_ALBUM_OR_PLAYLIST_HERE
Options:
-k, --api_key STRING API Key of YouTube
-v, --version Display the current version
-h, --help Display help and usage details
```
Expand All @@ -57,20 +54,6 @@ music-dl https://www.saavn.com/s/album/hindi/Yaara-Dildara-1993/OKbWYkAThtA_
music-dl https://www.saavn.com/s/featured-playlists/english/Hello_Adele/EFoglaGFXps_
```

### How to get/create an API key for YouTube?

YouTube requires an API key to allow searching the tracks.
That is why `music-dl` needs it.

Please follow instructions provided on [this wiki](https://github.com/vishaltelangre/music-dl/wiki/How-to-get-or-create-a-YouTube-API-Key%3F).

You will need to provide it only once using following command,
which will be stored at `$HOME/.music-dl.json` on your computer.

```
music-dl -k API_KEY_HERE
```

### Does it really download from these sites?

Nope, it doesn't.
Expand All @@ -81,6 +64,6 @@ It then downloads the matching music from YouTube.

### Copyright and License

Copyright (c) 2017-2018, Vishal Telangre and Contributors. All Rights Reserved.
Copyright (c) 2017-2020, Vishal Telangre and Contributors. All Rights Reserved.

This project is licenced under the [MIT License](LICENSE.txt).
16 changes: 0 additions & 16 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ PrerequisitesChecker(function() {

const { name, version } = require('./package.json');

const { Settings, SettingsManifestPath } = require('./lib/settings');
const Saavn = require('./lib/providers/saavn');
const Gaana = require('./lib/providers/gaana');

Expand All @@ -24,21 +23,6 @@ PrerequisitesChecker(function() {
cli.enable('version');
cli.setApp(name, version);

const options = cli.parse({
api_key: ['k', 'API Key of YoutTube', 'string']
});

if (!!options.api_key) {
Settings.setYouTubeApiKey(options.api_key);

return cli.ok(`Stored key at: ${SettingsManifestPath}`);
}

if (!Settings.getYouTubeApiKey()) {
cli.error("Please set the YouTube API key. Check --help for usage.");
return;
}

if (!cli.args[0]) {
cli.error("Please provide the URL to the album/playlist of songs which you want to download.")
console.log("Usage:".bold);
Expand Down
6 changes: 1 addition & 5 deletions lib/provider.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ const Promise = require("promise");
const colors = require('colors');

const YoutubeClient = require('./youtube/client');
const {Settings} = require('./settings');

module.exports = class Provider {
constructor(trackListUrl) {
Expand All @@ -21,10 +20,7 @@ module.exports = class Provider {
}

downloadTracks() {
const youtubeApiKey = Settings.getYouTubeApiKey();
if (!youtubeApiKey) throw new Error("YouTube api key is not provided");

const youtubeClient = new YoutubeClient(youtubeApiKey);
const youtubeClient = new YoutubeClient();

this.parseList().then(parsedInfo => {
const { listTitle, trackList } = parsedInfo;
Expand Down
35 changes: 0 additions & 35 deletions lib/settings.js

This file was deleted.

47 changes: 26 additions & 21 deletions lib/youtube/client.js
Original file line number Diff line number Diff line change
@@ -1,29 +1,34 @@
const path = require('path');
const path = require("path");
const Promise = require("promise");

const YouTubeSearch = require('./search');
const YouTubeDownloader = require('./downloader');
const Id3Tagger = require('./../id3_tagger');
const YouTubeSearch = require("./search");
const YouTubeDownloader = require("./downloader");
const Id3Tagger = require("./../id3_tagger");

module.exports = class YoutubeClient {
constructor(apiKey) {
this.apiKey = apiKey;
}

downloadAudioTrack(query, outputPath, outputFilename, trackInfo) {
return new Promise((resolve, reject) => {
if (!this.apiKey) reject(new Error("YouTube api key is not provided"));

const search = new YouTubeSearch(query, this.apiKey);
const search = new YouTubeSearch(query);

search.findLink().then((link) => {
new YouTubeDownloader(link, outputPath, outputFilename).download()
.then((mp3OutputPath) => {
const tagger = new Id3Tagger(mp3OutputPath, trackInfo);
tagger.tag();
resolve(mp3OutputPath);
}).catch(reject);
}).catch(reject);
})
search
.findLink()
.then((link) => {
new YouTubeDownloader(link, outputPath, outputFilename)
.download()
.then((mp3OutputPath) => {
const tagger = new Id3Tagger(mp3OutputPath, trackInfo);
tagger.tag();
resolve(mp3OutputPath);
})
.catch((reason) => {
console.error(reason);
reject(reason);
});
})
.catch((reason) => {
console.error(reason);
reject(reason);
});
});
}
}
};
36 changes: 21 additions & 15 deletions lib/youtube/downloader.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,35 +31,41 @@ module.exports = class YouTubeDownloader {
syncStdoutProgress(`Downloading: ${(downloaded / total * 100).toFixed(2)}% `);
});

track.on('end', () => {
this.getLength().then(lengthInSeconds => {
track.on('end', async () => {
try {
const lengthInSeconds = await this.getLength();
const conversionProc = ffmpeg(this.mp4OutputPath);

// Fix: Incorrectly displays doubled duration metadata
// in the converted audio file
// Reference: https://github.com/fluent-ffmpeg/node-fluent-ffmpeg/issues/387
conversionProc.outputOptions(['-write_xing 0']);
conversionProc.outputOptions(["-write_xing 0"]);

if (lengthInSeconds) conversionProc.withDuration(lengthInSeconds);

conversionProc.on('progress', (info) => {
syncStdoutProgress(`Converting: ${info.percent.toFixed(2)}% `);
}).on('end', () => {
syncStdoutProgress('✓'.green.bold, true);
fs.unlinkSync(this.mp4OutputPath);
resolve(this.mp3OutputPath);
}).save(this.mp3OutputPath);
}).catch((err) => console.log(err));
conversionProc
.on("progress", (info) => {
syncStdoutProgress(`Converting: ${info.percent.toFixed(2)}% `);
})
.on("end", () => {
syncStdoutProgress("✓".green.bold, true);
fs.unlinkSync(this.mp4OutputPath);
resolve(this.mp3OutputPath);
})
.save(this.mp3OutputPath);
} catch (error) {
console.error(error);
}
});

track.on('error', err => reject(err));
});
}

getLength() {
return new Promise((resolve, _) => {
ytdl.getInfo(this.link, (err, info) => resolve(info && info.length_seconds));
});
async getLength() {
const info = await ytdl.getInfo(this.link);

return info.videoDetails.lengthSeconds;
}

}
19 changes: 10 additions & 9 deletions lib/youtube/search.js
Original file line number Diff line number Diff line change
@@ -1,28 +1,29 @@
'use strict';

const ytSearch = require('youtube-search');
const ytSearch = require('yt-search');
const Promise = require("promise");

const DEFAULT_SEARCH_RESULT_LIMIT = 5;
const MAX_LENGTH_IN_SECONDS = 15 /* minutes */ * 60;

module.exports = class YouTubeSearch {

constructor(query, apiKey, limit = DEFAULT_SEARCH_RESULT_LIMIT) {
constructor(query) {
this.query = query;
this.apiKey = apiKey;
this.limit = limit;
}

findLink() {
const options = { maxResults: this.limit, key: this.apiKey };
const options = { query: this.query, pageStart: 1, pageEnd: 1 };

return new Promise((resolve, reject) => {
ytSearch(this.query, options, (err, results) => {
ytSearch(options, (err, { videos }) => {
if (err) reject(err);

const matchedVideo = results && results.find(result => result.kind === "youtube#video");

resolve(matchedVideo && matchedVideo.link);
const matchedVideo = videos.filter(
(video) => video.seconds <= MAX_LENGTH_IN_SECONDS
)[0];

resolve(matchedVideo && matchedVideo.url);
});
});
}
Expand Down
12 changes: 8 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"type": "git",
"url": "https://github.com/vishaltelangre/music-dl"
},
"version": "0.0.8",
"version": "0.0.9",
"description": "Download audio song playlists/albums from multiple song providers!",
"main": "index.js",
"author": "Vishal Telangre <[email protected]>",
Expand All @@ -19,12 +19,16 @@
"fluent-ffmpeg": "^2.1.2",
"lodash": "^4.17.15",
"mkdirp": "^0.5.1",
"needle": "2.3.0",
"node-id3": "^0.1.3",
"osmosis": "^1.1.6",
"osmosis": "^1.1.10",
"promise": "^8.0.1",
"request": "^2.88.0",
"update-notifier": "^2.4.0",
"youtube-search": "^1.1.0",
"ytdl-core": "^1.0.6"
"yt-search": "^2.1.6",
"ytdl-core": "^3.1.3"
},
"resolutions": {
"needle": "2.3.0"
}
}
Loading

0 comments on commit 2e25181

Please sign in to comment.