Save recordings before transcription#1024
Conversation
97eaaac to
47f44a8
Compare
|
Let's not do the ORT error fix here. We should be adding an option to transcribe-rs to do chunking. This is code which should be broadly applicable not just for Handy It will also keep this PR more focused |
|
Dropped the ORT split-retry commit from this PR to keep it focused on the durability/history fix. I kept local notes and a preserved branch for a follow-up chunking/chunked-transcription pass in transcribe-rs. |
VirenMohindra
left a comment
There was a problem hiding this comment.
minor nits, i think we can reduce the blast radius if we add back the comments + would be easier to review
| }, | ||
| async retryHistoryEntryTranscription(id: number) : Promise<Result<null, string>> { | ||
| try { | ||
| return { status: "ok", data: await TAURI_INVOKE("retry_history_entry_transcription", { id }) }; |
There was a problem hiding this comment.
needs a rerun of codegen + bun run format to fix
| error!("Failed to run paste on main thread: {:?}", e); | ||
| } | ||
|
|
||
| if processed.final_text.is_empty() { |
There was a problem hiding this comment.
when processed.final_text.is_empty(), the code silently hides the overlay and does nothing else but complete_transcription() was already called with an empty string, leaving the entry as status=Completed, transcription_text="". In the UI this shows as a successful entry with no text and users can't distinguish "completed but empty" from "failed." we should either call fail_transcription() with a descriptive error or skip complete_transcription() entirely for empty results
| crate::settings::RecordingRetentionPeriod::Days3 => now - (3 * 24 * 60 * 60), // 3 days in seconds | ||
| crate::settings::RecordingRetentionPeriod::Weeks2 => now - (2 * 7 * 24 * 60 * 60), // 2 weeks in seconds | ||
| crate::settings::RecordingRetentionPeriod::Months3 => now - (3 * 30 * 24 * 60 * 60), // 3 months in seconds (approximate) |
There was a problem hiding this comment.
nit: would it be possible to avoid blowing this diff up and avoid removing comments? would be easier to review
|
I think I have some inflight changes for this PR |
VirenMohindra
left a comment
There was a problem hiding this comment.
some misc UI fixes ordered in terms of prio~
- the retry button shows on completed entries and should only appear when
!hasTranscription - content area shows "Transcription failed" during retry and should instead swap to a loading state
- delete btn stays enabled during retry, and will be a possible race condition if you delete while retranscribing
i think we should do a proper UI pass before this lands
| } else { | ||
| // Save WAV concurrently with transcription | ||
| let sample_count = samples.len(); | ||
| let file_name = format!("handy-{}.wav", chrono::Utc::now().timestamp()); |
There was a problem hiding this comment.
lets use a uuid here instead. timestamp is a second class citizen and two recordings within the same second will overwrite each other
or even chrono::Utc::now().timestamp_nanos_opt().unwrap_or_else(|| chrono::Utc::now().timestamp_micros()) but il lean towards uuids
src-tauri/src/actions.rs
Outdated
| .await; | ||
|
|
||
| // Save to history if WAV was saved and transcription is non-empty | ||
| if wav_saved && !transcription.is_empty() { |
There was a problem hiding this comment.
orphaned wav files when there is silent audio and no transcription and then cleanup_old_entries won't touch it
the error path below this correctly writes an empty DB row for retry and the empty-transcription path should do the same
src-tauri/src/actions.rs
Outdated
| // Verify: 44-byte header + num_samples * 2 bytes (16-bit) | ||
| let expected_size = 44 + (sample_count * 2) as u64; |
There was a problem hiding this comment.
seems a bit fragile, rereading the header with WavReader::open and comparing sample counts is prob more robust
src-tauri/src/commands/history.rs
Outdated
|
|
||
| transcription_manager.initiate_model_load(); | ||
|
|
||
| match transcription_manager.transcribe(samples) { |
There was a problem hiding this comment.
lets wrap this with tauri::async_runtime::spawn_blocking if possible
this can run for 5 to 30s depending on model and hardware. calling it directly inside an async fn would block the thread for the entire time
src-tauri/src/commands/history.rs
Outdated
| history_manager | ||
| .update_transcription( | ||
| id, | ||
| transcription, | ||
| processed.post_processed_text, | ||
| processed.post_process_prompt, | ||
| ) |
There was a problem hiding this comment.
UI has no way to distinguish "retry succeeded with silence" from the original failed state and the user will retry again with the same result indefinitely
we should prob return an error when transcription.is_empty() so the fe can show a meaningful state
|
I think retry should be for everything, mainly if you want to re-transcribe with another model or you picked the wrong language (happens to me all the time) Otherwise other 2 I agree |
|
also please add screenshots to the PR |
- Save recordings before transcription to prevent data loss on crash (cjpais#1024) - Linux Wayland titlebar: disable decorations for custom titlebar (cjpais#1042) - Add change_secondary_selected_language_setting command (cjpais#1106 gap) - Fix CLI --auto-submit key type being ignored (cjpais#1099 bug)
|
@VirenMohindra let me know what you think of the current set of changes. Not sure if the original author will jump in, but I think things are doing okay right now. Would love a second opinion |
🧪 Test Build ReadyBuild artifacts for PR #1024 are available for testing. Download artifacts from workflow run Artifacts expire after 30 days. |
There was a problem hiding this comment.
LGTM, the ui feedback is addressed, thanks. the spawn_blocking and filename collision are worth fixing before this lands because both are easy changes and the former can stall the runtime for 30s+
the header sample count check and empty transcription handling can be follow-ups if needed
|
thx for getting this across the finish line @cjpais & @VirenMohindra !! |

Summary
This PR fixes the data-loss path where a recording could disappear if transcription failed.
Save recordings before transcription
pending,completed, andfailedstatestranscription_errorTesting
bun run buildcargo check -j 1