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 +51 -8
- package/dist/index.mjs +204 -10
- package/package.json +7 -7
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 =
|
|
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<
|
|
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,
|
|
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
|
|
1499
|
-
const
|
|
1500
|
-
|
|
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 [
|
|
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(
|
|
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 [
|
|
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,
|
|
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
|
+
"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.
|
|
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.
|
|
59
|
-
"oxfmt": "^0.
|
|
60
|
-
"oxlint": "^1.
|
|
61
|
-
"tsdown": "^0.22.
|
|
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.
|
|
63
|
+
"vitest": "^4.1.7"
|
|
64
64
|
},
|
|
65
65
|
"scripts": {
|
|
66
66
|
"test": "vitest",
|