agora-python-server-sdk 2.4.6__tar.gz → 2.4.8__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.
- {agora_python_server_sdk-2.4.6 → agora_python_server_sdk-2.4.8}/PKG-INFO +34 -2
- {agora_python_server_sdk-2.4.6 → agora_python_server_sdk-2.4.8}/README.md +33 -1
- {agora_python_server_sdk-2.4.6 → agora_python_server_sdk-2.4.8}/agora/rtc/_ctypes_handle/_ctypes_data.py +6 -3
- {agora_python_server_sdk-2.4.6 → agora_python_server_sdk-2.4.8}/agora/rtc/agora_base.py +2 -1
- {agora_python_server_sdk-2.4.6 → agora_python_server_sdk-2.4.8}/agora/rtc/local_video_track.py +2 -2
- {agora_python_server_sdk-2.4.6 → agora_python_server_sdk-2.4.8}/agora/rtc/rtc_connection.py +22 -2
- {agora_python_server_sdk-2.4.6 → agora_python_server_sdk-2.4.8}/agora/rtm/_ctypes_handle/_ctypes_data.py +2 -1
- {agora_python_server_sdk-2.4.6 → agora_python_server_sdk-2.4.8}/agora/rtm/rtm_client.py +13 -6
- {agora_python_server_sdk-2.4.6 → agora_python_server_sdk-2.4.8}/agora_python_server_sdk.egg-info/PKG-INFO +34 -2
- {agora_python_server_sdk-2.4.6 → agora_python_server_sdk-2.4.8}/agora_python_server_sdk.egg-info/SOURCES.txt +4 -1
- {agora_python_server_sdk-2.4.6 → agora_python_server_sdk-2.4.8}/setup.py +1 -1
- agora_python_server_sdk-2.4.8/tests/test_agora_base.py +51 -0
- agora_python_server_sdk-2.4.8/tests/test_rtc_ctypes_data.py +97 -0
- agora_python_server_sdk-2.4.8/tests/test_rtm_ctypes_data.py +72 -0
- {agora_python_server_sdk-2.4.6 → agora_python_server_sdk-2.4.8}/MANIFEST.in +0 -0
- {agora_python_server_sdk-2.4.6 → agora_python_server_sdk-2.4.8}/agora/__init__.py +0 -0
- {agora_python_server_sdk-2.4.6 → agora_python_server_sdk-2.4.8}/agora/rtc/__init__.py +0 -0
- {agora_python_server_sdk-2.4.6 → agora_python_server_sdk-2.4.8}/agora/rtc/_ctypes_handle/_audio_frame_observer.py +0 -0
- {agora_python_server_sdk-2.4.6 → agora_python_server_sdk-2.4.8}/agora/rtc/_ctypes_handle/_local_user_observer.py +0 -0
- {agora_python_server_sdk-2.4.6 → agora_python_server_sdk-2.4.8}/agora/rtc/_ctypes_handle/_rtc_connection_observer.py +0 -0
- {agora_python_server_sdk-2.4.6 → agora_python_server_sdk-2.4.8}/agora/rtc/_ctypes_handle/_video_encoded_frame_observer.py +0 -0
- {agora_python_server_sdk-2.4.6 → agora_python_server_sdk-2.4.8}/agora/rtc/_ctypes_handle/_video_frame_observer.py +0 -0
- {agora_python_server_sdk-2.4.6 → agora_python_server_sdk-2.4.8}/agora/rtc/_utils/globals.py +0 -0
- {agora_python_server_sdk-2.4.6 → agora_python_server_sdk-2.4.8}/agora/rtc/agora_parameter.py +0 -0
- {agora_python_server_sdk-2.4.6 → agora_python_server_sdk-2.4.8}/agora/rtc/agora_service.py +0 -0
- {agora_python_server_sdk-2.4.6 → agora_python_server_sdk-2.4.8}/agora/rtc/audio_encoded_frame_sender.py +0 -0
- {agora_python_server_sdk-2.4.6 → agora_python_server_sdk-2.4.8}/agora/rtc/audio_frame_observer.py +0 -0
- {agora_python_server_sdk-2.4.6 → agora_python_server_sdk-2.4.8}/agora/rtc/audio_pcm_data_sender.py +0 -0
- {agora_python_server_sdk-2.4.6 → agora_python_server_sdk-2.4.8}/agora/rtc/audio_sessionctrl.py +0 -0
- {agora_python_server_sdk-2.4.6 → agora_python_server_sdk-2.4.8}/agora/rtc/audio_vad_manager.py +0 -0
- {agora_python_server_sdk-2.4.6 → agora_python_server_sdk-2.4.8}/agora/rtc/external_audio_processor.py +0 -0
- {agora_python_server_sdk-2.4.6 → agora_python_server_sdk-2.4.8}/agora/rtc/local_audio_track.py +0 -0
- {agora_python_server_sdk-2.4.6 → agora_python_server_sdk-2.4.8}/agora/rtc/local_user.py +0 -0
- {agora_python_server_sdk-2.4.6 → agora_python_server_sdk-2.4.8}/agora/rtc/local_user_observer.py +0 -0
- {agora_python_server_sdk-2.4.6 → agora_python_server_sdk-2.4.8}/agora/rtc/media_node_factory.py +0 -0
- {agora_python_server_sdk-2.4.6 → agora_python_server_sdk-2.4.8}/agora/rtc/remote_audio_track.py +0 -0
- {agora_python_server_sdk-2.4.6 → agora_python_server_sdk-2.4.8}/agora/rtc/remote_video_track.py +0 -0
- {agora_python_server_sdk-2.4.6 → agora_python_server_sdk-2.4.8}/agora/rtc/rtc_connection_observer.py +0 -0
- {agora_python_server_sdk-2.4.6 → agora_python_server_sdk-2.4.8}/agora/rtc/utils/audio_consumer.py +0 -0
- {agora_python_server_sdk-2.4.6 → agora_python_server_sdk-2.4.8}/agora/rtc/utils/vad_dump.py +0 -0
- {agora_python_server_sdk-2.4.6 → agora_python_server_sdk-2.4.8}/agora/rtc/video_encoded_frame_observer.py +0 -0
- {agora_python_server_sdk-2.4.6 → agora_python_server_sdk-2.4.8}/agora/rtc/video_encoded_image_sender.py +0 -0
- {agora_python_server_sdk-2.4.6 → agora_python_server_sdk-2.4.8}/agora/rtc/video_frame_observer.py +0 -0
- {agora_python_server_sdk-2.4.6 → agora_python_server_sdk-2.4.8}/agora/rtc/video_frame_sender.py +0 -0
- {agora_python_server_sdk-2.4.6 → agora_python_server_sdk-2.4.8}/agora/rtc/voice_detection.py +0 -0
- {agora_python_server_sdk-2.4.6 → agora_python_server_sdk-2.4.8}/agora/rtm/__init__.py +0 -0
- {agora_python_server_sdk-2.4.6 → agora_python_server_sdk-2.4.8}/agora/rtm/rtm_base.py +0 -0
- {agora_python_server_sdk-2.4.6 → agora_python_server_sdk-2.4.8}/agora/rtm/rtm_event_handler.py +0 -0
- {agora_python_server_sdk-2.4.6 → agora_python_server_sdk-2.4.8}/agora_python_server_sdk.egg-info/dependency_links.txt +0 -0
- {agora_python_server_sdk-2.4.6 → agora_python_server_sdk-2.4.8}/agora_python_server_sdk.egg-info/top_level.txt +0 -0
- {agora_python_server_sdk-2.4.6 → agora_python_server_sdk-2.4.8}/pyproject.toml +0 -0
- {agora_python_server_sdk-2.4.6 → agora_python_server_sdk-2.4.8}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: agora_python_server_sdk
|
|
3
|
-
Version: 2.4.
|
|
3
|
+
Version: 2.4.8
|
|
4
4
|
Summary: A Python SDK for Agora Server
|
|
5
5
|
Home-page: https://github.com/AgoraIO-Extensions/Agora-Python-Server-SDK
|
|
6
6
|
Classifier: Intended Audience :: Developers
|
|
@@ -63,7 +63,39 @@ export LD_LIBRARY_PATH=/site_packages/agora/agora_sdk/
|
|
|
63
63
|
python agora_rtc/examples/example_audio_pcm_send.py --appId=xxx --channelId=xxx --userId=xxx --audioFile=./test_data/demo.pcm --sampleRate=16000 --numOfChannels=1
|
|
64
64
|
```
|
|
65
65
|
|
|
66
|
-
#
|
|
66
|
+
# Release Note
|
|
67
|
+
|
|
68
|
+
## 2026.06.24 Release Version 2.4.8
|
|
69
|
+
|
|
70
|
+
- **Bugfixes**:
|
|
71
|
+
- Fixed an implementation error in `encryptionconfigure`.
|
|
72
|
+
- **New Features**:
|
|
73
|
+
- Added `ut test case`
|
|
74
|
+
- Usage:
|
|
75
|
+
cd agora_rtc
|
|
76
|
+
pip install pytest
|
|
77
|
+
PYTHONPATH=. pytest tests/ -v
|
|
78
|
+
or pytest tests/ -v
|
|
79
|
+
|
|
80
|
+
## 2026.06.24 Release Version 2.4.7
|
|
81
|
+
|
|
82
|
+
- **New Features**:
|
|
83
|
+
- Added `RTCConnection.get_sid()` and `RTCConnection.set_simulcast_stream()` interfaces for retrieving SID and configuring Simulcast stream capabilities.
|
|
84
|
+
- In `EncryptionConfig`, added the `datastream_encryption_enabled` option to support data stream encryption.
|
|
85
|
+
|
|
86
|
+
- **Improvements and Enhancements**:
|
|
87
|
+
- Improved the Simulcast Stream configuration process to further simplify the usage of `LocalVideoTrack.enable_simulcast_stream()`.
|
|
88
|
+
- Adjusted audio encoding timestamp behavior: when `capture_time_ms` is not set, the current time will be used by default.
|
|
89
|
+
- Optimized RTC/RTM binary message processing to enhance raw data passthrough capability.
|
|
90
|
+
- Enhanced lifecycle management of RTM ctypes callback objects to improve overall stability.
|
|
91
|
+
|
|
92
|
+
- **Examples and Documentation**:
|
|
93
|
+
- Updated RTM/RTC example code, adding detailed examples for Simulcast and binary message transmission.
|
|
94
|
+
- Updated macOS SDK version records.
|
|
95
|
+
|
|
96
|
+
## 2026.06.01 Release Version 2.4.6
|
|
97
|
+
- **Update**: Updated the RTC SDK to version 174, resolving the issue where two same UIDs could join the same channel.
|
|
98
|
+
|
|
67
99
|
## 2026.05.08 Release Version 2.4.5
|
|
68
100
|
- **Update**: Update arm rtc sdk, which can run basic function on arm64 platform, the vad function is not supported yet.
|
|
69
101
|
|
|
@@ -48,7 +48,39 @@ export LD_LIBRARY_PATH=/site_packages/agora/agora_sdk/
|
|
|
48
48
|
python agora_rtc/examples/example_audio_pcm_send.py --appId=xxx --channelId=xxx --userId=xxx --audioFile=./test_data/demo.pcm --sampleRate=16000 --numOfChannels=1
|
|
49
49
|
```
|
|
50
50
|
|
|
51
|
-
#
|
|
51
|
+
# Release Note
|
|
52
|
+
|
|
53
|
+
## 2026.06.24 Release Version 2.4.8
|
|
54
|
+
|
|
55
|
+
- **Bugfixes**:
|
|
56
|
+
- Fixed an implementation error in `encryptionconfigure`.
|
|
57
|
+
- **New Features**:
|
|
58
|
+
- Added `ut test case`
|
|
59
|
+
- Usage:
|
|
60
|
+
cd agora_rtc
|
|
61
|
+
pip install pytest
|
|
62
|
+
PYTHONPATH=. pytest tests/ -v
|
|
63
|
+
or pytest tests/ -v
|
|
64
|
+
|
|
65
|
+
## 2026.06.24 Release Version 2.4.7
|
|
66
|
+
|
|
67
|
+
- **New Features**:
|
|
68
|
+
- Added `RTCConnection.get_sid()` and `RTCConnection.set_simulcast_stream()` interfaces for retrieving SID and configuring Simulcast stream capabilities.
|
|
69
|
+
- In `EncryptionConfig`, added the `datastream_encryption_enabled` option to support data stream encryption.
|
|
70
|
+
|
|
71
|
+
- **Improvements and Enhancements**:
|
|
72
|
+
- Improved the Simulcast Stream configuration process to further simplify the usage of `LocalVideoTrack.enable_simulcast_stream()`.
|
|
73
|
+
- Adjusted audio encoding timestamp behavior: when `capture_time_ms` is not set, the current time will be used by default.
|
|
74
|
+
- Optimized RTC/RTM binary message processing to enhance raw data passthrough capability.
|
|
75
|
+
- Enhanced lifecycle management of RTM ctypes callback objects to improve overall stability.
|
|
76
|
+
|
|
77
|
+
- **Examples and Documentation**:
|
|
78
|
+
- Updated RTM/RTC example code, adding detailed examples for Simulcast and binary message transmission.
|
|
79
|
+
- Updated macOS SDK version records.
|
|
80
|
+
|
|
81
|
+
## 2026.06.01 Release Version 2.4.6
|
|
82
|
+
- **Update**: Updated the RTC SDK to version 174, resolving the issue where two same UIDs could join the same channel.
|
|
83
|
+
|
|
52
84
|
## 2026.05.08 Release Version 2.4.5
|
|
53
85
|
- **Update**: Update arm rtc sdk, which can run basic function on arm64 platform, the vad function is not supported yet.
|
|
54
86
|
|
|
@@ -1246,14 +1246,16 @@ class EncryptionConfigInner(ctypes.Structure):
|
|
|
1246
1246
|
_fields_ = [
|
|
1247
1247
|
("encryption_mode", ctypes.c_int),
|
|
1248
1248
|
("encryption_key", ctypes.c_char_p),
|
|
1249
|
-
("encryption_kdf_salt", ctypes.c_uint8 * 32)
|
|
1249
|
+
("encryption_kdf_salt", ctypes.c_uint8 * 32),
|
|
1250
|
+
("datastream_encryption_enabled", ctypes.c_bool),
|
|
1250
1251
|
]
|
|
1251
1252
|
|
|
1252
1253
|
def get(self):
|
|
1253
1254
|
return EncryptionConfig(
|
|
1254
1255
|
encryption_mode=self.encryption_mode,
|
|
1255
1256
|
encryption_key=self.encryption_key.decode() if self.encryption_key else "",
|
|
1256
|
-
encryption_kdf_salt=bytearray(bytes(self.encryption_kdf_salt))
|
|
1257
|
+
encryption_kdf_salt=bytearray(bytes(self.encryption_kdf_salt)),
|
|
1258
|
+
datastream_encryption_enabled=self.datastream_encryption_enabled
|
|
1257
1259
|
)
|
|
1258
1260
|
|
|
1259
1261
|
@staticmethod
|
|
@@ -1276,7 +1278,8 @@ class EncryptionConfigInner(ctypes.Structure):
|
|
|
1276
1278
|
return EncryptionConfigInner(
|
|
1277
1279
|
config.encryption_mode,
|
|
1278
1280
|
encryption_key,
|
|
1279
|
-
encryption_kdf_salt
|
|
1281
|
+
encryption_kdf_salt,
|
|
1282
|
+
config.datastream_encryption_enabled
|
|
1280
1283
|
)
|
|
1281
1284
|
|
|
1282
1285
|
|
|
@@ -566,7 +566,7 @@ class EncodedAudioFrameInfo:
|
|
|
566
566
|
samples_per_channel: int = 1024
|
|
567
567
|
send_even_if_empty: int = 1
|
|
568
568
|
number_of_channels: int = 1
|
|
569
|
-
capture_time_ms: int =
|
|
569
|
+
capture_time_ms: int = -1 #-1 means not set, when push_audio_encoded_data, if capture_time_ms is not set, will use the current time
|
|
570
570
|
|
|
571
571
|
|
|
572
572
|
@dataclass(kw_only=True)
|
|
@@ -701,6 +701,7 @@ class EncryptionConfig:
|
|
|
701
701
|
encryption_mode: int
|
|
702
702
|
encryption_key: str
|
|
703
703
|
encryption_kdf_salt: bytearray = None
|
|
704
|
+
datastream_encryption_enabled: bool = False
|
|
704
705
|
@dataclass(kw_only=True)
|
|
705
706
|
class CapabilityItem:
|
|
706
707
|
id: int
|
{agora_python_server_sdk-2.4.6 → agora_python_server_sdk-2.4.8}/agora/rtc/local_video_track.py
RENAMED
|
@@ -53,8 +53,8 @@ class LocalVideoTrack:
|
|
|
53
53
|
ret = agora_local_video_track_set_video_encoder_config(self.track_handle, ctypes.byref(VideoEncoderConfigurationInner.create(config)))
|
|
54
54
|
return ret
|
|
55
55
|
|
|
56
|
-
def enable_simulcast_stream(self, enabled, config):
|
|
57
|
-
ret = agora_local_video_track_enable_simulcast_stream(self.track_handle, enabled, ctypes.byref(config))
|
|
56
|
+
def enable_simulcast_stream(self, enabled, config: SimulcastStreamConfig):
|
|
57
|
+
ret = agora_local_video_track_enable_simulcast_stream(self.track_handle, enabled, ctypes.byref(SimulcastStreamConfigInner.create(config)))
|
|
58
58
|
return ret
|
|
59
59
|
|
|
60
60
|
# def update_simulcast_stream(self, enabled, config):
|
|
@@ -87,6 +87,11 @@ agora_local_audio_track_set_total_extra_send_ms = agora_lib.agora_local_audio_tr
|
|
|
87
87
|
agora_local_audio_track_set_total_extra_send_ms.restype = AGORA_API_C_INT
|
|
88
88
|
agora_local_audio_track_set_total_extra_send_ms.argtypes = [AGORA_HANDLE, ctypes.c_uint64]
|
|
89
89
|
|
|
90
|
+
#get sid
|
|
91
|
+
agora_rtc_conn_get_sid = agora_lib.agora_rtc_conn_get_sid
|
|
92
|
+
agora_rtc_conn_get_sid.restype = ctypes.c_char_p
|
|
93
|
+
agora_rtc_conn_get_sid.argtypes = [AGORA_HANDLE]
|
|
94
|
+
|
|
90
95
|
#global variable
|
|
91
96
|
_is_deliver_mute_data_has_set: bool = False
|
|
92
97
|
|
|
@@ -208,11 +213,13 @@ class RTCConnection:
|
|
|
208
213
|
# send data stream message to connection
|
|
209
214
|
def send_stream_message(self, data) -> int:
|
|
210
215
|
length = len(data)
|
|
211
|
-
c_data = ctypes.c_char_p(data)
|
|
216
|
+
#c_data = ctypes.c_char_p(data)
|
|
217
|
+
arr = (ctypes.c_char * length).from_buffer(data) # zero copy
|
|
218
|
+
ptr = ctypes.cast(arr, ctypes.POINTER(ctypes.c_char_p))
|
|
212
219
|
ret = agora_rtc_conn_send_stream_message(
|
|
213
220
|
self.conn_handle,
|
|
214
221
|
self._data_stream_id,
|
|
215
|
-
|
|
222
|
+
ptr,
|
|
216
223
|
length
|
|
217
224
|
)
|
|
218
225
|
return ret
|
|
@@ -631,4 +638,17 @@ class RTCConnection:
|
|
|
631
638
|
ret = self.local_user._send_intra_request(remote_uid)
|
|
632
639
|
return ret
|
|
633
640
|
pass
|
|
641
|
+
def set_simulcast_stream(self, enabled: bool, config: SimulcastStreamConfig)->int:
|
|
642
|
+
ret = -1000
|
|
643
|
+
if self._video_track:
|
|
644
|
+
ret = self._video_track.enable_simulcast_stream(enabled, config)
|
|
645
|
+
return ret
|
|
646
|
+
pass
|
|
647
|
+
def get_sid(self)->str:
|
|
648
|
+
ret = -1000
|
|
649
|
+
if self.conn_handle is None:
|
|
650
|
+
return ""
|
|
651
|
+
sid = agora_rtc_conn_get_sid(self.conn_handle)
|
|
652
|
+
return sid.decode() if sid else ""
|
|
653
|
+
pass
|
|
634
654
|
|
|
@@ -182,12 +182,13 @@ class MessageEventInner(ctypes.Structure):
|
|
|
182
182
|
("customType", ctypes.c_char_p)
|
|
183
183
|
]
|
|
184
184
|
def get(self) -> MessageEvent:
|
|
185
|
+
message = ctypes.string_at(self.message, self.messageLength) if self.message else b""
|
|
185
186
|
return MessageEvent(
|
|
186
187
|
channel_type=self.channelType,
|
|
187
188
|
message_type=self.messageType,
|
|
188
189
|
channel_name=self.channelName.decode('utf-8') if self.channelName else "",
|
|
189
190
|
channel_topic=self.channelTopic.decode('utf-8') if self.channelTopic else "",
|
|
190
|
-
message=
|
|
191
|
+
message=message,
|
|
191
192
|
message_length=self.messageLength,
|
|
192
193
|
publisher=self.publisher.decode('utf-8') if self.publisher else "",
|
|
193
194
|
custom_type=self.customType.decode('utf-8') if self.customType else "",
|
|
@@ -100,12 +100,13 @@ class RTMClient:
|
|
|
100
100
|
#register event handler from python to ctypes
|
|
101
101
|
|
|
102
102
|
config_inner = RtmConfigInner.create(config)
|
|
103
|
-
|
|
104
|
-
config_inner.eventHandler = ctypes.cast(ctypes.byref(
|
|
103
|
+
self._event_handler = RtmEventHandlerInner(config.event_handler, self)
|
|
104
|
+
config_inner.eventHandler = ctypes.cast(ctypes.byref(self._event_handler), ctypes.c_void_p)
|
|
105
105
|
self.client_handle = agora_rtm_client_create(ctypes.byref(config_inner), ctypes.byref(ret))
|
|
106
106
|
print(f"create_rtm_client ret: {ret.value}, client_handle: {self.client_handle}")
|
|
107
107
|
print(f"error reason: {self.get_error_reason(ret.value)}")
|
|
108
108
|
self.is_valid = self.client_handle is not None and ret.value == 0
|
|
109
|
+
self._config_inner = config_inner
|
|
109
110
|
def _is_valid(self)->bool:
|
|
110
111
|
return self.is_valid
|
|
111
112
|
|
|
@@ -116,6 +117,8 @@ class RTMClient:
|
|
|
116
117
|
if ret == 0:
|
|
117
118
|
self.client_handle = None
|
|
118
119
|
self.config = None
|
|
120
|
+
self._event_handler = None # release 之后再清
|
|
121
|
+
self._config_inner = None
|
|
119
122
|
def login(self, token: str)->(int, int):
|
|
120
123
|
#convert from str to c_char_p without memory copy
|
|
121
124
|
bytes_data = token.encode('utf-8')
|
|
@@ -132,13 +135,17 @@ class RTMClient:
|
|
|
132
135
|
request_id = ctypes.c_uint64(0)
|
|
133
136
|
ret = agora_rtm_client_renew_token(self.client_handle, token.encode(), ctypes.byref(request_id))
|
|
134
137
|
return ret, int(request_id.value)
|
|
135
|
-
def publish(self, channel_name: str, message
|
|
138
|
+
def publish(self, channel_name: str, message, options: PublishOptions) ->(int, uint64_t):
|
|
136
139
|
inner_options = PublishOptionsInner.create(options)
|
|
137
140
|
request_id = ctypes.c_uint64(0)
|
|
138
|
-
|
|
141
|
+
#change msg to c_char_p without memory copy
|
|
142
|
+
length = len(message)
|
|
143
|
+
arr = (ctypes.c_char * length).from_buffer_copy(message)
|
|
144
|
+
ptr = ctypes.cast(arr, ctypes.c_char_p)
|
|
145
|
+
ret = agora_rtm_client_publish(self.client_handle, channel_name.encode(), ptr, length, ctypes.byref(inner_options), ctypes.byref(request_id))
|
|
139
146
|
return ret, int(request_id.value)
|
|
140
147
|
|
|
141
|
-
def send_channel_message(self, channel_name: str, message
|
|
148
|
+
def send_channel_message(self, channel_name: str, message) ->(int, uint64_t):
|
|
142
149
|
publish_options = PublishOptions(
|
|
143
150
|
channel_type=RtmChannelType.RTM_CHANNEL_TYPE_MESSAGE,
|
|
144
151
|
message_type=RtmMessageType.RTM_MESSAGE_TYPE_BINARY,
|
|
@@ -147,7 +154,7 @@ class RTMClient:
|
|
|
147
154
|
)
|
|
148
155
|
ret, request_id = self.publish(channel_name, message, publish_options)
|
|
149
156
|
return ret, request_id
|
|
150
|
-
def send_user_message(self, user_id: str, message
|
|
157
|
+
def send_user_message(self, user_id: str, message) ->(int, uint64_t):
|
|
151
158
|
publish_options = PublishOptions(
|
|
152
159
|
channel_type=RtmChannelType.RTM_CHANNEL_TYPE_USER,
|
|
153
160
|
message_type=RtmMessageType.RTM_MESSAGE_TYPE_BINARY,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: agora_python_server_sdk
|
|
3
|
-
Version: 2.4.
|
|
3
|
+
Version: 2.4.8
|
|
4
4
|
Summary: A Python SDK for Agora Server
|
|
5
5
|
Home-page: https://github.com/AgoraIO-Extensions/Agora-Python-Server-SDK
|
|
6
6
|
Classifier: Intended Audience :: Developers
|
|
@@ -63,7 +63,39 @@ export LD_LIBRARY_PATH=/site_packages/agora/agora_sdk/
|
|
|
63
63
|
python agora_rtc/examples/example_audio_pcm_send.py --appId=xxx --channelId=xxx --userId=xxx --audioFile=./test_data/demo.pcm --sampleRate=16000 --numOfChannels=1
|
|
64
64
|
```
|
|
65
65
|
|
|
66
|
-
#
|
|
66
|
+
# Release Note
|
|
67
|
+
|
|
68
|
+
## 2026.06.24 Release Version 2.4.8
|
|
69
|
+
|
|
70
|
+
- **Bugfixes**:
|
|
71
|
+
- Fixed an implementation error in `encryptionconfigure`.
|
|
72
|
+
- **New Features**:
|
|
73
|
+
- Added `ut test case`
|
|
74
|
+
- Usage:
|
|
75
|
+
cd agora_rtc
|
|
76
|
+
pip install pytest
|
|
77
|
+
PYTHONPATH=. pytest tests/ -v
|
|
78
|
+
or pytest tests/ -v
|
|
79
|
+
|
|
80
|
+
## 2026.06.24 Release Version 2.4.7
|
|
81
|
+
|
|
82
|
+
- **New Features**:
|
|
83
|
+
- Added `RTCConnection.get_sid()` and `RTCConnection.set_simulcast_stream()` interfaces for retrieving SID and configuring Simulcast stream capabilities.
|
|
84
|
+
- In `EncryptionConfig`, added the `datastream_encryption_enabled` option to support data stream encryption.
|
|
85
|
+
|
|
86
|
+
- **Improvements and Enhancements**:
|
|
87
|
+
- Improved the Simulcast Stream configuration process to further simplify the usage of `LocalVideoTrack.enable_simulcast_stream()`.
|
|
88
|
+
- Adjusted audio encoding timestamp behavior: when `capture_time_ms` is not set, the current time will be used by default.
|
|
89
|
+
- Optimized RTC/RTM binary message processing to enhance raw data passthrough capability.
|
|
90
|
+
- Enhanced lifecycle management of RTM ctypes callback objects to improve overall stability.
|
|
91
|
+
|
|
92
|
+
- **Examples and Documentation**:
|
|
93
|
+
- Updated RTM/RTC example code, adding detailed examples for Simulcast and binary message transmission.
|
|
94
|
+
- Updated macOS SDK version records.
|
|
95
|
+
|
|
96
|
+
## 2026.06.01 Release Version 2.4.6
|
|
97
|
+
- **Update**: Updated the RTC SDK to version 174, resolving the issue where two same UIDs could join the same channel.
|
|
98
|
+
|
|
67
99
|
## 2026.05.08 Release Version 2.4.5
|
|
68
100
|
- **Update**: Update arm rtc sdk, which can run basic function on arm64 platform, the vad function is not supported yet.
|
|
69
101
|
|
|
@@ -44,4 +44,7 @@ agora/rtm/_ctypes_handle/_ctypes_data.py
|
|
|
44
44
|
agora_python_server_sdk.egg-info/PKG-INFO
|
|
45
45
|
agora_python_server_sdk.egg-info/SOURCES.txt
|
|
46
46
|
agora_python_server_sdk.egg-info/dependency_links.txt
|
|
47
|
-
agora_python_server_sdk.egg-info/top_level.txt
|
|
47
|
+
agora_python_server_sdk.egg-info/top_level.txt
|
|
48
|
+
tests/test_agora_base.py
|
|
49
|
+
tests/test_rtc_ctypes_data.py
|
|
50
|
+
tests/test_rtm_ctypes_data.py
|
|
@@ -134,7 +134,7 @@ class CustomInstallCommand(install):
|
|
|
134
134
|
|
|
135
135
|
setup(
|
|
136
136
|
name='agora_python_server_sdk',
|
|
137
|
-
version='2.4.
|
|
137
|
+
version='2.4.8',
|
|
138
138
|
description='A Python SDK for Agora Server',
|
|
139
139
|
long_description=open('README.md').read(),
|
|
140
140
|
long_description_content_type='text/markdown',
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"""
|
|
2
|
+
author: Wei
|
|
3
|
+
date: 2026-07-01
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from agora.rtc.agora_base import (
|
|
7
|
+
AreaCode,
|
|
8
|
+
ChannelProfileType,
|
|
9
|
+
ClientRoleType,
|
|
10
|
+
RTCConnInfo,
|
|
11
|
+
VideoCodecType,
|
|
12
|
+
APMConfig,
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def test_channel_profile_enum():
|
|
17
|
+
assert ChannelProfileType.CHANNEL_PROFILE_COMMUNICATION == 0
|
|
18
|
+
assert ChannelProfileType.CHANNEL_PROFILE_LIVE_BROADCASTING == 1
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def test_client_role_enum():
|
|
22
|
+
assert ClientRoleType.CLIENT_ROLE_BROADCASTER == 1
|
|
23
|
+
assert ClientRoleType.CLIENT_ROLE_AUDIENCE == 2
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def test_video_codec_enum():
|
|
27
|
+
assert VideoCodecType.VIDEO_CODEC_H264 == 2
|
|
28
|
+
assert VideoCodecType.VIDEO_CODEC_AV1 == 12
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def test_area_code_enum():
|
|
32
|
+
assert AreaCode.AREA_CODE_GLOB == 0xFFFFFFFF
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def test_rtc_conn_info_dataclass():
|
|
36
|
+
info = RTCConnInfo(
|
|
37
|
+
id=1,
|
|
38
|
+
channel_id="test_channel",
|
|
39
|
+
state=2,
|
|
40
|
+
local_user_id="user_1",
|
|
41
|
+
internal_uid=10086,
|
|
42
|
+
)
|
|
43
|
+
assert info.channel_id == "test_channel"
|
|
44
|
+
assert info.internal_uid == 10086
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def test_apm_config_to_json_string():
|
|
48
|
+
config = APMConfig()
|
|
49
|
+
json_str = config._to_json_string()
|
|
50
|
+
assert '"enabled":false' in json_str
|
|
51
|
+
assert '"ainsModelPref":10' in json_str
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
"""
|
|
2
|
+
author: Wei
|
|
3
|
+
date: 2026-07-01
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from agora.rtc.agora_base import (
|
|
7
|
+
AudioEncoderConfiguration,
|
|
8
|
+
AudioProfileType,
|
|
9
|
+
AudioSubscriptionOptions,
|
|
10
|
+
EncryptionConfig,
|
|
11
|
+
EncodedVideoFrameInfo,
|
|
12
|
+
RTCConnInfo,
|
|
13
|
+
VideoCodecType,
|
|
14
|
+
VideoDimensions,
|
|
15
|
+
)
|
|
16
|
+
from agora.rtc._ctypes_handle._ctypes_data import (
|
|
17
|
+
AudioEncoderConfigurationInner,
|
|
18
|
+
AudioSubscriptionOptionsInner,
|
|
19
|
+
EncryptionConfigInner,
|
|
20
|
+
EncodedVideoFrameInfoInner,
|
|
21
|
+
RTCConnInfoInner,
|
|
22
|
+
VideoDimensionsInner,
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def test_audio_encoder_configuration_inner_create():
|
|
27
|
+
config = AudioEncoderConfiguration(audioProfile=AudioProfileType.AUDIO_PROFILE_MUSIC_STANDARD)
|
|
28
|
+
inner = AudioEncoderConfigurationInner.create(config)
|
|
29
|
+
assert inner.audioProfile == AudioProfileType.AUDIO_PROFILE_MUSIC_STANDARD
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def test_rtc_conn_info_inner_create_and_get():
|
|
33
|
+
info = RTCConnInfo(
|
|
34
|
+
id=1,
|
|
35
|
+
channel_id="channel_a",
|
|
36
|
+
state=2,
|
|
37
|
+
local_user_id="user_1",
|
|
38
|
+
internal_uid=10086,
|
|
39
|
+
)
|
|
40
|
+
inner = RTCConnInfoInner.create(info)
|
|
41
|
+
assert inner.channel_id == b"channel_a"
|
|
42
|
+
assert inner.local_user_id == b"user_1"
|
|
43
|
+
|
|
44
|
+
restored = inner.get()
|
|
45
|
+
assert restored.channel_id == "channel_a"
|
|
46
|
+
assert restored.local_user_id == "user_1"
|
|
47
|
+
assert restored.internal_uid == 10086
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def test_audio_subscription_options_inner_create_and_get():
|
|
51
|
+
options = AudioSubscriptionOptions(
|
|
52
|
+
pcm_data_only=1,
|
|
53
|
+
bytes_per_sample=2,
|
|
54
|
+
number_of_channels=2,
|
|
55
|
+
sample_rate_hz=48000,
|
|
56
|
+
)
|
|
57
|
+
inner = AudioSubscriptionOptionsInner.create(options)
|
|
58
|
+
assert inner.pcm_data_only == 1
|
|
59
|
+
assert inner.sample_rate_hz == 48000
|
|
60
|
+
|
|
61
|
+
restored = inner.get()
|
|
62
|
+
assert restored.number_of_channels == 2
|
|
63
|
+
assert restored.sample_rate_hz == 48000
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def test_encryption_config_inner_create_and_get():
|
|
67
|
+
config = EncryptionConfig(
|
|
68
|
+
encryption_mode=1,
|
|
69
|
+
encryption_key="secret",
|
|
70
|
+
encryption_kdf_salt=bytearray(b"salt"),
|
|
71
|
+
datastream_encryption_enabled=True,
|
|
72
|
+
)
|
|
73
|
+
inner = EncryptionConfigInner.create(config)
|
|
74
|
+
assert inner.encryption_key == b"secret"
|
|
75
|
+
assert inner.encryption_kdf_salt[0] == ord("s")
|
|
76
|
+
|
|
77
|
+
restored = inner.get()
|
|
78
|
+
assert restored.encryption_key == "secret"
|
|
79
|
+
assert restored.datastream_encryption_enabled is True
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def test_video_dimensions_and_encoded_frame_info_inner():
|
|
83
|
+
dimensions = VideoDimensions(width=1280, height=720)
|
|
84
|
+
dim_inner = VideoDimensionsInner.create(dimensions)
|
|
85
|
+
assert dim_inner.width == 1280
|
|
86
|
+
assert dim_inner.height == 720
|
|
87
|
+
assert dim_inner.get().height == 720
|
|
88
|
+
|
|
89
|
+
info = EncodedVideoFrameInfo(
|
|
90
|
+
codec_type=VideoCodecType.VIDEO_CODEC_H264,
|
|
91
|
+
width=1280,
|
|
92
|
+
height=720,
|
|
93
|
+
frames_per_second=30,
|
|
94
|
+
)
|
|
95
|
+
info_inner = EncodedVideoFrameInfoInner.create(info)
|
|
96
|
+
assert info_inner.codec_type == VideoCodecType.VIDEO_CODEC_H264
|
|
97
|
+
assert info_inner.get().frames_per_second == 30
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"""
|
|
2
|
+
author: Wei
|
|
3
|
+
date: 2026-07-01
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
import ctypes
|
|
7
|
+
|
|
8
|
+
from agora.rtm.rtm_base import (
|
|
9
|
+
PublishOptions,
|
|
10
|
+
RtmEncryptionConfig,
|
|
11
|
+
RtmLogConfig,
|
|
12
|
+
RtmLogLevel,
|
|
13
|
+
SubscribeOptions,
|
|
14
|
+
)
|
|
15
|
+
from agora.rtm._ctypes_handle._ctypes_data import (
|
|
16
|
+
MessageEventInner,
|
|
17
|
+
PublishOptionsInner,
|
|
18
|
+
RtmEncryptionConfigInner,
|
|
19
|
+
RtmLogConfigInner,
|
|
20
|
+
SubscribeOptionsInner,
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def test_subscribe_options_inner_create():
|
|
25
|
+
options = SubscribeOptions(with_message=False, with_presence=True)
|
|
26
|
+
inner = SubscribeOptionsInner.create(options)
|
|
27
|
+
assert inner.withMessage is False
|
|
28
|
+
assert inner.withPresence is True
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def test_rtm_encryption_config_inner_create():
|
|
32
|
+
config = RtmEncryptionConfig(encryption_key="secret", encryption_salt="salt")
|
|
33
|
+
inner = RtmEncryptionConfigInner.create(config)
|
|
34
|
+
assert inner.encryptionKey == b"secret"
|
|
35
|
+
assert inner.encryptionSalt[0] == ord("s")
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def test_rtm_log_config_inner_create():
|
|
39
|
+
config = RtmLogConfig(
|
|
40
|
+
file_path="/tmp/rtm.log",
|
|
41
|
+
file_size_kb=1024,
|
|
42
|
+
log_level=RtmLogLevel.RTM_LOG_LEVEL_INFO,
|
|
43
|
+
)
|
|
44
|
+
inner = RtmLogConfigInner.create(config)
|
|
45
|
+
assert inner.filePath == b"/tmp/rtm.log"
|
|
46
|
+
assert inner.fileSizeInKB == 1024
|
|
47
|
+
assert inner.level == RtmLogLevel.RTM_LOG_LEVEL_INFO
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def test_publish_options_inner_create():
|
|
51
|
+
options = PublishOptions(custom_type="demo", store_in_history=True)
|
|
52
|
+
inner = PublishOptionsInner.create(options)
|
|
53
|
+
assert inner.customType == b"demo"
|
|
54
|
+
assert inner.storeInHistory is True
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def test_message_event_inner_get():
|
|
58
|
+
payload = b"hello"
|
|
59
|
+
inner = MessageEventInner(
|
|
60
|
+
channelType=1,
|
|
61
|
+
messageType=0,
|
|
62
|
+
channelName=b"channel_a",
|
|
63
|
+
channelTopic=b"topic_a",
|
|
64
|
+
message=ctypes.c_char_p(payload),
|
|
65
|
+
messageLength=len(payload),
|
|
66
|
+
publisher=b"user_1",
|
|
67
|
+
customType=b"text",
|
|
68
|
+
)
|
|
69
|
+
event = inner.get()
|
|
70
|
+
assert event.channel_name == "channel_a"
|
|
71
|
+
assert event.message == payload
|
|
72
|
+
assert event.publisher == "user_1"
|
|
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
|
{agora_python_server_sdk-2.4.6 → agora_python_server_sdk-2.4.8}/agora/rtc/agora_parameter.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{agora_python_server_sdk-2.4.6 → agora_python_server_sdk-2.4.8}/agora/rtc/audio_frame_observer.py
RENAMED
|
File without changes
|
{agora_python_server_sdk-2.4.6 → agora_python_server_sdk-2.4.8}/agora/rtc/audio_pcm_data_sender.py
RENAMED
|
File without changes
|
{agora_python_server_sdk-2.4.6 → agora_python_server_sdk-2.4.8}/agora/rtc/audio_sessionctrl.py
RENAMED
|
File without changes
|
{agora_python_server_sdk-2.4.6 → agora_python_server_sdk-2.4.8}/agora/rtc/audio_vad_manager.py
RENAMED
|
File without changes
|
|
File without changes
|
{agora_python_server_sdk-2.4.6 → agora_python_server_sdk-2.4.8}/agora/rtc/local_audio_track.py
RENAMED
|
File without changes
|
|
File without changes
|
{agora_python_server_sdk-2.4.6 → agora_python_server_sdk-2.4.8}/agora/rtc/local_user_observer.py
RENAMED
|
File without changes
|
{agora_python_server_sdk-2.4.6 → agora_python_server_sdk-2.4.8}/agora/rtc/media_node_factory.py
RENAMED
|
File without changes
|
{agora_python_server_sdk-2.4.6 → agora_python_server_sdk-2.4.8}/agora/rtc/remote_audio_track.py
RENAMED
|
File without changes
|
{agora_python_server_sdk-2.4.6 → agora_python_server_sdk-2.4.8}/agora/rtc/remote_video_track.py
RENAMED
|
File without changes
|
{agora_python_server_sdk-2.4.6 → agora_python_server_sdk-2.4.8}/agora/rtc/rtc_connection_observer.py
RENAMED
|
File without changes
|
{agora_python_server_sdk-2.4.6 → agora_python_server_sdk-2.4.8}/agora/rtc/utils/audio_consumer.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{agora_python_server_sdk-2.4.6 → agora_python_server_sdk-2.4.8}/agora/rtc/video_frame_observer.py
RENAMED
|
File without changes
|
{agora_python_server_sdk-2.4.6 → agora_python_server_sdk-2.4.8}/agora/rtc/video_frame_sender.py
RENAMED
|
File without changes
|
{agora_python_server_sdk-2.4.6 → agora_python_server_sdk-2.4.8}/agora/rtc/voice_detection.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{agora_python_server_sdk-2.4.6 → agora_python_server_sdk-2.4.8}/agora/rtm/rtm_event_handler.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|