rift-local 0.1.0.dev1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,31 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+ *.so
6
+
7
+ # Distribution / packaging
8
+ dist/
9
+ build/
10
+ *.egg-info/
11
+ *.egg
12
+
13
+ # Virtual environments
14
+ .venv/
15
+ venv/
16
+ ENV/
17
+
18
+ # IDE
19
+ .idea/
20
+ .vscode/
21
+ *.swp
22
+ *.swo
23
+
24
+ # OS
25
+ .DS_Store
26
+ Thumbs.db
27
+
28
+ # Testing
29
+ .pytest_cache/
30
+ .coverage
31
+ htmlcov/
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Leftium
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,15 @@
1
+ # Include essential files
2
+ include README.md
3
+ include LICENSE
4
+ include pyproject.toml
5
+
6
+ # Exclude build artifacts and local files
7
+ exclude log.txt
8
+ exclude uv.lock
9
+ exclude .gitignore
10
+ prune tests
11
+ prune scripts
12
+ prune specs
13
+ prune .pytest_cache
14
+ prune .ruff_cache
15
+ prune .venv
@@ -0,0 +1,176 @@
1
+ Metadata-Version: 2.4
2
+ Name: rift-local
3
+ Version: 0.1.0.dev1
4
+ Summary: Local inference server for RIFT Transcription — streaming and batch speech recognition, LLM transforms, and CLI transcription backed by local models.
5
+ Project-URL: Homepage, https://github.com/Leftium/rift-local
6
+ Project-URL: Repository, https://github.com/Leftium/rift-local
7
+ Project-URL: Issues, https://github.com/Leftium/rift-local/issues
8
+ Author: Leftium
9
+ License-Expression: MIT
10
+ License-File: LICENSE
11
+ Keywords: asr,local-inference,speech-recognition,transcription,whisper
12
+ Classifier: Development Status :: 2 - Pre-Alpha
13
+ Classifier: Environment :: Console
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: License :: OSI Approved :: MIT License
16
+ Classifier: Operating System :: OS Independent
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3.10
19
+ Classifier: Programming Language :: Python :: 3.11
20
+ Classifier: Programming Language :: Python :: 3.12
21
+ Classifier: Programming Language :: Python :: 3.13
22
+ Classifier: Topic :: Multimedia :: Sound/Audio :: Speech
23
+ Requires-Python: >=3.10
24
+ Requires-Dist: fastapi>=0.115
25
+ Requires-Dist: httpx>=0.28
26
+ Requires-Dist: numpy>=1.24
27
+ Requires-Dist: pydantic>=2.0
28
+ Requires-Dist: uvicorn[standard]>=0.34
29
+ Provides-Extra: dev
30
+ Requires-Dist: pytest>=8.0; extra == 'dev'
31
+ Provides-Extra: mlx
32
+ Provides-Extra: moonshine
33
+ Requires-Dist: moonshine-voice>=0.0.48; extra == 'moonshine'
34
+ Provides-Extra: sherpa
35
+ Requires-Dist: onnx>=1.16; extra == 'sherpa'
36
+ Requires-Dist: sherpa-onnx>=1.11; extra == 'sherpa'
37
+ Description-Content-Type: text/markdown
38
+
39
+ # rift-local
40
+
41
+ Local inference server for [RIFT Transcription](https://github.com/Leftium/rift-transcription). Serves streaming speech recognition over WebSocket, backed by local models with automatic download.
42
+
43
+ ## Install
44
+
45
+ ```
46
+ pip install rift-local
47
+ ```
48
+
49
+ ### Backend extras
50
+
51
+ rift-local supports multiple ASR backends, each installed as an optional extra:
52
+
53
+ ```bash
54
+ pip install rift-local[sherpa] # sherpa-onnx (Nemotron, Kroko)
55
+ pip install rift-local[moonshine] # Moonshine Gen 2 (via moonshine-voice)
56
+ pip install rift-local[sherpa,moonshine] # both
57
+ ```
58
+
59
+ On Apple Silicon, add MLX support for future GPU-accelerated batch transcription:
60
+
61
+ ```bash
62
+ pip install rift-local[mlx]
63
+ ```
64
+
65
+ For development (includes pytest):
66
+
67
+ ```bash
68
+ pip install rift-local[dev]
69
+ ```
70
+
71
+ ## Models
72
+
73
+ List all available models and see which are installed:
74
+
75
+ ```
76
+ rift-local list
77
+ rift-local list --installed
78
+ ```
79
+
80
+ ### sherpa-onnx models
81
+
82
+ | Model | Params | Languages | Download | Notes |
83
+ |-------|--------|-----------|----------|-------|
84
+ | `nemotron-en` | 0.6B | EN | 447 MB | Best accuracy. |
85
+ | `zipformer-en-kroko` | ~30M | EN | 55 MB | Lightweight, fast. Only ~68 MB on disk. |
86
+
87
+ Requires: `pip install rift-local[sherpa]`
88
+
89
+ ### Moonshine models
90
+
91
+ | Model | Params | Languages | Size | Notes |
92
+ |-------|--------|-----------|------|-------|
93
+ | `moonshine-en-tiny` | 34M | EN | 26 MB | Fastest. Good for low-resource. |
94
+ | `moonshine-en-small` | 123M | EN | 95 MB | Balanced speed/accuracy. |
95
+ | `moonshine-en-medium` | 245M | EN | 190 MB | **Default.** Best Moonshine accuracy. |
96
+
97
+ Requires: `pip install rift-local[moonshine]`
98
+
99
+ Moonshine models are downloaded automatically by the `moonshine-voice` library on first use.
100
+
101
+ ## Usage
102
+
103
+ ### Server mode (for RIFT app)
104
+
105
+ Start the WebSocket server with any model:
106
+
107
+ ```bash
108
+ # Start server and open RIFT Transcription in your browser
109
+ rift-local serve --open
110
+
111
+ # Moonshine (default model)
112
+ rift-local serve
113
+
114
+ # sherpa-onnx
115
+ rift-local serve --model nemotron-en
116
+
117
+ # Custom host/port
118
+ rift-local serve --model moonshine-en-tiny --host 0.0.0.0 --port 8080
119
+ ```
120
+
121
+ The `--open` flag launches [RIFT Transcription](https://rift-transcription.vercel.app) in your browser, pre-configured to connect to the local server. The voice source is set to "Local" automatically — just click to start the mic.
122
+
123
+ For local development of the RIFT Transcription client:
124
+
125
+ ```bash
126
+ rift-local serve --open dev # opens http://localhost:5173
127
+ rift-local serve --open dev:3000 # custom port
128
+ ```
129
+
130
+ The server auto-downloads the model on first run, then listens on:
131
+ - **WebSocket**: `ws://127.0.0.1:2177/ws` (streaming ASR)
132
+ - **HTTP**: `http://127.0.0.1:2177/info` (model metadata)
133
+
134
+ ### Server options
135
+
136
+ | Flag | Default | Description |
137
+ |------|---------|-------------|
138
+ | `--model` | `moonshine-en-medium` | Model name from registry |
139
+ | `--host` | `127.0.0.1` | Bind address |
140
+ | `--port` | `2177` | Server port |
141
+ | `--threads` | `2` | Inference threads |
142
+ | `--open` | off | Open browser to RIFT Transcription client |
143
+
144
+ ## WebSocket protocol
145
+
146
+ 1. Client connects to `/ws`
147
+ 2. Server sends `info` JSON (model name, features, sample rate)
148
+ 3. Client sends binary frames of Float32 PCM audio at 16 kHz
149
+ 4. Server sends `result` JSON messages with partial/final transcriptions
150
+ 5. Client sends text `"Done"` to end the session
151
+
152
+ ## Running tests
153
+
154
+ ```bash
155
+ # Install dev + backend dependencies
156
+ pip install -e ".[dev,sherpa,moonshine]"
157
+
158
+ # Run fast tests (mocked backends, no model download)
159
+ pytest
160
+
161
+ # Run all tests including slow integration tests (downloads models)
162
+ pytest --slow
163
+ ```
164
+
165
+ Tests are in the `tests/` directory:
166
+ - `test_server.py` — WebSocket server tests using a mock backend
167
+ - `test_moonshine.py` — Moonshine adapter unit tests (mocked) + integration tests (slow)
168
+ - `conftest.py` — Shared `MockBackend` fixture and `--slow` flag
169
+
170
+ ## Spec
171
+
172
+ See [specs/rift-local.md](specs/rift-local.md) for the full design document.
173
+
174
+ ## License
175
+
176
+ [MIT](LICENSE)
@@ -0,0 +1,208 @@
1
+ # Publishing rift-local to PyPI
2
+
3
+ ## Quick Start
4
+
5
+ ```bash
6
+ # 1. Build and test
7
+ ./scripts/build.sh
8
+
9
+ # 2. Upload to TestPyPI (optional but recommended)
10
+ uv run python -m twine upload --repository testpypi dist/*
11
+
12
+ # 3. Test install from TestPyPI
13
+ pip install --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple/ rift-local
14
+
15
+ # 4. Upload to PyPI
16
+ uv run python -m twine upload dist/*
17
+ ```
18
+
19
+ ## First-Time Setup
20
+
21
+ ### 1. Create PyPI Accounts
22
+
23
+ - **TestPyPI**: https://test.pypi.org/account/register/
24
+ - **PyPI**: https://pypi.org/account/register/
25
+
26
+ ### 2. Generate API Tokens
27
+
28
+ For both TestPyPI and PyPI:
29
+ 1. Go to Account Settings → API tokens
30
+ 2. Click "Add API token"
31
+ 3. Name: `rift-local` (or "All projects" scope)
32
+ 4. Scope: Choose project or entire account
33
+ 5. Copy the token (starts with `pypi-`)
34
+
35
+ ### 3. Configure Authentication
36
+
37
+ Create `~/.pypirc`:
38
+
39
+ ```ini
40
+ [distutils]
41
+ index-servers =
42
+ pypi
43
+ testpypi
44
+
45
+ [pypi]
46
+ username = __token__
47
+ password = pypi-YOUR-PRODUCTION-TOKEN-HERE
48
+
49
+ [testpypi]
50
+ repository = https://test.pypi.org/legacy/
51
+ username = __token__
52
+ password = pypi-YOUR-TEST-TOKEN-HERE
53
+ ```
54
+
55
+ Set permissions:
56
+ ```bash
57
+ chmod 600 ~/.pypirc
58
+ ```
59
+
60
+ ## Build Script Features
61
+
62
+ The `scripts/build.sh` script automatically:
63
+
64
+ ✅ Checks version consistency (`pyproject.toml` ↔ `__init__.py`)
65
+ ✅ Verifies required files exist
66
+ ✅ Warns about uncommitted changes
67
+ ✅ Cleans old builds
68
+ ✅ Runs tests
69
+ ✅ Builds both wheel and source distribution
70
+ ✅ Validates package metadata with `twine check`
71
+ ✅ Shows next steps
72
+
73
+ ## Version Management
74
+
75
+ Current version: `0.1.0.dev0` (development release)
76
+
77
+ ### Update version in TWO places:
78
+
79
+ 1. `pyproject.toml`:
80
+ ```toml
81
+ [project]
82
+ version = "0.1.0"
83
+ ```
84
+
85
+ 2. `src/rift_local/__init__.py`:
86
+ ```python
87
+ __version__ = "0.1.0"
88
+ ```
89
+
90
+ ### Version Strategy
91
+
92
+ - `0.1.0.dev0` — Development release (TestPyPI testing)
93
+ - `0.1.0` — First stable release
94
+ - `0.1.1` — Bug fixes (patch)
95
+ - `0.2.0` — New features (minor)
96
+ - `1.0.0` — Stable API (major)
97
+
98
+ ## Testing the Package
99
+
100
+ ### Local Installation Test
101
+
102
+ ```bash
103
+ # Create clean venv
104
+ python3 -m venv /tmp/test_rift_local
105
+ source /tmp/test_rift_local/bin/activate
106
+
107
+ # Install from local build
108
+ pip install dist/rift_local-*.whl
109
+
110
+ # Test CLI
111
+ rift-local --help
112
+ rift-local list
113
+
114
+ # Test Python API
115
+ python3 -c "
116
+ import rift_local
117
+ print(f'Version: {rift_local.__version__}')
118
+ from rift_local.models.registry import list_models
119
+ print(f'Models: {len(list_models())}')
120
+ "
121
+ ```
122
+
123
+ ### TestPyPI Installation Test
124
+
125
+ ```bash
126
+ # Install from TestPyPI
127
+ pip install --index-url https://test.pypi.org/simple/ \
128
+ --extra-index-url https://pypi.org/simple/ \
129
+ rift-local
130
+
131
+ # Note: --extra-index-url needed for dependencies not on TestPyPI
132
+ ```
133
+
134
+ ## Publishing Checklist
135
+
136
+ Before uploading to PyPI:
137
+
138
+ - [ ] All tests pass
139
+ - [ ] Version updated in both places
140
+ - [ ] README.md up to date
141
+ - [ ] CHANGELOG updated (if exists)
142
+ - [ ] Git committed and tagged
143
+ - [ ] Tested on TestPyPI
144
+ - [ ] Verified installation in clean environment
145
+
146
+ ## Post-Publication
147
+
148
+ ### Tag the release
149
+
150
+ ```bash
151
+ git tag -a v0.1.0 -m "Release v0.1.0"
152
+ git push origin v0.1.0
153
+ ```
154
+
155
+ ### Create GitHub Release
156
+
157
+ 1. Go to https://github.com/Leftium/rift-local/releases
158
+ 2. Click "Draft a new release"
159
+ 3. Choose tag: `v0.1.0`
160
+ 4. Release title: `v0.1.0`
161
+ 5. Add release notes
162
+ 6. Publish release
163
+
164
+ ## Troubleshooting
165
+
166
+ ### `externally-managed-environment` error
167
+
168
+ The build script automatically handles this by using `uv` if available.
169
+
170
+ If needed, use a virtual environment:
171
+ ```bash
172
+ python3 -m venv .venv
173
+ source .venv/bin/activate
174
+ ./scripts/build.sh
175
+ ```
176
+
177
+ ### Upload fails with 403
178
+
179
+ - Check API token is correct
180
+ - Verify package name not already taken
181
+ - Ensure token has correct scope
182
+
183
+ ### Package name conflict
184
+
185
+ If `rift-local` is taken, consider:
186
+ - `rift-local-server`
187
+ - `riftlocal`
188
+ - `rift-inference`
189
+
190
+ Change in `pyproject.toml`:
191
+ ```toml
192
+ [project]
193
+ name = "rift-local-server"
194
+ ```
195
+
196
+ ## Useful Commands
197
+
198
+ ```bash
199
+ # View package contents
200
+ tar -tzf dist/rift_local-*.tar.gz | head -20
201
+ unzip -l dist/rift_local-*.whl
202
+
203
+ # Check package on PyPI
204
+ open https://pypi.org/project/rift-local/
205
+
206
+ # Check download stats (after 24-48 hours)
207
+ open https://pepy.tech/project/rift-local
208
+ ```
@@ -0,0 +1,138 @@
1
+ # rift-local
2
+
3
+ Local inference server for [RIFT Transcription](https://github.com/Leftium/rift-transcription). Serves streaming speech recognition over WebSocket, backed by local models with automatic download.
4
+
5
+ ## Install
6
+
7
+ ```
8
+ pip install rift-local
9
+ ```
10
+
11
+ ### Backend extras
12
+
13
+ rift-local supports multiple ASR backends, each installed as an optional extra:
14
+
15
+ ```bash
16
+ pip install rift-local[sherpa] # sherpa-onnx (Nemotron, Kroko)
17
+ pip install rift-local[moonshine] # Moonshine Gen 2 (via moonshine-voice)
18
+ pip install rift-local[sherpa,moonshine] # both
19
+ ```
20
+
21
+ On Apple Silicon, add MLX support for future GPU-accelerated batch transcription:
22
+
23
+ ```bash
24
+ pip install rift-local[mlx]
25
+ ```
26
+
27
+ For development (includes pytest):
28
+
29
+ ```bash
30
+ pip install rift-local[dev]
31
+ ```
32
+
33
+ ## Models
34
+
35
+ List all available models and see which are installed:
36
+
37
+ ```
38
+ rift-local list
39
+ rift-local list --installed
40
+ ```
41
+
42
+ ### sherpa-onnx models
43
+
44
+ | Model | Params | Languages | Download | Notes |
45
+ |-------|--------|-----------|----------|-------|
46
+ | `nemotron-en` | 0.6B | EN | 447 MB | Best accuracy. |
47
+ | `zipformer-en-kroko` | ~30M | EN | 55 MB | Lightweight, fast. Only ~68 MB on disk. |
48
+
49
+ Requires: `pip install rift-local[sherpa]`
50
+
51
+ ### Moonshine models
52
+
53
+ | Model | Params | Languages | Size | Notes |
54
+ |-------|--------|-----------|------|-------|
55
+ | `moonshine-en-tiny` | 34M | EN | 26 MB | Fastest. Good for low-resource. |
56
+ | `moonshine-en-small` | 123M | EN | 95 MB | Balanced speed/accuracy. |
57
+ | `moonshine-en-medium` | 245M | EN | 190 MB | **Default.** Best Moonshine accuracy. |
58
+
59
+ Requires: `pip install rift-local[moonshine]`
60
+
61
+ Moonshine models are downloaded automatically by the `moonshine-voice` library on first use.
62
+
63
+ ## Usage
64
+
65
+ ### Server mode (for RIFT app)
66
+
67
+ Start the WebSocket server with any model:
68
+
69
+ ```bash
70
+ # Start server and open RIFT Transcription in your browser
71
+ rift-local serve --open
72
+
73
+ # Moonshine (default model)
74
+ rift-local serve
75
+
76
+ # sherpa-onnx
77
+ rift-local serve --model nemotron-en
78
+
79
+ # Custom host/port
80
+ rift-local serve --model moonshine-en-tiny --host 0.0.0.0 --port 8080
81
+ ```
82
+
83
+ The `--open` flag launches [RIFT Transcription](https://rift-transcription.vercel.app) in your browser, pre-configured to connect to the local server. The voice source is set to "Local" automatically — just click to start the mic.
84
+
85
+ For local development of the RIFT Transcription client:
86
+
87
+ ```bash
88
+ rift-local serve --open dev # opens http://localhost:5173
89
+ rift-local serve --open dev:3000 # custom port
90
+ ```
91
+
92
+ The server auto-downloads the model on first run, then listens on:
93
+ - **WebSocket**: `ws://127.0.0.1:2177/ws` (streaming ASR)
94
+ - **HTTP**: `http://127.0.0.1:2177/info` (model metadata)
95
+
96
+ ### Server options
97
+
98
+ | Flag | Default | Description |
99
+ |------|---------|-------------|
100
+ | `--model` | `moonshine-en-medium` | Model name from registry |
101
+ | `--host` | `127.0.0.1` | Bind address |
102
+ | `--port` | `2177` | Server port |
103
+ | `--threads` | `2` | Inference threads |
104
+ | `--open` | off | Open browser to RIFT Transcription client |
105
+
106
+ ## WebSocket protocol
107
+
108
+ 1. Client connects to `/ws`
109
+ 2. Server sends `info` JSON (model name, features, sample rate)
110
+ 3. Client sends binary frames of Float32 PCM audio at 16 kHz
111
+ 4. Server sends `result` JSON messages with partial/final transcriptions
112
+ 5. Client sends text `"Done"` to end the session
113
+
114
+ ## Running tests
115
+
116
+ ```bash
117
+ # Install dev + backend dependencies
118
+ pip install -e ".[dev,sherpa,moonshine]"
119
+
120
+ # Run fast tests (mocked backends, no model download)
121
+ pytest
122
+
123
+ # Run all tests including slow integration tests (downloads models)
124
+ pytest --slow
125
+ ```
126
+
127
+ Tests are in the `tests/` directory:
128
+ - `test_server.py` — WebSocket server tests using a mock backend
129
+ - `test_moonshine.py` — Moonshine adapter unit tests (mocked) + integration tests (slow)
130
+ - `conftest.py` — Shared `MockBackend` fixture and `--slow` flag
131
+
132
+ ## Spec
133
+
134
+ See [specs/rift-local.md](specs/rift-local.md) for the full design document.
135
+
136
+ ## License
137
+
138
+ [MIT](LICENSE)
File without changes
@@ -0,0 +1,56 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "rift-local"
7
+ version = "0.1.0.dev1"
8
+ description = "Local inference server for RIFT Transcription — streaming and batch speech recognition, LLM transforms, and CLI transcription backed by local models."
9
+ readme = "README.md"
10
+ license = "MIT"
11
+ requires-python = ">=3.10"
12
+ authors = [{ name = "Leftium" }]
13
+ keywords = ["speech-recognition", "transcription", "asr", "whisper", "local-inference"]
14
+ dependencies = [
15
+ "fastapi>=0.115",
16
+ "uvicorn[standard]>=0.34",
17
+ "numpy>=1.24",
18
+ "httpx>=0.28",
19
+ "pydantic>=2.0",
20
+ ]
21
+ classifiers = [
22
+ "Development Status :: 2 - Pre-Alpha",
23
+ "Environment :: Console",
24
+ "Intended Audience :: Developers",
25
+ "License :: OSI Approved :: MIT License",
26
+ "Operating System :: OS Independent",
27
+ "Programming Language :: Python :: 3",
28
+ "Programming Language :: Python :: 3.10",
29
+ "Programming Language :: Python :: 3.11",
30
+ "Programming Language :: Python :: 3.12",
31
+ "Programming Language :: Python :: 3.13",
32
+ "Topic :: Multimedia :: Sound/Audio :: Speech",
33
+ ]
34
+
35
+ [project.urls]
36
+ Homepage = "https://github.com/Leftium/rift-local"
37
+ Repository = "https://github.com/Leftium/rift-local"
38
+ Issues = "https://github.com/Leftium/rift-local/issues"
39
+
40
+ [project.scripts]
41
+ rift-local = "rift_local.cli:main"
42
+
43
+ [project.optional-dependencies]
44
+ sherpa = ["sherpa-onnx>=1.11", "onnx>=1.16"]
45
+ moonshine = ["moonshine-voice>=0.0.48"]
46
+ mlx = []
47
+ dev = [
48
+ "pytest>=8.0",
49
+ ]
50
+
51
+ [tool.pytest.ini_options]
52
+ testpaths = ["tests"]
53
+ markers = ["slow: requires downloaded models (use --slow to run)"]
54
+
55
+ [tool.hatch.build.targets.wheel]
56
+ packages = ["src/rift_local"]