Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

shot-scraper video command #142

Open
simonw opened this issue Feb 6, 2024 · 3 comments
Open

shot-scraper video command #142

simonw opened this issue Feb 6, 2024 · 3 comments
Labels

Comments

@simonw
Copy link
Owner

simonw commented Feb 6, 2024

I'd really love the ability to use shot-scraper to record an automated video of interactions with a web app.

This is an ambitious challenge!

@simonw simonw added the research label Feb 6, 2024
@simonw
Copy link
Owner Author

simonw commented Feb 6, 2024

Got a VERY rough prototype working like this:

@cli.command()
@click.argument("url")
@click.argument("script")
@click.option(
    "-o",
    "--output",
    type=click.File("w"),
    help="Save output video to this file",
)
def video(
    url,
    script,
    output,
):
    """
    Record a video of the specified page

    The script should be a Python script using the following functions:

    \b
    sleep(0.5) - delay for half a second
    page.click('selector') - click the element identified by the selector
    page.scrollTo('selector', 300) - scroll that selector in view, take 300ms
    page.type('selector', 'Hello') - type 'Hello' into the specified input
    press('Enter') - press the Enter key
    """
    if not output:
        output = "/tmp/shot-scraper-video"
    url = url_or_file_path(url, _check_and_absolutize)
    with sync_playwright() as p:
        browser = p.chromium.launch()
        context = browser.new_context(
            record_video_dir=output,
            record_video_size={"width": 1280, "height": 720},
        )
        page = context.new_page()
        page.goto(url)
        exec(script, {"page": page, "sleep": time.sleep})
        context.close() # this saves the video
        browser.close()

Example usage:

shot-scraper video https://simonwillison.net/ '
sleep(1)
page.click("a:nth-of-type(3)")
sleep(3)
'

This produced the following video as /tmp/shot-scraper-video/95becf0c7ad1d278446018af7f44c49b.webm (541KB):

95becf0c7ad1d278446018af7f44c49b.webm

@simonw
Copy link
Owner Author

simonw commented Feb 6, 2024

I'd like the mouse cursor to be visible. This looks helpful for that: https://www.npmjs.com/package/mouse-helper

Also maybe this comment:

I think I'd need some extra utility functions for things like "smoothly scroll the page to this element" and "apply a yellow flash animated highlight to this element" and "smoothly move the mouse cursor to here".

It would also be nice if the video wasn't .webm - I think that's the only thing Playwright can output, but I could do a thing that attempts to use ffmpeg (if available) to convert to another specified format.

Needs a lot of thought about the best scripting language subset to expose, what other options, what browser viewport size etc.

@simonw
Copy link
Owner Author

simonw commented Feb 6, 2024

Asked for tips on Pallets Discord here: https://discord.com/channels/531221516914917387/531571912619458591/1204292849256890388 - when I thought I wanted a design that looked more like this, but needed a way to preserve the relative order of Click options:

my-tool --delay 300 \
  --click 'a[href="/"]' \
  --delay 1000 \
  --fill 'input[name="q"]' 'my search term' \
  --delay 200 \
  --click 'button[id="search"]'

I think I like the Python DSL better though.

simonw added a commit that referenced this issue Mar 25, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant