avbridge 2.9.0 → 2.10.0
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/CHANGELOG.md +31 -0
- package/dist/{chunk-SN4WZE24.js → chunk-3GKM5DFM.js} +42 -5
- package/dist/chunk-3GKM5DFM.js.map +1 -0
- package/dist/{chunk-EY6DZEDT.cjs → chunk-NQULEIA3.cjs} +42 -5
- package/dist/chunk-NQULEIA3.cjs.map +1 -0
- package/dist/element-browser.js +40 -3
- package/dist/element-browser.js.map +1 -1
- package/dist/element.cjs +2 -2
- package/dist/element.d.cts +1 -1
- package/dist/element.d.ts +1 -1
- package/dist/element.js +1 -1
- package/dist/index.cjs +8 -8
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/{player-DEcidWk6.d.cts → player-DDdNVFDv.d.cts} +23 -1
- package/dist/{player-DEcidWk6.d.ts → player-DDdNVFDv.d.ts} +23 -1
- package/dist/player.cjs +230 -98
- package/dist/player.cjs.map +1 -1
- package/dist/player.d.cts +27 -0
- package/dist/player.d.ts +27 -0
- package/dist/player.js +230 -98
- package/dist/player.js.map +1 -1
- package/package.json +1 -1
- package/src/element/avbridge-player.ts +150 -75
- package/src/element/player-styles.ts +85 -35
- package/src/index.ts +1 -0
- package/src/strategies/fallback/audio-output.ts +29 -4
- package/src/strategies/fallback/index.ts +12 -0
- package/src/strategies/hybrid/index.ts +9 -0
- package/src/types.ts +25 -0
- package/dist/chunk-EY6DZEDT.cjs.map +0 -1
- package/dist/chunk-SN4WZE24.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,37 @@ All notable changes to **avbridge.js** are documented here. The format follows
|
|
|
4
4
|
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and this project
|
|
5
5
|
adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
6
|
|
|
7
|
+
## [2.10.0]
|
|
8
|
+
|
|
9
|
+
Settings UI overhaul + playback rate on all strategies.
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
|
|
13
|
+
- **Bottom-sheet settings panel** replacing the popup menu. Slides up
|
|
14
|
+
from the controls bar with a scrim overlay. Each section uses a
|
|
15
|
+
native `<select>` picker overlaid on a styled row — the OS picker
|
|
16
|
+
renders outside the player bounds (intentional for small players).
|
|
17
|
+
Rows show label left, current value right. Tapping anywhere outside
|
|
18
|
+
the sheet or pressing Escape dismisses it.
|
|
19
|
+
- **Consumer extensibility API**: `player.addSettingsSection({ id,
|
|
20
|
+
label, items, onSelect })` / `player.removeSettingsSection(id)`.
|
|
21
|
+
Custom sections render after built-in ones using the same native
|
|
22
|
+
`<select>` pattern. New `SettingsSectionConfig` type exported.
|
|
23
|
+
- **Playback rate on hybrid + fallback strategies.** `playbackRate`
|
|
24
|
+
was a no-op on canvas strategies because the inner `<video>` has
|
|
25
|
+
no `src`. Now patched via `Object.defineProperty` — drives the
|
|
26
|
+
`AudioOutput` clock speed + `AudioBufferSourceNode.playbackRate`
|
|
27
|
+
for pitch-shifted audio. Video renderer follows automatically
|
|
28
|
+
since it syncs to `audio.now()`. The `ratechange` event fires.
|
|
29
|
+
|
|
30
|
+
### Fixed
|
|
31
|
+
|
|
32
|
+
- **Settings menu sizing** — JS-measured max-height (70% of player)
|
|
33
|
+
replaces the broken CSS percentage approach.
|
|
34
|
+
- **Blue tap-highlight flash** suppressed on `<avbridge-player>`.
|
|
35
|
+
- **`cursor: pointer` removed** from the player container — the
|
|
36
|
+
video surface isn't a button.
|
|
37
|
+
|
|
7
38
|
## [2.9.0]
|
|
8
39
|
|
|
9
40
|
Player chrome ergonomics — four changes driven by explorer integration
|
|
@@ -1374,6 +1374,10 @@ var AudioOutput = class {
|
|
|
1374
1374
|
_volume = 1;
|
|
1375
1375
|
/** User-set muted flag. When true, gain is forced to 0. */
|
|
1376
1376
|
_muted = false;
|
|
1377
|
+
/** Playback rate. Scales the media clock and each AudioBufferSourceNode's
|
|
1378
|
+
* playbackRate so audio pitches up/down accordingly (same as native
|
|
1379
|
+
* <video>.playbackRate). Default 1. */
|
|
1380
|
+
_rate = 1;
|
|
1377
1381
|
constructor() {
|
|
1378
1382
|
this.ctx = new AudioContext();
|
|
1379
1383
|
this.gain = this.ctx.createGain();
|
|
@@ -1395,6 +1399,20 @@ var AudioOutput = class {
|
|
|
1395
1399
|
getMuted() {
|
|
1396
1400
|
return this._muted;
|
|
1397
1401
|
}
|
|
1402
|
+
/** Set playback rate. Scales the media clock and pitches audio output
|
|
1403
|
+
* (same as native <video>.playbackRate — speed without pitch correction).
|
|
1404
|
+
* Rebases the anchor so the clock transition is seamless. */
|
|
1405
|
+
setPlaybackRate(rate) {
|
|
1406
|
+
if (rate === this._rate) return;
|
|
1407
|
+
const t = this.now();
|
|
1408
|
+
this.mediaTimeOfAnchor = t;
|
|
1409
|
+
this.ctxTimeAtAnchor = this.ctx.currentTime;
|
|
1410
|
+
this.wallAnchorMs = performance.now();
|
|
1411
|
+
this._rate = rate;
|
|
1412
|
+
}
|
|
1413
|
+
getPlaybackRate() {
|
|
1414
|
+
return this._rate;
|
|
1415
|
+
}
|
|
1398
1416
|
applyGain() {
|
|
1399
1417
|
const target = this._muted ? 0 : this._volume;
|
|
1400
1418
|
try {
|
|
@@ -1415,12 +1433,12 @@ var AudioOutput = class {
|
|
|
1415
1433
|
now() {
|
|
1416
1434
|
if (this.noAudio) {
|
|
1417
1435
|
if (this.state === "playing") {
|
|
1418
|
-
return this.mediaTimeOfAnchor + (performance.now() - this.wallAnchorMs) / 1e3;
|
|
1436
|
+
return this.mediaTimeOfAnchor + (performance.now() - this.wallAnchorMs) / 1e3 * this._rate;
|
|
1419
1437
|
}
|
|
1420
1438
|
return this.mediaTimeOfAnchor;
|
|
1421
1439
|
}
|
|
1422
1440
|
if (this.state === "playing") {
|
|
1423
|
-
return this.mediaTimeOfAnchor + (this.ctx.currentTime - this.ctxTimeAtAnchor);
|
|
1441
|
+
return this.mediaTimeOfAnchor + (this.ctx.currentTime - this.ctxTimeAtAnchor) * this._rate;
|
|
1424
1442
|
}
|
|
1425
1443
|
return this.mediaTimeOfAnchor;
|
|
1426
1444
|
}
|
|
@@ -1472,7 +1490,8 @@ var AudioOutput = class {
|
|
|
1472
1490
|
const node = this.ctx.createBufferSource();
|
|
1473
1491
|
node.buffer = buffer;
|
|
1474
1492
|
node.connect(this.gain);
|
|
1475
|
-
|
|
1493
|
+
if (this._rate !== 1) node.playbackRate.value = this._rate;
|
|
1494
|
+
let ctxStart = this.ctxTimeAtAnchor + (this.mediaTimeOfNext - this.mediaTimeOfAnchor) / this._rate;
|
|
1476
1495
|
if (ctxStart < this.ctx.currentTime) {
|
|
1477
1496
|
this.ctxTimeAtAnchor = this.ctx.currentTime;
|
|
1478
1497
|
this.mediaTimeOfAnchor = this.mediaTimeOfNext;
|
|
@@ -2120,6 +2139,14 @@ async function createHybridSession(ctx, target, transport) {
|
|
|
2120
2139
|
get: () => ctx.duration ?? NaN
|
|
2121
2140
|
});
|
|
2122
2141
|
}
|
|
2142
|
+
Object.defineProperty(target, "playbackRate", {
|
|
2143
|
+
configurable: true,
|
|
2144
|
+
get: () => audio.getPlaybackRate(),
|
|
2145
|
+
set: (v) => {
|
|
2146
|
+
audio.setPlaybackRate(v);
|
|
2147
|
+
target.dispatchEvent(new Event("ratechange"));
|
|
2148
|
+
}
|
|
2149
|
+
});
|
|
2123
2150
|
Object.defineProperty(target, "readyState", {
|
|
2124
2151
|
configurable: true,
|
|
2125
2152
|
get: () => {
|
|
@@ -2230,6 +2257,7 @@ async function createHybridSession(ctx, target, transport) {
|
|
|
2230
2257
|
delete target.muted;
|
|
2231
2258
|
delete target.readyState;
|
|
2232
2259
|
delete target.seekable;
|
|
2260
|
+
delete target.playbackRate;
|
|
2233
2261
|
} catch {
|
|
2234
2262
|
}
|
|
2235
2263
|
},
|
|
@@ -2765,6 +2793,14 @@ async function createFallbackSession(ctx, target, transport) {
|
|
|
2765
2793
|
get: () => ctx.duration ?? NaN
|
|
2766
2794
|
});
|
|
2767
2795
|
}
|
|
2796
|
+
Object.defineProperty(target, "playbackRate", {
|
|
2797
|
+
configurable: true,
|
|
2798
|
+
get: () => audio.getPlaybackRate(),
|
|
2799
|
+
set: (v) => {
|
|
2800
|
+
audio.setPlaybackRate(v);
|
|
2801
|
+
target.dispatchEvent(new Event("ratechange"));
|
|
2802
|
+
}
|
|
2803
|
+
});
|
|
2768
2804
|
Object.defineProperty(target, "readyState", {
|
|
2769
2805
|
configurable: true,
|
|
2770
2806
|
get: () => {
|
|
@@ -2896,6 +2932,7 @@ async function createFallbackSession(ctx, target, transport) {
|
|
|
2896
2932
|
delete target.muted;
|
|
2897
2933
|
delete target.readyState;
|
|
2898
2934
|
delete target.seekable;
|
|
2935
|
+
delete target.playbackRate;
|
|
2899
2936
|
} catch {
|
|
2900
2937
|
}
|
|
2901
2938
|
},
|
|
@@ -3498,5 +3535,5 @@ function defaultFallbackChain(strategy) {
|
|
|
3498
3535
|
}
|
|
3499
3536
|
|
|
3500
3537
|
export { FALLBACK_AUDIO_CODECS, FALLBACK_VIDEO_CODECS, NATIVE_AUDIO_CODECS, NATIVE_VIDEO_CODECS, UnifiedPlayer, classifyContext, createPlayer };
|
|
3501
|
-
//# sourceMappingURL=chunk-
|
|
3502
|
-
//# sourceMappingURL=chunk-
|
|
3538
|
+
//# sourceMappingURL=chunk-3GKM5DFM.js.map
|
|
3539
|
+
//# sourceMappingURL=chunk-3GKM5DFM.js.map
|