tungs / timesnap

Node.js program that takes screenshots at smooth intervals of web pages with JavaScript animations
BSD 3-Clause "New" or "Revised" License
234 stars 57 forks source link

Support for CSS Transitions and Animations #76

Open zuisho-1848-o opened 1 year ago

zuisho-1848-o commented 1 year ago

Describe the bug The animation speed in a video is too faster than web animation speed. I would like to turn CSS/JS animations on the web into mp4 videos while keeping the speed intact. However, the animation moves much faster than the speed at which it is displayed on the web.

To Reproduce Code is here.

const generateVideo = async (videoPath, url, selector, duration = 15, width = 1920, height = 1080, fps = 30,
    frameDir = 'frames', framePattern = "image%04d.png") => {

    console.log(`*will create ${videoPath} by ${selector} of ${url}`);

    console.log("*will screenshot with timesnap");
    await timesnap({
        url,
        viewport: {
            width, height
        },
        selector,

        width, height,

        fps,
        duration,
        outputDirectory: frameDir,
        outputPattern: framePattern
    });

    console.log("*finish screenshot");

    console.log("*img to video with ffmpeg");

    const command = `ffmpeg -y -r ${fps} -i ${frameDir}/${framePattern} -c:v libx264 -vf "fps=30,format=yuv420p" ${videoPath}`;

    try {
        await executeFFmpegCommand(command);
        console.log("*finish img to video");
    } catch(err) {
        console.error(`***Failed to execute FFmpeg command: ${err}`);
    }

    console.log("*cleaning up screenshots");
    // cleanDirFiles(frameDir);

    console.log("*finish all process");

}

I called the function like this.

generateVideo("videos/test002.mp4", "https://www.highsto.net/cards/", "#cardsSection", 3);

However animation speed in video was too fast as follows. https://user-images.githubusercontent.com/100674437/235637095-eedb214b-ac7b-489c-b9c3-3f73fe1defef.mp4

I checked frame images and it was wrong, so I think it's not the probrem of ffmpeg.

Expected behavior I would like to turn CSS/JS animations on the web into mp4 videos while keeping the speed intact.

Attachments and Screenshots If applicable to a local, publicly unavailable web site, upload a minimal reproducible example. Also if applicable, add screenshots to help explain your problem.

Desktop

Additional context Sorry for my poor English. I would appreciate any help you could give me.

tungs commented 1 year ago

The version of timeweb that timesnap uses (timeweb v0.3.1) doesn't support CSS transitions/animations, but newer versions of timeweb do. You also need to use a newer version of Chrome/Chromium to use this feature.

Upgrading timeweb

You can override the timeweb dependency by putting this in your package.json file:

  "overrides": {
     "timesnap": {
        "timeweb": "0.3.2"
      }
  }

and reinstalling dependencies.

Using a newer version of Chrome/Chromium

To use this feature you need to use a version of Chrome/Chromium that supports CSS Animations using the Web Animations API, which should be Chrome/Chromium version 84 and above. timesnap uses puppeteer v2.1.1, which ships with Chromium v80 or so.

One way to use a newer version is by downloading your own version of Chrome/Chromium, and then using config.executablePath, to use that version. You can check the Executable Path by going to chrome://version/ in your browser.

For example, if you have Google Chrome installed at /Applications/Google Chrome.app:

    await timesnap({
        url,
        //...
        executablePath: "/Applications/Google Chrome.app",
        // might need something like "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"
    });

Alternatively, newer versions of Puppeteer should ship with newer versions of Chromium, so you can also override the puppeteer dependency, like overriding the timeweb dependency above (for example add "puppeteer": "19.11.1" below "timeweb": "0.3.2",). Using a newer version of puppeteer might require some additional work installing dependencies, though there might not be any additional work for MacOS.

Let me know if you run into any problems, or if it works! timeweb support for CSS Animations is very new, so I'm curious how well it works.

zuisho-1848-o commented 1 year ago

Thank you for your answer.

I tried exactly what you said. The result was good.

https://user-images.githubusercontent.com/100674437/235852678-3fe54cb9-dd5c-4663-92a1-9ebf137a9f89.mp4

The animation speed was almost same as the one in web. https://highsto.net/cards/

I'll try in other web sites and HTML files.

If there is one problem, it would be ideal if the execution time were a little shorter. It took about 70sec to create a video(30fps, 3sec).

Anyway, thank you for your kindness.

zuisho-1848-o commented 1 year ago

Sorry for the repetition, but I have one more question.

I tried at other web sites, and found that the start of capture does not coincide with the start of the animation on the web site.

When I tried to capture the 3sec css animation, the animation in the result video had already finished in the start of the video.

Are there any way to control the start of capture? Or I would appreciate it if you taught me how to decide the start of capture in this package.

tungs commented 1 year ago

Can you post some links for the sites that are out of sync? I know about an issue where css animations with delays probably won't work as intended, but if there are other cases, I would like to know about them. It may be solvable in next versions of timesnap.

zuisho-1848-o commented 1 year ago

The link of the site I tried in the video is here. https://highsto.net/cards/

I also tried on the localhost site and same problem occurred.

I tried with some other libraries, and as I realize, CSS keyframe animations may be difficult to capture frame by frame. It would be great if this could be solved.

tungs commented 1 year ago

Which animations are finished at the start of the video? I see the flickering animation that you posted in the video above, but I don't see any other animations when I go to it in browser. Thanks!