soundcord 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +140 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -0
- package/dist/invidious.d.ts +12 -0
- package/dist/invidious.d.ts.map +1 -0
- package/dist/invidious.js +86 -0
- package/dist/invidious.js.map +1 -0
- package/dist/setup.d.ts +3 -0
- package/dist/setup.d.ts.map +1 -0
- package/dist/setup.js +311 -0
- package/dist/setup.js.map +1 -0
- package/dist/signature.d.ts +7 -0
- package/dist/signature.d.ts.map +1 -0
- package/dist/signature.js +128 -0
- package/dist/signature.js.map +1 -0
- package/dist/stream.d.ts.map +1 -0
- package/dist/stream.js.map +1 -0
- package/dist/types.d.ts +36 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +13 -0
- package/dist/types.js.map +1 -0
- package/dist/youtube.d.ts +21 -0
- package/dist/youtube.d.ts.map +1 -0
- package/dist/youtube.js +252 -0
- package/dist/youtube.js.map +1 -0
- package/package.json +32 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Shuzo
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
# soundcord
|
|
2
|
+
|
|
3
|
+
YouTube audio streaming for Discord bots. Simple API, no bloat.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install soundcord
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
### Dependencies
|
|
12
|
+
|
|
13
|
+
You need `yt-dlp` and `ffmpeg` installed. Run the setup helper:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npx soundcord-setup
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Or install manually:
|
|
20
|
+
- [yt-dlp](https://github.com/yt-dlp/yt-dlp)
|
|
21
|
+
- [ffmpeg](https://ffmpeg.org/download.html)
|
|
22
|
+
|
|
23
|
+
## Usage
|
|
24
|
+
|
|
25
|
+
```typescript
|
|
26
|
+
import { YouTube } from 'soundcord';
|
|
27
|
+
|
|
28
|
+
const yt = new YouTube();
|
|
29
|
+
|
|
30
|
+
// Search videos
|
|
31
|
+
const results = await yt.search('never gonna give you up');
|
|
32
|
+
console.log(results[0].title);
|
|
33
|
+
|
|
34
|
+
// Get video info
|
|
35
|
+
const info = await yt.getInfo('dQw4w9WgXcQ');
|
|
36
|
+
console.log(info.title, info.duration);
|
|
37
|
+
|
|
38
|
+
// Get audio stream URL (for discord.js voice)
|
|
39
|
+
const stream = await yt.getStream('dQw4w9WgXcQ');
|
|
40
|
+
console.log(stream.url);
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### With discord.js
|
|
44
|
+
|
|
45
|
+
```typescript
|
|
46
|
+
import { YouTube } from 'soundcord';
|
|
47
|
+
import { createAudioResource, createAudioPlayer, joinVoiceChannel } from '@discordjs/voice';
|
|
48
|
+
|
|
49
|
+
const yt = new YouTube();
|
|
50
|
+
|
|
51
|
+
// Join voice channel
|
|
52
|
+
const connection = joinVoiceChannel({
|
|
53
|
+
channelId: voiceChannel.id,
|
|
54
|
+
guildId: guild.id,
|
|
55
|
+
adapterCreator: guild.voiceAdapterCreator,
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
// Play audio
|
|
59
|
+
const { url } = await yt.getStream('dQw4w9WgXcQ');
|
|
60
|
+
const resource = createAudioResource(url);
|
|
61
|
+
const player = createAudioPlayer();
|
|
62
|
+
|
|
63
|
+
player.play(resource);
|
|
64
|
+
connection.subscribe(player);
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## API
|
|
68
|
+
|
|
69
|
+
### `new YouTube(options?)`
|
|
70
|
+
|
|
71
|
+
| Option | Type | Default | Description |
|
|
72
|
+
|--------|------|---------|-------------|
|
|
73
|
+
| `timeout` | number | 15000 | Request timeout in ms |
|
|
74
|
+
| `minDuration` | number | 0 | Min video duration to include in search |
|
|
75
|
+
| `cacheTTL` | number | 300000 | Stream URL cache duration (5min) |
|
|
76
|
+
| `ytdlpPath` | string | auto | Custom path to yt-dlp binary |
|
|
77
|
+
|
|
78
|
+
### Methods
|
|
79
|
+
|
|
80
|
+
#### `search(query, limit?): Promise<SearchResult[]>`
|
|
81
|
+
Search YouTube videos. Returns up to `limit` results (default 10).
|
|
82
|
+
|
|
83
|
+
#### `getInfo(urlOrId): Promise<VideoInfo>`
|
|
84
|
+
Get video metadata by URL or ID.
|
|
85
|
+
|
|
86
|
+
#### `getStream(urlOrId): Promise<StreamInfo>`
|
|
87
|
+
Get audio stream URL for playback.
|
|
88
|
+
|
|
89
|
+
#### `isValidUrl(url): boolean`
|
|
90
|
+
Check if string is a valid YouTube URL.
|
|
91
|
+
|
|
92
|
+
#### `extractId(url): string | null`
|
|
93
|
+
Extract video ID from URL.
|
|
94
|
+
|
|
95
|
+
## Types
|
|
96
|
+
|
|
97
|
+
```typescript
|
|
98
|
+
interface SearchResult {
|
|
99
|
+
id: string;
|
|
100
|
+
title: string;
|
|
101
|
+
author: string;
|
|
102
|
+
duration: number;
|
|
103
|
+
thumbnail: string;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
interface VideoInfo {
|
|
107
|
+
id: string;
|
|
108
|
+
title: string;
|
|
109
|
+
author: string;
|
|
110
|
+
duration: number;
|
|
111
|
+
thumbnail: string;
|
|
112
|
+
url: string;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
interface StreamInfo {
|
|
116
|
+
url: string;
|
|
117
|
+
mimeType: string;
|
|
118
|
+
bitrate: number;
|
|
119
|
+
}
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
## Error Handling
|
|
123
|
+
|
|
124
|
+
```typescript
|
|
125
|
+
import { YouTube, YouTubeError } from 'soundcord';
|
|
126
|
+
|
|
127
|
+
const yt = new YouTube();
|
|
128
|
+
|
|
129
|
+
try {
|
|
130
|
+
await yt.getStream('invalid');
|
|
131
|
+
} catch (err) {
|
|
132
|
+
if (err instanceof YouTubeError) {
|
|
133
|
+
console.log(err.code); // 'NOT_FOUND' | 'NETWORK_ERROR' | 'YTDLP_MISSING' | etc.
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
## License
|
|
139
|
+
|
|
140
|
+
MIT
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,UAAU,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAC5F,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,WAAW,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DiscordYT = exports.YouTubeError = exports.YouTube = void 0;
|
|
4
|
+
var youtube_1 = require("./youtube");
|
|
5
|
+
Object.defineProperty(exports, "YouTube", { enumerable: true, get: function () { return youtube_1.YouTube; } });
|
|
6
|
+
var types_1 = require("./types");
|
|
7
|
+
Object.defineProperty(exports, "YouTubeError", { enumerable: true, get: function () { return types_1.YouTubeError; } });
|
|
8
|
+
var youtube_2 = require("./youtube");
|
|
9
|
+
Object.defineProperty(exports, "DiscordYT", { enumerable: true, get: function () { return youtube_2.YouTube; } });
|
|
10
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,qCAAoC;AAA3B,kGAAA,OAAO,OAAA;AAChB,iCAA4F;AAA9B,qGAAA,YAAY,OAAA;AAC1E,qCAAiD;AAAxC,oGAAA,OAAO,OAAa"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { VideoInfo, SearchResult, StreamInfo } from './types';
|
|
2
|
+
export declare class Invidious {
|
|
3
|
+
private instances;
|
|
4
|
+
private currentIndex;
|
|
5
|
+
private timeout;
|
|
6
|
+
constructor(customInstances?: string[], timeout?: number);
|
|
7
|
+
private fetch;
|
|
8
|
+
search(query: string, limit?: number): Promise<SearchResult[]>;
|
|
9
|
+
getVideoInfo(videoId: string): Promise<VideoInfo>;
|
|
10
|
+
getAudioStream(videoId: string): Promise<StreamInfo>;
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=invidious.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"invidious.d.ts","sourceRoot":"","sources":["../src/invidious.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,UAAU,EAAqB,MAAM,SAAS,CAAC;AAMjF,qBAAa,SAAS;IACpB,OAAO,CAAC,SAAS,CAAsB;IACvC,OAAO,CAAC,YAAY,CAAa;IACjC,OAAO,CAAC,OAAO,CAAS;gBAEZ,eAAe,CAAC,EAAE,MAAM,EAAE,EAAE,OAAO,GAAE,MAAc;YAMjD,KAAK;IA0Cb,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,GAAE,MAAW,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;IAYlE,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC;IAajD,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;CAuB3D"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Invidious = void 0;
|
|
4
|
+
const DEFAULT_INSTANCES = [
|
|
5
|
+
'https://yewtu.be'
|
|
6
|
+
];
|
|
7
|
+
class Invidious {
|
|
8
|
+
constructor(customInstances, timeout = 10000) {
|
|
9
|
+
this.currentIndex = 0;
|
|
10
|
+
const urls = customInstances?.length ? customInstances : DEFAULT_INSTANCES;
|
|
11
|
+
this.instances = urls.map(url => ({ url: url.replace(/\/$/, ''), healthy: true }));
|
|
12
|
+
this.timeout = timeout;
|
|
13
|
+
}
|
|
14
|
+
async fetch(endpoint) {
|
|
15
|
+
let lastError = null;
|
|
16
|
+
for (let i = 0; i < this.instances.length; i++) {
|
|
17
|
+
const instance = this.instances[(this.currentIndex + i) % this.instances.length];
|
|
18
|
+
if (!instance.healthy)
|
|
19
|
+
continue;
|
|
20
|
+
try {
|
|
21
|
+
const controller = new AbortController();
|
|
22
|
+
const timeoutId = setTimeout(() => controller.abort(), this.timeout);
|
|
23
|
+
const response = await fetch(`${instance.url}${endpoint}`, {
|
|
24
|
+
signal: controller.signal,
|
|
25
|
+
headers: {
|
|
26
|
+
'Accept': 'application/json',
|
|
27
|
+
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36'
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
clearTimeout(timeoutId);
|
|
31
|
+
if (!response.ok) {
|
|
32
|
+
throw new Error(`HTTP ${response.status}`);
|
|
33
|
+
}
|
|
34
|
+
this.currentIndex = (this.currentIndex + i) % this.instances.length;
|
|
35
|
+
return await response.json();
|
|
36
|
+
}
|
|
37
|
+
catch (error) {
|
|
38
|
+
console.log(`❌ Instance ${instance.url} failed:`, error.message);
|
|
39
|
+
instance.healthy = false;
|
|
40
|
+
lastError = error;
|
|
41
|
+
// Réactive l'instance après 5 minutes
|
|
42
|
+
setTimeout(() => { instance.healthy = true; }, 5 * 60 * 1000);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
throw new Error(`Toutes les instances ont échoué: ${lastError?.message}`);
|
|
46
|
+
}
|
|
47
|
+
async search(query, limit = 10) {
|
|
48
|
+
const data = await this.fetch(`/api/v1/search?q=${encodeURIComponent(query)}&type=video`);
|
|
49
|
+
return data.slice(0, limit).map(item => ({
|
|
50
|
+
id: item.videoId,
|
|
51
|
+
title: item.title,
|
|
52
|
+
author: item.author,
|
|
53
|
+
duration: item.lengthSeconds,
|
|
54
|
+
thumbnail: item.videoThumbnails?.[0]?.url || ''
|
|
55
|
+
}));
|
|
56
|
+
}
|
|
57
|
+
async getVideoInfo(videoId) {
|
|
58
|
+
const data = await this.fetch(`/api/v1/videos/${videoId}`);
|
|
59
|
+
return {
|
|
60
|
+
id: data.videoId,
|
|
61
|
+
title: data.title,
|
|
62
|
+
author: data.author,
|
|
63
|
+
duration: data.lengthSeconds,
|
|
64
|
+
thumbnail: data.videoThumbnails?.[0]?.url || '',
|
|
65
|
+
url: `https://www.youtube.com/watch?v=${data.videoId}`
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
async getAudioStream(videoId) {
|
|
69
|
+
const data = await this.fetch(`/api/v1/videos/${videoId}`);
|
|
70
|
+
// Cherche le meilleur stream audio
|
|
71
|
+
const audioFormats = data.adaptiveFormats?.filter((f) => f.type?.startsWith('audio/')) || [];
|
|
72
|
+
if (!audioFormats.length) {
|
|
73
|
+
throw new Error('Aucun stream audio disponible');
|
|
74
|
+
}
|
|
75
|
+
// Trie par bitrate décroissant
|
|
76
|
+
audioFormats.sort((a, b) => (b.bitrate || 0) - (a.bitrate || 0));
|
|
77
|
+
const best = audioFormats[0];
|
|
78
|
+
return {
|
|
79
|
+
url: best.url,
|
|
80
|
+
mimeType: best.type,
|
|
81
|
+
bitrate: best.bitrate || 0
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
exports.Invidious = Invidious;
|
|
86
|
+
//# sourceMappingURL=invidious.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"invidious.js","sourceRoot":"","sources":["../src/invidious.ts"],"names":[],"mappings":"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"}
|
package/dist/setup.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../src/setup.ts"],"names":[],"mappings":""}
|
package/dist/setup.js
ADDED
|
@@ -0,0 +1,311 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
4
|
+
if (k2 === undefined) k2 = k;
|
|
5
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
6
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
7
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
8
|
+
}
|
|
9
|
+
Object.defineProperty(o, k2, desc);
|
|
10
|
+
}) : (function(o, m, k, k2) {
|
|
11
|
+
if (k2 === undefined) k2 = k;
|
|
12
|
+
o[k2] = m[k];
|
|
13
|
+
}));
|
|
14
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
15
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
16
|
+
}) : function(o, v) {
|
|
17
|
+
o["default"] = v;
|
|
18
|
+
});
|
|
19
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
20
|
+
var ownKeys = function(o) {
|
|
21
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
22
|
+
var ar = [];
|
|
23
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
24
|
+
return ar;
|
|
25
|
+
};
|
|
26
|
+
return ownKeys(o);
|
|
27
|
+
};
|
|
28
|
+
return function (mod) {
|
|
29
|
+
if (mod && mod.__esModule) return mod;
|
|
30
|
+
var result = {};
|
|
31
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
32
|
+
__setModuleDefault(result, mod);
|
|
33
|
+
return result;
|
|
34
|
+
};
|
|
35
|
+
})();
|
|
36
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
37
|
+
const child_process_1 = require("child_process");
|
|
38
|
+
const readline = __importStar(require("readline"));
|
|
39
|
+
const fs = __importStar(require("fs"));
|
|
40
|
+
const path = __importStar(require("path"));
|
|
41
|
+
const os = __importStar(require("os"));
|
|
42
|
+
const isWin = process.platform === 'win32';
|
|
43
|
+
const isMac = process.platform === 'darwin';
|
|
44
|
+
// configurable install paths
|
|
45
|
+
const config = {
|
|
46
|
+
win: {
|
|
47
|
+
installDir: process.env.DISCORD_YT_INSTALL_DIR || path.join(os.homedir(), 'soundcord-deps'),
|
|
48
|
+
},
|
|
49
|
+
unix: {
|
|
50
|
+
installDir: process.env.DISCORD_YT_INSTALL_DIR || '/usr/local/bin',
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
const installDir = isWin ? config.win.installDir : config.unix.installDir;
|
|
54
|
+
// terminal colors
|
|
55
|
+
const c = {
|
|
56
|
+
reset: '\x1b[0m',
|
|
57
|
+
bold: '\x1b[1m',
|
|
58
|
+
dim: '\x1b[2m',
|
|
59
|
+
cyan: '\x1b[36m',
|
|
60
|
+
green: '\x1b[32m',
|
|
61
|
+
red: '\x1b[31m',
|
|
62
|
+
yellow: '\x1b[33m',
|
|
63
|
+
magenta: '\x1b[35m',
|
|
64
|
+
};
|
|
65
|
+
const frames = ['|', '/', '-', '\\'];
|
|
66
|
+
let spinnerInterval = null;
|
|
67
|
+
let spinnerFrame = 0;
|
|
68
|
+
function startSpinner(text) {
|
|
69
|
+
process.stdout.write('\x1b[?25l'); // hide cursor
|
|
70
|
+
spinnerInterval = setInterval(() => {
|
|
71
|
+
process.stdout.write(`\r${c.cyan}${frames[spinnerFrame]}${c.reset} ${text}`);
|
|
72
|
+
spinnerFrame = (spinnerFrame + 1) % frames.length;
|
|
73
|
+
}, 100);
|
|
74
|
+
}
|
|
75
|
+
function stopSpinner(success, text) {
|
|
76
|
+
if (spinnerInterval)
|
|
77
|
+
clearInterval(spinnerInterval);
|
|
78
|
+
process.stdout.write('\x1b[?25h'); // show cursor
|
|
79
|
+
const icon = success ? `${c.green}+${c.reset}` : `${c.red}x${c.reset}`;
|
|
80
|
+
process.stdout.write(`\r${icon} ${text}\n`);
|
|
81
|
+
}
|
|
82
|
+
function banner() {
|
|
83
|
+
console.log();
|
|
84
|
+
console.log(` ${c.cyan}${c.bold}soundcord setup${c.reset}`);
|
|
85
|
+
console.log(` ${c.dim}YouTube streaming for Discord bots${c.reset}`);
|
|
86
|
+
console.log();
|
|
87
|
+
}
|
|
88
|
+
function printBox(title, lines) {
|
|
89
|
+
console.log();
|
|
90
|
+
console.log(` ${c.cyan}${title}${c.reset}`);
|
|
91
|
+
for (const line of lines) {
|
|
92
|
+
console.log(` ${line}`);
|
|
93
|
+
}
|
|
94
|
+
console.log();
|
|
95
|
+
}
|
|
96
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
97
|
+
function ask(question) {
|
|
98
|
+
return new Promise(resolve => {
|
|
99
|
+
rl.question(` ${c.magenta}?${c.reset} ${question} ${c.dim}(y/n)${c.reset} `, answer => {
|
|
100
|
+
resolve(answer.toLowerCase().startsWith('y'));
|
|
101
|
+
});
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
function hasCmd(cmd) {
|
|
105
|
+
try {
|
|
106
|
+
(0, child_process_1.execSync)(isWin ? `where ${cmd}` : `which ${cmd}`, { stdio: 'ignore' });
|
|
107
|
+
return true;
|
|
108
|
+
}
|
|
109
|
+
catch {
|
|
110
|
+
return false;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
function detectPackageManager() {
|
|
114
|
+
if (isWin) {
|
|
115
|
+
if (hasCmd('choco'))
|
|
116
|
+
return 'choco';
|
|
117
|
+
return null;
|
|
118
|
+
}
|
|
119
|
+
if (isMac) {
|
|
120
|
+
if (hasCmd('brew'))
|
|
121
|
+
return 'brew';
|
|
122
|
+
return null;
|
|
123
|
+
}
|
|
124
|
+
// linux
|
|
125
|
+
if (hasCmd('apt'))
|
|
126
|
+
return 'apt';
|
|
127
|
+
if (hasCmd('dnf'))
|
|
128
|
+
return 'dnf';
|
|
129
|
+
if (hasCmd('pacman'))
|
|
130
|
+
return 'pacman';
|
|
131
|
+
if (hasCmd('brew'))
|
|
132
|
+
return 'brew'; // linuxbrew
|
|
133
|
+
return null;
|
|
134
|
+
}
|
|
135
|
+
async function downloadFile(url, dest) {
|
|
136
|
+
return new Promise((resolve, reject) => {
|
|
137
|
+
if (isWin) {
|
|
138
|
+
(0, child_process_1.exec)(`powershell -Command "Invoke-WebRequest -Uri '${url}' -OutFile '${dest}'"`, { timeout: 120000 }, (err) => err ? reject(err) : resolve());
|
|
139
|
+
}
|
|
140
|
+
else {
|
|
141
|
+
(0, child_process_1.exec)(`curl -fsSL "${url}" -o "${dest}"`, { timeout: 120000 }, (err) => err ? reject(err) : resolve());
|
|
142
|
+
}
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
async function installYtdlp() {
|
|
146
|
+
const pm = detectPackageManager();
|
|
147
|
+
// try package manager first
|
|
148
|
+
if (pm) {
|
|
149
|
+
startSpinner(`Installing yt-dlp via ${pm}...`);
|
|
150
|
+
try {
|
|
151
|
+
const cmds = {
|
|
152
|
+
apt: 'sudo apt update && sudo apt install -y yt-dlp',
|
|
153
|
+
dnf: 'sudo dnf install -y yt-dlp',
|
|
154
|
+
pacman: 'sudo pacman -S --noconfirm yt-dlp',
|
|
155
|
+
brew: 'brew install yt-dlp',
|
|
156
|
+
choco: 'choco install yt-dlp -y',
|
|
157
|
+
};
|
|
158
|
+
(0, child_process_1.execSync)(cmds[pm], { stdio: 'ignore', timeout: 300000 });
|
|
159
|
+
stopSpinner(true, 'yt-dlp installed');
|
|
160
|
+
return true;
|
|
161
|
+
}
|
|
162
|
+
catch (err) {
|
|
163
|
+
stopSpinner(false, `${pm} install failed, trying direct download...`);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
// fallback: direct download
|
|
167
|
+
startSpinner('Downloading yt-dlp...');
|
|
168
|
+
fs.mkdirSync(installDir, { recursive: true });
|
|
169
|
+
const filename = isWin ? 'yt-dlp.exe' : 'yt-dlp';
|
|
170
|
+
const dest = path.join(installDir, filename);
|
|
171
|
+
const url = isWin
|
|
172
|
+
? 'https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp.exe'
|
|
173
|
+
: 'https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp';
|
|
174
|
+
try {
|
|
175
|
+
await downloadFile(url, dest);
|
|
176
|
+
if (!isWin) {
|
|
177
|
+
fs.chmodSync(dest, 0o755);
|
|
178
|
+
}
|
|
179
|
+
stopSpinner(true, `yt-dlp installed to ${dest}`);
|
|
180
|
+
return true;
|
|
181
|
+
}
|
|
182
|
+
catch (err) {
|
|
183
|
+
stopSpinner(false, `Download failed: ${err.message}`);
|
|
184
|
+
console.log(` ${c.dim}Manual install: pip install yt-dlp${c.reset}`);
|
|
185
|
+
return false;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
async function installFfmpeg() {
|
|
189
|
+
const pm = detectPackageManager();
|
|
190
|
+
if (pm && pm !== 'choco') {
|
|
191
|
+
startSpinner(`Installing ffmpeg via ${pm}...`);
|
|
192
|
+
try {
|
|
193
|
+
const cmds = {
|
|
194
|
+
apt: 'sudo apt update && sudo apt install -y ffmpeg',
|
|
195
|
+
dnf: 'sudo dnf install -y ffmpeg',
|
|
196
|
+
pacman: 'sudo pacman -S --noconfirm ffmpeg',
|
|
197
|
+
brew: 'brew install ffmpeg',
|
|
198
|
+
};
|
|
199
|
+
if (cmds[pm]) {
|
|
200
|
+
(0, child_process_1.execSync)(cmds[pm], { stdio: 'ignore', timeout: 600000 });
|
|
201
|
+
stopSpinner(true, 'ffmpeg installed');
|
|
202
|
+
return true;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
catch (err) {
|
|
206
|
+
stopSpinner(false, `${pm} install failed`);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
if (isWin) {
|
|
210
|
+
// windows: download ffmpeg essentials
|
|
211
|
+
const tmp = path.join(os.tmpdir(), 'ffmpeg.zip');
|
|
212
|
+
const extract = path.join(os.tmpdir(), 'ffmpeg_extract');
|
|
213
|
+
try {
|
|
214
|
+
startSpinner('Downloading ffmpeg (this may take a while)...');
|
|
215
|
+
await downloadFile('https://www.gyan.dev/ffmpeg/builds/ffmpeg-release-essentials.zip', tmp);
|
|
216
|
+
stopSpinner(true, 'Download complete');
|
|
217
|
+
startSpinner('Extracting...');
|
|
218
|
+
(0, child_process_1.execSync)(`powershell -Command "Expand-Archive -Path '${tmp}' -DestinationPath '${extract}' -Force"`, { stdio: 'ignore' });
|
|
219
|
+
fs.mkdirSync(installDir, { recursive: true });
|
|
220
|
+
const folders = fs.readdirSync(extract).filter(f => f.startsWith('ffmpeg-'));
|
|
221
|
+
if (folders.length > 0) {
|
|
222
|
+
const binSrc = path.join(extract, folders[0], 'bin');
|
|
223
|
+
for (const f of fs.readdirSync(binSrc)) {
|
|
224
|
+
fs.copyFileSync(path.join(binSrc, f), path.join(installDir, f));
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
// cleanup
|
|
228
|
+
try {
|
|
229
|
+
fs.rmSync(tmp, { force: true });
|
|
230
|
+
fs.rmSync(extract, { recursive: true, force: true });
|
|
231
|
+
}
|
|
232
|
+
catch {
|
|
233
|
+
// ignore cleanup errors
|
|
234
|
+
}
|
|
235
|
+
stopSpinner(true, `ffmpeg installed to ${installDir}`);
|
|
236
|
+
return true;
|
|
237
|
+
}
|
|
238
|
+
catch (err) {
|
|
239
|
+
stopSpinner(false, `Failed: ${err.message}`);
|
|
240
|
+
console.log(` ${c.dim}Manual install: https://ffmpeg.org/download.html${c.reset}`);
|
|
241
|
+
return false;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
// unix without package manager
|
|
245
|
+
console.log(` ${c.yellow}!${c.reset} No supported package manager found`);
|
|
246
|
+
console.log(` ${c.dim}Install ffmpeg manually: https://ffmpeg.org/download.html${c.reset}`);
|
|
247
|
+
return false;
|
|
248
|
+
}
|
|
249
|
+
async function main() {
|
|
250
|
+
console.clear();
|
|
251
|
+
banner();
|
|
252
|
+
console.log(` ${c.bold}Checking dependencies...${c.reset}\n`);
|
|
253
|
+
const ytdlpPaths = isWin
|
|
254
|
+
? ['yt-dlp', path.join(installDir, 'yt-dlp.exe')]
|
|
255
|
+
: ['yt-dlp', path.join(installDir, 'yt-dlp')];
|
|
256
|
+
const ffmpegPaths = isWin
|
|
257
|
+
? ['ffmpeg', path.join(installDir, 'ffmpeg.exe')]
|
|
258
|
+
: ['ffmpeg'];
|
|
259
|
+
const hasYtdlp = hasCmd('yt-dlp') || ytdlpPaths.some(p => fs.existsSync(p));
|
|
260
|
+
const hasFfmpeg = hasCmd('ffmpeg') || ffmpegPaths.some(p => fs.existsSync(p));
|
|
261
|
+
console.log(` ${hasYtdlp ? c.green + '+' : c.red + 'x'}${c.reset} yt-dlp`);
|
|
262
|
+
console.log(` ${hasFfmpeg ? c.green + '+' : c.red + 'x'}${c.reset} ffmpeg`);
|
|
263
|
+
console.log();
|
|
264
|
+
if (hasYtdlp && hasFfmpeg) {
|
|
265
|
+
printBox('Ready!', [
|
|
266
|
+
`${c.green}All dependencies installed${c.reset}`,
|
|
267
|
+
'',
|
|
268
|
+
`${c.dim}import { YouTube } from 'soundcord'${c.reset}`,
|
|
269
|
+
]);
|
|
270
|
+
rl.close();
|
|
271
|
+
return;
|
|
272
|
+
}
|
|
273
|
+
const missing = [];
|
|
274
|
+
if (!hasYtdlp)
|
|
275
|
+
missing.push('yt-dlp');
|
|
276
|
+
if (!hasFfmpeg)
|
|
277
|
+
missing.push('ffmpeg');
|
|
278
|
+
console.log(` ${c.yellow}!${c.reset} Missing: ${c.bold}${missing.join(', ')}${c.reset}\n`);
|
|
279
|
+
if (!hasYtdlp && await ask('Install yt-dlp?')) {
|
|
280
|
+
console.log();
|
|
281
|
+
await installYtdlp();
|
|
282
|
+
}
|
|
283
|
+
if (!hasFfmpeg && await ask('Install ffmpeg?')) {
|
|
284
|
+
console.log();
|
|
285
|
+
await installFfmpeg();
|
|
286
|
+
}
|
|
287
|
+
// show PATH instructions if needed
|
|
288
|
+
if (isWin && installDir !== 'C:\\Windows\\System32') {
|
|
289
|
+
const inPath = (process.env.PATH || '').toLowerCase().includes(installDir.toLowerCase());
|
|
290
|
+
if (!inPath) {
|
|
291
|
+
printBox('Add to PATH', [
|
|
292
|
+
`Add this folder to your system PATH:`,
|
|
293
|
+
`${c.cyan}${installDir}${c.reset}`,
|
|
294
|
+
'',
|
|
295
|
+
`Then restart your terminal.`,
|
|
296
|
+
]);
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
printBox('Usage', [
|
|
300
|
+
`${c.dim}npm install soundcord${c.reset}`,
|
|
301
|
+
'',
|
|
302
|
+
`${c.cyan}import { YouTube } from 'soundcord'${c.reset}`,
|
|
303
|
+
`${c.cyan}const yt = new YouTube()${c.reset}`,
|
|
304
|
+
]);
|
|
305
|
+
rl.close();
|
|
306
|
+
}
|
|
307
|
+
main().catch(err => {
|
|
308
|
+
console.error(`\n ${c.red}Error:${c.reset} ${err.message}\n`);
|
|
309
|
+
process.exit(1);
|
|
310
|
+
});
|
|
311
|
+
//# sourceMappingURL=setup.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"setup.js","sourceRoot":"","sources":["../src/setup.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
interface DecipherFunction {
|
|
2
|
+
(signature: string): string;
|
|
3
|
+
}
|
|
4
|
+
export declare function getDecipherFunction(html: string): Promise<DecipherFunction>;
|
|
5
|
+
export declare function decodeSignatureCipher(signatureCipher: string, decipher: DecipherFunction): string;
|
|
6
|
+
export {};
|
|
7
|
+
//# sourceMappingURL=signature.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"signature.d.ts","sourceRoot":"","sources":["../src/signature.ts"],"names":[],"mappings":"AAEA,UAAU,gBAAgB;IACxB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAAC;CAC7B;AAKD,wBAAsB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC,CA8BjF;AAsHD,wBAAgB,qBAAqB,CAAC,eAAe,EAAE,MAAM,EAAE,QAAQ,EAAE,gBAAgB,GAAG,MAAM,CAYjG"}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getDecipherFunction = getDecipherFunction;
|
|
4
|
+
exports.decodeSignatureCipher = decodeSignatureCipher;
|
|
5
|
+
const USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36';
|
|
6
|
+
let cachedDecipher = null;
|
|
7
|
+
let cachedPlayerUrl = null;
|
|
8
|
+
async function getDecipherFunction(html) {
|
|
9
|
+
// Extraire l'URL du player JS
|
|
10
|
+
const playerUrlMatch = html.match(/\/s\/player\/[^"]+\/player_ias\.vflset\/[^"]+\/base\.js/);
|
|
11
|
+
if (!playerUrlMatch) {
|
|
12
|
+
throw new Error('Impossible de trouver le player JS');
|
|
13
|
+
}
|
|
14
|
+
const playerUrl = 'https://www.youtube.com' + playerUrlMatch[0];
|
|
15
|
+
// Utiliser le cache si même player
|
|
16
|
+
if (cachedDecipher && cachedPlayerUrl === playerUrl) {
|
|
17
|
+
return cachedDecipher;
|
|
18
|
+
}
|
|
19
|
+
// Télécharger le player JS
|
|
20
|
+
const response = await fetch(playerUrl, {
|
|
21
|
+
headers: { 'User-Agent': USER_AGENT }
|
|
22
|
+
});
|
|
23
|
+
if (!response.ok) {
|
|
24
|
+
throw new Error(`Erreur téléchargement player: HTTP ${response.status}`);
|
|
25
|
+
}
|
|
26
|
+
const playerJs = await response.text();
|
|
27
|
+
// Extraire la fonction de déchiffrement
|
|
28
|
+
cachedDecipher = extractDecipherFunction(playerJs);
|
|
29
|
+
cachedPlayerUrl = playerUrl;
|
|
30
|
+
return cachedDecipher;
|
|
31
|
+
}
|
|
32
|
+
function extractDecipherFunction(playerJs) {
|
|
33
|
+
// Trouver le nom de la fonction principale
|
|
34
|
+
const funcNameMatch = playerJs.match(/\b([a-zA-Z0-9$]+)\s*=\s*function\(\s*a\s*\)\s*\{\s*a\s*=\s*a\.split\(\s*""\s*\)/);
|
|
35
|
+
if (!funcNameMatch) {
|
|
36
|
+
throw new Error('Impossible de trouver la fonction de déchiffrement');
|
|
37
|
+
}
|
|
38
|
+
const mainFuncName = funcNameMatch[1];
|
|
39
|
+
// Extraire le corps de la fonction principale
|
|
40
|
+
const mainFuncMatch = playerJs.match(new RegExp(escapeRegex(mainFuncName) + '\\s*=\\s*function\\([^)]*\\)\\s*\\{([^}]+)\\}'));
|
|
41
|
+
if (!mainFuncMatch) {
|
|
42
|
+
throw new Error('Impossible d\'extraire la fonction principale');
|
|
43
|
+
}
|
|
44
|
+
const mainFuncBody = mainFuncMatch[1];
|
|
45
|
+
// Trouver l'objet helper utilisé (ex: Xo, $n, etc.)
|
|
46
|
+
const helperMatch = mainFuncBody.match(/([a-zA-Z0-9$]+)\.[a-zA-Z0-9$]+\(/);
|
|
47
|
+
if (!helperMatch) {
|
|
48
|
+
throw new Error('Impossible de trouver l\'objet helper');
|
|
49
|
+
}
|
|
50
|
+
const helperName = helperMatch[1];
|
|
51
|
+
// Extraire l'objet helper
|
|
52
|
+
const helperMatch2 = playerJs.match(new RegExp('var\\s+' + escapeRegex(helperName) + '\\s*=\\s*\\{([\\s\\S]*?)\\};'));
|
|
53
|
+
if (!helperMatch2) {
|
|
54
|
+
throw new Error('Impossible d\'extraire l\'objet helper');
|
|
55
|
+
}
|
|
56
|
+
const helperBody = helperMatch2[1];
|
|
57
|
+
// Parser les méthodes helper
|
|
58
|
+
const helpers = parseHelperMethods(helperBody);
|
|
59
|
+
// Créer la fonction de déchiffrement
|
|
60
|
+
return createDecipherFunction(mainFuncBody, helperName, helpers);
|
|
61
|
+
}
|
|
62
|
+
function parseHelperMethods(helperBody) {
|
|
63
|
+
const helpers = {};
|
|
64
|
+
// Reverse: fonction qui inverse le tableau
|
|
65
|
+
const reverseMatch = helperBody.match(/([a-zA-Z0-9$]+)\s*:\s*function\s*\(\s*a\s*\)\s*\{\s*a\.reverse\(\)/);
|
|
66
|
+
if (reverseMatch) {
|
|
67
|
+
helpers[reverseMatch[1]] = (arr) => { arr.reverse(); };
|
|
68
|
+
}
|
|
69
|
+
// Splice: fonction qui supprime le premier élément n fois
|
|
70
|
+
const spliceMatch = helperBody.match(/([a-zA-Z0-9$]+)\s*:\s*function\s*\(\s*a\s*,\s*b\s*\)\s*\{\s*a\.splice\(\s*0\s*,\s*b\s*\)/);
|
|
71
|
+
if (spliceMatch) {
|
|
72
|
+
helpers[spliceMatch[1]] = (arr, b) => { arr.splice(0, b); };
|
|
73
|
+
}
|
|
74
|
+
// Swap: fonction qui échange des éléments
|
|
75
|
+
const swapMatch = helperBody.match(/([a-zA-Z0-9$]+)\s*:\s*function\s*\(\s*a\s*,\s*b\s*\)\s*\{\s*var\s+c\s*=\s*a\s*\[\s*0\s*\]/);
|
|
76
|
+
if (swapMatch) {
|
|
77
|
+
helpers[swapMatch[1]] = (arr, b) => {
|
|
78
|
+
const c = arr[0];
|
|
79
|
+
arr[0] = arr[b % arr.length];
|
|
80
|
+
arr[b % arr.length] = c;
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
return helpers;
|
|
84
|
+
}
|
|
85
|
+
function createDecipherFunction(funcBody, helperName, helpers) {
|
|
86
|
+
// Parser les opérations
|
|
87
|
+
const operations = [];
|
|
88
|
+
const regex = new RegExp(escapeRegex(helperName) + '\\.([a-zA-Z0-9$]+)\\(a,(\\d+)\\)', 'g');
|
|
89
|
+
let match;
|
|
90
|
+
while ((match = regex.exec(funcBody)) !== null) {
|
|
91
|
+
operations.push({
|
|
92
|
+
method: match[1],
|
|
93
|
+
arg: parseInt(match[2])
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
// Aussi chercher les appels sans argument (reverse)
|
|
97
|
+
const regex2 = new RegExp(escapeRegex(helperName) + '\\.([a-zA-Z0-9$]+)\\(a\\)', 'g');
|
|
98
|
+
// Reset lastIndex for the new regex
|
|
99
|
+
funcBody.replace(regex2, (_, method) => {
|
|
100
|
+
// Insérer au bon endroit - simplifié ici
|
|
101
|
+
return _;
|
|
102
|
+
});
|
|
103
|
+
return (signature) => {
|
|
104
|
+
const arr = signature.split('');
|
|
105
|
+
for (const op of operations) {
|
|
106
|
+
const helper = helpers[op.method];
|
|
107
|
+
if (helper) {
|
|
108
|
+
helper(arr, op.arg || 0);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
return arr.join('');
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
function escapeRegex(str) {
|
|
115
|
+
return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
116
|
+
}
|
|
117
|
+
function decodeSignatureCipher(signatureCipher, decipher) {
|
|
118
|
+
const params = new URLSearchParams(signatureCipher);
|
|
119
|
+
const url = params.get('url');
|
|
120
|
+
const s = params.get('s');
|
|
121
|
+
const sp = params.get('sp') || 'signature';
|
|
122
|
+
if (!url || !s) {
|
|
123
|
+
throw new Error('signatureCipher invalide');
|
|
124
|
+
}
|
|
125
|
+
const decodedSig = decipher(decodeURIComponent(s));
|
|
126
|
+
return `${decodeURIComponent(url)}&${sp}=${encodeURIComponent(decodedSig)}`;
|
|
127
|
+
}
|
|
128
|
+
//# sourceMappingURL=signature.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"signature.js","sourceRoot":"","sources":["../src/signature.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stream.d.ts","sourceRoot":"","sources":["../src/stream.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAEhF,qBAAa,SAAS;IACpB,OAAO,CAAC,OAAO,CAAU;gBAEb,OAAO,CAAC,EAAE,gBAAgB;IAIhC,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,GAAE,MAAW,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;IAIlE,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC;IAI1C,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IAI7C,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAKlD,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO;IAIlC,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;CAG7C"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stream.js","sourceRoot":"","sources":["../src/stream.ts"],"names":[],"mappings":";;;AAAA,uCAAoC;AAGpC,MAAa,SAAS;IAGpB,YAAY,OAA0B;QACpC,IAAI,CAAC,OAAO,GAAG,IAAI,iBAAO,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAC/C,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,KAAa,EAAE,QAAgB,EAAE;QAC5C,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;IAC3C,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,KAAa;QACzB,OAAO,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IACrC,CAAC;IAED,KAAK,CAAC,SAAS,CAAC,KAAa;QAC3B,OAAO,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IACvC,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,KAAa;QAC9B,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QAC3C,OAAO,MAAM,CAAC,GAAG,CAAC;IACpB,CAAC;IAED,UAAU,CAAC,KAAa;QACtB,OAAO,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;IACxC,CAAC;IAED,cAAc,CAAC,KAAa;QAC1B,OAAO,IAAI,CAAC,OAAO,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;IAC5C,CAAC;CACF;AA/BD,8BA+BC"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
export interface VideoInfo {
|
|
2
|
+
id: string;
|
|
3
|
+
title: string;
|
|
4
|
+
author: string;
|
|
5
|
+
duration: number;
|
|
6
|
+
thumbnail: string;
|
|
7
|
+
url: string;
|
|
8
|
+
}
|
|
9
|
+
export interface SearchResult {
|
|
10
|
+
id: string;
|
|
11
|
+
title: string;
|
|
12
|
+
author: string;
|
|
13
|
+
duration: number;
|
|
14
|
+
thumbnail: string;
|
|
15
|
+
}
|
|
16
|
+
export interface StreamInfo {
|
|
17
|
+
url: string;
|
|
18
|
+
mimeType: string;
|
|
19
|
+
bitrate: number;
|
|
20
|
+
}
|
|
21
|
+
export interface YouTubeOptions {
|
|
22
|
+
/** request timeout in ms (default: 15000) */
|
|
23
|
+
timeout?: number;
|
|
24
|
+
/** minimum video duration in seconds to include in search results (default: 0) */
|
|
25
|
+
minDuration?: number;
|
|
26
|
+
/** how long to cache stream URLs in ms (default: 300000 = 5min) */
|
|
27
|
+
cacheTTL?: number;
|
|
28
|
+
/** custom path to yt-dlp binary */
|
|
29
|
+
ytdlpPath?: string;
|
|
30
|
+
}
|
|
31
|
+
export declare class YouTubeError extends Error {
|
|
32
|
+
code: 'PARSE_ERROR' | 'NETWORK_ERROR' | 'NOT_FOUND' | 'YTDLP_MISSING' | 'RATE_LIMITED';
|
|
33
|
+
cause?: Error | undefined;
|
|
34
|
+
constructor(message: string, code: 'PARSE_ERROR' | 'NETWORK_ERROR' | 'NOT_FOUND' | 'YTDLP_MISSING' | 'RATE_LIMITED', cause?: Error | undefined);
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,UAAU;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,cAAc;IAC7B,6CAA6C;IAC7C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,kFAAkF;IAClF,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,mEAAmE;IACnE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,mCAAmC;IACnC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,qBAAa,YAAa,SAAQ,KAAK;IAG5B,IAAI,EAAE,aAAa,GAAG,eAAe,GAAG,WAAW,GAAG,eAAe,GAAG,cAAc;IACtF,KAAK,CAAC,EAAE,KAAK;gBAFpB,OAAO,EAAE,MAAM,EACR,IAAI,EAAE,aAAa,GAAG,eAAe,GAAG,WAAW,GAAG,eAAe,GAAG,cAAc,EACtF,KAAK,CAAC,EAAE,KAAK,YAAA;CAKvB"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.YouTubeError = void 0;
|
|
4
|
+
class YouTubeError extends Error {
|
|
5
|
+
constructor(message, code, cause) {
|
|
6
|
+
super(message);
|
|
7
|
+
this.code = code;
|
|
8
|
+
this.cause = cause;
|
|
9
|
+
this.name = 'YouTubeError';
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
exports.YouTubeError = YouTubeError;
|
|
13
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":";;;AAkCA,MAAa,YAAa,SAAQ,KAAK;IACrC,YACE,OAAe,EACR,IAAsF,EACtF,KAAa;QAEpB,KAAK,CAAC,OAAO,CAAC,CAAC;QAHR,SAAI,GAAJ,IAAI,CAAkF;QACtF,UAAK,GAAL,KAAK,CAAQ;QAGpB,IAAI,CAAC,IAAI,GAAG,cAAc,CAAC;IAC7B,CAAC;CACF;AATD,oCASC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { VideoInfo, SearchResult, StreamInfo, YouTubeOptions } from './types';
|
|
2
|
+
export declare class YouTube {
|
|
3
|
+
private timeout;
|
|
4
|
+
private minDuration;
|
|
5
|
+
private cacheTTL;
|
|
6
|
+
private ytdlp;
|
|
7
|
+
private ytdlpReady;
|
|
8
|
+
constructor(options?: YouTubeOptions);
|
|
9
|
+
private findYtdlp;
|
|
10
|
+
search(query: string, limit?: number): Promise<SearchResult[]>;
|
|
11
|
+
private webSearch;
|
|
12
|
+
private ytdlpSearch;
|
|
13
|
+
getInfo(input: string): Promise<VideoInfo>;
|
|
14
|
+
private webInfo;
|
|
15
|
+
private ytdlpInfo;
|
|
16
|
+
getStream(input: string): Promise<StreamInfo>;
|
|
17
|
+
isValidUrl(url: string): boolean;
|
|
18
|
+
extractId(input: string): string | null;
|
|
19
|
+
private parseDur;
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=youtube.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"youtube.d.ts","sourceRoot":"","sources":["../src/youtube.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,UAAU,EAAE,cAAc,EAAgB,MAAM,SAAS,CAAC;AAsC5F,qBAAa,OAAO;IAClB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,KAAK,CAAuB;IACpC,OAAO,CAAC,UAAU,CAAgB;gBAEtB,OAAO,GAAE,cAAmB;YAc1B,SAAS;IAgBjB,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,SAAK,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;YA8BlD,SAAS;YAqDT,WAAW;IAkBnB,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC;YA8BlC,OAAO;YA4CP,SAAS;IAgBjB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IA+BnD,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAIhC,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAIvC,OAAO,CAAC,QAAQ;CAMjB"}
|
package/dist/youtube.js
ADDED
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.YouTube = void 0;
|
|
4
|
+
const types_1 = require("./types");
|
|
5
|
+
const child_process_1 = require("child_process");
|
|
6
|
+
const util_1 = require("util");
|
|
7
|
+
const execAsync = (0, util_1.promisify)(child_process_1.exec);
|
|
8
|
+
// rotate user agents to reduce detection
|
|
9
|
+
const USER_AGENTS = [
|
|
10
|
+
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36',
|
|
11
|
+
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36',
|
|
12
|
+
'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36',
|
|
13
|
+
];
|
|
14
|
+
const streamCache = new Map();
|
|
15
|
+
// basic rate limit: track last request time
|
|
16
|
+
let lastRequestTime = 0;
|
|
17
|
+
const MIN_REQUEST_INTERVAL = 500; // ms between requests
|
|
18
|
+
function getRandomUA() {
|
|
19
|
+
return USER_AGENTS[Math.floor(Math.random() * USER_AGENTS.length)];
|
|
20
|
+
}
|
|
21
|
+
// sanitize input for shell commands to prevent injection
|
|
22
|
+
function escapeShellArg(arg) {
|
|
23
|
+
// remove any characters that could be dangerous
|
|
24
|
+
return arg.replace(/[;&|`$(){}[\]<>\\!*?#~'"]/g, '');
|
|
25
|
+
}
|
|
26
|
+
async function rateLimit() {
|
|
27
|
+
const now = Date.now();
|
|
28
|
+
const elapsed = now - lastRequestTime;
|
|
29
|
+
if (elapsed < MIN_REQUEST_INTERVAL) {
|
|
30
|
+
await new Promise(r => setTimeout(r, MIN_REQUEST_INTERVAL - elapsed));
|
|
31
|
+
}
|
|
32
|
+
lastRequestTime = Date.now();
|
|
33
|
+
}
|
|
34
|
+
class YouTube {
|
|
35
|
+
constructor(options = {}) {
|
|
36
|
+
this.ytdlp = null;
|
|
37
|
+
this.timeout = options.timeout ?? 15000;
|
|
38
|
+
this.minDuration = options.minDuration ?? 0;
|
|
39
|
+
this.cacheTTL = options.cacheTTL ?? 5 * 60 * 1000;
|
|
40
|
+
// allow custom ytdlp path or auto-detect
|
|
41
|
+
if (options.ytdlpPath) {
|
|
42
|
+
this.ytdlp = options.ytdlpPath;
|
|
43
|
+
this.ytdlpReady = Promise.resolve();
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
this.ytdlpReady = this.findYtdlp();
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
async findYtdlp() {
|
|
50
|
+
const paths = process.platform === 'win32'
|
|
51
|
+
? ['yt-dlp', 'C:\\ffmpeg\\bin\\yt-dlp.exe', './yt-dlp.exe']
|
|
52
|
+
: ['yt-dlp', '/usr/local/bin/yt-dlp', './yt-dlp'];
|
|
53
|
+
for (const p of paths) {
|
|
54
|
+
try {
|
|
55
|
+
await execAsync(`"${p}" --version`);
|
|
56
|
+
this.ytdlp = p;
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
catch (err) {
|
|
60
|
+
// try next path
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
async search(query, limit = 10) {
|
|
65
|
+
await this.ytdlpReady;
|
|
66
|
+
let webError;
|
|
67
|
+
try {
|
|
68
|
+
return await this.webSearch(query, limit);
|
|
69
|
+
}
|
|
70
|
+
catch (err) {
|
|
71
|
+
webError = err;
|
|
72
|
+
}
|
|
73
|
+
// fallback to yt-dlp
|
|
74
|
+
if (this.ytdlp) {
|
|
75
|
+
try {
|
|
76
|
+
return await this.ytdlpSearch(query, limit);
|
|
77
|
+
}
|
|
78
|
+
catch (err) {
|
|
79
|
+
throw new types_1.YouTubeError(`search failed: web (${webError?.message}), yt-dlp (${err.message})`, 'NETWORK_ERROR', err);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
throw new types_1.YouTubeError('search failed and yt-dlp not available', 'YTDLP_MISSING', webError);
|
|
83
|
+
}
|
|
84
|
+
async webSearch(query, limit) {
|
|
85
|
+
await rateLimit();
|
|
86
|
+
const ctrl = new AbortController();
|
|
87
|
+
const timer = setTimeout(() => ctrl.abort(), this.timeout);
|
|
88
|
+
try {
|
|
89
|
+
const res = await fetch(`https://www.youtube.com/results?search_query=${encodeURIComponent(query)}`, {
|
|
90
|
+
signal: ctrl.signal,
|
|
91
|
+
headers: { 'User-Agent': getRandomUA(), 'Accept-Language': 'en-US,en;q=0.9' }
|
|
92
|
+
});
|
|
93
|
+
clearTimeout(timer);
|
|
94
|
+
if (res.status === 429) {
|
|
95
|
+
throw new types_1.YouTubeError('rate limited by YouTube', 'RATE_LIMITED');
|
|
96
|
+
}
|
|
97
|
+
if (!res.ok) {
|
|
98
|
+
throw new types_1.YouTubeError(`http ${res.status}`, 'NETWORK_ERROR');
|
|
99
|
+
}
|
|
100
|
+
const html = await res.text();
|
|
101
|
+
const m = html.match(/var ytInitialData = (.+?);<\/script>/);
|
|
102
|
+
if (!m) {
|
|
103
|
+
throw new types_1.YouTubeError('failed to parse YouTube response', 'PARSE_ERROR');
|
|
104
|
+
}
|
|
105
|
+
const data = JSON.parse(m[1]);
|
|
106
|
+
const contents = data?.contents?.twoColumnSearchResultsRenderer?.primaryContents
|
|
107
|
+
?.sectionListRenderer?.contents?.[0]?.itemSectionRenderer?.contents || [];
|
|
108
|
+
const results = [];
|
|
109
|
+
for (const item of contents) {
|
|
110
|
+
if (results.length >= limit)
|
|
111
|
+
break;
|
|
112
|
+
const v = item?.videoRenderer;
|
|
113
|
+
if (!v?.lengthText?.simpleText)
|
|
114
|
+
continue;
|
|
115
|
+
const dur = this.parseDur(v.lengthText.simpleText);
|
|
116
|
+
if (dur < this.minDuration)
|
|
117
|
+
continue;
|
|
118
|
+
results.push({
|
|
119
|
+
id: v.videoId,
|
|
120
|
+
title: v.title?.runs?.[0]?.text || '',
|
|
121
|
+
author: v.ownerText?.runs?.[0]?.text || '',
|
|
122
|
+
duration: dur,
|
|
123
|
+
thumbnail: v.thumbnail?.thumbnails?.[0]?.url || ''
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
return results;
|
|
127
|
+
}
|
|
128
|
+
finally {
|
|
129
|
+
clearTimeout(timer);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
async ytdlpSearch(query, limit) {
|
|
133
|
+
const safeQuery = escapeShellArg(query);
|
|
134
|
+
const { stdout } = await execAsync(`"${this.ytdlp}" "ytsearch${limit}:${safeQuery}" --flat-playlist --no-warnings --print "%(id)s|%(title)s|%(channel)s|%(duration)s|%(thumbnail)s"`, { maxBuffer: 10 * 1024 * 1024 });
|
|
135
|
+
const results = [];
|
|
136
|
+
for (const line of stdout.trim().split('\n')) {
|
|
137
|
+
if (!line)
|
|
138
|
+
continue;
|
|
139
|
+
const [id, title, author, dur, thumb] = line.split('|');
|
|
140
|
+
const duration = parseInt(dur) || 0;
|
|
141
|
+
if (duration < this.minDuration)
|
|
142
|
+
continue;
|
|
143
|
+
results.push({ id, title, author: author || '', duration, thumbnail: thumb || '' });
|
|
144
|
+
}
|
|
145
|
+
return results;
|
|
146
|
+
}
|
|
147
|
+
async getInfo(input) {
|
|
148
|
+
await this.ytdlpReady;
|
|
149
|
+
const id = this.extractId(input) || input;
|
|
150
|
+
let webError;
|
|
151
|
+
try {
|
|
152
|
+
return await this.webInfo(id);
|
|
153
|
+
}
|
|
154
|
+
catch (err) {
|
|
155
|
+
webError = err;
|
|
156
|
+
}
|
|
157
|
+
if (this.ytdlp) {
|
|
158
|
+
try {
|
|
159
|
+
return await this.ytdlpInfo(id);
|
|
160
|
+
}
|
|
161
|
+
catch (err) {
|
|
162
|
+
throw new types_1.YouTubeError(`getInfo failed for ${id}`, 'NETWORK_ERROR', err);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
throw new types_1.YouTubeError(`getInfo failed for ${id}: ${webError?.message}`, 'NOT_FOUND', webError);
|
|
166
|
+
}
|
|
167
|
+
async webInfo(id) {
|
|
168
|
+
await rateLimit();
|
|
169
|
+
const ctrl = new AbortController();
|
|
170
|
+
const timer = setTimeout(() => ctrl.abort(), this.timeout);
|
|
171
|
+
try {
|
|
172
|
+
const res = await fetch(`https://www.youtube.com/watch?v=${id}`, {
|
|
173
|
+
signal: ctrl.signal,
|
|
174
|
+
headers: { 'User-Agent': getRandomUA(), 'Accept-Language': 'en-US,en;q=0.9' }
|
|
175
|
+
});
|
|
176
|
+
clearTimeout(timer);
|
|
177
|
+
if (res.status === 429) {
|
|
178
|
+
throw new types_1.YouTubeError('rate limited by YouTube', 'RATE_LIMITED');
|
|
179
|
+
}
|
|
180
|
+
if (!res.ok) {
|
|
181
|
+
throw new types_1.YouTubeError(`http ${res.status}`, 'NETWORK_ERROR');
|
|
182
|
+
}
|
|
183
|
+
const html = await res.text();
|
|
184
|
+
const m = html.match(/var ytInitialPlayerResponse = ({.+?});(?:var|<\/script>)/s);
|
|
185
|
+
if (!m) {
|
|
186
|
+
throw new types_1.YouTubeError('failed to parse video page', 'PARSE_ERROR');
|
|
187
|
+
}
|
|
188
|
+
const d = JSON.parse(m[1])?.videoDetails;
|
|
189
|
+
if (!d) {
|
|
190
|
+
throw new types_1.YouTubeError('video not found or unavailable', 'NOT_FOUND');
|
|
191
|
+
}
|
|
192
|
+
return {
|
|
193
|
+
id,
|
|
194
|
+
title: d.title || '',
|
|
195
|
+
author: d.author || '',
|
|
196
|
+
duration: parseInt(d.lengthSeconds || '0'),
|
|
197
|
+
thumbnail: d.thumbnail?.thumbnails?.[0]?.url || '',
|
|
198
|
+
url: `https://www.youtube.com/watch?v=${id}`
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
finally {
|
|
202
|
+
clearTimeout(timer);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
async ytdlpInfo(id) {
|
|
206
|
+
const { stdout } = await execAsync(`"${this.ytdlp}" "https://www.youtube.com/watch?v=${id}" --no-playlist --no-warnings --print "%(title)s|%(channel)s|%(duration)s|%(thumbnail)s"`, { maxBuffer: 1024 * 1024 });
|
|
207
|
+
const [title, author, dur, thumb] = stdout.trim().split('|');
|
|
208
|
+
return {
|
|
209
|
+
id,
|
|
210
|
+
title,
|
|
211
|
+
author: author || '',
|
|
212
|
+
duration: parseInt(dur) || 0,
|
|
213
|
+
thumbnail: thumb || '',
|
|
214
|
+
url: `https://www.youtube.com/watch?v=${id}`
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
async getStream(input) {
|
|
218
|
+
await this.ytdlpReady;
|
|
219
|
+
const id = this.extractId(input) || input;
|
|
220
|
+
// check cache
|
|
221
|
+
const cached = streamCache.get(id);
|
|
222
|
+
if (cached && Date.now() - cached.ts < this.cacheTTL) {
|
|
223
|
+
return { url: cached.url, mimeType: 'audio/webm', bitrate: 128000 };
|
|
224
|
+
}
|
|
225
|
+
if (!this.ytdlp) {
|
|
226
|
+
throw new types_1.YouTubeError('yt-dlp required for streaming - install from https://github.com/yt-dlp/yt-dlp', 'YTDLP_MISSING');
|
|
227
|
+
}
|
|
228
|
+
const { stdout } = await execAsync(`"${this.ytdlp}" "https://www.youtube.com/watch?v=${id}" -f bestaudio/best -g --no-playlist --no-warnings`, { maxBuffer: 1024 * 1024 });
|
|
229
|
+
const url = stdout.trim();
|
|
230
|
+
if (!url) {
|
|
231
|
+
throw new types_1.YouTubeError('no stream url returned', 'NOT_FOUND');
|
|
232
|
+
}
|
|
233
|
+
streamCache.set(id, { url, ts: Date.now() });
|
|
234
|
+
return { url, mimeType: 'audio/webm', bitrate: 128000 };
|
|
235
|
+
}
|
|
236
|
+
isValidUrl(url) {
|
|
237
|
+
return /(?:youtube\.com\/watch\?v=|youtu\.be\/)[\w-]{11}/.test(url);
|
|
238
|
+
}
|
|
239
|
+
extractId(input) {
|
|
240
|
+
return input.match(/(?:youtube\.com\/watch\?v=|youtu\.be\/)([\w-]{11})/)?.[1] || null;
|
|
241
|
+
}
|
|
242
|
+
parseDur(str) {
|
|
243
|
+
const p = str.split(':').map(Number);
|
|
244
|
+
if (p.length === 2)
|
|
245
|
+
return p[0] * 60 + p[1];
|
|
246
|
+
if (p.length === 3)
|
|
247
|
+
return p[0] * 3600 + p[1] * 60 + p[2];
|
|
248
|
+
return 0;
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
exports.YouTube = YouTube;
|
|
252
|
+
//# sourceMappingURL=youtube.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"youtube.js","sourceRoot":"","sources":["../src/youtube.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "soundcord",
|
|
3
|
+
"version": "1.0.1",
|
|
4
|
+
"description": "Simple YouTube audio streaming for Discord bots",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"bin": {
|
|
8
|
+
"soundcord-setup": "dist/setup.js"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"dist"
|
|
12
|
+
],
|
|
13
|
+
"scripts": {
|
|
14
|
+
"build": "tsc",
|
|
15
|
+
"dev": "tsc --watch",
|
|
16
|
+
"prepublishOnly": "npm run build"
|
|
17
|
+
},
|
|
18
|
+
"keywords": [
|
|
19
|
+
"discord",
|
|
20
|
+
"youtube",
|
|
21
|
+
"music",
|
|
22
|
+
"audio",
|
|
23
|
+
"stream",
|
|
24
|
+
"bot"
|
|
25
|
+
],
|
|
26
|
+
"author": "Shuzo",
|
|
27
|
+
"license": "MIT",
|
|
28
|
+
"devDependencies": {
|
|
29
|
+
"@types/node": "^25.0.10",
|
|
30
|
+
"typescript": "^5.9.3"
|
|
31
|
+
}
|
|
32
|
+
}
|