@mebius-io/web 0.6.0 → 0.6.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/LICENSE +21 -0
- package/dist/index.cjs +56 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +18 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.global.js +56 -6
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +56 -6
- package/dist/index.js.map +1 -1
- package/package.json +11 -12
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Mebius
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/dist/index.cjs
CHANGED
|
@@ -852,6 +852,7 @@ function normalize(c, fallback) {
|
|
|
852
852
|
var TICK_MS = 100;
|
|
853
853
|
var STALE_MS = 5e3;
|
|
854
854
|
var MAX_QUEUE_MS = 1500;
|
|
855
|
+
var HIDDEN_GRACE_MS = 6e4;
|
|
855
856
|
var MebiusCaptions = class extends TypedEmitter {
|
|
856
857
|
/** @internal */
|
|
857
858
|
constructor(signaling, player, opts) {
|
|
@@ -869,25 +870,74 @@ var MebiusCaptions = class extends TypedEmitter {
|
|
|
869
870
|
* every 100ms tick. Comparing revs emits exactly once per actual revision.
|
|
870
871
|
*/
|
|
871
872
|
this.shown = /* @__PURE__ */ new Map();
|
|
873
|
+
/** Kept so the feed can be reopened after a hidden-tab suspend. */
|
|
874
|
+
this.streamId = null;
|
|
875
|
+
this.hiddenTimer = null;
|
|
876
|
+
this.onVisibility = null;
|
|
872
877
|
}
|
|
873
878
|
/** Open the SSE connection and begin emitting segments for `streamId`. */
|
|
874
879
|
start(streamId) {
|
|
875
880
|
if (this.es) return;
|
|
876
|
-
|
|
877
|
-
|
|
881
|
+
this.streamId = streamId;
|
|
882
|
+
this.openFeed();
|
|
883
|
+
this.watchVisibility();
|
|
884
|
+
}
|
|
885
|
+
/** Close the connection and drop all buffered segments. */
|
|
886
|
+
stop() {
|
|
887
|
+
this.streamId = null;
|
|
888
|
+
if (this.onVisibility && typeof document !== "undefined") {
|
|
889
|
+
document.removeEventListener("visibilitychange", this.onVisibility);
|
|
890
|
+
}
|
|
891
|
+
this.onVisibility = null;
|
|
892
|
+
if (this.hiddenTimer) clearTimeout(this.hiddenTimer);
|
|
893
|
+
this.hiddenTimer = null;
|
|
894
|
+
this.closeFeed();
|
|
895
|
+
this.pending.clear();
|
|
896
|
+
this.shown.clear();
|
|
897
|
+
}
|
|
898
|
+
openFeed() {
|
|
899
|
+
if (this.es || !this.streamId) return;
|
|
900
|
+
const es = new EventSource(this.signaling.captionsUrl(this.streamId, this.opts.lang));
|
|
878
901
|
es.onmessage = (ev) => this.onFrame(ev);
|
|
879
902
|
es.onerror = () => this.emit("error", void 0);
|
|
880
903
|
this.es = es;
|
|
881
904
|
this.timer = setInterval(() => this.tick(), TICK_MS);
|
|
882
905
|
}
|
|
883
|
-
|
|
884
|
-
stop() {
|
|
906
|
+
closeFeed() {
|
|
885
907
|
this.es?.close();
|
|
886
908
|
this.es = null;
|
|
887
909
|
if (this.timer) clearInterval(this.timer);
|
|
888
910
|
this.timer = null;
|
|
889
|
-
|
|
890
|
-
|
|
911
|
+
}
|
|
912
|
+
/**
|
|
913
|
+
* Drop the feed while the page is hidden, restore it when it comes back.
|
|
914
|
+
*
|
|
915
|
+
* Nothing here is about rendering — a hidden tab shows no captions either
|
|
916
|
+
* way. It is about not holding a subscriber open, since that subscriber is
|
|
917
|
+
* what keeps a billed session alive on the engine.
|
|
918
|
+
*
|
|
919
|
+
* Buffered segments are deliberately kept across a suspend: they age out on
|
|
920
|
+
* their own (STALE_MS) and clearing them would blank the screen on return
|
|
921
|
+
* for no benefit.
|
|
922
|
+
*/
|
|
923
|
+
watchVisibility() {
|
|
924
|
+
if (typeof document === "undefined") return;
|
|
925
|
+
this.onVisibility = () => {
|
|
926
|
+
if (document.visibilityState === "hidden") {
|
|
927
|
+
if (this.hiddenTimer) return;
|
|
928
|
+
this.hiddenTimer = setTimeout(() => {
|
|
929
|
+
this.hiddenTimer = null;
|
|
930
|
+
this.closeFeed();
|
|
931
|
+
}, HIDDEN_GRACE_MS);
|
|
932
|
+
return;
|
|
933
|
+
}
|
|
934
|
+
if (this.hiddenTimer) {
|
|
935
|
+
clearTimeout(this.hiddenTimer);
|
|
936
|
+
this.hiddenTimer = null;
|
|
937
|
+
}
|
|
938
|
+
this.openFeed();
|
|
939
|
+
};
|
|
940
|
+
document.addEventListener("visibilitychange", this.onVisibility);
|
|
891
941
|
}
|
|
892
942
|
onFrame(ev) {
|
|
893
943
|
let frame;
|