Skip to content
This repository was archived by the owner on Nov 5, 2020. It is now read-only.

Commit 125cb11

Browse files
authored
Merge pull request #35 from ytdl-node/dev
feat: Inbuilt mp3 player
2 parents 5b81a29 + 995327a commit 125cb11

20 files changed

+418
-76
lines changed

.eslintrc.json

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@
2020
"project": [
2121
"./tsconfig.json",
2222
"./config/tsconfig.examples.json",
23-
"./config/tsconfig.test.json"
23+
"./config/tsconfig.test.json",
24+
"./config/tsconfig.preinstall.json"
2425
]
2526
},
2627
"rules": {
@@ -53,6 +54,12 @@
5354
"parserOptions": {
5455
"ecmaVersion": 2019
5556
}
57+
},
58+
{
59+
"files": "./preinstall.js",
60+
"rules": {
61+
"no-console": "off"
62+
}
5663
}
5764
]
5865
}

.github/workflows/build.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ jobs:
1212
steps:
1313
- uses: actions/checkout@v2
1414

15+
- run: |
16+
sudo apt-get update
17+
sudo apt-get install libasound2-dev # For alsa/asoundlib.h header needed for npm install
18+
1519
- name: npm install, build and test
1620
run: |
1721
npm install

.github/workflows/publish.yml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,13 @@ jobs:
2828
run: |
2929
echo "versionChanged- ${{steps.check.outputs.versionChanged}}"
3030
echo "releaseVersion- ${{steps.check.outputs.releaseVersion}}"
31+
32+
- run: |
33+
sudo apt-get update
34+
sudo apt-get install libasound2-dev # For alsa/asoundlib.h header needed for npm install
3135
3236
- if: steps.check.outputs.versionChanged == 'true'
33-
run: yarn install
37+
run: npm install
3438

3539
- if: steps.check.outputs.versionChanged == 'true'
3640
run: npm publish --access public

.github/workflows/release.yml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,11 @@ jobs:
2929
run: |
3030
echo "versionChanged- ${{steps.check.outputs.versionChanged}}"
3131
echo "releaseVersion- ${{steps.check.outputs.releaseVersion}}"
32-
32+
33+
- run: |
34+
sudo apt-get update
35+
sudo apt-get install libasound2-dev # For alsa/asoundlib.h header needed for npm install
36+
3337
- name: Pack
3438
if: steps.check.outputs.versionChanged == 'true'
3539
run: |

README.md

Lines changed: 42 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@
55
**ytdl** provides a library to integrate a Youtube Downloader for `Node.js` projects, and a CLI to download content from [Youtube](https://www.youtube.com). **ytdl** can also stream audio/video from YouTube, **without downloading**, directly to your locally installed media player!
66

77
> Note: You need [ffmpeg](https://ffmpeg.org/download.html) to be installed on your computer for complete functionality. Without it, you won't be able to some formats/qualities of videos.
8+
<br />
9+
10+
> Note: To use the inbuilt mp3 player `ytdl-mp3` on Linux distros, `<alsa/asoundlib.h>` header file must be present. The preinstall script logs a warning if it is not present. Ubuntu/Debian users require to install the `libasound2-dev` package (`sudo apt-get install libasound2-dev`), if not present already; before installing the library.
811
912
# Contents
1013

@@ -317,19 +320,26 @@ ytdl('https://www.youtube.com/watch?v=fJ9rUzIMcZQ').then((video) => {
317320
- Play audio or video from YouTube in your local media player.
318321
- `quality` may be an `itag` or among the ones mentioned [here](#quality-string).
319322
- Options are of [this](#options-object) format. This is ignored if parameter `quality` is an `itag`.
323+
- The function returns a `Player` object, with attributes `player` and `play(url, stream)`.
324+
325+
### Audio
326+
- By default, audio is played on a cross-platform player integrated with ytdl.
327+
- However, if the parameter `player` is passed, it is played on the specified media player.
328+
329+
### Video
330+
- `cvlc` is the default video player.
320331
- Allowed media players are: `cvlc`, `vlc`, `mplayer`, `afplay`, `mpg123`, `mpg321`, `play`, `omxplayer`, `aplay`, `cmdmp3`.
321332

322-
> Default player is `cvlc`.
323333
> The media player set must be on your [PATH](https://en.wikipedia.org/wiki/PATH_(variable)) or in your Environment Variables. On UNIX based systems, you can check if your media player is on your PATH by using the which command, e.g. `which mplayer`.
324334
325335
```javascript
326336
const ytdl = require('@ytdl/ytdl').default;
327337

328338
async function play() {
329339
const video = await ytdl('https://www.youtube.com/watch?v=fJ9rUzIMcZQ');
330-
video.play('any', { audioOnly: true }, 'mplayer');
340+
video.play('any', { audioOnly: true });
331341

332-
// Play audio of any quality on mplayer.
342+
// Play audio of any quality on ytdl-mp3 player.
333343
}
334344

335345
play();
@@ -341,9 +351,36 @@ play();
341351
const ytdl = require('@ytdl/ytdl').default;
342352

343353
ytdl('https://www.youtube.com/watch?v=fJ9rUzIMcZQ').then((video) => {
344-
video.play('any', { audioOnly: true }, 'mplayer');
354+
video.play('any', { audioOnly: true });
355+
356+
// Play audio of any quality on ytdl-mp3 player.
357+
});
358+
```
359+
360+
- The `Player` object returned can be used to log the name of the player being used.
361+
- In this example, `mplayer` is being used.
362+
363+
```javascript
364+
async function playLocal() {
365+
const video = await ytdl.init('https://www.youtube.com/watch?v=A7ry4cx6HfY');
366+
const player = await video.play('any', { audioOnly: true }, 'mplayer');
367+
console.log(`Player: ${player.player}`);
345368

346-
// Play audio of any quality on mplayer.
369+
// Logs the player on which media is being played.
370+
}
371+
372+
playLocal();
373+
```
374+
375+
### OR
376+
377+
```javascript
378+
ytdl.init('https://www.youtube.com/watch?v=A7ry4cx6HfY').then((video) => {
379+
video.play('any', { audioOnly: true }, 'mplayer').then((player) => {
380+
console.log(`Player: ${player.player}`);
381+
382+
// Logs the player on which media is being played.
383+
});
347384
});
348385
```
349386

config/tsconfig.preinstall.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"extends": "./tsconfig.base.json",
3+
"compilerOptions": {
4+
"allowJs": true,
5+
"checkJs": true,
6+
},
7+
"files": [
8+
"../preinstall.js"
9+
]
10+
}

examples/play.example.js

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,23 @@
11
const ytdl = require('..'); // require('@ytdl/ytdl');
22

33
/**
4-
* This function players audio from 'https://www.youtube.com/watch?v=A7ry4cx6HfY' on locally installed 'mplayer'
4+
* This function players audio from 'https://www.youtube.com/watch?v=A7ry4cx6HfY' on 'ytdl-mp3' player;
55
*/
66
async function play() {
77
const video = await ytdl.init('https://www.youtube.com/watch?v=A7ry4cx6HfY');
8-
video.play('any', { audioOnly: true }, 'mplayer');
8+
const player = await video.play('any', { audioOnly: true });
9+
console.log(`Player: ${player.player}`);
910
}
1011

1112
play();
13+
14+
/**
15+
* This function players audio from 'https://www.youtube.com/watch?v=A7ry4cx6HfY' on 'mplayer';
16+
*/
17+
async function playLocal() {
18+
const video = await ytdl.init('https://www.youtube.com/watch?v=A7ry4cx6HfY');
19+
const player = await video.play('any', { audioOnly: true }, 'mplayer');
20+
console.log(`Player: ${player.player}`);
21+
}
22+
23+
playLocal();

package-lock.json

Lines changed: 66 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@ytdl/ytdl",
3-
"version": "1.4.4",
3+
"version": "1.4.5",
44
"description": "A CLI/Library written in typescript/javascript, which allows you to download/play videos from YouTube onto your system.",
55
"keywords": [
66
"youtube",
@@ -16,14 +16,15 @@
1616
"main": "dist/src/index.js",
1717
"scripts": {
1818
"build": "npm run clean && tsc",
19-
"clean": "rm -rf ./dist",
19+
"clean": "rimraf ./dist",
2020
"test": "mocha --config test/.mocharc.json test/**/*.ts",
2121
"lint": "eslint \"src/**/*.{ts,js,jsx}\" \"test/**/*.ts\" \"examples/**/*.{ts,js}\"",
2222
"pack-src": "ncc build src/index.ts -o dist/src",
2323
"pack-cli": "ncc build bin/ytdl -o dist/cli && mv dist/cli/index.js dist/cli/ytdl",
2424
"pack": "npm run clean && npm run build && npm run pack-cli",
2525
"start": "ts-node src/index.ts",
26-
"prepare": "npm run build"
26+
"prepare": "npm run build",
27+
"preinstall": "node ./preinstall.js"
2728
},
2829
"bin": {
2930
"ytdl": "bin/ytdl"
@@ -71,5 +72,8 @@
7172
"commander": "^5.0.0",
7273
"fluent-ffmpeg": "^2.1.2",
7374
"winston": "^3.2.1"
75+
},
76+
"optionalDependencies": {
77+
"speaker": "^0.5.1"
7478
}
7579
}

preinstall.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
const { execSync } = require('child_process');
2+
3+
if (process.platform === 'linux') {
4+
let exitStatus;
5+
try {
6+
execSync('echo "#include <alsa/asoundlib.h>" | gcc -H -o /dev/null -x c - 2>&1 | head -n1').toString();
7+
exitStatus = 0;
8+
} catch (err) {
9+
exitStatus = err.status;
10+
}
11+
12+
if (exitStatus !== 0) {
13+
console.warn(`WARN: 'alsa/asoundlib.h' is absent. For Ubuntu/Debian operating systems, install using the following command:
14+
\nsudo apt-get update && sudo apt-get install libasound2-dev\n`);
15+
}
16+
}

src/cli.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,12 +77,13 @@ async function parseOptions(program: commander.Command): Promise<void> {
7777

7878
logger.info(`Video ID: ${id}`);
7979
logger.info(`Video Title: ${title}`);
80-
logger.info(`Video Time: ${time} seconds`);
80+
logger.info(`Video Time: ${time}`);
8181
logger.info(`Video Description:\n ${description}`);
8282
}
8383

8484
if (program.play) {
85-
ytdl.play(quality, options, program.setPlayer);
85+
const player = await ytdl.play(quality, options, program.setPlayer);
86+
logger.info(`Playing on ${player.player}.`);
8687
}
8788

8889
if (program.download) {

src/utils/AudioPlayer.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/* eslint global-require: "off" */
2+
/* eslint import/no-extraneous-dependencies: "off" */
3+
4+
import { ReadStream } from 'fs';
5+
import ffmpeg from 'fluent-ffmpeg';
6+
7+
import Player from './player';
8+
9+
export default class AudioPlayer implements Player {
10+
url: string;
11+
12+
stream: ReadStream;
13+
14+
player: string;
15+
16+
Speaker: any;
17+
18+
constructor() {
19+
this.url = '';
20+
this.player = 'ytdl-mp3';
21+
22+
this.Speaker = require('speaker');
23+
}
24+
25+
/**
26+
* Play video given a url and a stream.
27+
* @param url Stream URL
28+
* @param stream Media stream
29+
*/
30+
public play(url: string, stream: ReadStream) {
31+
this.url = url;
32+
this.stream = stream;
33+
ffmpeg(stream).toFormat('s16le').pipe(new this.Speaker());
34+
}
35+
}

0 commit comments

Comments
 (0)