gerdur 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/dist/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gerdur",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2",
|
|
4
4
|
"description": "The crucial streaming module for dabox systems.",
|
|
5
5
|
"author": "Christian",
|
|
6
6
|
"license": "SEE LICENSE IN LICENSE",
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
"adm-zip": "^0.5.16",
|
|
49
49
|
"chalk": "^4.1.2",
|
|
50
50
|
"commander": "^9.5.0",
|
|
51
|
-
"gerdur-core": "^1.0.
|
|
51
|
+
"gerdur-core": "^1.0.4",
|
|
52
52
|
"dot-prop": "^6.0.1",
|
|
53
53
|
"got": "^11.8.6",
|
|
54
54
|
"gradient-string": "^2.0.2",
|
package/dist/src/gerdur.js
CHANGED
|
@@ -219,6 +219,32 @@ const startDownload = async (saveLayout, url, skipPrompt) => {
|
|
|
219
219
|
const resolveFullPath = options.resolveFullPath ?? conf.get('playlist.resolveFullPath');
|
|
220
220
|
const savedFiles = [];
|
|
221
221
|
let m3u8 = [];
|
|
222
|
+
// One batched get_url for the whole selection instead of a request per track.
|
|
223
|
+
// Deezer returns the best licensed format, so pass an ordered preference list.
|
|
224
|
+
const QUALITY_PREF = {
|
|
225
|
+
'1': [1],
|
|
226
|
+
'128': [1],
|
|
227
|
+
'3': [3, 1],
|
|
228
|
+
'320': [3, 1],
|
|
229
|
+
'9': [9, 3, 1],
|
|
230
|
+
flac: [9, 3, 1],
|
|
231
|
+
};
|
|
232
|
+
const prefetchedUrls = new Map();
|
|
233
|
+
if (data.tracks.length > 1 && !process.env.SIMULATE) {
|
|
234
|
+
try {
|
|
235
|
+
const base = QUALITY_PREF[String(options.quality).toLowerCase()] ?? [3, 1];
|
|
236
|
+
const pref = fallbackQuality ? base : [base[0]];
|
|
237
|
+
const resolved = await (0, gerdur_core_1.resolveDownloadUrls)(data.tracks, pref);
|
|
238
|
+
resolved.forEach((r, i) => {
|
|
239
|
+
if (r) {
|
|
240
|
+
prefetchedUrls.set(data.tracks[i].SNG_ID, r);
|
|
241
|
+
}
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
catch {
|
|
245
|
+
// batch resolve failed wholesale — every track falls back to per-track resolution
|
|
246
|
+
}
|
|
247
|
+
}
|
|
222
248
|
await queue.addAll(data.tracks.map((track, index) => {
|
|
223
249
|
return async () => {
|
|
224
250
|
const savedPath = await (0, download_track_1.default)({
|
|
@@ -233,6 +259,7 @@ const startDownload = async (saveLayout, url, skipPrompt) => {
|
|
|
233
259
|
fallbackQuality,
|
|
234
260
|
overwrite,
|
|
235
261
|
message: `(${index}/${data.tracks.length})`,
|
|
262
|
+
prefetched: prefetchedUrls.get(track.SNG_ID) ?? null,
|
|
236
263
|
});
|
|
237
264
|
// Add to saved list
|
|
238
265
|
if (savedPath) {
|
|
@@ -19,6 +19,18 @@ interface downloadTrackProps {
|
|
|
19
19
|
isQualityFallback?: boolean;
|
|
20
20
|
overwrite?: boolean;
|
|
21
21
|
message?: string;
|
|
22
|
+
/**
|
|
23
|
+
* A download URL already resolved for this track by a batch `resolveDownloadUrls`
|
|
24
|
+
* pass. When set, the per-track `get_url` request and quality-fallback round-trips
|
|
25
|
+
* are skipped and `quality` is taken from the format Deezer actually granted.
|
|
26
|
+
* Falls through to the normal path when absent or `null` (track not in the batch).
|
|
27
|
+
*/
|
|
28
|
+
prefetched?: {
|
|
29
|
+
trackUrl: string;
|
|
30
|
+
isEncrypted: boolean;
|
|
31
|
+
fileSize: number;
|
|
32
|
+
format: string;
|
|
33
|
+
} | null;
|
|
22
34
|
}
|
|
23
|
-
declare const downloadTrack: ({ track, quality, info, coverSizes, path, totalTracks, trackNumber, fallbackTrack, fallbackQuality, isFallback, isQualityFallback, overwrite, message, }: downloadTrackProps) => Promise<string | undefined>;
|
|
35
|
+
declare const downloadTrack: ({ track, quality, info, coverSizes, path, totalTracks, trackNumber, fallbackTrack, fallbackQuality, isFallback, isQualityFallback, overwrite, message, prefetched, }: downloadTrackProps) => Promise<string | undefined>;
|
|
24
36
|
export default downloadTrack;
|
|
@@ -16,10 +16,17 @@ const util_2 = require("./util");
|
|
|
16
16
|
const decrypt_1 = require("./decrypt");
|
|
17
17
|
const pipeline = (0, util_1.promisify)(stream_1.default.pipeline);
|
|
18
18
|
const simulate = process.env.SIMULATE;
|
|
19
|
-
|
|
19
|
+
/** media-API format string -> gerdur's numeric quality */
|
|
20
|
+
const FORMAT_TO_QUALITY = { FLAC: 9, MP3_320: 3, MP3_256: 3, MP3_128: 1, MP3_64: 1 };
|
|
21
|
+
const downloadTrack = async ({ track, quality, info, coverSizes, path, totalTracks, trackNumber = true, fallbackTrack = true, fallbackQuality = true, isFallback = false, isQualityFallback = false, overwrite = false, message = '', prefetched = null, }) => {
|
|
20
22
|
(0, log_update_1.default)(signale_1.default.pending(track.SNG_TITLE + ' by ' + track.ART_NAME + ' from ' + track.ALB_TITLE));
|
|
21
23
|
try {
|
|
22
24
|
let ext = '.mp3', fileSize = 0, downloaded = 0, coverSize = 500;
|
|
25
|
+
// A batch resolve already picked the best licensed format for this track —
|
|
26
|
+
// align `quality` with it so the extension, cover size and file size match.
|
|
27
|
+
if (prefetched && FORMAT_TO_QUALITY[prefetched.format]) {
|
|
28
|
+
quality = FORMAT_TO_QUALITY[prefetched.format];
|
|
29
|
+
}
|
|
23
30
|
switch (quality) {
|
|
24
31
|
case 1:
|
|
25
32
|
case '1':
|
|
@@ -54,12 +61,17 @@ const downloadTrack = async ({ track, quality, info, coverSizes, path, totalTrac
|
|
|
54
61
|
return savePath;
|
|
55
62
|
}
|
|
56
63
|
let trackData;
|
|
57
|
-
|
|
58
|
-
trackData =
|
|
64
|
+
if (prefetched) {
|
|
65
|
+
trackData = prefetched;
|
|
59
66
|
}
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
67
|
+
else {
|
|
68
|
+
try {
|
|
69
|
+
trackData = await (0, gerdur_core_1.getTrackDownloadUrl)(track, quality);
|
|
70
|
+
}
|
|
71
|
+
catch (err) {
|
|
72
|
+
if (!(err instanceof gerdur_core_1.GeoBlocked) || !track.FALLBACK) {
|
|
73
|
+
throw err;
|
|
74
|
+
}
|
|
63
75
|
}
|
|
64
76
|
}
|
|
65
77
|
if (!trackData) {
|
|
@@ -114,7 +126,13 @@ const downloadTrack = async ({ track, quality, info, coverSizes, path, totalTrac
|
|
|
114
126
|
const bar = (0, util_2.progressBar)(fileSize, 40);
|
|
115
127
|
const humanSizeTotal = (fileSize / 1024 / 1024).toFixed(2);
|
|
116
128
|
let transferredLast = downloaded;
|
|
117
|
-
await pipeline(got_1.default
|
|
129
|
+
await pipeline(got_1.default
|
|
130
|
+
.stream(trackData.trackUrl, {
|
|
131
|
+
responseType: 'buffer',
|
|
132
|
+
headers,
|
|
133
|
+
agent: { http: gerdur_core_1.httpAgent, https: gerdur_core_1.httpsAgent },
|
|
134
|
+
})
|
|
135
|
+
.on('downloadProgress', ({ transferred }) => {
|
|
118
136
|
// Report download progress
|
|
119
137
|
transferred += downloaded;
|
|
120
138
|
if (transferred - transferredLast > 50000) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gerdur",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2",
|
|
4
4
|
"description": "The crucial streaming module for dabox systems.",
|
|
5
5
|
"author": "Christian",
|
|
6
6
|
"license": "SEE LICENSE IN LICENSE",
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
"adm-zip": "^0.5.16",
|
|
49
49
|
"chalk": "^4.1.2",
|
|
50
50
|
"commander": "^9.5.0",
|
|
51
|
-
"gerdur-core": "^1.0.
|
|
51
|
+
"gerdur-core": "^1.0.4",
|
|
52
52
|
"dot-prop": "^6.0.1",
|
|
53
53
|
"got": "^11.8.6",
|
|
54
54
|
"gradient-string": "^2.0.2",
|