fix(stream-test): restore audio after ads, enforce subtitle rule broadcast-wide, commit the 60fps MV path

Addresses review of the ad/subtitle work (the ad-skip.mjs -> broadcast-helper.mjs
rename's other half; the prior commit only recorded the deletion):

- ad mute leak: the ad-skipper muted during an ad but never un-muted, so the
  main video stayed silent after the first ad. Save the pre-ad muted/playbackRate
  and restore them when the ad ends (verified: muted false -> true -> false).
- captions were only applied once when scenario.mjs ran, not for the whole
  broadcast. The persistent helper now applies the rule (OFF by default, Korean
  ON if offered) per video and ENFORCES it every tick - one-shot did not hold
  because YouTube silently re-enabled captions (verified it stays off across 8s).
- ad-skip + captions merged into broadcast-helper.mjs (one CDP process).
- the 60fps MV test now lives in the repo: scenario.mjs gains MV_QUERY (search +
  auto-pick the first >=60fps result) and WATCH_SECONDS, plus the
  fullscreen-toolbar-hide fix. The broadcast runs via the committed
  stream-hold.ts (audio + keepalive), not an out-of-repo copy.
- document the test env vars (CDP_PORT, HOLD_MS, TEST_*, MV_QUERY, WATCH_SECONDS).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
javis-bot
2026-06-10 16:09:31 +09:00
parent 0241628fed
commit f93b241575
4 changed files with 187 additions and 48 deletions

View File

@@ -18,27 +18,32 @@ real browsing session captured from the X display.
(no DOM scrollIntoView); if an element has no on-screen box the click fails
rather than falling back to a synthetic click. The CDP/DOM API is used only to
read state for verification, never to act.
- `scenario.mjs` - the browse scenario (YouTube -> IU live -> 1080p ->
fullscreen -> Naver -> 나무위키), driven with the human helpers. Connects to a
Chrome already running with `--remote-debugging-port` (`CDP_PORT`, default
9222) on the streamed display. Captions default OFF, auto-enabling a Korean
track when one exists.
- `ad-skip.mjs` - persistent YouTube ad auto-skipper. Connects over CDP and
injects a watcher into every tab (current and future) that clicks "Skip ad"
the instant it appears, closes overlay ads, and fast-forwards unskippable ads
(seek-to-end + 16x + mute). Run it alongside the broadcast. Reconnects across
Chrome restarts.
- `scenario.mjs` - the browse scenario (YouTube -> 1080p -> fullscreen -> Naver
-> 나무위키), driven with the human helpers. Connects to a Chrome already
running with `--remote-debugging-port` (`CDP_PORT`, default 9222) on the
streamed display. Defaults to a fixed concert clip; set `MV_QUERY` to instead
search and auto-pick the first result that really reports >=60fps. `WATCH_SECONDS`
(default 20) sets the windowed/fullscreen watch durations.
- `broadcast-helper.mjs` - persistent CDP helper that injects one watcher into
every tab (current and future) and (1) auto-skips YouTube ads - clicks "Skip
ad" instantly, closes overlay ads, fast-forwards unskippable ads (seek-to-end
+ 16x + mute) and RESTORES the pre-ad muted/playbackRate when the ad ends; and
(2) applies the subtitle rule per video: captions OFF by default, Korean ON
when the video offers a Korean track. Run it alongside the broadcast; it
reconnects across Chrome restarts.
## Run
```
# keep the broadcast up (separate process / service)
bun bot/scripts/stream-test/stream-hold.ts
# Chrome on the streamed display with remote debugging, then:
node bot/scripts/stream-test/scenario.mjs
# keep ads auto-skipped + subtitles correct for the whole broadcast:
node bot/scripts/stream-test/broadcast-helper.mjs
# keep YouTube ads auto-skipped for the whole broadcast (separate process):
node bot/scripts/stream-test/ad-skip.mjs
# Chrome on the streamed display with remote debugging, then run a browse pass:
node bot/scripts/stream-test/scenario.mjs
# ...or the 60fps MV variant:
MV_QUERY="4K 60fps MV" WATCH_SECONDS=30 node bot/scripts/stream-test/scenario.mjs
```
Recommended Chrome flags on the streamed display (avoids the "restore pages?"