fix(recording): use CDP timestamps to preserve real-time video playback speed by octo-patch · Pull Request #4697 · browser-use/browser-use · GitHub
Skip to content

fix(recording): use CDP timestamps to preserve real-time video playback speed#4697

Open
octo-patch wants to merge 3 commits intobrowser-use:mainfrom
octo-patch:fix/issue-4696-video-real-time-playback
Open

fix(recording): use CDP timestamps to preserve real-time video playback speed#4697
octo-patch wants to merge 3 commits intobrowser-use:mainfrom
octo-patch:fix/issue-4696-video-real-time-playback

Conversation

@octo-patch
Copy link
Copy Markdown

@octo-patch octo-patch commented Apr 17, 2026

Fixes #4696

Problem

When using record_video_dir, the recorded video plays back much faster than real time. CDP screencast delivers frames only on visual change — during network waits or idle periods between agent steps, zero frames are produced. All captured frames are then written to the video at the configured framerate (30 fps default), so a 5-second page load appears to be instant in the video.

Solution

ScreencastFrameMetadata includes a timestamp field (Unix seconds). This PR threads that timestamp from the CDP event through to VideoRecorderService.add_frame(). When a new frame arrives, the recorder computes the wall-clock gap since the last frame and inserts duplicate filler frames to fill the silence — matching the video duration to actual session time.

Key details:

  • Filler frame count: int(gap_seconds * framerate) - 1 (the current frame accounts for the last slot)
  • Idle gaps longer than MAX_FILL_SECONDS (10 s) are capped to keep file sizes reasonable
  • Tab switches reset the timestamp so no spurious filler spans different targets
  • Fully backward-compatible: if no timestamp is available, add_frame() behaves as before

Testing

The change can be verified by recording a session that includes a few-second network wait and comparing the video duration to the actual elapsed time. Before this fix the video would be significantly shorter than wall-clock time; after the fix the durations match.


Summary by cubic

Preserves real-time playback speed in recorded videos by using CDP timestamps to fill idle gaps. Also validates file uploads against accept rules and retries flaky screenshot timeouts.

  • Bug Fixes
    • Recording: Use ScreencastFrameMetadata.timestamp to detect pauses and insert duplicate frames so video duration matches real time; cap idle fills at 10s and reset on tab switches; falls back to old behavior if no timestamp.
    • Screenshots: Retry Page.captureScreenshot up to 3 times with a 0.5s delay on transient "timed out" errors.
    • Uploads: Enforce <input accept> before upload (supports extensions like .pdf, wildcard types like image/*, and exact MIME types); raise BrowserError on rejection; add tests for reject/accept paths.

Written for commit f73d9a2. Summary will update on new commits.

octo-patch added 3 commits April 11, 2026 11:02
Page.captureScreenshot can time out intermittently under load (e.g. in
Docker containers with limited resources). Add up to 3 retries with a
0.5 s delay when a RuntimeError containing "timed out" is raised, so
occasional flaky failures recover automatically instead of crashing the
agent run.
…rowser-use#4662)

When a file input has an accept attribute, validate the uploaded file's
extension and MIME type against it before calling setFileInputFiles via CDP.
CDP bypasses browser-native accept validation, so without this check the agent
silently succeeds even when the file type is rejected by the UI.

Supports extension tokens (.pdf), wildcard MIME types (image/*), and exact
MIME types (application/pdf). Adds two regression tests covering rejection and
acceptance paths.
…ck speed (fixes browser-use#4696)

CDP screencast delivers frames only on visual change, not at fixed intervals.
Without timestamps, all frames are played back at the configured framerate (30fps
default), making automated sessions appear sped up.

Fix: use the timestamp field from ScreencastFrameMetadata to detect pauses and
insert duplicate frames to fill the gap, keeping playback in sync with wall-clock
time. Long idles are capped at MAX_FILL_SECONDS (10s) to avoid bloated files.

Tab-switches reset the timestamp so no spurious filler frames span different targets.
@CLAassistant
Copy link
Copy Markdown

Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 5 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="browser_use/browser/watchdogs/default_action_watchdog.py">

<violation number="1" location="browser_use/browser/watchdogs/default_action_watchdog.py:2668">
P2: Hard-failing `accept` validation on `mimetypes.guess_type()` can reject valid uploads when MIME inference is missing or OS-dependent.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review, or fix all with cubic.

accept_attr = (element_node.attributes or {}).get('accept', '').strip()
if accept_attr:
file_ext = os.path.splitext(event.file_path)[1].lower()
file_mime = mimetypes.guess_type(event.file_path)[0] or ''
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot Apr 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Hard-failing accept validation on mimetypes.guess_type() can reject valid uploads when MIME inference is missing or OS-dependent.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At browser_use/browser/watchdogs/default_action_watchdog.py, line 2668:

<comment>Hard-failing `accept` validation on `mimetypes.guess_type()` can reject valid uploads when MIME inference is missing or OS-dependent.</comment>

<file context>
@@ -2660,6 +2661,31 @@ async def on_UploadFileEvent(self, event: UploadFileEvent) -> None:
+				accept_attr = (element_node.attributes or {}).get('accept', '').strip()
+				if accept_attr:
+					file_ext = os.path.splitext(event.file_path)[1].lower()
+					file_mime = mimetypes.guess_type(event.file_path)[0] or ''
+					accepted_types = [t.strip().lower() for t in accept_attr.split(',') if t.strip()]
+					accepted = False
</file context>
Fix with Cubic

@gitguardian
Copy link
Copy Markdown

gitguardian Bot commented Apr 21, 2026

⚠️ GitGuardian has uncovered 1 secret following the scan of your pull request.

Please consider investigating the findings and remediating the incidents. Failure to do so may lead to compromising the associated services or software components.

Since your pull request originates from a forked repository, GitGuardian is not able to associate the secrets uncovered with secret incidents on your GitGuardian dashboard.
Skipping this check run and merging your pull request will create secret incidents on your GitGuardian dashboard.

🔎 Detected hardcoded secret in your pull request
GitGuardian id GitGuardian status Secret Commit Filename
- - Generic High Entropy Secret 3f9520c examples/glazyr_benchmark.py View secret
🛠 Guidelines to remediate hardcoded secrets
  1. Understand the implications of revoking this secret by investigating where it is used in your code.
  2. Replace and store your secret safely. Learn here the best practices.
  3. Revoke and rotate this secret.
  4. If possible, rewrite git history. Rewriting git history is not a trivial act. You might completely break other contributing developers' workflow and you risk accidentally deleting legitimate data.

To avoid such incidents in the future consider


🦉 GitGuardian detects secrets in your source code to help developers and security teams secure the modern development process. You are seeing this because you or someone else with access to this repository has authorized GitGuardian to scan your pull request.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bug: Video is too fast (Make it normal

2 participants