dasha 4.4.2 → 4.4.4
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/index.d.mts +5 -1
- package/dist/index.mjs +82 -32
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -183,6 +183,7 @@ type Segment = {
|
|
|
183
183
|
};
|
|
184
184
|
type DashSegmentLocation = {
|
|
185
185
|
path: string;
|
|
186
|
+
sourcePath: string;
|
|
186
187
|
offset: number;
|
|
187
188
|
length: number | null;
|
|
188
189
|
};
|
|
@@ -360,7 +361,10 @@ declare class DashDemuxer {
|
|
|
360
361
|
}): void;
|
|
361
362
|
findMatchingTrack(nextTracks: DashParsedTrack[], currentTrack: DashParsedTrack): DashParsedTrack | undefined;
|
|
362
363
|
refreshTracks(tracks: DashParsedTrack[]): Promise<void>;
|
|
363
|
-
|
|
364
|
+
fetchManifestText(url: string): Promise<{
|
|
365
|
+
text: string;
|
|
366
|
+
url: string;
|
|
367
|
+
}>;
|
|
364
368
|
resetManifestUrls(): void;
|
|
365
369
|
}
|
|
366
370
|
declare abstract class DashTrackBackingBase {
|
package/dist/index.mjs
CHANGED
|
@@ -316,6 +316,21 @@ const getDashTrackMatchKey = (track) => JSON.stringify({
|
|
|
316
316
|
const getSourcePath = (source) => {
|
|
317
317
|
if ("rootPath" in source && typeof source.rootPath === "string") return source.rootPath;
|
|
318
318
|
};
|
|
319
|
+
const resolvePathedSourceRequest = async (source, request) => {
|
|
320
|
+
const pathedSource = source;
|
|
321
|
+
if (typeof pathedSource._resolveRequest !== "function") throw new Error("DASH input currently requires a pathed source such as UrlSource.");
|
|
322
|
+
return await pathedSource._resolveRequest(request);
|
|
323
|
+
};
|
|
324
|
+
const resolvePathedSourcePath = async (source, request) => {
|
|
325
|
+
const ref = await resolvePathedSourceRequest(source, request);
|
|
326
|
+
try {
|
|
327
|
+
const path = getSourcePath(ref.source);
|
|
328
|
+
if (!path) throw new Error("DASH segment requests must resolve to a pathed source.");
|
|
329
|
+
return path;
|
|
330
|
+
} finally {
|
|
331
|
+
ref.free();
|
|
332
|
+
}
|
|
333
|
+
};
|
|
319
334
|
const normalizeHeaders$1 = (headers) => {
|
|
320
335
|
if (!headers) return {};
|
|
321
336
|
if (headers instanceof Headers) return Object.fromEntries(headers.entries());
|
|
@@ -330,30 +345,48 @@ const getSourceHeaders$1 = (source) => {
|
|
|
330
345
|
...optionHeaders
|
|
331
346
|
};
|
|
332
347
|
};
|
|
348
|
+
const getSourceFetch = (source) => {
|
|
349
|
+
return ("_options" in source && source._options && typeof source._options === "object" ? source._options : void 0)?.fetchFn ?? fetch;
|
|
350
|
+
};
|
|
351
|
+
const fetchDashManifest = async (source, url) => {
|
|
352
|
+
const response = await getSourceFetch(source)(url, { headers: getSourceHeaders$1(source) });
|
|
353
|
+
if (!response.ok) throw new Error(`Failed to fetch DASH manifest: ${response.status} ${response.statusText} (${response.url})`);
|
|
354
|
+
return response;
|
|
355
|
+
};
|
|
333
356
|
const parseOriginalUrlFromManifest = (text) => text.match(/<!--\s*URL:\s*([^\n]+?)\s*-->/)?.[1]?.trim();
|
|
334
357
|
const loadDashManifest = async (source) => {
|
|
335
358
|
const manifestPath = getSourcePath(source);
|
|
336
359
|
if (!manifestPath) throw new Error("DASH input currently requires a pathed source such as UrlSource.");
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
360
|
+
const manifestRef = await resolvePathedSourceRequest(source, {
|
|
361
|
+
path: manifestPath,
|
|
362
|
+
isRoot: true
|
|
363
|
+
});
|
|
364
|
+
const manifestSource = manifestRef.source;
|
|
365
|
+
const resolvedManifestPath = getSourcePath(manifestSource);
|
|
366
|
+
try {
|
|
367
|
+
if (!resolvedManifestPath) throw new Error("DASH manifest requests must resolve to a pathed source.");
|
|
368
|
+
if (resolvedManifestPath.startsWith("http://") || resolvedManifestPath.startsWith("https://")) {
|
|
369
|
+
const response = await fetchDashManifest(manifestSource, resolvedManifestPath);
|
|
370
|
+
return {
|
|
371
|
+
text: await response.text(),
|
|
372
|
+
url: response.url || resolvedManifestPath
|
|
373
|
+
};
|
|
374
|
+
}
|
|
375
|
+
if (resolvedManifestPath.startsWith("file:")) {
|
|
376
|
+
const text = await readFile(new URL(resolvedManifestPath), "utf8");
|
|
377
|
+
return {
|
|
378
|
+
text,
|
|
379
|
+
url: parseOriginalUrlFromManifest(text) ?? resolvedManifestPath
|
|
380
|
+
};
|
|
381
|
+
}
|
|
382
|
+
const text = await readFile(resolvedManifestPath, "utf8");
|
|
347
383
|
return {
|
|
348
384
|
text,
|
|
349
|
-
url: parseOriginalUrlFromManifest(text) ??
|
|
385
|
+
url: parseOriginalUrlFromManifest(text) ?? resolvedManifestPath
|
|
350
386
|
};
|
|
387
|
+
} finally {
|
|
388
|
+
manifestRef.free();
|
|
351
389
|
}
|
|
352
|
-
const text = await readFile(manifestPath, "utf8");
|
|
353
|
-
return {
|
|
354
|
-
text,
|
|
355
|
-
url: parseOriginalUrlFromManifest(text) ?? manifestPath
|
|
356
|
-
};
|
|
357
390
|
};
|
|
358
391
|
const isLikelyDashPath = (source) => {
|
|
359
392
|
const path = getSourcePath(source);
|
|
@@ -1828,23 +1861,27 @@ const getLeastRecentlyUsedIndex = (entries) => {
|
|
|
1828
1861
|
}
|
|
1829
1862
|
return bestIndex;
|
|
1830
1863
|
};
|
|
1831
|
-
const getSegmentLocation = (segment) => ({
|
|
1832
|
-
path:
|
|
1864
|
+
const getSegmentLocation = async (input, segment) => ({
|
|
1865
|
+
path: await resolvePathedSourcePath(input.source, {
|
|
1866
|
+
path: segment.url,
|
|
1867
|
+
isRoot: false
|
|
1868
|
+
}),
|
|
1869
|
+
sourcePath: segment.url,
|
|
1833
1870
|
offset: segment.startRange ?? 0,
|
|
1834
1871
|
length: segment.expectLength ?? null
|
|
1835
1872
|
});
|
|
1836
|
-
const createInitSegment = (segment) => ({
|
|
1873
|
+
const createInitSegment = async (input, segment) => ({
|
|
1837
1874
|
timestamp: 0,
|
|
1838
1875
|
duration: 0,
|
|
1839
1876
|
relativeToUnixEpoch: false,
|
|
1840
1877
|
firstSegment: null,
|
|
1841
1878
|
sequenceNumber: segment.sequenceNumber,
|
|
1842
|
-
location: getSegmentLocation(segment),
|
|
1879
|
+
location: await getSegmentLocation(input, segment),
|
|
1843
1880
|
encryption: segment.encryption,
|
|
1844
1881
|
initSegment: null,
|
|
1845
1882
|
lastProgramDateTimeSeconds: null
|
|
1846
1883
|
});
|
|
1847
|
-
const trackToDashSegments = (internalTrack) => {
|
|
1884
|
+
const trackToDashSegments = async (input, internalTrack) => {
|
|
1848
1885
|
const mediaSegments = internalTrack.track.mediaSegments;
|
|
1849
1886
|
if (mediaSegments.length === 0) return [];
|
|
1850
1887
|
let nextTimestamp = 0;
|
|
@@ -1857,7 +1894,7 @@ const trackToDashSegments = (internalTrack) => {
|
|
|
1857
1894
|
relativeToUnixEpoch: false,
|
|
1858
1895
|
firstSegment: null,
|
|
1859
1896
|
sequenceNumber: mediaSegment.sequenceNumber,
|
|
1860
|
-
location: getSegmentLocation(mediaSegment),
|
|
1897
|
+
location: await getSegmentLocation(input, mediaSegment),
|
|
1861
1898
|
encryption: mediaSegment.encryption,
|
|
1862
1899
|
initSegment: null,
|
|
1863
1900
|
lastProgramDateTimeSeconds: null
|
|
@@ -1866,7 +1903,7 @@ const trackToDashSegments = (internalTrack) => {
|
|
|
1866
1903
|
nextTimestamp = timestamp + mediaSegment.duration;
|
|
1867
1904
|
}
|
|
1868
1905
|
const firstSegment = segments[0] ?? null;
|
|
1869
|
-
const initSegment = internalTrack.track.initSegment ? createInitSegment(internalTrack.track.initSegment) : null;
|
|
1906
|
+
const initSegment = internalTrack.track.initSegment ? await createInitSegment(input, internalTrack.track.initSegment) : null;
|
|
1870
1907
|
for (const segment of segments) {
|
|
1871
1908
|
segment.firstSegment = firstSegment;
|
|
1872
1909
|
segment.initSegment = initSegment;
|
|
@@ -1902,8 +1939,9 @@ var DashSegmentedInput = class {
|
|
|
1902
1939
|
})();
|
|
1903
1940
|
}
|
|
1904
1941
|
async updateSegments() {
|
|
1942
|
+
const input = this.demuxer.input;
|
|
1905
1943
|
await this.demuxer.refreshTrackSegments(this.internalTrack);
|
|
1906
|
-
this.segments = trackToDashSegments(this.internalTrack);
|
|
1944
|
+
this.segments = await trackToDashSegments(input, this.internalTrack);
|
|
1907
1945
|
}
|
|
1908
1946
|
getRemainingWaitTimeMs() {
|
|
1909
1947
|
if (!this.internalTrack.track.isLive) return 0;
|
|
@@ -1967,7 +2005,7 @@ var DashSegmentedInput = class {
|
|
|
1967
2005
|
if (segment.initSegment && segment.initSegment !== segment) initInput = this.getInputForSegment(segment.initSegment);
|
|
1968
2006
|
const formatOptions = { ...input._formatOptions };
|
|
1969
2007
|
const segmentInput = preserveSubtitleBackingsOnInput(new Input$1({
|
|
1970
|
-
source: new CustomPathedSource(segment.location.
|
|
2008
|
+
source: new CustomPathedSource(segment.location.sourcePath, async (request) => {
|
|
1971
2009
|
if (!request.isRoot) throw new Error("Nested requests are not supported for DASH segments.");
|
|
1972
2010
|
const proxiedRequest = {
|
|
1973
2011
|
...request,
|
|
@@ -2761,11 +2799,10 @@ var DashDemuxer = class {
|
|
|
2761
2799
|
}
|
|
2762
2800
|
async refreshTracks(tracks) {
|
|
2763
2801
|
if (!tracks.length) return;
|
|
2764
|
-
const response = await this.
|
|
2765
|
-
const rawText = await response.text();
|
|
2802
|
+
const response = await this.fetchManifestText(this.manifestUrl).catch(() => this.fetchManifestText(this.originalUrl));
|
|
2766
2803
|
this.manifestUrl = response.url;
|
|
2767
2804
|
this.resetManifestUrls();
|
|
2768
|
-
const nextTracks = this.extractTracks(
|
|
2805
|
+
const nextTracks = this.extractTracks(response.text);
|
|
2769
2806
|
for (const track of tracks) {
|
|
2770
2807
|
const nextTrack = this.findMatchingTrack(nextTracks, track);
|
|
2771
2808
|
if (!nextTrack) continue;
|
|
@@ -2778,10 +2815,23 @@ var DashDemuxer = class {
|
|
|
2778
2815
|
track.subtitleGroupId = nextTrack.subtitleGroupId;
|
|
2779
2816
|
}
|
|
2780
2817
|
}
|
|
2781
|
-
async
|
|
2782
|
-
const
|
|
2783
|
-
|
|
2784
|
-
|
|
2818
|
+
async fetchManifestText(url) {
|
|
2819
|
+
const manifestRef = await resolvePathedSourceRequest(this.input.source, {
|
|
2820
|
+
path: url,
|
|
2821
|
+
isRoot: true
|
|
2822
|
+
});
|
|
2823
|
+
const manifestSource = manifestRef.source;
|
|
2824
|
+
try {
|
|
2825
|
+
const resolvedUrl = getSourcePath(manifestSource);
|
|
2826
|
+
if (!resolvedUrl) throw new Error("DASH manifest requests must resolve to a pathed source.");
|
|
2827
|
+
const response = await fetchDashManifest(manifestSource, resolvedUrl);
|
|
2828
|
+
return {
|
|
2829
|
+
text: await response.text(),
|
|
2830
|
+
url: response.url || resolvedUrl
|
|
2831
|
+
};
|
|
2832
|
+
} finally {
|
|
2833
|
+
manifestRef.free();
|
|
2834
|
+
}
|
|
2785
2835
|
}
|
|
2786
2836
|
resetManifestUrls() {
|
|
2787
2837
|
this.mpdUrl = this.manifestUrl;
|