livekit-plugins-speakerbeamss 0.1.0__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.
- livekit_plugins_speakerbeamss-0.1.0/.gitignore +27 -0
- livekit_plugins_speakerbeamss-0.1.0/PKG-INFO +169 -0
- livekit_plugins_speakerbeamss-0.1.0/README.md +138 -0
- livekit_plugins_speakerbeamss-0.1.0/pyproject.toml +84 -0
- livekit_plugins_speakerbeamss-0.1.0/src/livekit/plugins/speakerbeamss/__init__.py +72 -0
- livekit_plugins_speakerbeamss-0.1.0/src/livekit/plugins/speakerbeamss/log.py +5 -0
- livekit_plugins_speakerbeamss-0.1.0/src/livekit/plugins/speakerbeamss/models/__init__.py +7 -0
- livekit_plugins_speakerbeamss-0.1.0/src/livekit/plugins/speakerbeamss/models/speakerbeam_ss_int8.onnx +0 -0
- livekit_plugins_speakerbeamss-0.1.0/src/livekit/plugins/speakerbeamss/plugin.py +32 -0
- livekit_plugins_speakerbeamss-0.1.0/src/livekit/plugins/speakerbeamss/processor.py +425 -0
- livekit_plugins_speakerbeamss-0.1.0/src/livekit/plugins/speakerbeamss/stt.py +494 -0
- livekit_plugins_speakerbeamss-0.1.0/src/livekit/plugins/speakerbeamss/version.py +1 -0
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# Python-generated files
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[oc]
|
|
4
|
+
build/
|
|
5
|
+
dist/
|
|
6
|
+
wheels/
|
|
7
|
+
*.egg-info/
|
|
8
|
+
|
|
9
|
+
# Virtual environments
|
|
10
|
+
.venv
|
|
11
|
+
|
|
12
|
+
# ONNX / model artifacts (downloaded separately via export_onnx.py)
|
|
13
|
+
exports/*.onnx
|
|
14
|
+
*.onnx
|
|
15
|
+
|
|
16
|
+
# Pytest
|
|
17
|
+
.pytest_cache/
|
|
18
|
+
.coverage
|
|
19
|
+
htmlcov/
|
|
20
|
+
|
|
21
|
+
# Editor
|
|
22
|
+
.vscode/
|
|
23
|
+
.idea/
|
|
24
|
+
*.swp
|
|
25
|
+
|
|
26
|
+
# OS
|
|
27
|
+
.DS_Store
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: livekit-plugins-speakerbeamss
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: LiveKit Agents STT plugin that runs OpenSpeakerBeam-SS target-speaker extraction in front of any inner STT.
|
|
5
|
+
Author-email: linsan <bin.zaq@foxmail.com>
|
|
6
|
+
License: Apache-2.0
|
|
7
|
+
Keywords: asr,audio,livekit,realtime,speaker-extraction,target-speaker,webrtc
|
|
8
|
+
Classifier: Intended Audience :: Developers
|
|
9
|
+
Classifier: License :: OSI Approved :: Apache Software License
|
|
10
|
+
Classifier: Programming Language :: Python :: 3
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
14
|
+
Classifier: Topic :: Multimedia :: Sound/Audio
|
|
15
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
16
|
+
Requires-Python: >=3.10
|
|
17
|
+
Requires-Dist: livekit-agents>=1.5.13
|
|
18
|
+
Requires-Dist: numpy>=1.24
|
|
19
|
+
Requires-Dist: onnxruntime>=1.17.0
|
|
20
|
+
Requires-Dist: resemblyzer>=0.1.1
|
|
21
|
+
Requires-Dist: soundfile>=0.12
|
|
22
|
+
Provides-Extra: examples
|
|
23
|
+
Requires-Dist: livekit-plugins-volcengine>=1.3.26; extra == 'examples'
|
|
24
|
+
Provides-Extra: test
|
|
25
|
+
Requires-Dist: numpy>=1.24; extra == 'test'
|
|
26
|
+
Requires-Dist: onnx>=1.14; extra == 'test'
|
|
27
|
+
Requires-Dist: pytest-asyncio>=0.21; extra == 'test'
|
|
28
|
+
Requires-Dist: pytest>=7.0; extra == 'test'
|
|
29
|
+
Requires-Dist: setuptools<81; extra == 'test'
|
|
30
|
+
Description-Content-Type: text/markdown
|
|
31
|
+
|
|
32
|
+
# livekit-plugins-speakerbeamss
|
|
33
|
+
|
|
34
|
+
> A [LiveKit Agents](https://github.com/livekit/agents) STT plugin that
|
|
35
|
+
> runs [OpenSpeakerBeam-SS](../OpenSpeakerBeam-SS) target-speaker
|
|
36
|
+
> extraction in front of any inner STT instance. The agent hears only
|
|
37
|
+
> the user — even with competing speakers, music, or noise in the room.
|
|
38
|
+
|
|
39
|
+
The plugin is **ONNX-only**. The PyTorch separator never ships here.
|
|
40
|
+
The **trained INT8 model is bundled inside the wheel** at
|
|
41
|
+
`livekit/plugins/speakerbeamss/models/speakerbeam_ss_trained_int8.onnx`
|
|
42
|
+
(≈13 MB), so a fresh `pip install livekit-plugins-speakerbeamss` is
|
|
43
|
+
enough — no separate download. Follow step 0 below only if you want to
|
|
44
|
+
swap in a different export (FP32, the base release, or your own
|
|
45
|
+
fine-tune).
|
|
46
|
+
|
|
47
|
+
The reference audio for the target speaker is taken from the
|
|
48
|
+
*agent's first user turn*: the first sentence the user speaks is
|
|
49
|
+
forwarded to the inner STT **as-is** so the agent can still
|
|
50
|
+
understand it, and is *also* kept in a buffer. When the inner STT
|
|
51
|
+
emits `END_OF_SPEECH`, the buffer is collapsed to a Resemblyzer
|
|
52
|
+
d-vector and the plugin flips to extraction mode for every
|
|
53
|
+
subsequent utterance.
|
|
54
|
+
|
|
55
|
+
You can also pass a pre-recorded enrollment audio via
|
|
56
|
+
`reference_audio="path.wav"` to skip the capture phase entirely.
|
|
57
|
+
|
|
58
|
+
## Installation
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
# 1. Install this plugin (from the plugin source root):
|
|
62
|
+
cd livekit/plugins/speakerbeamss
|
|
63
|
+
pip install -e .
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
That's it — `pip install` wires up `livekit.plugins.speakerbeamss`
|
|
67
|
+
*and* ships the trained ONNX bundle, which the loader resolves via
|
|
68
|
+
`importlib.resources`. No env vars, no separate download.
|
|
69
|
+
|
|
70
|
+
### Using a different exported variant
|
|
71
|
+
|
|
72
|
+
If you have your own export (FP32, base release, a re-trained
|
|
73
|
+
checkpoint, …) you'd rather use, point the loader at it explicitly:
|
|
74
|
+
|
|
75
|
+
```python
|
|
76
|
+
from livekit.plugins.speakerbeamss import STT
|
|
77
|
+
|
|
78
|
+
sb_stt = STT(
|
|
79
|
+
inner=inner,
|
|
80
|
+
onnx_dir="/Users/linsan/Public/projects/OpenSpeakerBeam-SS/exports",
|
|
81
|
+
onnx_filename="speakerbeam_ss_int8.onnx", # base INT8 release
|
|
82
|
+
)
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
The loader's lookup order is:
|
|
86
|
+
|
|
87
|
+
1. **Bundled** — `livekit.plugins.speakerbeamss.models/<filename>`
|
|
88
|
+
(the trained INT8 lives here by default).
|
|
89
|
+
2. **Disk** — `{onnx_dir}/{filename}` if set, otherwise the
|
|
90
|
+
`~/Public/projects/OpenSpeakerBeam-SS/exports/` fallback.
|
|
91
|
+
|
|
92
|
+
To export a different variant yourself:
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
cd ~/Public/projects/OpenSpeakerBeam-SS
|
|
96
|
+
pip install -r requirements.txt
|
|
97
|
+
python export_onnx.py --ckpt checkpoints/best_model.pth
|
|
98
|
+
ls exports/ # -> speakerbeam_ss_{fp32,int8,trained_fp32,trained_int8}.onnx
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## Usage — wrap any inner STT
|
|
102
|
+
|
|
103
|
+
```python
|
|
104
|
+
from livekit.plugins.speakerbeamss import STT
|
|
105
|
+
from livekit.plugins.volcengine import STT as VolcSTT # any streaming inner STT
|
|
106
|
+
|
|
107
|
+
inner = VolcSTT() # read keys from env, etc.
|
|
108
|
+
stt = STT(inner=inner)
|
|
109
|
+
# ... pass `stt` to your VoicePipelineAgent as usual.
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
That's it. The agent will see exactly the transcripts it would have
|
|
113
|
+
seen without the wrapper, but with the first turn's enrollment
|
|
114
|
+
frozen into a d-vector and applied to every chunk that follows.
|
|
115
|
+
|
|
116
|
+
## Usage — offline
|
|
117
|
+
|
|
118
|
+
```python
|
|
119
|
+
import numpy as np
|
|
120
|
+
from livekit.plugins.speakerbeamss import OnnxSpeakerBeamExtractor
|
|
121
|
+
|
|
122
|
+
extractor = OnnxSpeakerBeamExtractor() # INT8 by default
|
|
123
|
+
extractor.enroll(np.random.randn(16000).astype(np.float32)) # reference audio
|
|
124
|
+
|
|
125
|
+
chunk = np.random.randn(8000).astype(np.float32) # < 1 s
|
|
126
|
+
print(extractor.append(chunk)) # [] (no full chunk yet)
|
|
127
|
+
print(extractor.append(np.zeros(8000, dtype=np.float32))) # [ndarray of len 16000]
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
## How the state machine works
|
|
131
|
+
|
|
132
|
+
| Phase | Inner STT input | Plugin behavior |
|
|
133
|
+
|------|-----------------|------------------|
|
|
134
|
+
| `CAPTURING` (first user turn) | Raw audio, downmixed to mono 16 kHz | Buffers audio; on `END_OF_SPEECH`, computes d-vector and locks |
|
|
135
|
+
| `LOCKED` (after first turn) | ONNX-extracted mono 16 kHz | Embedding reused for all subsequent user turns until stream ends |
|
|
136
|
+
| `EXTERNAL` (when `reference_audio` was provided) | Raw audio, downmixed to mono 16 kHz | No enrollment phase; extraction applied from the first frame |
|
|
137
|
+
|
|
138
|
+
## Configuration knobs
|
|
139
|
+
|
|
140
|
+
`STT(...)` arguments:
|
|
141
|
+
|
|
142
|
+
| Name | Default | Purpose |
|
|
143
|
+
|------|---------|---------|
|
|
144
|
+
| `inner` | *(required)* | Any `stt.STT` with `streaming=True`. |
|
|
145
|
+
| `reference_audio` | `None` | Path to an enrollment WAV/PCM file. Bypasses the capture phase. |
|
|
146
|
+
| `onnx_dir` | `~/Public/projects/OpenSpeakerBeam-SS/exports` | Fallback directory for `.onnx` files (used only when the bundled model is missing). |
|
|
147
|
+
| `onnx_filename` | `speakerbeam_ss_trained_int8.onnx` (bundled) | Override the exact model filename. Looked up in the bundled `models/` directory first, then on disk. |
|
|
148
|
+
| `chunk_seconds` | `1.0` | ONNX window length. Must match the time axis baked into the export. |
|
|
149
|
+
| `sample_rate` | `16_000` | Sample rate for both extractor and the framework resampler. |
|
|
150
|
+
| `min_enrollment_seconds` | `0.5` | Refuse to lock enrollment from < this much captured audio. |
|
|
151
|
+
| `pass_through_first_utterance` | `True` | When `True`, the first turn reaches the inner STT untouched so the agent's first reply still makes sense. |
|
|
152
|
+
| `interim_results` | *(inherit from inner)* | Capability flag for downstream `VoicePipelineAgent`. |
|
|
153
|
+
|
|
154
|
+
Environment variables:
|
|
155
|
+
|
|
156
|
+
| Var | Purpose |
|
|
157
|
+
|-----|---------|
|
|
158
|
+
| `SPEAKERBEAMSS_ONNX_DIR` | Override `onnx_dir` for one-off runs. |
|
|
159
|
+
|
|
160
|
+
## Verified against
|
|
161
|
+
|
|
162
|
+
- LiveKit Agents `>= 1.5.13`
|
|
163
|
+
- OpenSpeakerBeam-SS commit exporting
|
|
164
|
+
`speakerbeam_ss_trained_int8.onnx` (~13 MB) at opset 20, chunk length
|
|
165
|
+
16 000 samples / 16 kHz — the bundle that ships inside the wheel.
|
|
166
|
+
|
|
167
|
+
## License
|
|
168
|
+
|
|
169
|
+
Apache-2.0 (same as LiveKit Agents).
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
# livekit-plugins-speakerbeamss
|
|
2
|
+
|
|
3
|
+
> A [LiveKit Agents](https://github.com/livekit/agents) STT plugin that
|
|
4
|
+
> runs [OpenSpeakerBeam-SS](../OpenSpeakerBeam-SS) target-speaker
|
|
5
|
+
> extraction in front of any inner STT instance. The agent hears only
|
|
6
|
+
> the user — even with competing speakers, music, or noise in the room.
|
|
7
|
+
|
|
8
|
+
The plugin is **ONNX-only**. The PyTorch separator never ships here.
|
|
9
|
+
The **trained INT8 model is bundled inside the wheel** at
|
|
10
|
+
`livekit/plugins/speakerbeamss/models/speakerbeam_ss_trained_int8.onnx`
|
|
11
|
+
(≈13 MB), so a fresh `pip install livekit-plugins-speakerbeamss` is
|
|
12
|
+
enough — no separate download. Follow step 0 below only if you want to
|
|
13
|
+
swap in a different export (FP32, the base release, or your own
|
|
14
|
+
fine-tune).
|
|
15
|
+
|
|
16
|
+
The reference audio for the target speaker is taken from the
|
|
17
|
+
*agent's first user turn*: the first sentence the user speaks is
|
|
18
|
+
forwarded to the inner STT **as-is** so the agent can still
|
|
19
|
+
understand it, and is *also* kept in a buffer. When the inner STT
|
|
20
|
+
emits `END_OF_SPEECH`, the buffer is collapsed to a Resemblyzer
|
|
21
|
+
d-vector and the plugin flips to extraction mode for every
|
|
22
|
+
subsequent utterance.
|
|
23
|
+
|
|
24
|
+
You can also pass a pre-recorded enrollment audio via
|
|
25
|
+
`reference_audio="path.wav"` to skip the capture phase entirely.
|
|
26
|
+
|
|
27
|
+
## Installation
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
# 1. Install this plugin (from the plugin source root):
|
|
31
|
+
cd livekit/plugins/speakerbeamss
|
|
32
|
+
pip install -e .
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
That's it — `pip install` wires up `livekit.plugins.speakerbeamss`
|
|
36
|
+
*and* ships the trained ONNX bundle, which the loader resolves via
|
|
37
|
+
`importlib.resources`. No env vars, no separate download.
|
|
38
|
+
|
|
39
|
+
### Using a different exported variant
|
|
40
|
+
|
|
41
|
+
If you have your own export (FP32, base release, a re-trained
|
|
42
|
+
checkpoint, …) you'd rather use, point the loader at it explicitly:
|
|
43
|
+
|
|
44
|
+
```python
|
|
45
|
+
from livekit.plugins.speakerbeamss import STT
|
|
46
|
+
|
|
47
|
+
sb_stt = STT(
|
|
48
|
+
inner=inner,
|
|
49
|
+
onnx_dir="/Users/linsan/Public/projects/OpenSpeakerBeam-SS/exports",
|
|
50
|
+
onnx_filename="speakerbeam_ss_int8.onnx", # base INT8 release
|
|
51
|
+
)
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
The loader's lookup order is:
|
|
55
|
+
|
|
56
|
+
1. **Bundled** — `livekit.plugins.speakerbeamss.models/<filename>`
|
|
57
|
+
(the trained INT8 lives here by default).
|
|
58
|
+
2. **Disk** — `{onnx_dir}/{filename}` if set, otherwise the
|
|
59
|
+
`~/Public/projects/OpenSpeakerBeam-SS/exports/` fallback.
|
|
60
|
+
|
|
61
|
+
To export a different variant yourself:
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
cd ~/Public/projects/OpenSpeakerBeam-SS
|
|
65
|
+
pip install -r requirements.txt
|
|
66
|
+
python export_onnx.py --ckpt checkpoints/best_model.pth
|
|
67
|
+
ls exports/ # -> speakerbeam_ss_{fp32,int8,trained_fp32,trained_int8}.onnx
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Usage — wrap any inner STT
|
|
71
|
+
|
|
72
|
+
```python
|
|
73
|
+
from livekit.plugins.speakerbeamss import STT
|
|
74
|
+
from livekit.plugins.volcengine import STT as VolcSTT # any streaming inner STT
|
|
75
|
+
|
|
76
|
+
inner = VolcSTT() # read keys from env, etc.
|
|
77
|
+
stt = STT(inner=inner)
|
|
78
|
+
# ... pass `stt` to your VoicePipelineAgent as usual.
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
That's it. The agent will see exactly the transcripts it would have
|
|
82
|
+
seen without the wrapper, but with the first turn's enrollment
|
|
83
|
+
frozen into a d-vector and applied to every chunk that follows.
|
|
84
|
+
|
|
85
|
+
## Usage — offline
|
|
86
|
+
|
|
87
|
+
```python
|
|
88
|
+
import numpy as np
|
|
89
|
+
from livekit.plugins.speakerbeamss import OnnxSpeakerBeamExtractor
|
|
90
|
+
|
|
91
|
+
extractor = OnnxSpeakerBeamExtractor() # INT8 by default
|
|
92
|
+
extractor.enroll(np.random.randn(16000).astype(np.float32)) # reference audio
|
|
93
|
+
|
|
94
|
+
chunk = np.random.randn(8000).astype(np.float32) # < 1 s
|
|
95
|
+
print(extractor.append(chunk)) # [] (no full chunk yet)
|
|
96
|
+
print(extractor.append(np.zeros(8000, dtype=np.float32))) # [ndarray of len 16000]
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## How the state machine works
|
|
100
|
+
|
|
101
|
+
| Phase | Inner STT input | Plugin behavior |
|
|
102
|
+
|------|-----------------|------------------|
|
|
103
|
+
| `CAPTURING` (first user turn) | Raw audio, downmixed to mono 16 kHz | Buffers audio; on `END_OF_SPEECH`, computes d-vector and locks |
|
|
104
|
+
| `LOCKED` (after first turn) | ONNX-extracted mono 16 kHz | Embedding reused for all subsequent user turns until stream ends |
|
|
105
|
+
| `EXTERNAL` (when `reference_audio` was provided) | Raw audio, downmixed to mono 16 kHz | No enrollment phase; extraction applied from the first frame |
|
|
106
|
+
|
|
107
|
+
## Configuration knobs
|
|
108
|
+
|
|
109
|
+
`STT(...)` arguments:
|
|
110
|
+
|
|
111
|
+
| Name | Default | Purpose |
|
|
112
|
+
|------|---------|---------|
|
|
113
|
+
| `inner` | *(required)* | Any `stt.STT` with `streaming=True`. |
|
|
114
|
+
| `reference_audio` | `None` | Path to an enrollment WAV/PCM file. Bypasses the capture phase. |
|
|
115
|
+
| `onnx_dir` | `~/Public/projects/OpenSpeakerBeam-SS/exports` | Fallback directory for `.onnx` files (used only when the bundled model is missing). |
|
|
116
|
+
| `onnx_filename` | `speakerbeam_ss_trained_int8.onnx` (bundled) | Override the exact model filename. Looked up in the bundled `models/` directory first, then on disk. |
|
|
117
|
+
| `chunk_seconds` | `1.0` | ONNX window length. Must match the time axis baked into the export. |
|
|
118
|
+
| `sample_rate` | `16_000` | Sample rate for both extractor and the framework resampler. |
|
|
119
|
+
| `min_enrollment_seconds` | `0.5` | Refuse to lock enrollment from < this much captured audio. |
|
|
120
|
+
| `pass_through_first_utterance` | `True` | When `True`, the first turn reaches the inner STT untouched so the agent's first reply still makes sense. |
|
|
121
|
+
| `interim_results` | *(inherit from inner)* | Capability flag for downstream `VoicePipelineAgent`. |
|
|
122
|
+
|
|
123
|
+
Environment variables:
|
|
124
|
+
|
|
125
|
+
| Var | Purpose |
|
|
126
|
+
|-----|---------|
|
|
127
|
+
| `SPEAKERBEAMSS_ONNX_DIR` | Override `onnx_dir` for one-off runs. |
|
|
128
|
+
|
|
129
|
+
## Verified against
|
|
130
|
+
|
|
131
|
+
- LiveKit Agents `>= 1.5.13`
|
|
132
|
+
- OpenSpeakerBeam-SS commit exporting
|
|
133
|
+
`speakerbeam_ss_trained_int8.onnx` (~13 MB) at opset 20, chunk length
|
|
134
|
+
16 000 samples / 16 kHz — the bundle that ships inside the wheel.
|
|
135
|
+
|
|
136
|
+
## License
|
|
137
|
+
|
|
138
|
+
Apache-2.0 (same as LiveKit Agents).
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "livekit-plugins-speakerbeamss"
|
|
3
|
+
dynamic = ["version"]
|
|
4
|
+
description = "LiveKit Agents STT plugin that runs OpenSpeakerBeam-SS target-speaker extraction in front of any inner STT."
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
authors = [{ name = "linsan", email = "bin.zaq@foxmail.com" }]
|
|
7
|
+
keywords = ["webrtc", "realtime", "audio", "livekit", "speaker-extraction", "target-speaker", "asr"]
|
|
8
|
+
requires-python = ">=3.10"
|
|
9
|
+
license = { text = "Apache-2.0" }
|
|
10
|
+
dependencies = [
|
|
11
|
+
# LiveKit Agents framework (provides STT base classes, AudioByteStream, AudioBuffer, Plugin)
|
|
12
|
+
"livekit-agents>=1.5.13",
|
|
13
|
+
# ONNX runtime — the *only* inference backend the plugin ships with.
|
|
14
|
+
"onnxruntime>=1.17.0",
|
|
15
|
+
# Resemblyzer provides the d-vector speaker encoder used for enrollment.
|
|
16
|
+
# Resemblyzer itself pulls in torch (used only by the VoiceEncoder, not for the
|
|
17
|
+
# separator — the plugin model is ONNX-only).
|
|
18
|
+
"resemblyzer>=0.1.1",
|
|
19
|
+
# numpy for audio numpy interop; soundfile for offline example I/O.
|
|
20
|
+
"numpy>=1.24",
|
|
21
|
+
"soundfile>=0.12",
|
|
22
|
+
]
|
|
23
|
+
|
|
24
|
+
classifiers = [
|
|
25
|
+
"Intended Audience :: Developers",
|
|
26
|
+
"License :: OSI Approved :: Apache Software License",
|
|
27
|
+
"Topic :: Multimedia :: Sound/Audio",
|
|
28
|
+
"Topic :: Scientific/Engineering :: Artificial Intelligence",
|
|
29
|
+
"Programming Language :: Python :: 3",
|
|
30
|
+
"Programming Language :: Python :: 3.10",
|
|
31
|
+
"Programming Language :: Python :: 3.11",
|
|
32
|
+
"Programming Language :: Python :: 3.12",
|
|
33
|
+
]
|
|
34
|
+
|
|
35
|
+
[project.optional-dependencies]
|
|
36
|
+
test = [
|
|
37
|
+
"pytest>=7.0",
|
|
38
|
+
"pytest-asyncio>=0.21",
|
|
39
|
+
# for the SpeechStream-pattern fake STT used in tests / examples
|
|
40
|
+
"numpy>=1.24",
|
|
41
|
+
# for building the no-op ONNX fixture used in tests
|
|
42
|
+
"onnx>=1.14",
|
|
43
|
+
# resemblyzer needs setuptools < 81 to expose pkg_resources
|
|
44
|
+
"setuptools<81",
|
|
45
|
+
]
|
|
46
|
+
examples = [
|
|
47
|
+
"livekit-plugins-volcengine>=1.3.26",
|
|
48
|
+
]
|
|
49
|
+
|
|
50
|
+
[build-system]
|
|
51
|
+
requires = ["hatchling"]
|
|
52
|
+
build-backend = "hatchling.build"
|
|
53
|
+
|
|
54
|
+
[tool.hatch.version]
|
|
55
|
+
path = "src/livekit/plugins/speakerbeamss/version.py"
|
|
56
|
+
|
|
57
|
+
# Hatch bundles everything under `packages = ["src/livekit"]`, including
|
|
58
|
+
# the trained ONNX file at
|
|
59
|
+
# `src/livekit/plugins/speakerbeamss/models/*.onnx`. The explicit
|
|
60
|
+
# `artifacts` declarations below make that intent obvious and guarantee
|
|
61
|
+
# the binary file lands in both wheel and sdist even if a future revision
|
|
62
|
+
# moves it around.
|
|
63
|
+
[tool.hatch.build.targets.wheel]
|
|
64
|
+
packages = ["src/livekit"]
|
|
65
|
+
artifacts = [
|
|
66
|
+
"src/livekit/plugins/speakerbeamss/models/*.onnx",
|
|
67
|
+
]
|
|
68
|
+
|
|
69
|
+
[tool.hatch.build.targets.sdist]
|
|
70
|
+
include = ["/src"]
|
|
71
|
+
artifacts = [
|
|
72
|
+
"src/livekit/plugins/speakerbeamss/models/*.onnx",
|
|
73
|
+
]
|
|
74
|
+
|
|
75
|
+
[tool.pytest.ini_options]
|
|
76
|
+
asyncio_mode = "auto"
|
|
77
|
+
testpaths = ["tests"]
|
|
78
|
+
log_cli = true
|
|
79
|
+
log_cli_level = "INFO"
|
|
80
|
+
log_cli_format = "%(asctime)s [%(levelname)s] %(name)s: %(message)s"
|
|
81
|
+
log_cli_date_format = "%H:%M:%S"
|
|
82
|
+
markers = [
|
|
83
|
+
"integration: marks tests that require a real exported ONNX bundle under OpenSpeakerBeam-SS/exports/",
|
|
84
|
+
]
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"""LiveKit Agents plugin: target-speaker extraction in front of any STT.
|
|
2
|
+
|
|
3
|
+
Public surface:
|
|
4
|
+
|
|
5
|
+
>>> from livekit.plugins.speakerbeamss import STT
|
|
6
|
+
>>> from livekit.plugins.volcengine import STT as VolcSTT
|
|
7
|
+
>>> stt = STT(inner=VolcSTT()) # generic wrapper
|
|
8
|
+
>>> s = stt.stream(language="zh-CN")
|
|
9
|
+
|
|
10
|
+
Or use the standalone preprocessor without LiveKit:
|
|
11
|
+
|
|
12
|
+
>>> from livekit.plugins.speakerbeamss import (
|
|
13
|
+
... OnnxSpeakerBeamExtractor,
|
|
14
|
+
... EnrollmentState,
|
|
15
|
+
... ExtractorConfig,
|
|
16
|
+
... )
|
|
17
|
+
>>> ext = OnnxSpeakerBeamExtractor()
|
|
18
|
+
>>> ext.enroll(reference_clip) # 1-D numpy float32 at 16 kHz
|
|
19
|
+
>>> out = ext.process(chunk) # chunk of any size
|
|
20
|
+
|
|
21
|
+
The model is ONNX-only: ensure you ran ``python export_onnx.py`` in the
|
|
22
|
+
OpenSpeakerBeam-SS repository (producing ``exports/speakerbeam_ss_*.onnx``)
|
|
23
|
+
and pointed ``ExtractorConfig.onnx_dir`` (or the env var
|
|
24
|
+
``SPEAKERBEAMSS_ONNX_DIR``) at the right directory before importing
|
|
25
|
+
this module.
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
from __future__ import annotations
|
|
29
|
+
|
|
30
|
+
from .plugin import SpeakerBeamSSPlugin
|
|
31
|
+
from .processor import (
|
|
32
|
+
DEFAULT_SAMPLE_RATE,
|
|
33
|
+
EMBEDDING_DIM,
|
|
34
|
+
EnrollmentState,
|
|
35
|
+
ExtractorConfig,
|
|
36
|
+
OnnxSpeakerBeamExtractor,
|
|
37
|
+
)
|
|
38
|
+
from .stt import SpeakerBeamSTT
|
|
39
|
+
from .version import __version__
|
|
40
|
+
|
|
41
|
+
# Alias `STT` to the wrapper class so callers can ``from livekit.plugins
|
|
42
|
+
# .speakerbeamss import STT`` — matches every other LiveKit plugin's
|
|
43
|
+
# primary export shape.
|
|
44
|
+
STT = SpeakerBeamSTT
|
|
45
|
+
|
|
46
|
+
__all__ = [
|
|
47
|
+
"STT",
|
|
48
|
+
"SpeakerBeamSTT",
|
|
49
|
+
"OnnxSpeakerBeamExtractor",
|
|
50
|
+
"ExtractorConfig",
|
|
51
|
+
"EnrollmentState",
|
|
52
|
+
"SpeakerBeamSSPlugin",
|
|
53
|
+
"DEFAULT_SAMPLE_RATE",
|
|
54
|
+
"EMBEDDING_DIM",
|
|
55
|
+
"__version__",
|
|
56
|
+
]
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
# ---------------------------------------------------------------------------
|
|
60
|
+
# Plugin registration
|
|
61
|
+
# ---------------------------------------------------------------------------
|
|
62
|
+
from livekit.agents import Plugin as _Plugin
|
|
63
|
+
|
|
64
|
+
_Plugin.register_plugin(SpeakerBeamSSPlugin())
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
# Cleanup docs of unexported modules — mirrors livekit-plugins-volcengine
|
|
68
|
+
_module = dir()
|
|
69
|
+
NOT_IN_ALL = [m for m in _module if m not in __all__]
|
|
70
|
+
__pdoc__ = {}
|
|
71
|
+
for n in NOT_IN_ALL:
|
|
72
|
+
__pdoc__[n] = False
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"""Bundled SpeakerBeam-SS ONNX models.
|
|
2
|
+
|
|
3
|
+
The trained INT8 model ships inside the wheel so a fresh
|
|
4
|
+
``pip install livekit-plugins-speakerbeamss`` is enough — no separate
|
|
5
|
+
download is needed. ``processor._bundled_model_path`` resolves files
|
|
6
|
+
relative to this package via :mod:`importlib.resources`.
|
|
7
|
+
"""
|
|
Binary file
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"""LiveKit plugin entry-point.
|
|
2
|
+
|
|
3
|
+
Mirrors the pattern in
|
|
4
|
+
``livekit-plugins-volcengine/livekit/plugins/volcengine/__init__.py``.
|
|
5
|
+
Registering an instance via :py:meth:`Plugin.register_plugin` lets the
|
|
6
|
+
framework discover this package at import time (e.g. when LiveKit's
|
|
7
|
+
plugin loader scans for ``livekit.plugins.*`` modules).
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
from livekit.agents import Plugin
|
|
13
|
+
|
|
14
|
+
from .log import logger
|
|
15
|
+
from .version import __version__
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class SpeakerBeamSSPlugin(Plugin):
|
|
19
|
+
"""Plugin descriptor for ``livekit.plugins.speakerbeamss``.
|
|
20
|
+
|
|
21
|
+
Held by LiveKit's global plugin registry. The plugin does not run
|
|
22
|
+
any background work; it just exposes metadata so the framework can
|
|
23
|
+
see this package is installed.
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
def __init__(self) -> None:
|
|
27
|
+
super().__init__(__name__, __version__, __package__, logger)
|
|
28
|
+
logger.info(
|
|
29
|
+
"speakerbeam-ss plugin registered (version=%s, package=%s)",
|
|
30
|
+
__version__,
|
|
31
|
+
__package__,
|
|
32
|
+
)
|