dasha 4.2.2 → 4.3.1
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/README.md +24 -0
- package/dist/index.d.mts +10 -7
- package/dist/index.mjs +27 -4
- package/package.json +6 -6
package/README.md
CHANGED
|
@@ -131,6 +131,30 @@ async function getEnglishSubtitles() {
|
|
|
131
131
|
}
|
|
132
132
|
```
|
|
133
133
|
|
|
134
|
+
### Overriding track metadata
|
|
135
|
+
|
|
136
|
+
Some services expose track metadata outside the manifest. You can override the parsed language code on any dasha track, and the updated value will be visible through the regular query/filter APIs.
|
|
137
|
+
|
|
138
|
+
```ts
|
|
139
|
+
import { DASH_FORMATS, Input, UrlSource } from 'dasha';
|
|
140
|
+
|
|
141
|
+
async function getFrenchAudioTrack() {
|
|
142
|
+
const input = new Input({
|
|
143
|
+
source: new UrlSource('https://example.com/manifest.mpd'),
|
|
144
|
+
formats: DASH_FORMATS,
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
const audioTracks = await input.getAudioTracks();
|
|
148
|
+
const apiLanguageCode = 'fr';
|
|
149
|
+
|
|
150
|
+
audioTracks[0]?.setLanguageCode(apiLanguageCode);
|
|
151
|
+
|
|
152
|
+
return await input.getAudioTracks({
|
|
153
|
+
filter: async (track) => (await track.getLanguageCode()) === apiLanguageCode,
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
```
|
|
157
|
+
|
|
134
158
|
### Mediabunny with DASH support
|
|
135
159
|
|
|
136
160
|
> Only reading is supported
|
package/dist/index.d.mts
CHANGED
|
@@ -396,6 +396,7 @@ declare abstract class DashTrackBackingBase {
|
|
|
396
396
|
getNextKeyPacket(packet: EncodedPacket, options: PacketRetrievalOptions): Promise<EncodedPacket | null>;
|
|
397
397
|
getSegmentedInput(): DashSegmentedInput;
|
|
398
398
|
getSegments(): Promise<DashSegment[]>;
|
|
399
|
+
refreshSegments(): Promise<DashSegment[]>;
|
|
399
400
|
}
|
|
400
401
|
declare class DashInputVideoTrackBacking extends DashTrackBackingBase {
|
|
401
402
|
internalTrack: InternalVideoTrack;
|
|
@@ -557,6 +558,10 @@ declare module 'mediabunny' {
|
|
|
557
558
|
type SegmentAccessMethods = {
|
|
558
559
|
getSegmentedInput(): HlsSegmentedInput | DashSegmentedInput;
|
|
559
560
|
getSegments(): Promise<(HlsSegment | DashSegment)[]>;
|
|
561
|
+
refreshSegments(): Promise<(HlsSegment | DashSegment)[]>;
|
|
562
|
+
};
|
|
563
|
+
type TrackMetadataOverrideMethods = {
|
|
564
|
+
setLanguageCode(value: string): void;
|
|
560
565
|
};
|
|
561
566
|
type VideoDynamicRangeMethods = {
|
|
562
567
|
getDynamicRange(): Promise<VideoDynamicRange>;
|
|
@@ -564,10 +569,10 @@ type VideoDynamicRangeMethods = {
|
|
|
564
569
|
type MediabunnySubtitleTrackLike = InputTrack$2 & {
|
|
565
570
|
type: 'subtitle';
|
|
566
571
|
};
|
|
567
|
-
type InputTrack$1 = InputTrack$2 & SegmentAccessMethods;
|
|
568
|
-
type InputVideoTrack = InputVideoTrack$1 & SegmentAccessMethods & VideoDynamicRangeMethods;
|
|
569
|
-
type InputAudioTrack = InputAudioTrack$1 & SegmentAccessMethods;
|
|
570
|
-
type InputSubtitleTrack = MediabunnySubtitleTrackLike & SegmentAccessMethods;
|
|
572
|
+
type InputTrack$1 = InputTrack$2 & SegmentAccessMethods & TrackMetadataOverrideMethods;
|
|
573
|
+
type InputVideoTrack = InputVideoTrack$1 & SegmentAccessMethods & VideoDynamicRangeMethods & TrackMetadataOverrideMethods;
|
|
574
|
+
type InputAudioTrack = InputAudioTrack$1 & SegmentAccessMethods & TrackMetadataOverrideMethods;
|
|
575
|
+
type InputSubtitleTrack = MediabunnySubtitleTrackLike & SegmentAccessMethods & TrackMetadataOverrideMethods;
|
|
571
576
|
type InputSubtitleSource = PathedSource | SourceRef<PathedSource>;
|
|
572
577
|
type InputSubtitleTrackMetadata = {
|
|
573
578
|
codec?: SubtitleCodec | null;
|
|
@@ -626,8 +631,6 @@ declare class Input<S extends Source = Source> extends SegmentedMediabunnyInput<
|
|
|
626
631
|
constructor(options: DashaInputOptions<S>);
|
|
627
632
|
}
|
|
628
633
|
declare const isInput: (value: unknown) => value is Input;
|
|
629
|
-
declare const getSegmentedInput: (track: InputTrack$1) => InputSegmentedInput;
|
|
630
|
-
declare const getSegments: (track: InputTrack$1) => Promise<InputSegment[]>;
|
|
631
634
|
declare const ALL_FORMATS: InputFormat[];
|
|
632
635
|
//#endregion
|
|
633
|
-
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,
|
|
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, isInput, prefer, preserveSubtitleBackingsOnInput };
|
package/dist/index.mjs
CHANGED
|
@@ -1240,6 +1240,8 @@ const CUSTOM_SUBTITLE_TRACK_ID_OFFSET = 1e9;
|
|
|
1240
1240
|
const CUSTOM_PAIRING_BIT_START = 1024n;
|
|
1241
1241
|
const EXTRA_PAIRING_MASK = Symbol.for("dasha.extra-pairing-mask");
|
|
1242
1242
|
const ORIGINAL_GET_PAIRING_MASK = Symbol.for("dasha.original-get-pairing-mask");
|
|
1243
|
+
const TRACK_METADATA_OVERRIDES = Symbol.for("dasha.track-metadata-overrides");
|
|
1244
|
+
const ORIGINAL_GET_LANGUAGE_CODE = Symbol.for("dasha.original-get-language-code");
|
|
1243
1245
|
const HLS_VARIANT_INF_LINE = "#EXT-X-STREAM-INF:";
|
|
1244
1246
|
const HLS_DEMUXER_PATCHED = Symbol.for("dasha.hls-demuxer-patched");
|
|
1245
1247
|
const HLS_DEMUXER_METADATA_PATCH = Symbol.for("dasha.hls-demuxer-metadata-patch");
|
|
@@ -1406,15 +1408,33 @@ const patchBaseMediabunnyInput = () => {
|
|
|
1406
1408
|
prototype[BASE_INPUT_PATCHED] = true;
|
|
1407
1409
|
};
|
|
1408
1410
|
const getSegmentedInputForTrack = (track) => {
|
|
1409
|
-
const backing = track
|
|
1411
|
+
const backing = getTrackBacking(track);
|
|
1410
1412
|
if ("getSegmentedInput" in backing && typeof backing.getSegmentedInput === "function") return backing.getSegmentedInput();
|
|
1411
1413
|
const internalTrack = backing.internalTrack;
|
|
1412
1414
|
return internalTrack.demuxer.getSegmentedInputForPath(internalTrack.fullPath);
|
|
1413
1415
|
};
|
|
1416
|
+
const getTrackBacking = (track) => track._backing;
|
|
1417
|
+
const getTrackMetadataOverrides = (backing) => backing[TRACK_METADATA_OVERRIDES] ??= {};
|
|
1418
|
+
const ensureLanguageCodeOverridePatch = (backing) => {
|
|
1419
|
+
const patchedBacking = backing;
|
|
1420
|
+
if (patchedBacking[ORIGINAL_GET_LANGUAGE_CODE]) return patchedBacking;
|
|
1421
|
+
patchedBacking[ORIGINAL_GET_LANGUAGE_CODE] = backing.getLanguageCode?.bind(backing) ?? (() => "und");
|
|
1422
|
+
Object.assign(backing, { getLanguageCode: () => getTrackMetadataOverrides(patchedBacking).languageCode ?? patchedBacking[ORIGINAL_GET_LANGUAGE_CODE]?.() ?? "und" });
|
|
1423
|
+
return patchedBacking;
|
|
1424
|
+
};
|
|
1425
|
+
const setTrackLanguageCode = (track, value) => {
|
|
1426
|
+
getTrackMetadataOverrides(ensureLanguageCodeOverridePatch(getTrackBacking(track))).languageCode = value;
|
|
1427
|
+
};
|
|
1414
1428
|
const addSegmentAccess = (track) => new Proxy(track, { get(target, prop) {
|
|
1415
1429
|
if (prop === "getDynamicRange" && target instanceof InputVideoTrack) return () => getDynamicRangeForTrack(target);
|
|
1430
|
+
if (prop === "setLanguageCode") return (value) => setTrackLanguageCode(target, value);
|
|
1416
1431
|
if (prop === "getSegmentedInput") return () => getSegmentedInputForTrack(target);
|
|
1417
1432
|
if (prop === "getSegments") return async () => {
|
|
1433
|
+
const segmentedInput = getSegmentedInputForTrack(target);
|
|
1434
|
+
if (segmentedInput.segments.length === 0) await segmentedInput.runUpdateSegments();
|
|
1435
|
+
return segmentedInput.segments;
|
|
1436
|
+
};
|
|
1437
|
+
if (prop === "refreshSegments") return async () => {
|
|
1418
1438
|
const segmentedInput = getSegmentedInputForTrack(target);
|
|
1419
1439
|
await segmentedInput.runUpdateSegments();
|
|
1420
1440
|
return segmentedInput.segments;
|
|
@@ -2655,6 +2675,11 @@ var DashTrackBackingBase = class {
|
|
|
2655
2675
|
return this.internalTrack.demuxer.getSegmentedInputForTrack(this.internalTrack);
|
|
2656
2676
|
}
|
|
2657
2677
|
async getSegments() {
|
|
2678
|
+
const segmentedInput = this.getSegmentedInput();
|
|
2679
|
+
if (segmentedInput.segments.length === 0) await segmentedInput.runUpdateSegments();
|
|
2680
|
+
return segmentedInput.segments;
|
|
2681
|
+
}
|
|
2682
|
+
async refreshSegments() {
|
|
2658
2683
|
const segmentedInput = this.getSegmentedInput();
|
|
2659
2684
|
await segmentedInput.runUpdateSegments();
|
|
2660
2685
|
return segmentedInput.segments;
|
|
@@ -2772,8 +2797,6 @@ var Input = class extends SegmentedMediabunnyInput {
|
|
|
2772
2797
|
}
|
|
2773
2798
|
};
|
|
2774
2799
|
const isInput = (value) => value instanceof Input;
|
|
2775
|
-
const getSegmentedInput = (track) => track.getSegmentedInput();
|
|
2776
|
-
const getSegments = async (track) => track.getSegments();
|
|
2777
2800
|
const ALL_FORMATS = [...ALL_FORMATS$1, DASH];
|
|
2778
2801
|
//#endregion
|
|
2779
|
-
export { ALL_FORMATS, DASH, DASH_FORMATS, FilePathSource, HLS, HLS_FORMATS, Input, MP3, MP4, UrlSource, asc, desc,
|
|
2802
|
+
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.3.1",
|
|
4
4
|
"description": "Streaming manifest parser",
|
|
5
5
|
"files": [
|
|
6
6
|
"dist"
|
|
@@ -52,15 +52,15 @@
|
|
|
52
52
|
"temporal-polyfill": "^0.3.2"
|
|
53
53
|
},
|
|
54
54
|
"peerDependencies": {
|
|
55
|
-
"mediabunny": "^1.
|
|
55
|
+
"mediabunny": "^1.45.2"
|
|
56
56
|
},
|
|
57
57
|
"devDependencies": {
|
|
58
|
-
"@types/node": "^25.
|
|
59
|
-
"oxfmt": "^0.
|
|
60
|
-
"oxlint": "^1.
|
|
58
|
+
"@types/node": "^25.8.0",
|
|
59
|
+
"oxfmt": "^0.50.0",
|
|
60
|
+
"oxlint": "^1.65.0",
|
|
61
61
|
"tsdown": "^0.22.0",
|
|
62
62
|
"typescript": "^6.0.3",
|
|
63
|
-
"vitest": "^4.1.
|
|
63
|
+
"vitest": "^4.1.6"
|
|
64
64
|
},
|
|
65
65
|
"scripts": {
|
|
66
66
|
"test": "vitest",
|