refactor: Transcriber interface + unified sttmodel catalog - #46
Merged
Conversation
Groundwork for a second speech engine. No behavior change: vox still runs
whisper.cpp exactly as before.
Extract a Transcriber interface at the pipeline boundary. transcribe.Client
already had the matching method signature, so this is a one-line parameter
change in transcribeStage and nothing else.
Replace internal/whispermodel with internal/sttmodel, which adds two things
the old package could not express:
- an Engine dimension (whisper vs parakeet), since a second inference
backend is coming
- archive models, which extract to a directory of files rather than
landing as a single .bin
Model storage moves to ~/.local/share/vox/models/<engine>/. Existing whisper
installs are found via a fallback to ~/.local/share/whisper-cpp/, and
WHISPER_MODEL_DIR is still honored, so nobody re-downloads a 1.5 GiB model.
ResolvePath is used wherever a path reaches whisper-server; Path is reserved
for new downloads, which always land in the canonical location.
Archive extraction stages into a temp directory and verifies every required
file before swapping into place, so a partial extraction fails at install
time with a clear error rather than at inference time with a confusing one.
Entries are checked against path traversal and a per-entry size cap.
Remove is idempotent for both model shapes so callers need not guard with
IsInstalled.
Addresses supareview findings on PR #46 (1/3 in stack): Suggestions fixed: - Remove now cleans temp artifacts at both resolved and canonical paths - existsComplete returns false for archive models with empty Files slice - Added TestRemoveAtLegacyPath to cover legacy-path deletion Nits fixed: - Removed duplicate os.MkdirAll calls in model_test.go - Simplified hasher declaration, removed unused hash import
alohaninja
added a commit
that referenced
this pull request
Aug 21, 2026
Addresses supareview findings on PR #47 (2/3 in stack, base: #46): Blockers fixed: - Replace runWithTimeout goroutine/zombie leak with exec.CommandContext Suggestions fixed: - Add idle-timer lifecycle test (TestIdleTimerReleasesImpl) - Add modelMu precondition comment on activateModel - Rename currentWhisperModelID to currentModelID Nits fixed: - Add TestDecodeWAVLargeChunkSize for oversized chunk size field
alohaninja
added a commit
that referenced
this pull request
Aug 21, 2026
Addresses supareview findings on PR #47 (2/3 in stack, base: #46): Blockers fixed: - Replace runWithTimeout goroutine/zombie leak with exec.CommandContext Suggestions fixed: - Add idle-timer lifecycle test (TestIdleTimerReleasesImpl) - Add modelMu precondition comment on activateModel - Rename currentWhisperModelID to currentModelID Nits fixed: - Add TestDecodeWAVLargeChunkSize for oversized chunk size field
alohaninja
added a commit
that referenced
this pull request
Aug 21, 2026
Addresses supareview findings on PR #47 (2/3 in stack, base: #46): Blockers fixed: - Replace runWithTimeout goroutine/zombie leak with exec.CommandContext Suggestions fixed: - Add idle-timer lifecycle test (TestIdleTimerReleasesImpl) - Add modelMu precondition comment on activateModel - Rename currentWhisperModelID to currentModelID Nits fixed: - Add TestDecodeWAVLargeChunkSize for oversized chunk size field
mattthewong
approved these changes
Aug 21, 2026
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.
Groundwork for a second speech engine. No behavior change: vox still runs whisper.cpp exactly as before.
What this does
Extracts a
Transcriberinterface at the pipeline boundary (internal/transcribe/transcriber.go).transcribe.Clientalready had the matching method signature, so this is a one-line parameter change intranscribeStageand nothing else.Replaces
internal/whispermodelwithinternal/sttmodel, which adds two things the old package could not express:Enginedimension (whisper vs parakeet), since a second inference backend is coming in the next PRModel storage moves to
~/.local/share/vox/models/<engine>/. Existing whisper installs are found via a fallback to~/.local/share/whisper-cpp/, andWHISPER_MODEL_DIRis still honored, so nobody re-downloads multi-gigabyte models.Safe to merge first
This PR is intentionally separable: every test passes, whisper works identically, and no new engine is introduced. The next PR builds on this foundation.
Testing
go test -race -short ./...)