Skip to content

fix: keep Windows audio capture alive after transient WASAPI errors#635

Closed
Treasure520520 wants to merge 1 commit into
webadderallorg:mainfrom
Treasure520520:fix/windows-wasapi-audio-dropout
Closed

fix: keep Windows audio capture alive after transient WASAPI errors#635
Treasure520520 wants to merge 1 commit into
webadderallorg:mainfrom
Treasure520520:fix/windows-wasapi-audio-dropout

Conversation

@Treasure520520
Copy link
Copy Markdown

@Treasure520520 Treasure520520 commented May 31, 2026

Fixes #629

This targets the Windows recordings where audio can be present for the first few seconds and then disappear while video continues recording.

What changed:

  • Treat transient WASAPI AUDCLNT_E_BUFFER_ERROR capture failures as recoverable instead of letting the audio capture path go silent/stale.
  • Continue the capture loop after recoverable buffer errors so the next valid packet can resume audio writing.
  • Preserve fatal handling for non-recoverable WASAPI failures.
  • Add recoverableWasapiErrorCount to companion audio timing metadata and stderr diagnostics so future reports can confirm whether recovery happened during the recording.

Validation:

  • npm test -- electron/ipc/recording/windowsFallbacks.test.ts electron/ipc/recording/diagnostics.test.ts
  • npm run build:windows-capture on macOS confirms the project script skips Windows helper builds off Windows. The native helper still needs a Windows build/recording check in CI or on a Windows machine.

Bounty note: this PR is submitted for the $50 bounty mentioned in #629.

Summary by CodeRabbit

  • Bug Fixes
    • Improved audio capture resilience: transient/system and microphone audio glitches are now handled without aborting capture. Recoverable capture errors are counted, warning messages and the end-of-recording timing metadata now include this recoverable error count, and repeated warnings are rate-limited to reduce log spam.

@github-actions github-actions Bot added the Slop label May 31, 2026
@github-actions
Copy link
Copy Markdown
Contributor

⚠️ This pull request has been flagged by Anti-Slop.
Our automated checks detected patterns commonly associated with
low-quality or automated/AI submissions (failure count reached).
No automatic closure — a maintainer will review it.
If this is legitimate work, please add more context, link issues, or ping us.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 31, 2026

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: bbccbe68-c156-4ade-8113-07fa51a0697d

📥 Commits

Reviewing files that changed from the base of the PR and between 37546a5 and fd1d9eb.

📒 Files selected for processing (3)
  • electron/native/wgc-capture/src/main.cpp
  • electron/native/wgc-capture/src/wasapi_loopback.cpp
  • electron/native/wgc-capture/src/wasapi_loopback.h
🚧 Files skipped from review as they are similar to previous changes (3)
  • electron/native/wgc-capture/src/wasapi_loopback.h
  • electron/native/wgc-capture/src/main.cpp
  • electron/native/wgc-capture/src/wasapi_loopback.cpp

📝 Walkthrough

Walkthrough

Audio capture now classifies certain WASAPI buffer errors as recoverable, counts and bounds recoverable warnings per session, continues capture on recoverable failures, exposes a recoverableErrorCount() accessor, and reports the count in companion JSON and end-of-recording warnings.

Changes

Recoverable WASAPI Error Handling

Layer / File(s) Summary
Public error counter & flags
electron/native/wgc-capture/src/wasapi_loopback.h
Adds recoverableErrorCount() accessor, private recoverableErrorCount_ atomic counter, and fatalError_ atomic flag to WasapiCapture.
Recoverable classification & init
electron/native/wgc-capture/src/wasapi_loopback.cpp
Adds kMaxRecoverableWasapiErrorWarnings cap and isRecoverableWasapiCaptureError(HRESULT) helper; resets recoverableErrorCount_ and clears fatalError_ in WasapiCapture::start().
Capture thread: bounded logging and tolerant paths
electron/native/wgc-capture/src/wasapi_loopback.cpp
Adds logRecoverableError lambda that atomically increments the counter and emits warnings up to the cap; updates multiple GetNextPacketSize and GetBuffer failure paths to continue/skip on recoverable errors and set fatalError_ for non-recoverable failures.
Metadata and end-of-recording warnings
electron/native/wgc-capture/src/main.cpp
writeCompanionAudioTimingMetadata writes recoverableWasapiErrorCount when non-zero; system-audio and microphone post-recording warnings include and print recoverableWasapiErrors when present.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Suggested labels

Checked

Poem

A rabbit hops through WASAPI streams,
Where buffer blips disturb the dreams.
"Recoverable!" it hums with cheer,
Counting stumbles, warnings clear.
Capture persists — small hops, not stops, 🎧🐰

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The PR title 'fix: keep Windows audio capture alive after transient WASAPI errors' directly and clearly describes the main change in the changeset.
Description check ✅ Passed The PR description covers the main sections (fixes issue #629, what changed, validation steps) but lacks complete adherence to template structure (no Type of Change checkbox, no Screenshots/Video sections).
Linked Issues check ✅ Passed The code changes directly address issue #629 by treating transient WASAPI errors as recoverable and continuing capture instead of terminating, preventing audio loss during recordings.
Out of Scope Changes check ✅ Passed All changes are in-scope: wasapi_loopback.h/cpp add recoverable error handling, main.cpp reports error counts, and all modifications directly support the objective of preventing audio dropout.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@Treasure520520
Copy link
Copy Markdown
Author

Adding a little more context because this PR touches native capture code.

The symptom in #629 is consistent with the audio capture thread stopping or no longer writing after a transient WASAPI failure while the WGC video path keeps running. In WasapiCapture::captureThread, the first GetNextPacketSize failure in the outer capture loop previously broke out of the thread entirely, which leaves the companion WAV stuck at the first captured segment.

This patch only treats AUDCLNT_E_BUFFER_ERROR as recoverable. That HRESULT is documented as a buffer/data availability problem rather than device invalidation, so the helper now waits for the next capture pass instead of ending audio capture. Non-recoverable failures still stop the audio path and get logged.

Suggested Windows validation:

  1. Build the Windows helper with npm run build:windows-capture on Windows.
  2. Record a 30-60s screen capture with system audio playing continuously.
  3. Confirm the generated .system.wav continues for the recording duration and, if recovery happened, its sidecar JSON includes recoverableWasapiErrorCount.
  4. Open the recording in the editor and confirm playback/export keeps audio past the first few seconds.

@github-actions
Copy link
Copy Markdown
Contributor

⚠️ This pull request has been flagged by Anti-Slop.
Our automated checks detected patterns commonly associated with
low-quality or automated/AI submissions (failure count reached).
No automatic closure — a maintainer will review it.
If this is legitimate work, please add more context, link issues, or ping us.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@electron/native/wgc-capture/src/wasapi_loopback.cpp`:
- Around line 443-450: The fatal-error branches in the WASAPI loop currently set
capturing_ = false which prevents WasapiCapture::stop() from joining thread_ and
finalizing the WAV header/handles; instead introduce a separate fatal latch
(e.g. atomic<bool> fatal_error_ or fatal_failure_) and set that in the
captureClient_->GetBuffer(...) and captureClient_->GetNextPacketSize(...) fatal
branches, leaving capturing_ unchanged so stop() will still run its cleanup/join
logic, or alternatively modify WasapiCapture::stop() to always join thread_ and
finalize resources even when capturing_ is false; update the loop to break on
fatal_error_ and adjust any checks that rely on capturing_ accordingly
(reference symbols: capturing_, fatal_error_ (new), WasapiCapture::stop(),
captureClient_->GetBuffer, captureClient_->GetNextPacketSize, thread_, WAV
header/handle).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 8da997e4-b072-446e-b0e8-666a32d0f444

📥 Commits

Reviewing files that changed from the base of the PR and between 1f9912b and 37546a5.

📒 Files selected for processing (3)
  • electron/native/wgc-capture/src/main.cpp
  • electron/native/wgc-capture/src/wasapi_loopback.cpp
  • electron/native/wgc-capture/src/wasapi_loopback.h

Comment thread electron/native/wgc-capture/src/wasapi_loopback.cpp
@Treasure520520 Treasure520520 force-pushed the fix/windows-wasapi-audio-dropout branch from 37546a5 to fd1d9eb Compare May 31, 2026 03:27
@github-actions
Copy link
Copy Markdown
Contributor

⚠️ This pull request has been flagged by Anti-Slop.
Our automated checks detected patterns commonly associated with
low-quality or automated/AI submissions (failure count reached).
No automatic closure — a maintainer will review it.
If this is legitimate work, please add more context, link issues, or ping us.

1 similar comment
@github-actions
Copy link
Copy Markdown
Contributor

⚠️ This pull request has been flagged by Anti-Slop.
Our automated checks detected patterns commonly associated with
low-quality or automated/AI submissions (failure count reached).
No automatic closure — a maintainer will review it.
If this is legitimate work, please add more context, link issues, or ping us.

@Treasure520520
Copy link
Copy Markdown
Author

Follow-up from review:

  • Addressed CodeRabbit's cleanup concern by adding a separate fatalError_ latch instead of setting capturing_ = false from fatal WASAPI branches. This keeps WasapiCapture::stop() responsible for joining the thread and finalizing the WAV header/handle.
  • Re-ran git diff --check.
  • Re-ran npm test -- electron/ipc/recording/windowsFallbacks.test.ts electron/ipc/recording/diagnostics.test.ts — 19 tests passed.
  • npm run build:windows-capture still correctly skips on macOS; Windows host validation remains the remaining environment-specific check.

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

The video occasionally loses sound.

2 participants