From 22e0f006908fc13a77996dbd227d23ac374bf870 Mon Sep 17 00:00:00 2001 From: Kresna Date: Tue, 21 Jul 2026 20:43:20 +0700 Subject: [PATCH] fix(recording): capture audio and mux it correctly (silent recordings) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two bugs made every recording come out silent: 1. TauriCaptureService.startRecording dropped includeAudio/systemAudio before the IPC call, so Rust never started the AudioRecorder. Now forwarded. 2. The mux always used -c:a aac, but WebM (the default output) can't hold AAC — it needs Opus, so the mux failed and left a video-only file. Pick the audio codec by container: mp4 → aac, webm → libopus. Also fixes a build break: the [lints.rust] check-cfg form added earlier is invalid on current rustc (errored with "invalid --check-cfg argument"); switched to `unexpected_cfgs = "allow"`. macOS builds clean (0 warnings); 385 JS tests pass. Needs a mic-enabled recording on hardware to confirm audio lands in the file. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_013dqouzFP8vy9jaKhTDFj5H --- src-tauri/Cargo.toml | 6 +++--- src-tauri/src/audio.rs | 10 +++++++++- src/services/capture/tauri.ts | 4 ++++ 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 04a3435..619d4cb 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -41,6 +41,6 @@ default = ["custom-protocol"] custom-protocol = ["tauri/custom-protocol"] [lints.rust] -# The `objc` crate's msg_send! macro expands to a `cfg(cargo-clippy)` check; -# declare it as a known cfg so it doesn't trip the unexpected_cfgs lint. -unexpected_cfgs = { level = "warn", check-cfg = ['cfg(cargo-clippy)'] } +# The `objc` crate's msg_send! macro references a `cargo-clippy` cfg that trips +# the unexpected_cfgs lint — it's from the dependency macro, not our code. +unexpected_cfgs = "allow" diff --git a/src-tauri/src/audio.rs b/src-tauri/src/audio.rs index 29179ef..7c2d11e 100644 --- a/src-tauri/src/audio.rs +++ b/src-tauri/src/audio.rs @@ -76,13 +76,21 @@ impl AudioRecorder { output_path.display() ); + // The captured audio is AAC, but the container dictates the codec: + // WebM (VP9) can't hold AAC — it needs Opus; MP4 takes AAC. Using the + // wrong codec makes the mux fail, leaving a silent video-only file. + let audio_codec = match format { + "mp4" => "aac", + _ => "libopus", // webm + }; + let status = Command::new(ffmpeg_path()) .args([ "-y", "-i", &video_path.to_string_lossy(), "-i", &audio_path.to_string_lossy(), "-c:v", "copy", - "-c:a", "aac", + "-c:a", audio_codec, "-shortest", &output_path.to_string_lossy(), ]) diff --git a/src/services/capture/tauri.ts b/src/services/capture/tauri.ts index a7d99eb..c8b8c14 100644 --- a/src/services/capture/tauri.ts +++ b/src/services/capture/tauri.ts @@ -66,6 +66,10 @@ export class TauriCaptureService implements CaptureService { fps: options?.fps, displayId: options?.displayId, bounds: options?.bounds, + // Without these the Rust side never starts the audio recorder, + // so recordings came out silent. + includeAudio: options?.includeAudio, + systemAudio: options?.systemAudio, }, });