fix: navigate 后立即推一帧,静态页开流不再等重绘

screencast 帧只在重绘时来,页面可能在 startScreencast 之前
就已画好——静态页于是开流后一直无画面,直到下一次重绘。
navigate 后用 CDP captureScreenshot 抓一张当前视口塞进帧
队列,泵在下一轮就把桥帧文件写出来;泵跳过空 session 的
ack(eager 帧没有可确认的 screencast 帧)。失败静默,
screencast 本身仍照常流动。
This commit is contained in:
host committed 2026-10-30 13:14:38 +08:00
1 parent b844624c96
commit 2d840a6c37
2 files changed
+62 -2

No files matched your search

+29 -2
View File
@@ -120,6 +120,7 @@ class Browser:
wait_until="domcontentloaded")
self._current_url = self._page.url
self._start_screencast()
self._eager_frame()
except Exception as exc: # noqa: BLE001
raise BrowserError("navigate failed: %s" % exc)
result = self._info()
@@ -321,9 +322,35 @@ class Browser:
self._cdp = None
self._cdp_page = None
def _eager_frame(self):
"""Push one current-viewport frame into the sink, best-effort.
Screencast frames only arrive on repaint, and the page may
already have painted before startScreencast ran -- so a
static page would otherwise show nothing until its next
repaint. Capturing the viewport once right after navigate
guarantees the bridge file (and any open stream) has a
picture within milliseconds of the page loading.
"""
if self._cdp is None or self._frame_sink is None:
return
try:
result = self._cdp.send(
"Page.captureScreenshot",
{"format": "jpeg", "quality": 60})
data = result.get("data") if isinstance(result, dict) \
else None
if data:
# Empty session id: pump stores it but must not ack
# it (there is no screencast frame to acknowledge).
self._frame_sink.put(("", data))
except Exception: # noqa: BLE001 - screencast still flows
pass
def pump_screencast(self):
"""Main-thread only: store the latest frame and ack every
queued frame (no ack = CDP stops sending after the first).
real screencast frame (no ack = CDP stops sending after the
first). Eager frames carry no session id and skip ack.
Returns the latest frame data (base64 jpeg) or ''."""
if self._frame_sink is None:
return ""
@@ -335,7 +362,7 @@ class Browser:
break
if data:
latest = data
if self._cdp is not None:
if self._cdp is not None and sid:
try:
self._cdp.send("Page.screencastFrameAck",
{"sessionId": sid})