aboutsummaryrefslogtreecommitdiffstats
path: root/tools/pager-eager-test.js
diff options
context:
space:
mode:
authorAdam Soltys <[email protected]>2026-10-19 22:13:55 -0700
committerAdam Soltys <[email protected]>2026-10-19 22:13:55 -0700
commit1366ef7e517cbede61ac81b133bda8ab9ff74f23 (patch)
treedb7278e2198ccee5a0782abef4db3dbad8d17098 /tools/pager-eager-test.js
parenta0829612b8751e85f28d066fbaa0c2308a85fbda (diff)
downloadcoinosv3-1366ef7e517cbede61ac81b133bda8ab9ff74f23.tar.gz
coinosv3-1366ef7e517cbede61ac81b133bda8ab9ff74f23.zip
Videos start the moment a swipe lands, and streams say who's watching.
- The pager's next clip gets a warm player: once its opening is in the cache it reads to its first frame (preload metadata: Chrome stops ~2-4 MB in at real link speeds) and waits paused, so landing on it is only play and sound. coinosPagerStarts() in the console times every landing (swipe to moving picture, warm or cold, host, size). - A stream's "N watching" names who on hover, and a tap shows their faces: NIP-53 presence (kind 10312, as Shosho and zap.stream say it), fresh for half an hour. coinos says it too while a stream is open (every 5 min, with a key held here only, never for your own stream) and takes it back on leaving. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_013ZDf1cyCQLkfjftYhymZAg
Diffstat (limited to 'tools/pager-eager-test.js')
-rw-r--r--tools/pager-eager-test.js14
1 files changed, 9 insertions, 5 deletions
diff --git a/tools/pager-eager-test.js b/tools/pager-eager-test.js
index 15a5076..01c8dd6 100644
--- a/tools/pager-eager-test.js
+++ b/tools/pager-eager-test.js
@@ -88,7 +88,7 @@ async function run(saveData, slow = false) {
const feedRow = (w) => page.evaluate((x) => { const r = [...document.querySelectorAll('.notes-feed [data-key]')].find((n) => n.textContent.includes(x)); r.querySelector('.note-video-box').scrollIntoView({ block: 'center' }); const v = r.querySelector('video.note-video').getBoundingClientRect(); return { cover: !!r.querySelector('.vid-heavy'), x: v.x + v.width * 0.2, y: v.y + v.height * 0.3 }; }, w);
try {
await page.setViewport({ width: 390, height: 844 });
- pace = slow ? 375000 : 0;
+ pace = slow ? 375000 : 12_500_000; // 3 Mbps, or 100 (a loopback's speed is no link: Chrome reads a warm player's whole file before it can stop)
await page.goto(server.url.href, { waitUntil: 'domcontentloaded' });
await page.evaluate(() => localStorage.setItem('btc-wallet-network', 'regtest'));
await page.reload({ waitUntil: 'domcontentloaded' }); await sleep(400);
@@ -123,14 +123,17 @@ async function run(saveData, slow = false) {
const c1 = await slide('c1'), c2 = await slide('c2'), c3 = await slide('c3');
let head1 = 0;
if (!saveData) {
- check('the next clips wait on their pictures, no cover, no player yet', c1 && !c1.src && !c1.cover && c2 && !c2.src, JSON.stringify([c1, c2]));
+ check('the next clip has a warm player: its file, read to its first frame and paused', c1 && c1.src && c1.preload === 'metadata' && !c1.playing && !c1.cover && await page.evaluate(() => { const s = [...document.querySelectorAll('.mp-slide')].find((x) => x.getAttribute('data-k').endsWith('/c1.webm')); return s.querySelector('video.mp-media').readyState >= 2; }), JSON.stringify(c1));
+ check('…the one after waits on its picture, no player yet', c2 && !c2.src && !c2.cover, JSON.stringify(c2));
const hs = heads('c1'), h2 = heads('c2');
head1 = hs.length ? hs[0].end + 1 : 0;
const head2 = h2.length ? h2[0].end + 1 : 0;
// before any measure of the link: two seconds' worth (the second clip ahead, half)
check('the next clip\'s opening is fetched ahead: two seconds of it', hs.length === 1 && hs[0].start === 0 && near(head1, 2 * RATE), `${kb(head1)} (two seconds: ${kb(2 * RATE)})`);
check('…and half that of the one after', h2.length === 1 && near(head2, RATE), `${kb(head2)}`);
- check('nothing more than that ahead of time', sent('c1') <= head1 && sent('c2') <= head2 && sent('c3') === 0, `c1 ${kb(sent('c1'))}, c2 ${kb(sent('c2'))}, c3 ${kb(sent('c3'))} of ${kb(SIZE)} each`);
+ // the warm player reads on from the cached opening to its first frame and a little past, then stops
+ check('ahead of time: the next clip\'s opening and a few MB more for its warm player, the one after its opening only', sent('c1') <= head1 + 4 * 1024 * 1024 && sent('c2') <= head2 && sent('c3') === 0, `c1 ${kb(sent('c1'))}, c2 ${kb(sent('c2'))}, c3 ${kb(sent('c3'))} of ${kb(SIZE)} each`);
+ check('…the warm player took the opening from the cache, not the host', !log.some((e) => e.clip === 'c1' && e.dest === 'video' && e.start === 0), log.filter((e) => e.clip === 'c1').map((e) => e.dest + ':' + e.start).join(' '));
} else {
check('nothing loads ahead of a clip over budget', c1 && !c1.src && sent('c1') === 0, JSON.stringify(c1) + ' ' + kb(sent('c1')));
}
@@ -139,8 +142,9 @@ async function run(saveData, slow = false) {
const t0 = Date.now();
if (!saveData) {
check('swiped to, the next clip plays at once, no cover', await waitFor(() => { const s = [...document.querySelectorAll('.mp-slide')].find((x) => x.getAttribute('data-k').endsWith('/c1.webm')); const v = s.querySelector('video.mp-media'); return !s.querySelector('.vid-heavy') && !v.paused && v.currentTime > 0; }, null, 5000) && (Date.now() - t0) < (slow ? 3000 : 1500), (Date.now() - t0) + ' ms');
- const after = log.slice(before).filter((e) => e.clip === 'c1' && e.dest === 'video');
- check('…its player starting where the head start left off (the opening came from the cache)', after.length >= 1 && after[0].start === head1, 'the player asked for ' + (after.map((e) => e.start + '-').join(', ') || 'nothing') + ', head start ' + head1);
+ await waitFor(() => coinosPagerStarts().starts.some((x) => /c1\.webm$/.test(x.url)), null, 3000);
+ const st = await page.evaluate(() => coinosPagerStarts().starts.find((x) => /c1\.webm$/.test(x.url)));
+ check('…from its warm player, the clock says', st && st.warm && st.ms < 1000, JSON.stringify(st));
await sleep(1500);
const h3 = heads('c3'), head3 = h3.length ? h3[0].end + 1 : 0;
check('…the next one gets its head start', h3.length === 1);