Efficiently Capture Screenshots from Video in the Browser with JavaScript

Bibhuti Poudyal
3 min readJul 22, 2024
Photo by Wahid Khene on Unsplash

Problem

You have a video and you need to take screenshots from the video at 1-second interval.

Initial Thoughts

This task is typically suited for servers. However, processing on a server involves several steps:

  • Upload the video to the server.
  • For lengthy videos, store them in a storage facility like AWS S3.
  • Extract screenshots using tools like moviepy(python), ffmpeg(Node.js), FFMpeg-PHP(php), etc.
  • Save image in S3 or somewhere elese and allow the user to download them.

Why spend so much time and resources on server and storage when it can be done directly in the browser?

Solution

Load the video in a standard video element. After the video starts playing, create a timer using setInterval with a 1000ms delay. This timer will run a function to render the video on a canvas and extract the dataURL from the canvas every second.

However, this solution has a major flaw. Users need to wait for the entire video to play to get all the screenshots. For lengthy videos, this approach is too slow and inefficient.

Improved version

Instead of using a timer, utilize the timeupdate event from the video element. Manually increment the currentTime property of the video by 1 second after each screenshot is taken. This method advances the video immediately after capturing a screenshot, significantly reducing wait times. Performance may vary depending on the user’s device.

Demo

Here are some info from the demo:

Note:

If you are doing this is on a browser extension and you need to perform it in background, then you may encounter the issue of timeupdate event not firing. It happens when processing is happening on one browser tab and user is working on another tab. For that you will need to switch to that tab where video processing is running and you can immediately switch back to previous one after timeupdate has fired. For that, you need to keep track of the browser tabs.

// use this code to keep track of active tabs
chrome.tabs.onUpdated.addListener(async (tabId, changeInfo, tab) => {
workingTabId = tabId;
});

// switch to video-processing-tab
await chrome.tabs.update(processingTabId, { active: true, selected: true });

// take screenshots here...
// ......
// ......

// switch back to previous tab
video.addEventListener('timeupdate', async function () {
await chrome.tabs.update(workingTabId, { active: true, selected: true });

// ...
// ...
}

This switching will happen within milliseconds. So, users may not event notice it. timeupdate fires multiple time. Make sure to add a condition so that switching happens only once.

Conclusion

This article explores the perks of browser-based video processing to save server costs, time, and implementation effort. If it can be implemented on server, it doesn’t mean that it should be. With increasing capacity of desktop and mobile devices a lot of stuffs can be done on end devices without renting expensive servers.

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

No responses yet

Write a response