dasha 4.3.0 → 4.4.0

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
@@ -1,6 +1,4 @@
1
- import * as _$mediabunny from "mediabunny";
2
1
  import { AudioCodec as AudioCodec$1, DurationMetadataRequestOptions, EncodedPacket, FilePathSource, HLS, HLS_FORMATS, Input as Input$1, InputAudioTrack as InputAudioTrack$1, InputFormat, InputOptions, InputTrack as InputTrack$2, InputTrackQuery, InputTrackQuery as InputTrackQuery$1, InputVideoTrack as InputVideoTrack$1, MP3, MP4, MaybePromise, MediaCodec as MediaCodec$1, MetadataTags, PacketRetrievalOptions, PathedSource, Source, SourceRef, SubtitleCodec as SubtitleCodec$1, TrackDisposition, UrlSource, VideoCodec as VideoCodec$1, asc, desc, prefer } from "mediabunny";
3
- import * as _$_xmldom_xmldom0 from "@xmldom/xmldom";
4
2
 
5
3
  //#region src/mediabunny.d.ts
6
4
  type Segment$1 = {
@@ -104,7 +102,7 @@ declare const ROLE_TYPE: {
104
102
  type RoleType = (typeof ROLE_TYPE)[keyof typeof ROLE_TYPE];
105
103
  //#endregion
106
104
  //#region src/dash/dash-misc.d.ts
107
- type Element = _$_xmldom_xmldom0.Element;
105
+ type Element = import('@xmldom/xmldom').Element;
108
106
  type DashTrackType = 'video' | 'audio' | 'subtitle';
109
107
  type DashEncryptionData = {
110
108
  method: string;
@@ -231,7 +229,7 @@ declare class DashSegmentedInput {
231
229
  firstTrackPromise: Promise<TrackWithBacking> | null;
232
230
  packetInfos: WeakMap<EncodedPacket, PacketInfo>;
233
231
  firstSegmentFirstTimestamps: WeakMap<DashSegment, number>;
234
- firstTimestampCache: WeakMap<Input$1<_$mediabunny.Source>, number>;
232
+ firstTimestampCache: WeakMap<Input$1<import("mediabunny").Source>, number>;
235
233
  constructor(internalTrack: DashInternalTrack);
236
234
  runUpdateSegments(): Promise<void>;
237
235
  updateSegments(): Promise<void>;
@@ -396,6 +394,7 @@ declare abstract class DashTrackBackingBase {
396
394
  getNextKeyPacket(packet: EncodedPacket, options: PacketRetrievalOptions): Promise<EncodedPacket | null>;
397
395
  getSegmentedInput(): DashSegmentedInput;
398
396
  getSegments(): Promise<DashSegment[]>;
397
+ refreshSegments(): Promise<DashSegment[]>;
399
398
  }
400
399
  declare class DashInputVideoTrackBacking extends DashTrackBackingBase {
401
400
  internalTrack: InternalVideoTrack;
@@ -557,6 +556,7 @@ declare module 'mediabunny' {
557
556
  type SegmentAccessMethods = {
558
557
  getSegmentedInput(): HlsSegmentedInput | DashSegmentedInput;
559
558
  getSegments(): Promise<(HlsSegment | DashSegment)[]>;
559
+ refreshSegments(): Promise<(HlsSegment | DashSegment)[]>;
560
560
  };
561
561
  type TrackMetadataOverrideMethods = {
562
562
  setLanguageCode(value: string): void;
@@ -580,6 +580,14 @@ type InputSubtitleTrackMetadata = {
580
580
  name?: string | null;
581
581
  pairWith?: InputVideoTrack | Iterable<InputVideoTrack>;
582
582
  };
583
+ type InputAudioSource = Source | SourceRef<Source>;
584
+ type InputAudioTrackPairing = InputVideoTrack | Iterable<InputVideoTrack> | 'all' | 'primary' | false;
585
+ type InputAudioTracksOptions = {
586
+ filter?: InputTrackQuery$1<InputAudioTrack>['filter'];
587
+ formats?: readonly InputFormat[];
588
+ pairWith?: InputAudioTrackPairing;
589
+ sortBy?: InputTrackQuery$1<InputAudioTrack>['sortBy'];
590
+ };
583
591
  type SegmentableBacking = {
584
592
  getId(): number;
585
593
  getNumber(): number;
@@ -605,11 +613,46 @@ type TrackBacking = NativeTrackBacking | SegmentableBacking;
605
613
  declare const BACKING_TYPE_SUBTITLE = "subtitle";
606
614
  declare const BACKING_TYPE_AUDIO = "audio";
607
615
  declare const BACKING_TYPE_VIDEO = "video";
616
+ declare class ImportedAudioTrackBacking {
617
+ #private;
618
+ constructor(params: {
619
+ backing: SegmentableBacking;
620
+ id: number;
621
+ number: number;
622
+ source: Source;
623
+ });
624
+ getType(): string;
625
+ getId(): number;
626
+ getNumber(): number;
627
+ getCodec(): MediaCodec$1 | Promise<MediaCodec$1 | null> | null;
628
+ getInternalCodecId(): string | number | Uint8Array<ArrayBufferLike> | Promise<string | number | Uint8Array<ArrayBufferLike> | null> | null;
629
+ getName(): string | Promise<string | null> | null;
630
+ getLanguageCode(): string | Promise<string>;
631
+ getTimeResolution(): number | Promise<number>;
632
+ isRelativeToUnixEpoch(): boolean | Promise<boolean>;
633
+ getDisposition(): {};
634
+ getPairingMask(): bigint;
635
+ getBitrate(): number | Promise<number | null> | null;
636
+ getAverageBitrate(): number | Promise<number | null> | null;
637
+ getDurationFromMetadata(options: unknown): Promise<number | null>;
638
+ getLiveRefreshInterval(): Promise<number | null>;
639
+ getHasOnlyKeyPackets(): boolean;
640
+ getDecoderConfig(): Promise<VideoDecoderConfig | AudioDecoderConfig | null>;
641
+ getMetadataCodecParameterString(): string | Promise<string | null> | null;
642
+ getNumberOfChannels(): number | Promise<number>;
643
+ getSampleRate(): number | Promise<number>;
644
+ getFirstPacket(options: unknown): Promise<EncodedPacket | null>;
645
+ getPacket(timestamp: number, options: unknown): Promise<EncodedPacket | null>;
646
+ getNextPacket(packet: EncodedPacket, options: unknown): Promise<EncodedPacket | null>;
647
+ getKeyPacket(timestamp: number, options: unknown): Promise<EncodedPacket | null>;
648
+ getNextKeyPacket(packet: EncodedPacket, options: unknown): Promise<EncodedPacket | null>;
649
+ getSegmentedInput(): any;
650
+ }
608
651
  declare const preserveSubtitleBackingsOnInput: (input: Input$1) => Input$1<Source>;
609
652
  declare class SegmentedMediabunnyInput<S extends Source = Source> extends Input$1<S> {
610
653
  #private;
611
654
  _wrapBackingAsTrack(backing: TrackBacking): InputTrack$1;
612
- _getSyntheticTrackBackings(type?: typeof BACKING_TYPE_VIDEO | typeof BACKING_TYPE_AUDIO | typeof BACKING_TYPE_SUBTITLE): Promise<(ExternalSubtitleTrackBacking | HlsSubtitleTrackBacking)[]>;
655
+ _getSyntheticTrackBackings(type?: typeof BACKING_TYPE_VIDEO | typeof BACKING_TYPE_AUDIO | typeof BACKING_TYPE_SUBTITLE): Promise<(ImportedAudioTrackBacking | ExternalSubtitleTrackBacking | HlsSubtitleTrackBacking)[]>;
613
656
  getTracks(query?: InputTrackQuery$1<InputTrack$1>): Promise<InputTrack$1[]>;
614
657
  getVideoTracks(query?: InputTrackQuery$1<InputVideoTrack>): Promise<InputVideoTrack[]>;
615
658
  getAudioTracks(query?: InputTrackQuery$1<InputAudioTrack>): Promise<InputAudioTrack[]>;
@@ -617,6 +660,8 @@ declare class SegmentedMediabunnyInput<S extends Source = Source> extends Input$
617
660
  getPrimaryVideoTrack(query?: InputTrackQuery$1<InputVideoTrack>): Promise<InputVideoTrack | null>;
618
661
  getPrimaryAudioTrack(query?: InputTrackQuery$1<InputAudioTrack>): Promise<InputAudioTrack | null>;
619
662
  addSubtitleTrack(source: InputSubtitleSource, metadata?: InputSubtitleTrackMetadata): InputSubtitleTrack;
663
+ addAudioTracks(source: InputAudioSource, options?: InputAudioTracksOptions): Promise<InputAudioTrack[]>;
664
+ dispose(): void;
620
665
  }
621
666
  //#endregion
622
667
  //#region src/index.d.ts
@@ -629,8 +674,6 @@ declare class Input<S extends Source = Source> extends SegmentedMediabunnyInput<
629
674
  constructor(options: DashaInputOptions<S>);
630
675
  }
631
676
  declare const isInput: (value: unknown) => value is Input;
632
- declare const getSegmentedInput: (track: InputTrack$1) => InputSegmentedInput;
633
- declare const getSegments: (track: InputTrack$1) => Promise<InputSegment[]>;
634
677
  declare const ALL_FORMATS: InputFormat[];
635
678
  //#endregion
636
- export { ALL_FORMATS, type AudioCodec, DASH, DASH_FORMATS, type DashSegment, type DashSegmentedInput, FilePathSource, HLS, HLS_FORMATS, type HlsSegment, type HlsSegmentedInput, Input, type InputAudioTrack, InputSegment, InputSegmentedInput, type InputSubtitleSource, type InputSubtitleTrack, type InputSubtitleTrackMetadata, type InputTrack$1 as InputTrack, type InputTrackQuery, type InputTrackWithBacking, type InputVideoTrack, MP3, MP4, type MaybePromise, type MediaCodec, type SubtitleCodec, UrlSource, type VideoCodec, type VideoDynamicRange, asc, desc, getSegmentedInput, getSegments, isInput, prefer, preserveSubtitleBackingsOnInput };
679
+ export { ALL_FORMATS, type AudioCodec, DASH, DASH_FORMATS, type DashSegment, type DashSegmentedInput, FilePathSource, HLS, HLS_FORMATS, type HlsSegment, type HlsSegmentedInput, Input, type InputAudioSource, type InputAudioTrack, type InputAudioTrackPairing, type InputAudioTracksOptions, InputSegment, InputSegmentedInput, type InputSubtitleSource, type InputSubtitleTrack, type InputSubtitleTrackMetadata, type InputTrack$1 as InputTrack, type InputTrackQuery, type InputTrackWithBacking, type InputVideoTrack, MP3, MP4, type MaybePromise, type MediaCodec, type SubtitleCodec, UrlSource, type VideoCodec, type VideoDynamicRange, asc, desc, isInput, prefer, preserveSubtitleBackingsOnInput };
package/dist/index.mjs CHANGED
@@ -1237,6 +1237,7 @@ const getHlsSubtitleTrackBackings = (input) => {
1237
1237
  //#endregion
1238
1238
  //#region src/mediabunny-input.ts
1239
1239
  const CUSTOM_SUBTITLE_TRACK_ID_OFFSET = 1e9;
1240
+ const CUSTOM_AUDIO_TRACK_ID_OFFSET = 2e9;
1240
1241
  const CUSTOM_PAIRING_BIT_START = 1024n;
1241
1242
  const EXTRA_PAIRING_MASK = Symbol.for("dasha.extra-pairing-mask");
1242
1243
  const ORIGINAL_GET_PAIRING_MASK = Symbol.for("dasha.original-get-pairing-mask");
@@ -1382,6 +1383,131 @@ const BACKING_TYPE_AUDIO = "audio";
1382
1383
  const BACKING_TYPE_VIDEO = "video";
1383
1384
  const BASE_INPUT_PATCHED = Symbol.for("dasha.base-mediabunny-input-patched");
1384
1385
  const PRESERVE_SUBTITLE_BACKINGS = Symbol.for("dasha.preserve-subtitle-backings");
1386
+ const getDefaultAudioTrackFormats = (source) => {
1387
+ return isLikelyDashPath(source instanceof SourceRef ? source.source : source) ? [DASH, ...ALL_FORMATS$1] : [...ALL_FORMATS$1, DASH];
1388
+ };
1389
+ var WholeResourceAudioSegmentedInput = class {
1390
+ segments = [];
1391
+ #source;
1392
+ constructor(source) {
1393
+ this.#source = source;
1394
+ }
1395
+ async runUpdateSegments() {
1396
+ if (this.segments.length > 0) return;
1397
+ const sourceWithRootPath = this.#source;
1398
+ if (typeof sourceWithRootPath.rootPath !== "string") return;
1399
+ const segment = {
1400
+ timestamp: 0,
1401
+ duration: 0,
1402
+ relativeToUnixEpoch: false,
1403
+ firstSegment: null,
1404
+ sequenceNumber: 0,
1405
+ location: {
1406
+ path: sourceWithRootPath.rootPath,
1407
+ offset: 0,
1408
+ length: null
1409
+ },
1410
+ encryption: null,
1411
+ initSegment: null,
1412
+ lastProgramDateTimeSeconds: null
1413
+ };
1414
+ segment.firstSegment = segment;
1415
+ this.segments = [segment];
1416
+ }
1417
+ };
1418
+ var ImportedAudioTrackBacking = class {
1419
+ #backing;
1420
+ #id;
1421
+ #number;
1422
+ #wholeResourceSegmentedInput;
1423
+ constructor(params) {
1424
+ this.#backing = params.backing;
1425
+ this.#id = params.id;
1426
+ this.#number = params.number;
1427
+ this.#wholeResourceSegmentedInput = new WholeResourceAudioSegmentedInput(params.source);
1428
+ }
1429
+ getType() {
1430
+ return BACKING_TYPE_AUDIO;
1431
+ }
1432
+ getId() {
1433
+ return this.#id;
1434
+ }
1435
+ getNumber() {
1436
+ return this.#number;
1437
+ }
1438
+ getCodec() {
1439
+ return this.#backing.getCodec();
1440
+ }
1441
+ getInternalCodecId() {
1442
+ return this.#backing.getInternalCodecId?.() ?? null;
1443
+ }
1444
+ getName() {
1445
+ return this.#backing.getName?.() ?? null;
1446
+ }
1447
+ getLanguageCode() {
1448
+ return this.#backing.getLanguageCode?.() ?? "und";
1449
+ }
1450
+ getTimeResolution() {
1451
+ return this.#backing.getTimeResolution?.() ?? 1e3;
1452
+ }
1453
+ isRelativeToUnixEpoch() {
1454
+ return this.#backing.isRelativeToUnixEpoch?.() ?? false;
1455
+ }
1456
+ getDisposition() {
1457
+ return this.#backing.getDisposition?.() ?? {};
1458
+ }
1459
+ getPairingMask() {
1460
+ return 0n;
1461
+ }
1462
+ getBitrate() {
1463
+ return this.#backing.getBitrate?.() ?? null;
1464
+ }
1465
+ getAverageBitrate() {
1466
+ return this.#backing.getAverageBitrate?.() ?? null;
1467
+ }
1468
+ getDurationFromMetadata(options) {
1469
+ return this.#backing.getDurationFromMetadata?.(options) ?? Promise.resolve(null);
1470
+ }
1471
+ getLiveRefreshInterval() {
1472
+ return this.#backing.getLiveRefreshInterval?.() ?? Promise.resolve(null);
1473
+ }
1474
+ getHasOnlyKeyPackets() {
1475
+ return true;
1476
+ }
1477
+ getDecoderConfig() {
1478
+ return this.#backing.getDecoderConfig?.() ?? Promise.resolve(null);
1479
+ }
1480
+ getMetadataCodecParameterString() {
1481
+ return this.#backing.getMetadataCodecParameterString?.() ?? null;
1482
+ }
1483
+ getNumberOfChannels() {
1484
+ return this.#backing.getNumberOfChannels?.() ?? 0;
1485
+ }
1486
+ getSampleRate() {
1487
+ return this.#backing.getSampleRate?.() ?? 0;
1488
+ }
1489
+ getFirstPacket(options) {
1490
+ return this.#backing.getFirstPacket?.(options) ?? Promise.resolve(null);
1491
+ }
1492
+ getPacket(timestamp, options) {
1493
+ return this.#backing.getPacket?.(timestamp, options) ?? Promise.resolve(null);
1494
+ }
1495
+ getNextPacket(packet, options) {
1496
+ return this.#backing.getNextPacket?.(packet, options) ?? Promise.resolve(null);
1497
+ }
1498
+ getKeyPacket(timestamp, options) {
1499
+ return this.#backing.getKeyPacket?.(timestamp, options) ?? Promise.resolve(null);
1500
+ }
1501
+ getNextKeyPacket(packet, options) {
1502
+ return this.#backing.getNextKeyPacket?.(packet, options) ?? Promise.resolve(null);
1503
+ }
1504
+ getSegmentedInput() {
1505
+ if (this.#backing.getSegmentedInput) return this.#backing.getSegmentedInput();
1506
+ const hlsBacking = this.#backing;
1507
+ if (hlsBacking.internalTrack?.demuxer?.getSegmentedInputForPath) return hlsBacking.internalTrack.demuxer.getSegmentedInputForPath(hlsBacking.internalTrack.fullPath);
1508
+ return this.#wholeResourceSegmentedInput;
1509
+ }
1510
+ };
1385
1511
  const getBackingType = (backing) => backing.getType?.();
1386
1512
  const queryWrappedTracks = (input, backings, query) => {
1387
1513
  return queryTracks(backings.map((backing) => input._wrapBackingAsTrack(backing)), query);
@@ -1430,6 +1556,11 @@ const addSegmentAccess = (track) => new Proxy(track, { get(target, prop) {
1430
1556
  if (prop === "setLanguageCode") return (value) => setTrackLanguageCode(target, value);
1431
1557
  if (prop === "getSegmentedInput") return () => getSegmentedInputForTrack(target);
1432
1558
  if (prop === "getSegments") return async () => {
1559
+ const segmentedInput = getSegmentedInputForTrack(target);
1560
+ if (segmentedInput.segments.length === 0) await segmentedInput.runUpdateSegments();
1561
+ return segmentedInput.segments;
1562
+ };
1563
+ if (prop === "refreshSegments") return async () => {
1433
1564
  const segmentedInput = getSegmentedInputForTrack(target);
1434
1565
  await segmentedInput.runUpdateSegments();
1435
1566
  return segmentedInput.segments;
@@ -1474,13 +1605,17 @@ const preserveSubtitleBackingsOnInput = (input) => {
1474
1605
  Object.assign(input, { [PRESERVE_SUBTITLE_BACKINGS]: true });
1475
1606
  return input;
1476
1607
  };
1477
- var SegmentedMediabunnyInput = class extends Input$1 {
1608
+ var SegmentedMediabunnyInput = class SegmentedMediabunnyInput extends Input$1 {
1478
1609
  #trackCache = /* @__PURE__ */ new WeakMap();
1479
1610
  #subtitleTrackCache = /* @__PURE__ */ new WeakMap();
1480
1611
  #hlsSubtitleBackingsPromise = null;
1481
1612
  #customSubtitleBackings = [];
1613
+ #customAudioBackings = [];
1614
+ #audioInputs = [];
1482
1615
  #nextCustomSubtitleTrackId = CUSTOM_SUBTITLE_TRACK_ID_OFFSET;
1483
1616
  #nextCustomSubtitleTrackNumber = CUSTOM_SUBTITLE_TRACK_ID_OFFSET;
1617
+ #nextCustomAudioTrackId = CUSTOM_AUDIO_TRACK_ID_OFFSET;
1618
+ #nextCustomAudioTrackNumber = CUSTOM_AUDIO_TRACK_ID_OFFSET;
1484
1619
  #nextPairingBitIndex = null;
1485
1620
  async #queryTracks(query, type) {
1486
1621
  const internalInput = this;
@@ -1495,9 +1630,11 @@ var SegmentedMediabunnyInput = class extends Input$1 {
1495
1630
  return wrapped;
1496
1631
  }
1497
1632
  async _getSyntheticTrackBackings(type) {
1498
- if (type && type !== BACKING_TYPE_SUBTITLE) return [];
1499
- const backings = [...this.#customSubtitleBackings];
1500
- if (await this.getFormat() !== HLS$1) return backings;
1633
+ if (type === BACKING_TYPE_VIDEO) return [];
1634
+ const audioBackings = type !== BACKING_TYPE_SUBTITLE ? [...this.#customAudioBackings] : [];
1635
+ const backings = type !== BACKING_TYPE_AUDIO ? [...this.#customSubtitleBackings] : [];
1636
+ if (type === BACKING_TYPE_AUDIO) return audioBackings;
1637
+ if (await this.getFormat() !== HLS$1) return [...audioBackings, ...backings];
1501
1638
  if (!this.#hlsSubtitleBackingsPromise) {
1502
1639
  const promise = getHlsSubtitleTrackBackings(this).catch((error) => {
1503
1640
  if (this.#hlsSubtitleBackingsPromise === promise) this.#hlsSubtitleBackingsPromise = null;
@@ -1505,7 +1642,11 @@ var SegmentedMediabunnyInput = class extends Input$1 {
1505
1642
  });
1506
1643
  this.#hlsSubtitleBackingsPromise = promise;
1507
1644
  }
1508
- return [...backings, ...await this.#hlsSubtitleBackingsPromise];
1645
+ return [
1646
+ ...audioBackings,
1647
+ ...backings,
1648
+ ...await this.#hlsSubtitleBackingsPromise
1649
+ ];
1509
1650
  }
1510
1651
  #wrapSubtitleBacking(backing) {
1511
1652
  const existing = this.#subtitleTrackCache.get(backing);
@@ -1551,6 +1692,31 @@ var SegmentedMediabunnyInput = class extends Input$1 {
1551
1692
  this.#customSubtitleBackings.push(backing);
1552
1693
  return this._wrapBackingAsTrack(backing);
1553
1694
  }
1695
+ async addAudioTracks(source, options = {}) {
1696
+ const audioInput = new SegmentedMediabunnyInput({
1697
+ source,
1698
+ formats: [...options.formats ?? getDefaultAudioTrackFormats(source)]
1699
+ });
1700
+ this.#audioInputs.push(audioInput);
1701
+ const audioTracks = await audioInput.getAudioTracks({
1702
+ filter: options.filter,
1703
+ sortBy: options.sortBy
1704
+ });
1705
+ const pairWith = await this.#getAudioPairingVideoTracks(options.pairWith);
1706
+ const importedTracks = [];
1707
+ for (const audioTrack of audioTracks) {
1708
+ const backing = new ImportedAudioTrackBacking({
1709
+ id: this.#nextCustomAudioTrackId++,
1710
+ number: this.#nextCustomAudioTrackNumber++,
1711
+ backing: getTrackBacking(audioTrack),
1712
+ source: audioInput.source
1713
+ });
1714
+ this.#pairAudioBacking(backing, pairWith);
1715
+ this.#customAudioBackings.push(backing);
1716
+ importedTracks.push(this._wrapBackingAsTrack(backing));
1717
+ }
1718
+ return importedTracks;
1719
+ }
1554
1720
  #takeSubtitleSourceRef(source) {
1555
1721
  const rawSource = source instanceof SourceRef ? source.source : source;
1556
1722
  if (!(rawSource instanceof Object) || !("rootPath" in rawSource) || !("ref" in rawSource) || typeof rawSource.ref !== "function") throw new TypeError("source must be a pathed source such as UrlSource or FilePathSource.");
@@ -1567,13 +1733,28 @@ var SegmentedMediabunnyInput = class extends Input$1 {
1567
1733
  }
1568
1734
  return tracks;
1569
1735
  }
1736
+ async #getAudioPairingVideoTracks(pairWith) {
1737
+ if (pairWith === false) return [];
1738
+ if (!pairWith || pairWith === "all") return this.getVideoTracks();
1739
+ if (pairWith === "primary") {
1740
+ const primaryVideoTrack = await this.getPrimaryVideoTrack();
1741
+ return primaryVideoTrack ? [primaryVideoTrack] : [];
1742
+ }
1743
+ return this.#toPairableVideoTracks(pairWith);
1744
+ }
1570
1745
  #isIterable(value) {
1571
1746
  return typeof value === "object" && value !== null && Symbol.iterator in value;
1572
1747
  }
1573
1748
  #pairSubtitleBacking(subtitleBacking, videoTracks) {
1749
+ this.#pairBackingWithVideoTracks(subtitleBacking, videoTracks);
1750
+ }
1751
+ #pairAudioBacking(audioBacking, videoTracks) {
1752
+ this.#pairBackingWithVideoTracks(audioBacking, videoTracks);
1753
+ }
1754
+ #pairBackingWithVideoTracks(backing, videoTracks) {
1574
1755
  for (const track of videoTracks) {
1575
1756
  const bit = this.#allocatePairingBit();
1576
- this.#appendPairingMask(subtitleBacking, bit);
1757
+ this.#appendPairingMask(backing, bit);
1577
1758
  this.#appendPairingMask(track._backing, bit);
1578
1759
  }
1579
1760
  }
@@ -1585,7 +1766,11 @@ var SegmentedMediabunnyInput = class extends Input$1 {
1585
1766
  #getInitialPairingBitIndex() {
1586
1767
  const loadedBackings = [...this._trackBackingsCache ?? []];
1587
1768
  let maxBitIndex = -1n;
1588
- for (const backing of [...loadedBackings, ...this.#customSubtitleBackings]) {
1769
+ for (const backing of [
1770
+ ...loadedBackings,
1771
+ ...this.#customSubtitleBackings,
1772
+ ...this.#customAudioBackings
1773
+ ]) {
1589
1774
  const mask = backing.getPairingMask?.() ?? 0n;
1590
1775
  if (mask === 0n) continue;
1591
1776
  const bitIndex = BigInt(mask.toString(2).length - 1);
@@ -1600,6 +1785,12 @@ var SegmentedMediabunnyInput = class extends Input$1 {
1600
1785
  patchedBacking[ORIGINAL_GET_PAIRING_MASK] = backing.getPairingMask?.bind(backing) ?? (() => 0n);
1601
1786
  Object.assign(backing, { getPairingMask: () => (patchedBacking[ORIGINAL_GET_PAIRING_MASK]?.() ?? 0n) | (patchedBacking[EXTRA_PAIRING_MASK] ?? 0n) });
1602
1787
  }
1788
+ dispose() {
1789
+ if (this.disposed) return;
1790
+ super.dispose();
1791
+ for (const input of this.#audioInputs) input.dispose();
1792
+ this.#audioInputs.length = 0;
1793
+ }
1603
1794
  };
1604
1795
  //#endregion
1605
1796
  //#region src/dash/dash-segmented-input.ts
@@ -2670,6 +2861,11 @@ var DashTrackBackingBase = class {
2670
2861
  return this.internalTrack.demuxer.getSegmentedInputForTrack(this.internalTrack);
2671
2862
  }
2672
2863
  async getSegments() {
2864
+ const segmentedInput = this.getSegmentedInput();
2865
+ if (segmentedInput.segments.length === 0) await segmentedInput.runUpdateSegments();
2866
+ return segmentedInput.segments;
2867
+ }
2868
+ async refreshSegments() {
2673
2869
  const segmentedInput = this.getSegmentedInput();
2674
2870
  await segmentedInput.runUpdateSegments();
2675
2871
  return segmentedInput.segments;
@@ -2787,8 +2983,6 @@ var Input = class extends SegmentedMediabunnyInput {
2787
2983
  }
2788
2984
  };
2789
2985
  const isInput = (value) => value instanceof Input;
2790
- const getSegmentedInput = (track) => track.getSegmentedInput();
2791
- const getSegments = async (track) => track.getSegments();
2792
2986
  const ALL_FORMATS = [...ALL_FORMATS$1, DASH];
2793
2987
  //#endregion
2794
- export { ALL_FORMATS, DASH, DASH_FORMATS, FilePathSource, HLS, HLS_FORMATS, Input, MP3, MP4, UrlSource, asc, desc, getSegmentedInput, getSegments, isInput, prefer, preserveSubtitleBackingsOnInput };
2988
+ export { ALL_FORMATS, DASH, DASH_FORMATS, FilePathSource, HLS, HLS_FORMATS, Input, MP3, MP4, UrlSource, asc, desc, isInput, prefer, preserveSubtitleBackingsOnInput };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dasha",
3
- "version": "4.3.0",
3
+ "version": "4.4.0",
4
4
  "description": "Streaming manifest parser",
5
5
  "files": [
6
6
  "dist"
@@ -45,7 +45,7 @@
45
45
  }
46
46
  ],
47
47
  "engines": {
48
- "node": ">=22.18"
48
+ "node": ">=22.19"
49
49
  },
50
50
  "dependencies": {
51
51
  "@xmldom/xmldom": "^0.9.10",
@@ -55,12 +55,12 @@
55
55
  "mediabunny": "^1.45.2"
56
56
  },
57
57
  "devDependencies": {
58
- "@types/node": "^25.8.0",
59
- "oxfmt": "^0.50.0",
60
- "oxlint": "^1.65.0",
61
- "tsdown": "^0.22.0",
58
+ "@types/node": "^25.9.1",
59
+ "oxfmt": "^0.52.0",
60
+ "oxlint": "^1.67.0",
61
+ "tsdown": "^0.22.1",
62
62
  "typescript": "^6.0.3",
63
- "vitest": "^4.1.6"
63
+ "vitest": "^4.1.7"
64
64
  },
65
65
  "scripts": {
66
66
  "test": "vitest",