Jellyfish Python Server SDK
Python server SDK for the Jellyfish Media Server.
Read the docs here
Installation
pip install jellyfish-server-sdk
Usage
The SDK exports two main classes for interacting with Jellyfish server:
RoomApi
and Notifier
.
RoomApi
wraps http REST api calls, while Notifier
is responsible for receiving real-time updates from the server.
RoomApi
Create a RoomApi
instance, providing the jellyfish server address and api token
from jellyfish import RoomApi
room_api = RoomApi(server_address="localhost:5002", server_api_token="development")
You can use it to interact with Jellyfish, manage rooms, peers and components
# Create a room
jellyfish_address, room = room_api.create_room(video_codec="h264", webhook_url="http://localhost:5000/webhook")
# '127.0.0.1:5002', Room(components=[], config=RoomConfig(max_peers=None, video_codec=<RoomConfigVideoCodec.H264: 'h264'>, webhook_url='http://localhost:5000/webhook'), id='1d905478-ccfc-44d6-a6e7-8ccb1b38d955', peers=[])
# Add peer to the room
from jellyfish import PeerOptionsWebRTC
peer_token, peer_webrtc = room_api.add_peer(room.id, options=PeerOptionsWebRTC())
# 'M8TUGhj-L11KpyG-2zBPIo', Peer(id='b1232c7e-c969-4450-acdf-ea24f3cdd7f6', status=<PeerStatus.DISCONNECTED: 'disconnected'>, type='webrtc')
# Add component to the room
from jellyfish import ComponentOptionsHLS
component_hls = room_api.add_component(room.id, options=ComponentOptionsHLS())
# ComponentHLS(id='5f062447-a9f7-45ed-8d1b-511f77dc78ae', properties=ComponentPropertiesHLS(low_latency=False, persistent=False, playable=False, subscribe_mode=<ComponentPropertiesHLSSubscribeMode.AUTO: 'auto'>, target_window_duration=None), type='hls')
All methods in RoomApi
may raise one of the exceptions deriving from jellyfish.errors.HTTPError
. They are defined in jellyfish.errors
.
Notifier
Notifier allows for receiving real-time updates from the Jellyfish Server.
You can read more about notifications in the Jellyfish Docs.
Create Notifier
instance
from jellyfish import Notifier
notifier = Notifier(server_address='localhost:5002', server_api_token='development')
Then define handlers for incoming messages
@notifier.on_server_notification
def handle_notification(server_notification):
print(f'Received a notification: {server_notification}')
@notifier.on_metrics
def handle_metrics(metrics_report):
print(f'Received WebRTC metrics: {metrics_report}')
After that you can start the notifier
async def test_notifier():
notifier_task = asyncio.create_task(notifier.connect())
# Wait for notifier to be ready to receive messages
await notifier.wait_ready()
# Create a room to trigger a server notification
room_api = RoomApi()
room_api.create_room()
await notifier_task
asyncio.run(test_notifier())
# Received a notification: ServerMessageRoomCreated(room_id='69a3fd1a-6a4d-47bc-ae54-0c72b0d05e29')
# Received WebRTC metrics: ServerMessageMetricsReport(metrics='{}')
Testing
You can test the SDK by running
poetry run ci_test
In local development you can use
poetry run local_test
Format & Lint
You can format code by running
poetry run format
You can check linter by running
poetry run lint
Copyright and License
Copyright 2023, Software Mansion
Licensed under the Apache License, Version 2.0
1""" 2 .. include:: ../README.md 3""" 4 5# pylint: disable=locally-disabled, no-name-in-module, import-error 6 7# Exceptions and Server Messages 8from jellyfish import errors, events 9 10# Models 11from jellyfish._openapi_client.models import ( 12 ComponentFile, 13 ComponentHLS, 14 ComponentOptionsFile, 15 ComponentOptionsHLS, 16 ComponentOptionsHLSSubscribeMode, 17 ComponentOptionsRTSP, 18 ComponentPropertiesFile, 19 ComponentPropertiesHLS, 20 ComponentPropertiesHLSSubscribeMode, 21 ComponentPropertiesRTSP, 22 ComponentRTSP, 23 Peer, 24 PeerOptionsWebRTC, 25 PeerStatus, 26 Room, 27 RoomConfig, 28 RoomConfigVideoCodec, 29) 30 31# API 32from jellyfish._webhook_notifier import receive_json 33from jellyfish._ws_notifier import Notifier 34from jellyfish.api._recording_api import RecordingApi 35from jellyfish.api._room_api import RoomApi 36 37__all__ = [ 38 "RoomApi", 39 "RecordingApi", 40 "Notifier", 41 "receive_json", 42 "Room", 43 "RoomConfig", 44 "RoomConfigVideoCodec", 45 "Peer", 46 "PeerOptionsWebRTC", 47 "PeerStatus", 48 "ComponentHLS", 49 "ComponentOptionsHLS", 50 "ComponentOptionsHLSSubscribeMode", 51 "ComponentPropertiesHLS", 52 "ComponentPropertiesHLSSubscribeMode", 53 "ComponentRTSP", 54 "ComponentOptionsRTSP", 55 "ComponentPropertiesRTSP", 56 "ComponentFile", 57 "ComponentOptionsFile", 58 "ComponentPropertiesFile", 59 "events", 60 "errors", 61] 62__docformat__ = "restructuredtext"
36class RoomApi(BaseApi): 37 """Allows for managing rooms""" 38 39 def __init__( 40 self, 41 server_address: str = "localhost:5002", 42 server_api_token: str = "development", 43 secure: bool = False, 44 ): 45 """ 46 Create RoomApi instance, providing the jellyfish address and api token. 47 Set secure to `True` for `https` and `False` for `http` connection (default). 48 """ 49 super().__init__( 50 server_address=server_address, 51 server_api_token=server_api_token, 52 secure=secure, 53 ) 54 55 def create_room( 56 self, 57 room_id: str = None, 58 max_peers: int = None, 59 video_codec: Literal["h264", "vp8"] = None, 60 webhook_url: str = None, 61 ) -> (str, Room): 62 """ 63 Creates a new room 64 65 Returns a tuple (`jellyfish_address`, `Room`) - the address of the Jellyfish 66 in which the room has been created and the created `Room` 67 68 The returned address may be different from the current `RoomApi` instance. 69 In such case, a new `RoomApi` instance has to be created using 70 the returned address in order to interact with the room. 71 """ 72 73 if video_codec is not None: 74 video_codec = RoomConfigVideoCodec(video_codec) 75 else: 76 video_codec = None 77 78 room_config = RoomConfig( 79 room_id=room_id, 80 max_peers=max_peers, 81 video_codec=video_codec, 82 webhook_url=webhook_url, 83 ) 84 85 resp = self._request(room_create_room, json_body=room_config) 86 return (resp.data.jellyfish_address, resp.data.room) 87 88 def delete_room(self, room_id: str) -> None: 89 """Deletes a room""" 90 91 return self._request(room_delete_room, room_id=room_id) 92 93 def get_all_rooms(self) -> list: 94 """Returns list of all rooms""" 95 96 return self._request(room_get_all_rooms).data 97 98 def get_room(self, room_id: str) -> Room: 99 """Returns room with the given id""" 100 101 return self._request(room_get_room, room_id=room_id).data 102 103 def add_peer(self, room_id: str, options: PeerOptionsWebRTC) -> (str, Peer): 104 """ 105 Creates peer in the room 106 107 Currently only `webrtc` peer is supported 108 109 Returns a tuple (`peer_token`, `Peer`) - the token needed by Peer 110 to authenticate to Jellyfish and the new `Peer` 111 """ 112 113 peer_type = "webrtc" 114 json_body = AddPeerJsonBody(type=peer_type, options=options) 115 116 resp = self._request(room_add_peer, room_id=room_id, json_body=json_body) 117 return (resp.data.token, resp.data.peer) 118 119 def delete_peer(self, room_id: str, peer_id: str) -> None: 120 """Deletes peer""" 121 122 return self._request(room_delete_peer, id=peer_id, room_id=room_id) 123 124 def add_component( 125 self, 126 room_id: str, 127 options: Union[ComponentOptionsFile, ComponentOptionsHLS, ComponentOptionsRTSP], 128 ) -> Union[ComponentFile, ComponentHLS, ComponentRTSP]: 129 """Creates component in the room""" 130 131 if isinstance(options, ComponentOptionsFile): 132 component_type = "file" 133 elif isinstance(options, ComponentOptionsHLS): 134 component_type = "hls" 135 elif isinstance(options, ComponentOptionsRTSP): 136 component_type = "rtsp" 137 else: 138 raise ValueError( 139 "options must be ComponentFile, ComponentOptionsHLS" 140 "or ComponentOptionsRTSP" 141 ) 142 143 json_body = AddComponentJsonBody(type=component_type, options=options) 144 145 return self._request( 146 room_add_component, room_id=room_id, json_body=json_body 147 ).data 148 149 def delete_component(self, room_id: str, component_id: str) -> None: 150 """Deletes component""" 151 152 return self._request(room_delete_component, id=component_id, room_id=room_id) 153 154 def hls_subscribe(self, room_id: str, origins: [str]): 155 """ 156 In order to subscribe to HLS peers/components, 157 the HLS component should be initialized with the subscribe_mode set to manual. 158 This mode proves beneficial when you do not wish to record or stream 159 all the available streams within a room via HLS. 160 It allows for selective addition instead – 161 you can manually select specific streams. 162 For instance, you could opt to record only the stream of an event's host. 163 """ 164 165 return self._request( 166 hls_subscribe_hls_to, 167 room_id=room_id, 168 json_body=SubscriptionConfig(origins=origins), 169 )
Allows for managing rooms
39 def __init__( 40 self, 41 server_address: str = "localhost:5002", 42 server_api_token: str = "development", 43 secure: bool = False, 44 ): 45 """ 46 Create RoomApi instance, providing the jellyfish address and api token. 47 Set secure to `True` for `https` and `False` for `http` connection (default). 48 """ 49 super().__init__( 50 server_address=server_address, 51 server_api_token=server_api_token, 52 secure=secure, 53 )
Create RoomApi instance, providing the jellyfish address and api token.
Set secure to True
for https
and False
for http
connection (default).
55 def create_room( 56 self, 57 room_id: str = None, 58 max_peers: int = None, 59 video_codec: Literal["h264", "vp8"] = None, 60 webhook_url: str = None, 61 ) -> (str, Room): 62 """ 63 Creates a new room 64 65 Returns a tuple (`jellyfish_address`, `Room`) - the address of the Jellyfish 66 in which the room has been created and the created `Room` 67 68 The returned address may be different from the current `RoomApi` instance. 69 In such case, a new `RoomApi` instance has to be created using 70 the returned address in order to interact with the room. 71 """ 72 73 if video_codec is not None: 74 video_codec = RoomConfigVideoCodec(video_codec) 75 else: 76 video_codec = None 77 78 room_config = RoomConfig( 79 room_id=room_id, 80 max_peers=max_peers, 81 video_codec=video_codec, 82 webhook_url=webhook_url, 83 ) 84 85 resp = self._request(room_create_room, json_body=room_config) 86 return (resp.data.jellyfish_address, resp.data.room)
Creates a new room
Returns a tuple (jellyfish_address
, Room
) - the address of the Jellyfish
in which the room has been created and the created Room
The returned address may be different from the current RoomApi
instance.
In such case, a new RoomApi
instance has to be created using
the returned address in order to interact with the room.
88 def delete_room(self, room_id: str) -> None: 89 """Deletes a room""" 90 91 return self._request(room_delete_room, room_id=room_id)
Deletes a room
93 def get_all_rooms(self) -> list: 94 """Returns list of all rooms""" 95 96 return self._request(room_get_all_rooms).data
Returns list of all rooms
98 def get_room(self, room_id: str) -> Room: 99 """Returns room with the given id""" 100 101 return self._request(room_get_room, room_id=room_id).data
Returns room with the given id
103 def add_peer(self, room_id: str, options: PeerOptionsWebRTC) -> (str, Peer): 104 """ 105 Creates peer in the room 106 107 Currently only `webrtc` peer is supported 108 109 Returns a tuple (`peer_token`, `Peer`) - the token needed by Peer 110 to authenticate to Jellyfish and the new `Peer` 111 """ 112 113 peer_type = "webrtc" 114 json_body = AddPeerJsonBody(type=peer_type, options=options) 115 116 resp = self._request(room_add_peer, room_id=room_id, json_body=json_body) 117 return (resp.data.token, resp.data.peer)
119 def delete_peer(self, room_id: str, peer_id: str) -> None: 120 """Deletes peer""" 121 122 return self._request(room_delete_peer, id=peer_id, room_id=room_id)
Deletes peer
124 def add_component( 125 self, 126 room_id: str, 127 options: Union[ComponentOptionsFile, ComponentOptionsHLS, ComponentOptionsRTSP], 128 ) -> Union[ComponentFile, ComponentHLS, ComponentRTSP]: 129 """Creates component in the room""" 130 131 if isinstance(options, ComponentOptionsFile): 132 component_type = "file" 133 elif isinstance(options, ComponentOptionsHLS): 134 component_type = "hls" 135 elif isinstance(options, ComponentOptionsRTSP): 136 component_type = "rtsp" 137 else: 138 raise ValueError( 139 "options must be ComponentFile, ComponentOptionsHLS" 140 "or ComponentOptionsRTSP" 141 ) 142 143 json_body = AddComponentJsonBody(type=component_type, options=options) 144 145 return self._request( 146 room_add_component, room_id=room_id, json_body=json_body 147 ).data
Creates component in the room
149 def delete_component(self, room_id: str, component_id: str) -> None: 150 """Deletes component""" 151 152 return self._request(room_delete_component, id=component_id, room_id=room_id)
Deletes component
154 def hls_subscribe(self, room_id: str, origins: [str]): 155 """ 156 In order to subscribe to HLS peers/components, 157 the HLS component should be initialized with the subscribe_mode set to manual. 158 This mode proves beneficial when you do not wish to record or stream 159 all the available streams within a room via HLS. 160 It allows for selective addition instead – 161 you can manually select specific streams. 162 For instance, you could opt to record only the stream of an event's host. 163 """ 164 165 return self._request( 166 hls_subscribe_hls_to, 167 room_id=room_id, 168 json_body=SubscriptionConfig(origins=origins), 169 )
In order to subscribe to HLS peers/components, the HLS component should be initialized with the subscribe_mode set to manual. This mode proves beneficial when you do not wish to record or stream all the available streams within a room via HLS. It allows for selective addition instead – you can manually select specific streams. For instance, you could opt to record only the stream of an event's host.
Inherited Members
- jellyfish.api._base_api.BaseApi
- client
10class RecordingApi(BaseApi): 11 """Allows for managing recordings""" 12 13 def __init__( 14 self, 15 server_address: str = "localhost:5002", 16 server_api_token: str = "development", 17 secure: bool = False, 18 ): 19 """ 20 Create RecordingApi instance, providing the jellyfish address and api token. 21 Set secure to `True` for `https` and `False` for `http` connection (default). 22 """ 23 24 super().__init__( 25 server_address=server_address, 26 server_api_token=server_api_token, 27 secure=secure, 28 ) 29 30 def get_list(self) -> list: 31 """Returns a list of available recordings""" 32 33 return self._request(get_recordings).data 34 35 def delete(self, recording_id: str): 36 """Deletes recording with given id""" 37 38 return self._request(delete_recording, recording_id=recording_id)
Allows for managing recordings
13 def __init__( 14 self, 15 server_address: str = "localhost:5002", 16 server_api_token: str = "development", 17 secure: bool = False, 18 ): 19 """ 20 Create RecordingApi instance, providing the jellyfish address and api token. 21 Set secure to `True` for `https` and `False` for `http` connection (default). 22 """ 23 24 super().__init__( 25 server_address=server_address, 26 server_api_token=server_api_token, 27 secure=secure, 28 )
Create RecordingApi instance, providing the jellyfish address and api token.
Set secure to True
for https
and False
for http
connection (default).
30 def get_list(self) -> list: 31 """Returns a list of available recordings""" 32 33 return self._request(get_recordings).data
Returns a list of available recordings
35 def delete(self, recording_id: str): 36 """Deletes recording with given id""" 37 38 return self._request(delete_recording, recording_id=recording_id)
Deletes recording with given id
Inherited Members
- jellyfish.api._base_api.BaseApi
- client
24class Notifier: 25 """ 26 Allows for receiving WebSocket messages from Jellyfish. 27 """ 28 29 def __init__( 30 self, 31 server_address: str = "localhost:5002", 32 server_api_token: str = "development", 33 secure: bool = False, 34 ): 35 """ 36 Create Notifier instance, providing the jellyfish address and api token. 37 Set secure to `True` for `wss` and `False` for `ws` connection (default). 38 """ 39 40 protocol = "wss" if secure else "ws" 41 self._server_address = f"{protocol}://{server_address}/socket/server/websocket" 42 self._server_api_token = server_api_token 43 self._websocket = None 44 self._ready = False 45 46 self._ready_event: asyncio.Event = None 47 48 self._notification_handler: Callable = None 49 self._metrics_handler: Callable = None 50 51 def on_server_notification(self, handler: Callable[[Any], None]): 52 """ 53 Decorator used for defining handler for ServerNotifications 54 i.e. all messages other than `ServerMessageMetricsReport`. 55 """ 56 self._notification_handler = handler 57 return handler 58 59 def on_metrics(self, handler: Callable[[ServerMessageMetricsReport], None]): 60 """ 61 Decorator used for defining handler for `ServerMessageMetricsReport`. 62 """ 63 self._metrics_handler = handler 64 return handler 65 66 async def connect(self): 67 """ 68 A coroutine which connects Notifier to Jellyfish and listens for all incoming 69 messages from the Jellyfish. 70 71 It runs until the connection isn't closed. 72 73 The incoming messages are handled by the functions defined using the 74 `on_server_notification` and `on_metrics` decorators. 75 76 The handlers have to be defined before calling `connect`, 77 otherwise the messages won't be received. 78 """ 79 async with client.connect(self._server_address) as websocket: 80 try: 81 self._websocket = websocket 82 await self._authenticate() 83 84 if self._notification_handler: 85 await self._subscribe_event( 86 event=ServerMessageEventType.EVENT_TYPE_SERVER_NOTIFICATION 87 ) 88 89 if self._metrics_handler: 90 await self._subscribe_event( 91 event=ServerMessageEventType.EVENT_TYPE_METRICS 92 ) 93 94 self._ready = True 95 if self._ready_event: 96 self._ready_event.set() 97 98 await self._receive_loop() 99 finally: 100 self._websocket = None 101 102 async def wait_ready(self) -> True: 103 """ 104 Waits until the notifier is connected and authenticated to Jellyfish. 105 106 If already connected, returns `True` immediately. 107 """ 108 if self._ready: 109 return True 110 111 if self._ready_event is None: 112 self._ready_event = asyncio.Event() 113 114 await self._ready_event.wait() 115 116 async def _authenticate(self): 117 msg = ServerMessage( 118 auth_request=ServerMessageAuthRequest(token=self._server_api_token) 119 ) 120 await self._websocket.send(bytes(msg)) 121 122 try: 123 message = await self._websocket.recv() 124 except ConnectionClosed as exception: 125 if "invalid token" in str(exception): 126 raise RuntimeError("Invalid server_api_token") from exception 127 raise 128 129 message = ServerMessage().parse(message) 130 131 _type, message = betterproto.which_one_of(message, "content") 132 assert isinstance(message, ServerMessageAuthenticated) 133 134 async def _receive_loop(self): 135 while True: 136 message = await self._websocket.recv() 137 message = ServerMessage().parse(message) 138 _which, message = betterproto.which_one_of(message, "content") 139 140 if isinstance(message, ServerMessageMetricsReport): 141 self._metrics_handler(message) 142 else: 143 self._notification_handler(message) 144 145 async def _subscribe_event(self, event: ServerMessageEventType): 146 request = ServerMessage(subscribe_request=ServerMessageSubscribeRequest(event)) 147 148 await self._websocket.send(bytes(request)) 149 message = await self._websocket.recv() 150 message = ServerMessage().parse(message) 151 _which, message = betterproto.which_one_of(message, "content") 152 assert isinstance(message, ServerMessageSubscribeResponse)
Allows for receiving WebSocket messages from Jellyfish.
29 def __init__( 30 self, 31 server_address: str = "localhost:5002", 32 server_api_token: str = "development", 33 secure: bool = False, 34 ): 35 """ 36 Create Notifier instance, providing the jellyfish address and api token. 37 Set secure to `True` for `wss` and `False` for `ws` connection (default). 38 """ 39 40 protocol = "wss" if secure else "ws" 41 self._server_address = f"{protocol}://{server_address}/socket/server/websocket" 42 self._server_api_token = server_api_token 43 self._websocket = None 44 self._ready = False 45 46 self._ready_event: asyncio.Event = None 47 48 self._notification_handler: Callable = None 49 self._metrics_handler: Callable = None
Create Notifier instance, providing the jellyfish address and api token.
Set secure to True
for wss
and False
for ws
connection (default).
51 def on_server_notification(self, handler: Callable[[Any], None]): 52 """ 53 Decorator used for defining handler for ServerNotifications 54 i.e. all messages other than `ServerMessageMetricsReport`. 55 """ 56 self._notification_handler = handler 57 return handler
Decorator used for defining handler for ServerNotifications
i.e. all messages other than ServerMessageMetricsReport
.
59 def on_metrics(self, handler: Callable[[ServerMessageMetricsReport], None]): 60 """ 61 Decorator used for defining handler for `ServerMessageMetricsReport`. 62 """ 63 self._metrics_handler = handler 64 return handler
Decorator used for defining handler for ServerMessageMetricsReport
.
66 async def connect(self): 67 """ 68 A coroutine which connects Notifier to Jellyfish and listens for all incoming 69 messages from the Jellyfish. 70 71 It runs until the connection isn't closed. 72 73 The incoming messages are handled by the functions defined using the 74 `on_server_notification` and `on_metrics` decorators. 75 76 The handlers have to be defined before calling `connect`, 77 otherwise the messages won't be received. 78 """ 79 async with client.connect(self._server_address) as websocket: 80 try: 81 self._websocket = websocket 82 await self._authenticate() 83 84 if self._notification_handler: 85 await self._subscribe_event( 86 event=ServerMessageEventType.EVENT_TYPE_SERVER_NOTIFICATION 87 ) 88 89 if self._metrics_handler: 90 await self._subscribe_event( 91 event=ServerMessageEventType.EVENT_TYPE_METRICS 92 ) 93 94 self._ready = True 95 if self._ready_event: 96 self._ready_event.set() 97 98 await self._receive_loop() 99 finally: 100 self._websocket = None
A coroutine which connects Notifier to Jellyfish and listens for all incoming messages from the Jellyfish.
It runs until the connection isn't closed.
The incoming messages are handled by the functions defined using the
on_server_notification
and on_metrics
decorators.
The handlers have to be defined before calling connect
,
otherwise the messages won't be received.
102 async def wait_ready(self) -> True: 103 """ 104 Waits until the notifier is connected and authenticated to Jellyfish. 105 106 If already connected, returns `True` immediately. 107 """ 108 if self._ready: 109 return True 110 111 if self._ready_event is None: 112 self._ready_event = asyncio.Event() 113 114 await self._ready_event.wait()
Waits until the notifier is connected and authenticated to Jellyfish.
If already connected, returns True
immediately.
14def receive_json(json: Dict) -> betterproto.Message: 15 """ 16 Transform received json notification to adequate notification instance. 17 18 The available notifications are listed in `jellyfish.events` module. 19 """ 20 msg = json["notification"] 21 msg = bytes(msg, "utf-8") 22 message = ServerMessage().parse(msg) 23 _which, message = betterproto.which_one_of(message, "content") 24 return message
Transform received json notification to adequate notification instance.
The available notifications are listed in jellyfish.events
module.
18@_attrs_define 19class Room: 20 """Description of the room state""" 21 22 components: List[Union["ComponentFile", "ComponentHLS", "ComponentRTSP"]] 23 """List of all components""" 24 config: "RoomConfig" 25 """Room configuration""" 26 id: str 27 """Room ID""" 28 peers: List["Peer"] 29 """List of all peers""" 30 additional_properties: Dict[str, Any] = _attrs_field(init=False, factory=dict) 31 """@private""" 32 33 def to_dict(self) -> Dict[str, Any]: 34 """@private""" 35 from ..models.component_hls import ComponentHLS 36 from ..models.component_rtsp import ComponentRTSP 37 38 components = [] 39 for components_item_data in self.components: 40 components_item: Dict[str, Any] 41 42 if isinstance(components_item_data, ComponentHLS): 43 components_item = components_item_data.to_dict() 44 45 elif isinstance(components_item_data, ComponentRTSP): 46 components_item = components_item_data.to_dict() 47 48 else: 49 components_item = components_item_data.to_dict() 50 51 components.append(components_item) 52 53 config = self.config.to_dict() 54 55 id = self.id 56 peers = [] 57 for peers_item_data in self.peers: 58 peers_item = peers_item_data.to_dict() 59 60 peers.append(peers_item) 61 62 field_dict: Dict[str, Any] = {} 63 field_dict.update(self.additional_properties) 64 field_dict.update( 65 { 66 "components": components, 67 "config": config, 68 "id": id, 69 "peers": peers, 70 } 71 ) 72 73 return field_dict 74 75 @classmethod 76 def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: 77 """@private""" 78 from ..models.component_file import ComponentFile 79 from ..models.component_hls import ComponentHLS 80 from ..models.component_rtsp import ComponentRTSP 81 from ..models.peer import Peer 82 from ..models.room_config import RoomConfig 83 84 d = src_dict.copy() 85 components = [] 86 _components = d.pop("components") 87 for components_item_data in _components: 88 89 def _parse_components_item( 90 data: object, 91 ) -> Union["ComponentFile", "ComponentHLS", "ComponentRTSP"]: 92 try: 93 if not isinstance(data, dict): 94 raise TypeError() 95 componentsschemas_component_type_0 = ComponentHLS.from_dict(data) 96 97 return componentsschemas_component_type_0 98 except: # noqa: E722 99 pass 100 try: 101 if not isinstance(data, dict): 102 raise TypeError() 103 componentsschemas_component_type_1 = ComponentRTSP.from_dict(data) 104 105 return componentsschemas_component_type_1 106 except: # noqa: E722 107 pass 108 if not isinstance(data, dict): 109 raise TypeError() 110 componentsschemas_component_type_2 = ComponentFile.from_dict(data) 111 112 return componentsschemas_component_type_2 113 114 components_item = _parse_components_item(components_item_data) 115 116 components.append(components_item) 117 118 config = RoomConfig.from_dict(d.pop("config")) 119 120 id = d.pop("id") 121 122 peers = [] 123 _peers = d.pop("peers") 124 for peers_item_data in _peers: 125 peers_item = Peer.from_dict(peers_item_data) 126 127 peers.append(peers_item) 128 129 room = cls( 130 components=components, 131 config=config, 132 id=id, 133 peers=peers, 134 ) 135 136 room.additional_properties = d 137 return room 138 139 @property 140 def additional_keys(self) -> List[str]: 141 """@private""" 142 return list(self.additional_properties.keys()) 143 144 def __getitem__(self, key: str) -> Any: 145 return self.additional_properties[key] 146 147 def __setitem__(self, key: str, value: Any) -> None: 148 self.additional_properties[key] = value 149 150 def __delitem__(self, key: str) -> None: 151 del self.additional_properties[key] 152 153 def __contains__(self, key: str) -> bool: 154 return key in self.additional_properties
Description of the room state
2def __init__(self, components, config, id, peers): 3 self.components = components 4 self.config = config 5 self.id = id 6 self.peers = peers 7 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class Room.
13@_attrs_define 14class RoomConfig: 15 """Room configuration""" 16 17 max_peers: Union[Unset, None, int] = UNSET 18 """Maximum amount of peers allowed into the room""" 19 room_id: Union[Unset, None, str] = UNSET 20 """Custom id used for identifying room within Jellyfish. Must be unique across all rooms. If not provided, random UUID is generated.""" 21 video_codec: Union[Unset, None, RoomConfigVideoCodec] = UNSET 22 """Enforces video codec for each peer in the room""" 23 webhook_url: Union[Unset, None, str] = UNSET 24 """URL where Jellyfish notifications will be sent""" 25 additional_properties: Dict[str, Any] = _attrs_field(init=False, factory=dict) 26 """@private""" 27 28 def to_dict(self) -> Dict[str, Any]: 29 """@private""" 30 max_peers = self.max_peers 31 room_id = self.room_id 32 video_codec: Union[Unset, None, str] = UNSET 33 if not isinstance(self.video_codec, Unset): 34 video_codec = self.video_codec.value if self.video_codec else None 35 36 webhook_url = self.webhook_url 37 38 field_dict: Dict[str, Any] = {} 39 field_dict.update(self.additional_properties) 40 field_dict.update({}) 41 if max_peers is not UNSET: 42 field_dict["maxPeers"] = max_peers 43 if room_id is not UNSET: 44 field_dict["roomId"] = room_id 45 if video_codec is not UNSET: 46 field_dict["videoCodec"] = video_codec 47 if webhook_url is not UNSET: 48 field_dict["webhookUrl"] = webhook_url 49 50 return field_dict 51 52 @classmethod 53 def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: 54 """@private""" 55 d = src_dict.copy() 56 max_peers = d.pop("maxPeers", UNSET) 57 58 room_id = d.pop("roomId", UNSET) 59 60 _video_codec = d.pop("videoCodec", UNSET) 61 video_codec: Union[Unset, None, RoomConfigVideoCodec] 62 if _video_codec is None: 63 video_codec = None 64 elif isinstance(_video_codec, Unset): 65 video_codec = UNSET 66 else: 67 video_codec = RoomConfigVideoCodec(_video_codec) 68 69 webhook_url = d.pop("webhookUrl", UNSET) 70 71 room_config = cls( 72 max_peers=max_peers, 73 room_id=room_id, 74 video_codec=video_codec, 75 webhook_url=webhook_url, 76 ) 77 78 room_config.additional_properties = d 79 return room_config 80 81 @property 82 def additional_keys(self) -> List[str]: 83 """@private""" 84 return list(self.additional_properties.keys()) 85 86 def __getitem__(self, key: str) -> Any: 87 return self.additional_properties[key] 88 89 def __setitem__(self, key: str, value: Any) -> None: 90 self.additional_properties[key] = value 91 92 def __delitem__(self, key: str) -> None: 93 del self.additional_properties[key] 94 95 def __contains__(self, key: str) -> bool: 96 return key in self.additional_properties
Room configuration
2def __init__(self, max_peers=attr_dict['max_peers'].default, room_id=attr_dict['room_id'].default, video_codec=attr_dict['video_codec'].default, webhook_url=attr_dict['webhook_url'].default): 3 self.max_peers = max_peers 4 self.room_id = room_id 5 self.video_codec = video_codec 6 self.webhook_url = webhook_url 7 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class RoomConfig.
Maximum amount of peers allowed into the room
Custom id used for identifying room within Jellyfish. Must be unique across all rooms. If not provided, random UUID is generated.
Enforces video codec for each peer in the room
5class RoomConfigVideoCodec(str, Enum): 6 """Enforces video codec for each peer in the room""" 7 8 H264 = "h264" 9 VP8 = "vp8" 10 11 def __str__(self) -> str: 12 return str(self.value)
Enforces video codec for each peer in the room
Inherited Members
- enum.Enum
- name
- value
- builtins.str
- encode
- replace
- split
- rsplit
- join
- capitalize
- casefold
- title
- center
- count
- expandtabs
- find
- partition
- index
- ljust
- lower
- lstrip
- rfind
- rindex
- rjust
- rstrip
- rpartition
- splitlines
- strip
- swapcase
- translate
- upper
- startswith
- endswith
- removeprefix
- removesuffix
- isascii
- islower
- isupper
- istitle
- isspace
- isdecimal
- isdigit
- isnumeric
- isalpha
- isalnum
- isidentifier
- isprintable
- zfill
- format
- format_map
- maketrans
12@_attrs_define 13class Peer: 14 """Describes peer status""" 15 16 id: str 17 """Assigned peer id""" 18 status: PeerStatus 19 """Informs about the peer status""" 20 type: str 21 """Peer type""" 22 additional_properties: Dict[str, Any] = _attrs_field(init=False, factory=dict) 23 """@private""" 24 25 def to_dict(self) -> Dict[str, Any]: 26 """@private""" 27 id = self.id 28 status = self.status.value 29 30 type = self.type 31 32 field_dict: Dict[str, Any] = {} 33 field_dict.update(self.additional_properties) 34 field_dict.update( 35 { 36 "id": id, 37 "status": status, 38 "type": type, 39 } 40 ) 41 42 return field_dict 43 44 @classmethod 45 def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: 46 """@private""" 47 d = src_dict.copy() 48 id = d.pop("id") 49 50 status = PeerStatus(d.pop("status")) 51 52 type = d.pop("type") 53 54 peer = cls( 55 id=id, 56 status=status, 57 type=type, 58 ) 59 60 peer.additional_properties = d 61 return peer 62 63 @property 64 def additional_keys(self) -> List[str]: 65 """@private""" 66 return list(self.additional_properties.keys()) 67 68 def __getitem__(self, key: str) -> Any: 69 return self.additional_properties[key] 70 71 def __setitem__(self, key: str, value: Any) -> None: 72 self.additional_properties[key] = value 73 74 def __delitem__(self, key: str) -> None: 75 del self.additional_properties[key] 76 77 def __contains__(self, key: str) -> bool: 78 return key in self.additional_properties
Describes peer status
12@_attrs_define 13class PeerOptionsWebRTC: 14 """Options specific to the WebRTC peer""" 15 16 enable_simulcast: Union[Unset, bool] = True 17 """Enables the peer to use simulcast""" 18 additional_properties: Dict[str, Any] = _attrs_field(init=False, factory=dict) 19 """@private""" 20 21 def to_dict(self) -> Dict[str, Any]: 22 """@private""" 23 enable_simulcast = self.enable_simulcast 24 25 field_dict: Dict[str, Any] = {} 26 field_dict.update(self.additional_properties) 27 field_dict.update({}) 28 if enable_simulcast is not UNSET: 29 field_dict["enableSimulcast"] = enable_simulcast 30 31 return field_dict 32 33 @classmethod 34 def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: 35 """@private""" 36 d = src_dict.copy() 37 enable_simulcast = d.pop("enableSimulcast", UNSET) 38 39 peer_options_web_rtc = cls( 40 enable_simulcast=enable_simulcast, 41 ) 42 43 peer_options_web_rtc.additional_properties = d 44 return peer_options_web_rtc 45 46 @property 47 def additional_keys(self) -> List[str]: 48 """@private""" 49 return list(self.additional_properties.keys()) 50 51 def __getitem__(self, key: str) -> Any: 52 return self.additional_properties[key] 53 54 def __setitem__(self, key: str, value: Any) -> None: 55 self.additional_properties[key] = value 56 57 def __delitem__(self, key: str) -> None: 58 del self.additional_properties[key] 59 60 def __contains__(self, key: str) -> bool: 61 return key in self.additional_properties
Options specific to the WebRTC peer
2def __init__(self, enable_simulcast=attr_dict['enable_simulcast'].default): 3 self.enable_simulcast = enable_simulcast 4 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class PeerOptionsWebRTC.
5class PeerStatus(str, Enum): 6 """Informs about the peer status""" 7 8 CONNECTED = "connected" 9 DISCONNECTED = "disconnected" 10 11 def __str__(self) -> str: 12 return str(self.value)
Informs about the peer status
Inherited Members
- enum.Enum
- name
- value
- builtins.str
- encode
- replace
- split
- rsplit
- join
- capitalize
- casefold
- title
- center
- count
- expandtabs
- find
- partition
- index
- ljust
- lower
- lstrip
- rfind
- rindex
- rjust
- rstrip
- rpartition
- splitlines
- strip
- swapcase
- translate
- upper
- startswith
- endswith
- removeprefix
- removesuffix
- isascii
- islower
- isupper
- istitle
- isspace
- isdecimal
- isdigit
- isnumeric
- isalpha
- isalnum
- isidentifier
- isprintable
- zfill
- format
- format_map
- maketrans
14@_attrs_define 15class ComponentHLS: 16 """Describes the HLS component""" 17 18 id: str 19 """Assigned component ID""" 20 properties: "ComponentPropertiesHLS" 21 """Properties specific to the HLS component""" 22 type: str 23 """Component type""" 24 additional_properties: Dict[str, Any] = _attrs_field(init=False, factory=dict) 25 """@private""" 26 27 def to_dict(self) -> Dict[str, Any]: 28 """@private""" 29 id = self.id 30 properties = self.properties.to_dict() 31 32 type = self.type 33 34 field_dict: Dict[str, Any] = {} 35 field_dict.update(self.additional_properties) 36 field_dict.update( 37 { 38 "id": id, 39 "properties": properties, 40 "type": type, 41 } 42 ) 43 44 return field_dict 45 46 @classmethod 47 def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: 48 """@private""" 49 from ..models.component_properties_hls import ComponentPropertiesHLS 50 51 d = src_dict.copy() 52 id = d.pop("id") 53 54 properties = ComponentPropertiesHLS.from_dict(d.pop("properties")) 55 56 type = d.pop("type") 57 58 component_hls = cls( 59 id=id, 60 properties=properties, 61 type=type, 62 ) 63 64 component_hls.additional_properties = d 65 return component_hls 66 67 @property 68 def additional_keys(self) -> List[str]: 69 """@private""" 70 return list(self.additional_properties.keys()) 71 72 def __getitem__(self, key: str) -> Any: 73 return self.additional_properties[key] 74 75 def __setitem__(self, key: str, value: Any) -> None: 76 self.additional_properties[key] = value 77 78 def __delitem__(self, key: str) -> None: 79 del self.additional_properties[key] 80 81 def __contains__(self, key: str) -> bool: 82 return key in self.additional_properties
Describes the HLS component
19@_attrs_define 20class ComponentOptionsHLS: 21 """Options specific to the HLS component""" 22 23 low_latency: Union[Unset, bool] = False 24 """Whether the component should use LL-HLS""" 25 persistent: Union[Unset, bool] = False 26 """Whether the video is stored after end of stream""" 27 s3: Union[Unset, None, "S3Credentials"] = UNSET 28 """An AWS S3 credential that will be used to send HLS stream. The stream will only be uploaded if credentials are provided""" 29 subscribe_mode: Union[ 30 Unset, ComponentOptionsHLSSubscribeMode 31 ] = ComponentOptionsHLSSubscribeMode.AUTO 32 """Whether the HLS component should subscribe to tracks automatically or manually.""" 33 target_window_duration: Union[Unset, None, int] = UNSET 34 """Duration of stream available for viewer""" 35 additional_properties: Dict[str, Any] = _attrs_field(init=False, factory=dict) 36 """@private""" 37 38 def to_dict(self) -> Dict[str, Any]: 39 """@private""" 40 low_latency = self.low_latency 41 persistent = self.persistent 42 s3: Union[Unset, None, Dict[str, Any]] = UNSET 43 if not isinstance(self.s3, Unset): 44 s3 = self.s3.to_dict() if self.s3 else None 45 46 subscribe_mode: Union[Unset, str] = UNSET 47 if not isinstance(self.subscribe_mode, Unset): 48 subscribe_mode = self.subscribe_mode.value 49 50 target_window_duration = self.target_window_duration 51 52 field_dict: Dict[str, Any] = {} 53 field_dict.update(self.additional_properties) 54 field_dict.update({}) 55 if low_latency is not UNSET: 56 field_dict["lowLatency"] = low_latency 57 if persistent is not UNSET: 58 field_dict["persistent"] = persistent 59 if s3 is not UNSET: 60 field_dict["s3"] = s3 61 if subscribe_mode is not UNSET: 62 field_dict["subscribeMode"] = subscribe_mode 63 if target_window_duration is not UNSET: 64 field_dict["targetWindowDuration"] = target_window_duration 65 66 return field_dict 67 68 @classmethod 69 def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: 70 """@private""" 71 from ..models.s3_credentials import S3Credentials 72 73 d = src_dict.copy() 74 low_latency = d.pop("lowLatency", UNSET) 75 76 persistent = d.pop("persistent", UNSET) 77 78 _s3 = d.pop("s3", UNSET) 79 s3: Union[Unset, None, S3Credentials] 80 if _s3 is None: 81 s3 = None 82 elif isinstance(_s3, Unset): 83 s3 = UNSET 84 else: 85 s3 = S3Credentials.from_dict(_s3) 86 87 _subscribe_mode = d.pop("subscribeMode", UNSET) 88 subscribe_mode: Union[Unset, ComponentOptionsHLSSubscribeMode] 89 if isinstance(_subscribe_mode, Unset): 90 subscribe_mode = UNSET 91 else: 92 subscribe_mode = ComponentOptionsHLSSubscribeMode(_subscribe_mode) 93 94 target_window_duration = d.pop("targetWindowDuration", UNSET) 95 96 component_options_hls = cls( 97 low_latency=low_latency, 98 persistent=persistent, 99 s3=s3, 100 subscribe_mode=subscribe_mode, 101 target_window_duration=target_window_duration, 102 ) 103 104 component_options_hls.additional_properties = d 105 return component_options_hls 106 107 @property 108 def additional_keys(self) -> List[str]: 109 """@private""" 110 return list(self.additional_properties.keys()) 111 112 def __getitem__(self, key: str) -> Any: 113 return self.additional_properties[key] 114 115 def __setitem__(self, key: str, value: Any) -> None: 116 self.additional_properties[key] = value 117 118 def __delitem__(self, key: str) -> None: 119 del self.additional_properties[key] 120 121 def __contains__(self, key: str) -> bool: 122 return key in self.additional_properties
Options specific to the HLS component
2def __init__(self, low_latency=attr_dict['low_latency'].default, persistent=attr_dict['persistent'].default, s3=attr_dict['s3'].default, subscribe_mode=attr_dict['subscribe_mode'].default, target_window_duration=attr_dict['target_window_duration'].default): 3 self.low_latency = low_latency 4 self.persistent = persistent 5 self.s3 = s3 6 self.subscribe_mode = subscribe_mode 7 self.target_window_duration = target_window_duration 8 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class ComponentOptionsHLS.
Whether the component should use LL-HLS
Whether the video is stored after end of stream
An AWS S3 credential that will be used to send HLS stream. The stream will only be uploaded if credentials are provided
Whether the HLS component should subscribe to tracks automatically or manually.
5class ComponentOptionsHLSSubscribeMode(str, Enum): 6 """Whether the HLS component should subscribe to tracks automatically or manually.""" 7 8 AUTO = "auto" 9 MANUAL = "manual" 10 11 def __str__(self) -> str: 12 return str(self.value)
Whether the HLS component should subscribe to tracks automatically or manually.
Inherited Members
- enum.Enum
- name
- value
- builtins.str
- encode
- replace
- split
- rsplit
- join
- capitalize
- casefold
- title
- center
- count
- expandtabs
- find
- partition
- index
- ljust
- lower
- lstrip
- rfind
- rindex
- rjust
- rstrip
- rpartition
- splitlines
- strip
- swapcase
- translate
- upper
- startswith
- endswith
- removeprefix
- removesuffix
- isascii
- islower
- isupper
- istitle
- isspace
- isdecimal
- isdigit
- isnumeric
- isalpha
- isalnum
- isidentifier
- isprintable
- zfill
- format
- format_map
- maketrans
14@_attrs_define 15class ComponentPropertiesHLS: 16 """Properties specific to the HLS component""" 17 18 low_latency: bool 19 """Whether the component uses LL-HLS""" 20 persistent: bool 21 """Whether the video is stored after end of stream""" 22 playable: bool 23 """Whether the generated HLS playlist is playable""" 24 subscribe_mode: ComponentPropertiesHLSSubscribeMode 25 """Whether the HLS component should subscribe to tracks automatically or manually""" 26 target_window_duration: Optional[int] 27 """Duration of stream available for viewer""" 28 additional_properties: Dict[str, Any] = _attrs_field(init=False, factory=dict) 29 """@private""" 30 31 def to_dict(self) -> Dict[str, Any]: 32 """@private""" 33 low_latency = self.low_latency 34 persistent = self.persistent 35 playable = self.playable 36 subscribe_mode = self.subscribe_mode.value 37 38 target_window_duration = self.target_window_duration 39 40 field_dict: Dict[str, Any] = {} 41 field_dict.update(self.additional_properties) 42 field_dict.update( 43 { 44 "lowLatency": low_latency, 45 "persistent": persistent, 46 "playable": playable, 47 "subscribeMode": subscribe_mode, 48 "targetWindowDuration": target_window_duration, 49 } 50 ) 51 52 return field_dict 53 54 @classmethod 55 def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: 56 """@private""" 57 d = src_dict.copy() 58 low_latency = d.pop("lowLatency") 59 60 persistent = d.pop("persistent") 61 62 playable = d.pop("playable") 63 64 subscribe_mode = ComponentPropertiesHLSSubscribeMode(d.pop("subscribeMode")) 65 66 target_window_duration = d.pop("targetWindowDuration") 67 68 component_properties_hls = cls( 69 low_latency=low_latency, 70 persistent=persistent, 71 playable=playable, 72 subscribe_mode=subscribe_mode, 73 target_window_duration=target_window_duration, 74 ) 75 76 component_properties_hls.additional_properties = d 77 return component_properties_hls 78 79 @property 80 def additional_keys(self) -> List[str]: 81 """@private""" 82 return list(self.additional_properties.keys()) 83 84 def __getitem__(self, key: str) -> Any: 85 return self.additional_properties[key] 86 87 def __setitem__(self, key: str, value: Any) -> None: 88 self.additional_properties[key] = value 89 90 def __delitem__(self, key: str) -> None: 91 del self.additional_properties[key] 92 93 def __contains__(self, key: str) -> bool: 94 return key in self.additional_properties
Properties specific to the HLS component
2def __init__(self, low_latency, persistent, playable, subscribe_mode, target_window_duration): 3 self.low_latency = low_latency 4 self.persistent = persistent 5 self.playable = playable 6 self.subscribe_mode = subscribe_mode 7 self.target_window_duration = target_window_duration 8 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class ComponentPropertiesHLS.
Whether the HLS component should subscribe to tracks automatically or manually
5class ComponentPropertiesHLSSubscribeMode(str, Enum): 6 """Whether the HLS component should subscribe to tracks automatically or manually""" 7 8 AUTO = "auto" 9 MANUAL = "manual" 10 11 def __str__(self) -> str: 12 return str(self.value)
Whether the HLS component should subscribe to tracks automatically or manually
Inherited Members
- enum.Enum
- name
- value
- builtins.str
- encode
- replace
- split
- rsplit
- join
- capitalize
- casefold
- title
- center
- count
- expandtabs
- find
- partition
- index
- ljust
- lower
- lstrip
- rfind
- rindex
- rjust
- rstrip
- rpartition
- splitlines
- strip
- swapcase
- translate
- upper
- startswith
- endswith
- removeprefix
- removesuffix
- isascii
- islower
- isupper
- istitle
- isspace
- isdecimal
- isdigit
- isnumeric
- isalpha
- isalnum
- isidentifier
- isprintable
- zfill
- format
- format_map
- maketrans
14@_attrs_define 15class ComponentRTSP: 16 """Describes the RTSP component""" 17 18 id: str 19 """Assigned component ID""" 20 properties: "ComponentPropertiesRTSP" 21 """Properties specific to the RTSP component""" 22 type: str 23 """Component type""" 24 additional_properties: Dict[str, Any] = _attrs_field(init=False, factory=dict) 25 """@private""" 26 27 def to_dict(self) -> Dict[str, Any]: 28 """@private""" 29 id = self.id 30 properties = self.properties.to_dict() 31 32 type = self.type 33 34 field_dict: Dict[str, Any] = {} 35 field_dict.update(self.additional_properties) 36 field_dict.update( 37 { 38 "id": id, 39 "properties": properties, 40 "type": type, 41 } 42 ) 43 44 return field_dict 45 46 @classmethod 47 def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: 48 """@private""" 49 from ..models.component_properties_rtsp import ComponentPropertiesRTSP 50 51 d = src_dict.copy() 52 id = d.pop("id") 53 54 properties = ComponentPropertiesRTSP.from_dict(d.pop("properties")) 55 56 type = d.pop("type") 57 58 component_rtsp = cls( 59 id=id, 60 properties=properties, 61 type=type, 62 ) 63 64 component_rtsp.additional_properties = d 65 return component_rtsp 66 67 @property 68 def additional_keys(self) -> List[str]: 69 """@private""" 70 return list(self.additional_properties.keys()) 71 72 def __getitem__(self, key: str) -> Any: 73 return self.additional_properties[key] 74 75 def __setitem__(self, key: str, value: Any) -> None: 76 self.additional_properties[key] = value 77 78 def __delitem__(self, key: str) -> None: 79 del self.additional_properties[key] 80 81 def __contains__(self, key: str) -> bool: 82 return key in self.additional_properties
Describes the RTSP component
2def __init__(self, id, properties, type): 3 self.id = id 4 self.properties = properties 5 self.type = type 6 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class ComponentRTSP.
12@_attrs_define 13class ComponentOptionsRTSP: 14 """Options specific to the RTSP component""" 15 16 source_uri: str 17 """URI of RTSP source stream""" 18 keep_alive_interval: Union[Unset, int] = 15000 19 """Interval (in ms) in which keep-alive RTSP messages will be sent to the remote stream source""" 20 pierce_nat: Union[Unset, bool] = True 21 """Whether to attempt to create client-side NAT binding by sending an empty datagram from client to source, after the completion of RTSP setup""" 22 reconnect_delay: Union[Unset, int] = 15000 23 """Delay (in ms) between successive reconnect attempts""" 24 rtp_port: Union[Unset, int] = 20000 25 """Local port RTP stream will be received at""" 26 additional_properties: Dict[str, Any] = _attrs_field(init=False, factory=dict) 27 """@private""" 28 29 def to_dict(self) -> Dict[str, Any]: 30 """@private""" 31 source_uri = self.source_uri 32 keep_alive_interval = self.keep_alive_interval 33 pierce_nat = self.pierce_nat 34 reconnect_delay = self.reconnect_delay 35 rtp_port = self.rtp_port 36 37 field_dict: Dict[str, Any] = {} 38 field_dict.update(self.additional_properties) 39 field_dict.update( 40 { 41 "sourceUri": source_uri, 42 } 43 ) 44 if keep_alive_interval is not UNSET: 45 field_dict["keepAliveInterval"] = keep_alive_interval 46 if pierce_nat is not UNSET: 47 field_dict["pierceNat"] = pierce_nat 48 if reconnect_delay is not UNSET: 49 field_dict["reconnectDelay"] = reconnect_delay 50 if rtp_port is not UNSET: 51 field_dict["rtpPort"] = rtp_port 52 53 return field_dict 54 55 @classmethod 56 def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: 57 """@private""" 58 d = src_dict.copy() 59 source_uri = d.pop("sourceUri") 60 61 keep_alive_interval = d.pop("keepAliveInterval", UNSET) 62 63 pierce_nat = d.pop("pierceNat", UNSET) 64 65 reconnect_delay = d.pop("reconnectDelay", UNSET) 66 67 rtp_port = d.pop("rtpPort", UNSET) 68 69 component_options_rtsp = cls( 70 source_uri=source_uri, 71 keep_alive_interval=keep_alive_interval, 72 pierce_nat=pierce_nat, 73 reconnect_delay=reconnect_delay, 74 rtp_port=rtp_port, 75 ) 76 77 component_options_rtsp.additional_properties = d 78 return component_options_rtsp 79 80 @property 81 def additional_keys(self) -> List[str]: 82 """@private""" 83 return list(self.additional_properties.keys()) 84 85 def __getitem__(self, key: str) -> Any: 86 return self.additional_properties[key] 87 88 def __setitem__(self, key: str, value: Any) -> None: 89 self.additional_properties[key] = value 90 91 def __delitem__(self, key: str) -> None: 92 del self.additional_properties[key] 93 94 def __contains__(self, key: str) -> bool: 95 return key in self.additional_properties
Options specific to the RTSP component
2def __init__(self, source_uri, keep_alive_interval=attr_dict['keep_alive_interval'].default, pierce_nat=attr_dict['pierce_nat'].default, reconnect_delay=attr_dict['reconnect_delay'].default, rtp_port=attr_dict['rtp_port'].default): 3 self.source_uri = source_uri 4 self.keep_alive_interval = keep_alive_interval 5 self.pierce_nat = pierce_nat 6 self.reconnect_delay = reconnect_delay 7 self.rtp_port = rtp_port 8 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class ComponentOptionsRTSP.
Interval (in ms) in which keep-alive RTSP messages will be sent to the remote stream source
Whether to attempt to create client-side NAT binding by sending an empty datagram from client to source, after the completion of RTSP setup
12@_attrs_define 13class ComponentPropertiesRTSP: 14 """Properties specific to the RTSP component""" 15 16 source_uri: str 17 """URI of RTSP source stream""" 18 keep_alive_interval: Union[Unset, int] = UNSET 19 """Interval (in ms) in which keep-alive RTSP messages will be sent to the remote stream source""" 20 pierce_nat: Union[Unset, bool] = UNSET 21 """Whether to attempt to create client-side NAT binding by sending an empty datagram from client to source, after the completion of RTSP setup""" 22 reconnect_delay: Union[Unset, int] = UNSET 23 """Delay (in ms) between successive reconnect attempts""" 24 rtp_port: Union[Unset, int] = UNSET 25 """Local port RTP stream will be received at""" 26 additional_properties: Dict[str, Any] = _attrs_field(init=False, factory=dict) 27 """@private""" 28 29 def to_dict(self) -> Dict[str, Any]: 30 """@private""" 31 source_uri = self.source_uri 32 keep_alive_interval = self.keep_alive_interval 33 pierce_nat = self.pierce_nat 34 reconnect_delay = self.reconnect_delay 35 rtp_port = self.rtp_port 36 37 field_dict: Dict[str, Any] = {} 38 field_dict.update(self.additional_properties) 39 field_dict.update( 40 { 41 "sourceUri": source_uri, 42 } 43 ) 44 if keep_alive_interval is not UNSET: 45 field_dict["keepAliveInterval"] = keep_alive_interval 46 if pierce_nat is not UNSET: 47 field_dict["pierceNat"] = pierce_nat 48 if reconnect_delay is not UNSET: 49 field_dict["reconnectDelay"] = reconnect_delay 50 if rtp_port is not UNSET: 51 field_dict["rtpPort"] = rtp_port 52 53 return field_dict 54 55 @classmethod 56 def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: 57 """@private""" 58 d = src_dict.copy() 59 source_uri = d.pop("sourceUri") 60 61 keep_alive_interval = d.pop("keepAliveInterval", UNSET) 62 63 pierce_nat = d.pop("pierceNat", UNSET) 64 65 reconnect_delay = d.pop("reconnectDelay", UNSET) 66 67 rtp_port = d.pop("rtpPort", UNSET) 68 69 component_properties_rtsp = cls( 70 source_uri=source_uri, 71 keep_alive_interval=keep_alive_interval, 72 pierce_nat=pierce_nat, 73 reconnect_delay=reconnect_delay, 74 rtp_port=rtp_port, 75 ) 76 77 component_properties_rtsp.additional_properties = d 78 return component_properties_rtsp 79 80 @property 81 def additional_keys(self) -> List[str]: 82 """@private""" 83 return list(self.additional_properties.keys()) 84 85 def __getitem__(self, key: str) -> Any: 86 return self.additional_properties[key] 87 88 def __setitem__(self, key: str, value: Any) -> None: 89 self.additional_properties[key] = value 90 91 def __delitem__(self, key: str) -> None: 92 del self.additional_properties[key] 93 94 def __contains__(self, key: str) -> bool: 95 return key in self.additional_properties
Properties specific to the RTSP component
2def __init__(self, source_uri, keep_alive_interval=attr_dict['keep_alive_interval'].default, pierce_nat=attr_dict['pierce_nat'].default, reconnect_delay=attr_dict['reconnect_delay'].default, rtp_port=attr_dict['rtp_port'].default): 3 self.source_uri = source_uri 4 self.keep_alive_interval = keep_alive_interval 5 self.pierce_nat = pierce_nat 6 self.reconnect_delay = reconnect_delay 7 self.rtp_port = rtp_port 8 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class ComponentPropertiesRTSP.
Interval (in ms) in which keep-alive RTSP messages will be sent to the remote stream source
Whether to attempt to create client-side NAT binding by sending an empty datagram from client to source, after the completion of RTSP setup
16@_attrs_define 17class ComponentFile: 18 """Describes the File component""" 19 20 id: str 21 """Assigned component ID""" 22 type: str 23 """Component type""" 24 properties: Union[Unset, "ComponentPropertiesFile"] = UNSET 25 """Properties specific to the File component""" 26 additional_properties: Dict[str, Any] = _attrs_field(init=False, factory=dict) 27 """@private""" 28 29 def to_dict(self) -> Dict[str, Any]: 30 """@private""" 31 id = self.id 32 type = self.type 33 properties: Union[Unset, Dict[str, Any]] = UNSET 34 if not isinstance(self.properties, Unset): 35 properties = self.properties.to_dict() 36 37 field_dict: Dict[str, Any] = {} 38 field_dict.update(self.additional_properties) 39 field_dict.update( 40 { 41 "id": id, 42 "type": type, 43 } 44 ) 45 if properties is not UNSET: 46 field_dict["properties"] = properties 47 48 return field_dict 49 50 @classmethod 51 def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: 52 """@private""" 53 from ..models.component_properties_file import ComponentPropertiesFile 54 55 d = src_dict.copy() 56 id = d.pop("id") 57 58 type = d.pop("type") 59 60 _properties = d.pop("properties", UNSET) 61 properties: Union[Unset, ComponentPropertiesFile] 62 if isinstance(_properties, Unset): 63 properties = UNSET 64 else: 65 properties = ComponentPropertiesFile.from_dict(_properties) 66 67 component_file = cls( 68 id=id, 69 type=type, 70 properties=properties, 71 ) 72 73 component_file.additional_properties = d 74 return component_file 75 76 @property 77 def additional_keys(self) -> List[str]: 78 """@private""" 79 return list(self.additional_properties.keys()) 80 81 def __getitem__(self, key: str) -> Any: 82 return self.additional_properties[key] 83 84 def __setitem__(self, key: str, value: Any) -> None: 85 self.additional_properties[key] = value 86 87 def __delitem__(self, key: str) -> None: 88 del self.additional_properties[key] 89 90 def __contains__(self, key: str) -> bool: 91 return key in self.additional_properties
Describes the File component
2def __init__(self, id, type, properties=attr_dict['properties'].default): 3 self.id = id 4 self.type = type 5 self.properties = properties 6 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class ComponentFile.
Properties specific to the File component
10@_attrs_define 11class ComponentOptionsFile: 12 """Options specific to the File component""" 13 14 file_path: str 15 """Path to track file. Must be either OPUS encapsulated in Ogg or raw h264""" 16 additional_properties: Dict[str, Any] = _attrs_field(init=False, factory=dict) 17 """@private""" 18 19 def to_dict(self) -> Dict[str, Any]: 20 """@private""" 21 file_path = self.file_path 22 23 field_dict: Dict[str, Any] = {} 24 field_dict.update(self.additional_properties) 25 field_dict.update( 26 { 27 "filePath": file_path, 28 } 29 ) 30 31 return field_dict 32 33 @classmethod 34 def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: 35 """@private""" 36 d = src_dict.copy() 37 file_path = d.pop("filePath") 38 39 component_options_file = cls( 40 file_path=file_path, 41 ) 42 43 component_options_file.additional_properties = d 44 return component_options_file 45 46 @property 47 def additional_keys(self) -> List[str]: 48 """@private""" 49 return list(self.additional_properties.keys()) 50 51 def __getitem__(self, key: str) -> Any: 52 return self.additional_properties[key] 53 54 def __setitem__(self, key: str, value: Any) -> None: 55 self.additional_properties[key] = value 56 57 def __delitem__(self, key: str) -> None: 58 del self.additional_properties[key] 59 60 def __contains__(self, key: str) -> bool: 61 return key in self.additional_properties
Options specific to the File component
10@_attrs_define 11class ComponentPropertiesFile: 12 """Properties specific to the File component""" 13 14 file_path: str 15 """Path to track file. Must be either OPUS encapsulated in Ogg or raw h264""" 16 additional_properties: Dict[str, Any] = _attrs_field(init=False, factory=dict) 17 """@private""" 18 19 def to_dict(self) -> Dict[str, Any]: 20 """@private""" 21 file_path = self.file_path 22 23 field_dict: Dict[str, Any] = {} 24 field_dict.update(self.additional_properties) 25 field_dict.update( 26 { 27 "filePath": file_path, 28 } 29 ) 30 31 return field_dict 32 33 @classmethod 34 def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: 35 """@private""" 36 d = src_dict.copy() 37 file_path = d.pop("filePath") 38 39 component_properties_file = cls( 40 file_path=file_path, 41 ) 42 43 component_properties_file.additional_properties = d 44 return component_properties_file 45 46 @property 47 def additional_keys(self) -> List[str]: 48 """@private""" 49 return list(self.additional_properties.keys()) 50 51 def __getitem__(self, key: str) -> Any: 52 return self.additional_properties[key] 53 54 def __setitem__(self, key: str, value: Any) -> None: 55 self.additional_properties[key] = value 56 57 def __delitem__(self, key: str) -> None: 58 del self.additional_properties[key] 59 60 def __contains__(self, key: str) -> bool: 61 return key in self.additional_properties
Properties specific to the File component