xvideo-dll 1.0.1 → 1.0.2
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 +70 -58
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,84 +1,95 @@
|
|
|
1
1
|
# xvideo-dll
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
A Node.js library that reads a video page, lists the available qualities and downloads the one you choose.
|
|
4
4
|
|
|
5
|
-
-
|
|
6
|
-
-
|
|
7
|
-
-
|
|
8
|
-
- **No
|
|
9
|
-
-
|
|
5
|
+
- Reads the basic page data (title, thumbnail, description).
|
|
6
|
+
- Detects every quality: direct MP4 (`mp4-low`, `mp4-high`) and HLS (`hls-480p`, `hls-720p`, ...).
|
|
7
|
+
- Downloads HLS in parallel and converts it to a **real MP4** (plays in browsers, VS Code, etc.).
|
|
8
|
+
- **No ffmpeg required.**
|
|
9
|
+
- If the signed URL expires mid-download, it can refresh it automatically.
|
|
10
10
|
|
|
11
|
-
##
|
|
11
|
+
## Requirements
|
|
12
12
|
|
|
13
|
-
- Node.js 18
|
|
13
|
+
- Node.js 18 or higher.
|
|
14
14
|
|
|
15
|
-
##
|
|
15
|
+
## Install
|
|
16
16
|
|
|
17
17
|
```bash
|
|
18
18
|
npm install xvideo-dll
|
|
19
19
|
```
|
|
20
20
|
|
|
21
|
-
##
|
|
21
|
+
## Quick start
|
|
22
22
|
|
|
23
|
-
1.
|
|
23
|
+
1. Create a folder and install the package:
|
|
24
24
|
|
|
25
25
|
```bash
|
|
26
|
-
mkdir
|
|
26
|
+
mkdir test && cd test
|
|
27
27
|
npm init -y
|
|
28
28
|
npm install xvideo-dll
|
|
29
29
|
```
|
|
30
30
|
|
|
31
|
-
2.
|
|
31
|
+
2. Create a file named `example.mjs` (the `.mjs` extension lets you use `import` and top-level `await` with no extra setup):
|
|
32
32
|
|
|
33
33
|
```js
|
|
34
34
|
import { fetchPageHtml, parseVideo, getResolutions, download } from "xvideo-dll";
|
|
35
35
|
|
|
36
|
-
//
|
|
37
|
-
const
|
|
36
|
+
// Usage: node example.mjs "PAGE_URL" [quality] [--list | -F]
|
|
37
|
+
const args = process.argv.slice(2);
|
|
38
|
+
const listOnly = args.includes("--list") || args.includes("-F");
|
|
39
|
+
const [pageUrl, quality = "mp4-low"] = args.filter((a) => !a.startsWith("-"));
|
|
40
|
+
|
|
38
41
|
if (!pageUrl) {
|
|
39
|
-
console.error('
|
|
42
|
+
console.error('Usage: node example.mjs "PAGE_URL" [quality] [--list | -F]');
|
|
40
43
|
process.exit(1);
|
|
41
44
|
}
|
|
42
45
|
|
|
43
|
-
// 1.
|
|
46
|
+
// 1. Fetch the page (always live: signed URLs expire)
|
|
44
47
|
const html = await fetchPageHtml(pageUrl);
|
|
45
48
|
|
|
46
|
-
// 2.
|
|
49
|
+
// 2. Basic info
|
|
47
50
|
console.log(parseVideo(html));
|
|
48
51
|
|
|
49
|
-
// 3.
|
|
52
|
+
// 3. Available qualities
|
|
50
53
|
const resolutions = await getResolutions(html);
|
|
51
|
-
|
|
54
|
+
const keys = Object.keys(resolutions);
|
|
55
|
+
|
|
56
|
+
if (listOnly) {
|
|
57
|
+
console.log("\nAvailable qualities:");
|
|
58
|
+
for (const key of keys) console.log(` ${key}`);
|
|
59
|
+
process.exit(0);
|
|
60
|
+
}
|
|
52
61
|
|
|
53
|
-
// 4.
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
console.error(`La resolución "${key}" no existe.`);
|
|
62
|
+
// 4. Download the chosen quality (default: "mp4-low", the lightest)
|
|
63
|
+
if (!resolutions[quality]) {
|
|
64
|
+
console.error(`Quality "${quality}" not found. Available: ${keys.join(", ")}`);
|
|
57
65
|
process.exit(1);
|
|
58
66
|
}
|
|
59
67
|
|
|
60
68
|
const result = await download(
|
|
61
|
-
resolutions[
|
|
62
|
-
`video-${
|
|
63
|
-
(p) => process.stdout.write(`\r${Math.round(p * 100)}%`), //
|
|
64
|
-
8, //
|
|
65
|
-
async () => { //
|
|
69
|
+
resolutions[quality],
|
|
70
|
+
`video-${quality}.mp4`,
|
|
71
|
+
(p) => process.stdout.write(`\r${Math.round(p * 100)}%`), // progress (0 to 1)
|
|
72
|
+
8, // parallel connections (HLS only)
|
|
73
|
+
async () => { // optional: refresh the URL if it expires
|
|
66
74
|
const fresh = await getResolutions(await fetchPageHtml(pageUrl));
|
|
67
|
-
return fresh[
|
|
75
|
+
return fresh[quality];
|
|
68
76
|
}
|
|
69
77
|
);
|
|
70
78
|
|
|
71
|
-
console.log(`\
|
|
79
|
+
console.log(`\nSaved to ${result.path} (${(result.bytes / 1024 / 1024).toFixed(1)} MB)`);
|
|
72
80
|
```
|
|
73
81
|
|
|
74
|
-
3.
|
|
82
|
+
3. Run it:
|
|
75
83
|
|
|
76
84
|
```bash
|
|
77
|
-
node
|
|
78
|
-
node
|
|
85
|
+
node example.mjs "PAGE_URL" --list # list the available qualities
|
|
86
|
+
node example.mjs "PAGE_URL" # download mp4-low (the fastest)
|
|
87
|
+
node example.mjs "PAGE_URL" hls-480p # download a specific quality
|
|
79
88
|
```
|
|
80
89
|
|
|
81
|
-
|
|
90
|
+
The quality names (`mp4-low`, `hls-480p`, ...) are the keys returned by `getResolutions`, so always list them first: they change from video to video.
|
|
91
|
+
|
|
92
|
+
It also works with `require`, inside an `async` function (CommonJS does not allow top-level `await`):
|
|
82
93
|
|
|
83
94
|
```js
|
|
84
95
|
const { fetchPageHtml, getResolutions, download } = require("xvideo-dll");
|
|
@@ -86,6 +97,7 @@ const { fetchPageHtml, getResolutions, download } = require("xvideo-dll");
|
|
|
86
97
|
async function main() {
|
|
87
98
|
const html = await fetchPageHtml(process.argv[2]);
|
|
88
99
|
const resolutions = await getResolutions(html);
|
|
100
|
+
console.log(Object.keys(resolutions)); // see the qualities
|
|
89
101
|
await download(resolutions["mp4-low"], "video.mp4");
|
|
90
102
|
}
|
|
91
103
|
|
|
@@ -94,29 +106,29 @@ main();
|
|
|
94
106
|
|
|
95
107
|
## API
|
|
96
108
|
|
|
97
|
-
|
|
|
109
|
+
| Function | What it does |
|
|
98
110
|
|---|---|
|
|
99
|
-
| `fetchPageHtml(url)` |
|
|
100
|
-
| `getVideoInfo(url)` |
|
|
101
|
-
| `parseVideo(html)` |
|
|
102
|
-
| `parsePlayerUrls(html)` |
|
|
103
|
-
| `parseHlsMaster(m3u8, masterUrl)` |
|
|
104
|
-
| `getResolutions(html)` |
|
|
105
|
-
| `download(url, outPath, onProgress?, threads?, refreshUrl?)` |
|
|
106
|
-
| `downloadHlsFast(...)` |
|
|
107
|
-
| `downloadFile(url, outPath, onProgress?)` |
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
##
|
|
112
|
-
|
|
113
|
-
- **
|
|
114
|
-
- **
|
|
115
|
-
- **
|
|
116
|
-
- **MP4
|
|
117
|
-
- **
|
|
118
|
-
- **
|
|
119
|
-
|
|
120
|
-
##
|
|
111
|
+
| `fetchPageHtml(url)` | Downloads the page HTML (follows redirects). |
|
|
112
|
+
| `getVideoInfo(url)` | Downloads the page and returns `parseVideo` of its HTML. |
|
|
113
|
+
| `parseVideo(html)` | Extracts `title`, `thumbnail`, `description` and `jsonLd` from an HTML string. |
|
|
114
|
+
| `parsePlayerUrls(html)` | Extracts the `low`, `high` and `hls` URLs from the player script. |
|
|
115
|
+
| `parseHlsMaster(m3u8, masterUrl)` | Turns an HLS master playlist into `{ "hls-720p": url, ... }`. |
|
|
116
|
+
| `getResolutions(html)` | Returns every available quality. |
|
|
117
|
+
| `download(url, outPath, onProgress?, threads?, refreshUrl?)` | Downloads one quality. Picks the right method from the URL. |
|
|
118
|
+
| `downloadHlsFast(...)` | Downloads HLS in parallel and converts it to MP4. |
|
|
119
|
+
| `downloadFile(url, outPath, onProgress?)` | Downloads a direct MP4. |
|
|
120
|
+
|
|
121
|
+
All functions and the `VideoInfo` and `Resolutions` types are exported.
|
|
122
|
+
|
|
123
|
+
## Things to keep in mind
|
|
124
|
+
|
|
125
|
+
- **URLs expire.** They carry a time-limited token. Always fetch the page with `fetchPageHtml` right before downloading, and never store URLs to use later.
|
|
126
|
+
- **HLS download:** segments are saved to a temporary folder (`.hls_temp_*`, next to the output file), joined and converted to MP4. The folder is deleted when finished, even if an error occurs.
|
|
127
|
+
- **Memory:** for HLS, the whole video goes through memory during conversion. This is fine for videos of tens of MB; very large files will use a lot of RAM.
|
|
128
|
+
- **Direct MP4:** downloaded with a single connection (the `threads` parameter does not apply).
|
|
129
|
+
- **Compatibility:** built for pages whose player exposes `setVideoUrlLow`, `setVideoUrlHigh` and `setVideoHLS`. If the site changes that code, `parsePlayerUrls` has to be adjusted.
|
|
130
|
+
- **Responsible use:** respect the site's terms of use and the copyright of the content, and do not send many requests in a row.
|
|
131
|
+
|
|
132
|
+
## License
|
|
121
133
|
|
|
122
134
|
ISC
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "xvideo-dll",
|
|
3
|
-
"version": "1.0.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "1.0.2",
|
|
4
|
+
"description": "Lists the qualities of a video page and downloads it (direct MP4 or HLS converted to a real MP4) without ffmpeg.",
|
|
5
5
|
"main": "./dist/index.cjs",
|
|
6
6
|
"module": "./dist/index.js",
|
|
7
7
|
"types": "./dist/index.d.ts",
|