A local desktop tool for recording browser interactions and exporting them as narrated MP4 tutorial videos. Built with Playwright, React, and Express.
- Record — a Playwright-controlled Chromium window opens at your chosen URL. Every click, form input, navigation, scroll, and keypress is captured as a timestamped step.
- Narrate — as each step lands in the sidebar, type an optional narration string. These appear as a styled overlay banner at the bottom of the screen during playback.
- Save — export the journey as a portable
.jsonscript you can load, edit, and re-run at any time. - Replay — Playwright replays the script in a fresh browser window, injecting narrations as each step executes, and records the entire session as video.
- Export — the recording is automatically converted to an
.mp4and downloaded to your machine.
- Node.js v18 or later
- macOS or Windows
git clone <repo-url>
cd tutorial-recorder
npm installnpm install automatically downloads the Playwright Chromium browser.
npm run dev # build + launch Electron window (first run, or after editing source)
npm start # build + launch (alias for the above)
npm run standalone # run as a plain web server at http://localhost:3535 (no Electron)The app opens as a native desktop window powered by Electron.
The app is packaged with electron-builder. Each platform produces a self-contained installer — end users do not need Node.js installed.
Install the project dependencies first:
npm installnpm run dist| Command | Output | Platform |
|---|---|---|
npm run dist:mac |
.dmg (universal: x64 + arm64) |
macOS |
npm run dist:win |
.exe NSIS installer |
Windows (x64) |
Cross-compilation is limited: building a Windows installer from macOS requires Wine, and vice versa. The recommended approach is to build on the target platform (e.g. via CI).
Output files are placed in the release/ directory.
- Electron runtime — Chromium + Node.js, no system install required
- ffmpeg — the
ffmpeg-staticbinary is unpacked from the asar so the OS can execute it - React UI — pre-built into
dist/renderer.jsat package time
The Chromium browser is bundled inside the installer — end users do not need to install anything separately. The dist commands handle this automatically by running npm run install:browsers first, which downloads Chromium into ./playwright-browsers/ and electron-builder copies it into the app bundle as extraResources.
This adds ~300 MB to the installer size.
If you need to download the browser manually (e.g. for development without running npm run dev):
npm run install:browsersIf the Electron window does not open and you see errors about app being undefined, check whether ELECTRON_RUN_AS_NODE=1 is set in your shell environment:
echo $ELECTRON_RUN_AS_NODEIf it is set, unset it before running or building:
unset ELECTRON_RUN_AS_NODE
npm run devThe npm scripts already prepend unset ELECTRON_RUN_AS_NODE automatically, but a global shell export can override this.
- Paste a URL into the address bar and press ● Record (or hit Enter).
- A browser window opens — interact with the site as you normally would.
- Each action appears in the sidebar. Type a narration for each step while you browse, or fill them in afterwards.
- Press ■ Stop when done.
- ↓ Save — downloads the journey as a
.jsonfile you can version-control or share. - ↑ Load — opens a file picker to restore any previously saved script. Steps and narrations are preserved.
- ▶ Replay — Playwright replays the script and records the session. A visible browser window shows the narration overlay at the bottom of the screen as each step runs.
- Once complete, ↓ Download MP4 appears. Click it to save the finished tutorial video.
Click ⚙ Style in the top-right corner to customise the narration banner: background colour, opacity, text colour, font size, and font family. Changes are saved with the script.
Form inputs whose type is password, email, tel, or hidden are automatically encrypted before being written to the .json script file. Playback decrypts them transparently — the plaintext value is never written to disk.
The encryption key is generated on first use and stored at:
~/.tutorial-recorder-key
Keep this file safe. Without it, encrypted steps in saved scripts cannot be replayed. Back it up alongside your scripts if you plan to use them on another machine.
tutorial-recorder/
├── main.js # Electron main process — starts server, opens window
├── server.js # Express + Socket.io server, API routes
├── recorder/
│ ├── index.js # Playwright recorder — launches browser, wires up events
│ └── inject.js # Content script injected into every page
├── player/
│ └── index.js # Playwright player — replays script, records video
├── exporter/
│ └── index.js # ffmpeg wrapper — converts .webm → .mp4
├── crypto-util.js # AES-256-CBC encryption for sensitive step values
├── src/
│ ├── App.jsx # Root React component, application state
│ ├── api.js # fetch + Socket.io client transport layer
│ ├── components/
│ │ ├── Controls.jsx # URL input, record/stop/replay/export buttons
│ │ ├── StepList.jsx # Scrollable list of recorded steps
│ │ ├── StepItem.jsx # Single step with narration input
│ │ ├── OverlaySettings.jsx# Narration banner style editor
│ │ └── StatusBar.jsx # Mode indicator and status messages
│ └── styles.css
└── dist/ # Compiled renderer bundle (generated)
- File uploads — steps that involve a file-chooser (
<input type="file">) are recorded but cannot be replayed automatically, as the original files are not available. They are skipped during playback. - Cross-origin iframes — events inside third-party iframes may not be captured depending on the site's CSP.
- Selector fragility — playback uses CSS selectors with XPath and coordinate fallbacks. Heavily dynamic or randomly-generated class names may require the script to be re-recorded if the site changes.
| Layer | Technology |
|---|---|
| Desktop shell | Electron 41 |
| UI | React 18, Socket.io client |
| Server | Express 4, Socket.io |
| Browser automation | Playwright (Chromium) |
| Video encoding | ffmpeg-static, fluent-ffmpeg |
| Encryption | Node.js crypto (AES-256-CBC) |
| Bundler | Webpack 5, Babel |
| Packaging | electron-builder |