Clear the show-poster flag after per-viewport video source reload
v.load() resets the media element's show-poster flag; pause cancels autoplay and the at-zero seek skip left nothing to clear it, so screenshots after a source re-selection rendered the poster instead of the new source's frame 0. Reloaded videos now force an epsilon seek (awaiting seeked, which also serves as the readiness signal on slow CDNs), and re-selection emits a video_source_reselected log event. 386 tests pass (4 new), typecheck clean. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
762855664c
commit
144e7ab16b
@@ -1,6 +1,6 @@
|
||||
import { describe, it } from "node:test";
|
||||
import assert from "node:assert/strict";
|
||||
import { selectVideoSourceIndex, type VideoSourceCandidate } from "../src/capture/capture.js";
|
||||
import { selectVideoSourceIndex, planVideoSeek, type VideoSourceCandidate } from "../src/capture/capture.js";
|
||||
|
||||
// Predicate builders for the injected matchMedia / canPlayType.
|
||||
const matchesAny = (matching: Set<string>) => (m: string) => matching.has(m);
|
||||
@@ -64,3 +64,30 @@ describe("selectVideoSourceIndex (video <source> resource-selection)", () => {
|
||||
assert.equal(selectVideoSourceIndex(sources, matchesAny(new Set(["(min-width: 100px)"])), canPlayAll), 0);
|
||||
});
|
||||
});
|
||||
|
||||
describe("planVideoSeek (post-reselection seek decision)", () => {
|
||||
it("forces an epsilon seek on a reloaded video even at t=0 (clears the show-poster flag)", () => {
|
||||
// The core regression: a just-reloaded video is at t=0 with the poster flag set. Seeking to 0
|
||||
// fires no `seeked` and leaves the poster showing; only a genuine seek to a nonzero epsilon
|
||||
// clears the flag and paints the new source's frame 0.
|
||||
const plan = planVideoSeek(true, 0);
|
||||
assert.ok(plan, "reloaded video must seek");
|
||||
assert.ok(plan!.target > 0, "reloaded seek target must be nonzero so `seeked` actually fires");
|
||||
assert.ok(plan!.target < 1e-3, "epsilon must be well inside frame 0");
|
||||
});
|
||||
|
||||
it("still forces the epsilon seek on a reloaded video that reports a small nonzero time", () => {
|
||||
const plan = planVideoSeek(true, 5e-4);
|
||||
assert.deepEqual(plan, { target: 1e-4 });
|
||||
});
|
||||
|
||||
it("fast-skips a non-reloaded video already at frame 0", () => {
|
||||
assert.equal(planVideoSeek(false, 0), null);
|
||||
assert.equal(planVideoSeek(false, 5e-4), null); // within the 1e-3 skip band
|
||||
});
|
||||
|
||||
it("seeks a non-reloaded playing video back to 0", () => {
|
||||
assert.deepEqual(planVideoSeek(false, 3.2), { target: 0 });
|
||||
assert.deepEqual(planVideoSeek(false, 1e-3), { target: 0 }); // exactly at the band edge → seek
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user