@amazon/vinyl 1.2.1 → 1.2.2
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.cjs +13 -4
- package/dist/index.cjs.map +2 -2
- package/dist/index.js +18 -9
- package/dist/index.js.map +3 -3
- package/dist/test/integ.es5.js +60 -60
- package/dist/test/integ.js +49 -4
- package/dist/test/integ.js.map +2 -2
- package/dist/types/current/ad/AdBreakInfo.d.ts.map +1 -1
- package/dist/types/current/ad/AdControllerImpl.d.ts +18 -2
- package/dist/types/current/ad/AdControllerImpl.d.ts.map +1 -1
- package/dist/types/current/ad/AdControllerImpl.js +58 -22
- package/dist/types/current/ad/discoverHlsInterstitials.d.ts.map +1 -1
- package/dist/types/current/ad/discoverHlsInterstitials.js +5 -3
- package/dist/types/current/drm/DrmControllerImpl.d.ts +6 -0
- package/dist/types/current/drm/DrmControllerImpl.d.ts.map +1 -1
- package/dist/types/current/drm/DrmControllerImpl.js +13 -1
- package/dist/types/current/playback/createStallDetector.d.ts +43 -0
- package/dist/types/current/playback/createStallDetector.d.ts.map +1 -0
- package/dist/types/current/playback/createStallDetector.js +101 -0
- package/dist/types/current/playback/createStallMonitor.d.ts +45 -0
- package/dist/types/current/playback/createStallMonitor.d.ts.map +1 -0
- package/dist/types/current/playback/createStallMonitor.js +99 -0
- package/dist/types/current/streaming/AudioOptions.d.ts +27 -0
- package/dist/types/current/streaming/AudioOptions.d.ts.map +1 -1
- package/dist/types/current/streaming/AudioOptions.js +5 -1
- package/dist/types/current/streaming/LoadMetric.d.ts +15 -1
- package/dist/types/current/streaming/LoadMetric.d.ts.map +1 -1
- package/dist/types/current/streaming/createTimelineContentTypesValue.d.ts +21 -0
- package/dist/types/current/streaming/createTimelineContentTypesValue.d.ts.map +1 -0
- package/dist/types/current/streaming/createTimelineContentTypesValue.js +25 -0
- package/dist/types/current/text/SidecarTextTrackLoader.d.ts.map +1 -1
- package/dist/types/current/text/SidecarTextTrackLoader.js +4 -4
- package/dist/types/current/text/TextTrack.d.ts.map +1 -1
- package/dist/types/current/text/discoverDashTextTracks.d.ts +2 -2
- package/dist/types/current/text/discoverDashTextTracks.js +4 -3
- package/dist/types/current/text/parseWebVtt.d.ts.map +1 -1
- package/dist/types/current/text/parseWebVtt.js +3 -2
- package/dist/types/current/track/mse/MseTrack.d.ts +0 -1
- package/dist/types/current/track/mse/MseTrack.d.ts.map +1 -1
- package/dist/types/current/track/mse/MseTrack.js +4 -5
- package/dist/types/current/tsconfig.tsbuildinfo +1 -1
- package/dist/types/ts3.7/ad/AdControllerImpl.d.ts +18 -2
- package/dist/types/ts3.7/drm/DrmControllerImpl.d.ts +6 -0
- package/dist/types/ts3.7/playback/createStallDetector.d.ts +43 -0
- package/dist/types/ts3.7/playback/createStallMonitor.d.ts +45 -0
- package/dist/types/ts3.7/streaming/AudioOptions.d.ts +27 -0
- package/dist/types/ts3.7/streaming/LoadMetric.d.ts +15 -1
- package/dist/types/ts3.7/streaming/createTimelineContentTypesValue.d.ts +21 -0
- package/dist/types/ts3.7/text/discoverDashTextTracks.d.ts +2 -2
- package/dist/types/ts3.7/track/mse/MseTrack.d.ts +0 -1
- package/dist/types/ts4.1/ad/AdControllerImpl.d.ts +18 -2
- package/dist/types/ts4.1/drm/DrmControllerImpl.d.ts +6 -0
- package/dist/types/ts4.1/playback/createStallDetector.d.ts +43 -0
- package/dist/types/ts4.1/playback/createStallMonitor.d.ts +45 -0
- package/dist/types/ts4.1/streaming/AudioOptions.d.ts +27 -0
- package/dist/types/ts4.1/streaming/LoadMetric.d.ts +15 -1
- package/dist/types/ts4.1/streaming/createTimelineContentTypesValue.d.ts +21 -0
- package/dist/types/ts4.1/text/discoverDashTextTracks.d.ts +2 -2
- package/dist/types/ts4.1/track/mse/MseTrack.d.ts +0 -1
- package/dist/types/ts4.7/ad/AdControllerImpl.d.ts +18 -2
- package/dist/types/ts4.7/drm/DrmControllerImpl.d.ts +6 -0
- package/dist/types/ts4.7/playback/createStallDetector.d.ts +43 -0
- package/dist/types/ts4.7/playback/createStallMonitor.d.ts +45 -0
- package/dist/types/ts4.7/streaming/AudioOptions.d.ts +27 -0
- package/dist/types/ts4.7/streaming/LoadMetric.d.ts +15 -1
- package/dist/types/ts4.7/streaming/createTimelineContentTypesValue.d.ts +21 -0
- package/dist/types/ts4.7/text/discoverDashTextTracks.d.ts +2 -2
- package/dist/types/ts4.7/track/mse/MseTrack.d.ts +0 -1
- package/dist/unit/types/current/ad/AdControllerImpl.test.js +203 -5
- package/dist/unit/types/current/ad/discoverHlsInterstitials.test.js +2 -1
- package/dist/unit/types/current/drm/DrmControllerImpl.test.js +30 -1
- package/dist/unit/types/current/playback/createStallDetector.test.d.ts +2 -0
- package/dist/unit/types/current/playback/createStallDetector.test.d.ts.map +1 -0
- package/dist/unit/types/current/playback/createStallDetector.test.js +163 -0
- package/dist/unit/types/current/playback/createStallMonitor.test.d.ts +2 -0
- package/dist/unit/types/current/playback/createStallMonitor.test.d.ts.map +1 -0
- package/dist/unit/types/current/playback/createStallMonitor.test.js +163 -0
- package/dist/unit/types/current/streaming/MseTrack.test.js +15 -0
- package/dist/unit/types/current/streaming/createTimelineContentTypesValue.test.d.ts +2 -0
- package/dist/unit/types/current/streaming/createTimelineContentTypesValue.test.d.ts.map +1 -0
- package/dist/unit/types/current/streaming/createTimelineContentTypesValue.test.js +57 -0
- package/dist/unit/types/current/text/TextTrack.test.d.ts +2 -0
- package/dist/unit/types/current/text/TextTrack.test.d.ts.map +1 -0
- package/dist/unit/types/current/text/TextTrack.test.js +12 -0
- package/dist/unit/types/current/text/discoverDashTextTracks.test.js +17 -0
- package/dist/unit/types/current/text/parseWebVtt.test.js +26 -0
- package/dist/unit/types/current/tsconfig.tsbuildinfo +1 -1
- package/dist/vinylTestUtil/types/current/tsconfig.tsbuildinfo +1 -1
- package/package.json +9 -9
|
@@ -7,6 +7,15 @@ import { AdsProvider } from './AdsProvider';
|
|
|
7
7
|
* The % playhead start tolerance for playback progress when emitting ad progress events.
|
|
8
8
|
*/
|
|
9
9
|
export declare const AD_START_TOLERANCE = 0.05;
|
|
10
|
+
/**
|
|
11
|
+
* When a break's X-PLAYOUT-LIMIT budget is reached, an ad whose real media end is
|
|
12
|
+
* within this many seconds is allowed to finish on its own `ended` rather than
|
|
13
|
+
* being cut. The limit is a coarse, often whole-second budget while the media's
|
|
14
|
+
* true length is fractional, so without this grace an ad effectively as long as
|
|
15
|
+
* its budget would be clipped a fraction short. The tolerance is measured against
|
|
16
|
+
* the playback-reported (media) duration, not the ad's declared duration.
|
|
17
|
+
*/
|
|
18
|
+
export declare const PLAYOUT_LIMIT_TOLERANCE = 1;
|
|
10
19
|
export interface AdControllerImplDeps {
|
|
11
20
|
readonly playbackController: ReadonlyPlaybackController;
|
|
12
21
|
}
|
|
@@ -129,8 +138,15 @@ export declare class AdControllerImpl extends EventHostImpl<AdEventMap> implemen
|
|
|
129
138
|
private emitAdProgressEvents;
|
|
130
139
|
private emitTimeUpdate;
|
|
131
140
|
/**
|
|
132
|
-
*
|
|
133
|
-
*
|
|
141
|
+
* Enforces the break-level playout limit (X-PLAYOUT-LIMIT): a budget shared
|
|
142
|
+
* across all of the break's ads. When cumulative playout reaches it, the
|
|
143
|
+
* whole break ends, dropping any ads that have not started.
|
|
144
|
+
*
|
|
145
|
+
* This is deliberately NOT a per-ad cap. Each ad asset is its own source and
|
|
146
|
+
* ends on its media `ended` (see the 'ended' handler), which is what advances
|
|
147
|
+
* a multi-ad break. Ending an ad at its declared per-ad DURATION instead would
|
|
148
|
+
* truncate the real asset whenever a packager under-declares it — e.g. rounds
|
|
149
|
+
* a 6.732s asset down to a whole-second 6 — cutting off the fractional tail.
|
|
134
150
|
*/
|
|
135
151
|
private enforcePlayoutLimits;
|
|
136
152
|
private setPendingBreaks;
|
|
@@ -11,6 +11,12 @@ import { MediaFormatMetadata } from '../streaming/MediaQualityMetadata';
|
|
|
11
11
|
* indicates a stalled promise result from the license provider.
|
|
12
12
|
*/
|
|
13
13
|
export declare const LICENSE_TIMEOUT = 90;
|
|
14
|
+
/**
|
|
15
|
+
* An excessive number of concurrent key sessions. Sessions are expected to be
|
|
16
|
+
* closed as tracks deactivate; a count this high signals sessions are leaking
|
|
17
|
+
* (never closing) rather than a legitimate playback need.
|
|
18
|
+
*/
|
|
19
|
+
export declare const EXCESSIVE_SESSION_COUNT = 20;
|
|
14
20
|
/**
|
|
15
21
|
* Dependencies for creating DrmController.
|
|
16
22
|
*/
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
export interface StallDetectorOptions {
|
|
2
|
+
/**
|
|
3
|
+
* Called when playback resumes without emitting a `playing` event (or after the detector
|
|
4
|
+
* revived it), so the caller can announce playback.
|
|
5
|
+
*/
|
|
6
|
+
readonly fabricatePlaying: () => void;
|
|
7
|
+
/** Poll interval in seconds. Default: 0.25 */
|
|
8
|
+
readonly pollInterval?: number;
|
|
9
|
+
/** Seconds the play head must be frozen before recovering. Default: 0.75 */
|
|
10
|
+
readonly stallThreshold?: number;
|
|
11
|
+
/**
|
|
12
|
+
* Don't nudge this close to the end of buffered data; a freeze there is a
|
|
13
|
+
* legitimate wait for more data. Seconds. Default: 0.5
|
|
14
|
+
*/
|
|
15
|
+
readonly bufferEndMargin?: number;
|
|
16
|
+
/** Seconds to nudge the play head forward to prod a resume. Default: 0.1 */
|
|
17
|
+
readonly stallSkip?: number;
|
|
18
|
+
/** Max recovery attempts before giving up. Default: 3 */
|
|
19
|
+
readonly maxAttempts?: number;
|
|
20
|
+
/**
|
|
21
|
+
* Nudge even when the playhead isn't inside a buffered range. Some WebKit versions leave a
|
|
22
|
+
* seek perpetually pending (no `seeked`) with a stale empty `buffered` even though data is
|
|
23
|
+
* appended; re-issuing the seek via a nudge can complete it. Off by default (only nudge over
|
|
24
|
+
* genuinely buffered data). Default: false
|
|
25
|
+
*/
|
|
26
|
+
readonly nudgeUnbuffered?: boolean;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Watches a media element after a seek/play and drives it back into a playing state. Some WebKit
|
|
30
|
+
* versions stall: the play head freezes inside buffered data and playback never resumes (often with
|
|
31
|
+
* a stale low readyState). This polls the play head and, while the element should be advancing:
|
|
32
|
+
*
|
|
33
|
+
* - if it's frozen inside buffered data, nudges currentTime forward to prod a resume;
|
|
34
|
+
* - if there's no data at the playhead, waits (it's legitimately buffering, or between sources).
|
|
35
|
+
*
|
|
36
|
+
* When the play head progresses it calls {@link StallDetectorOptions.fabricatePlaying} if playback
|
|
37
|
+
* resumed without a `playing` event (or after the detector revived it), then stops. It also stops
|
|
38
|
+
* on pause/ended/emptied or after {@link StallDetectorOptions.maxAttempts}.
|
|
39
|
+
*
|
|
40
|
+
* Start it after a seek or play only when playback is intended — a paused element won't advance.
|
|
41
|
+
*/
|
|
42
|
+
export declare function createStallDetector(media: HTMLMediaElement, options: StallDetectorOptions): () => void;
|
|
43
|
+
//# sourceMappingURL=createStallDetector.d.ts.map
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { Timestamp } from '@amazon/vinyl-util';
|
|
2
|
+
import { ReadonlyPlaybackController } from './ReadonlyPlaybackController';
|
|
3
|
+
import { StallEndedReason } from './ReadonlyPlaybackController';
|
|
4
|
+
export interface StallMonitorOptions {
|
|
5
|
+
/**
|
|
6
|
+
* Seconds the play head must be frozen (no `timeUpdate`) while playing before a stall is
|
|
7
|
+
* reported. Default: 1
|
|
8
|
+
*/
|
|
9
|
+
readonly stallThreshold?: number;
|
|
10
|
+
/**
|
|
11
|
+
* How often (seconds) the play head freeze is checked. Default: 0.25
|
|
12
|
+
*/
|
|
13
|
+
readonly pollInterval?: number;
|
|
14
|
+
}
|
|
15
|
+
export interface StallEndedInfo {
|
|
16
|
+
/** Time of the last `timeUpdate` observed before the play head froze. */
|
|
17
|
+
readonly started: Timestamp;
|
|
18
|
+
/** Time the stall ended. */
|
|
19
|
+
readonly ended: Timestamp;
|
|
20
|
+
/** Total seconds the play head was frozen. */
|
|
21
|
+
readonly duration: number;
|
|
22
|
+
/** Why the stall ended. */
|
|
23
|
+
readonly reason: StallEndedReason;
|
|
24
|
+
}
|
|
25
|
+
export interface StallMonitorCallbacks {
|
|
26
|
+
/** Called when a stall is first detected. */
|
|
27
|
+
readonly onStallEntered: () => void;
|
|
28
|
+
/** Called when a detected stall ends. */
|
|
29
|
+
readonly onStallEnded: (info: StallEndedInfo) => void;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Watches a {@link ReadonlyPlaybackController} for stalls while playing: the play head freezing
|
|
33
|
+
* (no `timeUpdate`) for longer than {@link StallMonitorOptions.stallThreshold} seconds.
|
|
34
|
+
*
|
|
35
|
+
* Detection only runs once playback has actually been observed (a `playing` event) and is
|
|
36
|
+
* suspended on `pause`/`seeking`/`emptied` until playback is observed again — so a stall is never
|
|
37
|
+
* reported during initial loading or while awaiting a seek. A detected stall ends when the play
|
|
38
|
+
* head advances again (`playing`) or playback stops for another reason (`pause`/`seeking`/
|
|
39
|
+
* `emptied`); {@link StallEndedInfo.duration} is measured from the last `timeUpdate` before the
|
|
40
|
+
* freeze, so it reflects the full frozen time rather than only the time past the threshold.
|
|
41
|
+
*
|
|
42
|
+
* Returns a function that stops the monitor.
|
|
43
|
+
*/
|
|
44
|
+
export declare function createStallMonitor(controller: ReadonlyPlaybackController, callbacks: StallMonitorCallbacks, options?: StallMonitorOptions): () => void;
|
|
45
|
+
//# sourceMappingURL=createStallMonitor.d.ts.map
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { ObjectSchema } from '@amazon/vinyl-validation';
|
|
2
|
+
import { Maybe } from '@amazon/vinyl-util';
|
|
2
3
|
/**
|
|
3
4
|
* Criteria used to pick which audio rendition to play.
|
|
4
5
|
*/
|
|
@@ -33,6 +34,32 @@ export interface AudioOptions {
|
|
|
33
34
|
* The audio selection criteria (language / descriptive).
|
|
34
35
|
*/
|
|
35
36
|
readonly selection?: AudioSelection;
|
|
37
|
+
/**
|
|
38
|
+
* When `true`, disables the audio sampling-rate support filter, so audio
|
|
39
|
+
* renditions whose sampling rate exceeds what the platform reports (via the
|
|
40
|
+
* `AudioContext` output rate) are kept and offered to playback anyway.
|
|
41
|
+
* `false` (the default) applies the filter. Changing this re-filters the
|
|
42
|
+
* timeline immediately.
|
|
43
|
+
*/
|
|
44
|
+
readonly disableSampleRateFilter?: boolean;
|
|
45
|
+
/**
|
|
46
|
+
* The maximum audio sampling rate (Hz) the sampling-rate filter treats as
|
|
47
|
+
* supported. When set, it takes precedence over the platform's
|
|
48
|
+
* `AudioContext`-reported output rate. Ignored when
|
|
49
|
+
* {@link disableSampleRateFilter} is `true`. Changing this re-filters the
|
|
50
|
+
* timeline immediately. `null`/`undefined` falls back to the reported rate.
|
|
51
|
+
*/
|
|
52
|
+
readonly maxSampleRate?: Maybe<number>;
|
|
53
|
+
/**
|
|
54
|
+
* The minimum audio sampling rate (Hz) the sampling-rate filter treats as
|
|
55
|
+
* supported. When set, renditions below it are filtered out as a soft floor
|
|
56
|
+
* (if every audio rendition is below it, the highest is kept so playback is
|
|
57
|
+
* never stranded). Applied alongside the max cap whenever the filter runs,
|
|
58
|
+
* regardless of how the max was determined; ignored when
|
|
59
|
+
* {@link disableSampleRateFilter} is `true`. Changing this re-filters the
|
|
60
|
+
* timeline immediately.
|
|
61
|
+
*/
|
|
62
|
+
readonly minSampleRate?: Maybe<number>;
|
|
36
63
|
}
|
|
37
64
|
export declare const defaultAudioOptions: AudioOptions;
|
|
38
65
|
export declare const audioOptionsValidator: ObjectSchema<AudioOptions>;
|
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
import { Timestamp } from '@amazon/vinyl-util';
|
|
2
2
|
import { TrackUri } from '../track/Track';
|
|
3
|
+
import { ContentType } from './MediaQualityMetadata';
|
|
3
4
|
/**
|
|
4
5
|
* The stage of the track-load journey a {@link LoadSpanMeasurement} describes.
|
|
5
6
|
*
|
|
6
7
|
* - `manifest`: fetching and parsing the DASH/HLS manifest.
|
|
8
|
+
* - `keySetup`: the EME/CDM setup, from session creation to the CDM's first
|
|
9
|
+
* license message. Precedes and is contiguous with `license`.
|
|
7
10
|
* - `license`: the DRM license request/response exchange.
|
|
8
11
|
* - `initSegment`: fetching the initialization segment.
|
|
9
12
|
* - `firstSegment`: fetching the first media segment.
|
|
10
13
|
*/
|
|
11
|
-
export type LoadSpanKind = 'manifest' | 'license' | 'initSegment' | 'firstSegment';
|
|
14
|
+
export type LoadSpanKind = 'manifest' | 'keySetup' | 'license' | 'initSegment' | 'firstSegment';
|
|
12
15
|
/**
|
|
13
16
|
* A timed span for one stage of a track load.
|
|
14
17
|
*
|
|
@@ -35,6 +38,17 @@ export interface LoadSpanMeasurement {
|
|
|
35
38
|
* buffering DRM info is set).
|
|
36
39
|
*/
|
|
37
40
|
readonly trackUri?: TrackUri;
|
|
41
|
+
/**
|
|
42
|
+
* The MIME type of the content this span was measured for, when known. Set
|
|
43
|
+
* for DRM `license` spans so a certificate exchange and the per-content-type
|
|
44
|
+
* license exchanges are distinguishable.
|
|
45
|
+
*/
|
|
46
|
+
readonly mimeType?: string;
|
|
47
|
+
/**
|
|
48
|
+
* The content type this span was measured for, when known. Set alongside
|
|
49
|
+
* {@link mimeType} for DRM `license` spans.
|
|
50
|
+
*/
|
|
51
|
+
readonly contentType?: ContentType;
|
|
38
52
|
}
|
|
39
53
|
/**
|
|
40
54
|
* A {@link LoadSpanMeasurement} attributed to the track it was measured for.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { ContentTypesValue } from './ContentTypesValue';
|
|
2
|
+
import { MediaTimeline } from './MediaTimeline';
|
|
3
|
+
import { ObservableValue } from '@amazon/vinyl-observable';
|
|
4
|
+
export interface TimelineContentTypesValueDeps {
|
|
5
|
+
/**
|
|
6
|
+
* The filtered, playable timeline. Content types are derived from the
|
|
7
|
+
* qualities that survive filtering, so a content type whose renditions are
|
|
8
|
+
* all filtered out (e.g. every audio rendition dropped by the sample-rate
|
|
9
|
+
* filter) is not reported — it never gates readiness and no source buffer
|
|
10
|
+
* is expected for it, so the remaining content types still play.
|
|
11
|
+
*/
|
|
12
|
+
readonly mediaTimelineTransformed: ObservableValue<Promise<MediaTimeline>>;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Provides the MSE content types to create source buffers for, derived from the
|
|
16
|
+
* qualities that survive timeline filtering rather than the raw manifest. Only
|
|
17
|
+
* `'audio'`/`'video'` are reported; text is a sidecar pipeline, never an MSE
|
|
18
|
+
* source buffer.
|
|
19
|
+
*/
|
|
20
|
+
export declare function createTimelineContentTypesValue(deps: TimelineContentTypesValueDeps): ContentTypesValue;
|
|
21
|
+
//# sourceMappingURL=createTimelineContentTypesValue.d.ts.map
|
|
@@ -5,8 +5,8 @@ import { TextTrackInfo } from './TextTrack';
|
|
|
5
5
|
*
|
|
6
6
|
* Considers an `<AdaptationSet>` to carry text when one of:
|
|
7
7
|
* - `contentType="text"`
|
|
8
|
-
* - `mimeType
|
|
9
|
-
*
|
|
8
|
+
* - its `mimeType`, or that of one of its `<Representation>`s, starts with
|
|
9
|
+
* `text/` (e.g. `text/vtt`)
|
|
10
10
|
*
|
|
11
11
|
* Within a text adaptation set, each `<Representation>` becomes one
|
|
12
12
|
* {@link TextTrackInfo}. The `BaseURL` chain (MPD → Period → AdaptationSet →
|
|
@@ -26,7 +26,6 @@ export declare class MseTrack extends TrackBase {
|
|
|
26
26
|
get [Symbol.toStringTag](): string;
|
|
27
27
|
protected readonly deps: MseTrackDeps;
|
|
28
28
|
private readonly streams;
|
|
29
|
-
private readonly disposeAbort;
|
|
30
29
|
private lastPreloadOptions;
|
|
31
30
|
private activateOptions;
|
|
32
31
|
private readonly allFetchedRanges;
|
|
@@ -7,6 +7,15 @@ import type { AdsProvider } from './AdsProvider';
|
|
|
7
7
|
* The % playhead start tolerance for playback progress when emitting ad progress events.
|
|
8
8
|
*/
|
|
9
9
|
export declare const AD_START_TOLERANCE = 0.05;
|
|
10
|
+
/**
|
|
11
|
+
* When a break's X-PLAYOUT-LIMIT budget is reached, an ad whose real media end is
|
|
12
|
+
* within this many seconds is allowed to finish on its own `ended` rather than
|
|
13
|
+
* being cut. The limit is a coarse, often whole-second budget while the media's
|
|
14
|
+
* true length is fractional, so without this grace an ad effectively as long as
|
|
15
|
+
* its budget would be clipped a fraction short. The tolerance is measured against
|
|
16
|
+
* the playback-reported (media) duration, not the ad's declared duration.
|
|
17
|
+
*/
|
|
18
|
+
export declare const PLAYOUT_LIMIT_TOLERANCE = 1;
|
|
10
19
|
export interface AdControllerImplDeps {
|
|
11
20
|
readonly playbackController: ReadonlyPlaybackController;
|
|
12
21
|
}
|
|
@@ -129,8 +138,15 @@ export declare class AdControllerImpl extends EventHostImpl<AdEventMap> implemen
|
|
|
129
138
|
private emitAdProgressEvents;
|
|
130
139
|
private emitTimeUpdate;
|
|
131
140
|
/**
|
|
132
|
-
*
|
|
133
|
-
*
|
|
141
|
+
* Enforces the break-level playout limit (X-PLAYOUT-LIMIT): a budget shared
|
|
142
|
+
* across all of the break's ads. When cumulative playout reaches it, the
|
|
143
|
+
* whole break ends, dropping any ads that have not started.
|
|
144
|
+
*
|
|
145
|
+
* This is deliberately NOT a per-ad cap. Each ad asset is its own source and
|
|
146
|
+
* ends on its media `ended` (see the 'ended' handler), which is what advances
|
|
147
|
+
* a multi-ad break. Ending an ad at its declared per-ad DURATION instead would
|
|
148
|
+
* truncate the real asset whenever a packager under-declares it — e.g. rounds
|
|
149
|
+
* a 6.732s asset down to a whole-second 6 — cutting off the fractional tail.
|
|
134
150
|
*/
|
|
135
151
|
private enforcePlayoutLimits;
|
|
136
152
|
private setPendingBreaks;
|
|
@@ -12,6 +12,12 @@ import type { MediaFormatMetadata } from '../streaming/MediaQualityMetadata';
|
|
|
12
12
|
* indicates a stalled promise result from the license provider.
|
|
13
13
|
*/
|
|
14
14
|
export declare const LICENSE_TIMEOUT = 90;
|
|
15
|
+
/**
|
|
16
|
+
* An excessive number of concurrent key sessions. Sessions are expected to be
|
|
17
|
+
* closed as tracks deactivate; a count this high signals sessions are leaking
|
|
18
|
+
* (never closing) rather than a legitimate playback need.
|
|
19
|
+
*/
|
|
20
|
+
export declare const EXCESSIVE_SESSION_COUNT = 20;
|
|
15
21
|
/**
|
|
16
22
|
* Dependencies for creating DrmController.
|
|
17
23
|
*/
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
export interface StallDetectorOptions {
|
|
2
|
+
/**
|
|
3
|
+
* Called when playback resumes without emitting a `playing` event (or after the detector
|
|
4
|
+
* revived it), so the caller can announce playback.
|
|
5
|
+
*/
|
|
6
|
+
readonly fabricatePlaying: () => void;
|
|
7
|
+
/** Poll interval in seconds. Default: 0.25 */
|
|
8
|
+
readonly pollInterval?: number;
|
|
9
|
+
/** Seconds the play head must be frozen before recovering. Default: 0.75 */
|
|
10
|
+
readonly stallThreshold?: number;
|
|
11
|
+
/**
|
|
12
|
+
* Don't nudge this close to the end of buffered data; a freeze there is a
|
|
13
|
+
* legitimate wait for more data. Seconds. Default: 0.5
|
|
14
|
+
*/
|
|
15
|
+
readonly bufferEndMargin?: number;
|
|
16
|
+
/** Seconds to nudge the play head forward to prod a resume. Default: 0.1 */
|
|
17
|
+
readonly stallSkip?: number;
|
|
18
|
+
/** Max recovery attempts before giving up. Default: 3 */
|
|
19
|
+
readonly maxAttempts?: number;
|
|
20
|
+
/**
|
|
21
|
+
* Nudge even when the playhead isn't inside a buffered range. Some WebKit versions leave a
|
|
22
|
+
* seek perpetually pending (no `seeked`) with a stale empty `buffered` even though data is
|
|
23
|
+
* appended; re-issuing the seek via a nudge can complete it. Off by default (only nudge over
|
|
24
|
+
* genuinely buffered data). Default: false
|
|
25
|
+
*/
|
|
26
|
+
readonly nudgeUnbuffered?: boolean;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Watches a media element after a seek/play and drives it back into a playing state. Some WebKit
|
|
30
|
+
* versions stall: the play head freezes inside buffered data and playback never resumes (often with
|
|
31
|
+
* a stale low readyState). This polls the play head and, while the element should be advancing:
|
|
32
|
+
*
|
|
33
|
+
* - if it's frozen inside buffered data, nudges currentTime forward to prod a resume;
|
|
34
|
+
* - if there's no data at the playhead, waits (it's legitimately buffering, or between sources).
|
|
35
|
+
*
|
|
36
|
+
* When the play head progresses it calls {@link StallDetectorOptions.fabricatePlaying} if playback
|
|
37
|
+
* resumed without a `playing` event (or after the detector revived it), then stops. It also stops
|
|
38
|
+
* on pause/ended/emptied or after {@link StallDetectorOptions.maxAttempts}.
|
|
39
|
+
*
|
|
40
|
+
* Start it after a seek or play only when playback is intended — a paused element won't advance.
|
|
41
|
+
*/
|
|
42
|
+
export declare function createStallDetector(media: HTMLMediaElement, options: StallDetectorOptions): () => void;
|
|
43
|
+
//# sourceMappingURL=createStallDetector.d.ts.map
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { Timestamp } from '@amazon/vinyl-util';
|
|
2
|
+
import type { ReadonlyPlaybackController } from './ReadonlyPlaybackController';
|
|
3
|
+
import { StallEndedReason } from './ReadonlyPlaybackController';
|
|
4
|
+
export interface StallMonitorOptions {
|
|
5
|
+
/**
|
|
6
|
+
* Seconds the play head must be frozen (no `timeUpdate`) while playing before a stall is
|
|
7
|
+
* reported. Default: 1
|
|
8
|
+
*/
|
|
9
|
+
readonly stallThreshold?: number;
|
|
10
|
+
/**
|
|
11
|
+
* How often (seconds) the play head freeze is checked. Default: 0.25
|
|
12
|
+
*/
|
|
13
|
+
readonly pollInterval?: number;
|
|
14
|
+
}
|
|
15
|
+
export interface StallEndedInfo {
|
|
16
|
+
/** Time of the last `timeUpdate` observed before the play head froze. */
|
|
17
|
+
readonly started: Timestamp;
|
|
18
|
+
/** Time the stall ended. */
|
|
19
|
+
readonly ended: Timestamp;
|
|
20
|
+
/** Total seconds the play head was frozen. */
|
|
21
|
+
readonly duration: number;
|
|
22
|
+
/** Why the stall ended. */
|
|
23
|
+
readonly reason: StallEndedReason;
|
|
24
|
+
}
|
|
25
|
+
export interface StallMonitorCallbacks {
|
|
26
|
+
/** Called when a stall is first detected. */
|
|
27
|
+
readonly onStallEntered: () => void;
|
|
28
|
+
/** Called when a detected stall ends. */
|
|
29
|
+
readonly onStallEnded: (info: StallEndedInfo) => void;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Watches a {@link ReadonlyPlaybackController} for stalls while playing: the play head freezing
|
|
33
|
+
* (no `timeUpdate`) for longer than {@link StallMonitorOptions.stallThreshold} seconds.
|
|
34
|
+
*
|
|
35
|
+
* Detection only runs once playback has actually been observed (a `playing` event) and is
|
|
36
|
+
* suspended on `pause`/`seeking`/`emptied` until playback is observed again — so a stall is never
|
|
37
|
+
* reported during initial loading or while awaiting a seek. A detected stall ends when the play
|
|
38
|
+
* head advances again (`playing`) or playback stops for another reason (`pause`/`seeking`/
|
|
39
|
+
* `emptied`); {@link StallEndedInfo.duration} is measured from the last `timeUpdate` before the
|
|
40
|
+
* freeze, so it reflects the full frozen time rather than only the time past the threshold.
|
|
41
|
+
*
|
|
42
|
+
* Returns a function that stops the monitor.
|
|
43
|
+
*/
|
|
44
|
+
export declare function createStallMonitor(controller: ReadonlyPlaybackController, callbacks: StallMonitorCallbacks, options?: StallMonitorOptions): () => void;
|
|
45
|
+
//# sourceMappingURL=createStallMonitor.d.ts.map
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { ObjectSchema } from '@amazon/vinyl-validation';
|
|
2
|
+
import type { Maybe } from '@amazon/vinyl-util';
|
|
2
3
|
/**
|
|
3
4
|
* Criteria used to pick which audio rendition to play.
|
|
4
5
|
*/
|
|
@@ -33,6 +34,32 @@ export interface AudioOptions {
|
|
|
33
34
|
* The audio selection criteria (language / descriptive).
|
|
34
35
|
*/
|
|
35
36
|
readonly selection?: AudioSelection;
|
|
37
|
+
/**
|
|
38
|
+
* When `true`, disables the audio sampling-rate support filter, so audio
|
|
39
|
+
* renditions whose sampling rate exceeds what the platform reports (via the
|
|
40
|
+
* `AudioContext` output rate) are kept and offered to playback anyway.
|
|
41
|
+
* `false` (the default) applies the filter. Changing this re-filters the
|
|
42
|
+
* timeline immediately.
|
|
43
|
+
*/
|
|
44
|
+
readonly disableSampleRateFilter?: boolean;
|
|
45
|
+
/**
|
|
46
|
+
* The maximum audio sampling rate (Hz) the sampling-rate filter treats as
|
|
47
|
+
* supported. When set, it takes precedence over the platform's
|
|
48
|
+
* `AudioContext`-reported output rate. Ignored when
|
|
49
|
+
* {@link disableSampleRateFilter} is `true`. Changing this re-filters the
|
|
50
|
+
* timeline immediately. `null`/`undefined` falls back to the reported rate.
|
|
51
|
+
*/
|
|
52
|
+
readonly maxSampleRate?: Maybe<number>;
|
|
53
|
+
/**
|
|
54
|
+
* The minimum audio sampling rate (Hz) the sampling-rate filter treats as
|
|
55
|
+
* supported. When set, renditions below it are filtered out as a soft floor
|
|
56
|
+
* (if every audio rendition is below it, the highest is kept so playback is
|
|
57
|
+
* never stranded). Applied alongside the max cap whenever the filter runs,
|
|
58
|
+
* regardless of how the max was determined; ignored when
|
|
59
|
+
* {@link disableSampleRateFilter} is `true`. Changing this re-filters the
|
|
60
|
+
* timeline immediately.
|
|
61
|
+
*/
|
|
62
|
+
readonly minSampleRate?: Maybe<number>;
|
|
36
63
|
}
|
|
37
64
|
export declare const defaultAudioOptions: AudioOptions;
|
|
38
65
|
export declare const audioOptionsValidator: ObjectSchema<AudioOptions>;
|
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
import type { Timestamp } from '@amazon/vinyl-util';
|
|
2
2
|
import type { TrackUri } from '../track/Track';
|
|
3
|
+
import type { ContentType } from './MediaQualityMetadata';
|
|
3
4
|
/**
|
|
4
5
|
* The stage of the track-load journey a {@link LoadSpanMeasurement} describes.
|
|
5
6
|
*
|
|
6
7
|
* - `manifest`: fetching and parsing the DASH/HLS manifest.
|
|
8
|
+
* - `keySetup`: the EME/CDM setup, from session creation to the CDM's first
|
|
9
|
+
* license message. Precedes and is contiguous with `license`.
|
|
7
10
|
* - `license`: the DRM license request/response exchange.
|
|
8
11
|
* - `initSegment`: fetching the initialization segment.
|
|
9
12
|
* - `firstSegment`: fetching the first media segment.
|
|
10
13
|
*/
|
|
11
|
-
export type LoadSpanKind = 'manifest' | 'license' | 'initSegment' | 'firstSegment';
|
|
14
|
+
export type LoadSpanKind = 'manifest' | 'keySetup' | 'license' | 'initSegment' | 'firstSegment';
|
|
12
15
|
/**
|
|
13
16
|
* A timed span for one stage of a track load.
|
|
14
17
|
*
|
|
@@ -35,6 +38,17 @@ export interface LoadSpanMeasurement {
|
|
|
35
38
|
* buffering DRM info is set).
|
|
36
39
|
*/
|
|
37
40
|
readonly trackUri?: TrackUri;
|
|
41
|
+
/**
|
|
42
|
+
* The MIME type of the content this span was measured for, when known. Set
|
|
43
|
+
* for DRM `license` spans so a certificate exchange and the per-content-type
|
|
44
|
+
* license exchanges are distinguishable.
|
|
45
|
+
*/
|
|
46
|
+
readonly mimeType?: string;
|
|
47
|
+
/**
|
|
48
|
+
* The content type this span was measured for, when known. Set alongside
|
|
49
|
+
* {@link mimeType} for DRM `license` spans.
|
|
50
|
+
*/
|
|
51
|
+
readonly contentType?: ContentType;
|
|
38
52
|
}
|
|
39
53
|
/**
|
|
40
54
|
* A {@link LoadSpanMeasurement} attributed to the track it was measured for.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { ContentTypesValue } from './ContentTypesValue';
|
|
2
|
+
import type { MediaTimeline } from './MediaTimeline';
|
|
3
|
+
import type { ObservableValue } from '@amazon/vinyl-observable';
|
|
4
|
+
export interface TimelineContentTypesValueDeps {
|
|
5
|
+
/**
|
|
6
|
+
* The filtered, playable timeline. Content types are derived from the
|
|
7
|
+
* qualities that survive filtering, so a content type whose renditions are
|
|
8
|
+
* all filtered out (e.g. every audio rendition dropped by the sample-rate
|
|
9
|
+
* filter) is not reported — it never gates readiness and no source buffer
|
|
10
|
+
* is expected for it, so the remaining content types still play.
|
|
11
|
+
*/
|
|
12
|
+
readonly mediaTimelineTransformed: ObservableValue<Promise<MediaTimeline>>;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Provides the MSE content types to create source buffers for, derived from the
|
|
16
|
+
* qualities that survive timeline filtering rather than the raw manifest. Only
|
|
17
|
+
* `'audio'`/`'video'` are reported; text is a sidecar pipeline, never an MSE
|
|
18
|
+
* source buffer.
|
|
19
|
+
*/
|
|
20
|
+
export declare function createTimelineContentTypesValue(deps: TimelineContentTypesValueDeps): ContentTypesValue;
|
|
21
|
+
//# sourceMappingURL=createTimelineContentTypesValue.d.ts.map
|
|
@@ -5,8 +5,8 @@ import type { TextTrackInfo } from './TextTrack';
|
|
|
5
5
|
*
|
|
6
6
|
* Considers an `<AdaptationSet>` to carry text when one of:
|
|
7
7
|
* - `contentType="text"`
|
|
8
|
-
* - `mimeType
|
|
9
|
-
*
|
|
8
|
+
* - its `mimeType`, or that of one of its `<Representation>`s, starts with
|
|
9
|
+
* `text/` (e.g. `text/vtt`)
|
|
10
10
|
*
|
|
11
11
|
* Within a text adaptation set, each `<Representation>` becomes one
|
|
12
12
|
* {@link TextTrackInfo}. The `BaseURL` chain (MPD → Period → AdaptationSet →
|
|
@@ -27,7 +27,6 @@ export declare class MseTrack extends TrackBase {
|
|
|
27
27
|
get [Symbol.toStringTag](): string;
|
|
28
28
|
protected readonly deps: MseTrackDeps;
|
|
29
29
|
private readonly streams;
|
|
30
|
-
private readonly disposeAbort;
|
|
31
30
|
private lastPreloadOptions;
|
|
32
31
|
private activateOptions;
|
|
33
32
|
private readonly allFetchedRanges;
|
|
@@ -7,6 +7,15 @@ import type { AdsProvider } from './AdsProvider';
|
|
|
7
7
|
* The % playhead start tolerance for playback progress when emitting ad progress events.
|
|
8
8
|
*/
|
|
9
9
|
export declare const AD_START_TOLERANCE = 0.05;
|
|
10
|
+
/**
|
|
11
|
+
* When a break's X-PLAYOUT-LIMIT budget is reached, an ad whose real media end is
|
|
12
|
+
* within this many seconds is allowed to finish on its own `ended` rather than
|
|
13
|
+
* being cut. The limit is a coarse, often whole-second budget while the media's
|
|
14
|
+
* true length is fractional, so without this grace an ad effectively as long as
|
|
15
|
+
* its budget would be clipped a fraction short. The tolerance is measured against
|
|
16
|
+
* the playback-reported (media) duration, not the ad's declared duration.
|
|
17
|
+
*/
|
|
18
|
+
export declare const PLAYOUT_LIMIT_TOLERANCE = 1;
|
|
10
19
|
export interface AdControllerImplDeps {
|
|
11
20
|
readonly playbackController: ReadonlyPlaybackController;
|
|
12
21
|
}
|
|
@@ -129,8 +138,15 @@ export declare class AdControllerImpl extends EventHostImpl<AdEventMap> implemen
|
|
|
129
138
|
private emitAdProgressEvents;
|
|
130
139
|
private emitTimeUpdate;
|
|
131
140
|
/**
|
|
132
|
-
*
|
|
133
|
-
*
|
|
141
|
+
* Enforces the break-level playout limit (X-PLAYOUT-LIMIT): a budget shared
|
|
142
|
+
* across all of the break's ads. When cumulative playout reaches it, the
|
|
143
|
+
* whole break ends, dropping any ads that have not started.
|
|
144
|
+
*
|
|
145
|
+
* This is deliberately NOT a per-ad cap. Each ad asset is its own source and
|
|
146
|
+
* ends on its media `ended` (see the 'ended' handler), which is what advances
|
|
147
|
+
* a multi-ad break. Ending an ad at its declared per-ad DURATION instead would
|
|
148
|
+
* truncate the real asset whenever a packager under-declares it — e.g. rounds
|
|
149
|
+
* a 6.732s asset down to a whole-second 6 — cutting off the fractional tail.
|
|
134
150
|
*/
|
|
135
151
|
private enforcePlayoutLimits;
|
|
136
152
|
private setPendingBreaks;
|
|
@@ -11,6 +11,12 @@ import type { MediaFormatMetadata } from '../streaming/MediaQualityMetadata';
|
|
|
11
11
|
* indicates a stalled promise result from the license provider.
|
|
12
12
|
*/
|
|
13
13
|
export declare const LICENSE_TIMEOUT = 90;
|
|
14
|
+
/**
|
|
15
|
+
* An excessive number of concurrent key sessions. Sessions are expected to be
|
|
16
|
+
* closed as tracks deactivate; a count this high signals sessions are leaking
|
|
17
|
+
* (never closing) rather than a legitimate playback need.
|
|
18
|
+
*/
|
|
19
|
+
export declare const EXCESSIVE_SESSION_COUNT = 20;
|
|
14
20
|
/**
|
|
15
21
|
* Dependencies for creating DrmController.
|
|
16
22
|
*/
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
export interface StallDetectorOptions {
|
|
2
|
+
/**
|
|
3
|
+
* Called when playback resumes without emitting a `playing` event (or after the detector
|
|
4
|
+
* revived it), so the caller can announce playback.
|
|
5
|
+
*/
|
|
6
|
+
readonly fabricatePlaying: () => void;
|
|
7
|
+
/** Poll interval in seconds. Default: 0.25 */
|
|
8
|
+
readonly pollInterval?: number;
|
|
9
|
+
/** Seconds the play head must be frozen before recovering. Default: 0.75 */
|
|
10
|
+
readonly stallThreshold?: number;
|
|
11
|
+
/**
|
|
12
|
+
* Don't nudge this close to the end of buffered data; a freeze there is a
|
|
13
|
+
* legitimate wait for more data. Seconds. Default: 0.5
|
|
14
|
+
*/
|
|
15
|
+
readonly bufferEndMargin?: number;
|
|
16
|
+
/** Seconds to nudge the play head forward to prod a resume. Default: 0.1 */
|
|
17
|
+
readonly stallSkip?: number;
|
|
18
|
+
/** Max recovery attempts before giving up. Default: 3 */
|
|
19
|
+
readonly maxAttempts?: number;
|
|
20
|
+
/**
|
|
21
|
+
* Nudge even when the playhead isn't inside a buffered range. Some WebKit versions leave a
|
|
22
|
+
* seek perpetually pending (no `seeked`) with a stale empty `buffered` even though data is
|
|
23
|
+
* appended; re-issuing the seek via a nudge can complete it. Off by default (only nudge over
|
|
24
|
+
* genuinely buffered data). Default: false
|
|
25
|
+
*/
|
|
26
|
+
readonly nudgeUnbuffered?: boolean;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Watches a media element after a seek/play and drives it back into a playing state. Some WebKit
|
|
30
|
+
* versions stall: the play head freezes inside buffered data and playback never resumes (often with
|
|
31
|
+
* a stale low readyState). This polls the play head and, while the element should be advancing:
|
|
32
|
+
*
|
|
33
|
+
* - if it's frozen inside buffered data, nudges currentTime forward to prod a resume;
|
|
34
|
+
* - if there's no data at the playhead, waits (it's legitimately buffering, or between sources).
|
|
35
|
+
*
|
|
36
|
+
* When the play head progresses it calls {@link StallDetectorOptions.fabricatePlaying} if playback
|
|
37
|
+
* resumed without a `playing` event (or after the detector revived it), then stops. It also stops
|
|
38
|
+
* on pause/ended/emptied or after {@link StallDetectorOptions.maxAttempts}.
|
|
39
|
+
*
|
|
40
|
+
* Start it after a seek or play only when playback is intended — a paused element won't advance.
|
|
41
|
+
*/
|
|
42
|
+
export declare function createStallDetector(media: HTMLMediaElement, options: StallDetectorOptions): () => void;
|
|
43
|
+
//# sourceMappingURL=createStallDetector.d.ts.map
|