dasha 4.4.3 → 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 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
- fetchManifest(url: string): Promise<Response>;
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());
@@ -333,30 +348,45 @@ const getSourceHeaders$1 = (source) => {
333
348
  const getSourceFetch = (source) => {
334
349
  return ("_options" in source && source._options && typeof source._options === "object" ? source._options : void 0)?.fetchFn ?? fetch;
335
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
+ };
336
356
  const parseOriginalUrlFromManifest = (text) => text.match(/<!--\s*URL:\s*([^\n]+?)\s*-->/)?.[1]?.trim();
337
357
  const loadDashManifest = async (source) => {
338
358
  const manifestPath = getSourcePath(source);
339
359
  if (!manifestPath) throw new Error("DASH input currently requires a pathed source such as UrlSource.");
340
- if (manifestPath.startsWith("http://") || manifestPath.startsWith("https://")) {
341
- const response = await getSourceFetch(source)(manifestPath, { headers: getSourceHeaders$1(source) });
342
- if (!response.ok) throw new Error(`Failed to fetch DASH manifest: ${response.status} ${response.statusText} (${response.url})`);
343
- return {
344
- text: await response.text(),
345
- url: response.url
346
- };
347
- }
348
- if (manifestPath.startsWith("file:")) {
349
- const text = await readFile(new URL(manifestPath), "utf8");
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");
350
383
  return {
351
384
  text,
352
- url: parseOriginalUrlFromManifest(text) ?? manifestPath
385
+ url: parseOriginalUrlFromManifest(text) ?? resolvedManifestPath
353
386
  };
387
+ } finally {
388
+ manifestRef.free();
354
389
  }
355
- const text = await readFile(manifestPath, "utf8");
356
- return {
357
- text,
358
- url: parseOriginalUrlFromManifest(text) ?? manifestPath
359
- };
360
390
  };
361
391
  const isLikelyDashPath = (source) => {
362
392
  const path = getSourcePath(source);
@@ -1831,23 +1861,27 @@ const getLeastRecentlyUsedIndex = (entries) => {
1831
1861
  }
1832
1862
  return bestIndex;
1833
1863
  };
1834
- const getSegmentLocation = (segment) => ({
1835
- path: segment.url,
1864
+ const getSegmentLocation = async (input, segment) => ({
1865
+ path: await resolvePathedSourcePath(input.source, {
1866
+ path: segment.url,
1867
+ isRoot: false
1868
+ }),
1869
+ sourcePath: segment.url,
1836
1870
  offset: segment.startRange ?? 0,
1837
1871
  length: segment.expectLength ?? null
1838
1872
  });
1839
- const createInitSegment = (segment) => ({
1873
+ const createInitSegment = async (input, segment) => ({
1840
1874
  timestamp: 0,
1841
1875
  duration: 0,
1842
1876
  relativeToUnixEpoch: false,
1843
1877
  firstSegment: null,
1844
1878
  sequenceNumber: segment.sequenceNumber,
1845
- location: getSegmentLocation(segment),
1879
+ location: await getSegmentLocation(input, segment),
1846
1880
  encryption: segment.encryption,
1847
1881
  initSegment: null,
1848
1882
  lastProgramDateTimeSeconds: null
1849
1883
  });
1850
- const trackToDashSegments = (internalTrack) => {
1884
+ const trackToDashSegments = async (input, internalTrack) => {
1851
1885
  const mediaSegments = internalTrack.track.mediaSegments;
1852
1886
  if (mediaSegments.length === 0) return [];
1853
1887
  let nextTimestamp = 0;
@@ -1860,7 +1894,7 @@ const trackToDashSegments = (internalTrack) => {
1860
1894
  relativeToUnixEpoch: false,
1861
1895
  firstSegment: null,
1862
1896
  sequenceNumber: mediaSegment.sequenceNumber,
1863
- location: getSegmentLocation(mediaSegment),
1897
+ location: await getSegmentLocation(input, mediaSegment),
1864
1898
  encryption: mediaSegment.encryption,
1865
1899
  initSegment: null,
1866
1900
  lastProgramDateTimeSeconds: null
@@ -1869,7 +1903,7 @@ const trackToDashSegments = (internalTrack) => {
1869
1903
  nextTimestamp = timestamp + mediaSegment.duration;
1870
1904
  }
1871
1905
  const firstSegment = segments[0] ?? null;
1872
- const initSegment = internalTrack.track.initSegment ? createInitSegment(internalTrack.track.initSegment) : null;
1906
+ const initSegment = internalTrack.track.initSegment ? await createInitSegment(input, internalTrack.track.initSegment) : null;
1873
1907
  for (const segment of segments) {
1874
1908
  segment.firstSegment = firstSegment;
1875
1909
  segment.initSegment = initSegment;
@@ -1905,8 +1939,9 @@ var DashSegmentedInput = class {
1905
1939
  })();
1906
1940
  }
1907
1941
  async updateSegments() {
1942
+ const input = this.demuxer.input;
1908
1943
  await this.demuxer.refreshTrackSegments(this.internalTrack);
1909
- this.segments = trackToDashSegments(this.internalTrack);
1944
+ this.segments = await trackToDashSegments(input, this.internalTrack);
1910
1945
  }
1911
1946
  getRemainingWaitTimeMs() {
1912
1947
  if (!this.internalTrack.track.isLive) return 0;
@@ -1970,7 +2005,7 @@ var DashSegmentedInput = class {
1970
2005
  if (segment.initSegment && segment.initSegment !== segment) initInput = this.getInputForSegment(segment.initSegment);
1971
2006
  const formatOptions = { ...input._formatOptions };
1972
2007
  const segmentInput = preserveSubtitleBackingsOnInput(new Input$1({
1973
- source: new CustomPathedSource(segment.location.path, async (request) => {
2008
+ source: new CustomPathedSource(segment.location.sourcePath, async (request) => {
1974
2009
  if (!request.isRoot) throw new Error("Nested requests are not supported for DASH segments.");
1975
2010
  const proxiedRequest = {
1976
2011
  ...request,
@@ -2764,11 +2799,10 @@ var DashDemuxer = class {
2764
2799
  }
2765
2800
  async refreshTracks(tracks) {
2766
2801
  if (!tracks.length) return;
2767
- const response = await this.fetchManifest(this.manifestUrl).catch(() => this.fetchManifest(this.originalUrl));
2768
- const rawText = await response.text();
2802
+ const response = await this.fetchManifestText(this.manifestUrl).catch(() => this.fetchManifestText(this.originalUrl));
2769
2803
  this.manifestUrl = response.url;
2770
2804
  this.resetManifestUrls();
2771
- const nextTracks = this.extractTracks(rawText);
2805
+ const nextTracks = this.extractTracks(response.text);
2772
2806
  for (const track of tracks) {
2773
2807
  const nextTrack = this.findMatchingTrack(nextTracks, track);
2774
2808
  if (!nextTrack) continue;
@@ -2781,10 +2815,23 @@ var DashDemuxer = class {
2781
2815
  track.subtitleGroupId = nextTrack.subtitleGroupId;
2782
2816
  }
2783
2817
  }
2784
- async fetchManifest(url) {
2785
- const response = await fetch(url, { headers: this.headers });
2786
- if (!response.ok) throw new Error(`Failed to fetch DASH manifest: ${response.status} ${response.statusText} (${response.url})`);
2787
- return response;
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
+ }
2788
2835
  }
2789
2836
  resetManifestUrls() {
2790
2837
  this.mpdUrl = this.manifestUrl;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dasha",
3
- "version": "4.4.3",
3
+ "version": "4.4.4",
4
4
  "description": "Streaming manifest parser",
5
5
  "files": [
6
6
  "dist"