From c6a0ca457258dbb558062f3f479d02f3b053c325 Mon Sep 17 00:00:00 2001 From: javis-bot Date: Wed, 10 Jun 2026 15:39:08 +0900 Subject: [PATCH] fix(stream-test): hide Chrome toolbar in fullscreen so the address bar stays off the broadcast On the streamed VNC desktop (xfwm4), Chrome did not hide its toolbar when a video entered HTML5 fullscreen via 'f' - the window was full-screen (outerHeight 1080) but the tab/address bar stayed, leaving only 988px of content, so the address bar bled into the Go-Live broadcast. Toggle Chrome-initiated browser fullscreen via CDP (Browser.setWindowBounds windowState fullscreen) around the 'f' step. That reliably hides the toolbar (innerHeight 1080 vs 988); the toolbar is restored on exit, so normal browsing still shows it. Verified live: clean full-screen video, no toolbar. Co-Authored-By: Claude Opus 4.7 --- bot/scripts/stream-test/scenario.mjs | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/bot/scripts/stream-test/scenario.mjs b/bot/scripts/stream-test/scenario.mjs index b1d4c9a..8d18733 100644 --- a/bot/scripts/stream-test/scenario.mjs +++ b/bot/scripts/stream-test/scenario.mjs @@ -8,6 +8,13 @@ // and entering 나무위키. The CDP/DOM API is used ONLY to read state for // verification (paused/quality/fullscreen) and as a rare click fallback when an // element has no on-screen box. +// +// One environment workaround: on the streamed VNC desktop (xfwm4) Chrome does +// NOT hide its toolbar when a video enters HTML5 fullscreen ('f'), so the +// address bar bleeds into the broadcast. We therefore toggle the BROWSER window +// into Chrome-initiated fullscreen via CDP (Browser.setWindowBounds) around the +// 'f' step - that reliably hides the toolbar (innerHeight 1080 vs 988) - then +// restore it. This is a window-chrome action, not a page interaction. import { chromium } from 'playwright'; import { humanClick, humanType, humanKey, humanHover, navigateOmnibox, humanScroll, sleep } from './human.mjs'; @@ -23,6 +30,19 @@ page.setDefaultTimeout(25000); const read = (fn) => page.evaluate(fn); const playerLoc = () => page.locator('#movie_player'); +// Toggle Chrome-initiated browser fullscreen (hides the toolbar on this WM, +// which HTML5 'f' fullscreen alone does not). on=true -> fullscreen. +async function browserFullscreen(on) { + try { + const sess = await b.newBrowserCDPSession(); + const { targetInfos } = await sess.send('Target.getTargets'); + const t = targetInfos.find((x) => x.type === 'page' && x.url.startsWith('http')); + if (!t) return; + const { windowId } = await sess.send('Browser.getWindowForTarget', { targetId: t.targetId }); + await sess.send('Browser.setWindowBounds', { windowId, bounds: { windowState: on ? 'fullscreen' : 'normal' } }); + } catch { /* best-effort */ } +} + // 1) open YouTube by typing the URL in the address bar await navigateOmnibox('https://www.youtube.com'); await sleep(3000); @@ -73,14 +93,17 @@ if ((await auto.count().catch(() => 0)) && (await auto.getAttribute('aria-checke } console.log('STEP watch-1080-windowed'); await sleep(20000); -// 7) fullscreen with the real 'f' key (hover the player to focus it), 20s +// 7) fullscreen: hide the browser toolbar (CDP), then the real 'f' key makes the +// video fill the now toolbar-free screen (innerHeight 1080). 20s. +await browserFullscreen(true); await sleep(800); await humanHover(page, playerLoc()); await humanKey('f'); await sleep(1500); if (!(await read(() => !!document.fullscreenElement))) { await humanHover(page, playerLoc()); await humanKey('f'); await sleep(1200); } console.log('STEP fullscreen', await read(() => ({ full: !!document.fullscreenElement, h: window.innerHeight }))); await sleep(20000); -// 8) exit fullscreen with real 'f' +// 8) exit video fullscreen ('f'), then restore the browser toolbar await humanKey('f'); await sleep(1500); +await browserFullscreen(false); await sleep(500); // 9) Naver via the address bar, then really type the query await navigateOmnibox('https://www.naver.com'); await sleep(2800);