Recording webRTC with a ghost participant using puppeteer

Tosh Velaga
4 min readJan 18, 2022

--

TLDR: check out puppeteer-stream if you want to set up recording of video and audio for a webRTC video chat with little effort.

I have recently been working on different ways to record my webRTC group video chat application. During my research I have come across several different methods. Basically you can either record the meeting on the client or the server. The client methods that I have tried are the following: 1) using a canvas element and the canvas.captureStream(frameRate) method 2) mixing the individual streams using a library like recordRTC.js 3) using getDisplayMedia to record the screen which is what this awesome open source project mirotalk uses.

check out open source project mirotalk which uses getDisplayMedia to record the screen

To be honest these methods on the client are less than ideal and a little bit hacky. Additionally if you can get one of them to work they put even more strain on the client. In my research it seems that the more widely used way to record a webRTC meeting is to do it on the server instead of the client. The way it works is pretty creative IMO. A ghost participant joins the meeting on the server using a service like puppeteer and records the screen. This approach has much more flexibility as you can drag around video participants on the screen and incorporate fun animations on the client that can get recorded. The only downside is that it would be difficult to scale as you need to launch an instance of puppeteer for each recording.

To get started with this server side approach I set up a couple of small and simple experiments to see what was possible to develop in the fastest time possible. Before diving into the code check out the video app I used HERE. Note that I forked the code from this excellent repo and made a bunch of changes to suit my use case. To get started you can just clone the repo since that would be faster.

video meeting app that I will be using

You probably already know what puppeteer is and you’ve probably used it for scraping, but just a quick explanation is that it is a super popular Node JS library that lets you launch a headless instance of the chrome or chromium browser.

To create a puppeteer script that joins the video meeting and takes a picture of the participants in the meeting create a file in the root directory called puppeteer.js and copy and the paste the code from below. In this script we are using an async IIFE to launch a chromium instance, go to the url https://video-meeting-socket.herokuapp.com/room, click the connect button, wait for 2 seconds to give enough time for the other participants to render on the screen, take a screenshot, and finally close the browser.

to run this script on the command line use:

node puppeteer.js example
picture after running node puppeteer.js

Where the argument example on the command line is the name of the picture that gets created. Pretty cool huh? Well let’s go a step further. Let’s record a video using this awesome library puppeteer-screen-recorder which uses the chrome devtool protocol. The library has an excellent maintainer who answers issues fast.

maintainer explaining how the library works

Create another file in the root directory called puppeteerRecord.js and copy and paste the code from below into the file.

run this script on the command line using:

node puppeteerRecord.js example2
short video after running node puppeteerRecord.js

This will join the video meeting and record a short ~8 second video of the participants in the room. The only thing that is missing is audio, which is not currently supported by the library. To solve for this we are going to a use a different library that is less popular but totally ingenious. It only gets around 200 weekly downloads, but it’s a gem. Check out puppeteer-stream. It also has an excellent maintainer who responds to issues fast. If you’re curious here is an explanation by the author of how puppeteer-stream works:

library author explaining how the puppeteer-stream works

Create a file in our root directory called puppeteerStream.js and copy and paste the code from below.

Run the script using:

node puppeteerStream.js example3
short video after running node puppeteerStream.js

In this example you should have a recording with the participants that includes video and audio. Wow wasn’t that fun! Now these solutions aren’t perfect, but they should get you started on the road to building a more robust recording solutions for webRTC apps. As for me I’ll be building a more scalable and sophisticated solution. I’ll post another article soonish with those notes. Hope this article helps! If so give it a clap :).

Relevant links:

--

--