@ziplayer/plugin 0.1.33 → 0.1.40
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/README.md +180 -180
- package/YTSR_README.md +310 -310
- package/dist/TTSPlugin.js.map +1 -1
- package/dist/YTSRPlugin.d.ts.map +1 -1
- package/dist/YTSRPlugin.js +17 -1
- package/dist/YTSRPlugin.js.map +1 -1
- package/dist/YouTubePlugin.d.ts +15 -6
- package/dist/YouTubePlugin.d.ts.map +1 -1
- package/dist/YouTubePlugin.js +122 -47
- package/dist/YouTubePlugin.js.map +1 -1
- package/dist/utils/progress-bar.d.ts +8 -0
- package/dist/utils/progress-bar.d.ts.map +1 -0
- package/dist/utils/progress-bar.js +24 -0
- package/dist/utils/progress-bar.js.map +1 -0
- package/dist/utils/sabr-stream-factory.d.ts +25 -0
- package/dist/utils/sabr-stream-factory.d.ts.map +1 -0
- package/dist/utils/sabr-stream-factory.js +83 -0
- package/dist/utils/sabr-stream-factory.js.map +1 -0
- package/dist/utils/stream-converter.d.ts +10 -0
- package/dist/utils/stream-converter.d.ts.map +1 -0
- package/dist/utils/stream-converter.js +78 -0
- package/dist/utils/stream-converter.js.map +1 -0
- package/package.json +44 -42
- package/src/SoundCloudPlugin.ts +368 -368
- package/src/SpotifyPlugin.ts +312 -312
- package/src/TTSPlugin.ts +361 -361
- package/src/YTSRPlugin.ts +596 -583
- package/src/YouTubePlugin.ts +620 -528
- package/src/index.ts +103 -103
- package/src/types/googlevideo.d.ts +45 -0
- package/src/utils/sabr-stream-factory.ts +96 -0
- package/src/utils/stream-converter.ts +87 -0
- package/tsconfig.json +23 -23
package/YTSR_README.md
CHANGED
|
@@ -1,310 +1,310 @@
|
|
|
1
|
-
# YTSRPlugin - Plugin Tìm Kiếm Nâng Cao YouTube
|
|
2
|
-
|
|
3
|
-
YTSRPlugin là một plugin mạnh mẽ cho ZiPlayer, cung cấp khả năng tìm kiếm nâng cao trên YouTube mà không cần tạo stream. Plugin
|
|
4
|
-
này sử dụng thư viện `youtube-sr` để tìm kiếm và trích xuất metadata từ YouTube.
|
|
5
|
-
|
|
6
|
-
## ✨ Tính Năng
|
|
7
|
-
|
|
8
|
-
- 🔍 **Tìm kiếm video nâng cao** với nhiều tùy chọn lọc
|
|
9
|
-
- 📋 **Tìm kiếm playlist** và channel
|
|
10
|
-
- 🎯 **Hỗ trợ nhiều loại tìm kiếm**: video, playlist, channel, hoặc tất cả
|
|
11
|
-
- ⏱️ **Lọc theo thời lượng**: short (< 4 phút), medium (4-20 phút), long (> 20 phút)
|
|
12
|
-
- 📅 **Lọc theo ngày upload**: hour, today, week, month, year
|
|
13
|
-
- 📊 **Sắp xếp kết quả**: relevance, uploadDate, viewCount, rating
|
|
14
|
-
- 🔗 **Hỗ trợ URL YouTube** trực tiếp
|
|
15
|
-
- 📱 **Metadata phong phú**: tác giả, lượt xem, mô tả, ngày upload, v.v.
|
|
16
|
-
- 🔄 **Video liên quan**: Tìm kiếm video liên quan cho một video cụ thể
|
|
17
|
-
- 🎵 **Mix Playlist**: Hỗ trợ xử lý YouTube Mix playlists (RD)
|
|
18
|
-
- ⚡ **Không streaming**: Chỉ trả về metadata, không tạo stream
|
|
19
|
-
|
|
20
|
-
## 🚀 Cài Đặt
|
|
21
|
-
|
|
22
|
-
```bash
|
|
23
|
-
npm install youtube-sr
|
|
24
|
-
```
|
|
25
|
-
|
|
26
|
-
## 📖 Cách Sử Dụng
|
|
27
|
-
|
|
28
|
-
### Khởi Tạo Plugin
|
|
29
|
-
|
|
30
|
-
```javascript
|
|
31
|
-
const { YTSRPlugin } = require("ziplayer/plugins");
|
|
32
|
-
const plugin = new YTSRPlugin();
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
### Tìm Kiếm Video Cơ Bản
|
|
36
|
-
|
|
37
|
-
```javascript
|
|
38
|
-
// Tìm kiếm video đơn giản
|
|
39
|
-
const result = await plugin.search("Never Gonna Give You Up", "user123");
|
|
40
|
-
console.log(`Tìm thấy ${result.tracks.length} video`);
|
|
41
|
-
|
|
42
|
-
result.tracks.forEach((track) => {
|
|
43
|
-
console.log(`${track.title} - ${track.metadata?.author}`);
|
|
44
|
-
console.log(`URL: ${track.url}`);
|
|
45
|
-
console.log(`Thời lượng: ${track.duration}s`);
|
|
46
|
-
});
|
|
47
|
-
```
|
|
48
|
-
|
|
49
|
-
### Tìm Kiếm Với Tùy Chọn Nâng Cao
|
|
50
|
-
|
|
51
|
-
```javascript
|
|
52
|
-
// Tìm kiếm với các filter nâng cao
|
|
53
|
-
const advancedResult = await plugin.search("chill music", "user123", {
|
|
54
|
-
limit: 10, // Số lượng kết quả tối đa
|
|
55
|
-
duration: "medium", // Thời lượng: short, medium, long, all
|
|
56
|
-
sortBy: "viewCount", // Sắp xếp: relevance, uploadDate, viewCount, rating
|
|
57
|
-
uploadDate: "month", // Ngày upload: hour, today, week, month, year, all
|
|
58
|
-
type: "video", // Loại: video, playlist, channel, all
|
|
59
|
-
});
|
|
60
|
-
```
|
|
61
|
-
|
|
62
|
-
### Tìm Kiếm Playlist
|
|
63
|
-
|
|
64
|
-
```javascript
|
|
65
|
-
// Tìm kiếm playlist
|
|
66
|
-
const playlistResult = await plugin.searchPlaylist("lofi hip hop", "user123", 5);
|
|
67
|
-
playlistResult.tracks.forEach((track) => {
|
|
68
|
-
console.log(`Playlist: ${track.title}`);
|
|
69
|
-
console.log(`Channel: ${track.metadata?.author}`);
|
|
70
|
-
console.log(`Số video: ${track.metadata?.videoCount}`);
|
|
71
|
-
});
|
|
72
|
-
```
|
|
73
|
-
|
|
74
|
-
### Tìm Kiếm Channel
|
|
75
|
-
|
|
76
|
-
```javascript
|
|
77
|
-
// Tìm kiếm channel
|
|
78
|
-
const channelResult = await plugin.searchChannel("PewDiePie", "user123", 3);
|
|
79
|
-
channelResult.tracks.forEach((track) => {
|
|
80
|
-
console.log(`Channel: ${track.title}`);
|
|
81
|
-
console.log(`Subscribers: ${track.metadata?.subscriberCount}`);
|
|
82
|
-
console.log(`URL: ${track.url}`);
|
|
83
|
-
});
|
|
84
|
-
```
|
|
85
|
-
|
|
86
|
-
### Tìm Kiếm Tất Cả Loại
|
|
87
|
-
|
|
88
|
-
```javascript
|
|
89
|
-
// Tìm kiếm tất cả loại (video, playlist, channel)
|
|
90
|
-
const allResult = await plugin.search("music", "user123", {
|
|
91
|
-
type: "all",
|
|
92
|
-
limit: 15,
|
|
93
|
-
});
|
|
94
|
-
|
|
95
|
-
allResult.tracks.forEach((track) => {
|
|
96
|
-
const type = track.metadata?.type || "video";
|
|
97
|
-
console.log(`[${type.toUpperCase()}] ${track.title}`);
|
|
98
|
-
});
|
|
99
|
-
```
|
|
100
|
-
|
|
101
|
-
### Xử Lý URL YouTube
|
|
102
|
-
|
|
103
|
-
```javascript
|
|
104
|
-
// Xử lý URL YouTube trực tiếp
|
|
105
|
-
const urlResult = await plugin.search("https://www.youtube.com/watch?v=dQw4w9WgXcQ", "user123");
|
|
106
|
-
if (urlResult.tracks.length > 0) {
|
|
107
|
-
const track = urlResult.tracks[0];
|
|
108
|
-
console.log(`Video: ${track.title}`);
|
|
109
|
-
console.log(`Tác giả: ${track.metadata?.author}`);
|
|
110
|
-
}
|
|
111
|
-
```
|
|
112
|
-
|
|
113
|
-
### Lấy Video Theo ID
|
|
114
|
-
|
|
115
|
-
```javascript
|
|
116
|
-
// Lấy video theo ID cụ thể
|
|
117
|
-
const video = await plugin.getVideoById("dQw4w9WgXcQ", "user123");
|
|
118
|
-
if (video) {
|
|
119
|
-
console.log(`Video: ${video.title}`);
|
|
120
|
-
console.log(`Tác giả: ${video.metadata?.author}`);
|
|
121
|
-
console.log(`URL: ${video.url}`);
|
|
122
|
-
}
|
|
123
|
-
```
|
|
124
|
-
|
|
125
|
-
### Lấy Video Liên Quan
|
|
126
|
-
|
|
127
|
-
```javascript
|
|
128
|
-
// Lấy video liên quan cho một video cụ thể
|
|
129
|
-
const relatedTracks = await plugin.getRelatedTracks("https://www.youtube.com/watch?v=dQw4w9WgXcQ", {
|
|
130
|
-
limit: 5, // Số lượng video liên quan tối đa
|
|
131
|
-
offset: 0, // Bỏ qua N video đầu tiên
|
|
132
|
-
history: [currentTrack], // Loại trừ các video đã phát
|
|
133
|
-
});
|
|
134
|
-
|
|
135
|
-
relatedTracks.forEach((track, index) => {
|
|
136
|
-
console.log(`${index + 1}. ${track.title} - ${track.metadata?.author}`);
|
|
137
|
-
});
|
|
138
|
-
```
|
|
139
|
-
|
|
140
|
-
### Xử Lý Mix Playlist (RD)
|
|
141
|
-
|
|
142
|
-
```javascript
|
|
143
|
-
// Xử lý YouTube Mix playlist (RD)
|
|
144
|
-
const mixResult = await plugin.handleMixPlaylist(
|
|
145
|
-
"https://www.youtube.com/watch?v=dQw4w9WgXcQ&list=RDMWGnHCaqxdU&start_radio=1",
|
|
146
|
-
"user123",
|
|
147
|
-
10, // Số lượng track tối đa
|
|
148
|
-
);
|
|
149
|
-
|
|
150
|
-
console.log(`Mix playlist: ${mixResult.playlist?.name}`);
|
|
151
|
-
console.log(`Tìm thấy ${mixResult.tracks.length} track trong Mix`);
|
|
152
|
-
|
|
153
|
-
mixResult.tracks.forEach((track, index) => {
|
|
154
|
-
console.log(`${index + 1}. ${track.title} - ${track.metadata?.author}`);
|
|
155
|
-
});
|
|
156
|
-
```
|
|
157
|
-
|
|
158
|
-
## 📋 API Reference
|
|
159
|
-
|
|
160
|
-
### `search(query, requestedBy, options?)`
|
|
161
|
-
|
|
162
|
-
Tìm kiếm nội dung trên YouTube với các tùy chọn nâng cao.
|
|
163
|
-
|
|
164
|
-
**Tham số:**
|
|
165
|
-
|
|
166
|
-
- `query` (string): Query tìm kiếm hoặc URL YouTube
|
|
167
|
-
- `requestedBy` (string): ID của user yêu cầu tìm kiếm
|
|
168
|
-
- `options` (object, tùy chọn):
|
|
169
|
-
- `limit` (number): Số lượng kết quả tối đa (mặc định: 10)
|
|
170
|
-
- `type` (string): Loại tìm kiếm - "video", "playlist", "channel", "all" (mặc định: "video")
|
|
171
|
-
- `duration` (string): Lọc theo thời lượng - "short", "medium", "long", "all" (mặc định: "all")
|
|
172
|
-
- `sortBy` (string): Sắp xếp - "relevance", "uploadDate", "viewCount", "rating" (mặc định: "relevance")
|
|
173
|
-
- `uploadDate` (string): Lọc theo ngày upload - "hour", "today", "week", "month", "year", "all" (mặc định: "all")
|
|
174
|
-
|
|
175
|
-
**Trả về:** `Promise<SearchResult>`
|
|
176
|
-
|
|
177
|
-
### `searchPlaylist(query, requestedBy, limit?)`
|
|
178
|
-
|
|
179
|
-
Tìm kiếm playlist trên YouTube.
|
|
180
|
-
|
|
181
|
-
**Tham số:**
|
|
182
|
-
|
|
183
|
-
- `query` (string): Query tìm kiếm playlist
|
|
184
|
-
- `requestedBy` (string): ID của user yêu cầu
|
|
185
|
-
- `limit` (number, tùy chọn): Số lượng playlist tối đa (mặc định: 5)
|
|
186
|
-
|
|
187
|
-
**Trả về:** `Promise<SearchResult>`
|
|
188
|
-
|
|
189
|
-
### `searchChannel(query, requestedBy, limit?)`
|
|
190
|
-
|
|
191
|
-
Tìm kiếm channel trên YouTube.
|
|
192
|
-
|
|
193
|
-
**Tham số:**
|
|
194
|
-
|
|
195
|
-
- `query` (string): Query tìm kiếm channel
|
|
196
|
-
- `requestedBy` (string): ID của user yêu cầu
|
|
197
|
-
- `limit` (number, tùy chọn): Số lượng channel tối đa (mặc định: 5)
|
|
198
|
-
|
|
199
|
-
**Trả về:** `Promise<SearchResult>`
|
|
200
|
-
|
|
201
|
-
### `getVideoById(videoId, requestedBy)`
|
|
202
|
-
|
|
203
|
-
Lấy thông tin video theo ID cụ thể.
|
|
204
|
-
|
|
205
|
-
**Tham số:**
|
|
206
|
-
|
|
207
|
-
- `videoId` (string): ID của video YouTube
|
|
208
|
-
- `requestedBy` (string): ID của user yêu cầu
|
|
209
|
-
|
|
210
|
-
**Trả về:** `Promise<Track | null>`
|
|
211
|
-
|
|
212
|
-
### `getRelatedTracks(trackURL, opts?)`
|
|
213
|
-
|
|
214
|
-
Lấy các video liên quan cho một video YouTube cụ thể.
|
|
215
|
-
|
|
216
|
-
**Tham số:**
|
|
217
|
-
|
|
218
|
-
- `trackURL` (string): URL của video YouTube để lấy video liên quan
|
|
219
|
-
- `opts` (object, tùy chọn):
|
|
220
|
-
- `limit` (number): Số lượng video liên quan tối đa (mặc định: 5)
|
|
221
|
-
- `offset` (number): Số lượng video bỏ qua từ đầu (mặc định: 0)
|
|
222
|
-
- `history` (Track[]): Mảng các track để loại trừ khỏi kết quả
|
|
223
|
-
|
|
224
|
-
**Trả về:** `Promise<Track[]>`
|
|
225
|
-
|
|
226
|
-
### `handleMixPlaylist(mixUrl, requestedBy, limit?)`
|
|
227
|
-
|
|
228
|
-
Xử lý YouTube Mix playlist (RD) và tạo danh sách các video liên quan.
|
|
229
|
-
|
|
230
|
-
**Tham số:**
|
|
231
|
-
|
|
232
|
-
- `mixUrl` (string): URL của playlist Mix YouTube
|
|
233
|
-
- `requestedBy` (string): ID của user yêu cầu
|
|
234
|
-
- `limit` (number, tùy chọn): Số lượng track tối đa (mặc định: 10)
|
|
235
|
-
|
|
236
|
-
**Trả về:** `Promise<SearchResult>`
|
|
237
|
-
|
|
238
|
-
### `canHandle(query)`
|
|
239
|
-
|
|
240
|
-
Kiểm tra xem plugin có thể xử lý query này không.
|
|
241
|
-
|
|
242
|
-
**Tham số:**
|
|
243
|
-
|
|
244
|
-
- `query` (string): Query để kiểm tra
|
|
245
|
-
|
|
246
|
-
**Trả về:** `boolean`
|
|
247
|
-
|
|
248
|
-
### `validate(url)`
|
|
249
|
-
|
|
250
|
-
Xác thực URL YouTube.
|
|
251
|
-
|
|
252
|
-
**Tham số:**
|
|
253
|
-
|
|
254
|
-
- `url` (string): URL để xác thực
|
|
255
|
-
|
|
256
|
-
**Trả về:** `boolean`
|
|
257
|
-
|
|
258
|
-
## ⚠️ Lưu Ý Quan Trọng
|
|
259
|
-
|
|
260
|
-
- **KHÔNG hỗ trợ streaming**: Plugin này chỉ dành cho tìm kiếm metadata, không tạo stream audio
|
|
261
|
-
- **KHÔNG hỗ trợ fallback**: Không có phương thức fallback streaming
|
|
262
|
-
- **Chỉ metadata**: Trả về thông tin về video/playlist/channel, không phải audio stream
|
|
263
|
-
- **Sử dụng với plugin khác**: Có thể kết hợp với YouTubePlugin để có cả tìm kiếm nâng cao và streaming
|
|
264
|
-
|
|
265
|
-
## 🔧 Tích Hợp Với Plugin Khác
|
|
266
|
-
|
|
267
|
-
```javascript
|
|
268
|
-
const { YTSRPlugin, YouTubePlugin } = require("ziplayer/plugins");
|
|
269
|
-
|
|
270
|
-
// Sử dụng YTSRPlugin để tìm kiếm nâng cao
|
|
271
|
-
const ytsrPlugin = new YTSRPlugin();
|
|
272
|
-
const searchResult = await ytsrPlugin.search("music", "user123", {
|
|
273
|
-
duration: "medium",
|
|
274
|
-
sortBy: "viewCount",
|
|
275
|
-
});
|
|
276
|
-
|
|
277
|
-
// Lấy video liên quan
|
|
278
|
-
const relatedTracks = await ytsrPlugin.getRelatedTracks(searchResult.tracks[0].url, {
|
|
279
|
-
limit: 3,
|
|
280
|
-
history: searchResult.tracks,
|
|
281
|
-
});
|
|
282
|
-
|
|
283
|
-
// Sử dụng YouTubePlugin để tạo stream
|
|
284
|
-
const youtubePlugin = new YouTubePlugin();
|
|
285
|
-
const stream = await youtubePlugin.getStream(searchResult.tracks[0]);
|
|
286
|
-
```
|
|
287
|
-
|
|
288
|
-
## 🧪 Testing
|
|
289
|
-
|
|
290
|
-
```bash
|
|
291
|
-
# Chạy test cho YTSRPlugin
|
|
292
|
-
npm test tests/plugins/ytsrplugin.test.js
|
|
293
|
-
```
|
|
294
|
-
|
|
295
|
-
## 📝 Ví Dụ Hoàn Chỉnh
|
|
296
|
-
|
|
297
|
-
Xem file `examples/ytsr-example.js` để có ví dụ chi tiết về cách sử dụng plugin.
|
|
298
|
-
|
|
299
|
-
## 🤝 Đóng Góp
|
|
300
|
-
|
|
301
|
-
Nếu bạn muốn đóng góp vào plugin này, vui lòng:
|
|
302
|
-
|
|
303
|
-
1. Fork repository
|
|
304
|
-
2. Tạo branch mới cho feature
|
|
305
|
-
3. Commit changes
|
|
306
|
-
4. Tạo Pull Request
|
|
307
|
-
|
|
308
|
-
## 📄 License
|
|
309
|
-
|
|
310
|
-
MIT License - xem file LICENSE để biết thêm chi tiết.
|
|
1
|
+
# YTSRPlugin - Plugin Tìm Kiếm Nâng Cao YouTube
|
|
2
|
+
|
|
3
|
+
YTSRPlugin là một plugin mạnh mẽ cho ZiPlayer, cung cấp khả năng tìm kiếm nâng cao trên YouTube mà không cần tạo stream. Plugin
|
|
4
|
+
này sử dụng thư viện `youtube-sr` để tìm kiếm và trích xuất metadata từ YouTube.
|
|
5
|
+
|
|
6
|
+
## ✨ Tính Năng
|
|
7
|
+
|
|
8
|
+
- 🔍 **Tìm kiếm video nâng cao** với nhiều tùy chọn lọc
|
|
9
|
+
- 📋 **Tìm kiếm playlist** và channel
|
|
10
|
+
- 🎯 **Hỗ trợ nhiều loại tìm kiếm**: video, playlist, channel, hoặc tất cả
|
|
11
|
+
- ⏱️ **Lọc theo thời lượng**: short (< 4 phút), medium (4-20 phút), long (> 20 phút)
|
|
12
|
+
- 📅 **Lọc theo ngày upload**: hour, today, week, month, year
|
|
13
|
+
- 📊 **Sắp xếp kết quả**: relevance, uploadDate, viewCount, rating
|
|
14
|
+
- 🔗 **Hỗ trợ URL YouTube** trực tiếp
|
|
15
|
+
- 📱 **Metadata phong phú**: tác giả, lượt xem, mô tả, ngày upload, v.v.
|
|
16
|
+
- 🔄 **Video liên quan**: Tìm kiếm video liên quan cho một video cụ thể
|
|
17
|
+
- 🎵 **Mix Playlist**: Hỗ trợ xử lý YouTube Mix playlists (RD)
|
|
18
|
+
- ⚡ **Không streaming**: Chỉ trả về metadata, không tạo stream
|
|
19
|
+
|
|
20
|
+
## 🚀 Cài Đặt
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
npm install youtube-sr
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## 📖 Cách Sử Dụng
|
|
27
|
+
|
|
28
|
+
### Khởi Tạo Plugin
|
|
29
|
+
|
|
30
|
+
```javascript
|
|
31
|
+
const { YTSRPlugin } = require("ziplayer/plugins");
|
|
32
|
+
const plugin = new YTSRPlugin();
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### Tìm Kiếm Video Cơ Bản
|
|
36
|
+
|
|
37
|
+
```javascript
|
|
38
|
+
// Tìm kiếm video đơn giản
|
|
39
|
+
const result = await plugin.search("Never Gonna Give You Up", "user123");
|
|
40
|
+
console.log(`Tìm thấy ${result.tracks.length} video`);
|
|
41
|
+
|
|
42
|
+
result.tracks.forEach((track) => {
|
|
43
|
+
console.log(`${track.title} - ${track.metadata?.author}`);
|
|
44
|
+
console.log(`URL: ${track.url}`);
|
|
45
|
+
console.log(`Thời lượng: ${track.duration}s`);
|
|
46
|
+
});
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### Tìm Kiếm Với Tùy Chọn Nâng Cao
|
|
50
|
+
|
|
51
|
+
```javascript
|
|
52
|
+
// Tìm kiếm với các filter nâng cao
|
|
53
|
+
const advancedResult = await plugin.search("chill music", "user123", {
|
|
54
|
+
limit: 10, // Số lượng kết quả tối đa
|
|
55
|
+
duration: "medium", // Thời lượng: short, medium, long, all
|
|
56
|
+
sortBy: "viewCount", // Sắp xếp: relevance, uploadDate, viewCount, rating
|
|
57
|
+
uploadDate: "month", // Ngày upload: hour, today, week, month, year, all
|
|
58
|
+
type: "video", // Loại: video, playlist, channel, all
|
|
59
|
+
});
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### Tìm Kiếm Playlist
|
|
63
|
+
|
|
64
|
+
```javascript
|
|
65
|
+
// Tìm kiếm playlist
|
|
66
|
+
const playlistResult = await plugin.searchPlaylist("lofi hip hop", "user123", 5);
|
|
67
|
+
playlistResult.tracks.forEach((track) => {
|
|
68
|
+
console.log(`Playlist: ${track.title}`);
|
|
69
|
+
console.log(`Channel: ${track.metadata?.author}`);
|
|
70
|
+
console.log(`Số video: ${track.metadata?.videoCount}`);
|
|
71
|
+
});
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### Tìm Kiếm Channel
|
|
75
|
+
|
|
76
|
+
```javascript
|
|
77
|
+
// Tìm kiếm channel
|
|
78
|
+
const channelResult = await plugin.searchChannel("PewDiePie", "user123", 3);
|
|
79
|
+
channelResult.tracks.forEach((track) => {
|
|
80
|
+
console.log(`Channel: ${track.title}`);
|
|
81
|
+
console.log(`Subscribers: ${track.metadata?.subscriberCount}`);
|
|
82
|
+
console.log(`URL: ${track.url}`);
|
|
83
|
+
});
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### Tìm Kiếm Tất Cả Loại
|
|
87
|
+
|
|
88
|
+
```javascript
|
|
89
|
+
// Tìm kiếm tất cả loại (video, playlist, channel)
|
|
90
|
+
const allResult = await plugin.search("music", "user123", {
|
|
91
|
+
type: "all",
|
|
92
|
+
limit: 15,
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
allResult.tracks.forEach((track) => {
|
|
96
|
+
const type = track.metadata?.type || "video";
|
|
97
|
+
console.log(`[${type.toUpperCase()}] ${track.title}`);
|
|
98
|
+
});
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### Xử Lý URL YouTube
|
|
102
|
+
|
|
103
|
+
```javascript
|
|
104
|
+
// Xử lý URL YouTube trực tiếp
|
|
105
|
+
const urlResult = await plugin.search("https://www.youtube.com/watch?v=dQw4w9WgXcQ", "user123");
|
|
106
|
+
if (urlResult.tracks.length > 0) {
|
|
107
|
+
const track = urlResult.tracks[0];
|
|
108
|
+
console.log(`Video: ${track.title}`);
|
|
109
|
+
console.log(`Tác giả: ${track.metadata?.author}`);
|
|
110
|
+
}
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### Lấy Video Theo ID
|
|
114
|
+
|
|
115
|
+
```javascript
|
|
116
|
+
// Lấy video theo ID cụ thể
|
|
117
|
+
const video = await plugin.getVideoById("dQw4w9WgXcQ", "user123");
|
|
118
|
+
if (video) {
|
|
119
|
+
console.log(`Video: ${video.title}`);
|
|
120
|
+
console.log(`Tác giả: ${video.metadata?.author}`);
|
|
121
|
+
console.log(`URL: ${video.url}`);
|
|
122
|
+
}
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### Lấy Video Liên Quan
|
|
126
|
+
|
|
127
|
+
```javascript
|
|
128
|
+
// Lấy video liên quan cho một video cụ thể
|
|
129
|
+
const relatedTracks = await plugin.getRelatedTracks("https://www.youtube.com/watch?v=dQw4w9WgXcQ", {
|
|
130
|
+
limit: 5, // Số lượng video liên quan tối đa
|
|
131
|
+
offset: 0, // Bỏ qua N video đầu tiên
|
|
132
|
+
history: [currentTrack], // Loại trừ các video đã phát
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
relatedTracks.forEach((track, index) => {
|
|
136
|
+
console.log(`${index + 1}. ${track.title} - ${track.metadata?.author}`);
|
|
137
|
+
});
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### Xử Lý Mix Playlist (RD)
|
|
141
|
+
|
|
142
|
+
```javascript
|
|
143
|
+
// Xử lý YouTube Mix playlist (RD)
|
|
144
|
+
const mixResult = await plugin.handleMixPlaylist(
|
|
145
|
+
"https://www.youtube.com/watch?v=dQw4w9WgXcQ&list=RDMWGnHCaqxdU&start_radio=1",
|
|
146
|
+
"user123",
|
|
147
|
+
10, // Số lượng track tối đa
|
|
148
|
+
);
|
|
149
|
+
|
|
150
|
+
console.log(`Mix playlist: ${mixResult.playlist?.name}`);
|
|
151
|
+
console.log(`Tìm thấy ${mixResult.tracks.length} track trong Mix`);
|
|
152
|
+
|
|
153
|
+
mixResult.tracks.forEach((track, index) => {
|
|
154
|
+
console.log(`${index + 1}. ${track.title} - ${track.metadata?.author}`);
|
|
155
|
+
});
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
## 📋 API Reference
|
|
159
|
+
|
|
160
|
+
### `search(query, requestedBy, options?)`
|
|
161
|
+
|
|
162
|
+
Tìm kiếm nội dung trên YouTube với các tùy chọn nâng cao.
|
|
163
|
+
|
|
164
|
+
**Tham số:**
|
|
165
|
+
|
|
166
|
+
- `query` (string): Query tìm kiếm hoặc URL YouTube
|
|
167
|
+
- `requestedBy` (string): ID của user yêu cầu tìm kiếm
|
|
168
|
+
- `options` (object, tùy chọn):
|
|
169
|
+
- `limit` (number): Số lượng kết quả tối đa (mặc định: 10)
|
|
170
|
+
- `type` (string): Loại tìm kiếm - "video", "playlist", "channel", "all" (mặc định: "video")
|
|
171
|
+
- `duration` (string): Lọc theo thời lượng - "short", "medium", "long", "all" (mặc định: "all")
|
|
172
|
+
- `sortBy` (string): Sắp xếp - "relevance", "uploadDate", "viewCount", "rating" (mặc định: "relevance")
|
|
173
|
+
- `uploadDate` (string): Lọc theo ngày upload - "hour", "today", "week", "month", "year", "all" (mặc định: "all")
|
|
174
|
+
|
|
175
|
+
**Trả về:** `Promise<SearchResult>`
|
|
176
|
+
|
|
177
|
+
### `searchPlaylist(query, requestedBy, limit?)`
|
|
178
|
+
|
|
179
|
+
Tìm kiếm playlist trên YouTube.
|
|
180
|
+
|
|
181
|
+
**Tham số:**
|
|
182
|
+
|
|
183
|
+
- `query` (string): Query tìm kiếm playlist
|
|
184
|
+
- `requestedBy` (string): ID của user yêu cầu
|
|
185
|
+
- `limit` (number, tùy chọn): Số lượng playlist tối đa (mặc định: 5)
|
|
186
|
+
|
|
187
|
+
**Trả về:** `Promise<SearchResult>`
|
|
188
|
+
|
|
189
|
+
### `searchChannel(query, requestedBy, limit?)`
|
|
190
|
+
|
|
191
|
+
Tìm kiếm channel trên YouTube.
|
|
192
|
+
|
|
193
|
+
**Tham số:**
|
|
194
|
+
|
|
195
|
+
- `query` (string): Query tìm kiếm channel
|
|
196
|
+
- `requestedBy` (string): ID của user yêu cầu
|
|
197
|
+
- `limit` (number, tùy chọn): Số lượng channel tối đa (mặc định: 5)
|
|
198
|
+
|
|
199
|
+
**Trả về:** `Promise<SearchResult>`
|
|
200
|
+
|
|
201
|
+
### `getVideoById(videoId, requestedBy)`
|
|
202
|
+
|
|
203
|
+
Lấy thông tin video theo ID cụ thể.
|
|
204
|
+
|
|
205
|
+
**Tham số:**
|
|
206
|
+
|
|
207
|
+
- `videoId` (string): ID của video YouTube
|
|
208
|
+
- `requestedBy` (string): ID của user yêu cầu
|
|
209
|
+
|
|
210
|
+
**Trả về:** `Promise<Track | null>`
|
|
211
|
+
|
|
212
|
+
### `getRelatedTracks(trackURL, opts?)`
|
|
213
|
+
|
|
214
|
+
Lấy các video liên quan cho một video YouTube cụ thể.
|
|
215
|
+
|
|
216
|
+
**Tham số:**
|
|
217
|
+
|
|
218
|
+
- `trackURL` (string): URL của video YouTube để lấy video liên quan
|
|
219
|
+
- `opts` (object, tùy chọn):
|
|
220
|
+
- `limit` (number): Số lượng video liên quan tối đa (mặc định: 5)
|
|
221
|
+
- `offset` (number): Số lượng video bỏ qua từ đầu (mặc định: 0)
|
|
222
|
+
- `history` (Track[]): Mảng các track để loại trừ khỏi kết quả
|
|
223
|
+
|
|
224
|
+
**Trả về:** `Promise<Track[]>`
|
|
225
|
+
|
|
226
|
+
### `handleMixPlaylist(mixUrl, requestedBy, limit?)`
|
|
227
|
+
|
|
228
|
+
Xử lý YouTube Mix playlist (RD) và tạo danh sách các video liên quan.
|
|
229
|
+
|
|
230
|
+
**Tham số:**
|
|
231
|
+
|
|
232
|
+
- `mixUrl` (string): URL của playlist Mix YouTube
|
|
233
|
+
- `requestedBy` (string): ID của user yêu cầu
|
|
234
|
+
- `limit` (number, tùy chọn): Số lượng track tối đa (mặc định: 10)
|
|
235
|
+
|
|
236
|
+
**Trả về:** `Promise<SearchResult>`
|
|
237
|
+
|
|
238
|
+
### `canHandle(query)`
|
|
239
|
+
|
|
240
|
+
Kiểm tra xem plugin có thể xử lý query này không.
|
|
241
|
+
|
|
242
|
+
**Tham số:**
|
|
243
|
+
|
|
244
|
+
- `query` (string): Query để kiểm tra
|
|
245
|
+
|
|
246
|
+
**Trả về:** `boolean`
|
|
247
|
+
|
|
248
|
+
### `validate(url)`
|
|
249
|
+
|
|
250
|
+
Xác thực URL YouTube.
|
|
251
|
+
|
|
252
|
+
**Tham số:**
|
|
253
|
+
|
|
254
|
+
- `url` (string): URL để xác thực
|
|
255
|
+
|
|
256
|
+
**Trả về:** `boolean`
|
|
257
|
+
|
|
258
|
+
## ⚠️ Lưu Ý Quan Trọng
|
|
259
|
+
|
|
260
|
+
- **KHÔNG hỗ trợ streaming**: Plugin này chỉ dành cho tìm kiếm metadata, không tạo stream audio
|
|
261
|
+
- **KHÔNG hỗ trợ fallback**: Không có phương thức fallback streaming
|
|
262
|
+
- **Chỉ metadata**: Trả về thông tin về video/playlist/channel, không phải audio stream
|
|
263
|
+
- **Sử dụng với plugin khác**: Có thể kết hợp với YouTubePlugin để có cả tìm kiếm nâng cao và streaming
|
|
264
|
+
|
|
265
|
+
## 🔧 Tích Hợp Với Plugin Khác
|
|
266
|
+
|
|
267
|
+
```javascript
|
|
268
|
+
const { YTSRPlugin, YouTubePlugin } = require("ziplayer/plugins");
|
|
269
|
+
|
|
270
|
+
// Sử dụng YTSRPlugin để tìm kiếm nâng cao
|
|
271
|
+
const ytsrPlugin = new YTSRPlugin();
|
|
272
|
+
const searchResult = await ytsrPlugin.search("music", "user123", {
|
|
273
|
+
duration: "medium",
|
|
274
|
+
sortBy: "viewCount",
|
|
275
|
+
});
|
|
276
|
+
|
|
277
|
+
// Lấy video liên quan
|
|
278
|
+
const relatedTracks = await ytsrPlugin.getRelatedTracks(searchResult.tracks[0].url, {
|
|
279
|
+
limit: 3,
|
|
280
|
+
history: searchResult.tracks,
|
|
281
|
+
});
|
|
282
|
+
|
|
283
|
+
// Sử dụng YouTubePlugin để tạo stream
|
|
284
|
+
const youtubePlugin = new YouTubePlugin();
|
|
285
|
+
const stream = await youtubePlugin.getStream(searchResult.tracks[0]);
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
## 🧪 Testing
|
|
289
|
+
|
|
290
|
+
```bash
|
|
291
|
+
# Chạy test cho YTSRPlugin
|
|
292
|
+
npm test tests/plugins/ytsrplugin.test.js
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
## 📝 Ví Dụ Hoàn Chỉnh
|
|
296
|
+
|
|
297
|
+
Xem file `examples/ytsr-example.js` để có ví dụ chi tiết về cách sử dụng plugin.
|
|
298
|
+
|
|
299
|
+
## 🤝 Đóng Góp
|
|
300
|
+
|
|
301
|
+
Nếu bạn muốn đóng góp vào plugin này, vui lòng:
|
|
302
|
+
|
|
303
|
+
1. Fork repository
|
|
304
|
+
2. Tạo branch mới cho feature
|
|
305
|
+
3. Commit changes
|
|
306
|
+
4. Tạo Pull Request
|
|
307
|
+
|
|
308
|
+
## 📄 License
|
|
309
|
+
|
|
310
|
+
MIT License - xem file LICENSE để biết thêm chi tiết.
|
package/dist/TTSPlugin.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TTSPlugin.js","sourceRoot":"","sources":["../src/TTSPlugin.ts"],"names":[],"mappings":";;;;;;AAAA,uCAAuE;AACvE,mCAAkC;AAClC,wCAA0C;AAC1C,kDAA0B;AAgD1B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,MAAa,SAAU,SAAQ,qBAAU;IAKxC;;;;;;;;;;;;;;;;;;;;;;;;;OAyBG;IACH,YAAY,IAAuB;QAClC,KAAK,EAAE,CAAC;QA/BT,SAAI,GAAG,KAAK,CAAC;QACb,YAAO,GAAG,OAAO,CAAC;QA+BjB,IAAI,CAAC,IAAI,GAAG;YACX,WAAW,EAAE,IAAI,EAAE,WAAW,IAAI,IAAI;YACtC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,IAAI;YAClB,YAAY,EAAE,IAAI,EAAE,YAAY;SAChC,CAAC;IACH,CAAC;IAED;;;;;;;;;;OAUG;IACH,SAAS,CAAC,KAAa;QACtB,IAAI,CAAC,KAAK;YAAE,OAAO,KAAK,CAAC;QACzB,MAAM,CAAC,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QACrC,OAAO,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;IACrD,CAAC;IAED;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACH,KAAK,CAAC,MAAM,CAAC,KAAa,EAAE,WAAmB;QAC9C,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC;YAC5B,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;QACvB,CAAC;QACD,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;QACpD,MAAM,MAAM,GAAc,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;QAC/C,MAAM,GAAG,GAAG,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;QACtC,MAAM,KAAK,GAAG,QAAQ,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,MAAM,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;QACzG,MAAM,gBAAgB,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC;QAEhF,MAAM,KAAK,GAAU;YACpB,EAAE,EAAE,OAAO,IAAI,CAAC,GAAG,EAAE,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE;YACjE,KAAK;YACL,GAAG;YACH,QAAQ,EAAE,gBAAgB;YAC1B,WAAW;YACX,MAAM,EAAE,IAAI,CAAC,IAAI;YACjB,QAAQ,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE;SACzB,CAAC;QAEF,OAAO,EAAE,MAAM,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC;IAC5B,CAAC;IAED;;;;;;;;;;;;;;;;OAgBG;IACH,KAAK,CAAC,SAAS,CAAC,KAAY;QAC3B,MAAM,GAAG,GAAG,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;QACtC,IAAI,KAAK,CAAC,MAAM,KAAK,IAAI,CAAC,IAAI;YAAE,OAAO,
|
|
1
|
+
{"version":3,"file":"TTSPlugin.js","sourceRoot":"","sources":["../src/TTSPlugin.ts"],"names":[],"mappings":"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"}
|