livekit-api 0.8.0__tar.gz → 0.8.2__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_api-0.8.0 → livekit_api-0.8.2}/PKG-INFO +13 -3
- {livekit_api-0.8.0 → livekit_api-0.8.2}/livekit/api/__init__.py +24 -1
- {livekit_api-0.8.0 → livekit_api-0.8.2}/livekit/api/agent_dispatch_service.py +26 -21
- {livekit_api-0.8.0 → livekit_api-0.8.2}/livekit/api/egress_service.py +48 -34
- {livekit_api-0.8.0 → livekit_api-0.8.2}/livekit/api/ingress_service.py +30 -17
- {livekit_api-0.8.0 → livekit_api-0.8.2}/livekit/api/livekit_api.py +46 -5
- livekit_api-0.8.2/livekit/api/room_service.py +300 -0
- {livekit_api-0.8.0 → livekit_api-0.8.2}/livekit/api/sip_service.py +71 -40
- livekit_api-0.8.2/livekit/api/version.py +1 -0
- {livekit_api-0.8.0 → livekit_api-0.8.2}/livekit/api/webhook.py +3 -3
- {livekit_api-0.8.0 → livekit_api-0.8.2}/livekit_api.egg-info/PKG-INFO +13 -3
- {livekit_api-0.8.0 → livekit_api-0.8.2}/livekit_api.egg-info/requires.txt +1 -1
- {livekit_api-0.8.0 → livekit_api-0.8.2}/setup.py +1 -1
- livekit_api-0.8.0/livekit/api/room_service.py +0 -136
- livekit_api-0.8.0/livekit/api/version.py +0 -1
- {livekit_api-0.8.0 → livekit_api-0.8.2}/README.md +0 -0
- {livekit_api-0.8.0 → livekit_api-0.8.2}/livekit/api/_service.py +0 -0
- {livekit_api-0.8.0 → livekit_api-0.8.2}/livekit/api/access_token.py +0 -0
- {livekit_api-0.8.0 → livekit_api-0.8.2}/livekit/api/py.typed +0 -0
- {livekit_api-0.8.0 → livekit_api-0.8.2}/livekit/api/twirp_client.py +0 -0
- {livekit_api-0.8.0 → livekit_api-0.8.2}/livekit_api.egg-info/SOURCES.txt +0 -0
- {livekit_api-0.8.0 → livekit_api-0.8.2}/livekit_api.egg-info/dependency_links.txt +0 -0
- {livekit_api-0.8.0 → livekit_api-0.8.2}/livekit_api.egg-info/top_level.txt +0 -0
- {livekit_api-0.8.0 → livekit_api-0.8.2}/pyproject.toml +0 -0
- {livekit_api-0.8.0 → livekit_api-0.8.2}/setup.cfg +0 -0
- {livekit_api-0.8.0 → livekit_api-0.8.2}/tests/test_access_token.py +0 -0
- {livekit_api-0.8.0 → livekit_api-0.8.2}/tests/test_webhook.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
2
|
Name: livekit-api
|
|
3
|
-
Version: 0.8.
|
|
3
|
+
Version: 0.8.2
|
|
4
4
|
Summary: Python Server API for LiveKit
|
|
5
5
|
Home-page: https://github.com/livekit/python-sdks
|
|
6
6
|
License: Apache-2.0
|
|
@@ -25,7 +25,17 @@ Requires-Dist: pyjwt>=2.0.0
|
|
|
25
25
|
Requires-Dist: aiohttp>=3.9.0
|
|
26
26
|
Requires-Dist: protobuf>=3
|
|
27
27
|
Requires-Dist: types-protobuf<5,>=4
|
|
28
|
-
Requires-Dist: livekit-protocol<2,>=0.
|
|
28
|
+
Requires-Dist: livekit-protocol<2,>=0.8.2
|
|
29
|
+
Dynamic: classifier
|
|
30
|
+
Dynamic: description
|
|
31
|
+
Dynamic: description-content-type
|
|
32
|
+
Dynamic: home-page
|
|
33
|
+
Dynamic: keywords
|
|
34
|
+
Dynamic: license
|
|
35
|
+
Dynamic: project-url
|
|
36
|
+
Dynamic: requires-dist
|
|
37
|
+
Dynamic: requires-python
|
|
38
|
+
Dynamic: summary
|
|
29
39
|
|
|
30
40
|
# LiveKit Server APIs
|
|
31
41
|
|
|
@@ -12,7 +12,16 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
|
-
"""LiveKit
|
|
15
|
+
"""LiveKit Server APIs for Python
|
|
16
|
+
|
|
17
|
+
`pip install livekit-api`
|
|
18
|
+
|
|
19
|
+
Manage rooms, participants, egress, ingress, SIP, and Agent dispatch.
|
|
20
|
+
|
|
21
|
+
Primary entry point is `LiveKitAPI`.
|
|
22
|
+
|
|
23
|
+
See https://docs.livekit.io/reference/server/server-apis for more information.
|
|
24
|
+
"""
|
|
16
25
|
|
|
17
26
|
# flake8: noqa
|
|
18
27
|
# re-export packages from protocol
|
|
@@ -30,3 +39,17 @@ from .livekit_api import LiveKitAPI
|
|
|
30
39
|
from .access_token import VideoGrants, SIPGrants, AccessToken, TokenVerifier
|
|
31
40
|
from .webhook import WebhookReceiver
|
|
32
41
|
from .version import __version__
|
|
42
|
+
|
|
43
|
+
__all__ = [
|
|
44
|
+
"LiveKitAPI",
|
|
45
|
+
"room_service",
|
|
46
|
+
"egress_service",
|
|
47
|
+
"ingress_service",
|
|
48
|
+
"sip_service",
|
|
49
|
+
"agent_dispatch_service",
|
|
50
|
+
"VideoGrants",
|
|
51
|
+
"SIPGrants",
|
|
52
|
+
"AccessToken",
|
|
53
|
+
"TokenVerifier",
|
|
54
|
+
"WebhookReceiver",
|
|
55
|
+
]
|
|
@@ -1,16 +1,29 @@
|
|
|
1
1
|
import aiohttp
|
|
2
2
|
from typing import Optional
|
|
3
|
-
from livekit.protocol import
|
|
3
|
+
from livekit.protocol.agent_dispatch import (
|
|
4
|
+
CreateAgentDispatchRequest,
|
|
5
|
+
AgentDispatch,
|
|
6
|
+
DeleteAgentDispatchRequest,
|
|
7
|
+
ListAgentDispatchRequest,
|
|
8
|
+
ListAgentDispatchResponse,
|
|
9
|
+
)
|
|
4
10
|
from ._service import Service
|
|
5
11
|
from .access_token import VideoGrants
|
|
6
12
|
|
|
7
13
|
SVC = "AgentDispatchService"
|
|
14
|
+
"""@private"""
|
|
8
15
|
|
|
9
16
|
|
|
10
17
|
class AgentDispatchService(Service):
|
|
11
18
|
"""Manage agent dispatches. Service APIs require roomAdmin permissions.
|
|
12
19
|
|
|
13
|
-
|
|
20
|
+
Recommended way to use this service is via `livekit.api.LiveKitAPI`:
|
|
21
|
+
|
|
22
|
+
```python
|
|
23
|
+
from livekit import api
|
|
24
|
+
lkapi = api.LiveKitAPI()
|
|
25
|
+
agent_dispatch = lkapi.agent_dispatch
|
|
26
|
+
```
|
|
14
27
|
"""
|
|
15
28
|
|
|
16
29
|
def __init__(
|
|
@@ -18,9 +31,7 @@ class AgentDispatchService(Service):
|
|
|
18
31
|
):
|
|
19
32
|
super().__init__(session, url, api_key, api_secret)
|
|
20
33
|
|
|
21
|
-
async def create_dispatch(
|
|
22
|
-
self, req: proto_agent_dispatch.CreateAgentDispatchRequest
|
|
23
|
-
) -> proto_agent_dispatch.AgentDispatch:
|
|
34
|
+
async def create_dispatch(self, req: CreateAgentDispatchRequest) -> AgentDispatch:
|
|
24
35
|
"""Create an explicit dispatch for an agent to join a room.
|
|
25
36
|
|
|
26
37
|
To use explicit dispatch, your agent must be registered with an `agentName`.
|
|
@@ -36,12 +47,10 @@ class AgentDispatchService(Service):
|
|
|
36
47
|
"CreateDispatch",
|
|
37
48
|
req,
|
|
38
49
|
self._auth_header(VideoGrants(room_admin=True, room=req.room)),
|
|
39
|
-
|
|
50
|
+
AgentDispatch,
|
|
40
51
|
)
|
|
41
52
|
|
|
42
|
-
async def delete_dispatch(
|
|
43
|
-
self, dispatch_id: str, room_name: str
|
|
44
|
-
) -> proto_agent_dispatch.AgentDispatch:
|
|
53
|
+
async def delete_dispatch(self, dispatch_id: str, room_name: str) -> AgentDispatch:
|
|
45
54
|
"""Delete an explicit dispatch for an agent in a room.
|
|
46
55
|
|
|
47
56
|
Args:
|
|
@@ -54,17 +63,15 @@ class AgentDispatchService(Service):
|
|
|
54
63
|
return await self._client.request(
|
|
55
64
|
SVC,
|
|
56
65
|
"DeleteDispatch",
|
|
57
|
-
|
|
66
|
+
DeleteAgentDispatchRequest(
|
|
58
67
|
dispatch_id=dispatch_id,
|
|
59
68
|
room=room_name,
|
|
60
69
|
),
|
|
61
70
|
self._auth_header(VideoGrants(room_admin=True, room=room_name)),
|
|
62
|
-
|
|
71
|
+
AgentDispatch,
|
|
63
72
|
)
|
|
64
73
|
|
|
65
|
-
async def list_dispatch(
|
|
66
|
-
self, room_name: str
|
|
67
|
-
) -> list[proto_agent_dispatch.AgentDispatch]:
|
|
74
|
+
async def list_dispatch(self, room_name: str) -> list[AgentDispatch]:
|
|
68
75
|
"""List all agent dispatches in a room.
|
|
69
76
|
|
|
70
77
|
Args:
|
|
@@ -76,15 +83,15 @@ class AgentDispatchService(Service):
|
|
|
76
83
|
res = await self._client.request(
|
|
77
84
|
SVC,
|
|
78
85
|
"ListDispatch",
|
|
79
|
-
|
|
86
|
+
ListAgentDispatchRequest(room=room_name),
|
|
80
87
|
self._auth_header(VideoGrants(room_admin=True, room=room_name)),
|
|
81
|
-
|
|
88
|
+
ListAgentDispatchResponse,
|
|
82
89
|
)
|
|
83
90
|
return list(res.agent_dispatches)
|
|
84
91
|
|
|
85
92
|
async def get_dispatch(
|
|
86
93
|
self, dispatch_id: str, room_name: str
|
|
87
|
-
) -> Optional[
|
|
94
|
+
) -> Optional[AgentDispatch]:
|
|
88
95
|
"""Get an Agent dispatch by ID
|
|
89
96
|
|
|
90
97
|
Args:
|
|
@@ -97,11 +104,9 @@ class AgentDispatchService(Service):
|
|
|
97
104
|
res = await self._client.request(
|
|
98
105
|
SVC,
|
|
99
106
|
"ListDispatch",
|
|
100
|
-
|
|
101
|
-
dispatch_id=dispatch_id, room=room_name
|
|
102
|
-
),
|
|
107
|
+
ListAgentDispatchRequest(dispatch_id=dispatch_id, room=room_name),
|
|
103
108
|
self._auth_header(VideoGrants(room_admin=True, room=room_name)),
|
|
104
|
-
|
|
109
|
+
ListAgentDispatchResponse,
|
|
105
110
|
)
|
|
106
111
|
if len(res.agent_dispatches) > 0:
|
|
107
112
|
return res.agent_dispatches[0]
|
|
@@ -1,112 +1,126 @@
|
|
|
1
1
|
import aiohttp
|
|
2
|
-
from livekit.protocol import
|
|
2
|
+
from livekit.protocol.egress import (
|
|
3
|
+
RoomCompositeEgressRequest,
|
|
4
|
+
WebEgressRequest,
|
|
5
|
+
ParticipantEgressRequest,
|
|
6
|
+
TrackCompositeEgressRequest,
|
|
7
|
+
TrackEgressRequest,
|
|
8
|
+
UpdateLayoutRequest,
|
|
9
|
+
UpdateStreamRequest,
|
|
10
|
+
ListEgressRequest,
|
|
11
|
+
StopEgressRequest,
|
|
12
|
+
EgressInfo,
|
|
13
|
+
ListEgressResponse,
|
|
14
|
+
)
|
|
3
15
|
from ._service import Service
|
|
4
16
|
from .access_token import VideoGrants
|
|
5
17
|
|
|
6
18
|
SVC = "Egress"
|
|
19
|
+
"""@private"""
|
|
7
20
|
|
|
8
21
|
|
|
9
22
|
class EgressService(Service):
|
|
23
|
+
"""Client for LiveKit Egress Service API
|
|
24
|
+
|
|
25
|
+
Recommended way to use this service is via `livekit.api.LiveKitAPI`:
|
|
26
|
+
|
|
27
|
+
```python
|
|
28
|
+
from livekit import api
|
|
29
|
+
lkapi = api.LiveKitAPI()
|
|
30
|
+
egress = lkapi.egress
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Also see https://docs.livekit.io/home/egress/overview/
|
|
34
|
+
"""
|
|
35
|
+
|
|
10
36
|
def __init__(
|
|
11
37
|
self, session: aiohttp.ClientSession, url: str, api_key: str, api_secret: str
|
|
12
38
|
):
|
|
13
39
|
super().__init__(session, url, api_key, api_secret)
|
|
14
40
|
|
|
15
41
|
async def start_room_composite_egress(
|
|
16
|
-
self, start:
|
|
17
|
-
) ->
|
|
42
|
+
self, start: RoomCompositeEgressRequest
|
|
43
|
+
) -> EgressInfo:
|
|
18
44
|
return await self._client.request(
|
|
19
45
|
SVC,
|
|
20
46
|
"StartRoomCompositeEgress",
|
|
21
47
|
start,
|
|
22
48
|
self._auth_header(VideoGrants(room_record=True)),
|
|
23
|
-
|
|
49
|
+
EgressInfo,
|
|
24
50
|
)
|
|
25
51
|
|
|
26
|
-
async def start_web_egress(
|
|
27
|
-
self, start: proto_egress.WebEgressRequest
|
|
28
|
-
) -> proto_egress.EgressInfo:
|
|
52
|
+
async def start_web_egress(self, start: WebEgressRequest) -> EgressInfo:
|
|
29
53
|
return await self._client.request(
|
|
30
54
|
SVC,
|
|
31
55
|
"StartWebEgress",
|
|
32
56
|
start,
|
|
33
57
|
self._auth_header(VideoGrants(room_record=True)),
|
|
34
|
-
|
|
58
|
+
EgressInfo,
|
|
35
59
|
)
|
|
36
60
|
|
|
37
61
|
async def start_participant_egress(
|
|
38
|
-
self, start:
|
|
39
|
-
) ->
|
|
62
|
+
self, start: ParticipantEgressRequest
|
|
63
|
+
) -> EgressInfo:
|
|
40
64
|
return await self._client.request(
|
|
41
65
|
SVC,
|
|
42
66
|
"StartParticipantEgress",
|
|
43
67
|
start,
|
|
44
68
|
self._auth_header(VideoGrants(room_record=True)),
|
|
45
|
-
|
|
69
|
+
EgressInfo,
|
|
46
70
|
)
|
|
47
71
|
|
|
48
72
|
async def start_track_composite_egress(
|
|
49
|
-
self, start:
|
|
50
|
-
) ->
|
|
73
|
+
self, start: TrackCompositeEgressRequest
|
|
74
|
+
) -> EgressInfo:
|
|
51
75
|
return await self._client.request(
|
|
52
76
|
SVC,
|
|
53
77
|
"StartTrackCompositeEgress",
|
|
54
78
|
start,
|
|
55
79
|
self._auth_header(VideoGrants(room_record=True)),
|
|
56
|
-
|
|
80
|
+
EgressInfo,
|
|
57
81
|
)
|
|
58
82
|
|
|
59
|
-
async def start_track_egress(
|
|
60
|
-
self, start: proto_egress.TrackEgressRequest
|
|
61
|
-
) -> proto_egress.EgressInfo:
|
|
83
|
+
async def start_track_egress(self, start: TrackEgressRequest) -> EgressInfo:
|
|
62
84
|
return await self._client.request(
|
|
63
85
|
SVC,
|
|
64
86
|
"StartTrackEgress",
|
|
65
87
|
start,
|
|
66
88
|
self._auth_header(VideoGrants(room_record=True)),
|
|
67
|
-
|
|
89
|
+
EgressInfo,
|
|
68
90
|
)
|
|
69
91
|
|
|
70
|
-
async def update_layout(
|
|
71
|
-
self, update: proto_egress.UpdateLayoutRequest
|
|
72
|
-
) -> proto_egress.EgressInfo:
|
|
92
|
+
async def update_layout(self, update: UpdateLayoutRequest) -> EgressInfo:
|
|
73
93
|
return await self._client.request(
|
|
74
94
|
SVC,
|
|
75
95
|
"UpdateLayout",
|
|
76
96
|
update,
|
|
77
97
|
self._auth_header(VideoGrants(room_record=True)),
|
|
78
|
-
|
|
98
|
+
EgressInfo,
|
|
79
99
|
)
|
|
80
100
|
|
|
81
|
-
async def update_stream(
|
|
82
|
-
self, update: proto_egress.UpdateStreamRequest
|
|
83
|
-
) -> proto_egress.EgressInfo:
|
|
101
|
+
async def update_stream(self, update: UpdateStreamRequest) -> EgressInfo:
|
|
84
102
|
return await self._client.request(
|
|
85
103
|
SVC,
|
|
86
104
|
"UpdateStream",
|
|
87
105
|
update,
|
|
88
106
|
self._auth_header(VideoGrants(room_record=True)),
|
|
89
|
-
|
|
107
|
+
EgressInfo,
|
|
90
108
|
)
|
|
91
109
|
|
|
92
|
-
async def list_egress(
|
|
93
|
-
self, list: proto_egress.ListEgressRequest
|
|
94
|
-
) -> proto_egress.ListEgressResponse:
|
|
110
|
+
async def list_egress(self, list: ListEgressRequest) -> ListEgressResponse:
|
|
95
111
|
return await self._client.request(
|
|
96
112
|
SVC,
|
|
97
113
|
"ListEgress",
|
|
98
114
|
list,
|
|
99
115
|
self._auth_header(VideoGrants(room_record=True)),
|
|
100
|
-
|
|
116
|
+
ListEgressResponse,
|
|
101
117
|
)
|
|
102
118
|
|
|
103
|
-
async def stop_egress(
|
|
104
|
-
self, stop: proto_egress.StopEgressRequest
|
|
105
|
-
) -> proto_egress.EgressInfo:
|
|
119
|
+
async def stop_egress(self, stop: StopEgressRequest) -> EgressInfo:
|
|
106
120
|
return await self._client.request(
|
|
107
121
|
SVC,
|
|
108
122
|
"StopEgress",
|
|
109
123
|
stop,
|
|
110
124
|
self._auth_header(VideoGrants(room_record=True)),
|
|
111
|
-
|
|
125
|
+
EgressInfo,
|
|
112
126
|
)
|
|
@@ -1,57 +1,70 @@
|
|
|
1
1
|
import aiohttp
|
|
2
|
-
from livekit.protocol import
|
|
2
|
+
from livekit.protocol.ingress import (
|
|
3
|
+
CreateIngressRequest,
|
|
4
|
+
IngressInfo,
|
|
5
|
+
UpdateIngressRequest,
|
|
6
|
+
ListIngressRequest,
|
|
7
|
+
DeleteIngressRequest,
|
|
8
|
+
ListIngressResponse,
|
|
9
|
+
)
|
|
3
10
|
from ._service import Service
|
|
4
11
|
from .access_token import VideoGrants
|
|
5
12
|
|
|
6
13
|
SVC = "Ingress"
|
|
14
|
+
"""@private"""
|
|
7
15
|
|
|
8
16
|
|
|
9
17
|
class IngressService(Service):
|
|
18
|
+
"""Client for LiveKit Ingress Service API
|
|
19
|
+
|
|
20
|
+
Recommended way to use this service is via `livekit.api.LiveKitAPI`:
|
|
21
|
+
|
|
22
|
+
```python
|
|
23
|
+
from livekit import api
|
|
24
|
+
lkapi = api.LiveKitAPI()
|
|
25
|
+
ingress = lkapi.ingress
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Also see https://docs.livekit.io/home/ingress/overview/
|
|
29
|
+
"""
|
|
30
|
+
|
|
10
31
|
def __init__(
|
|
11
32
|
self, session: aiohttp.ClientSession, url: str, api_key: str, api_secret: str
|
|
12
33
|
):
|
|
13
34
|
super().__init__(session, url, api_key, api_secret)
|
|
14
35
|
|
|
15
|
-
async def create_ingress(
|
|
16
|
-
self, create: proto_ingress.CreateIngressRequest
|
|
17
|
-
) -> proto_ingress.IngressInfo:
|
|
36
|
+
async def create_ingress(self, create: CreateIngressRequest) -> IngressInfo:
|
|
18
37
|
return await self._client.request(
|
|
19
38
|
SVC,
|
|
20
39
|
"CreateIngress",
|
|
21
40
|
create,
|
|
22
41
|
self._auth_header(VideoGrants(ingress_admin=True)),
|
|
23
|
-
|
|
42
|
+
IngressInfo,
|
|
24
43
|
)
|
|
25
44
|
|
|
26
|
-
async def update_ingress(
|
|
27
|
-
self, update: proto_ingress.UpdateIngressRequest
|
|
28
|
-
) -> proto_ingress.IngressInfo:
|
|
45
|
+
async def update_ingress(self, update: UpdateIngressRequest) -> IngressInfo:
|
|
29
46
|
return await self._client.request(
|
|
30
47
|
SVC,
|
|
31
48
|
"UpdateIngress",
|
|
32
49
|
update,
|
|
33
50
|
self._auth_header(VideoGrants(ingress_admin=True)),
|
|
34
|
-
|
|
51
|
+
IngressInfo,
|
|
35
52
|
)
|
|
36
53
|
|
|
37
|
-
async def list_ingress(
|
|
38
|
-
self, list: proto_ingress.ListIngressRequest
|
|
39
|
-
) -> proto_ingress.ListIngressResponse:
|
|
54
|
+
async def list_ingress(self, list: ListIngressRequest) -> ListIngressResponse:
|
|
40
55
|
return await self._client.request(
|
|
41
56
|
SVC,
|
|
42
57
|
"ListIngress",
|
|
43
58
|
list,
|
|
44
59
|
self._auth_header(VideoGrants(ingress_admin=True)),
|
|
45
|
-
|
|
60
|
+
ListIngressResponse,
|
|
46
61
|
)
|
|
47
62
|
|
|
48
|
-
async def delete_ingress(
|
|
49
|
-
self, delete: proto_ingress.DeleteIngressRequest
|
|
50
|
-
) -> proto_ingress.IngressInfo:
|
|
63
|
+
async def delete_ingress(self, delete: DeleteIngressRequest) -> IngressInfo:
|
|
51
64
|
return await self._client.request(
|
|
52
65
|
SVC,
|
|
53
66
|
"DeleteIngress",
|
|
54
67
|
delete,
|
|
55
68
|
self._auth_header(VideoGrants(ingress_admin=True)),
|
|
56
|
-
|
|
69
|
+
IngressInfo,
|
|
57
70
|
)
|
|
@@ -9,6 +9,19 @@ from typing import Optional
|
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
class LiveKitAPI:
|
|
12
|
+
"""LiveKit Server API Client
|
|
13
|
+
|
|
14
|
+
This class is the main entrypoint, which exposes all services.
|
|
15
|
+
|
|
16
|
+
Usage:
|
|
17
|
+
|
|
18
|
+
```python
|
|
19
|
+
from livekit import api
|
|
20
|
+
lkapi = api.LiveKitAPI()
|
|
21
|
+
rooms = await lkapi.room.list_rooms(api.proto_room.ListRoomsRequest(names=['test-room']))
|
|
22
|
+
```
|
|
23
|
+
"""
|
|
24
|
+
|
|
12
25
|
def __init__(
|
|
13
26
|
self,
|
|
14
27
|
url: Optional[str] = None,
|
|
@@ -17,6 +30,14 @@ class LiveKitAPI:
|
|
|
17
30
|
*,
|
|
18
31
|
timeout: aiohttp.ClientTimeout = aiohttp.ClientTimeout(total=60), # 60 seconds
|
|
19
32
|
):
|
|
33
|
+
"""Create a new LiveKitAPI instance.
|
|
34
|
+
|
|
35
|
+
Args:
|
|
36
|
+
url: LiveKit server URL (read from `LIVEKIT_URL` environment variable if not provided)
|
|
37
|
+
api_key: API key (read from `LIVEKIT_API_KEY` environment variable if not provided)
|
|
38
|
+
api_secret: API secret (read from `LIVEKIT_API_SECRET` environment variable if not provided)
|
|
39
|
+
timeout: Request timeout (default: 60 seconds)
|
|
40
|
+
"""
|
|
20
41
|
url = url or os.getenv("LIVEKIT_URL")
|
|
21
42
|
api_key = api_key or os.getenv("LIVEKIT_API_KEY")
|
|
22
43
|
api_secret = api_secret or os.getenv("LIVEKIT_API_SECRET")
|
|
@@ -37,24 +58,44 @@ class LiveKitAPI:
|
|
|
37
58
|
)
|
|
38
59
|
|
|
39
60
|
@property
|
|
40
|
-
def agent_dispatch(self):
|
|
61
|
+
def agent_dispatch(self) -> AgentDispatchService:
|
|
62
|
+
"""Instance of the AgentDispatchService"""
|
|
41
63
|
return self._agent_dispatch
|
|
42
64
|
|
|
43
65
|
@property
|
|
44
|
-
def room(self):
|
|
66
|
+
def room(self) -> RoomService:
|
|
67
|
+
"""Instance of the RoomService"""
|
|
45
68
|
return self._room
|
|
46
69
|
|
|
47
70
|
@property
|
|
48
|
-
def ingress(self):
|
|
71
|
+
def ingress(self) -> IngressService:
|
|
72
|
+
"""Instance of the IngressService"""
|
|
49
73
|
return self._ingress
|
|
50
74
|
|
|
51
75
|
@property
|
|
52
|
-
def egress(self):
|
|
76
|
+
def egress(self) -> EgressService:
|
|
77
|
+
"""Instance of the EgressService"""
|
|
53
78
|
return self._egress
|
|
54
79
|
|
|
55
80
|
@property
|
|
56
|
-
def sip(self):
|
|
81
|
+
def sip(self) -> SipService:
|
|
82
|
+
"""Instance of the SipService"""
|
|
57
83
|
return self._sip
|
|
58
84
|
|
|
59
85
|
async def aclose(self):
|
|
86
|
+
"""Close the API client
|
|
87
|
+
|
|
88
|
+
Call this before your application exits or when the API client is no longer needed."""
|
|
60
89
|
await self._session.close()
|
|
90
|
+
|
|
91
|
+
async def __aenter__(self):
|
|
92
|
+
"""@private
|
|
93
|
+
|
|
94
|
+
Support for `async with`"""
|
|
95
|
+
return self
|
|
96
|
+
|
|
97
|
+
async def __aexit__(self, exc_type, exc_val, exc_tb):
|
|
98
|
+
"""@private
|
|
99
|
+
|
|
100
|
+
Support for `async with`"""
|
|
101
|
+
await self.aclose()
|
|
@@ -0,0 +1,300 @@
|
|
|
1
|
+
import aiohttp
|
|
2
|
+
from uuid import uuid4
|
|
3
|
+
from livekit.protocol.room import (
|
|
4
|
+
CreateRoomRequest,
|
|
5
|
+
ListRoomsRequest,
|
|
6
|
+
DeleteRoomRequest,
|
|
7
|
+
ListRoomsResponse,
|
|
8
|
+
DeleteRoomResponse,
|
|
9
|
+
ListParticipantsRequest,
|
|
10
|
+
ListParticipantsResponse,
|
|
11
|
+
RoomParticipantIdentity,
|
|
12
|
+
MuteRoomTrackRequest,
|
|
13
|
+
MuteRoomTrackResponse,
|
|
14
|
+
UpdateParticipantRequest,
|
|
15
|
+
UpdateSubscriptionsRequest,
|
|
16
|
+
SendDataRequest,
|
|
17
|
+
SendDataResponse,
|
|
18
|
+
UpdateRoomMetadataRequest,
|
|
19
|
+
RemoveParticipantResponse,
|
|
20
|
+
UpdateSubscriptionsResponse,
|
|
21
|
+
)
|
|
22
|
+
from livekit.protocol.models import Room, ParticipantInfo
|
|
23
|
+
from ._service import Service
|
|
24
|
+
from .access_token import VideoGrants
|
|
25
|
+
|
|
26
|
+
SVC = "RoomService"
|
|
27
|
+
"""@private"""
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class RoomService(Service):
|
|
31
|
+
"""Client for LiveKit RoomService API
|
|
32
|
+
|
|
33
|
+
Recommended way to use this service is via `livekit.api.LiveKitAPI`:
|
|
34
|
+
|
|
35
|
+
```python
|
|
36
|
+
from livekit import api
|
|
37
|
+
lkapi = api.LiveKitAPI()
|
|
38
|
+
room_service = lkapi.room
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Also see https://docs.livekit.io/home/server/managing-rooms/ and https://docs.livekit.io/home/server/managing-participants/
|
|
42
|
+
"""
|
|
43
|
+
|
|
44
|
+
def __init__(
|
|
45
|
+
self, session: aiohttp.ClientSession, url: str, api_key: str, api_secret: str
|
|
46
|
+
):
|
|
47
|
+
super().__init__(session, url, api_key, api_secret)
|
|
48
|
+
|
|
49
|
+
async def create_room(
|
|
50
|
+
self,
|
|
51
|
+
create: CreateRoomRequest,
|
|
52
|
+
) -> Room:
|
|
53
|
+
"""Creates a new room with specified configuration.
|
|
54
|
+
|
|
55
|
+
Args:
|
|
56
|
+
create (CreateRoomRequest): arg containing:
|
|
57
|
+
- name: str - Unique room name
|
|
58
|
+
- empty_timeout: int - Seconds to keep room open if empty
|
|
59
|
+
- max_participants: int - Max allowed participants
|
|
60
|
+
- metadata: str - Custom room metadata
|
|
61
|
+
- egress: RoomEgress - Egress configuration
|
|
62
|
+
- min_playout_delay: int - Minimum playout delay in ms
|
|
63
|
+
- max_playout_delay: int - Maximum playout delay in ms
|
|
64
|
+
- sync_streams: bool - Enable A/V sync for playout delays >200ms
|
|
65
|
+
|
|
66
|
+
Returns:
|
|
67
|
+
Room: The created room object
|
|
68
|
+
"""
|
|
69
|
+
return await self._client.request(
|
|
70
|
+
SVC,
|
|
71
|
+
"CreateRoom",
|
|
72
|
+
create,
|
|
73
|
+
self._auth_header(VideoGrants(room_create=True)),
|
|
74
|
+
Room,
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
async def list_rooms(self, list: ListRoomsRequest) -> ListRoomsResponse:
|
|
78
|
+
"""Lists active rooms.
|
|
79
|
+
|
|
80
|
+
Args:
|
|
81
|
+
list (ListRoomsRequest): arg containing:
|
|
82
|
+
- names: list[str] - Optional list of room names to filter by
|
|
83
|
+
|
|
84
|
+
Returns:
|
|
85
|
+
ListRoomsResponse:
|
|
86
|
+
- rooms: list[Room] - List of active Room objects
|
|
87
|
+
"""
|
|
88
|
+
return await self._client.request(
|
|
89
|
+
SVC,
|
|
90
|
+
"ListRooms",
|
|
91
|
+
list,
|
|
92
|
+
self._auth_header(VideoGrants(room_list=True)),
|
|
93
|
+
ListRoomsResponse,
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
async def delete_room(self, delete: DeleteRoomRequest) -> DeleteRoomResponse:
|
|
97
|
+
"""Deletes a room and disconnects all participants.
|
|
98
|
+
|
|
99
|
+
Args:
|
|
100
|
+
delete (DeleteRoomRequest): arg containing:
|
|
101
|
+
- room: str - Name of room to delete
|
|
102
|
+
|
|
103
|
+
Returns:
|
|
104
|
+
DeleteRoomResponse: Empty response object
|
|
105
|
+
"""
|
|
106
|
+
return await self._client.request(
|
|
107
|
+
SVC,
|
|
108
|
+
"DeleteRoom",
|
|
109
|
+
delete,
|
|
110
|
+
self._auth_header(VideoGrants(room_create=True)),
|
|
111
|
+
DeleteRoomResponse,
|
|
112
|
+
)
|
|
113
|
+
|
|
114
|
+
async def update_room_metadata(self, update: UpdateRoomMetadataRequest) -> Room:
|
|
115
|
+
"""Updates a room's [metadata](https://docs.livekit.io/home/client/data/room-metadata/).
|
|
116
|
+
|
|
117
|
+
Args:
|
|
118
|
+
update (UpdateRoomMetadataRequest): arg containing:
|
|
119
|
+
- room: str - Name of room to update
|
|
120
|
+
- metadata: str - New metadata to set
|
|
121
|
+
|
|
122
|
+
Returns:
|
|
123
|
+
Room: Updated Room object
|
|
124
|
+
"""
|
|
125
|
+
return await self._client.request(
|
|
126
|
+
SVC,
|
|
127
|
+
"UpdateRoomMetadata",
|
|
128
|
+
update,
|
|
129
|
+
self._auth_header(VideoGrants(room_admin=True, room=update.room)),
|
|
130
|
+
Room,
|
|
131
|
+
)
|
|
132
|
+
|
|
133
|
+
async def list_participants(
|
|
134
|
+
self, list: ListParticipantsRequest
|
|
135
|
+
) -> ListParticipantsResponse:
|
|
136
|
+
"""Lists all participants in a room.
|
|
137
|
+
|
|
138
|
+
Args:
|
|
139
|
+
list (ListParticipantsRequest): arg containing:
|
|
140
|
+
- room: str - Name of room to list participants from
|
|
141
|
+
|
|
142
|
+
Returns:
|
|
143
|
+
ListParticipantsResponse:
|
|
144
|
+
- participants: list[ParticipantInfo] - List of participant details
|
|
145
|
+
"""
|
|
146
|
+
return await self._client.request(
|
|
147
|
+
SVC,
|
|
148
|
+
"ListParticipants",
|
|
149
|
+
list,
|
|
150
|
+
self._auth_header(VideoGrants(room_admin=True, room=list.room)),
|
|
151
|
+
ListParticipantsResponse,
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
async def get_participant(self, get: RoomParticipantIdentity) -> ParticipantInfo:
|
|
155
|
+
"""Gets details about a specific participant.
|
|
156
|
+
|
|
157
|
+
Args:
|
|
158
|
+
get (RoomParticipantIdentity): arg containing:
|
|
159
|
+
- room: str - Room name
|
|
160
|
+
- identity: str - Participant identity to look up
|
|
161
|
+
|
|
162
|
+
Returns:
|
|
163
|
+
ParticipantInfo:
|
|
164
|
+
- sid: str - Participant session ID
|
|
165
|
+
- identity: str - Participant identity
|
|
166
|
+
- state: int - Connection state
|
|
167
|
+
- tracks: list[TrackInfo] - Published tracks
|
|
168
|
+
- metadata: str - Participant metadata
|
|
169
|
+
- joined_at: int - Join timestamp
|
|
170
|
+
- name: str - Display name
|
|
171
|
+
- version: int - Protocol version
|
|
172
|
+
- permission: ParticipantPermission - Granted permissions
|
|
173
|
+
- region: str - Connected region
|
|
174
|
+
"""
|
|
175
|
+
return await self._client.request(
|
|
176
|
+
SVC,
|
|
177
|
+
"GetParticipant",
|
|
178
|
+
get,
|
|
179
|
+
self._auth_header(VideoGrants(room_admin=True, room=get.room)),
|
|
180
|
+
ParticipantInfo,
|
|
181
|
+
)
|
|
182
|
+
|
|
183
|
+
async def remove_participant(
|
|
184
|
+
self, remove: RoomParticipantIdentity
|
|
185
|
+
) -> RemoveParticipantResponse:
|
|
186
|
+
"""Removes a participant from a room.
|
|
187
|
+
|
|
188
|
+
Args:
|
|
189
|
+
remove (RoomParticipantIdentity): arg containing:
|
|
190
|
+
- room: str - Room name
|
|
191
|
+
- identity: str - Identity of participant to remove
|
|
192
|
+
|
|
193
|
+
Returns:
|
|
194
|
+
RemoveParticipantResponse: Empty response object
|
|
195
|
+
"""
|
|
196
|
+
return await self._client.request(
|
|
197
|
+
SVC,
|
|
198
|
+
"RemoveParticipant",
|
|
199
|
+
remove,
|
|
200
|
+
self._auth_header(VideoGrants(room_admin=True, room=remove.room)),
|
|
201
|
+
RemoveParticipantResponse,
|
|
202
|
+
)
|
|
203
|
+
|
|
204
|
+
async def mute_published_track(
|
|
205
|
+
self,
|
|
206
|
+
update: MuteRoomTrackRequest,
|
|
207
|
+
) -> MuteRoomTrackResponse:
|
|
208
|
+
"""Mutes or unmutes a participant's published track.
|
|
209
|
+
|
|
210
|
+
Args:
|
|
211
|
+
update (MuteRoomTrackRequest): arg containing:
|
|
212
|
+
- room: str - Room name
|
|
213
|
+
- identity: str - Participant identity
|
|
214
|
+
- track_sid: str - Track session ID to mute
|
|
215
|
+
- muted: bool - True to mute, False to unmute
|
|
216
|
+
|
|
217
|
+
Returns:
|
|
218
|
+
MuteRoomTrackResponse containing:
|
|
219
|
+
- track: TrackInfo - Updated track information
|
|
220
|
+
"""
|
|
221
|
+
return await self._client.request(
|
|
222
|
+
SVC,
|
|
223
|
+
"MutePublishedTrack",
|
|
224
|
+
update,
|
|
225
|
+
self._auth_header(VideoGrants(room_admin=True, room=update.room)),
|
|
226
|
+
MuteRoomTrackResponse,
|
|
227
|
+
)
|
|
228
|
+
|
|
229
|
+
async def update_participant(
|
|
230
|
+
self, update: UpdateParticipantRequest
|
|
231
|
+
) -> ParticipantInfo:
|
|
232
|
+
"""Updates a participant's metadata or permissions.
|
|
233
|
+
|
|
234
|
+
Args:
|
|
235
|
+
update (UpdateParticipantRequest): arg containing:
|
|
236
|
+
- room: str - Room name
|
|
237
|
+
- identity: str - Participant identity
|
|
238
|
+
- metadata: str - New metadata
|
|
239
|
+
- permission: ParticipantPermission - New permissions
|
|
240
|
+
- name: str - New display name
|
|
241
|
+
- attributes: dict[str, str] - Key-value attributes
|
|
242
|
+
|
|
243
|
+
Returns:
|
|
244
|
+
ParticipantInfo: Updated participant information
|
|
245
|
+
"""
|
|
246
|
+
return await self._client.request(
|
|
247
|
+
SVC,
|
|
248
|
+
"UpdateParticipant",
|
|
249
|
+
update,
|
|
250
|
+
self._auth_header(VideoGrants(room_admin=True, room=update.room)),
|
|
251
|
+
ParticipantInfo,
|
|
252
|
+
)
|
|
253
|
+
|
|
254
|
+
async def update_subscriptions(
|
|
255
|
+
self, update: UpdateSubscriptionsRequest
|
|
256
|
+
) -> UpdateSubscriptionsResponse:
|
|
257
|
+
"""Updates a participant's track subscriptions.
|
|
258
|
+
|
|
259
|
+
Args:
|
|
260
|
+
update (UpdateSubscriptionsRequest): arg containing:
|
|
261
|
+
- room: str - Room name
|
|
262
|
+
- identity: str - Participant identity
|
|
263
|
+
- track_sids: list[str] - Track session IDs
|
|
264
|
+
- subscribe: bool - True to subscribe, False to unsubscribe
|
|
265
|
+
- participant_tracks: list[ParticipantTracks] - Participant track mappings
|
|
266
|
+
|
|
267
|
+
Returns:
|
|
268
|
+
UpdateSubscriptionsResponse: Empty response object
|
|
269
|
+
"""
|
|
270
|
+
return await self._client.request(
|
|
271
|
+
SVC,
|
|
272
|
+
"UpdateSubscriptions",
|
|
273
|
+
update,
|
|
274
|
+
self._auth_header(VideoGrants(room_admin=True, room=update.room)),
|
|
275
|
+
UpdateSubscriptionsResponse,
|
|
276
|
+
)
|
|
277
|
+
|
|
278
|
+
async def send_data(self, send: SendDataRequest) -> SendDataResponse:
|
|
279
|
+
"""Sends data to participants in a room.
|
|
280
|
+
|
|
281
|
+
Args:
|
|
282
|
+
send (SendDataRequest): arg containing:
|
|
283
|
+
- room: str - Room name
|
|
284
|
+
- data: bytes - Data payload to send
|
|
285
|
+
- kind: DataPacket.Kind - RELIABLE or LOSSY delivery
|
|
286
|
+
- destination_identities: list[str] - Target participant identities
|
|
287
|
+
- topic: str - Optional topic for the message
|
|
288
|
+
|
|
289
|
+
Returns:
|
|
290
|
+
SendDataResponse: Empty response object
|
|
291
|
+
"""
|
|
292
|
+
|
|
293
|
+
send.nonce = uuid4().bytes
|
|
294
|
+
return await self._client.request(
|
|
295
|
+
SVC,
|
|
296
|
+
"SendData",
|
|
297
|
+
send,
|
|
298
|
+
self._auth_header(VideoGrants(room_admin=True, room=send.room)),
|
|
299
|
+
SendDataResponse,
|
|
300
|
+
)
|
|
@@ -1,141 +1,172 @@
|
|
|
1
1
|
import aiohttp
|
|
2
|
-
from livekit.protocol import
|
|
2
|
+
from livekit.protocol.sip import (
|
|
3
|
+
CreateSIPTrunkRequest,
|
|
4
|
+
SIPTrunkInfo,
|
|
5
|
+
CreateSIPInboundTrunkRequest,
|
|
6
|
+
SIPInboundTrunkInfo,
|
|
7
|
+
CreateSIPOutboundTrunkRequest,
|
|
8
|
+
SIPOutboundTrunkInfo,
|
|
9
|
+
ListSIPTrunkRequest,
|
|
10
|
+
ListSIPTrunkResponse,
|
|
11
|
+
ListSIPInboundTrunkRequest,
|
|
12
|
+
ListSIPInboundTrunkResponse,
|
|
13
|
+
ListSIPOutboundTrunkRequest,
|
|
14
|
+
ListSIPOutboundTrunkResponse,
|
|
15
|
+
DeleteSIPTrunkRequest,
|
|
16
|
+
SIPDispatchRuleInfo,
|
|
17
|
+
CreateSIPDispatchRuleRequest,
|
|
18
|
+
ListSIPDispatchRuleRequest,
|
|
19
|
+
ListSIPDispatchRuleResponse,
|
|
20
|
+
DeleteSIPDispatchRuleRequest,
|
|
21
|
+
CreateSIPParticipantRequest,
|
|
22
|
+
TransferSIPParticipantRequest,
|
|
23
|
+
SIPParticipantInfo,
|
|
24
|
+
)
|
|
3
25
|
from ._service import Service
|
|
4
26
|
from .access_token import VideoGrants, SIPGrants
|
|
5
27
|
|
|
6
28
|
SVC = "SIP"
|
|
29
|
+
"""@private"""
|
|
7
30
|
|
|
8
31
|
|
|
9
32
|
class SipService(Service):
|
|
33
|
+
"""Client for LiveKit SIP Service API
|
|
34
|
+
|
|
35
|
+
Recommended way to use this service is via `livekit.api.LiveKitAPI`:
|
|
36
|
+
|
|
37
|
+
```python
|
|
38
|
+
from livekit import api
|
|
39
|
+
lkapi = api.LiveKitAPI()
|
|
40
|
+
sip_service = lkapi.sip
|
|
41
|
+
```
|
|
42
|
+
"""
|
|
43
|
+
|
|
10
44
|
def __init__(
|
|
11
45
|
self, session: aiohttp.ClientSession, url: str, api_key: str, api_secret: str
|
|
12
46
|
):
|
|
13
47
|
super().__init__(session, url, api_key, api_secret)
|
|
14
48
|
|
|
15
|
-
async def create_sip_trunk(
|
|
16
|
-
|
|
17
|
-
|
|
49
|
+
async def create_sip_trunk(self, create: CreateSIPTrunkRequest) -> SIPTrunkInfo:
|
|
50
|
+
"""
|
|
51
|
+
@deprecated Use create_sip_inbound_trunk or create_sip_outbound_trunk instead
|
|
52
|
+
"""
|
|
18
53
|
return await self._client.request(
|
|
19
54
|
SVC,
|
|
20
55
|
"CreateSIPTrunk",
|
|
21
56
|
create,
|
|
22
57
|
self._auth_header(VideoGrants(), sip=SIPGrants(admin=True)),
|
|
23
|
-
|
|
58
|
+
SIPTrunkInfo,
|
|
24
59
|
)
|
|
25
60
|
|
|
26
61
|
async def create_sip_inbound_trunk(
|
|
27
|
-
self, create:
|
|
28
|
-
) ->
|
|
62
|
+
self, create: CreateSIPInboundTrunkRequest
|
|
63
|
+
) -> SIPInboundTrunkInfo:
|
|
29
64
|
return await self._client.request(
|
|
30
65
|
SVC,
|
|
31
66
|
"CreateSIPInboundTrunk",
|
|
32
67
|
create,
|
|
33
68
|
self._auth_header(VideoGrants(), sip=SIPGrants(admin=True)),
|
|
34
|
-
|
|
69
|
+
SIPInboundTrunkInfo,
|
|
35
70
|
)
|
|
36
71
|
|
|
37
72
|
async def create_sip_outbound_trunk(
|
|
38
|
-
self, create:
|
|
39
|
-
) ->
|
|
73
|
+
self, create: CreateSIPOutboundTrunkRequest
|
|
74
|
+
) -> SIPOutboundTrunkInfo:
|
|
40
75
|
return await self._client.request(
|
|
41
76
|
SVC,
|
|
42
77
|
"CreateSIPOutboundTrunk",
|
|
43
78
|
create,
|
|
44
79
|
self._auth_header(VideoGrants(), sip=SIPGrants(admin=True)),
|
|
45
|
-
|
|
80
|
+
SIPOutboundTrunkInfo,
|
|
46
81
|
)
|
|
47
82
|
|
|
48
|
-
async def list_sip_trunk(
|
|
49
|
-
self, list: proto_sip.ListSIPTrunkRequest
|
|
50
|
-
) -> proto_sip.ListSIPTrunkResponse:
|
|
83
|
+
async def list_sip_trunk(self, list: ListSIPTrunkRequest) -> ListSIPTrunkResponse:
|
|
51
84
|
return await self._client.request(
|
|
52
85
|
SVC,
|
|
53
86
|
"ListSIPTrunk",
|
|
54
87
|
list,
|
|
55
88
|
self._auth_header(VideoGrants(), sip=SIPGrants(admin=True)),
|
|
56
|
-
|
|
89
|
+
ListSIPTrunkResponse,
|
|
57
90
|
)
|
|
58
91
|
|
|
59
92
|
async def list_sip_inbound_trunk(
|
|
60
|
-
self, list:
|
|
61
|
-
) ->
|
|
93
|
+
self, list: ListSIPInboundTrunkRequest
|
|
94
|
+
) -> ListSIPInboundTrunkResponse:
|
|
62
95
|
return await self._client.request(
|
|
63
96
|
SVC,
|
|
64
97
|
"ListSIPInboundTrunk",
|
|
65
98
|
list,
|
|
66
99
|
self._auth_header(VideoGrants(), sip=SIPGrants(admin=True)),
|
|
67
|
-
|
|
100
|
+
ListSIPInboundTrunkResponse,
|
|
68
101
|
)
|
|
69
102
|
|
|
70
103
|
async def list_sip_outbound_trunk(
|
|
71
|
-
self, list:
|
|
72
|
-
) ->
|
|
104
|
+
self, list: ListSIPOutboundTrunkRequest
|
|
105
|
+
) -> ListSIPOutboundTrunkResponse:
|
|
73
106
|
return await self._client.request(
|
|
74
107
|
SVC,
|
|
75
108
|
"ListSIPOutboundTrunk",
|
|
76
109
|
list,
|
|
77
110
|
self._auth_header(VideoGrants(), sip=SIPGrants(admin=True)),
|
|
78
|
-
|
|
111
|
+
ListSIPOutboundTrunkResponse,
|
|
79
112
|
)
|
|
80
113
|
|
|
81
|
-
async def delete_sip_trunk(
|
|
82
|
-
self, delete: proto_sip.DeleteSIPTrunkRequest
|
|
83
|
-
) -> proto_sip.SIPTrunkInfo:
|
|
114
|
+
async def delete_sip_trunk(self, delete: DeleteSIPTrunkRequest) -> SIPTrunkInfo:
|
|
84
115
|
return await self._client.request(
|
|
85
116
|
SVC,
|
|
86
117
|
"DeleteSIPTrunk",
|
|
87
118
|
delete,
|
|
88
119
|
self._auth_header(VideoGrants(), sip=SIPGrants(admin=True)),
|
|
89
|
-
|
|
120
|
+
SIPTrunkInfo,
|
|
90
121
|
)
|
|
91
122
|
|
|
92
123
|
async def create_sip_dispatch_rule(
|
|
93
|
-
self, create:
|
|
94
|
-
) ->
|
|
124
|
+
self, create: CreateSIPDispatchRuleRequest
|
|
125
|
+
) -> SIPDispatchRuleInfo:
|
|
95
126
|
return await self._client.request(
|
|
96
127
|
SVC,
|
|
97
128
|
"CreateSIPDispatchRule",
|
|
98
129
|
create,
|
|
99
130
|
self._auth_header(VideoGrants(), sip=SIPGrants(admin=True)),
|
|
100
|
-
|
|
131
|
+
SIPDispatchRuleInfo,
|
|
101
132
|
)
|
|
102
133
|
|
|
103
134
|
async def list_sip_dispatch_rule(
|
|
104
|
-
self, list:
|
|
105
|
-
) ->
|
|
135
|
+
self, list: ListSIPDispatchRuleRequest
|
|
136
|
+
) -> ListSIPDispatchRuleResponse:
|
|
106
137
|
return await self._client.request(
|
|
107
138
|
SVC,
|
|
108
139
|
"ListSIPDispatchRule",
|
|
109
140
|
list,
|
|
110
141
|
self._auth_header(VideoGrants(), sip=SIPGrants(admin=True)),
|
|
111
|
-
|
|
142
|
+
ListSIPDispatchRuleResponse,
|
|
112
143
|
)
|
|
113
144
|
|
|
114
145
|
async def delete_sip_dispatch_rule(
|
|
115
|
-
self, delete:
|
|
116
|
-
) ->
|
|
146
|
+
self, delete: DeleteSIPDispatchRuleRequest
|
|
147
|
+
) -> SIPDispatchRuleInfo:
|
|
117
148
|
return await self._client.request(
|
|
118
149
|
SVC,
|
|
119
150
|
"DeleteSIPDispatchRule",
|
|
120
151
|
delete,
|
|
121
152
|
self._auth_header(VideoGrants(), sip=SIPGrants(admin=True)),
|
|
122
|
-
|
|
153
|
+
SIPDispatchRuleInfo,
|
|
123
154
|
)
|
|
124
155
|
|
|
125
156
|
async def create_sip_participant(
|
|
126
|
-
self, create:
|
|
127
|
-
) ->
|
|
157
|
+
self, create: CreateSIPParticipantRequest
|
|
158
|
+
) -> SIPParticipantInfo:
|
|
128
159
|
return await self._client.request(
|
|
129
160
|
SVC,
|
|
130
161
|
"CreateSIPParticipant",
|
|
131
162
|
create,
|
|
132
163
|
self._auth_header(VideoGrants(), sip=SIPGrants(call=True)),
|
|
133
|
-
|
|
164
|
+
SIPParticipantInfo,
|
|
134
165
|
)
|
|
135
166
|
|
|
136
167
|
async def transfer_sip_participant(
|
|
137
|
-
self, transfer:
|
|
138
|
-
) ->
|
|
168
|
+
self, transfer: TransferSIPParticipantRequest
|
|
169
|
+
) -> SIPParticipantInfo:
|
|
139
170
|
return await self._client.request(
|
|
140
171
|
SVC,
|
|
141
172
|
"TransferSIPParticipant",
|
|
@@ -147,5 +178,5 @@ class SipService(Service):
|
|
|
147
178
|
),
|
|
148
179
|
sip=SIPGrants(call=True),
|
|
149
180
|
),
|
|
150
|
-
|
|
181
|
+
SIPParticipantInfo,
|
|
151
182
|
)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.8.2"
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
from .access_token import TokenVerifier
|
|
2
|
-
from livekit.protocol import
|
|
2
|
+
from livekit.protocol.webhook import WebhookEvent
|
|
3
3
|
from google.protobuf.json_format import Parse
|
|
4
4
|
import hashlib
|
|
5
5
|
import base64
|
|
@@ -9,7 +9,7 @@ class WebhookReceiver:
|
|
|
9
9
|
def __init__(self, token_verifier: TokenVerifier):
|
|
10
10
|
self._verifier = token_verifier
|
|
11
11
|
|
|
12
|
-
def receive(self, body: str, auth_token: str) ->
|
|
12
|
+
def receive(self, body: str, auth_token: str) -> WebhookEvent:
|
|
13
13
|
claims = self._verifier.verify(auth_token)
|
|
14
14
|
if claims.sha256 is None:
|
|
15
15
|
raise Exception("sha256 was not found in the token")
|
|
@@ -20,4 +20,4 @@ class WebhookReceiver:
|
|
|
20
20
|
if body_hash != claims_hash:
|
|
21
21
|
raise Exception("hash mismatch")
|
|
22
22
|
|
|
23
|
-
return Parse(body,
|
|
23
|
+
return Parse(body, WebhookEvent(), ignore_unknown_fields=True)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
2
|
Name: livekit-api
|
|
3
|
-
Version: 0.8.
|
|
3
|
+
Version: 0.8.2
|
|
4
4
|
Summary: Python Server API for LiveKit
|
|
5
5
|
Home-page: https://github.com/livekit/python-sdks
|
|
6
6
|
License: Apache-2.0
|
|
@@ -25,7 +25,17 @@ Requires-Dist: pyjwt>=2.0.0
|
|
|
25
25
|
Requires-Dist: aiohttp>=3.9.0
|
|
26
26
|
Requires-Dist: protobuf>=3
|
|
27
27
|
Requires-Dist: types-protobuf<5,>=4
|
|
28
|
-
Requires-Dist: livekit-protocol<2,>=0.
|
|
28
|
+
Requires-Dist: livekit-protocol<2,>=0.8.2
|
|
29
|
+
Dynamic: classifier
|
|
30
|
+
Dynamic: description
|
|
31
|
+
Dynamic: description-content-type
|
|
32
|
+
Dynamic: home-page
|
|
33
|
+
Dynamic: keywords
|
|
34
|
+
Dynamic: license
|
|
35
|
+
Dynamic: project-url
|
|
36
|
+
Dynamic: requires-dist
|
|
37
|
+
Dynamic: requires-python
|
|
38
|
+
Dynamic: summary
|
|
29
39
|
|
|
30
40
|
# LiveKit Server APIs
|
|
31
41
|
|
|
@@ -1,136 +0,0 @@
|
|
|
1
|
-
import aiohttp
|
|
2
|
-
from livekit.protocol import room as proto_room
|
|
3
|
-
from livekit.protocol import models as proto_models
|
|
4
|
-
from ._service import Service
|
|
5
|
-
from .access_token import VideoGrants
|
|
6
|
-
|
|
7
|
-
SVC = "RoomService"
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
class RoomService(Service):
|
|
11
|
-
def __init__(
|
|
12
|
-
self, session: aiohttp.ClientSession, url: str, api_key: str, api_secret: str
|
|
13
|
-
):
|
|
14
|
-
super().__init__(session, url, api_key, api_secret)
|
|
15
|
-
|
|
16
|
-
async def create_room(
|
|
17
|
-
self, create: proto_room.CreateRoomRequest
|
|
18
|
-
) -> proto_models.Room:
|
|
19
|
-
return await self._client.request(
|
|
20
|
-
SVC,
|
|
21
|
-
"CreateRoom",
|
|
22
|
-
create,
|
|
23
|
-
self._auth_header(VideoGrants(room_create=True)),
|
|
24
|
-
proto_models.Room,
|
|
25
|
-
)
|
|
26
|
-
|
|
27
|
-
async def list_rooms(
|
|
28
|
-
self, list: proto_room.ListRoomsRequest
|
|
29
|
-
) -> proto_room.ListRoomsResponse:
|
|
30
|
-
return await self._client.request(
|
|
31
|
-
SVC,
|
|
32
|
-
"ListRooms",
|
|
33
|
-
list,
|
|
34
|
-
self._auth_header(VideoGrants(room_list=True)),
|
|
35
|
-
proto_room.ListRoomsResponse,
|
|
36
|
-
)
|
|
37
|
-
|
|
38
|
-
async def delete_room(
|
|
39
|
-
self, delete: proto_room.DeleteRoomRequest
|
|
40
|
-
) -> proto_room.DeleteRoomResponse:
|
|
41
|
-
return await self._client.request(
|
|
42
|
-
SVC,
|
|
43
|
-
"DeleteRoom",
|
|
44
|
-
delete,
|
|
45
|
-
self._auth_header(VideoGrants(room_create=True)),
|
|
46
|
-
proto_room.DeleteRoomResponse,
|
|
47
|
-
)
|
|
48
|
-
|
|
49
|
-
async def update_room_metadata(
|
|
50
|
-
self, update: proto_room.UpdateRoomMetadataRequest
|
|
51
|
-
) -> proto_models.Room:
|
|
52
|
-
return await self._client.request(
|
|
53
|
-
SVC,
|
|
54
|
-
"UpdateRoomMetadata",
|
|
55
|
-
update,
|
|
56
|
-
self._auth_header(VideoGrants(room_admin=True, room=update.room)),
|
|
57
|
-
proto_models.Room,
|
|
58
|
-
)
|
|
59
|
-
|
|
60
|
-
async def list_participants(
|
|
61
|
-
self, list: proto_room.ListParticipantsRequest
|
|
62
|
-
) -> proto_room.ListParticipantsResponse:
|
|
63
|
-
return await self._client.request(
|
|
64
|
-
SVC,
|
|
65
|
-
"ListParticipants",
|
|
66
|
-
list,
|
|
67
|
-
self._auth_header(VideoGrants(room_admin=True, room=list.room)),
|
|
68
|
-
proto_room.ListParticipantsResponse,
|
|
69
|
-
)
|
|
70
|
-
|
|
71
|
-
async def get_participant(
|
|
72
|
-
self, get: proto_room.RoomParticipantIdentity
|
|
73
|
-
) -> proto_models.ParticipantInfo:
|
|
74
|
-
return await self._client.request(
|
|
75
|
-
SVC,
|
|
76
|
-
"GetParticipant",
|
|
77
|
-
get,
|
|
78
|
-
self._auth_header(VideoGrants(room_admin=True, room=get.room)),
|
|
79
|
-
proto_models.ParticipantInfo,
|
|
80
|
-
)
|
|
81
|
-
|
|
82
|
-
async def remove_participant(
|
|
83
|
-
self, remove: proto_room.RoomParticipantIdentity
|
|
84
|
-
) -> proto_room.RemoveParticipantResponse:
|
|
85
|
-
return await self._client.request(
|
|
86
|
-
SVC,
|
|
87
|
-
"RemoveParticipant",
|
|
88
|
-
remove,
|
|
89
|
-
self._auth_header(VideoGrants(room_admin=True, room=remove.room)),
|
|
90
|
-
proto_room.RemoveParticipantResponse,
|
|
91
|
-
)
|
|
92
|
-
|
|
93
|
-
async def mute_published_track(
|
|
94
|
-
self,
|
|
95
|
-
update: proto_room.MuteRoomTrackRequest,
|
|
96
|
-
) -> proto_room.MuteRoomTrackResponse:
|
|
97
|
-
return await self._client.request(
|
|
98
|
-
SVC,
|
|
99
|
-
"MutePublishedTrack",
|
|
100
|
-
update,
|
|
101
|
-
self._auth_header(VideoGrants(room_admin=True, room=update.room)),
|
|
102
|
-
proto_room.MuteRoomTrackResponse,
|
|
103
|
-
)
|
|
104
|
-
|
|
105
|
-
async def update_participant(
|
|
106
|
-
self, update: proto_room.UpdateParticipantRequest
|
|
107
|
-
) -> proto_models.ParticipantInfo:
|
|
108
|
-
return await self._client.request(
|
|
109
|
-
SVC,
|
|
110
|
-
"UpdateParticipant",
|
|
111
|
-
update,
|
|
112
|
-
self._auth_header(VideoGrants(room_admin=True, room=update.room)),
|
|
113
|
-
proto_models.ParticipantInfo,
|
|
114
|
-
)
|
|
115
|
-
|
|
116
|
-
async def update_subscriptions(
|
|
117
|
-
self, update: proto_room.UpdateSubscriptionsRequest
|
|
118
|
-
) -> proto_room.UpdateSubscriptionsResponse:
|
|
119
|
-
return await self._client.request(
|
|
120
|
-
SVC,
|
|
121
|
-
"UpdateSubscriptions",
|
|
122
|
-
update,
|
|
123
|
-
self._auth_header(VideoGrants(room_admin=True, room=update.room)),
|
|
124
|
-
proto_room.UpdateSubscriptionsResponse,
|
|
125
|
-
)
|
|
126
|
-
|
|
127
|
-
async def send_data(
|
|
128
|
-
self, send: proto_room.SendDataRequest
|
|
129
|
-
) -> proto_room.SendDataResponse:
|
|
130
|
-
return await self._client.request(
|
|
131
|
-
SVC,
|
|
132
|
-
"SendData",
|
|
133
|
-
send,
|
|
134
|
-
self._auth_header(VideoGrants(room_admin=True, room=send.room)),
|
|
135
|
-
proto_room.SendDataResponse,
|
|
136
|
-
)
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "0.8.0"
|
|
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
|