Skip to content

feat: add meeting transcription for macOS#788

Open
aj47 wants to merge 3 commits into
mainfrom
feat/meeting-transcription-macos
Open

feat: add meeting transcription for macOS#788
aj47 wants to merge 3 commits into
mainfrom
feat/meeting-transcription-macos

Conversation

@aj47

@aj47 aj47 commented Dec 26, 2025

Copy link
Copy Markdown
Owner

Summary

Adds meeting transcription functionality for macOS that captures both microphone audio (user's voice) and system audio (meeting participants from Zoom, Meet, Teams, etc.).

Changes

Core Implementation

  • electron-audio-loopback: Added package for system audio capture using Chromium's built-in audio loopback
  • MeetingRecorder class: New renderer-side recorder that captures and mixes mic + system audio streams
  • createMeetingTranscription TIPC route: Backend route that sends combined audio to existing STT providers (OpenAI/Groq)

UI

  • Meeting Transcription page: New page accessible from sidebar with recording controls
  • MeetingTranscriptionPanel component: Recording UI with audio visualizer, duration display, and start/stop controls
  • Navigation: Added "Meeting" link to sidebar navigation

Requirements

  • macOS 12.3 (Monterey) or later
  • Screen recording permission (required for system audio capture)
  • Configured STT provider (OpenAI or Groq API key)

How it Works

  1. Uses electron-audio-loopback to enable Chromium's internal audio loopback flags
  2. Captures microphone via getUserMedia()
  3. Captures system audio via getDisplayMedia() with loopback enabled
  4. Mixes both streams using Web Audio API
  5. Records to WebM and sends to transcription provider

Files Changed

  • apps/desktop/package.json - Added electron-audio-loopback dependency
  • apps/desktop/src/main/index.ts - Initialize audio loopback before app ready
  • apps/desktop/src/main/tipc.ts - Added createMeetingTranscription route
  • apps/desktop/src/preload/index.ts - Exposed loopback IPC methods
  • apps/desktop/src/renderer/src/lib/meeting-recorder.ts - New MeetingRecorder class
  • apps/desktop/src/renderer/src/components/meeting-transcription-panel.tsx - New UI component
  • apps/desktop/src/renderer/src/pages/meeting-transcription.tsx - New page
  • apps/desktop/src/renderer/src/router.tsx - Added route
  • apps/desktop/src/renderer/src/components/app-layout.tsx - Added nav link

Pull Request opened by Augment Code with guidance from the PR author

- Add electron-audio-loopback package for system audio capture
- Create MeetingRecorder class to capture mic + system audio
- Add createMeetingTranscription TIPC route
- Create Meeting Transcription UI page and navigation
- Requires macOS 12.3+ for system audio capture via Chromium loopback
@augmentcode

augmentcode Bot commented Dec 26, 2025

Copy link
Copy Markdown
🤖 Augment PR Summary

Summary: Adds a macOS-only “Meeting Transcription” flow that records both microphone input and system (loopback) audio, then transcribes the combined recording via the existing STT providers.

Changes:

  • Adds electron-audio-loopback and initializes it in the main process (guarded with try/catch) before app.whenReady().
  • Exposes loopback enable/disable methods via preload so the renderer can temporarily toggle Chromium loopback behavior.
  • Introduces a renderer-side MeetingRecorder that captures mic + display/system audio, mixes streams via Web Audio, and records to WebM (with duration/size safety limits).
  • Adds a new TIPC route createMeetingTranscription that posts the WebM audio to OpenAI/Groq transcription, post-processes the text, and stores it in recordings history.
  • Adds a Meeting Transcription page/panel UI plus router + sidebar navigation entry (shown only on macOS).

Technical Notes: Requires macOS 12.3+ and Screen Recording permission; system audio capture uses getDisplayMedia() with loopback enabled and discards video tracks.

🤖 Was this summary useful? React with 👍 or 👎

@augmentcode augmentcode Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review completed. 4 suggestions posted.

Fix All in Augment

Comment augment review to trigger a new review at any time.

Comment thread apps/desktop/src/main/index.ts Outdated
// Must be called before app.whenReady()
import { initMain as initAudioLoopback } from "electron-audio-loopback"
if (process.platform === "darwin") {
initAudioLoopback()

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If initAudioLoopback() throws (unsupported OS version / Electron flags / packaging issues), this top-level call will prevent the app from starting; consider guarding it so meeting transcription failure doesn’t take down the whole app.

Fix This in Augment

🤖 Was this useful? React with 👍 or 👎

if (this.mediaRecorder && this.mediaRecorder.state !== "inactive") {
this.mediaRecorder.stop()
}
this.cleanup()

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

stopRecording() calls cleanup() immediately after MediaRecorder.stop(), which stops tracks/closes the AudioContext and also nulls this.mediaRecorder before onstop runs; this can lead to truncated/empty blobs and losing the recorder mimeType (also makes the existing empty-blob warning more likely).

Fix This in Augment

🤖 Was this useful? React with 👍 or 👎

}
})

recorder.on("error", (err) => {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the "error" handler, the duration interval isn’t cleared/reset, so the timer can keep running (and updating state) after an error mid-recording.

Fix This in Augment

🤖 Was this useful? React with 👍 or 👎

icon: "i-mingcute-server-line",
},
{
text: "Meeting",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The “Meeting” nav link is shown on all platforms, but the implementation is macOS-specific (and loopback IPC isn’t initialized off-darwin); consider hiding/disabled UI on non-macOS to avoid a broken route/UX.

Fix This in Augment

🤖 Was this useful? React with 👍 or 👎

- Guard initAudioLoopback() with try-catch to prevent app crash on init failure
- Fix stopRecording() cleanup timing to avoid truncating recordings
- Clear duration interval in error handler to prevent timer from continuing
- Hide Meeting nav link on non-macOS platforms

Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
@aj47

aj47 commented Dec 26, 2025

Copy link
Copy Markdown
Owner Author

augment review

@augmentcode augmentcode Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review completed. 1 suggestions posted.

Fix All in Augment

Comment augment review to trigger a new review at any time.

audioBitsPerSecond: 128000,
})

let audioChunks: Blob[] = []

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since meetings can be long, buffering all audioChunks in memory until onstop can grow large and risk OOM/hangs in the renderer. Consider adding some kind of duration/size guard or incremental persistence (also applies to the later blob.arrayBuffer() IPC transfer).

Fix This in Augment

🤖 Was this useful? React with 👍 or 👎

- Add maximum recording duration limit (2 hours)
- Add maximum recording size limit (500 MB)
- Emit 'max-duration-reached' event when limits are reached
- Auto-stop recording and save transcription when limits are hit
- Clear duration check interval on cleanup

Addresses PR review feedback about OOM risk for long meetings.

Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
@aj47

aj47 commented Dec 26, 2025

Copy link
Copy Markdown
Owner Author

augment review

@augmentcode augmentcode Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review completed. No suggestions at this time.

Comment augment review to trigger a new review at any time.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant