@hyperframes/core 0.6.66 → 0.6.68
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.
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared volume-automation utilities used by both the renderer (offline PCM
|
|
3
|
+
* baking in audioVolumeEnvelope.ts) and the preview runtime (per-tick gain
|
|
4
|
+
* applied in syncRuntimeMedia).
|
|
5
|
+
*
|
|
6
|
+
* Keeping the two concerns in one place ensures preview and render derive the
|
|
7
|
+
* envelope from the same logic and the same probe samples.
|
|
8
|
+
*/
|
|
9
|
+
export interface VolumeKeyframe {
|
|
10
|
+
time: number;
|
|
11
|
+
volume: number;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Normalise raw keyframes to track-relative seconds: subtract `trackStart`,
|
|
15
|
+
* clamp to [0,1], sort, de-duplicate, and prepend a `baseVolume` anchor at
|
|
16
|
+
* t=0 when the first keyframe starts after the clip's begin.
|
|
17
|
+
*
|
|
18
|
+
* Returns an empty array when all keyframes are invalid — the caller should
|
|
19
|
+
* treat an empty envelope as "no automation, use static volume."
|
|
20
|
+
*/
|
|
21
|
+
export declare function normaliseEnvelope(keyframes: VolumeKeyframe[], trackStart: number, baseVolume: number): VolumeKeyframe[];
|
|
22
|
+
/**
|
|
23
|
+
* Linearly interpolate the gain at time `t` (track-relative seconds) from a
|
|
24
|
+
* normalised envelope produced by `normaliseEnvelope`. Returns 1 when the
|
|
25
|
+
* envelope is empty.
|
|
26
|
+
*/
|
|
27
|
+
export declare function interpolateVolumeGain(envelope: VolumeKeyframe[], t: number): number;
|
|
28
|
+
/**
|
|
29
|
+
* Probe a single media element's volume automation by seeking a GSAP timeline
|
|
30
|
+
* through the element's active window.
|
|
31
|
+
*
|
|
32
|
+
* Runs synchronously in the browser. The timeline is left at its current
|
|
33
|
+
* position after the probe (the next transport tick re-seeks it to `t`).
|
|
34
|
+
*
|
|
35
|
+
* Returns null when the element has no detectable automation (volume never
|
|
36
|
+
* changes from its initial `data-volume` value).
|
|
37
|
+
*/
|
|
38
|
+
export declare function probeElementVolumeKeyframes(el: HTMLAudioElement | HTMLVideoElement, seekTimeline: (t: number) => void, compositionDuration: number, sampleFps: number): VolumeKeyframe[] | null;
|
|
39
|
+
export interface RuntimeTimelineRef {
|
|
40
|
+
totalTime?: ((t: number, suppressEvents?: boolean) => unknown) | undefined;
|
|
41
|
+
seek?: ((t: number, suppressEvents?: boolean) => unknown) | undefined;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Probe a media element and, if volume automation is detected, store the
|
|
45
|
+
* keyframes in `cache`. Safe to call with a null timeline — returns early.
|
|
46
|
+
*/
|
|
47
|
+
export declare function probeAndCacheElementVolume(mediaEl: HTMLMediaElement, timeline: RuntimeTimelineRef | null | undefined, compositionDuration: number, cache: WeakMap<HTMLMediaElement, VolumeKeyframe[]>): void;
|
|
48
|
+
//# sourceMappingURL=mediaVolumeEnvelope.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mediaVolumeEnvelope.d.ts","sourceRoot":"","sources":["../../src/runtime/mediaVolumeEnvelope.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAC/B,SAAS,EAAE,cAAc,EAAE,EAC3B,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,GACjB,cAAc,EAAE,CAwBlB;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,cAAc,EAAE,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAanF;AAGD;;;;;;;;;GASG;AACH,wBAAgB,2BAA2B,CACzC,EAAE,EAAE,gBAAgB,GAAG,gBAAgB,EACvC,YAAY,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,EACjC,mBAAmB,EAAE,MAAM,EAC3B,SAAS,EAAE,MAAM,GAChB,cAAc,EAAE,GAAG,IAAI,CAqCzB;AAED,MAAM,WAAW,kBAAkB;IACjC,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,cAAc,CAAC,EAAE,OAAO,KAAK,OAAO,CAAC,GAAG,SAAS,CAAC;IAC3E,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,cAAc,CAAC,EAAE,OAAO,KAAK,OAAO,CAAC,GAAG,SAAS,CAAC;CACvE;AAED;;;GAGG;AACH,wBAAgB,0BAA0B,CACxC,OAAO,EAAE,gBAAgB,EACzB,QAAQ,EAAE,kBAAkB,GAAG,IAAI,GAAG,SAAS,EAC/C,mBAAmB,EAAE,MAAM,EAC3B,KAAK,EAAE,OAAO,CAAC,gBAAgB,EAAE,cAAc,EAAE,CAAC,GACjD,IAAI,CAqBN"}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared volume-automation utilities used by both the renderer (offline PCM
|
|
3
|
+
* baking in audioVolumeEnvelope.ts) and the preview runtime (per-tick gain
|
|
4
|
+
* applied in syncRuntimeMedia).
|
|
5
|
+
*
|
|
6
|
+
* Keeping the two concerns in one place ensures preview and render derive the
|
|
7
|
+
* envelope from the same logic and the same probe samples.
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Normalise raw keyframes to track-relative seconds: subtract `trackStart`,
|
|
11
|
+
* clamp to [0,1], sort, de-duplicate, and prepend a `baseVolume` anchor at
|
|
12
|
+
* t=0 when the first keyframe starts after the clip's begin.
|
|
13
|
+
*
|
|
14
|
+
* Returns an empty array when all keyframes are invalid — the caller should
|
|
15
|
+
* treat an empty envelope as "no automation, use static volume."
|
|
16
|
+
*/
|
|
17
|
+
export function normaliseEnvelope(keyframes, trackStart, baseVolume) {
|
|
18
|
+
const points = keyframes
|
|
19
|
+
.filter((k) => Number.isFinite(k.time) && Number.isFinite(k.volume))
|
|
20
|
+
.map((k) => ({
|
|
21
|
+
time: Math.max(0, k.time - trackStart),
|
|
22
|
+
volume: Math.max(0, Math.min(1, k.volume)),
|
|
23
|
+
}))
|
|
24
|
+
.sort((a, b) => a.time - b.time);
|
|
25
|
+
const deduped = [];
|
|
26
|
+
for (const point of points) {
|
|
27
|
+
const previous = deduped.at(-1);
|
|
28
|
+
if (previous && Math.abs(previous.time - point.time) < 1e-9) {
|
|
29
|
+
previous.volume = point.volume;
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
deduped.push(point);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
if (deduped.length === 0)
|
|
36
|
+
return deduped;
|
|
37
|
+
if (deduped[0].time > 0) {
|
|
38
|
+
deduped.unshift({ time: 0, volume: Math.max(0, Math.min(1, baseVolume)) });
|
|
39
|
+
}
|
|
40
|
+
return deduped;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Linearly interpolate the gain at time `t` (track-relative seconds) from a
|
|
44
|
+
* normalised envelope produced by `normaliseEnvelope`. Returns 1 when the
|
|
45
|
+
* envelope is empty.
|
|
46
|
+
*/
|
|
47
|
+
export function interpolateVolumeGain(envelope, t) {
|
|
48
|
+
if (envelope.length === 0)
|
|
49
|
+
return 1;
|
|
50
|
+
let segment = 0;
|
|
51
|
+
while (segment < envelope.length - 2 && t >= envelope[segment + 1].time) {
|
|
52
|
+
segment += 1;
|
|
53
|
+
}
|
|
54
|
+
const a = envelope[segment];
|
|
55
|
+
const b = envelope[segment + 1] ?? a;
|
|
56
|
+
const span = b.time - a.time;
|
|
57
|
+
const progress = span <= 0 ? 0 : Math.min(1, Math.max(0, (t - a.time) / span));
|
|
58
|
+
return a.volume + (b.volume - a.volume) * progress;
|
|
59
|
+
}
|
|
60
|
+
// fallow-ignore-next-line complexity
|
|
61
|
+
/**
|
|
62
|
+
* Probe a single media element's volume automation by seeking a GSAP timeline
|
|
63
|
+
* through the element's active window.
|
|
64
|
+
*
|
|
65
|
+
* Runs synchronously in the browser. The timeline is left at its current
|
|
66
|
+
* position after the probe (the next transport tick re-seeks it to `t`).
|
|
67
|
+
*
|
|
68
|
+
* Returns null when the element has no detectable automation (volume never
|
|
69
|
+
* changes from its initial `data-volume` value).
|
|
70
|
+
*/
|
|
71
|
+
export function probeElementVolumeKeyframes(el, seekTimeline, compositionDuration, sampleFps) {
|
|
72
|
+
const start = Number.parseFloat(el.dataset.start ?? "0") || 0;
|
|
73
|
+
const endAttr = Number.parseFloat(el.dataset.end ?? "");
|
|
74
|
+
const durAttr = Number.parseFloat(el.dataset.duration ?? "");
|
|
75
|
+
const end = Number.isFinite(endAttr) && endAttr > start
|
|
76
|
+
? endAttr
|
|
77
|
+
: Number.isFinite(durAttr) && durAttr > 0
|
|
78
|
+
? start + durAttr
|
|
79
|
+
: compositionDuration;
|
|
80
|
+
const staticAttr = Number.parseFloat(el.dataset.volume ?? "");
|
|
81
|
+
const staticVolume = Number.isFinite(staticAttr) ? Math.max(0, Math.min(1, staticAttr)) : 1;
|
|
82
|
+
// Reset to data-volume so GSAP captures the correct FROM value.
|
|
83
|
+
el.volume = staticVolume;
|
|
84
|
+
const step = 1 / Math.min(60, Math.max(1, sampleFps));
|
|
85
|
+
const sampleStart = Math.max(0, start);
|
|
86
|
+
const sampleEnd = Math.min(compositionDuration, end);
|
|
87
|
+
const keyframes = [];
|
|
88
|
+
for (let t = sampleStart; t <= sampleEnd + 1e-6; t += step) {
|
|
89
|
+
const bounded = Math.min(sampleEnd, t);
|
|
90
|
+
seekTimeline(bounded);
|
|
91
|
+
const raw = Number(el.volume);
|
|
92
|
+
if (!Number.isFinite(raw))
|
|
93
|
+
continue;
|
|
94
|
+
const volume = Math.max(0, Math.min(1, raw));
|
|
95
|
+
const last = keyframes.at(-1);
|
|
96
|
+
if (!last || Math.abs(last.volume - volume) > 0.0001 || bounded === sampleEnd) {
|
|
97
|
+
keyframes.push({ time: Number(bounded.toFixed(6)), volume: Number(volume.toFixed(6)) });
|
|
98
|
+
}
|
|
99
|
+
if (bounded === sampleEnd)
|
|
100
|
+
break;
|
|
101
|
+
}
|
|
102
|
+
const hasAutomation = keyframes.some((kf) => Math.abs(kf.volume - staticVolume) > 0.0001);
|
|
103
|
+
return hasAutomation ? keyframes : null;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Probe a media element and, if volume automation is detected, store the
|
|
107
|
+
* keyframes in `cache`. Safe to call with a null timeline — returns early.
|
|
108
|
+
*/
|
|
109
|
+
export function probeAndCacheElementVolume(mediaEl, timeline, compositionDuration, cache) {
|
|
110
|
+
if (!timeline)
|
|
111
|
+
return;
|
|
112
|
+
if (!(mediaEl instanceof HTMLAudioElement) && !(mediaEl instanceof HTMLVideoElement))
|
|
113
|
+
return;
|
|
114
|
+
if (compositionDuration <= 0)
|
|
115
|
+
return;
|
|
116
|
+
const seekFn = (t) => {
|
|
117
|
+
try {
|
|
118
|
+
if (typeof timeline.totalTime === "function") {
|
|
119
|
+
timeline.totalTime(t, true);
|
|
120
|
+
}
|
|
121
|
+
else if (typeof timeline.seek === "function") {
|
|
122
|
+
timeline.seek(t, true);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
catch {
|
|
126
|
+
// ignore seek failures during probe
|
|
127
|
+
}
|
|
128
|
+
};
|
|
129
|
+
const keyframes = probeElementVolumeKeyframes(mediaEl, seekFn, compositionDuration, 60);
|
|
130
|
+
if (keyframes) {
|
|
131
|
+
cache.set(mediaEl, keyframes);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
//# sourceMappingURL=mediaVolumeEnvelope.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mediaVolumeEnvelope.js","sourceRoot":"","sources":["../../src/runtime/mediaVolumeEnvelope.ts"],"names":[],"mappings":"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"}
|