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.
@@ -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,5 @@
1
+ from __future__ import annotations
2
+
3
+ import logging
4
+
5
+ logger = logging.getLogger("livekit.plugins.speakerbeamss")
@@ -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
+ """
@@ -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
+ )