Monorepo for MyPipCam: Loom-style camera PiP on macOS and in Chrome.
Created by EarnYour Marketing and published freely on GitHub under the MIT License. See NOTICE for attribution.
Product site / funnel: mypipcam.earnyour.com
Chrome extension (end users): Add to Chrome — Chrome Web Store (ID meiehjfjcaahfjcdneoegjkmajbfghmm)
Tip jar (optional): Support MyPipCam on Stripe — pay what you want; keeps the project free and open source.
| Path | What |
|---|---|
apps/macos |
macOS companion — floating always-on-top camera bubble for OBS / desktop recording |
apps/extension |
Chrome extension — screen + camera PiP recording, local library, trim/cut editor |
apps/web |
Product site + share watch pages (/w/{shareId}) and view-count API |
Legal & safety: Terms of Use · Privacy · Security · Contributing · Code of Conduct
AI / IDE agents: start with AGENTS.md (install, env, load unpacked, pitfalls, verify checklist).
Install the published extension:
Pin it, open any http(s) page, click the icon → start recording. Optional Google Drive: Library → Settings → Connect Google.
Source, issues, and the macOS companion app are on this GitHub repo (secondary).
There is no root package.json — build each app from its directory.
cd /path/to/MyPipCam/apps/extension
npm install
cp .env.example .env.local # optional: set VITE_GOOGLE_OAUTH_CLIENT_ID for Drive
npm run buildThen Chrome → chrome://extensions → Developer mode → Load unpacked → select apps/extension/dist.
cd /path/to/MyPipCam/apps/web
npm install
# Set SUPABASE_* in Vercel (see apps/web/.env.example) for share/view API
vercel --prod# Xcode: open apps/macos/MyPipCam.xcodeproj → Run
# Or install Release to Applications (needs ImageMagick + Xcode):
./scripts/install-macos-app.shDetails, Drive OAuth, shared library folder, and pitfalls: AGENTS.md · CONTRIBUTING.md.
- Chrome extension is the Loom-like capture path: record this Chrome tab with a live draggable camera PiP on the page (tab capture), browse clips in a local library, trim/cut, and download. An Advanced path still supports screen/window capture.
- macOS app is the desktop companion: a real always-on-top camera window, plus Record (ScreenCaptureKit screen/window capture with PiP) that saves into the shared library folder Chrome uses.
- Shared library folder (optional): both apps can point at the same local folder so Chrome writes recordings to disk and the Mac app browses/plays them. Until a folder is chosen, the extension keeps clips in IndexedDB only.
You can use either alone, or both (e.g. Mac bubble for OBS + extension for quick browser recordings).
Pick one folder on disk (suggested: ~/Movies/MyPipCam). Chrome and the Mac app both use it as the source of truth for recordings — no cloud sync required.
<LibraryRoot>/
.mypipcam-library # marker (version 1)
recordings/
<uuid>/
meta.json # id, title, createdAt, durationMs, mimeType, sizeBytes (+ optional Drive fields)
video.webm # or video.mp4
thumb.jpg # optional
transcript.json # optional
meta.json may also include driveFileId, driveWebViewLink, and driveShared when the clip is uploaded to Google Drive.
- Open Library → Settings (or use the banner when no folder is set).
- Under Recording library, click Choose folder… and select (or create) the folder — e.g.
Movies/MyPipCam. - When prompted, optionally move existing browser recordings into the folder (one-shot IndexedDB → disk migration).
- New recordings are written under
recordings/<uuid>/. If the offscreen recorder cannot write (permission), clips queue in IndexedDB and flush when you reopen Library.
- Choose Choose Recording Library… (menu bar or bubble menu) and select the same folder.
- Open Recording Library opens the native library window when a folder is set (browse, play, rename, delete, Reveal in Finder).
- Use Open in Chrome… when you need the extension editor / transcription workflow.
Transcription still uses an OpenAI API key in extension Settings only (Deepgram / AssemblyAI placeholders were removed).
Chrome extension only. Local folder + Mac shared-folder support are unchanged. Drive is an optional layer: upload after save, list/play from Drive on other browsers, and create Loom-style MyPipCam watch links with view counts.
Google Drive does not expose reliable “anyone with the link” view analytics to third-party apps. MyPipCam therefore shares a link to https://mypipcam.earnyour.com/w/{shareId}. Opening that page counts as a view; the page embeds the Drive preview when a driveFileId is available. The Library shows 👁 N views / last viewed (refreshed on Library load).
MyPipCam uses https://www.googleapis.com/auth/drive.file (app-created / app-opened files only). On Connect, the extension creates (or reuses) a MyPipCam folder in your My Drive and stores its folder ID in chrome.storage.sync.
| Approach | Pros | Cons |
|---|---|---|
drive.file + app folder (chosen) |
Minimal access; works for multi-device via folder ID sync | Cannot pick an arbitrary existing folder you didn’t open with the app |
Full Drive / drive.readonly |
Folder picker for any folder | Broader access than needed |
Auth still uses chrome.identity with a Chrome extension OAuth client. The product website is for the OAuth consent screen (and public legal links)—it is not the OAuth client “Application ID” and does not replace the extension client ID.
- Open Google Cloud Console and create (or select) a project.
- Enable Google Drive API (APIs & Services → Library → “Google Drive API” → Enable).
- Configure the OAuth consent screen (External is fine for personal use). Add yourself as a test user while the app is in Testing.
- Application home page:
https://mypipcam.earnyour.com - Application privacy policy link:
https://mypipcam.earnyour.com/privacy(host or mirrorPRIVACY.mdthere) - Application terms of service link (optional):
https://mypipcam.earnyour.com/terms(host or mirrorTERMS.mdthere) - Authorized domains: add
earnyour.com
- Application home page:
- Create two credentials (recommended): APIs & Services → Credentials → Create credentials → OAuth client ID — Application type Chrome extension (not “Web application”) for each.
- Item ID / Application ID = the extension ID for that build — not the website hostname:
| Client | Suggested name | Item ID | Use |
|---|---|---|---|
| A — store | MyPipCam Store |
meiehjfjcaahfjcdneoegjkmajbfghmm |
Store zip / published listing only |
| B — local | MyPipCam Local |
akpchobfndfddajiihkkdpnihihdicjc |
Daily .env.local + unpacked dist (manifest key present) |
Unpacked without key gets a random third ID; OAuth will fail until you reload a build that keeps key. Do not flip one client’s Item ID between store and local. Full dual-client workflow: docs/marketing/CHROME_WEBSTORE.md. Connect Google surfaces the live extension ID in Settings when auth fails for a mismatch.
6. Copy Client B’s Client ID (ends with .apps.googleusercontent.com) for local work.
7. Put it in gitignored env (never commit the real ID):
cp apps/extension/.env.example apps/extension/.env.local
# edit .env.local — Client B (local Item ID), not the store client:
VITE_GOOGLE_OAUTH_CLIENT_ID=YOUR_CLIENT_ID.apps.googleusercontent.comdriveConfig.ts reads VITE_GOOGLE_OAUTH_CLIENT_ID at build time; the committed fallback is a placeholder. The manifest oauth2.client_id imports that value automatically. Bake Client A only when packaging the store zip.
- Rebuild and reload:
cd apps/extension
npm run buildThen Reload the extension on chrome://extensions (ID should be akpchobfndfddajiihkkdpnihihdicjc).
- Library → Settings → Google Drive → Connect Google — sign in; a
MyPipCamfolder is created/found on Drive. - Leave Auto-upload new recordings to Drive on (default) so new clips upload after local save (retries when you open Library).
- Per clip: Upload to Drive (if not uploaded), Share / Copy link — copies the MyPipCam watch URL (also enables Drive anyone-with-link so the embed can play).
- Cards show a Drive badge when the file is on Drive; shared clips also show 👁 views / last viewed. Drive only means it exists remotely but not in this browser’s local library.
| Piece | Role |
|---|---|
apps/web watch page |
/w/{shareId} embeds Drive preview + POST /api/shares/:id/view |
| Supabase tables | mypipcam_shares, mypipcam_views (see apps/web/.env.example) |
| Extension Library | Creates share via POST /api/shares, copies watch URL, refreshes stats |
Vercel env vars (project mypipcam, Production + Preview) — server-only, never commit:
SUPABASE_URL=https://YOUR_PROJECT_REF.supabase.co
SUPABASE_SERVICE_ROLE_KEY=<service_role from Supabase → Settings → API>With RLS locked down, SUPABASE_SERVICE_ROLE_KEY is required on Vercel. SUPABASE_ANON_KEY alone cannot create shares or record views. Set both Production and Preview (Dashboard or vercel env add).
Deploy from the monorepo root (Vercel root directory is apps/web):
cd /path/to/MyPipCam
vercel --prod- Connect Google Drive on computer A (same Google account as Chrome sync).
- Folder ID is stored in
chrome.storage.sync, so other Chrome profiles signed into that Google account receive the same folder ID. - On computer B: open Library → Connect Google (if needed) → recordings uploaded from A appear (play downloads from Drive).
- Local disk library and Mac app stay independent; Drive does not replace them.
Add to Chrome → pin MyPipCam → open an http(s) page → start recording.
Shortcut: ⌘⇧U (Mac) / Ctrl+Shift+U (Windows/Linux) — start or stop.
- Build:
cd apps/extension
npm install
npm run build- Open Chrome →
chrome://extensions - Enable Developer mode
- Load unpacked → select
apps/extension/dist - Pin MyPipCam, open a normal http(s) page, click the icon → pick mode → Start recording — 3→2→1 countdown, then a draggable camera bubble + left control dock (no big recorder window).
Extension IDs: store (live) meiehjfjcaahfjcdneoegjkmajbfghmm · unpacked (key) akpchobfndfddajiihkkdpnihihdicjc
Store listing: chromewebstore.google.com/detail/mypipcam/meiehjfjcaahfjcdneoegjkmajbfghmm
Library page (store): chrome-extension://meiehjfjcaahfjcdneoegjkmajbfghmm/src/library/index.html
Library page (unpacked): chrome-extension://akpchobfndfddajiihkkdpnihihdicjc/src/library/index.html
Open in Chrome… (macOS) opens the HTTPS bridge https://mypipcam.earnyour.com/open-library?ext=… with either ID so the extension opens Library via chrome.tabs — direct chrome-extension:// navigation is often blocked by ad blockers (ERR_BLOCKED_BY_CLIENT).
(The macOS app Open Recording Library menu opens this URL.)
If auto-detect picks the wrong install, use Set Extension ID… and paste the ID from chrome://extensions (Developer mode), then Save & Open Library. The app recognizes both the store and unpacked IDs under Chrome/Edge/Brave/Arc profiles.
| Surface | Role |
|---|---|
| Popup | Tab+Cam / Tab only / Cam only, mic picker, start/stop, library, Advanced |
| In-page chrome | Countdown, draggable cam bubble (⋯), left dock (timer / stop / pause / discard) |
| Offscreen | Hidden MediaRecorder for tab or camera capture |
| Advanced recorder | Optional screen/window capture + canvas PiP compositor |
| Library | Browse, play, rename, delete, download, open editor, Drive upload/share |
| Editor | Trim in/out, optional middle cut-out, export via ffmpeg.wasm |
cd apps/extension
npm install
npm run devThen load the unpacked path Vite/CRXJS prints (or rebuild and reload dist).
A Loom-style floating camera bubble for macOS. Point it at your webcam (or OBS Virtual Camera), drag it around, and use Record to capture the desktop (or a window) with the PiP included — or keep using OBS if you prefer.
- Circular always-on-top camera bubble
- Drag anywhere to move
- Scroll while hovering to resize
- Camera picker (OBS Virtual Camera, FaceTime, Continuity Camera, etc.)
- Microphone picker (built-in / USB / Bluetooth mics) — choice is remembered and used for desktop recording
- Border color presets + soft Loom-like drop shadow
- Mirror toggle
- Menu bar icon to show/quit (no Dock icon)
- Record… — dots menu / menu bar: pick camera, mic, Screen or Window, then ScreenCaptureKit-record; saves MP4 into the shared library folder (
recordings/<uuid>/). Choose microphone or system audio (not both — a single AAC track cannot mix them cleanly). Tab capture stays in the Chrome extension. Google Drive upload still runs through the extension when Connect Google + auto-upload are enabled. - Open Recording Library — opens the native library window when a shared folder is set (prompts to choose otherwise)
- Choose Recording Library… / Reveal Library in Finder — pick or show the on-disk folder shared with Chrome
- Open in Chrome… — secondary path for editor / transcription / Drive sync (via
mypipcam.earnyour.com/open-librarybridge) - Set Extension ID… — paste ID from
chrome://extensionsif the bridge cannot reach the extension - Install Chrome Extension… — opens
chrome://extensions+ revealsapps/extension/distwith load steps
Install a normal Applications app (screen icon with orange PiP dot):
cd /path/to/MyPipCam
./scripts/install-macos-app.shThat builds a signed Release .app, copies it to /Applications/MyPipCam.app, and opens it. Find it in Applications / Launchpad, or run open -a MyPipCam.
- Open
apps/macos/MyPipCam.xcodeprojin Xcode - Under Signing & Capabilities, pick your Apple Development Team (replace the sample team ID in the Xcode project if you are forking). Keep a Team selected so Camera permission survives rebuilds.
- Press Run (⌘R)
- Allow camera access when prompted (once). Camera choice and appearance settings are remembered across launches.
- Open the mic menu (toolbar mic icon or right-click → Microphone) and allow microphone access if prompted — selection is remembered for next launch. The bubble itself does not capture audio; pick the same mic in OBS (or use the Chrome extension recorder) for the final mix.
- In OBS: Start Virtual Camera
- Hover the bubble → camera icon → choose OBS Virtual Camera (last choice is restored next launch; OBS is preferred only when nothing is saved)
macOS Privacy (TCC) ties Camera access to the app’s code signature, not only the bundle ID (com.stevenmartinez.MyPipCam).
- Same signed build / Development Team: Grant once → relaunches should start silently without re-prompting. Selected camera + bubble settings persist in UserDefaults.
- Ad-hoc / unsigned / empty Team: Each rebuild can look like a new app to TCC, so macOS may ask for Camera again. Prefer a Signing Team in Xcode.
- If access was denied: the app will not spam the system dialog. Use Open System Settings on the bubble, or go to System Settings → Privacy & Security → Camera and enable MyPipCam.
- Launch from one consistent location (Xcode Run, or one built
.app) — different paths can create separate TCC entries.
Record your display/screen in OBS as usual. MyPipCam sits on top of your desktop as a real window, so it appears in the recording with you inside the circle.
Audio: The macOS bubble is video-only (no in-app mic capture or file recording). Choose your mic in MyPipCam for preference parity with the extension; configure the same input in OBS (or record with the Chrome extension) for the actual soundtrack.
| Action | How |
|---|---|
| Show / Hide Bubble | Menu bar icon (also Hide in bubble ⋯ / right-click; Show restores after Hide, Cmd+W, or Cmd+H) |
| Move | Drag the bubble |
| Resize | Scroll while hovering, or right-click → Size |
| Switch camera | Hover → video icon, or right-click → Camera |
| Switch microphone | Hover → mic icon, or right-click → Microphone |
| Border color | Hover → palette icon, or right-click → Appearance… |
| Shadow / mirror | Right-click the bubble / Appearance popover |
| Quit | Hover → ✕, menu bar icon → Quit, or right-click → Quit |
| Open at Login | Menu bar icon → Open at Login, or right-click the bubble |
| Open Recording Library | Menu bar or bubble context menu → native window (shared folder) |
| Choose / Reveal Library | Menu bar or bubble context menu → pick or show folder in Finder |
| Open in Chrome… | Menu bar or bubble context menu → extension library/editor |
| Install Chrome Extension… | Menu bar or bubble context menu → load-unpacked helper |
- macOS 14+
- Xcode 16+
- Camera permission
- Microphone permission (for the mic picker; optional if you never open that menu)
- OBS Virtual Camera (optional, if that's your source)
Both the macOS app and the Chrome extension can point at the same local folder so recordings on disk are visible in both.
- In Chrome MyPipCam Settings, choose a library folder (suggested:
~/Movies/MyPipCam). - In the Mac app menu bar (or bubble context menu), choose Choose Recording Library… and pick that same folder. First open suggests
~/Movies/MyPipCam. - Open Recording Library opens the native Mac window (list / play / rename / delete / Reveal in Finder).
- Use Open in Chrome… when you need the extension editor or transcription UI.
On-disk layout:
<LibraryRoot>/
.mypipcam-library
recordings/
<uuid>/
meta.json
video.webm # or video.mp4
thumb.jpg # optional
transcript.json # optional
- Drawing tools, reaction stickers, auto-zoom
- Native Mac Google Drive SDK (Chrome Drive library is enough for multi-browser sync)
MyPipCam is open source under the MIT License. Copyright © 2026 EarnYour Marketing and contributors. Published freely on GitHub — see NOTICE.
Not affiliated with Loom, OpenAI, Google, Apple, or Chrome.