Skip to content

fix(windows): apply live microphone gain and mute#120

Merged
TheOrcDev merged 1 commit into
mainfrom
codex/issue-117-windows-live-mic-controls
Jul 14, 2026
Merged

fix(windows): apply live microphone gain and mute#120
TheOrcDev merged 1 commit into
mainfrom
codex/issue-117-windows-live-mic-controls

Conversation

@TheOrcDev

@TheOrcDev TheOrcDev commented Jul 14, 2026

Copy link
Copy Markdown
Owner

Problem

Windows microphones are captured directly by FFmpeg through DirectShow. Initial gain/mute values were baked into the FFmpeg filter graph, while Videorc's live update RPC only knew how to update the in-process CoreAudio capture path. A Windows recording therefore returned native-audio-unavailable, rolled the controls back, and showed the warning from #117 even though microphone capture itself was healthy.

The System Audio placeholder shown in the issue is a separate missing native adapter; it is not the cause of the microphone control failure.

Plan and implementation

  • Give every FFmpeg-owned microphone volume filter a stable volume@videorc_live_mic command target, including neutral-gain sessions.
  • Retain FFmpeg stdin only for session shapes that need it and use FFmpeg's broadcast filter-command protocol so record, stream, and split-output graphs update together.
  • Parse command acknowledgements from stderr and report success only after every matching output graph returns ret:0.
  • Keep command serialization session-scoped instead of holding the global recording mutex while waiting for FFmpeg. The acknowledgement deadline is 5 seconds because production FFmpeg polls stdin on its 2-second stats cadence; the previous 2-second boundary could expire after the command had already applied.
  • Coalesce continuous slider edits in the renderer with a one-in-flight/latest-wins queue: at most the active command and the newest complete gain/mute state survive, and pending work is retired at the session stop edge.
  • Publish the authoritative stopping state before waiting on command I/O; prevent delayed updates from crossing the stop edge; preserve FIFO-owned shutdown for encoder-bridge sessions.
  • If one output rejects a command, attempt and verify rollback across all outputs and return the backend-confirmed rollback values. If timeout, transport loss, channel loss, or rollback failure makes the captured state uncertain, keep that unknown state sticky, disable live edits, and show explicit state-unknown guidance instead of claiming restoration.
  • Count live-control targets only in actual FFmpeg audio-filter arguments so an output path or stream key containing the filter name cannot create phantom acknowledgements.
  • Add a maintained artifact probe that applies +6 dB, mute, and unmute to two simultaneous outputs, deliberately writes just after production's progress=continue boundary, proves acknowledgement crosses the unsafe legacy 2-second deadline but stays below 5 seconds, and verifies both finished WAV artifacts with FFmpeg.
  • Run that probe in the recording-studio gate and against the bundled FFmpeg in hosted Windows CI.
  • Update the Windows port plan's current capability statement to record acknowledged, coalesced live gain/mute support while keeping System Audio out of scope.

FFmpeg command-loop behavior is grounded in the upstream implementation: https://www.ffmpeg.org/doxygen/8.0/ffmpeg_8c_source.html

Acceptance criteria

  • Windows DirectShow mic graphs always expose a stable live-control target.
  • Gain, mute, and unmute update every active output graph without restarting capture.
  • The backend acknowledges success only after every expected FFmpeg reply succeeds.
  • A slider drag cannot build a FIFO of stale multi-second commands; only the newest pending settings survive.
  • Stop intent/status is not blocked by a missing command acknowledgement.
  • Delayed updates cannot write after the session stop edge.
  • Confirmed rollback values, controller-unavailable state, and unknown captured state produce distinct truthful UI outcomes; a lost RPC response never claims restoration.
  • Existing CoreAudio live controls retain their in-process behavior.
  • Encoder-bridge sessions without live FFmpeg targets retain their previous null-stdin lifecycle.

Verification

  • Focused Rust controller, routing, rollback, stop-race, filter-construction, parser, and real-WebSocket dispatcher tests; the transport suite proves prompt stop dispatch, bounded busy rejection, ordinary barriers, and late ID-correlated replies.
  • Maintained two-output FFmpeg artifact probe (+6 dB -> mute -> unmute): acknowledgements took 2004/2000/2000ms against the 5-second deadline, and both WAVs measured -18.1 -> -12.1 -> -91.0 -> -18.1 dB.
  • Desktop unit suite (1042 passed, 1 skipped), Node script suite (619 passed), TypeScript typecheck/lint/format, and desktop production build.
  • Rust format, clippy with warnings denied, full backend suite (1269 passed, 8 ignored, one unrelated test skipped), and Windows cross-check (pass with the existing target-only warnings).
  • Active-session live-layout record and record+stream artifacts passed with a valid local RTMP capture.
  • pnpm smoke:recording-studio was run; see Known gate blockers below.

Known gate blockers

  • The existing native-preview portrait-resize test/source-loop currently renders 476x847 while leaving the Metal target at 960x540 instead of adopting portrait output; the identical failure reproduces from the preview-untouched comparison branch and prevents the aggregate recording-studio command from reaching its final steps.
  • Physical DirectShow microphone validation is not possible from this macOS host. Hosted Windows CI exercises the packaged FFmpeg command path; final alpha acceptance should also record a real Windows microphone while changing gain, muting, unmuting, and stopping during a queued update.

Non-goals and follow-up

Closes #117

Summary by CodeRabbit

  • New Features

    • Added live microphone gain and mute controls for FFmpeg-based Windows capture.
    • Changes are applied in order, with rapid updates consolidated to the latest setting.
    • Added confirmation and rollback handling when microphone changes cannot be verified.
    • Added a Windows smoke probe to validate gain, mute, and unmute behavior.
  • Bug Fixes

    • Improved session shutdown ordering and handling of unavailable or uncertain microphone controls.
    • Prevented stale updates from overriding newer microphone settings.

@coderabbitai

coderabbitai Bot commented Jul 14, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 5767e2f7-dbd1-4902-ba88-0a76f94bb0fa

📥 Commits

Reviewing files that changed from the base of the PR and between 4dabc59 and 11606be.

📒 Files selected for processing (13)
  • .github/workflows/windows.yml
  • apps/desktop/src/renderer/src/hooks/use-studio.tsx
  • apps/desktop/src/renderer/src/lib/live-audio-processing.test.ts
  • apps/desktop/src/renderer/src/lib/live-audio-processing.ts
  • apps/desktop/src/shared/backend.ts
  • crates/videorc-backend/src/main.rs
  • crates/videorc-backend/src/protocol.rs
  • crates/videorc-backend/src/recording.rs
  • docs/windows-port-plan.md
  • package.json
  • scripts/lib/recording-studio-gates.mjs
  • scripts/lib/recording-studio-gates.test.mjs
  • scripts/probe-live-audio-controls.mjs

📝 Walkthrough

Walkthrough

Live microphone gain and mute control now runs through acknowledged FFmpeg commands, latest-wins renderer scheduling, bounded backend dispatch, rollback handling, and Windows installer smoke validation.

Changes

Live microphone controls

Layer / File(s) Summary
Settlement contracts and latest-wins queue
apps/desktop/src/renderer/src/lib/live-audio-processing.*, apps/desktop/src/shared/backend.ts
Update results include confirmed microphone state; queued edits coalesce, settle asynchronously, and handle rollback or unknown-state outcomes.
FFmpeg live control session
crates/videorc-backend/src/recording.rs, crates/videorc-backend/src/protocol.rs
Named FFmpeg volume filters accept acknowledged gain/mute commands, parse replies, report confirmed state, and coordinate recording shutdown.
Bounded dispatch and stop ordering
crates/videorc-backend/src/main.rs
Audio updates use a single-flight lane, busy requests fail immediately, ordinary commands wait for acknowledgements, and session stop bypasses that wait.
Renderer session synchronization
apps/desktop/src/renderer/src/hooks/use-studio.tsx
The studio hook binds queues to active sessions, avoids redundant updates, disables failed sessions, and stops queued work during teardown.
Windows probe and rollout documentation
scripts/probe-live-audio-controls.mjs, scripts/lib/recording-studio-gates.*, .github/workflows/windows.yml, package.json, docs/windows-port-plan.md
A scripted FFmpeg audio probe validates gain, mute, unmute, acknowledgements, and timing in Windows installer CI; the port plan documents the updated behavior.

Estimated code review effort: 5 (Critical) | ~120 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Studio
  participant Backend
  participant FFmpeg
  participant SmokeProbe
  Studio->>Backend: enqueue latest gain/mute update
  Backend->>FFmpeg: send live volume command
  FFmpeg-->>Backend: return command acknowledgement
  Backend-->>Studio: return applied or confirmed rollback state
  SmokeProbe->>FFmpeg: run live control probe
  FFmpeg-->>SmokeProbe: produce acknowledgements and audio artifacts
Loading

Possibly related PRs

  • TheOrcDev/videorc#38: Adds the Windows workflow foundation extended here with the live-microphone smoke probe.
  • TheOrcDev/videorc#72: Introduced related audio-processing update protocol and renderer synchronization paths.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/issue-117-windows-live-mic-controls

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint install failed: private package registry requires authentication. Disable ESLint in CodeRabbit settings or use public packages.


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.

@TheOrcDev TheOrcDev marked this pull request as ready for review July 14, 2026 07:41
@TheOrcDev TheOrcDev merged commit d79b068 into main Jul 14, 2026
3 of 5 checks passed
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.

Windows - Live Mic Controls Unavailable

1 participant