mirror of
https://github.com/vee1e/meeticulous.git
synced 2026-09-01 10:18:39 +00:00
fix(recording): capture mic alongside system audio
Mic callbacks returned early when the system-audio tap was live, so your own voice was never transcribed or recorded. Always run the mic writer; it feeds the STT buffer in both modes and writes the WAV only when the system tap is unavailable (mic-only).
This commit is contained in:
parent
51b8c4a272
commit
c2a3e60eee
1 changed files with 17 additions and 21 deletions
|
|
@ -177,9 +177,9 @@ pub async fn start_recording(
|
|||
#[cfg(not(target_os = "macos"))]
|
||||
let system_audio = ();
|
||||
|
||||
// Mic: only feed the STT buffer when system audio is unavailable.
|
||||
// When system tap is live, it already captures meeting playback; mixing both
|
||||
// into one stream desyncs the timeline. Mic is still opened for diagnostics.
|
||||
// Mic is always captured: it feeds the STT buffer even when the system tap
|
||||
// is live (your voice is transcribed alongside meeting playback). When the
|
||||
// system tap is unavailable, mic becomes the sole source for the WAV too.
|
||||
#[cfg(target_os = "macos")]
|
||||
let system_up = system_audio.is_some();
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
|
|
@ -212,7 +212,7 @@ pub async fn start_recording(
|
|||
let _ = (cap.sample_rate, cap.channels);
|
||||
if system_up {
|
||||
let mut d = diagnostics.lock().unwrap();
|
||||
d.push_log("mic open for presence; STT uses SYSTEM AUDIO only (meeting playback)");
|
||||
d.push_log("mic open + feeding STT (your voice captured alongside system audio)");
|
||||
}
|
||||
(cap.stream, cap.writer)
|
||||
}
|
||||
|
|
@ -311,7 +311,6 @@ fn start_cpal_capture(
|
|||
channels,
|
||||
from_rate: sample_rate,
|
||||
to_rate: target_rate,
|
||||
system_up,
|
||||
};
|
||||
let stream = match config.sample_format() {
|
||||
cpal::SampleFormat::F32 => build_stream_f32(&device, &stream_config, capture)?,
|
||||
|
|
@ -320,20 +319,15 @@ fn start_cpal_capture(
|
|||
other => anyhow::bail!("unsupported sample format: {other:?}"),
|
||||
};
|
||||
// Writer thread drains WAV + STT feed off the audio thread. Start before
|
||||
// play() so no mic chunk is ever dropped. When system audio is up the mic
|
||||
// callback returns immediately and no writer thread is needed.
|
||||
let writer = if system_up {
|
||||
None
|
||||
} else {
|
||||
std::thread::Builder::new()
|
||||
.name("meeticulous-mic-writer".into())
|
||||
.spawn(move || mic_writer_loop(rx, wav_writer, stt_samples, target_rate))
|
||||
.ok()
|
||||
};
|
||||
// play() so no mic chunk is ever dropped.
|
||||
let writer = std::thread::Builder::new()
|
||||
.name("meeticulous-mic-writer".into())
|
||||
.spawn(move || mic_writer_loop(rx, wav_writer, stt_samples, target_rate, system_up))
|
||||
.ok();
|
||||
stream.play()?;
|
||||
{
|
||||
let mut d = diag.lock().unwrap();
|
||||
d.push_log("mic stream playing (mixed with system when available)");
|
||||
d.push_log("mic stream playing (fed to STT; WAV source when system tap is down)");
|
||||
}
|
||||
Ok(MicCapture {
|
||||
stream: Some(stream),
|
||||
|
|
@ -360,7 +354,6 @@ struct CaptureContext {
|
|||
channels: u16,
|
||||
from_rate: u32,
|
||||
to_rate: u32,
|
||||
system_up: bool,
|
||||
}
|
||||
|
||||
impl CaptureContext {
|
||||
|
|
@ -381,9 +374,12 @@ fn mic_writer_loop(
|
|||
wav_writer: LiveWavWriter,
|
||||
stt_samples: Arc<Mutex<Vec<f32>>>,
|
||||
sample_rate: u32,
|
||||
system_up: bool,
|
||||
) {
|
||||
while let Ok(chunk) = rx.recv() {
|
||||
append_wav_samples(&wav_writer, &chunk);
|
||||
if !system_up {
|
||||
append_wav_samples(&wav_writer, &chunk);
|
||||
}
|
||||
if let Ok(mut feed) = stt_samples.lock() {
|
||||
extend_stt_feed(&mut feed, &chunk, sample_rate);
|
||||
}
|
||||
|
|
@ -399,7 +395,7 @@ fn build_stream_f32(
|
|||
let stream = device.build_input_stream(
|
||||
config,
|
||||
move |data: &[f32], _| {
|
||||
if capture.stop_flag.load(Ordering::Relaxed) || capture.system_up {
|
||||
if capture.stop_flag.load(Ordering::Relaxed) {
|
||||
return;
|
||||
}
|
||||
let mono = capture.mono_chunk(data);
|
||||
|
|
@ -420,7 +416,7 @@ fn build_stream_i16(
|
|||
let stream = device.build_input_stream(
|
||||
config,
|
||||
move |data: &[i16], _| {
|
||||
if capture.stop_flag.load(Ordering::Relaxed) || capture.system_up {
|
||||
if capture.stop_flag.load(Ordering::Relaxed) {
|
||||
return;
|
||||
}
|
||||
let f: Vec<f32> = data.iter().map(|&s| s as f32 / i16::MAX as f32).collect();
|
||||
|
|
@ -442,7 +438,7 @@ fn build_stream_u16(
|
|||
let stream = device.build_input_stream(
|
||||
config,
|
||||
move |data: &[u16], _| {
|
||||
if capture.stop_flag.load(Ordering::Relaxed) || capture.system_up {
|
||||
if capture.stop_flag.load(Ordering::Relaxed) {
|
||||
return;
|
||||
}
|
||||
let f: Vec<f32> = data
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue