Skip to content

Start transcription before capture-session teardown#266

Open
swimmer-303 wants to merge 2 commits into
zachlatta:mainfrom
swimmer-303:split/start-transcription
Open

Start transcription before capture-session teardown#266
swimmer-303 wants to merge 2 commits into
zachlatta:mainfrom
swimmer-303:split/start-transcription

Conversation

@swimmer-303

@swimmer-303 swimmer-303 commented Jul 11, 2026

Copy link
Copy Markdown

Split out from #254.

AVCaptureSession.stopRunning() can take 100–300 ms and ran before the stop completion fired. The audio cut-off point (sample-buffer delegate removal) and the queued-tail drain are byte-for-byte unchanged; only the slow teardown now happens after the completion, so the upload starts immediately.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Improvements
    • Reduced stop-to-paste latency by beginning transcription upload immediately when recording stops.
    • Improved recording completion by preserving queued audio data before finalizing the recording and releasing capture resources.

AVCaptureSession.stopRunning() can take 100-300ms and ran before the
stop completion fired, delaying the transcription upload. The audio
cut-off point (sample buffer delegate removal) and the queued-tail
drain are unchanged; only the slow session teardown now happens after
the completion.

(cherry picked from commit 462f741)
@coderabbitai

coderabbitai Bot commented Jul 11, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Recording shutdown now removes the audio sample-buffer delegate before draining queued buffers, finalizes the audio file, and tears down the capture session afterward. The changelog documents the reduced stop-to-paste latency.

Changes

Audio stop lifecycle

Layer / File(s) Summary
Stop-recording drain and teardown ordering
Sources/AudioRecorder.swift, CHANGELOG.md
stopRecording cuts off delegate delivery before finalizing queued audio buffers, then tears down the session; the changelog records the latency improvement.

Estimated code review effort: 2 (Simple) | ~10 minutes

Sequence Diagram(s)

sequenceDiagram
  participant stopRecording
  participant AVCaptureAudioDataOutput
  participant AudioFile
  participant CaptureSession
  stopRecording->>AVCaptureAudioDataOutput: Remove sample-buffer delegate
  stopRecording->>AudioFile: Finish and drain queued buffers
  stopRecording->>CaptureSession: Tear down session
  stopRecording-->>stopRecording: Dispatch completion with output URL
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main change: starting transcription before capture-session teardown to reduce stop-to-paste latency.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
Sources/AudioRecorder.swift (1)

692-697: 🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

cleanup() called synchronously from error-path completions will block the main thread during deferred teardown.

teardownSessionLocked() at line 697 runs on the session queue concurrently with the completion handler. In AppState.stopAndTranscribe, the error and cancelled paths call self.audioRecorder.cleanup() synchronously inside the completion. Since cleanup() uses sessionQueue.sync when off the session queue, it blocks the main thread for 100–300 ms while session.stopRunning() executes — causing a UI freeze in those paths. The success path is unaffected (transcription starts via Task, cleanup() is deferred).

Previously, teardown completed before the completion fired, so cleanup() never blocked. Consider switching cleanup() to sessionQueue.async to avoid the freeze — no downstream caller depends on synchronous file removal.

🔧 Proposed fix for cleanup()
 func cleanup() {
     let cleanup = {
         if let url = self.tempFileURL {
             try? FileManager.default.removeItem(at: url)
             self.tempFileURL = nil
         }
     }
 
     if DispatchQueue.getSpecific(key: Self.sessionQueueKey) != nil {
         cleanup()
     } else {
-        sessionQueue.sync(execute: cleanup)
+        sessionQueue.async(execute: cleanup)
     }
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Sources/AudioRecorder.swift` around lines 692 - 697, Change cleanup() to
perform session teardown asynchronously via sessionQueue.async rather than
synchronously with sessionQueue.sync, ensuring callers such as
AppState.stopAndTranscribe error and cancellation completions do not block the
main thread while session.stopRunning() executes. Preserve the existing cleanup
and file-removal behavior, and verify teardown remains serialized with other
session operations.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@Sources/AudioRecorder.swift`:
- Around line 692-697: Change cleanup() to perform session teardown
asynchronously via sessionQueue.async rather than synchronously with
sessionQueue.sync, ensuring callers such as AppState.stopAndTranscribe error and
cancellation completions do not block the main thread while
session.stopRunning() executes. Preserve the existing cleanup and file-removal
behavior, and verify teardown remains serialized with other session operations.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 406f1d02-b413-465e-aa6f-a074409ca879

📥 Commits

Reviewing files that changed from the base of the PR and between 7427ca9 and 2196834.

📒 Files selected for processing (2)
  • CHANGELOG.md
  • Sources/AudioRecorder.swift

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant