TalkOver

Record your browser tab as a polished video with webcam overlay — or export as an animated GIF. One click to capture demos, tutorials, bug reports, and walkthroughs, right from your browser.

Install from the Chrome Web Store: coming soon — pending review.

Zero dependencies. Zero accounts. Zero cloud. Everything runs locally using browser APIs.

Chrome Manifest V3 Version License

Why TalkOver?

Most screen recorders need accounts, cloud uploads, or desktop apps. TalkOver is different:

Perfect for developers sharing bug reproductions, educators making walkthroughs, designers demoing flows, or anyone who needs a quick screen capture with a personal touch.

Features

Recording

Editing

Export

Settings

| Setting | Options | Default | |———|———|———| | GIF Frame Rate | 5, 10, 15, 24, 30 fps | 10 fps | | Scale | 100%, 75%, 50%, 25% | 100% | | Quality | Low, Med, High | Med | | Cursor | on / off | on | | Loop GIF | on / off | on | | Webcam Position | TL, TR, BL, BR | BR | | Webcam Shape | Rectangle, Square, Circle | Rectangle |

All settings persist across sessions.

Extras

Install

From source (Developer mode)

  1. Clone this repository
    git clone https://github.com/NeoVand/TalkOver.git
    
  2. Open chrome://extensions/ in Chrome
  3. Enable Developer mode (top right toggle)
  4. Click Load unpacked and select the project folder
  5. Pin the extension to your toolbar

From Chrome Web Store

Coming soon.

Usage

  1. Click the TalkOver icon in your toolbar
  2. Toggle Webcam and/or Audio if you want them
  3. Press the Record button (or Alt+Shift+R)
  4. Interact with your tab — everything is being captured
  5. Press Stop
  6. Trim if needed, then Save as GIF or Save as Video

The file downloads instantly with a timestamped filename.

Architecture

popup.html/js/css    UI — controls, preview, trim, webcam overlay, export
background.js        Service worker — state machine, tab capture, message routing
offscreen.js         Offscreen document — MediaRecorder, stream capture, blob storage
gif-worker.js        Web Worker — frame quantization, LZW compression, GIF89a encoding
db.js                IndexedDB wrapper — stores video, webcam, and GIF blobs
permissions.html/js  Dedicated page for mic/camera permission prompts

Recording flow

                   ┌─────────────────────────────────────────────┐
  User clicks      │  background.js                              │
  Record ─────────>│  tabCapture.getMediaStreamId()              │
                   │  reads tab dimensions (width × height)      │
                   │  sends config to offscreen document         │
                   └──────────────┬──────────────────────────────┘
                                  │
                   ┌──────────────v──────────────────────────────┐
                   │  offscreen.js                               │
                   │  getUserMedia(tab stream at native res)     │
                   │  getUserMedia(webcam) ─> separate recorder  │
                   │  getUserMedia(mic)                          │
                   │  mix tab audio + mic via Web Audio API      │
                   │  MediaRecorder(tab video + mixed audio)     │
                   │  MediaRecorder(webcam video)                │
                   │  ──> blobs saved to IndexedDB               │
                   └──────────────┬──────────────────────────────┘
                                  │
                   ┌──────────────v──────────────────────────────┐
  User sees        │  popup.js (done view)                       │
  preview ─────────│  loads tab video from IndexedDB             │
                   │  loads webcam video from IndexedDB          │
                   │  overlays webcam via CSS (same as live)     │
                   │  trim handles adjust clip range             │
                   └──────────────┬──────────────────────────────┘
                                  │
                   ┌──────────────v──────────────────────────────┐
  User clicks      │  popup.js (export)                          │
  Save ───────────>│  GIF: frame-by-frame canvas + webcam PIP   │
                   │       quantize + LZW in Web Worker          │
                   │  Video: canvas composite + MediaRecorder    │
                   │       (in visible popup — not offscreen)    │
                   │  ──> download                               │
                   └─────────────────────────────────────────────┘

Why compositing happens in the popup

Chrome’s canvas.captureStream() is broken in offscreen/hidden documents (Chromium #41270855, #41279417). Tab and webcam streams are recorded separately in the offscreen document, then composited during export in the popup where the canvas rendering pipeline is active.

How the GIF encoder works

The extension includes a from-scratch GIF89a encoder (no libraries):

  1. Frame extraction — each frame drawn to canvas at configured FPS and scale, with webcam PIP overlay
  2. Median-cut quantization — reduces each frame to a 256-color palette by recursively splitting the color space
  3. Transparency optimization — pixels unchanged from the previous frame are marked transparent, reducing file size
  4. LZW compression — standard GIF compression on the indexed pixel data
  5. Binary assembly — header, logical screen descriptor, application extension (for looping), and frame blocks assembled into valid GIF89a

All encoding runs in a Web Worker with progress updates streamed back to the UI.

Permissions

Permission Why
tabCapture Capture the active tab as a media stream
activeTab Read the title of the tab you’re recording (so the file is named after it)
offscreen Run MediaRecorder in a background document (MV3 requirement)
storage Persist user settings and per-tab recording metadata across sessions

No data leaves your browser. Recordings live in your browser’s IndexedDB until you start a new recording in that tab or close the tab; nothing is uploaded.

Privacy

TalkOver does not collect, transmit, or store any personal data. All recordings live only in your browser’s local IndexedDB, are scoped per tab, and are cleared when you start a new recording in that tab or when the tab closes. No analytics, no telemetry, no network requests, no third-party fonts or scripts.

See PRIVACY.md for the full privacy policy used on the Chrome Web Store listing.

Contributing

Contributions are welcome! Please open an issue or pull request.

License

MIT