livekit 0.7.0.dev1__tar.gz → 0.7.1.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.
- {livekit-0.7.0.dev1 → livekit-0.7.1.dev1}/PKG-INFO +3 -3
- {livekit-0.7.0.dev1 → livekit-0.7.1.dev1}/livekit/rtc/__init__.py +63 -2
- {livekit-0.7.0.dev1 → livekit-0.7.1.dev1}/livekit/rtc/_ffi_client.py +23 -14
- {livekit-0.7.0.dev1 → livekit-0.7.1.dev1}/livekit/rtc/_utils.py +21 -0
- {livekit-0.7.0.dev1 → livekit-0.7.1.dev1}/livekit/rtc/audio_frame.py +3 -3
- {livekit-0.7.0.dev1 → livekit-0.7.1.dev1}/livekit/rtc/audio_source.py +5 -5
- {livekit-0.7.0.dev1 → livekit-0.7.1.dev1}/livekit/rtc/audio_stream.py +7 -6
- {livekit-0.7.0.dev1 → livekit-0.7.1.dev1}/livekit/rtc/e2ee.py +11 -11
- {livekit-0.7.0.dev1 → livekit-0.7.1.dev1}/livekit/rtc/participant.py +13 -12
- livekit-0.7.1.dev1/livekit/rtc/resources/__init__.py +1 -0
- {livekit-0.7.0.dev1 → livekit-0.7.1.dev1}/livekit/rtc/room.py +27 -15
- {livekit-0.7.0.dev1 → livekit-0.7.1.dev1}/livekit/rtc/track.py +6 -6
- {livekit-0.7.0.dev1 → livekit-0.7.1.dev1}/livekit/rtc/track_publication.py +2 -2
- livekit-0.7.1.dev1/livekit/rtc/version.py +1 -0
- {livekit-0.7.0.dev1 → livekit-0.7.1.dev1}/livekit/rtc/video_frame.py +5 -5
- {livekit-0.7.0.dev1 → livekit-0.7.1.dev1}/livekit/rtc/video_source.py +3 -3
- {livekit-0.7.0.dev1 → livekit-0.7.1.dev1}/livekit/rtc/video_stream.py +7 -6
- {livekit-0.7.0.dev1 → livekit-0.7.1.dev1}/livekit.egg-info/PKG-INFO +3 -3
- {livekit-0.7.0.dev1 → livekit-0.7.1.dev1}/livekit.egg-info/SOURCES.txt +2 -1
- livekit-0.7.1.dev1/livekit.egg-info/requires.txt +2 -0
- {livekit-0.7.0.dev1 → livekit-0.7.1.dev1}/pyproject.toml +2 -0
- {livekit-0.7.0.dev1 → livekit-0.7.1.dev1}/setup.py +3 -29
- livekit-0.7.0.dev1/livekit/rtc/version.py +0 -1
- livekit-0.7.0.dev1/livekit.egg-info/requires.txt +0 -2
- {livekit-0.7.0.dev1 → livekit-0.7.1.dev1}/README.md +0 -0
- {livekit-0.7.0.dev1 → livekit-0.7.1.dev1}/livekit/rtc/_event_emitter.py +0 -0
- {livekit-0.7.0.dev1 → livekit-0.7.1.dev1}/livekit/rtc/_proto/__init__.py +0 -0
- {livekit-0.7.0.dev1 → livekit-0.7.1.dev1}/livekit/rtc/_proto/audio_frame_pb2.py +0 -0
- {livekit-0.7.0.dev1 → livekit-0.7.1.dev1}/livekit/rtc/_proto/audio_frame_pb2.pyi +0 -0
- {livekit-0.7.0.dev1 → livekit-0.7.1.dev1}/livekit/rtc/_proto/e2ee_pb2.py +0 -0
- {livekit-0.7.0.dev1 → livekit-0.7.1.dev1}/livekit/rtc/_proto/e2ee_pb2.pyi +0 -0
- {livekit-0.7.0.dev1 → livekit-0.7.1.dev1}/livekit/rtc/_proto/ffi_pb2.py +0 -0
- {livekit-0.7.0.dev1 → livekit-0.7.1.dev1}/livekit/rtc/_proto/ffi_pb2.pyi +0 -0
- {livekit-0.7.0.dev1 → livekit-0.7.1.dev1}/livekit/rtc/_proto/handle_pb2.py +0 -0
- {livekit-0.7.0.dev1 → livekit-0.7.1.dev1}/livekit/rtc/_proto/handle_pb2.pyi +0 -0
- {livekit-0.7.0.dev1 → livekit-0.7.1.dev1}/livekit/rtc/_proto/participant_pb2.py +0 -0
- {livekit-0.7.0.dev1 → livekit-0.7.1.dev1}/livekit/rtc/_proto/participant_pb2.pyi +0 -0
- {livekit-0.7.0.dev1 → livekit-0.7.1.dev1}/livekit/rtc/_proto/room_pb2.py +0 -0
- {livekit-0.7.0.dev1 → livekit-0.7.1.dev1}/livekit/rtc/_proto/room_pb2.pyi +0 -0
- {livekit-0.7.0.dev1 → livekit-0.7.1.dev1}/livekit/rtc/_proto/stats_pb2.py +0 -0
- {livekit-0.7.0.dev1 → livekit-0.7.1.dev1}/livekit/rtc/_proto/stats_pb2.pyi +0 -0
- {livekit-0.7.0.dev1 → livekit-0.7.1.dev1}/livekit/rtc/_proto/track_pb2.py +0 -0
- {livekit-0.7.0.dev1 → livekit-0.7.1.dev1}/livekit/rtc/_proto/track_pb2.pyi +0 -0
- {livekit-0.7.0.dev1 → livekit-0.7.1.dev1}/livekit/rtc/_proto/video_frame_pb2.py +0 -0
- {livekit-0.7.0.dev1 → livekit-0.7.1.dev1}/livekit/rtc/_proto/video_frame_pb2.pyi +0 -0
- {livekit-0.7.0.dev1 → livekit-0.7.1.dev1}/livekit.egg-info/dependency_links.txt +0 -0
- {livekit-0.7.0.dev1 → livekit-0.7.1.dev1}/livekit.egg-info/top_level.txt +0 -0
- {livekit-0.7.0.dev1 → livekit-0.7.1.dev1}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: livekit
|
|
3
|
-
Version: 0.7.
|
|
3
|
+
Version: 0.7.1.dev1
|
|
4
4
|
Summary: Python Real-time SDK for LiveKit
|
|
5
5
|
Home-page: https://github.com/livekit/python-sdks
|
|
6
6
|
License: Apache-2.0
|
|
@@ -19,8 +19,8 @@ Classifier: Programming Language :: Python :: 3.10
|
|
|
19
19
|
Classifier: Programming Language :: Python :: 3 :: Only
|
|
20
20
|
Requires-Python: >=3.9.0
|
|
21
21
|
Description-Content-Type: text/markdown
|
|
22
|
-
Requires-Dist: protobuf>=
|
|
23
|
-
Requires-Dist: types-protobuf>=
|
|
22
|
+
Requires-Dist: protobuf>=4
|
|
23
|
+
Requires-Dist: types-protobuf>=4
|
|
24
24
|
|
|
25
25
|
# LiveKit Real-time Python SDK
|
|
26
26
|
|
|
@@ -15,7 +15,6 @@
|
|
|
15
15
|
"""LiveKit RTC SDK
|
|
16
16
|
"""
|
|
17
17
|
|
|
18
|
-
# flake8: noqa
|
|
19
18
|
from ._proto.room_pb2 import (
|
|
20
19
|
ConnectionQuality,
|
|
21
20
|
ConnectionState,
|
|
@@ -33,7 +32,7 @@ from .audio_frame import AudioFrame
|
|
|
33
32
|
from .audio_source import AudioSource
|
|
34
33
|
from .audio_stream import AudioStream
|
|
35
34
|
from .participant import LocalParticipant, Participant, RemoteParticipant
|
|
36
|
-
from .room import ConnectError, Room, RoomOptions, RtcConfiguration
|
|
35
|
+
from .room import ConnectError, Room, RoomOptions, RtcConfiguration, DataPacket
|
|
37
36
|
from .track import (
|
|
38
37
|
LocalAudioTrack,
|
|
39
38
|
LocalVideoTrack,
|
|
@@ -75,3 +74,65 @@ from .video_source import VideoSource
|
|
|
75
74
|
from .video_stream import VideoStream
|
|
76
75
|
|
|
77
76
|
from .version import __version__
|
|
77
|
+
|
|
78
|
+
__all__ = [
|
|
79
|
+
"ConnectionQuality",
|
|
80
|
+
"ConnectionState",
|
|
81
|
+
"DataPacketKind",
|
|
82
|
+
"TrackPublishOptions",
|
|
83
|
+
"IceTransportType",
|
|
84
|
+
"ContinualGatheringPolicy",
|
|
85
|
+
"IceServer",
|
|
86
|
+
"EncryptionType",
|
|
87
|
+
"EncryptionState",
|
|
88
|
+
"StreamState",
|
|
89
|
+
"TrackKind",
|
|
90
|
+
"TrackSource",
|
|
91
|
+
"VideoFormatType",
|
|
92
|
+
"VideoFrameBufferType",
|
|
93
|
+
"VideoRotation",
|
|
94
|
+
"stats",
|
|
95
|
+
"AudioFrame",
|
|
96
|
+
"AudioSource",
|
|
97
|
+
"AudioStream",
|
|
98
|
+
"LocalParticipant",
|
|
99
|
+
"Participant",
|
|
100
|
+
"RemoteParticipant",
|
|
101
|
+
"ConnectError",
|
|
102
|
+
"Room",
|
|
103
|
+
"RoomOptions",
|
|
104
|
+
"RtcConfiguration",
|
|
105
|
+
"DataPacket",
|
|
106
|
+
"LocalAudioTrack",
|
|
107
|
+
"LocalVideoTrack",
|
|
108
|
+
"RemoteAudioTrack",
|
|
109
|
+
"RemoteVideoTrack",
|
|
110
|
+
"Track",
|
|
111
|
+
"LocalTrack",
|
|
112
|
+
"RemoteTrack",
|
|
113
|
+
"AudioTrack",
|
|
114
|
+
"VideoTrack",
|
|
115
|
+
"E2EEManager",
|
|
116
|
+
"E2EEOptions",
|
|
117
|
+
"KeyProviderOptions",
|
|
118
|
+
"KeyProvider",
|
|
119
|
+
"FrameCryptor",
|
|
120
|
+
"LocalTrackPublication",
|
|
121
|
+
"RemoteTrackPublication",
|
|
122
|
+
"TrackPublication",
|
|
123
|
+
"ArgbFrame",
|
|
124
|
+
"I010Buffer",
|
|
125
|
+
"I420ABuffer",
|
|
126
|
+
"I420Buffer",
|
|
127
|
+
"I422Buffer",
|
|
128
|
+
"NativeVideoBuffer",
|
|
129
|
+
"NV12Buffer",
|
|
130
|
+
"PlanarYuv8Buffer",
|
|
131
|
+
"PlanarYuv16Buffer",
|
|
132
|
+
"PlanarYuvBuffer",
|
|
133
|
+
"VideoFrame",
|
|
134
|
+
"VideoFrameBuffer",
|
|
135
|
+
"VideoSource",
|
|
136
|
+
"VideoStream",
|
|
137
|
+
"__version__",
|
|
138
|
+
]
|
|
@@ -13,22 +13,26 @@
|
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
15
|
import asyncio
|
|
16
|
-
import
|
|
16
|
+
from contextlib import ExitStack
|
|
17
17
|
import ctypes
|
|
18
|
+
import importlib.resources
|
|
19
|
+
import logging
|
|
18
20
|
import os
|
|
19
21
|
import platform
|
|
22
|
+
import atexit
|
|
20
23
|
import threading
|
|
21
24
|
from typing import Generic, List, Optional, TypeVar
|
|
22
25
|
|
|
23
|
-
import pkg_resources
|
|
24
|
-
|
|
25
26
|
from ._proto import ffi_pb2 as proto_ffi
|
|
26
|
-
from ._utils import Queue
|
|
27
|
+
from ._utils import Queue, classproperty
|
|
27
28
|
|
|
28
29
|
logger = logging.getLogger("livekit")
|
|
29
30
|
|
|
31
|
+
_resource_files = ExitStack()
|
|
32
|
+
atexit.register(_resource_files.close)
|
|
33
|
+
|
|
30
34
|
|
|
31
|
-
def
|
|
35
|
+
def get_ffi_lib():
|
|
32
36
|
# allow to override the lib path using an env var
|
|
33
37
|
libpath = os.environ.get("LIVEKIT_LIB_PATH", "").strip()
|
|
34
38
|
if libpath:
|
|
@@ -46,13 +50,13 @@ def get_ffi_lib_path():
|
|
|
46
50
|
Set LIVEKIT_LIB_PATH to specify a the lib path"
|
|
47
51
|
)
|
|
48
52
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
)
|
|
52
|
-
return
|
|
53
|
+
res = importlib.resources.files("livekit.rtc.resources") / libname
|
|
54
|
+
ctx = importlib.resources.as_file(res)
|
|
55
|
+
path = _resource_files.enter_context(ctx)
|
|
56
|
+
return ctypes.CDLL(str(path))
|
|
53
57
|
|
|
54
58
|
|
|
55
|
-
ffi_lib =
|
|
59
|
+
ffi_lib = get_ffi_lib()
|
|
56
60
|
ffi_cb_fnc = ctypes.CFUNCTYPE(None, ctypes.POINTER(ctypes.c_uint8), ctypes.c_size_t)
|
|
57
61
|
|
|
58
62
|
# C function types
|
|
@@ -142,7 +146,7 @@ def ffi_event_callback(
|
|
|
142
146
|
|
|
143
147
|
return # no need to queue the logs
|
|
144
148
|
|
|
145
|
-
|
|
149
|
+
FfiClient.instance.queue.put(event)
|
|
146
150
|
|
|
147
151
|
|
|
148
152
|
def to_python_level(level: proto_ffi.LogLevel.ValueType) -> int:
|
|
@@ -161,6 +165,14 @@ def to_python_level(level: proto_ffi.LogLevel.ValueType) -> int:
|
|
|
161
165
|
|
|
162
166
|
|
|
163
167
|
class FfiClient:
|
|
168
|
+
_instance: Optional["FfiClient"] = None
|
|
169
|
+
|
|
170
|
+
@classproperty
|
|
171
|
+
def instance(self):
|
|
172
|
+
if self._instance is None:
|
|
173
|
+
self._instance = FfiClient()
|
|
174
|
+
return self._instance
|
|
175
|
+
|
|
164
176
|
def __init__(self) -> None:
|
|
165
177
|
self._lock = threading.RLock()
|
|
166
178
|
self._queue = FfiQueue[proto_ffi.FfiEvent]()
|
|
@@ -188,6 +200,3 @@ class FfiClient:
|
|
|
188
200
|
|
|
189
201
|
FfiHandle(handle)
|
|
190
202
|
return resp
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
ffi_client = FfiClient()
|
|
@@ -1,8 +1,29 @@
|
|
|
1
1
|
import asyncio
|
|
2
|
+
import logging
|
|
2
3
|
from collections import deque
|
|
3
4
|
import ctypes
|
|
4
5
|
from typing import Callable, Generic, List, TypeVar
|
|
5
6
|
|
|
7
|
+
logger = logging.getLogger("livekit")
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class classproperty(object):
|
|
11
|
+
def __init__(self, f):
|
|
12
|
+
self.f = classmethod(f)
|
|
13
|
+
|
|
14
|
+
def __get__(self, *a):
|
|
15
|
+
return self.f.__get__(*a)()
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def task_done_logger(task: asyncio.Task) -> None:
|
|
19
|
+
if task.cancelled():
|
|
20
|
+
logger.info("task cancelled: %s", task)
|
|
21
|
+
return
|
|
22
|
+
|
|
23
|
+
if task.exception():
|
|
24
|
+
logger.error("task exception: %s", task, exc_info=task.exception())
|
|
25
|
+
return
|
|
26
|
+
|
|
6
27
|
|
|
7
28
|
def get_address(data: memoryview) -> int:
|
|
8
29
|
"""Get the address of a buffer using ctypes"""
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
15
|
import ctypes
|
|
16
|
-
from ._ffi_client import FfiHandle,
|
|
16
|
+
from ._ffi_client import FfiHandle, FfiClient
|
|
17
17
|
from ._proto import audio_frame_pb2 as proto_audio
|
|
18
18
|
from ._proto import ffi_pb2 as proto_ffi
|
|
19
19
|
from ._utils import get_address
|
|
@@ -65,7 +65,7 @@ class AudioFrame:
|
|
|
65
65
|
req = proto_ffi.FfiRequest()
|
|
66
66
|
req.new_audio_resampler.CopyFrom(proto_audio.NewAudioResamplerRequest())
|
|
67
67
|
|
|
68
|
-
resp =
|
|
68
|
+
resp = FfiClient.instance.request(req)
|
|
69
69
|
resampler_handle = FfiHandle(resp.new_audio_resampler.resampler.handle.id)
|
|
70
70
|
|
|
71
71
|
resample_req = proto_ffi.FfiRequest()
|
|
@@ -74,7 +74,7 @@ class AudioFrame:
|
|
|
74
74
|
resample_req.remix_and_resample.sample_rate = sample_rate
|
|
75
75
|
resample_req.remix_and_resample.num_channels = num_channels
|
|
76
76
|
|
|
77
|
-
resp =
|
|
77
|
+
resp = FfiClient.instance.request(resample_req)
|
|
78
78
|
return AudioFrame._from_owned_info(resp.remix_and_resample.buffer)
|
|
79
79
|
|
|
80
80
|
def _proto_info(self) -> proto_audio.AudioFrameBufferInfo:
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
|
-
from ._ffi_client import FfiHandle,
|
|
15
|
+
from ._ffi_client import FfiHandle, FfiClient
|
|
16
16
|
from ._proto import audio_frame_pb2 as proto_audio_frame
|
|
17
17
|
from ._proto import ffi_pb2 as proto_ffi
|
|
18
18
|
from .audio_frame import AudioFrame
|
|
@@ -27,7 +27,7 @@ class AudioSource:
|
|
|
27
27
|
req.new_audio_source.sample_rate = sample_rate
|
|
28
28
|
req.new_audio_source.num_channels = num_channels
|
|
29
29
|
|
|
30
|
-
resp =
|
|
30
|
+
resp = FfiClient.instance.request(req)
|
|
31
31
|
self._info = resp.new_audio_source.source
|
|
32
32
|
self._ffi_handle = FfiHandle(self._info.handle.id)
|
|
33
33
|
|
|
@@ -37,15 +37,15 @@ class AudioSource:
|
|
|
37
37
|
req.capture_audio_frame.source_handle = self._ffi_handle.handle
|
|
38
38
|
req.capture_audio_frame.buffer.CopyFrom(frame._proto_info())
|
|
39
39
|
|
|
40
|
-
queue =
|
|
40
|
+
queue = FfiClient.instance.queue.subscribe()
|
|
41
41
|
try:
|
|
42
|
-
resp =
|
|
42
|
+
resp = FfiClient.instance.request(req)
|
|
43
43
|
cb = await queue.wait_for(
|
|
44
44
|
lambda e: e.capture_audio_frame.async_id
|
|
45
45
|
== resp.capture_audio_frame.async_id
|
|
46
46
|
)
|
|
47
47
|
finally:
|
|
48
|
-
|
|
48
|
+
FfiClient.instance.queue.unsubscribe(queue)
|
|
49
49
|
|
|
50
50
|
if cb.capture_audio_frame.error:
|
|
51
51
|
raise Exception(cb.capture_audio_frame.error)
|
|
@@ -15,10 +15,10 @@
|
|
|
15
15
|
import asyncio
|
|
16
16
|
from typing import Optional
|
|
17
17
|
|
|
18
|
-
from ._ffi_client import FfiHandle,
|
|
18
|
+
from ._ffi_client import FfiHandle, FfiClient
|
|
19
19
|
from ._proto import audio_frame_pb2 as proto_audio_frame
|
|
20
20
|
from ._proto import ffi_pb2 as proto_ffi
|
|
21
|
-
from ._utils import RingQueue
|
|
21
|
+
from ._utils import RingQueue, task_done_logger
|
|
22
22
|
from .audio_frame import AudioFrame
|
|
23
23
|
from .track import Track
|
|
24
24
|
|
|
@@ -32,23 +32,24 @@ class AudioStream:
|
|
|
32
32
|
) -> None:
|
|
33
33
|
self._track = track
|
|
34
34
|
self._loop = loop or asyncio.get_event_loop()
|
|
35
|
-
self._ffi_queue =
|
|
35
|
+
self._ffi_queue = FfiClient.instance.queue.subscribe(self._loop)
|
|
36
36
|
self._queue: RingQueue[AudioFrame] = RingQueue(capacity)
|
|
37
37
|
|
|
38
38
|
req = proto_ffi.FfiRequest()
|
|
39
39
|
new_audio_stream = req.new_audio_stream
|
|
40
40
|
new_audio_stream.track_handle = track._ffi_handle.handle
|
|
41
41
|
new_audio_stream.type = proto_audio_frame.AudioStreamType.AUDIO_STREAM_NATIVE
|
|
42
|
-
resp =
|
|
42
|
+
resp = FfiClient.instance.request(req)
|
|
43
43
|
|
|
44
44
|
stream_info = resp.new_audio_stream.stream
|
|
45
45
|
self._ffi_handle = FfiHandle(stream_info.handle.id)
|
|
46
46
|
self._info = stream_info
|
|
47
47
|
|
|
48
48
|
self._task = self._loop.create_task(self._run())
|
|
49
|
+
self._task.add_done_callback(task_done_logger)
|
|
49
50
|
|
|
50
51
|
def __del__(self) -> None:
|
|
51
|
-
|
|
52
|
+
FfiClient.instance.queue.unsubscribe(self._ffi_queue)
|
|
52
53
|
|
|
53
54
|
async def _run(self):
|
|
54
55
|
while True:
|
|
@@ -62,7 +63,7 @@ class AudioStream:
|
|
|
62
63
|
elif audio_event.HasField("eos"):
|
|
63
64
|
break
|
|
64
65
|
|
|
65
|
-
|
|
66
|
+
FfiClient.instance.queue.unsubscribe(self._ffi_queue)
|
|
66
67
|
|
|
67
68
|
async def aclose(self):
|
|
68
69
|
self._ffi_handle.dispose()
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
from dataclasses import dataclass, field
|
|
16
16
|
from typing import List, Optional
|
|
17
17
|
|
|
18
|
-
from ._ffi_client import
|
|
18
|
+
from ._ffi_client import FfiClient
|
|
19
19
|
from ._proto import e2ee_pb2 as proto_e2ee
|
|
20
20
|
from ._proto import ffi_pb2 as proto_ffi
|
|
21
21
|
|
|
@@ -52,13 +52,13 @@ class KeyProvider:
|
|
|
52
52
|
req.e2ee.room_handle = self._room_handle
|
|
53
53
|
req.e2ee.set_shared_key.key_index = key_index
|
|
54
54
|
req.e2ee.set_shared_key.shared_key = key
|
|
55
|
-
|
|
55
|
+
FfiClient.instance.request(req)
|
|
56
56
|
|
|
57
57
|
def export_shared_key(self, key_index: int) -> bytes:
|
|
58
58
|
req = proto_ffi.FfiRequest()
|
|
59
59
|
req.e2ee.room_handle = self._room_handle
|
|
60
60
|
req.e2ee.get_shared_key.key_index = key_index
|
|
61
|
-
resp =
|
|
61
|
+
resp = FfiClient.instance.request(req)
|
|
62
62
|
key = resp.e2ee.get_shared_key.key
|
|
63
63
|
return key
|
|
64
64
|
|
|
@@ -67,7 +67,7 @@ class KeyProvider:
|
|
|
67
67
|
req.e2ee.room_handle = self._room_handle
|
|
68
68
|
req.e2ee.ratchet_shared_key.key_index = key_index
|
|
69
69
|
|
|
70
|
-
resp =
|
|
70
|
+
resp = FfiClient.instance.request(req)
|
|
71
71
|
|
|
72
72
|
new_key = resp.e2ee.ratchet_shared_key.new_key
|
|
73
73
|
return new_key
|
|
@@ -80,14 +80,14 @@ class KeyProvider:
|
|
|
80
80
|
req.e2ee.set_key.key = key
|
|
81
81
|
|
|
82
82
|
self.key_index = key_index
|
|
83
|
-
|
|
83
|
+
FfiClient.instance.request(req)
|
|
84
84
|
|
|
85
85
|
def export_key(self, participant_identity: str, key_index: int) -> bytes:
|
|
86
86
|
req = proto_ffi.FfiRequest()
|
|
87
87
|
req.e2ee.room_handle = self._room_handle
|
|
88
88
|
req.e2ee.get_key.participant_identity = participant_identity
|
|
89
89
|
req.e2ee.get_key.key_index = key_index
|
|
90
|
-
resp =
|
|
90
|
+
resp = FfiClient.instance.request(req)
|
|
91
91
|
key = resp.e2ee.get_key.key
|
|
92
92
|
return key
|
|
93
93
|
|
|
@@ -97,7 +97,7 @@ class KeyProvider:
|
|
|
97
97
|
req.e2ee.ratchet_key.participant_identity = participant_identity
|
|
98
98
|
req.e2ee.ratchet_key.key_index = key_index
|
|
99
99
|
|
|
100
|
-
resp =
|
|
100
|
+
resp = FfiClient.instance.request(req)
|
|
101
101
|
new_key = resp.e2ee.ratchet_key.new_key
|
|
102
102
|
return new_key
|
|
103
103
|
|
|
@@ -129,7 +129,7 @@ class FrameCryptor:
|
|
|
129
129
|
req.e2ee.room_handle = self._room_handle
|
|
130
130
|
req.e2ee.cryptor_set_enabled.participant_identity = self._participant_identity
|
|
131
131
|
req.e2ee.cryptor_set_enabled.enabled = enabled
|
|
132
|
-
|
|
132
|
+
FfiClient.instance.request(req)
|
|
133
133
|
|
|
134
134
|
def set_key_index(self, key_index: int) -> None:
|
|
135
135
|
self._key_index = key_index
|
|
@@ -137,7 +137,7 @@ class FrameCryptor:
|
|
|
137
137
|
req.e2ee.room_handle = self._room_handle
|
|
138
138
|
req.e2ee.cryptor_set_key_index.participant_identity = self._participant_identity
|
|
139
139
|
req.e2ee.cryptor_set_key_index.key_index = key_index
|
|
140
|
-
|
|
140
|
+
FfiClient.instance.request(req)
|
|
141
141
|
|
|
142
142
|
|
|
143
143
|
class E2EEManager:
|
|
@@ -164,13 +164,13 @@ class E2EEManager:
|
|
|
164
164
|
req = proto_ffi.FfiRequest()
|
|
165
165
|
req.e2ee.room_handle = self._room_handle
|
|
166
166
|
req.e2ee.manager_set_enabled.enabled = enabled
|
|
167
|
-
|
|
167
|
+
FfiClient.instance.request(req)
|
|
168
168
|
|
|
169
169
|
def frame_cryptors(self) -> List[FrameCryptor]:
|
|
170
170
|
req = proto_ffi.FfiRequest()
|
|
171
171
|
req.e2ee.room_handle = self._room_handle
|
|
172
172
|
|
|
173
|
-
resp =
|
|
173
|
+
resp = FfiClient.instance.request(req)
|
|
174
174
|
frame_cryptors = []
|
|
175
175
|
for frame_cryptor in resp.e2ee.manager_get_frame_cryptors.frame_cryptors:
|
|
176
176
|
frame_cryptors.append(
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
import ctypes
|
|
16
16
|
from typing import List, Union
|
|
17
17
|
|
|
18
|
-
from ._ffi_client import FfiHandle,
|
|
18
|
+
from ._ffi_client import FfiHandle, FfiClient
|
|
19
19
|
from ._proto import ffi_pb2 as proto_ffi
|
|
20
20
|
from ._proto import participant_pb2 as proto_participant
|
|
21
21
|
from ._proto.room_pb2 import DataPacketKind, TrackPublishOptions
|
|
@@ -105,14 +105,14 @@ class LocalParticipant(Participant):
|
|
|
105
105
|
|
|
106
106
|
req.publish_data.destination_sids.extend(sids)
|
|
107
107
|
|
|
108
|
-
queue =
|
|
108
|
+
queue = FfiClient.instance.queue.subscribe()
|
|
109
109
|
try:
|
|
110
|
-
resp =
|
|
110
|
+
resp = FfiClient.instance.request(req)
|
|
111
111
|
cb = await queue.wait_for(
|
|
112
112
|
lambda e: e.publish_data.async_id == resp.publish_data.async_id
|
|
113
113
|
)
|
|
114
114
|
finally:
|
|
115
|
-
|
|
115
|
+
FfiClient.instance.queue.unsubscribe(queue)
|
|
116
116
|
|
|
117
117
|
if cb.publish_data.error:
|
|
118
118
|
raise PublishDataError(cb.publish_data.error)
|
|
@@ -122,30 +122,30 @@ class LocalParticipant(Participant):
|
|
|
122
122
|
req.update_local_metadata.local_participant_handle = self._ffi_handle.handle
|
|
123
123
|
req.update_local_metadata.metadata = metadata
|
|
124
124
|
|
|
125
|
-
queue =
|
|
125
|
+
queue = FfiClient.instance.queue.subscribe()
|
|
126
126
|
try:
|
|
127
|
-
resp =
|
|
127
|
+
resp = FfiClient.instance.request(req)
|
|
128
128
|
await queue.wait_for(
|
|
129
129
|
lambda e: e.update_local_metadata.async_id
|
|
130
130
|
== resp.update_local_metadata.async_id
|
|
131
131
|
)
|
|
132
132
|
finally:
|
|
133
|
-
|
|
133
|
+
FfiClient.instance.queue.unsubscribe(queue)
|
|
134
134
|
|
|
135
135
|
async def update_name(self, name: str) -> None:
|
|
136
136
|
req = proto_ffi.FfiRequest()
|
|
137
137
|
req.update_local_name.local_participant_handle = self._ffi_handle.handle
|
|
138
138
|
req.update_local_name.name = name
|
|
139
139
|
|
|
140
|
-
queue =
|
|
140
|
+
queue = FfiClient.instance.queue.subscribe()
|
|
141
141
|
try:
|
|
142
|
-
resp =
|
|
142
|
+
resp = FfiClient.instance.request(req)
|
|
143
143
|
await queue.wait_for(
|
|
144
144
|
lambda e: e.update_local_name.async_id
|
|
145
145
|
== resp.update_local_name.async_id
|
|
146
146
|
)
|
|
147
147
|
finally:
|
|
148
|
-
|
|
148
|
+
FfiClient.instance.queue.unsubscribe(queue)
|
|
149
149
|
|
|
150
150
|
async def publish_track(
|
|
151
151
|
self, track: LocalTrack, options: TrackPublishOptions
|
|
@@ -157,7 +157,7 @@ class LocalParticipant(Participant):
|
|
|
157
157
|
|
|
158
158
|
queue = self._room_queue.subscribe()
|
|
159
159
|
try:
|
|
160
|
-
resp =
|
|
160
|
+
resp = FfiClient.instance.request(req)
|
|
161
161
|
cb = await queue.wait_for(
|
|
162
162
|
lambda e: e.publish_track.async_id == resp.publish_track.async_id
|
|
163
163
|
)
|
|
@@ -167,6 +167,7 @@ class LocalParticipant(Participant):
|
|
|
167
167
|
|
|
168
168
|
track_publication = LocalTrackPublication(cb.publish_track.publication)
|
|
169
169
|
track_publication.track = track
|
|
170
|
+
track._info.sid = track_publication.sid
|
|
170
171
|
self.tracks[track_publication.sid] = track_publication
|
|
171
172
|
|
|
172
173
|
queue.task_done()
|
|
@@ -181,7 +182,7 @@ class LocalParticipant(Participant):
|
|
|
181
182
|
|
|
182
183
|
queue = self._room_queue.subscribe()
|
|
183
184
|
try:
|
|
184
|
-
resp =
|
|
185
|
+
resp = FfiClient.instance.request(req)
|
|
185
186
|
cb = await queue.wait_for(
|
|
186
187
|
lambda e: e.unpublish_track.async_id == resp.unpublish_track.async_id
|
|
187
188
|
)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
""" Used by importlib.resources and setuptools """
|
|
@@ -17,7 +17,7 @@ import ctypes
|
|
|
17
17
|
import logging
|
|
18
18
|
from dataclasses import dataclass, field
|
|
19
19
|
from typing import Dict, Optional, Literal
|
|
20
|
-
from ._ffi_client import FfiHandle,
|
|
20
|
+
from ._ffi_client import FfiHandle, FfiClient
|
|
21
21
|
from ._proto import ffi_pb2 as proto_ffi
|
|
22
22
|
from ._proto import participant_pb2 as proto_participant
|
|
23
23
|
from ._proto import room_pb2 as proto_room
|
|
@@ -76,6 +76,16 @@ class RoomOptions:
|
|
|
76
76
|
rtc_config: Optional[RtcConfiguration] = None
|
|
77
77
|
|
|
78
78
|
|
|
79
|
+
@dataclass
|
|
80
|
+
class DataPacket:
|
|
81
|
+
data: bytes
|
|
82
|
+
kind: proto_room.DataPacketKind.ValueType
|
|
83
|
+
participant: Optional[
|
|
84
|
+
RemoteParticipant
|
|
85
|
+
] = None # None when the data has been sent by a server SDK
|
|
86
|
+
topic: Optional[str] = None
|
|
87
|
+
|
|
88
|
+
|
|
79
89
|
class ConnectError(Exception):
|
|
80
90
|
def __init__(self, message: str):
|
|
81
91
|
self.message = message
|
|
@@ -95,7 +105,7 @@ class Room(EventEmitter[EventTypes]):
|
|
|
95
105
|
|
|
96
106
|
def __del__(self) -> None:
|
|
97
107
|
if self._ffi_handle is not None:
|
|
98
|
-
|
|
108
|
+
FfiClient.instance.queue.unsubscribe(self._ffi_queue)
|
|
99
109
|
|
|
100
110
|
@property
|
|
101
111
|
def sid(self) -> str:
|
|
@@ -157,19 +167,19 @@ class Room(EventEmitter[EventTypes]):
|
|
|
157
167
|
)
|
|
158
168
|
|
|
159
169
|
# subscribe before connecting so we don't miss any events
|
|
160
|
-
self._ffi_queue =
|
|
170
|
+
self._ffi_queue = FfiClient.instance.queue.subscribe(self._loop)
|
|
161
171
|
|
|
162
|
-
queue =
|
|
172
|
+
queue = FfiClient.instance.queue.subscribe()
|
|
163
173
|
try:
|
|
164
|
-
resp =
|
|
174
|
+
resp = FfiClient.instance.request(req)
|
|
165
175
|
cb = await queue.wait_for(
|
|
166
176
|
lambda e: e.connect.async_id == resp.connect.async_id
|
|
167
177
|
)
|
|
168
178
|
finally:
|
|
169
|
-
|
|
179
|
+
FfiClient.instance.queue.unsubscribe(queue)
|
|
170
180
|
|
|
171
181
|
if cb.connect.error:
|
|
172
|
-
|
|
182
|
+
FfiClient.instance.queue.unsubscribe(self._ffi_queue)
|
|
173
183
|
raise ConnectError(cb.connect.error)
|
|
174
184
|
|
|
175
185
|
self._ffi_handle = FfiHandle(cb.connect.room.handle.id)
|
|
@@ -201,17 +211,17 @@ class Room(EventEmitter[EventTypes]):
|
|
|
201
211
|
req = proto_ffi.FfiRequest()
|
|
202
212
|
req.disconnect.room_handle = self._ffi_handle.handle # type: ignore
|
|
203
213
|
|
|
204
|
-
queue =
|
|
214
|
+
queue = FfiClient.instance.queue.subscribe()
|
|
205
215
|
try:
|
|
206
|
-
resp =
|
|
216
|
+
resp = FfiClient.instance.request(req)
|
|
207
217
|
await queue.wait_for(
|
|
208
218
|
lambda e: e.disconnect.async_id == resp.disconnect.async_id
|
|
209
219
|
)
|
|
210
220
|
finally:
|
|
211
|
-
|
|
221
|
+
FfiClient.instance.queue.unsubscribe(queue)
|
|
212
222
|
|
|
213
223
|
await self._task
|
|
214
|
-
|
|
224
|
+
FfiClient.instance.queue.unsubscribe(self._ffi_queue)
|
|
215
225
|
|
|
216
226
|
async def _listen_task(self) -> None:
|
|
217
227
|
# listen to incoming room events
|
|
@@ -372,10 +382,12 @@ class Room(EventEmitter[EventTypes]):
|
|
|
372
382
|
rparticipant = self.participants[event.data_received.participant_sid]
|
|
373
383
|
self.emit(
|
|
374
384
|
"data_received",
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
385
|
+
DataPacket(
|
|
386
|
+
data=data,
|
|
387
|
+
kind=event.data_received.kind,
|
|
388
|
+
participant=rparticipant,
|
|
389
|
+
topic=event.data_received.topic,
|
|
390
|
+
),
|
|
379
391
|
)
|
|
380
392
|
elif which == "e2ee_state_changed":
|
|
381
393
|
sid = event.e2ee_state_changed.participant_sid
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
15
|
from typing import TYPE_CHECKING, List, Union
|
|
16
|
-
from ._ffi_client import FfiHandle,
|
|
16
|
+
from ._ffi_client import FfiHandle, FfiClient
|
|
17
17
|
from ._proto import ffi_pb2 as proto_ffi
|
|
18
18
|
from ._proto import track_pb2 as proto_track
|
|
19
19
|
from ._proto import stats_pb2 as proto_stats
|
|
@@ -52,14 +52,14 @@ class Track:
|
|
|
52
52
|
req = proto_ffi.FfiRequest()
|
|
53
53
|
req.get_stats.track_handle = self._ffi_handle.handle
|
|
54
54
|
|
|
55
|
-
queue =
|
|
55
|
+
queue = FfiClient.instance.queue.subscribe()
|
|
56
56
|
try:
|
|
57
|
-
resp =
|
|
57
|
+
resp = FfiClient.instance.request(req)
|
|
58
58
|
cb = await queue.wait_for(
|
|
59
59
|
lambda e: e.get_stats.async_id == resp.get_stats.async_id
|
|
60
60
|
)
|
|
61
61
|
finally:
|
|
62
|
-
|
|
62
|
+
FfiClient.instance.queue.unsubscribe(queue)
|
|
63
63
|
|
|
64
64
|
if cb.get_stats.error:
|
|
65
65
|
raise Exception(cb.get_stats.error)
|
|
@@ -77,7 +77,7 @@ class LocalAudioTrack(Track):
|
|
|
77
77
|
req.create_audio_track.name = name
|
|
78
78
|
req.create_audio_track.source_handle = source._ffi_handle.handle
|
|
79
79
|
|
|
80
|
-
resp =
|
|
80
|
+
resp = FfiClient.instance.request(req)
|
|
81
81
|
return LocalAudioTrack(resp.create_audio_track.track)
|
|
82
82
|
|
|
83
83
|
|
|
@@ -91,7 +91,7 @@ class LocalVideoTrack(Track):
|
|
|
91
91
|
req.create_video_track.name = name
|
|
92
92
|
req.create_video_track.source_handle = source._ffi_handle.handle
|
|
93
93
|
|
|
94
|
-
resp =
|
|
94
|
+
resp = FfiClient.instance.request(req)
|
|
95
95
|
return LocalVideoTrack(resp.create_video_track.track)
|
|
96
96
|
|
|
97
97
|
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
|
|
15
15
|
from typing import Optional
|
|
16
16
|
|
|
17
|
-
from ._ffi_client import FfiHandle,
|
|
17
|
+
from ._ffi_client import FfiHandle, FfiClient
|
|
18
18
|
from ._proto import e2ee_pb2 as proto_e2ee
|
|
19
19
|
from ._proto import ffi_pb2 as proto_ffi
|
|
20
20
|
from ._proto import track_pb2 as proto_track
|
|
@@ -82,4 +82,4 @@ class RemoteTrackPublication(TrackPublication):
|
|
|
82
82
|
req = proto_ffi.FfiRequest()
|
|
83
83
|
req.set_subscribed.subscribe = subscribed
|
|
84
84
|
req.set_subscribed.publication_handle = self._ffi_handle.handle
|
|
85
|
-
|
|
85
|
+
FfiClient.instance.request(req)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.7.1.dev1"
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
import ctypes
|
|
16
16
|
from typing import Union
|
|
17
17
|
|
|
18
|
-
from ._ffi_client import FfiHandle,
|
|
18
|
+
from ._ffi_client import FfiHandle, FfiClient
|
|
19
19
|
from ._proto import ffi_pb2 as proto_ffi
|
|
20
20
|
from ._utils import get_address
|
|
21
21
|
from ._proto import video_frame_pb2 as proto_video_frame
|
|
@@ -75,7 +75,7 @@ class VideoFrameBuffer(ABC):
|
|
|
75
75
|
def to_i420(self) -> "I420Buffer":
|
|
76
76
|
req = proto_ffi.FfiRequest()
|
|
77
77
|
req.to_i420.buffer.CopyFrom(self._proto_info())
|
|
78
|
-
resp =
|
|
78
|
+
resp = FfiClient.instance.request(req)
|
|
79
79
|
return I420Buffer._from_owned_info(resp.to_i420.buffer)
|
|
80
80
|
|
|
81
81
|
def to_argb(self, dst: "ArgbFrame") -> None:
|
|
@@ -86,7 +86,7 @@ class VideoFrameBuffer(ABC):
|
|
|
86
86
|
req.to_argb.dst_stride = dst.stride
|
|
87
87
|
req.to_argb.dst_width = dst.width
|
|
88
88
|
req.to_argb.dst_height = dst.height
|
|
89
|
-
|
|
89
|
+
FfiClient.instance.request(req)
|
|
90
90
|
|
|
91
91
|
@staticmethod
|
|
92
92
|
def _from_owned_info(
|
|
@@ -139,7 +139,7 @@ class NativeVideoBuffer(VideoFrameBuffer):
|
|
|
139
139
|
def to_i420(self) -> "I420Buffer":
|
|
140
140
|
req = proto_ffi.FfiRequest()
|
|
141
141
|
req.to_i420.handle = self._ffi_handle.handle
|
|
142
|
-
resp =
|
|
142
|
+
resp = FfiClient.instance.request(req)
|
|
143
143
|
return I420Buffer._from_owned_info(resp.to_i420.buffer)
|
|
144
144
|
|
|
145
145
|
def to_argb(self, dst: "ArgbFrame") -> None:
|
|
@@ -768,7 +768,7 @@ class ArgbFrame:
|
|
|
768
768
|
req.to_i420.argb.height = self.height
|
|
769
769
|
req.to_i420.argb.stride = self.stride
|
|
770
770
|
req.to_i420.argb.ptr = get_address(memoryview(self._data))
|
|
771
|
-
res =
|
|
771
|
+
res = FfiClient.instance.request(req)
|
|
772
772
|
return I420Buffer._from_owned_info(res.to_i420.buffer)
|
|
773
773
|
|
|
774
774
|
@property
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
|
-
from ._ffi_client import FfiHandle,
|
|
15
|
+
from ._ffi_client import FfiHandle, FfiClient
|
|
16
16
|
from ._proto import ffi_pb2 as proto_ffi
|
|
17
17
|
from ._proto import video_frame_pb2 as proto_video_frame
|
|
18
18
|
from .video_frame import VideoFrame
|
|
@@ -27,7 +27,7 @@ class VideoSource:
|
|
|
27
27
|
req.new_video_source.resolution.width = width
|
|
28
28
|
req.new_video_source.resolution.height = height
|
|
29
29
|
|
|
30
|
-
resp =
|
|
30
|
+
resp = FfiClient.instance.request(req)
|
|
31
31
|
self._info = resp.new_video_source.source
|
|
32
32
|
self._ffi_handle = FfiHandle(self._info.handle.id)
|
|
33
33
|
|
|
@@ -37,4 +37,4 @@ class VideoSource:
|
|
|
37
37
|
req.capture_video_frame.info.CopyFrom(frame.buffer._proto_info())
|
|
38
38
|
req.capture_video_frame.frame.rotation = frame.rotation
|
|
39
39
|
req.capture_video_frame.frame.timestamp_us = frame.timestamp_us
|
|
40
|
-
|
|
40
|
+
FfiClient.instance.request(req)
|
|
@@ -15,10 +15,10 @@
|
|
|
15
15
|
import asyncio
|
|
16
16
|
from typing import Optional
|
|
17
17
|
|
|
18
|
-
from ._ffi_client import FfiHandle,
|
|
18
|
+
from ._ffi_client import FfiHandle, FfiClient
|
|
19
19
|
from ._proto import ffi_pb2 as proto_ffi
|
|
20
20
|
from ._proto import video_frame_pb2 as proto_video_frame
|
|
21
|
-
from ._utils import RingQueue
|
|
21
|
+
from ._utils import RingQueue, task_done_logger
|
|
22
22
|
from .track import Track
|
|
23
23
|
from .video_frame import VideoFrame, VideoFrameBuffer
|
|
24
24
|
|
|
@@ -32,22 +32,23 @@ class VideoStream:
|
|
|
32
32
|
) -> None:
|
|
33
33
|
self._track = track
|
|
34
34
|
self._loop = loop or asyncio.get_event_loop()
|
|
35
|
-
self._ffi_queue =
|
|
35
|
+
self._ffi_queue = FfiClient.instance.queue.subscribe(self._loop)
|
|
36
36
|
self._queue: RingQueue[VideoFrame] = RingQueue(capacity)
|
|
37
37
|
|
|
38
38
|
req = proto_ffi.FfiRequest()
|
|
39
39
|
new_video_stream = req.new_video_stream
|
|
40
40
|
new_video_stream.track_handle = track._ffi_handle.handle
|
|
41
41
|
new_video_stream.type = proto_video_frame.VideoStreamType.VIDEO_STREAM_NATIVE
|
|
42
|
-
resp =
|
|
42
|
+
resp = FfiClient.instance.request(req)
|
|
43
43
|
|
|
44
44
|
stream_info = resp.new_video_stream.stream
|
|
45
45
|
self._ffi_handle = FfiHandle(stream_info.handle.id)
|
|
46
46
|
self._info = stream_info.info
|
|
47
47
|
self._task = self._loop.create_task(self._run())
|
|
48
|
+
self._task.add_done_callback(task_done_logger)
|
|
48
49
|
|
|
49
50
|
def __del__(self) -> None:
|
|
50
|
-
|
|
51
|
+
FfiClient.instance.queue.unsubscribe(self._ffi_queue)
|
|
51
52
|
|
|
52
53
|
async def _run(self):
|
|
53
54
|
while True:
|
|
@@ -67,7 +68,7 @@ class VideoStream:
|
|
|
67
68
|
elif video_event.HasField("eos"):
|
|
68
69
|
break
|
|
69
70
|
|
|
70
|
-
|
|
71
|
+
FfiClient.instance.queue.unsubscribe(self._ffi_queue)
|
|
71
72
|
|
|
72
73
|
async def aclose(self):
|
|
73
74
|
self._ffi_handle.dispose()
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: livekit
|
|
3
|
-
Version: 0.7.
|
|
3
|
+
Version: 0.7.1.dev1
|
|
4
4
|
Summary: Python Real-time SDK for LiveKit
|
|
5
5
|
Home-page: https://github.com/livekit/python-sdks
|
|
6
6
|
License: Apache-2.0
|
|
@@ -19,8 +19,8 @@ Classifier: Programming Language :: Python :: 3.10
|
|
|
19
19
|
Classifier: Programming Language :: Python :: 3 :: Only
|
|
20
20
|
Requires-Python: >=3.9.0
|
|
21
21
|
Description-Content-Type: text/markdown
|
|
22
|
-
Requires-Dist: protobuf>=
|
|
23
|
-
Requires-Dist: types-protobuf>=
|
|
22
|
+
Requires-Dist: protobuf>=4
|
|
23
|
+
Requires-Dist: types-protobuf>=4
|
|
24
24
|
|
|
25
25
|
# LiveKit Real-time Python SDK
|
|
26
26
|
|
|
@@ -10,6 +10,8 @@ build-backend = "setuptools.build_meta"
|
|
|
10
10
|
build = "cp39-*"
|
|
11
11
|
skip = "*-musllinux_*" # not supported (libwebrtc is using glibc)
|
|
12
12
|
|
|
13
|
+
before-build = "pip install requests && python rust-sdks/download_ffi.py --output livekit/rtc/resources"
|
|
14
|
+
|
|
13
15
|
manylinux-x86_64-image = "manylinux_2_28"
|
|
14
16
|
manylinux-i686-image = "manylinux_2_28"
|
|
15
17
|
manylinux-aarch64-image = "manylinux_2_28"
|
|
@@ -14,8 +14,6 @@
|
|
|
14
14
|
|
|
15
15
|
import os
|
|
16
16
|
import pathlib
|
|
17
|
-
import subprocess
|
|
18
|
-
|
|
19
17
|
import setuptools
|
|
20
18
|
import setuptools.command.build_py
|
|
21
19
|
from wheel.bdist_wheel import bdist_wheel as _bdist_wheel
|
|
@@ -33,30 +31,6 @@ class bdist_wheel(_bdist_wheel):
|
|
|
33
31
|
_bdist_wheel.finalize_options(self)
|
|
34
32
|
|
|
35
33
|
|
|
36
|
-
class BuildPyCommand(setuptools.command.build_py.build_py):
|
|
37
|
-
"""Download a prebuilt version of livekit_ffi"""
|
|
38
|
-
|
|
39
|
-
def run(self):
|
|
40
|
-
download_script = here / "rust-sdks" / "download_ffi.py"
|
|
41
|
-
output = here / "livekit" / "rtc" / "resources"
|
|
42
|
-
cmd = [
|
|
43
|
-
"python3",
|
|
44
|
-
str(download_script.absolute()),
|
|
45
|
-
"--output",
|
|
46
|
-
str(output.absolute()),
|
|
47
|
-
]
|
|
48
|
-
|
|
49
|
-
# cibuildwheel is crosscompiling to arm64 on macos, make sure we download the
|
|
50
|
-
# right binary (kind of a hack here...)
|
|
51
|
-
if os.environ.get("CIBUILDWHEEL") == "1" and "arm64" in os.environ.get(
|
|
52
|
-
"ARCHFLAGS", ""
|
|
53
|
-
):
|
|
54
|
-
cmd += ["--arch", "arm64"]
|
|
55
|
-
|
|
56
|
-
subprocess.run(cmd, check=True)
|
|
57
|
-
setuptools.command.build_py.build_py.run(self)
|
|
58
|
-
|
|
59
|
-
|
|
60
34
|
setuptools.setup(
|
|
61
35
|
name="livekit",
|
|
62
36
|
version=about["__version__"],
|
|
@@ -66,7 +40,6 @@ setuptools.setup(
|
|
|
66
40
|
url="https://github.com/livekit/python-sdks",
|
|
67
41
|
cmdclass={
|
|
68
42
|
"bdist_wheel": bdist_wheel,
|
|
69
|
-
"build_py": BuildPyCommand,
|
|
70
43
|
},
|
|
71
44
|
classifiers=[
|
|
72
45
|
"Intended Audience :: Developers",
|
|
@@ -83,9 +56,10 @@ setuptools.setup(
|
|
|
83
56
|
license="Apache-2.0",
|
|
84
57
|
packages=setuptools.find_namespace_packages(include=["livekit.*"]),
|
|
85
58
|
python_requires=">=3.9.0",
|
|
86
|
-
install_requires=["protobuf>=
|
|
59
|
+
install_requires=["protobuf>=4", "types-protobuf>=4"],
|
|
87
60
|
package_data={
|
|
88
|
-
"livekit.rtc": ["
|
|
61
|
+
"livekit.rtc": ["_proto/*.py", "py.typed", "*.pyi", "**/*.pyi"],
|
|
62
|
+
"livekit.rtc.resources": ["*.so", "*.dylib", "*.dll", "LICENSE.md", "*.h"],
|
|
89
63
|
},
|
|
90
64
|
project_urls={
|
|
91
65
|
"Documentation": "https://docs.livekit.io",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "0.7.0.dev1"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|