Repository navigation
feat(macos): quick language switching per lane and session export (P2) - #18
Merged
Merged
Conversation
SessionTranscript is an untrimmed value-type record of finalized segments and their translations, independent of the 5-card display limit. SessionExporter renders it as Markdown, aligned plain text, or SRT subtitles with per-lane non-overlapping cue timings estimated from finalization offsets.
TranscriptionVM now begins a SessionTranscript on capture start, appends finalized segments, writes back completed translations (even after segments scroll off screen), drops rolled-back entries, and exposes exportSession(_:) which renders the record and saves it via NSSavePanel. The HUD gains a share menu next to History/Settings and the File menu gains matching commands (Markdown bound to Cmd-E) routed through a new .exportSession notification.
microphoneSourceLanguage (nil = follow the system-audio lane) plus AppSettings.language(for:) give each capture lane its own effective recognition language; older settings JSON decodes the missing key as nil.
SpeechRecognitionEngine gains restartLane(_:language:) and languageAvailability(). The SpeechTranscriber engine tears down and rebuilds only the affected lane (finalizing its in-flight utterance, downloading the on-device model when needed) while per-lane generation counters keep overlapping restarts and stop() from resurrecting stale lanes; the legacy engine falls back to stop+start of its single lane. RecognitionStallDetector can reset one lane so a new language gets a fresh stall budget.
updateSettings no longer demands a stop/start for language changes: each lane whose effective language changed restarts its own recognition, the lane's uncommitted draft is kept as a caption (the same flush semantics as a finished ASR task), and the translation target applies to new translations without any restart. A capture session id keeps a restart that outlives its session — e.g. during an on-device model download — from touching the next session's lanes.
The HUD language label becomes a menu with System Audio, Microphone (new engine only) and Translate To sections; languages the device cannot recognize on-device are hidden and downloadable ones are annotated. Settings mirrors this with a renamed System Audio Language picker and a Microphone Language picker defaulting to Same as System Audio.
A fake engine records lane restarts while view-model tests verify lane routing (follow vs override, reset to follow, idle save-only, not-running lanes skipped), the draft flush on a live switch, the restart-free translation-target change, and that language edits drop the needs-restart warning; pure tests cover the HUD label formats and the language-availability mapping.
Resolve TranscriptionVM conflicts (keep language availability and session transcript; begin the session and a new capture session id together), add the F9 engine methods to the F10 test fake, export per-lane languages in the session header, and fix a Sendable capture warning in the export test. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…gnizes again Found in GUI testing: after switching the microphone lane to the right language it recognized normally, but the warning stayed on screen. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
P2: quick per-lane language switching (F9) and session export (F10).
F9 — language menu
ZH → ENlabel is now a menu: System Audio language, Microphone language (default "Same as System Audio"), Translate To. Label showsSYS ZH · MIC EN → ENwhen the lanes differ.(download).SpeechRecognitionEngine.restartLane); the other lane keeps running. Changing the translation language restarts nothing. Settings / ⌘, language changes apply live too (no "restart needed" notice).microphoneSourceLanguage(nil = follow system audio), backward-compatible decoding.F10 — export this session
SessionTranscript: an untrimmed record of the session (on-screen cards are trimmed to 5), begun at Start, kept after Stop, updated with final translations and ASR rollbacks.SessionExporter: Markdown, plain text and SRT. SRT timing is estimated (end = finalize time, duration from text length, no overlap within a lane) because the pipeline has no utterance start times.NSSavePanel; independent of the history setting. Logs record only line count and format.Integration fixes (Claude)
TranscriptionVM; F9 engine methods added to the F10 test fake; export header shows per-lane languages; a Sendable capture warning in the export test.Test results
./Scripts/run_tests.sh: 504 tests, 0 failures, no new warnings. Tests use fake engines/stubs — no real recognition, downloads, permissions or network.(download)markers. Microphone → English (US): label becameSYS ZH · MIC EN → EN, log showed only the microphone lane restarted (0.33 s). A Chinese clip on the system lane and an English clip on the microphone lane were both recognized correctly.SYS ZH · MIC EN → JA, duration); the SRT parsed with sequential indices, valid timestamps and start < end for every cue.(download)language (model download during a live switch); the legacy-engine path (macOS < 26).Code by Qoder (Kimi-K3) from two parallel task briefs; integration, one UX fix, review and GUI verification by Claude.
🤖 Generated with Claude Code