Building my own screen-recording app
For a recent job interview I had to record my screen completing a code challenge.
The obvious solution would be to grab a tool like loom but they require payment for recording video. So I thought to myself, I’ve got ffmpeg, a browser, node, an LLM and 2 hours time, I can build this myself 😅
Here’s a video of the final output (without any sound for this demo)
I’ve worked with MediaCapture API before, so to add some extra challenge I built the frontend with Svelte.
Table of contents
A simple screen recorder with svelte
To get started with Svelte we’ll start with a simple boilerplate by using the CLI
Similar to Vue.JS templates, Svelte works with scripts, styles and templates in a single file.
Let’s set up some state in our src/App.svelte
file!
In svelte this is as simple as creating a let statement:
Let’s a write a function to record!
For now we can take the audio stream from the webcam and combine it into the screen stream.
In the template we show a very simple Record / Stop Recording button with the final video output files.
And that’s basically it 🎉
We’ve got a working application that can record the screen as well as a webcam feed.
Improvements
While this basic application functions, there were some improvements that really made the result work for me 🤓
Moving the webcam feed into a Picture in Picture window
I wanted to move my webcam frame into a separate window, so I will never block any content from the viewer.
I like the approach described in this article about composing the desktop & webcam streams together into a <canvas />
element and saving the output as a video file, but while approach looks very cool, it is lacking the context of the webcam position.
It also introduces another layer where things might go out of sync with the audio as well as a performance overhead of another composition layer.
But we can solve this by using the requestPictureInPicture method on the a video.
We separate the webcam stream from the desktop stream again, and just open it in a separate Picture in Picture window.
Here’s a demo of the result:
You won’t get a nice circle as loom, but for my purposes this was good enough.
Tuning the Codec
As the codec for the recorded screen I’ve used these options:
This gave me the best results with acceptable performance.
Apparently the newer AV1
codec gives you an even better output quality, but It’s very CPU intensive and was unusable on my machine.
Fixing the color profile under Linux
On my linux machine the colors of the recordings looked washed out.
I could fix this by forcing a color profile via the chrome flags:
chrome://flags/#force-color-profile
For my machine forcing them to sRGB
led to the best results.
Streaming the video directly to my hard drive
While saving the video locally is fine, I would like to be in control of any recorded data at all time. When the browser crashes or I close it accidentally, the whole stream would be lost 😢
As a simple solution I’ve set up a WebSockets Server that accepts the video stream and writes it directly to a file.
And on the client we simply connect to our server when we start a recording and close the session when stopping.
Whenever we’ve got new data we send it to the server.
We’ll also define how often we want to push chunks to the server, in our case every second.
The only thing left is to close the WebSocket connection when we stop the recording.
Now whenever we finish a recording the file already sits at the root of our repository, no more downloading needed!
Processing the recorded files
Depending on your display resolution the files size is most likely to quite large.
For my machine with a 1920x1200
resolution I’m getting around 3 GB of data for 1 Hour of video.
We can optimize the final result using ffmpeg:
This will optimize our video so we can upload it to a server to share.
With these properties I could reduce the file size to 365 Mb 🏋️
Tuning Audio Settings
To get a better output for the audio you could try these settings, although I did encounter some cutting of short voice responses.
That’s a wrap!
Have a look a the source code here:
https://github.com/floscr/svelte-screen-record