livekit-plugins-azure 0.2.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,38 @@
1
+ Metadata-Version: 2.1
2
+ Name: livekit-plugins-azure
3
+ Version: 0.2.0
4
+ Summary: Agent Framework plugin for services from Azure
5
+ Home-page: https://github.com/livekit/agents
6
+ License: Apache-2.0
7
+ Project-URL: Documentation, https://docs.livekit.io
8
+ Project-URL: Website, https://livekit.io/
9
+ Project-URL: Source, https://github.com/livekit/agents
10
+ Keywords: webrtc,realtime,audio,video,livekit
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: License :: OSI Approved :: Apache Software License
13
+ Classifier: Topic :: Multimedia :: Sound/Audio
14
+ Classifier: Topic :: Multimedia :: Video
15
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.9
18
+ Classifier: Programming Language :: Python :: 3.10
19
+ Classifier: Programming Language :: Python :: 3 :: Only
20
+ Requires-Python: >=3.9.0
21
+ Description-Content-Type: text/markdown
22
+ Requires-Dist: livekit>=0.9.0
23
+ Requires-Dist: livekit-agents>=0.3.0
24
+ Requires-Dist: azure-cognitiveservices-speech>=1.35.0
25
+
26
+ # LiveKit Plugins Azure
27
+
28
+ Agent Framework plugin for services from Azure Cognitive Services. Currently supports STT and TTS.
29
+
30
+ ## Installation
31
+
32
+ ```bash
33
+ pip install livekit-plugins-azure
34
+ ```
35
+
36
+ ## Pre-requisites
37
+
38
+ You'll need to specify an Azure Speech Key and a Deployment Region. They can be set as environment variables: `AZURE_SPEECH_KEY` and `AZURE_SPEECH_REGION`, respectively.
@@ -0,0 +1,13 @@
1
+ # LiveKit Plugins Azure
2
+
3
+ Agent Framework plugin for services from Azure Cognitive Services. Currently supports STT and TTS.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ pip install livekit-plugins-azure
9
+ ```
10
+
11
+ ## Pre-requisites
12
+
13
+ You'll need to specify an Azure Speech Key and a Deployment Region. They can be set as environment variables: `AZURE_SPEECH_KEY` and `AZURE_SPEECH_REGION`, respectively.
@@ -0,0 +1,35 @@
1
+ # Licensed under the Apache License, Version 2.0 (the "License");
2
+ # you may not use this file except in compliance with the License.
3
+ # You may obtain a copy of the License at
4
+ #
5
+ # http://www.apache.org/licenses/LICENSE-2.0
6
+ #
7
+ # Unless required by applicable law or agreed to in writing, software
8
+ # distributed under the License is distributed on an "AS IS" BASIS,
9
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10
+ # See the License for the specific language governing permissions and
11
+ # limitations under the License.
12
+
13
+ from .stt import STT, SpeechStream
14
+ from .tts import TTS
15
+ from .version import __version__
16
+
17
+ __all__ = [
18
+ "STT",
19
+ "SpeechStream",
20
+ "TTS",
21
+ "__version__",
22
+ ]
23
+
24
+ from livekit.agents import Plugin
25
+
26
+
27
+ class AzurePlugin(Plugin):
28
+ def __init__(self):
29
+ super().__init__(__name__, __version__, __package__)
30
+
31
+ def download_files(self):
32
+ pass
33
+
34
+
35
+ Plugin.register_plugin(AzurePlugin())
@@ -0,0 +1,3 @@
1
+ import logging
2
+
3
+ logger = logging.getLogger("livekit.plugins.azure")
@@ -0,0 +1,224 @@
1
+ # Licensed under the Apache License, Version 2.0 (the "License");
2
+ # you may not use this file except in compliance with the License.
3
+ # You may obtain a copy of the License at
4
+ #
5
+ # http://www.apache.org/licenses/LICENSE-2.0
6
+ #
7
+ # Unless required by applicable law or agreed to in writing, software
8
+ # distributed under the License is distributed on an "AS IS" BASIS,
9
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10
+ # See the License for the specific language governing permissions and
11
+ # limitations under the License.
12
+
13
+ from __future__ import annotations
14
+
15
+ import asyncio
16
+ import os
17
+ from dataclasses import dataclass
18
+ from typing import Optional
19
+
20
+ from livekit import rtc
21
+ from livekit.agents import stt
22
+ from livekit.agents.utils import AudioBuffer
23
+
24
+ import azure.cognitiveservices.speech as speechsdk
25
+
26
+ from .log import logger
27
+
28
+
29
+ @dataclass
30
+ class STTOptions:
31
+ speech_key: str
32
+ speech_region: str
33
+ sample_rate: int
34
+ num_channels: int
35
+ languages: list[
36
+ str
37
+ ] # see https://learn.microsoft.com/en-us/azure/ai-services/speech-service/language-support?tabs=stt
38
+
39
+
40
+ class STT(stt.STT):
41
+ def __init__(
42
+ self,
43
+ *,
44
+ speech_key: str | None = None,
45
+ speech_region: str | None = None,
46
+ sample_rate: int = 48000,
47
+ num_channels: int = 1,
48
+ languages: list[str] = [], # when empty, auto-detect the language
49
+ ):
50
+ super().__init__(streaming_supported=True)
51
+
52
+ speech_key = speech_key or os.environ.get("AZURE_SPEECH_KEY")
53
+ if not speech_key:
54
+ raise ValueError("AZURE_SPEECH_KEY must be set")
55
+
56
+ speech_region = speech_region or os.environ.get("AZURE_SPEECH_REGION")
57
+ if not speech_region:
58
+ raise ValueError("AZURE_SPEECH_REGION must be set")
59
+
60
+ self._config = STTOptions(
61
+ speech_key=speech_key,
62
+ speech_region=speech_region,
63
+ languages=languages,
64
+ sample_rate=sample_rate,
65
+ num_channels=num_channels,
66
+ )
67
+
68
+ async def recognize(
69
+ self,
70
+ *,
71
+ buffer: AudioBuffer,
72
+ language: str | None = None,
73
+ ) -> stt.SpeechEvent:
74
+ raise NotImplementedError("Azure STT does not support single frame recognition")
75
+
76
+ def stream(
77
+ self,
78
+ *,
79
+ language: str | None = None,
80
+ ) -> "SpeechStream":
81
+ return SpeechStream(self._config)
82
+
83
+
84
+ class SpeechStream(stt.SpeechStream):
85
+ def __init__(self, opts: STTOptions) -> None:
86
+ super().__init__()
87
+ self._opts = opts
88
+ self._event_queue = asyncio.Queue[Optional[stt.SpeechEvent]]()
89
+ self._closed = False
90
+ self._speaking = False
91
+
92
+ self._stream = speechsdk.audio.PushAudioInputStream(
93
+ stream_format=speechsdk.audio.AudioStreamFormat(
94
+ samples_per_second=self._opts.sample_rate,
95
+ bits_per_sample=16,
96
+ channels=self._opts.num_channels,
97
+ )
98
+ )
99
+ self._recognizer = _create_speech_recognizer(
100
+ config=self._opts, stream=self._stream
101
+ )
102
+ self._recognizer.recognizing.connect(self._on_recognizing)
103
+ self._recognizer.recognized.connect(self._on_recognized)
104
+ self._recognizer.speech_start_detected.connect(self._on_speech_start)
105
+ self._recognizer.speech_end_detected.connect(self._on_speech_end)
106
+ self._recognizer.session_stopped.connect(self._on_session_stopped)
107
+ self._recognizer.start_continuous_recognition()
108
+ self._done_event = asyncio.Event()
109
+ self._loop = asyncio.get_running_loop()
110
+
111
+ def push_frame(self, frame: rtc.AudioFrame) -> None:
112
+ if self._closed:
113
+ raise ValueError("cannot push frame to closed stream")
114
+
115
+ self._stream.write(frame.data.tobytes())
116
+
117
+ async def aclose(self, *, wait: bool = True) -> None:
118
+ if self._closed:
119
+ return
120
+
121
+ self._closed = True
122
+ self._stream.close()
123
+
124
+ await self._done_event.wait()
125
+
126
+ def _cleanup():
127
+ self._recognizer.stop_continuous_recognition()
128
+ del self._recognizer
129
+
130
+ await asyncio.to_thread(_cleanup)
131
+
132
+ def _on_recognized(self, evt: speechsdk.SpeechRecognitionEventArgs):
133
+ detected_lg = speechsdk.AutoDetectSourceLanguageResult(evt.result).language
134
+ text = evt.result.text.strip()
135
+ if not text:
136
+ return
137
+
138
+ final_data = stt.SpeechData(
139
+ language=detected_lg,
140
+ confidence=1.0,
141
+ text=evt.result.text,
142
+ )
143
+
144
+ self._threadsafe_put(
145
+ stt.SpeechEvent(
146
+ type=stt.SpeechEventType.FINAL_TRANSCRIPT,
147
+ alternatives=[final_data],
148
+ )
149
+ )
150
+
151
+ def _on_recognizing(self, evt: speechsdk.SpeechRecognitionEventArgs):
152
+ detected_lg = speechsdk.AutoDetectSourceLanguageResult(evt.result).language
153
+ text = evt.result.text.strip()
154
+ if not text:
155
+ return
156
+
157
+ interim_data = stt.SpeechData(
158
+ language=detected_lg,
159
+ confidence=0.0,
160
+ text=evt.result.text,
161
+ )
162
+
163
+ self._threadsafe_put(
164
+ stt.SpeechEvent(
165
+ type=stt.SpeechEventType.INTERIM_TRANSCRIPT,
166
+ alternatives=[interim_data],
167
+ )
168
+ )
169
+
170
+ def _on_speech_start(self, evt: speechsdk.SpeechRecognitionEventArgs):
171
+ if self._speaking:
172
+ return
173
+
174
+ self._speaking = True
175
+ self._threadsafe_put(stt.SpeechEvent(type=stt.SpeechEventType.START_OF_SPEECH))
176
+
177
+ def _on_speech_end(self, evt: speechsdk.SpeechRecognitionEventArgs):
178
+ if not self._speaking:
179
+ return
180
+
181
+ self._speaking = False
182
+ self._threadsafe_put(stt.SpeechEvent(type=stt.SpeechEventType.END_OF_SPEECH))
183
+
184
+ def _on_session_stopped(self, evt: speechsdk.SpeechRecognitionEventArgs):
185
+ if not self._closed:
186
+ logger.error("session stopped unexpectedly")
187
+
188
+ self._loop.call_soon_threadsafe(self._done_event.set)
189
+ self._threadsafe_put(None)
190
+
191
+ def _threadsafe_put(self, evt: stt.SpeechEvent | None):
192
+ self._loop.call_soon_threadsafe(self._event_queue.put_nowait, evt)
193
+
194
+ async def __anext__(self) -> stt.SpeechEvent:
195
+ evt = await self._event_queue.get()
196
+ if evt is None:
197
+ raise StopAsyncIteration
198
+
199
+ return evt
200
+
201
+
202
+ def _create_speech_recognizer(
203
+ *, config: STTOptions, stream: speechsdk.audio.AudioInputStream
204
+ ) -> speechsdk.SpeechRecognizer:
205
+ speech_config = speechsdk.SpeechConfig(
206
+ subscription=config.speech_key, region=config.speech_region
207
+ )
208
+
209
+ auto_detect_source_language_config = None
210
+ if config.languages:
211
+ auto_detect_source_language_config = (
212
+ speechsdk.languageconfig.AutoDetectSourceLanguageConfig(
213
+ languages=config.languages
214
+ )
215
+ )
216
+
217
+ audio_config = speechsdk.audio.AudioConfig(stream=stream)
218
+ speech_recognizer = speechsdk.SpeechRecognizer(
219
+ speech_config=speech_config,
220
+ audio_config=audio_config,
221
+ auto_detect_source_language_config=auto_detect_source_language_config, # type: ignore
222
+ )
223
+
224
+ return speech_recognizer
@@ -0,0 +1,168 @@
1
+ # Licensed under the Apache License, Version 2.0 (the "License");
2
+ # you may not use this file except in compliance with the License.
3
+ # You may obtain a copy of the License at
4
+ #
5
+ # http://www.apache.org/licenses/LICENSE-2.0
6
+ #
7
+ # Unless required by applicable law or agreed to in writing, software
8
+ # distributed under the License is distributed on an "AS IS" BASIS,
9
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10
+ # See the License for the specific language governing permissions and
11
+ # limitations under the License.
12
+
13
+ from __future__ import annotations
14
+
15
+ import asyncio
16
+ import contextlib
17
+ import os
18
+ from dataclasses import dataclass
19
+ from typing import Optional
20
+
21
+ from livekit import rtc
22
+ from livekit.agents import tts
23
+
24
+ import azure.cognitiveservices.speech as speechsdk
25
+
26
+ from .log import logger
27
+
28
+ AZURE_SAMPLE_RATE: int = 16000
29
+ AZURE_BITS_PER_SAMPLE: int = 16
30
+ AZURE_NUM_CHANNELS: int = 1
31
+
32
+
33
+ @dataclass
34
+ class _TTSOptions:
35
+ speech_key: str | None = None
36
+ speech_region: str | None = None
37
+ # see https://learn.microsoft.com/en-us/azure/ai-services/speech-service/language-support?tabs=tts
38
+ voice: str | None = None
39
+
40
+
41
+ class TTS(tts.TTS):
42
+ def __init__(
43
+ self,
44
+ *,
45
+ speech_key: str | None = None,
46
+ speech_region: str | None = None,
47
+ voice: str | None = None,
48
+ ) -> None:
49
+ super().__init__(
50
+ streaming_supported=False,
51
+ sample_rate=AZURE_SAMPLE_RATE,
52
+ num_channels=AZURE_NUM_CHANNELS,
53
+ )
54
+
55
+ speech_key = speech_key or os.environ.get("AZURE_SPEECH_KEY")
56
+ if not speech_key:
57
+ raise ValueError("AZURE_SPEECH_KEY must be set")
58
+
59
+ speech_region = speech_region or os.environ.get("AZURE_SPEECH_REGION")
60
+ if not speech_region:
61
+ raise ValueError("AZURE_SPEECH_REGION must be set")
62
+
63
+ self._opts = _TTSOptions(
64
+ speech_key=speech_key,
65
+ speech_region=speech_region,
66
+ voice=voice,
67
+ )
68
+
69
+ def synthesize(
70
+ self,
71
+ text: str,
72
+ ) -> "ChunkedStream":
73
+ return ChunkedStream(text, self._opts)
74
+
75
+
76
+ class ChunkedStream(tts.ChunkedStream):
77
+ def __init__(self, text: str, opts: _TTSOptions) -> None:
78
+ self._opts = opts
79
+ self._text = text
80
+ self._main_task: asyncio.Task | None = None
81
+ self._queue = asyncio.Queue[Optional[tts.SynthesizedAudio]]()
82
+
83
+ async def _run(self):
84
+ try:
85
+ stream_callback = _PushAudioOutputStreamCallback(
86
+ asyncio.get_running_loop(), self._queue
87
+ )
88
+ push_stream = speechsdk.audio.PushAudioOutputStream(stream_callback)
89
+ synthesizer = _create_speech_synthesizer(
90
+ config=self._opts, stream=push_stream
91
+ )
92
+
93
+ def _synthesize() -> speechsdk.SpeechSynthesisResult:
94
+ return synthesizer.speak_text_async(self._text).get() # type: ignore
95
+
96
+ result = await asyncio.to_thread(_synthesize)
97
+ if result.reason != speechsdk.ResultReason.SynthesizingAudioCompleted:
98
+ raise ValueError(
99
+ f"failed to synthesize audio: {result.reason} {result.cancellation_details}"
100
+ )
101
+
102
+ def _cleanup() -> None:
103
+ nonlocal synthesizer, result
104
+ del synthesizer
105
+ del result
106
+
107
+ await asyncio.to_thread(_cleanup)
108
+
109
+ except Exception:
110
+ logger.exception("failed to synthesize")
111
+ finally:
112
+ self._queue.put_nowait(None)
113
+
114
+ async def __anext__(self) -> tts.SynthesizedAudio:
115
+ if not self._main_task:
116
+ self._main_task = asyncio.create_task(self._run())
117
+
118
+ frame = await self._queue.get()
119
+ if frame is None:
120
+ raise StopAsyncIteration
121
+
122
+ return frame
123
+
124
+ async def aclose(self) -> None:
125
+ if not self._main_task:
126
+ return
127
+
128
+ self._main_task.cancel()
129
+ with contextlib.suppress(asyncio.CancelledError):
130
+ await self._main_task
131
+
132
+
133
+ def _create_speech_synthesizer(
134
+ *, config: _TTSOptions, stream: speechsdk.audio.AudioOutputStream
135
+ ) -> speechsdk.SpeechSynthesizer:
136
+ speech_config = speechsdk.SpeechConfig(
137
+ subscription=config.speech_key, region=config.speech_region
138
+ )
139
+ stream_config = speechsdk.audio.AudioOutputConfig(stream=stream)
140
+ if config.voice is not None:
141
+ speech_config.speech_synthesis_voice_name = config.voice
142
+
143
+ return speechsdk.SpeechSynthesizer(
144
+ speech_config=speech_config, audio_config=stream_config
145
+ )
146
+
147
+
148
+ class _PushAudioOutputStreamCallback(speechsdk.audio.PushAudioOutputStreamCallback):
149
+ def __init__(
150
+ self,
151
+ loop: asyncio.AbstractEventLoop,
152
+ event_queue: asyncio.Queue[tts.SynthesizedAudio | None],
153
+ ):
154
+ super().__init__()
155
+ self._event_queue = event_queue
156
+ self._loop = loop
157
+
158
+ def write(self, audio_buffer: memoryview) -> int:
159
+ audio_frame = rtc.AudioFrame(
160
+ data=audio_buffer,
161
+ sample_rate=AZURE_SAMPLE_RATE,
162
+ num_channels=AZURE_NUM_CHANNELS,
163
+ samples_per_channel=audio_buffer.nbytes // 2,
164
+ )
165
+
166
+ audio = tts.SynthesizedAudio(text="", data=audio_frame)
167
+ self._loop.call_soon_threadsafe(self._event_queue.put_nowait, audio)
168
+ return audio_buffer.nbytes
@@ -0,0 +1,13 @@
1
+ # Licensed under the Apache License, Version 2.0 (the "License");
2
+ # you may not use this file except in compliance with the License.
3
+ # You may obtain a copy of the License at
4
+ #
5
+ # http://www.apache.org/licenses/LICENSE-2.0
6
+ #
7
+ # Unless required by applicable law or agreed to in writing, software
8
+ # distributed under the License is distributed on an "AS IS" BASIS,
9
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10
+ # See the License for the specific language governing permissions and
11
+ # limitations under the License.
12
+
13
+ __version__ = "0.2.0"
@@ -0,0 +1,38 @@
1
+ Metadata-Version: 2.1
2
+ Name: livekit-plugins-azure
3
+ Version: 0.2.0
4
+ Summary: Agent Framework plugin for services from Azure
5
+ Home-page: https://github.com/livekit/agents
6
+ License: Apache-2.0
7
+ Project-URL: Documentation, https://docs.livekit.io
8
+ Project-URL: Website, https://livekit.io/
9
+ Project-URL: Source, https://github.com/livekit/agents
10
+ Keywords: webrtc,realtime,audio,video,livekit
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: License :: OSI Approved :: Apache Software License
13
+ Classifier: Topic :: Multimedia :: Sound/Audio
14
+ Classifier: Topic :: Multimedia :: Video
15
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.9
18
+ Classifier: Programming Language :: Python :: 3.10
19
+ Classifier: Programming Language :: Python :: 3 :: Only
20
+ Requires-Python: >=3.9.0
21
+ Description-Content-Type: text/markdown
22
+ Requires-Dist: livekit>=0.9.0
23
+ Requires-Dist: livekit-agents>=0.3.0
24
+ Requires-Dist: azure-cognitiveservices-speech>=1.35.0
25
+
26
+ # LiveKit Plugins Azure
27
+
28
+ Agent Framework plugin for services from Azure Cognitive Services. Currently supports STT and TTS.
29
+
30
+ ## Installation
31
+
32
+ ```bash
33
+ pip install livekit-plugins-azure
34
+ ```
35
+
36
+ ## Pre-requisites
37
+
38
+ You'll need to specify an Azure Speech Key and a Deployment Region. They can be set as environment variables: `AZURE_SPEECH_KEY` and `AZURE_SPEECH_REGION`, respectively.
@@ -0,0 +1,13 @@
1
+ README.md
2
+ pyproject.toml
3
+ setup.py
4
+ livekit/plugins/azure/__init__.py
5
+ livekit/plugins/azure/log.py
6
+ livekit/plugins/azure/stt.py
7
+ livekit/plugins/azure/tts.py
8
+ livekit/plugins/azure/version.py
9
+ livekit_plugins_azure.egg-info/PKG-INFO
10
+ livekit_plugins_azure.egg-info/SOURCES.txt
11
+ livekit_plugins_azure.egg-info/dependency_links.txt
12
+ livekit_plugins_azure.egg-info/requires.txt
13
+ livekit_plugins_azure.egg-info/top_level.txt
@@ -0,0 +1,3 @@
1
+ livekit>=0.9.0
2
+ livekit-agents>=0.3.0
3
+ azure-cognitiveservices-speech>=1.35.0
@@ -0,0 +1,3 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61.0"]
3
+ build-backend = "setuptools.build_meta"
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,59 @@
1
+ # Licensed under the Apache License, Version 2.0 (the "License");
2
+ # you may not use this file except in compliance with the License.
3
+ # You may obtain a copy of the License at
4
+ #
5
+ # http://www.apache.org/licenses/LICENSE-2.0
6
+ #
7
+ # Unless required by applicable law or agreed to in writing, software
8
+ # distributed under the License is distributed on an "AS IS" BASIS,
9
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10
+ # See the License for the specific language governing permissions and
11
+ # limitations under the License.
12
+
13
+ import os
14
+ import pathlib
15
+
16
+ import setuptools
17
+ import setuptools.command.build_py
18
+
19
+ here = pathlib.Path(__file__).parent.resolve()
20
+ about = {}
21
+ with open(os.path.join(here, "livekit", "plugins", "azure", "version.py"), "r") as f:
22
+ exec(f.read(), about)
23
+
24
+
25
+ setuptools.setup(
26
+ name="livekit-plugins-azure",
27
+ version=about["__version__"],
28
+ description="Agent Framework plugin for services from Azure",
29
+ long_description=(here / "README.md").read_text(encoding="utf-8"),
30
+ long_description_content_type="text/markdown",
31
+ url="https://github.com/livekit/agents",
32
+ cmdclass={},
33
+ classifiers=[
34
+ "Intended Audience :: Developers",
35
+ "License :: OSI Approved :: Apache Software License",
36
+ "Topic :: Multimedia :: Sound/Audio",
37
+ "Topic :: Multimedia :: Video",
38
+ "Topic :: Scientific/Engineering :: Artificial Intelligence",
39
+ "Programming Language :: Python :: 3",
40
+ "Programming Language :: Python :: 3.9",
41
+ "Programming Language :: Python :: 3.10",
42
+ "Programming Language :: Python :: 3 :: Only",
43
+ ],
44
+ keywords=["webrtc", "realtime", "audio", "video", "livekit"],
45
+ license="Apache-2.0",
46
+ packages=setuptools.find_namespace_packages(include=["livekit.*"]),
47
+ python_requires=">=3.9.0",
48
+ install_requires=[
49
+ "livekit >= 0.9.0",
50
+ "livekit-agents >= 0.3.0",
51
+ "azure-cognitiveservices-speech >= 1.35.0",
52
+ ],
53
+ package_data={},
54
+ project_urls={
55
+ "Documentation": "https://docs.livekit.io",
56
+ "Website": "https://livekit.io/",
57
+ "Source": "https://github.com/livekit/agents",
58
+ },
59
+ )