Skip to content

Commit 28d32b2

Browse files
committed
Reorder helpers and drop syntax that stricter ESLint configs reject
Behavior-neutral: hoist the module helpers above the class, avoid continue and for...of, and use optional catch bindings, so the file drops into projects with airbnb-style lint configs (like the Owncast web app) without divergence.
1 parent ec152c3 commit 28d32b2

1 file changed

Lines changed: 74 additions & 75 deletions

File tree

latencyCompensator.js

Lines changed: 74 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -345,6 +345,67 @@ function mean(values) {
345345
return values.reduce((a, b) => a + b, 0) / values.length;
346346
}
347347

348+
function getCurrentlyPlayingSegment(tech) {
349+
const playlist = tech.vhs.playlists.media();
350+
if (!playlist || !playlist.segments || playlist.segments.length === 0) {
351+
return null;
352+
}
353+
354+
const snapshotTime = tech.currentTime();
355+
356+
// Find the first segment whose end is past the playhead.
357+
for (let i = 0; i < playlist.segments.length; i += 1) {
358+
// Note: segment.end may be undefined when not yet buffered.
359+
if (snapshotTime < playlist.segments[i].end) {
360+
return playlist.segments[i];
361+
}
362+
}
363+
364+
return playlist.segments[0];
365+
}
366+
367+
// ---- Rebuffer memory persistence ----
368+
// A page reload should not reset learned caution: events are stored in
369+
// sessionStorage and restored (age-pruned) at construction. All storage
370+
// access is failure-tolerant — missing or broken sessionStorage (Node,
371+
// sandboxed iframes, private modes) silently degrades to in-memory only.
372+
373+
function loadPersistedRebufferEvents() {
374+
try {
375+
if (typeof window === "undefined" || !window.sessionStorage) {
376+
return [];
377+
}
378+
const raw = window.sessionStorage.getItem(REBUFFER_STORAGE_KEY);
379+
if (!raw) {
380+
return [];
381+
}
382+
const events = JSON.parse(raw);
383+
if (!Array.isArray(events)) {
384+
return [];
385+
}
386+
const cutoff = Date.now() - BUFFERING_AMNESTY_DURATION;
387+
return events
388+
.filter((e) => e && typeof e.atMs === "number" && e.atMs > cutoff)
389+
.map((e) => ({
390+
latencyMs: Number.isFinite(e.latencyMs) ? e.latencyMs : null,
391+
atMs: e.atMs,
392+
}));
393+
} catch {
394+
return [];
395+
}
396+
}
397+
398+
function persistRebufferEvents(events) {
399+
try {
400+
if (typeof window === "undefined" || !window.sessionStorage) {
401+
return;
402+
}
403+
window.sessionStorage.setItem(REBUFFER_STORAGE_KEY, JSON.stringify(events));
404+
} catch {
405+
// Storage full or forbidden; in-memory behavior is the fallback.
406+
}
407+
}
408+
348409
class LatencyCompensator {
349410
constructor(player, options = {}) {
350411
this.player = player;
@@ -425,22 +486,21 @@ class LatencyCompensator {
425486
// recent sightings is the least-delayed bound and under-reports latency —
426487
// the conservative direction.
427488
observeClockSkew(playlist) {
428-
for (let i = playlist.segments.length - 1; i >= 0; i--) {
489+
for (let i = playlist.segments.length - 1; i >= 0; i -= 1) {
429490
const segment = playlist.segments[i];
430-
if (!segment.dateTimeObject) {
431-
continue;
432-
}
433-
const key = segment.dateTimeObject.getTime();
434-
if (key !== this.lastSkewSightingKey) {
435-
this.lastSkewSightingKey = key;
436-
this.skewSightings.push(
437-
key + (segment.duration || 0) * 1000 - Date.now()
438-
);
439-
if (this.skewSightings.length > SKEW_SIGHTING_WINDOW) {
440-
this.skewSightings.shift();
491+
if (segment.dateTimeObject) {
492+
const key = segment.dateTimeObject.getTime();
493+
if (key !== this.lastSkewSightingKey) {
494+
this.lastSkewSightingKey = key;
495+
this.skewSightings.push(
496+
key + (segment.duration || 0) * 1000 - Date.now()
497+
);
498+
if (this.skewSightings.length > SKEW_SIGHTING_WINDOW) {
499+
this.skewSightings.shift();
500+
}
441501
}
502+
return;
442503
}
443-
return;
444504
}
445505
}
446506

@@ -1077,7 +1137,7 @@ class LatencyCompensator {
10771137
representations.forEach((rep) => {
10781138
rep.enabled(pinned ? rep === lowest : true);
10791139
});
1080-
} catch (err) {
1140+
} catch {
10811141
// Renditions API unavailable; quality pinning is best-effort.
10821142
}
10831143
}
@@ -1123,65 +1183,4 @@ class LatencyCompensator {
11231183
}
11241184
}
11251185

1126-
function getCurrentlyPlayingSegment(tech) {
1127-
const playlist = tech.vhs.playlists.media();
1128-
if (!playlist || !playlist.segments || playlist.segments.length === 0) {
1129-
return null;
1130-
}
1131-
1132-
const snapshotTime = tech.currentTime();
1133-
1134-
// Find the first segment whose end is past the playhead.
1135-
for (const segment of playlist.segments) {
1136-
// Note: segment.end may be undefined when not yet buffered.
1137-
if (snapshotTime < segment.end) {
1138-
return segment;
1139-
}
1140-
}
1141-
1142-
return playlist.segments[0];
1143-
}
1144-
1145-
// ---- Rebuffer memory persistence ----
1146-
// A page reload should not reset learned caution: events are stored in
1147-
// sessionStorage and restored (age-pruned) at construction. All storage
1148-
// access is failure-tolerant — missing or broken sessionStorage (Node,
1149-
// sandboxed iframes, private modes) silently degrades to in-memory only.
1150-
1151-
function loadPersistedRebufferEvents() {
1152-
try {
1153-
if (typeof window === "undefined" || !window.sessionStorage) {
1154-
return [];
1155-
}
1156-
const raw = window.sessionStorage.getItem(REBUFFER_STORAGE_KEY);
1157-
if (!raw) {
1158-
return [];
1159-
}
1160-
const events = JSON.parse(raw);
1161-
if (!Array.isArray(events)) {
1162-
return [];
1163-
}
1164-
const cutoff = Date.now() - BUFFERING_AMNESTY_DURATION;
1165-
return events
1166-
.filter((e) => e && typeof e.atMs === "number" && e.atMs > cutoff)
1167-
.map((e) => ({
1168-
latencyMs: Number.isFinite(e.latencyMs) ? e.latencyMs : null,
1169-
atMs: e.atMs,
1170-
}));
1171-
} catch (err) {
1172-
return [];
1173-
}
1174-
}
1175-
1176-
function persistRebufferEvents(events) {
1177-
try {
1178-
if (typeof window === "undefined" || !window.sessionStorage) {
1179-
return;
1180-
}
1181-
window.sessionStorage.setItem(REBUFFER_STORAGE_KEY, JSON.stringify(events));
1182-
} catch (err) {
1183-
// Storage full or forbidden; in-memory behavior is the fallback.
1184-
}
1185-
}
1186-
11871186
export default LatencyCompensator;

0 commit comments

Comments
 (0)