dasha 3.0.1 → 3.0.3
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/lib/dash.js +33 -35
- package/lib/track.js +10 -6
- package/package.json +1 -1
- package/types/dasha.d.ts +3 -3
package/lib/dash.js
CHANGED
|
@@ -56,16 +56,12 @@ const combineGetters = (representation, adaptationSet) => {
|
|
|
56
56
|
};
|
|
57
57
|
|
|
58
58
|
const parseBaseUrl = (manifestUrl, mpd, period, representation) => {
|
|
59
|
-
let
|
|
60
|
-
if (!
|
|
61
|
-
else if (!
|
|
62
|
-
|
|
63
|
-
const
|
|
64
|
-
|
|
65
|
-
representation.getBaseUrl() || '',
|
|
66
|
-
periodBaseUrl
|
|
67
|
-
).toString();
|
|
68
|
-
return representationBaseUrl;
|
|
59
|
+
let base = mpd.getBaseUrl();
|
|
60
|
+
if (!base) base = manifestUrl;
|
|
61
|
+
else if (!base.startsWith('https://')) base = new URL(base, manifestUrl).toString();
|
|
62
|
+
if (!!period.getBaseUrl() || !!base) base = new URL(period.getBaseUrl() || '', base).toString();
|
|
63
|
+
const baseUrl = new URL(representation.getBaseUrl() || '', base).toString();
|
|
64
|
+
return baseUrl;
|
|
69
65
|
};
|
|
70
66
|
|
|
71
67
|
const parseContentTypes = (representation) => {
|
|
@@ -236,35 +232,36 @@ const parseSegmentFromBase = async (segmentBase, baseUrl) => {
|
|
|
236
232
|
return { url: baseUrl, range: mediaRange };
|
|
237
233
|
};
|
|
238
234
|
|
|
235
|
+
const transformSegmentUrls = (segments) => {
|
|
236
|
+
for (const segment of segments) {
|
|
237
|
+
const hasHtmlEscapeCode = segment.url.includes('&');
|
|
238
|
+
if (hasHtmlEscapeCode) {
|
|
239
|
+
const url = new URL(segment.url);
|
|
240
|
+
const entries = new URLSearchParams(url.searchParams.toString()).entries();
|
|
241
|
+
for (const [key, value] of entries) {
|
|
242
|
+
url.searchParams.delete(key);
|
|
243
|
+
url.searchParams.append(key.replaceAll('amp;', ''), value);
|
|
244
|
+
}
|
|
245
|
+
segment.url = url.toString();
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
};
|
|
249
|
+
|
|
250
|
+
const protectionSchemas = {
|
|
251
|
+
'urn:mpeg:dash:mp4protection:2011': 'common',
|
|
252
|
+
'urn:uuid:9a04f079-9840-4286-ab92-e65be0885f95': 'playready',
|
|
253
|
+
'urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed': 'widevine',
|
|
254
|
+
};
|
|
255
|
+
|
|
239
256
|
const parseContentProtection = (contentProtections) => {
|
|
240
257
|
const protection = {};
|
|
241
|
-
const commonId = 'urn:mpeg:dash:mp4protection:2011';
|
|
242
|
-
const playreadyId = 'urn:uuid:9a04f079-9840-4286-ab92-e65be0885f95';
|
|
243
|
-
const widevineId = 'urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed';
|
|
244
258
|
for (const contentProtection of contentProtections) {
|
|
245
259
|
const id = contentProtection.get('schemeIdUri')?.toLowerCase();
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
keyId: contentProtection.get('cenc:default_KID'),
|
|
252
|
-
};
|
|
253
|
-
continue;
|
|
254
|
-
case playreadyId:
|
|
255
|
-
protection.playready = {
|
|
256
|
-
id,
|
|
257
|
-
value: contentProtection.get('value'),
|
|
258
|
-
pssh: contentProtection.get('cenc:pssh')?.get(),
|
|
259
|
-
};
|
|
260
|
-
continue;
|
|
261
|
-
case widevineId:
|
|
262
|
-
protection.widevine = {
|
|
263
|
-
id,
|
|
264
|
-
pssh: contentProtection.get('cenc:pssh')?.get(),
|
|
265
|
-
};
|
|
266
|
-
continue;
|
|
267
|
-
}
|
|
260
|
+
const value = contentProtection.get('value');
|
|
261
|
+
const pssh = contentProtection.get('cenc:pssh')?.get();
|
|
262
|
+
const defaultKeyId = contentProtection.get('cenc:default_KID');
|
|
263
|
+
const data = { id, value, pssh, defaultKeyId };
|
|
264
|
+
protection[protectionSchemas[id]] = data;
|
|
268
265
|
}
|
|
269
266
|
return protection;
|
|
270
267
|
};
|
|
@@ -312,6 +309,7 @@ const parseManifest = async (text, url, fallbackLanguage) => {
|
|
|
312
309
|
} else {
|
|
313
310
|
throw new Error('Could not find a way to get segments from this MPD manifest.');
|
|
314
311
|
}
|
|
312
|
+
transformSegmentUrls(segments);
|
|
315
313
|
|
|
316
314
|
const label = get('label');
|
|
317
315
|
const fps = get('frameRate') ?? segmentBase?.attributes.timescale;
|
package/lib/track.js
CHANGED
|
@@ -33,14 +33,18 @@ const createAudioLanguageFilter = (audios) => {
|
|
|
33
33
|
if (!alreadyAdded) languages.push(audio.language);
|
|
34
34
|
}
|
|
35
35
|
}
|
|
36
|
-
const
|
|
36
|
+
const filtered = [];
|
|
37
37
|
for (const language of languages) {
|
|
38
38
|
const tracks = audios.filter((track) => track.language?.startsWith(language));
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
39
|
+
filtered.push(...tracks);
|
|
40
|
+
}
|
|
41
|
+
const results = [];
|
|
42
|
+
const filteredLanguages = [...new Set(filtered.map((track) => track.language))];
|
|
43
|
+
for (const language of filteredLanguages) {
|
|
44
|
+
const tracks = filtered
|
|
45
|
+
.filter((track) => track.language === language)
|
|
46
|
+
.slice(0, maxTracksPerLanguage);
|
|
47
|
+
results.push(...tracks);
|
|
44
48
|
}
|
|
45
49
|
return results;
|
|
46
50
|
};
|
package/package.json
CHANGED
package/types/dasha.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export function parse(text: string, url
|
|
1
|
+
export function parse(text: string, url?: string, fallbackLanguage?: string): Promise<Manifest>;
|
|
2
2
|
|
|
3
3
|
export interface Manifest {
|
|
4
4
|
duration?: number;
|
|
@@ -50,9 +50,9 @@ export interface Segment {
|
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
export interface TrackProtection {
|
|
53
|
-
common?: { id: string; value: 'cenc' | 'cbcs';
|
|
53
|
+
common?: { id: string; value: 'cenc' | 'cbcs'; defaultKeyId?: string };
|
|
54
54
|
playready?: { id: string; pssh?: string; value?: string };
|
|
55
|
-
widevine?: { id: string; pssh: string };
|
|
55
|
+
widevine?: { id: string; pssh: string; defaultKeyId?: string };
|
|
56
56
|
fairplay?: { keyFormat: string; uri: string; method: string };
|
|
57
57
|
}
|
|
58
58
|
|