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.
- rift_local-0.1.0.dev1/.gitignore +31 -0
- rift_local-0.1.0.dev1/LICENSE +21 -0
- rift_local-0.1.0.dev1/MANIFEST.in +15 -0
- rift_local-0.1.0.dev1/PKG-INFO +176 -0
- rift_local-0.1.0.dev1/PUBLISHING.md +208 -0
- rift_local-0.1.0.dev1/README.md +138 -0
- rift_local-0.1.0.dev1/log.txt +0 -0
- rift_local-0.1.0.dev1/pyproject.toml +56 -0
- rift_local-0.1.0.dev1/scripts/build.sh +127 -0
- rift_local-0.1.0.dev1/scripts/bump-version.sh +103 -0
- rift_local-0.1.0.dev1/specs/rift-local.md +1211 -0
- rift_local-0.1.0.dev1/src/rift_local/__init__.py +3 -0
- rift_local-0.1.0.dev1/src/rift_local/backends/__init__.py +48 -0
- rift_local-0.1.0.dev1/src/rift_local/backends/moonshine.py +224 -0
- rift_local-0.1.0.dev1/src/rift_local/backends/sherpa.py +139 -0
- rift_local-0.1.0.dev1/src/rift_local/cli.py +237 -0
- rift_local-0.1.0.dev1/src/rift_local/models/__init__.py +19 -0
- rift_local-0.1.0.dev1/src/rift_local/models/download.py +159 -0
- rift_local-0.1.0.dev1/src/rift_local/models/registry.py +173 -0
- rift_local-0.1.0.dev1/src/rift_local/server.py +199 -0
- rift_local-0.1.0.dev1/src/rift_local/types.py +67 -0
- rift_local-0.1.0.dev1/tests/__init__.py +0 -0
- rift_local-0.1.0.dev1/tests/conftest.py +125 -0
- rift_local-0.1.0.dev1/tests/test_moonshine.py +383 -0
- rift_local-0.1.0.dev1/tests/test_server.py +214 -0
- rift_local-0.1.0.dev1/uv.lock +1381 -0
|
@@ -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"]
|