@hyperframes/core 0.9.7 → 0.9.8
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/runtime/clock.d.ts
CHANGED
|
@@ -29,6 +29,7 @@ export declare class TransportClock {
|
|
|
29
29
|
/** Wall-clock time of the last `now()` read while playing; null while paused. */
|
|
30
30
|
private _lastReadMs;
|
|
31
31
|
private _lastNow;
|
|
32
|
+
private _audioStart;
|
|
32
33
|
constructor(opts?: {
|
|
33
34
|
initialTime?: number;
|
|
34
35
|
rate?: number;
|
|
@@ -37,6 +38,8 @@ export declare class TransportClock {
|
|
|
37
38
|
});
|
|
38
39
|
now(): number;
|
|
39
40
|
private _elementTimeNeverBehind;
|
|
41
|
+
private _heldUntilAudioOutputStarts;
|
|
42
|
+
private _pendingAudioStart;
|
|
40
43
|
/** Folds a >500ms gap since the last read into `_playStartMs` so it's never reported as played time. */
|
|
41
44
|
private _applyStallCorrection;
|
|
42
45
|
play(): boolean;
|
package/dist/runtime/clock.js
CHANGED
|
@@ -4,6 +4,8 @@ import { playRangeHoldTime } from "./protocol.js";
|
|
|
4
4
|
const STALL_THRESHOLD_MS = 500;
|
|
5
5
|
const STALL_ADJUSTED_LAG_MS = 33;
|
|
6
6
|
const HAVE_FUTURE_DATA = 3;
|
|
7
|
+
const AUDIO_START_WAIT_MS = 1500;
|
|
8
|
+
const MEDIA_SYNC_STEER_TOLERANCE_SECONDS = 0.04;
|
|
7
9
|
export class TransportClock {
|
|
8
10
|
_baseTime = 0;
|
|
9
11
|
_playStartMs = null;
|
|
@@ -17,6 +19,7 @@ export class TransportClock {
|
|
|
17
19
|
/** Wall-clock time of the last `now()` read while playing; null while paused. */
|
|
18
20
|
_lastReadMs = null;
|
|
19
21
|
_lastNow = 0;
|
|
22
|
+
_audioStart = null;
|
|
20
23
|
constructor(opts) {
|
|
21
24
|
this._baseTime = opts?.initialTime ?? 0;
|
|
22
25
|
this._rate = opts?.rate ?? 1;
|
|
@@ -57,15 +60,35 @@ export class TransportClock {
|
|
|
57
60
|
const { el, compositionStart, mediaStart, rate } = source;
|
|
58
61
|
if (el.paused || !Number.isFinite(el.currentTime))
|
|
59
62
|
return null;
|
|
60
|
-
if (el.seeking)
|
|
61
|
-
return null;
|
|
62
63
|
const spec = rate ?? 1;
|
|
63
64
|
const time = timeAtSourceTime(spec, el.currentTime - mediaStart) + compositionStart;
|
|
65
|
+
const held = this._heldUntilAudioOutputStarts(el.seeking, time);
|
|
66
|
+
if (held !== undefined)
|
|
67
|
+
return held;
|
|
64
68
|
if (time >= this._lastNow)
|
|
65
69
|
return time;
|
|
66
70
|
const wrapped = el.loop && this._lastNow - time > timeAtSourceTime(spec, el.duration) / 2;
|
|
67
71
|
return !wrapped && el.readyState < HAVE_FUTURE_DATA ? this._lastNow : null;
|
|
68
72
|
}
|
|
73
|
+
_heldUntilAudioOutputStarts(seeking, time) {
|
|
74
|
+
const pending = this._pendingAudioStart();
|
|
75
|
+
if (seeking)
|
|
76
|
+
return pending ? this._lastNow : null;
|
|
77
|
+
if (!pending)
|
|
78
|
+
return undefined;
|
|
79
|
+
pending.from ??= time;
|
|
80
|
+
const startsHere = Math.abs(pending.from - pending.at) <= MEDIA_SYNC_STEER_TOLERANCE_SECONDS;
|
|
81
|
+
if (startsHere && time === pending.from)
|
|
82
|
+
return time;
|
|
83
|
+
this._audioStart = null;
|
|
84
|
+
return undefined;
|
|
85
|
+
}
|
|
86
|
+
_pendingAudioStart() {
|
|
87
|
+
const pending = this._audioStart;
|
|
88
|
+
if (pending && this._nowMs() - pending.sinceMs > AUDIO_START_WAIT_MS)
|
|
89
|
+
this._audioStart = null;
|
|
90
|
+
return this._audioStart;
|
|
91
|
+
}
|
|
69
92
|
/** Folds a >500ms gap since the last read into `_playStartMs` so it's never reported as played time. */
|
|
70
93
|
_applyStallCorrection() {
|
|
71
94
|
if (this._playStartMs === null)
|
|
@@ -85,6 +108,7 @@ export class TransportClock {
|
|
|
85
108
|
if (this._baseTime >= this.getEnd())
|
|
86
109
|
return false;
|
|
87
110
|
this._playStartMs = this._nowMs();
|
|
111
|
+
this._audioStart = { sinceMs: this._playStartMs, at: this._baseTime, from: null };
|
|
88
112
|
this._lastNow = this._baseTime;
|
|
89
113
|
// Not a stall: the gap since the clock was last read (possibly a long
|
|
90
114
|
// paused idle) says nothing about lost playback time, since none was
|
|
@@ -108,6 +132,7 @@ export class TransportClock {
|
|
|
108
132
|
this._lastNow = clamped;
|
|
109
133
|
if (this._playStartMs !== null) {
|
|
110
134
|
this._playStartMs = this._nowMs();
|
|
135
|
+
this._audioStart = { sinceMs: this._playStartMs, at: clamped, from: null };
|
|
111
136
|
// Same reasoning as `play()`: the seek itself, not any elapsed gap
|
|
112
137
|
// since the last read, is why the reported time is moving now.
|
|
113
138
|
this._lastReadMs = null;
|
|
@@ -166,6 +191,7 @@ export class TransportClock {
|
|
|
166
191
|
this._audioSource = null;
|
|
167
192
|
}
|
|
168
193
|
/** The element the playhead currently follows, if the source is one. */
|
|
194
|
+
// fallow-ignore-next-line unused-class-member
|
|
169
195
|
audioElement() {
|
|
170
196
|
return this._audioSource && "el" in this._audioSource ? this._audioSource.el : null;
|
|
171
197
|
}
|
|
@@ -6,6 +6,7 @@ export declare function defersMediaIn(doc: Document): boolean;
|
|
|
6
6
|
export declare const STUDIO_PREVIEW_UPCOMING_ATTR = "data-hf-upcoming";
|
|
7
7
|
export declare const STUDIO_PREVIEW_LAZY_ATTR = "data-hf-preview-lazy";
|
|
8
8
|
export declare const STUDIO_PREVIEW_ERRORS = "__hfPreviewErrors";
|
|
9
|
+
export declare const STUDIO_PREVIEW_ERROR_KINDS = "__hfPreviewErrorKinds";
|
|
9
10
|
export declare const refusedPreviewMessage: (status: number) => string;
|
|
10
11
|
export declare function refusedPreviewStatus(message: string): number | null;
|
|
11
12
|
export declare const PREVIEW_RASTER_ATTR = "data-hf-preview-raster";
|
|
@@ -11,6 +11,7 @@ export function defersMediaIn(doc) {
|
|
|
11
11
|
export const STUDIO_PREVIEW_UPCOMING_ATTR = "data-hf-upcoming";
|
|
12
12
|
export const STUDIO_PREVIEW_LAZY_ATTR = "data-hf-preview-lazy";
|
|
13
13
|
export const STUDIO_PREVIEW_ERRORS = "__hfPreviewErrors";
|
|
14
|
+
export const STUDIO_PREVIEW_ERROR_KINDS = "__hfPreviewErrorKinds";
|
|
14
15
|
export const refusedPreviewMessage = (status) => `The preview page could not be loaded (HTTP ${status}).`;
|
|
15
16
|
export function refusedPreviewStatus(message) {
|
|
16
17
|
const status = /^The preview page could not be loaded \(HTTP (\d{3})\)\.$/.exec(message)?.[1];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hyperframes/core",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.8",
|
|
4
4
|
"description": "",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -437,9 +437,9 @@
|
|
|
437
437
|
"linkedom": "^0.18.12",
|
|
438
438
|
"postcss": "^8.5.8",
|
|
439
439
|
"wawoff2": "^2.0.1",
|
|
440
|
-
"@hyperframes/lint": "0.9.
|
|
441
|
-
"@hyperframes/
|
|
442
|
-
"@hyperframes/
|
|
440
|
+
"@hyperframes/lint": "0.9.8",
|
|
441
|
+
"@hyperframes/studio-server": "0.9.8",
|
|
442
|
+
"@hyperframes/parsers": "0.9.8"
|
|
443
443
|
},
|
|
444
444
|
"devDependencies": {
|
|
445
445
|
"@fontsource/archivo-black": "^5.2.8",
|