fix(A.2 #19): only report audio_path when the WAV writer finalises cleanly

Review feedback: reported_audio_path was cached at writer-open time
and survived a mid-session writer drop. If an append error cleared
wav_writer (or hound's Drop ran instead of finalize), the Summary
still reported the path — risking StopLiveTranscriptionResponse
pointing at a file whose header did not reflect its data chunk.

Moves the decision to end-of-session. wav_writer.take() is inspected:
- writer present + finalize Ok → report the path,
- writer present + finalize Err → None, emit a Warning,
- writer absent (mid-session drop, or never opened) → None.

StopLiveTranscriptionResponse.audio_path now means "the recording is
known-good" rather than "a recording was attempted". Users can still
recover partial files via filesystem if needed; the warning toasts
already emitted by append_resampled_audio on write failure surface
that path implicitly.
This commit is contained in:
2026-04-22 04:54:15 +01:00
parent e4adcc1832
commit 6f4adae56c

View File

@@ -402,15 +402,12 @@ fn run_live_session(
},
None => None,
};
// Resolve the reported audio_path only if the writer actually
// opened; otherwise the returned Summary must not claim a path.
let reported_audio_path: Option<String> = if wav_writer.is_some() {
audio_path
.as_ref()
.map(|p| p.to_string_lossy().to_string())
} else {
None
};
// `reported_audio_path` is decided at end-of-session based on
// whether the writer finalised successfully, not at open time.
// This way a writer that dies mid-session (append error clearing
// wav_writer, or finalise returning Err) does not leak a stale
// path back to the frontend that might point to a file whose
// header is out of sync with its data chunk.
let mut buffer_start_sample: u64 = 0;
let mut dropped_audio_ms: u64 = 0;
@@ -552,23 +549,32 @@ fn run_live_session(
thread::sleep(Duration::from_millis(10));
}
// Finalise the progressive WAV writer so the terminal header
// reflects every written sample. A failure here leaves the last
// flushed header state on disk — still a playable WAV — so we
// report a warning but don't fail the whole session.
if let Some(writer) = wav_writer.take() {
if let Err(e) = writer.finalize() {
let _ = status_channel.send(LiveStatusMessage::Warning {
session_id,
message: format!("WAV finalise failed: {e}; partial recording is still playable."),
});
}
}
// Finalise the progressive WAV writer and decide whether to
// report a path to the frontend. Only a clean finalise produces a
// reported path: a writer that died mid-session (wav_writer was
// already None) or a finalise that itself errored both yield
// `None`, so `StopLiveTranscriptionResponse.audio_path` reflects
// "recording is known-good" rather than "recording was attempted".
let audio_path = match wav_writer.take() {
Some(writer) => match writer.finalize() {
Ok(()) => audio_path.as_ref().map(|p| p.to_string_lossy().to_string()),
Err(e) => {
let _ = status_channel.send(LiveStatusMessage::Warning {
session_id,
message: format!(
"WAV finalise failed: {e}. A partial recording may still be on disk from earlier flushes."
),
});
None
}
},
None => None,
};
Ok(LiveSessionSummary {
session_id,
dropped_audio_ms,
audio_path: reported_audio_path,
audio_path,
})
}