+9
-5
src/components/embeds/players/video-player.tsx
+9
-5
src/components/embeds/players/video-player.tsx
···
8
8
9
9
import { replaceVideoCdnUrl } from '~/lib/bsky/video';
10
10
import { useSession } from '~/lib/states/session';
11
+
import { throttleTrailing } from '~/lib/utils/misc';
11
12
12
13
const isMobile = /Android|iPhone|iPad|iPod/.test(navigator.userAgent);
13
14
···
70
71
node.volume = currentAccount.preferences.ui.mediaVolume;
71
72
}
72
73
73
-
hls.on(Hls.Events.FRAG_LOADED, () => {
74
-
if (currentAccount) {
75
-
currentAccount.preferences.ui.videoBwEstimate = hls.bandwidthEstimate;
76
-
}
77
-
});
74
+
hls.on(
75
+
Hls.Events.FRAG_LOADED,
76
+
throttleTrailing(() => {
77
+
if (currentAccount && !Number.isNaN(hls.bandwidthEstimate)) {
78
+
currentAccount.preferences.ui.videoBwEstimate = Math.round(hls.bandwidthEstimate);
79
+
}
80
+
}, 5_000),
81
+
);
78
82
79
83
hls.on(Hls.Events.LEVEL_LOADED, (_event, data) => {
80
84
const hasAudio = data.levelInfo.audioCodec !== undefined;
+69
src/lib/utils/misc.ts
+69
src/lib/utils/misc.ts
···
88
88
89
89
return result as Omit<T, K>;
90
90
};
91
+
92
+
export const throttleLeading = <T extends (...args: any[]) => void>(
93
+
fn: T,
94
+
wait: number,
95
+
): ((...args: Parameters<T>) => void) => {
96
+
let lastCallTime: number | undefined;
97
+
98
+
return (...args: Parameters<T>) => {
99
+
const now = performance.now();
100
+
101
+
if (lastCallTime === undefined || now - lastCallTime >= wait) {
102
+
lastCallTime = now;
103
+
fn(...args);
104
+
}
105
+
};
106
+
};
107
+
108
+
export const throttleTrailing = <T extends (...args: any[]) => void>(
109
+
fn: T,
110
+
wait: number,
111
+
): ((...args: Parameters<T>) => void) => {
112
+
let timeoutId: ReturnType<typeof setTimeout> | undefined;
113
+
let lastArgs: Parameters<T> | undefined;
114
+
115
+
return (...args: Parameters<T>) => {
116
+
lastArgs = args;
117
+
118
+
if (timeoutId === undefined) {
119
+
timeoutId = setTimeout(() => {
120
+
timeoutId = undefined;
121
+
fn(...lastArgs!);
122
+
}, wait);
123
+
}
124
+
};
125
+
};
126
+
127
+
export const throttle = <T extends (...args: any[]) => void>(
128
+
fn: T,
129
+
wait: number,
130
+
): ((...args: Parameters<T>) => void) => {
131
+
let timeoutId: ReturnType<typeof setTimeout> | undefined;
132
+
let lastArgs: Parameters<T> | undefined;
133
+
let lastCallTime: number | undefined;
134
+
135
+
return (...args: Parameters<T>) => {
136
+
const now = performance.now();
137
+
const elapsed = lastCallTime !== undefined ? now - lastCallTime : wait;
138
+
139
+
if (elapsed >= wait) {
140
+
if (timeoutId !== undefined) {
141
+
clearTimeout(timeoutId);
142
+
timeoutId = undefined;
143
+
}
144
+
145
+
lastCallTime = now;
146
+
fn(...args);
147
+
} else {
148
+
lastArgs = args;
149
+
150
+
if (timeoutId === undefined) {
151
+
timeoutId = setTimeout(() => {
152
+
timeoutId = undefined;
153
+
lastCallTime = performance.now();
154
+
fn(...lastArgs!);
155
+
}, wait - elapsed);
156
+
}
157
+
}
158
+
};
159
+
};