@hyperframes/inspector 0.0.0-stage → 0.8.152

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.
Files changed (74) hide show
  1. package/LICENSE +190 -0
  2. package/README.md +104 -2
  3. package/dist/inspection.js +2007 -0
  4. package/dist/live.js +1288 -0
  5. package/dist/service.js +63122 -0
  6. package/dist/types/core/src/audioAutomation.d.ts +202 -0
  7. package/dist/types/core/src/audioFx.d.ts +181 -0
  8. package/dist/types/core/src/audioGain.d.ts +44 -0
  9. package/dist/types/core/src/colorGrading.d.ts +1959 -0
  10. package/dist/types/core/src/colorGradingCurves.d.ts +8 -0
  11. package/dist/types/core/src/colorLuts.d.ts +24 -0
  12. package/dist/types/core/src/compiler/assetPaths.d.ts +1 -0
  13. package/dist/types/core/src/compiler/compositionAssembly.d.ts +144 -0
  14. package/dist/types/core/src/compiler/compositionScoping.d.ts +28 -0
  15. package/dist/types/core/src/compiler/externalScripts.d.ts +8 -0
  16. package/dist/types/core/src/compiler/htmlBundler.d.ts +74 -0
  17. package/dist/types/core/src/compiler/htmlCompiler.d.ts +18 -0
  18. package/dist/types/core/src/compiler/htmlDocument.d.ts +23 -0
  19. package/dist/types/core/src/compiler/importMaps.d.ts +18 -0
  20. package/dist/types/core/src/compiler/inlineSubCompositions.d.ts +151 -0
  21. package/dist/types/core/src/compiler/rewriteSubCompPaths.d.ts +1 -0
  22. package/dist/types/core/src/compiler/scriptRuns.d.ts +31 -0
  23. package/dist/types/core/src/compiler/selectorIdTokens.d.ts +70 -0
  24. package/dist/types/core/src/compiler/standaloneEntry.d.ts +2 -0
  25. package/dist/types/core/src/compiler/staticGuard.d.ts +7 -0
  26. package/dist/types/core/src/compiler/svgIdNamespacing.d.ts +80 -0
  27. package/dist/types/core/src/compiler/svgSelectorAliases.d.ts +30 -0
  28. package/dist/types/core/src/compiler/timingCompiler.d.ts +89 -0
  29. package/dist/types/core/src/generated/runtime-inline.d.ts +6 -0
  30. package/dist/types/core/src/generated/svg-selector-aliases-inline.d.ts +2 -0
  31. package/dist/types/core/src/inline-scripts/pickerApi.d.ts +32 -0
  32. package/dist/types/core/src/inline-scripts/runtimeContract.d.ts +13 -0
  33. package/dist/types/core/src/mediaTiming.d.ts +41 -0
  34. package/dist/types/core/src/playbackRateBounds.d.ts +1 -0
  35. package/dist/types/core/src/runtime/analytics.d.ts +18 -0
  36. package/dist/types/core/src/runtime/applyVariableBindings.d.ts +47 -0
  37. package/dist/types/core/src/runtime/audioAutomationVolume.d.ts +19 -0
  38. package/dist/types/core/src/runtime/authoredTiming.d.ts +16 -0
  39. package/dist/types/core/src/runtime/compositionDimension.d.ts +5 -0
  40. package/dist/types/core/src/runtime/diagnostics.d.ts +3 -0
  41. package/dist/types/core/src/runtime/domRealm.d.ts +67 -0
  42. package/dist/types/core/src/runtime/flattenedRoot.d.ts +9 -0
  43. package/dist/types/core/src/runtime/getVariables.d.ts +42 -0
  44. package/dist/types/core/src/runtime/globals.d.ts +11 -0
  45. package/dist/types/core/src/runtime/inspectionTypes.d.ts +68 -0
  46. package/dist/types/core/src/runtime/playbackRate.d.ts +26 -0
  47. package/dist/types/core/src/runtime/protocol.d.ts +30 -0
  48. package/dist/types/core/src/runtime/proxySrc.d.ts +3 -0
  49. package/dist/types/core/src/runtime/startExpression.d.ts +14 -0
  50. package/dist/types/core/src/runtime/startResolver.d.ts +21 -0
  51. package/dist/types/core/src/runtime/timelineDuration.d.ts +3 -0
  52. package/dist/types/core/src/runtime/timelineInspection.d.ts +46 -0
  53. package/dist/types/core/src/runtime/timelineValues.d.ts +15 -0
  54. package/dist/types/core/src/runtime/types.d.ts +335 -0
  55. package/dist/types/core/src/runtime/variableScope.d.ts +8 -0
  56. package/dist/types/core/src/safePath.d.ts +49 -0
  57. package/dist/types/core/src/sceneParts.d.ts +9 -0
  58. package/dist/types/core/src/speedRamp.d.ts +59 -0
  59. package/dist/types/core/src/tokenSlug.d.ts +12 -0
  60. package/dist/types/inspector/src/elementMap.d.ts +33 -0
  61. package/dist/types/inspector/src/engine.d.ts +35 -0
  62. package/dist/types/inspector/src/live.d.ts +18 -0
  63. package/dist/types/inspector/src/mapInspection.d.ts +76 -0
  64. package/dist/types/inspector/src/outputSchemas.d.ts +12 -0
  65. package/dist/types/inspector/src/pageQueries.d.ts +21 -0
  66. package/dist/types/inspector/src/pageServer.d.ts +2 -0
  67. package/dist/types/inspector/src/requests.d.ts +5 -0
  68. package/dist/types/inspector/src/service.d.ts +98 -0
  69. package/dist/types/inspector/src/sourceDependencies.d.ts +5 -0
  70. package/dist/types/inspector/src/sources.d.ts +49 -0
  71. package/dist/types/inspector/src/timelineReport.d.ts +28 -0
  72. package/dist/types/inspector/src/tools.d.ts +18 -0
  73. package/dist/types/inspector/src/types.d.ts +1 -0
  74. package/package.json +54 -3
@@ -0,0 +1,202 @@
1
+ /**
2
+ * Automation envelopes for audio tracks.
3
+ *
4
+ * A lane is a list of breakpoints over one parameter — track volume, or one
5
+ * knob of one effect in the track's FX chain. Ableton's clip-envelope model:
6
+ * times are clip-local, so an envelope travels with the clip when it moves.
7
+ *
8
+ * Nothing here touches Web Audio. This module owns the format and the
9
+ * interpolation, and the same `sampleAutomationLane` is used to draw the lane
10
+ * in the timeline, to schedule it in preview, and to bake it at render — one
11
+ * curve, three consumers, or the picture and the sound disagree.
12
+ */
13
+ import { type HfAudioFxChain } from "./audioFx.js";
14
+ export declare const HF_AUDIO_AUTOMATION_ATTR = "data-automation";
15
+ /** The same attribute as a `dataset` / `dataAttributes` key. See `HF_AUDIO_FX_DATA_KEY`. */
16
+ export declare const HF_AUDIO_AUTOMATION_DATA_KEY: string;
17
+ /** Automation files are versioned; a reader must refuse a version it doesn't know. */
18
+ export declare const HF_AUDIO_AUTOMATION_VERSION = 1;
19
+ /**
20
+ * A pathological document should not be able to hang the scheduler, which
21
+ * expands every segment into scheduled ramps. Well past any hand-drawn
22
+ * envelope; a lane is dense at 100 points.
23
+ */
24
+ export declare const MAX_AUTOMATION_POINTS = 512;
25
+ export interface HfAutomationPoint {
26
+ /** Seconds from the start of the clip, not the composition. */
27
+ t: number;
28
+ /** Value in the parameter's own unit — dB for a threshold, Hz for a cutoff. */
29
+ v: number;
30
+ /**
31
+ * Curvature of the segment *leaving* this point, -1..1. Absent or 0 is a
32
+ * straight line; positive holds low then rises late, negative rises early.
33
+ */
34
+ curve?: number;
35
+ /**
36
+ * An interior point the segment *leaving* this point passes through, in
37
+ * normalised segment space: `viaX` is progress 0..1 between the two
38
+ * breakpoints, `viaY` is how far the value has travelled by then. Both are
39
+ * needed for either to mean anything; without them the segment falls back to
40
+ * `curve` above, so everything authored before this existed reads unchanged.
41
+ *
42
+ * Two numbers rather than one because `curve` answers only "how hard", and an
43
+ * exponent cannot say "and where". Every upward bend a single exponent can
44
+ * draw has its deepest deviation in the first fifth of the segment, whatever
45
+ * the author aimed at, and an exponent steep enough to reach a point near
46
+ * either end runs past the ±1 the model accepts — so a bend dragged near the
47
+ * right-hand breakpoint bulged on the left and then stopped following the
48
+ * pointer at all. Naming the point the curve goes through makes both the
49
+ * height and the position of the bend the author's to choose, and takes the
50
+ * saturation with it: any interior point is reachable exactly.
51
+ */
52
+ viaX?: number;
53
+ viaY?: number;
54
+ }
55
+ export interface HfAutomationLane {
56
+ /** `volume`, or `fx.<nodeId>.<paramKey>`. */
57
+ target: string;
58
+ points: HfAutomationPoint[];
59
+ }
60
+ export interface HfAutomation {
61
+ version: number;
62
+ lanes: HfAutomationLane[];
63
+ }
64
+ export declare class AudioAutomationError extends Error {
65
+ constructor(message: string);
66
+ }
67
+ export declare const VOLUME_TARGET = "volume";
68
+ /** Playback-rate lane: `v` is a speed multiplier over clip-local time. See `speedRamp.ts`. */
69
+ export declare const RATE_TARGET = "rate";
70
+ export type HfAutomationTarget = {
71
+ kind: "volume";
72
+ } | {
73
+ kind: "rate";
74
+ } | {
75
+ kind: "fx";
76
+ nodeId: string;
77
+ param: string;
78
+ } | {
79
+ kind: "preset";
80
+ presetId: string;
81
+ };
82
+ /** Split a target string. Returns null for anything unrecognised. */
83
+ export declare function parseAutomationTarget(target: string): HfAutomationTarget | null;
84
+ export declare function fxAutomationTarget(nodeId: string, param: string): string;
85
+ /**
86
+ * How much of a preset is applied, 0..1.
87
+ *
88
+ * A preset's nodes share no automatable parameter — and its worklet effects
89
+ * expose no AudioParams at all — so there is nothing to aim a lane at
90
+ * node-by-node. The graph wraps a preset's run in a wet/dry pair instead, and
91
+ * this drives the blend: 0 is the dry signal untouched, 1 is the preset fully
92
+ * applied, and between them it crossfades.
93
+ */
94
+ export declare function presetAutomationTarget(presetId: string): string;
95
+ /** 0..1 blend, the same shape as a wet/dry mix knob. */
96
+ export declare const PRESET_RANGE: AutomationRange;
97
+ /**
98
+ * The value range a lane is drawn and clamped against.
99
+ *
100
+ * Volume is linear over the full authoring gain range, matching `data-volume`
101
+ * and the existing volume envelope machinery — no dB conversion enters the
102
+ * volume path. Everything
103
+ * else is read from the effect registry, so a lane can never offer a value the
104
+ * renderer would reject, and the log-scaled knobs sweep the way a DAW's do.
105
+ */
106
+ export interface AutomationRange {
107
+ min: number;
108
+ max: number;
109
+ step: number;
110
+ unit: string;
111
+ label: string;
112
+ scale: "linear" | "log";
113
+ /** Where an empty lane draws its flat line, and what a new point starts at. */
114
+ default: number;
115
+ }
116
+ /**
117
+ * One ceiling for the fader, the lane, the preview transport and the render
118
+ * mixer. Capping the lane at unity while the fader reached +12 dB made
119
+ * automating a boosted clip silently discard the boost — and the panel
120
+ * disables the fader while a lane owns it, so there was no way back.
121
+ */
122
+ export declare const VOLUME_RANGE: AutomationRange;
123
+ export declare const RATE_RANGE: AutomationRange;
124
+ /**
125
+ * Resolve a lane's target against a chain. Returns null when the target names
126
+ * a node or parameter that is not there — the effect was deleted, or the
127
+ * parameter is an enum, which has no envelope between its values.
128
+ */
129
+ export declare function resolveAutomationRange(target: string, chain: HfAudioFxChain | undefined): AutomationRange | null;
130
+ /**
131
+ * The via point a segment will actually be drawn with, given one that was asked
132
+ * for — pulled into the steady region, or null when it describes no bend.
133
+ *
134
+ * Exported so an editor can write what the model will honour rather than what the
135
+ * pointer happened to ask for. Without it a lane's attribute claims a shape the
136
+ * renderer quietly declines to draw, and the two only agree once the file makes a
137
+ * round trip.
138
+ */
139
+ export declare function steadyViaPoint(viaX: number | undefined, viaY: number | undefined): {
140
+ viaX: number;
141
+ viaY: number;
142
+ } | null;
143
+ /**
144
+ * Structural normalisation, with no knowledge of the chain: sort and clean the
145
+ * points of every lane and drop lanes that carry none. Range clamping and
146
+ * orphan removal need the chain and happen in `resolveAutomation`.
147
+ */
148
+ export declare function normalizeAutomation(automation: HfAutomation): HfAutomation;
149
+ /**
150
+ * Bind automation to a chain: clamp each lane into its parameter's declared
151
+ * range and drop lanes whose target no longer exists.
152
+ *
153
+ * Dropping is deliberate. An envelope on a deleted effect has nothing to
154
+ * drive, and keeping it would silently reattach if an unrelated effect later
155
+ * took the same node id.
156
+ */
157
+ export declare function resolveAutomation(automation: HfAutomation, chain: HfAudioFxChain | undefined): HfAutomation;
158
+ /**
159
+ * Parse an automation attribute.
160
+ *
161
+ * Malformed input throws rather than being skipped, matching the chain reader:
162
+ * a track that quietly loses its envelope renders differently from the project
163
+ * the author saved, which is worse than refusing.
164
+ */
165
+ export declare function parseAutomation(json: string): HfAutomation;
166
+ /** Serialise for the `data-automation` attribute. */
167
+ export declare function serializeAutomation(automation: HfAutomation): string;
168
+ /**
169
+ * Shape the 0..1 progress across a segment.
170
+ *
171
+ * `curve` is an exponent in disguise: 0 is linear, and the ends reach a
172
+ * quarter-power and a fourth-power bend, which is about the range a DAW's
173
+ * envelope handle covers before the segment stops reading as a curve.
174
+ */
175
+ export declare function applyCurve(x: number, curve: number | undefined): number;
176
+ /**
177
+ * The progress a segment leaving `point` has reached at normalised `x`.
178
+ *
179
+ * A via point wins when it is there, since it says strictly more than an
180
+ * exponent can. Everything authored before via points existed carries only
181
+ * `curve` and takes the exponent path unchanged.
182
+ */
183
+ export declare function shapeProgress(x: number, point: {
184
+ curve?: number | undefined;
185
+ viaX?: number | undefined;
186
+ viaY?: number | undefined;
187
+ }): number;
188
+ /**
189
+ * Value of a lane at a clip-local time.
190
+ *
191
+ * Outside the points, the envelope holds — the first value before it starts
192
+ * and the last value after it ends, so a lane never snaps to zero at the edges.
193
+ */
194
+ export declare function sampleAutomationLane(lane: HfAutomationLane, t: number, scale?: "linear" | "log"): number;
195
+ /** True when the lane is a single value, i.e. worth setting once and not scheduling. */
196
+ export declare function isConstantLane(lane: HfAutomationLane): boolean;
197
+ /**
198
+ * Sample a lane onto evenly spaced times, for consumers that want a plain
199
+ * curve rather than a breakpoint list: `setValueCurveAtTime`, the render-side
200
+ * volume envelope, and the lane's own drawing code.
201
+ */
202
+ export declare function sampleAutomationCurve(lane: HfAutomationLane, from: number, to: number, count: number, scale?: "linear" | "log"): Float32Array;
@@ -0,0 +1,181 @@
1
+ /**
2
+ * Audio FX chain: the one description of every effect that can be applied to an
3
+ * audio track.
4
+ *
5
+ * Preview and render both run the same Web Audio graph — the studio in a live
6
+ * AudioContext, the engine in an OfflineAudioContext inside the headless
7
+ * browser it already drives. There is only one implementation of each effect,
8
+ * so preview predicting the render is a property of the architecture rather
9
+ * than something to measure and defend.
10
+ *
11
+ * This file holds what both ends need to agree on: the parameter set for each
12
+ * effect with its usable range, and the id of the graph builder that realises
13
+ * it. Parameters are declared in the units a person thinks in (dB, ms, Hz);
14
+ * the graph builders convert where the Web Audio node wants something else.
15
+ */
16
+ export declare const HF_AUDIO_FX_ATTR = "data-fx-chain";
17
+ /**
18
+ * The same attribute as a `dataset` / `dataAttributes` key — the `data-` prefix
19
+ * is not part of that spelling.
20
+ *
21
+ * Derived rather than restated: the studio writes through
22
+ * `HF_AUDIO_FX_ATTR` and reads through the key, so a hardcoded `"fx-chain"`
23
+ * on the read side is a rename waiting to half-land.
24
+ */
25
+ export declare const HF_AUDIO_FX_DATA_KEY: string;
26
+ /** Chain files are versioned; a reader must refuse a version it doesn't know. */
27
+ export declare const HF_AUDIO_FX_CHAIN_VERSION = 1;
28
+ export type HfAudioFxGroup = "filter" | "dynamics" | "nonlinear" | "time";
29
+ export interface HfAudioFxNumberParam {
30
+ kind: "number";
31
+ key: string;
32
+ label: string;
33
+ /** Shown after the value in the panel; "" for a bare ratio. */
34
+ unit: string;
35
+ min: number;
36
+ max: number;
37
+ step: number;
38
+ default: number;
39
+ /** Frequency-style controls need a log knob to be usable. */
40
+ scale?: "linear" | "log";
41
+ /**
42
+ * The knob is backed by an AudioParam, so an automation lane can drive it.
43
+ *
44
+ * Not every knob can be: a WaveShaper curve, a convolution impulse and a
45
+ * worklet's `processorOptions` are all set wholesale rather than scheduled.
46
+ * A graph builder must expose an AudioParam for every parameter flagged here
47
+ * — `audioFxGraph.test.ts` builds each effect and checks it.
48
+ */
49
+ automatable?: boolean;
50
+ /** One line explaining what turning this does, shown on the control. */
51
+ hint?: string;
52
+ }
53
+ export interface HfAudioFxEnumParam {
54
+ kind: "enum";
55
+ key: string;
56
+ label: string;
57
+ options: readonly {
58
+ value: string;
59
+ label: string;
60
+ }[];
61
+ default: string;
62
+ hint?: string;
63
+ }
64
+ export type HfAudioFxParam = HfAudioFxNumberParam | HfAudioFxEnumParam;
65
+ export type HfAudioFxParamValues = Record<string, number | string>;
66
+ export interface HfAudioFxDef {
67
+ id: string;
68
+ label: string;
69
+ group: HfAudioFxGroup;
70
+ /** One sentence on what the effect is for, shown when adding it. */
71
+ description: string;
72
+ params: readonly HfAudioFxParam[];
73
+ /**
74
+ * Identifier for the Web Audio graph builder that realises this effect. Kept
75
+ * as a string rather than a function so this module stays free of browser
76
+ * globals and can be imported by the engine and the linter.
77
+ */
78
+ web: string;
79
+ }
80
+ /**
81
+ * Every effect, in panel order. Ranges are the usable span for each control;
82
+ * a value that survives `normalizeAudioFxParams` is always safe to realise.
83
+ */
84
+ export declare const HF_AUDIO_FX: readonly HfAudioFxDef[];
85
+ export declare function getAudioFxDef(id: string): HfAudioFxDef | undefined;
86
+ export declare const HF_AUDIO_FX_IDS: readonly string[];
87
+ /** Every parameter at its declared default, ready to seed a freshly added effect. */
88
+ export declare function defaultAudioFxParams(id: string): HfAudioFxParamValues;
89
+ /**
90
+ * Clamp and fill a parameter set so it is always renderable: unknown keys are
91
+ * dropped, missing keys take their default, numbers are clamped into their
92
+ * declared range, and an unrecognised enum value falls back to its default.
93
+ * A non-finite number is treated as missing rather than passed through, since
94
+ * NaN reaching an AudioParam silences the node for the rest of the render.
95
+ */
96
+ export declare function normalizeAudioFxParams(id: string, values: Readonly<HfAudioFxParamValues> | undefined): HfAudioFxParamValues;
97
+ export interface HfAudioFxNode {
98
+ /** Effect id from HF_AUDIO_FX. */
99
+ type: string;
100
+ /**
101
+ * Stable handle for this node within its chain, minted when the node is
102
+ * added. Automation lanes address nodes by id (`fx.<id>.<param>`) so that
103
+ * reordering the chain never re-points a lane at a different effect. Older
104
+ * chains have no ids; they load fine and simply cannot be automated until
105
+ * the panel touches them.
106
+ */
107
+ id?: string;
108
+ /** Set on nodes the carve analysis generated, so re-running replaces them
109
+ * instead of stacking another set on top of hand-added effects. */
110
+ fromCarve?: boolean;
111
+ /**
112
+ * Id of the preset that wrote this node, for the same reason `fromCarve`
113
+ * exists: re-applying a preset replaces its own nodes rather than adding a
114
+ * second copy, and the rack can brace them together under the preset's name.
115
+ *
116
+ * The id rather than a flag, because a chain can carry more than one preset
117
+ * and each has to be able to find its own.
118
+ */
119
+ fromPreset?: string;
120
+ /**
121
+ * What the rack calls this node, when the effect's own name is not specific
122
+ * enough to be useful.
123
+ *
124
+ * A peaking filter is "Shape One Range" wherever it appears, so a chain that
125
+ * cuts mud at 250 Hz and lifts clarity at 3 kHz shows the same words twice
126
+ * and an author cannot tell the two apart. A preset names each node for the
127
+ * JOB it is doing instead — "Reduce Mud", "Add Clarity" — and the rack reads
128
+ * as a list of things that were done rather than a list of filter types.
129
+ */
130
+ label?: string;
131
+ /**
132
+ * Id of the multi-band EQ that owns this node, when it is one of its bands.
133
+ *
134
+ * Same device as `fromCarve`: the module gathers its own nodes out of the
135
+ * chain and presents them as one control surface, so an EQ needs no new
136
+ * effect type and its bands stay ordinary filters underneath.
137
+ */
138
+ fromEq?: string;
139
+ /**
140
+ * How much of this node's preset is applied, 0..1 — the wet/dry blend the
141
+ * graph wraps its run in.
142
+ *
143
+ * On every node of the run rather than beside the chain, because the chain has
144
+ * nowhere else to put it: `HfAudioFxChain` is a version and a list of nodes,
145
+ * and a preset is defined by which nodes carry its tag. The graph reads it off
146
+ * the first node of each run. Absent means fully applied, which is what every
147
+ * chain written before this means.
148
+ */
149
+ presetAmount?: number;
150
+ /**
151
+ * Set on the gain stage the leveller writes, so re-running replaces it rather
152
+ * than stacking a second one — the same contract `fromCarve` has.
153
+ */
154
+ fromLeveller?: boolean;
155
+ /** Absent means enabled — chain files written before the field existed still load. */
156
+ enabled?: boolean;
157
+ params?: HfAudioFxParamValues;
158
+ }
159
+ export interface HfAudioFxChain {
160
+ version: number;
161
+ nodes: HfAudioFxNode[];
162
+ }
163
+ export declare class AudioFxChainError extends Error {
164
+ constructor(message: string);
165
+ }
166
+ /**
167
+ * Parse a chain file. Unknown effect ids are rejected rather than skipped: a
168
+ * chain that silently loses a node would render differently from the project
169
+ * the author saved, which is worse than refusing to render at all.
170
+ */
171
+ export declare function parseAudioFxChain(json: string): HfAudioFxChain;
172
+ /** The nodes that should process audio, in order. */
173
+ export declare function enabledAudioFxNodes(chain: HfAudioFxChain): HfAudioFxNode[];
174
+ /** Serialise a chain for the `data-fx-chain` attribute. */
175
+ export declare function serializeAudioFxChain(chain: HfAudioFxChain): string;
176
+ /**
177
+ * Next free node id for a chain, as `n1`, `n2`, … — counted rather than random
178
+ * so that adding an effect produces the same document on every machine, which
179
+ * compositions require.
180
+ */
181
+ export declare function mintAudioFxNodeId(chain: HfAudioFxChain): string;
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Authoring gain for a media clip.
3
+ *
4
+ * HTMLMediaElement.volume is limited to 0..1, but HyperFrames' Web Audio
5
+ * preview and FFmpeg render paths both support gain above unity. Keep the
6
+ * shared ceiling here so Studio, preview, and render cannot drift.
7
+ */
8
+ export declare const MAX_AUDIO_GAIN_DB = 12;
9
+ /** Linear gain from a decibel value. Owner of the dB → gain formula. */
10
+ export declare function audioDbToGain(db: number): number;
11
+ /** Inverse of `audioDbToGain`. Caller must pass a positive finite gain. */
12
+ export declare function audioGainToDb(gain: number): number;
13
+ export declare const MAX_AUDIO_GAIN: number;
14
+ /** Studio fader coordinates. Unity is deliberately the physical midpoint. */
15
+ export declare const AUDIO_GAIN_FADER_MIN = -100;
16
+ export declare const AUDIO_GAIN_FADER_MAX = 100;
17
+ export declare function clampAudioGain(value: number): number;
18
+ export declare function clampNativeMediaVolume(value: number): number;
19
+ /**
20
+ * Serialize an authored gain for `data-volume`.
21
+ *
22
+ * The fader travels in dB, so its stops are irrational (position -70 is
23
+ * 10 ** (-42/20)). Rounding to two decimals — what the generic numeric
24
+ * attribute formatter does — collapses the whole bottom of the fader onto
25
+ * `"0"` (a hard mute) and makes the knob jump on release everywhere below
26
+ * unity. Six decimals round-trip every integer fader stop back to itself.
27
+ */
28
+ export declare function formatAudioGain(gain: number): string;
29
+ /**
30
+ * Run `probe` with `el.volume` shadowed by an accessor that keeps the authored
31
+ * value instead of the spec's [0,1] clamp.
32
+ *
33
+ * `HTMLMediaElement.volume` cannot hold gain above unity, so a clip authored
34
+ * at `data-volume="1.95"` reads back as 1 the moment the probe seeds it — and
35
+ * a GSAP tween started from that seed fades from 0 dB rather than from the
36
+ * authored boost. Both the FFmpeg mixer and the Web Audio transport carry gain
37
+ * up to MAX_AUDIO_GAIN, so the clamp is a probe artefact, not a real ceiling.
38
+ * The native setter still receives the clamped value, so nothing outside the
39
+ * probe observes an out-of-range volume, and the shadow is removed afterwards.
40
+ */
41
+ export declare function withUnclampedVolume<T>(el: HTMLMediaElement, probe: () => T): T;
42
+ export declare function audioFaderPositionToGain(position: number): number;
43
+ export declare function audioGainToFaderPosition(gain: number): number;
44
+ export declare function audioGainToText(gain: number): string;