Skip to content

browser_probe video visibility discovery is O(videos × duration) and hurts GCP Cloud Run plan time #3360

Description

@valeriangalliat

Describe the bug

When compile injects data-hf-auto-start (videos with no authored data-start), discoverVideoVisibilityFromTimeline walks the GSAP timeline once per video. Coarse seeks ≈ V × D / 0.1.

This mainly shows up on GCP Cloud Run (CPU / SwiftShader). Local Metal finishes the same loop quickly. On Cloud Run, plan stage wall time grows with video count. Heavy real compositions can push the probe past the ~5 min Puppeteer protocolTimeout.

Optional patch (same windows, one seek per step): #3233

Link to reproduction

https://github.com/ArcadeHQ/hyperframes-repros/tree/patch/visibility-scrub

Steps to reproduce

Local (path check only):

  1. Clone the branch. Pin unpatched hyperframes@0.8.3 / 0.8.4.
  2. npm run render -- --debug -f 1 --quality draft --output renders/unpatched.mp4
  3. Confirm:
    Launching browser for composition probe... { reasons: [ 'auto-start video(s)' ] }
    Discovering video visibility windows... { videoCount: 5 }
    

Do not add data-start. lint media_missing_data_start is expected.

Cloud Run (where the cost matters):

  1. Deploy unpatched HyperFrames with hyperframes cloudrun deploy (or an equivalent unpatched image).
  2. From the repro branch:
    npx -p hyperframes@0.8.4 -p @hyperframes/gcp-cloud-run@0.8.4 \
      hyperframes cloudrun render . --width 1920 --height 1080 --fps 24 --quality draft --wait
  3. Read Plan.DurationMs from the workflow execution result (see branch README).
  4. Repeat against a build that includes the single-pass scrub (or a 1-video control on the same unpatched image).

Expected behavior

Probe cost scales with duration, not V × D. On Cloud Run, plan time for N auto-start videos should stay near a 1-video control when seek work is the same.

Actual behavior

Unpatched coarse seeks for this fixture: 5 × 364 / 0.1 = 18,200 vs ~3,640 single-pass.

GCP Cloud Run results (same fixture: 31 scenes, 364s, 5 auto-start videos, nested GSAP with transform/blur weight, dummy color clips):

Image Plan.DurationMs Job wall
Unpatched main (~0.8.4) 10590 ~163s
Build with single-pass scrub 5068 ~70s

About plan time on unpatched. This run did not hit protocolTimeout. Dummy 1s color clips still make each seek cheap; production hangs we hit used real 1080p footage and heavier per-seek GSAP, and failed the probe on Cloud Run.

Earlier empty-timeline fixtures (60s×6, 600s×6 with plain tl.set) showed almost no Plan gap — seek count alone is not enough on 8 vCPU. The tween weight in this branch is what made the A/B readable.

Environment

hyperframes doctor

  ✓ Version          0.8.4 (latest)
  ✓ Node.js          v24.19.0 (darwin arm64)
  ✓ CPU              0 cores · Unknown
  ✓ Memory           16.0 GB total · 2.6 GB available
  ✓ Disk             341.0 GB free
  ✓ Frames cache     /var/folders/bl/c4hk6r7n34g1d81txd99gsgr0000gn/T/hyperframes-extract-cache-501 · 341.0 GB free at /var/folders/bl/c4hk6r7n34g1d81txd99gsgr0000gn/T/hyperframes-extract-cache-501 · default
  ✓ Archive extractor unzip
  ✓ Environment      non-TTY
  ✗ whisper-cpp      Not found (optional — needed for transcription)
                     brew install whisper-cpp
  ✗ TTS (Kokoro)     Not installed (optional — local voice fallback)
                     pip install kokoro-onnx soundfile
  ✗ BGM (MusicGen)   Not installed (optional — local music fallback)
                     pip install transformers torch soundfile numpy
  ✓ FFmpeg           ffmpeg 8.1.2 at /opt/homebrew/bin/ffmpeg
  ✓ FFprobe          ffprobe 8.1.2 at /opt/homebrew/bin/ffprobe
  ✓ Chrome           cache: /Users/val/.cache/puppeteer/chrome-headless-shell/mac_arm-152.0.7977.42/chrome-headless-shell-mac-arm64/chrome-headless-shell
  ✗ Docker           Not found
                     https://docs.docker.com/get-docker/
  ✗ Docker running   Not running
                     Start Docker Desktop or run: sudo systemctl start docker

  ◇  Some checks failed — see hints above

Cloud Run A/B above used GCP Cloud Run + SwiftShader (hyperframes cloudrun), unpatched ~0.8.4 vs a build that includes the single-pass scrub.

Additional context

  • Trigger: in-scene <video> with no data-startdata-hf-auto-start → visibility scan in browser_probe / plan.
  • Do not treat a fast Mac render as a counterexample. The failure mode is Cloud Run plan/probe cost.
  • A unit test that counts seekTl calls (V × samples vs samples) would pin the bug without relying on wall clock.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions