Skip to content

feat(apple): move Apple Speech to SpeechAnalyzer; require macOS 26 - #58

Merged
giraphant merged 1 commit into
mainfrom
giraphant/apple-speech-analyzer
Oct 12, 2026
Merged

giraphant merged 1 commit into
mainfrom
giraphant/apple-speech-analyzer

Conversation

@giraphant

Copy link
Copy Markdown
Owner

Summary

  • The Apple engine now runs SpeechTranscriber through SpeechAnalyzer (macOS 26) instead of SFSpeechRecognizer. The old recognizer dropped everything before a pause and only waited 0.3 s after endAudio, which is why dictations were truncated. The new pipeline returns the whole recording.
  • AppleSpeechBackend is now a PCMCaptureEngine. SpeechTranscriber's preferred input is the hub's 16 kHz mono int16 PCM, so the native-buffer path is removed: BufferCaptureEngine, the AudioTapHub buffer sinks, and the replay int16Buffer.
  • SpeechTranscriber needs no Speech Recognition authorization, so the launch-time request, the 权限管理 row and the usage strings are removed.
  • The deployment target and LSMinimumSystemVersion move to 26.0.

Verification

  • swift test: 452 tests, 0 failures. make build/make install succeed with a Developer ID signature and the audio-input entitlement.
  • A standalone script runs the same API on 7 real recordings. Stop→final takes 21–83 ms, the output is 16 kHz/int16/mono, and nothing is truncated. The recordings that the old engine reduced to "东阳确实阶段的问题" now come back in full.
  • I wrapped the script in an .app bundle with no NSSpeechRecognitionUsageDescription and authorization .notDetermined. Transcription works.
  • I installed the app and tested by hand: a 121.8 s dictation was transcribed in full (132 characters), with stop→final at 85 ms.

Known limits

  • Accuracy on mixed Chinese/English and academic terms is lower than Qwen3 (e.g. 本体论 → 跟听论).

🤖 Generated with Claude Code

The Apple engine now runs SpeechTranscriber through SpeechAnalyzer instead
of SFSpeechRecognizer. The old recognizer dropped everything before a
pause and only waited 0.3s after endAudio, so dictations came back
truncated; the new pipeline finalizes the whole recording in tens of
milliseconds. The system manages the model, so the bundle does not grow.

- AppleSpeechBackend becomes a PCMCaptureEngine: SpeechTranscriber's
  preferred input is the hub's 16 kHz mono int16 PCM, so the native-buffer
  sink path (BufferCaptureEngine, AudioTapHub buffer sinks, replay
  int16Buffer) is removed.
- Lifecycle calls arrive from arbitrary tasks, so the backend hops to main
  and keeps session state main-confined; ingest reaches the session's
  AnalyzerInput stream through a Lock. Finalized text shows solid in the
  HUD and the volatile tail dimmed, like the other engines.
- SpeechTranscriber needs no Speech Recognition authorization (verified in
  an app bundle with the permission undetermined and no usage string), so
  the launch request, the permissions-pane row and the usage strings go.
- Deployment target, LSMinimumSystemVersion and README move to macOS 26.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@giraphant
giraphant merged commit dd8fd82 into main Oct 12, 2026
@giraphant
giraphant deleted the giraphant/apple-speech-analyzer branch October 12, 2026 22:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant