agora-python-server-sdk 2.4.0__tar.gz → 2.4.1__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.0 → agora_python_server_sdk-2.4.1}/PKG-INFO +41 -26
- {agora_python_server_sdk-2.4.0 → agora_python_server_sdk-2.4.1}/README.md +40 -25
- {agora_python_server_sdk-2.4.0 → agora_python_server_sdk-2.4.1}/agora/__init__.py +33 -5
- {agora_python_server_sdk-2.4.0 → agora_python_server_sdk-2.4.1}/agora/rtc/_ctypes_handle/_ctypes_data.py +46 -1
- {agora_python_server_sdk-2.4.0 → agora_python_server_sdk-2.4.1}/agora/rtc/agora_service.py +6 -0
- agora_python_server_sdk-2.4.1/agora/rtc/external_audio_processor.py +222 -0
- {agora_python_server_sdk-2.4.0 → agora_python_server_sdk-2.4.1}/agora/rtc/local_user.py +4 -4
- {agora_python_server_sdk-2.4.0 → agora_python_server_sdk-2.4.1}/agora_python_server_sdk.egg-info/PKG-INFO +41 -26
- {agora_python_server_sdk-2.4.0 → agora_python_server_sdk-2.4.1}/agora_python_server_sdk.egg-info/SOURCES.txt +1 -0
- {agora_python_server_sdk-2.4.0 → agora_python_server_sdk-2.4.1}/setup.py +14 -1
- {agora_python_server_sdk-2.4.0 → agora_python_server_sdk-2.4.1}/MANIFEST.in +0 -0
- {agora_python_server_sdk-2.4.0 → agora_python_server_sdk-2.4.1}/agora/rtc/__init__.py +0 -0
- {agora_python_server_sdk-2.4.0 → agora_python_server_sdk-2.4.1}/agora/rtc/_ctypes_handle/_audio_frame_observer.py +0 -0
- {agora_python_server_sdk-2.4.0 → agora_python_server_sdk-2.4.1}/agora/rtc/_ctypes_handle/_local_user_observer.py +0 -0
- {agora_python_server_sdk-2.4.0 → agora_python_server_sdk-2.4.1}/agora/rtc/_ctypes_handle/_rtc_connection_observer.py +0 -0
- {agora_python_server_sdk-2.4.0 → agora_python_server_sdk-2.4.1}/agora/rtc/_ctypes_handle/_video_encoded_frame_observer.py +0 -0
- {agora_python_server_sdk-2.4.0 → agora_python_server_sdk-2.4.1}/agora/rtc/_ctypes_handle/_video_frame_observer.py +0 -0
- {agora_python_server_sdk-2.4.0 → agora_python_server_sdk-2.4.1}/agora/rtc/_utils/globals.py +0 -0
- {agora_python_server_sdk-2.4.0 → agora_python_server_sdk-2.4.1}/agora/rtc/agora_base.py +0 -0
- {agora_python_server_sdk-2.4.0 → agora_python_server_sdk-2.4.1}/agora/rtc/agora_parameter.py +0 -0
- {agora_python_server_sdk-2.4.0 → agora_python_server_sdk-2.4.1}/agora/rtc/audio_encoded_frame_sender.py +0 -0
- {agora_python_server_sdk-2.4.0 → agora_python_server_sdk-2.4.1}/agora/rtc/audio_frame_observer.py +0 -0
- {agora_python_server_sdk-2.4.0 → agora_python_server_sdk-2.4.1}/agora/rtc/audio_pcm_data_sender.py +0 -0
- {agora_python_server_sdk-2.4.0 → agora_python_server_sdk-2.4.1}/agora/rtc/audio_sessionctrl.py +0 -0
- {agora_python_server_sdk-2.4.0 → agora_python_server_sdk-2.4.1}/agora/rtc/audio_vad_manager.py +0 -0
- {agora_python_server_sdk-2.4.0 → agora_python_server_sdk-2.4.1}/agora/rtc/local_audio_track.py +0 -0
- {agora_python_server_sdk-2.4.0 → agora_python_server_sdk-2.4.1}/agora/rtc/local_user_observer.py +0 -0
- {agora_python_server_sdk-2.4.0 → agora_python_server_sdk-2.4.1}/agora/rtc/local_video_track.py +0 -0
- {agora_python_server_sdk-2.4.0 → agora_python_server_sdk-2.4.1}/agora/rtc/media_node_factory.py +0 -0
- {agora_python_server_sdk-2.4.0 → agora_python_server_sdk-2.4.1}/agora/rtc/remote_audio_track.py +0 -0
- {agora_python_server_sdk-2.4.0 → agora_python_server_sdk-2.4.1}/agora/rtc/remote_video_track.py +0 -0
- {agora_python_server_sdk-2.4.0 → agora_python_server_sdk-2.4.1}/agora/rtc/rtc_connection.py +0 -0
- {agora_python_server_sdk-2.4.0 → agora_python_server_sdk-2.4.1}/agora/rtc/rtc_connection_observer.py +0 -0
- {agora_python_server_sdk-2.4.0 → agora_python_server_sdk-2.4.1}/agora/rtc/utils/audio_consumer.py +0 -0
- {agora_python_server_sdk-2.4.0 → agora_python_server_sdk-2.4.1}/agora/rtc/utils/vad_dump.py +0 -0
- {agora_python_server_sdk-2.4.0 → agora_python_server_sdk-2.4.1}/agora/rtc/video_encoded_frame_observer.py +0 -0
- {agora_python_server_sdk-2.4.0 → agora_python_server_sdk-2.4.1}/agora/rtc/video_encoded_image_sender.py +0 -0
- {agora_python_server_sdk-2.4.0 → agora_python_server_sdk-2.4.1}/agora/rtc/video_frame_observer.py +0 -0
- {agora_python_server_sdk-2.4.0 → agora_python_server_sdk-2.4.1}/agora/rtc/video_frame_sender.py +0 -0
- {agora_python_server_sdk-2.4.0 → agora_python_server_sdk-2.4.1}/agora/rtc/voice_detection.py +0 -0
- {agora_python_server_sdk-2.4.0 → agora_python_server_sdk-2.4.1}/agora/rtm/__init__.py +0 -0
- {agora_python_server_sdk-2.4.0 → agora_python_server_sdk-2.4.1}/agora/rtm/_ctypes_handle/_ctypes_data.py +0 -0
- {agora_python_server_sdk-2.4.0 → agora_python_server_sdk-2.4.1}/agora/rtm/rtm_base.py +0 -0
- {agora_python_server_sdk-2.4.0 → agora_python_server_sdk-2.4.1}/agora/rtm/rtm_client.py +0 -0
- {agora_python_server_sdk-2.4.0 → agora_python_server_sdk-2.4.1}/agora/rtm/rtm_event_handler.py +0 -0
- {agora_python_server_sdk-2.4.0 → agora_python_server_sdk-2.4.1}/agora_python_server_sdk.egg-info/dependency_links.txt +0 -0
- {agora_python_server_sdk-2.4.0 → agora_python_server_sdk-2.4.1}/agora_python_server_sdk.egg-info/top_level.txt +0 -0
- {agora_python_server_sdk-2.4.0 → agora_python_server_sdk-2.4.1}/pyproject.toml +0 -0
- {agora_python_server_sdk-2.4.0 → agora_python_server_sdk-2.4.1}/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.1
|
|
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
|
|
@@ -38,7 +38,7 @@ Description-Content-Type: text/markdown
|
|
|
38
38
|
# Required Operating Systems and Python Versions
|
|
39
39
|
- Supported Linux versions:
|
|
40
40
|
- Ubuntu 18.04 LTS and above
|
|
41
|
-
- CentOS
|
|
41
|
+
- CentOS 8.0 and above
|
|
42
42
|
|
|
43
43
|
- Supported Mac versions:
|
|
44
44
|
- MacOS 13 and above(only for coding and testing)
|
|
@@ -57,40 +57,55 @@ pip install agora_python_server_sdk
|
|
|
57
57
|
- Download and unzip [test_data.zip](https://download.agora.io/demo/test/test_data_202408221437.zip) to the Agora-Python-Server-SDK directory.
|
|
58
58
|
|
|
59
59
|
## Executing Test Script
|
|
60
|
-
|
|
60
|
+
for linux os, should set env to :/site_packages/agora/agora_sdk/, like:
|
|
61
61
|
export LD_LIBRARY_PATH=/site_packages/agora/agora_sdk/
|
|
62
62
|
```
|
|
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
|
# Change log
|
|
67
|
-
## 2025.
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
-
|
|
75
|
-
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
67
|
+
## 2025.12.17 Release 2.4.1
|
|
68
|
+
|
|
69
|
+
- Updated RTC SDK to version 154.
|
|
70
|
+
- Added support for VAD (Voice Activity Detection) for external audio sources, including:
|
|
71
|
+
- **Background voice removal**
|
|
72
|
+
- **Noise suppression**
|
|
73
|
+
- **Echo cancellation**
|
|
74
|
+
- **Automatic gain control**
|
|
75
|
+
- **Other 3A algorithms**
|
|
76
|
+
All supported via the `external_Audio_Processor`.
|
|
77
|
+
- Modified LocalUser return values for clearer SDK error code distinction.
|
|
78
|
+
- Added `example_external_Audio_Processor.py` to demonstrate external audio data processing.
|
|
79
|
+
|
|
80
|
+
---
|
|
81
|
+
|
|
82
|
+
## 2025.11.18 Release 2.4.0
|
|
83
|
+
|
|
84
|
+
- Updated SDK to APM version: `4.4.32/1025`
|
|
85
|
+
- Added configuration support to enable/disable APM.
|
|
86
|
+
- Updated methods in `setup.py` and `__init__.py`, including version/URL and MD5 processing.
|
|
87
|
+
- Completed main code pipeline (**further testing recommended**).
|
|
88
|
+
- Added RTM support: one SDK now supports both RTC and RTM.
|
|
89
|
+
|
|
90
|
+
**To-Do Items:**
|
|
91
|
+
- [x] Add VAD algorithm update
|
|
92
|
+
- [x] Add vad_dump modifications
|
|
93
|
+
- [x] Add APM algorithm VAD switch support
|
|
94
|
+
- [x] Add VAD configuration parameter setting
|
|
95
|
+
- [x] Download and check for MD5 mismatch on every download
|
|
96
|
+
|
|
97
|
+
**Notes:**
|
|
98
|
+
- **APM features** include server-side echo cancellation, noise suppression, automatic gain control, background voice removal, and more.
|
|
99
|
+
- Typically, AEC/AINS/AGC, etc., are handled on the client; server-side activation is only necessary for specific requirements.
|
|
100
|
+
- If you need to enable APM, please contact Agora technical support.
|
|
101
|
+
|
|
102
|
+
**Usage Examples:**
|
|
103
|
+
- [RTC usage example](https://github.com/AgoraIO-Extensions/Agora-Python-Server-SDK/tree/main/agora_rtc/examples)
|
|
104
|
+
- [RTM usage example](https://github.com/AgoraIO-Extensions/Agora-Python-Server-SDK/tree/main/agora_rtc/rtm_examples)
|
|
86
105
|
# 2025.11.07 release 2.3.3
|
|
87
106
|
-- update: to support rtm
|
|
88
107
|
-- adjust sdk's directory structure
|
|
89
108
|
-- change requests to urllib
|
|
90
|
-
# 2025.10.23 release 2.3.2: support rtc and rtm in one package
|
|
91
|
-
-- update: to support rtm.can support both rtc and rtm in one package.
|
|
92
|
-
-- adjust sdk's directory structure
|
|
93
|
-
-- update rtc sdk
|
|
94
109
|
# 2025.10.09 release 2.3.1
|
|
95
110
|
-- update arm64 rtc sdk:Fixed a JNI referencing issue in the previous arm64 build. This issue only outputs logs to the console and does not affect functionality.
|
|
96
111
|
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
# Required Operating Systems and Python Versions
|
|
24
24
|
- Supported Linux versions:
|
|
25
25
|
- Ubuntu 18.04 LTS and above
|
|
26
|
-
- CentOS
|
|
26
|
+
- CentOS 8.0 and above
|
|
27
27
|
|
|
28
28
|
- Supported Mac versions:
|
|
29
29
|
- MacOS 13 and above(only for coding and testing)
|
|
@@ -42,40 +42,55 @@ pip install agora_python_server_sdk
|
|
|
42
42
|
- Download and unzip [test_data.zip](https://download.agora.io/demo/test/test_data_202408221437.zip) to the Agora-Python-Server-SDK directory.
|
|
43
43
|
|
|
44
44
|
## Executing Test Script
|
|
45
|
-
|
|
45
|
+
for linux os, should set env to :/site_packages/agora/agora_sdk/, like:
|
|
46
46
|
export LD_LIBRARY_PATH=/site_packages/agora/agora_sdk/
|
|
47
47
|
```
|
|
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
|
# Change log
|
|
52
|
-
## 2025.
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
-
|
|
60
|
-
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
52
|
+
## 2025.12.17 Release 2.4.1
|
|
53
|
+
|
|
54
|
+
- Updated RTC SDK to version 154.
|
|
55
|
+
- Added support for VAD (Voice Activity Detection) for external audio sources, including:
|
|
56
|
+
- **Background voice removal**
|
|
57
|
+
- **Noise suppression**
|
|
58
|
+
- **Echo cancellation**
|
|
59
|
+
- **Automatic gain control**
|
|
60
|
+
- **Other 3A algorithms**
|
|
61
|
+
All supported via the `external_Audio_Processor`.
|
|
62
|
+
- Modified LocalUser return values for clearer SDK error code distinction.
|
|
63
|
+
- Added `example_external_Audio_Processor.py` to demonstrate external audio data processing.
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## 2025.11.18 Release 2.4.0
|
|
68
|
+
|
|
69
|
+
- Updated SDK to APM version: `4.4.32/1025`
|
|
70
|
+
- Added configuration support to enable/disable APM.
|
|
71
|
+
- Updated methods in `setup.py` and `__init__.py`, including version/URL and MD5 processing.
|
|
72
|
+
- Completed main code pipeline (**further testing recommended**).
|
|
73
|
+
- Added RTM support: one SDK now supports both RTC and RTM.
|
|
74
|
+
|
|
75
|
+
**To-Do Items:**
|
|
76
|
+
- [x] Add VAD algorithm update
|
|
77
|
+
- [x] Add vad_dump modifications
|
|
78
|
+
- [x] Add APM algorithm VAD switch support
|
|
79
|
+
- [x] Add VAD configuration parameter setting
|
|
80
|
+
- [x] Download and check for MD5 mismatch on every download
|
|
81
|
+
|
|
82
|
+
**Notes:**
|
|
83
|
+
- **APM features** include server-side echo cancellation, noise suppression, automatic gain control, background voice removal, and more.
|
|
84
|
+
- Typically, AEC/AINS/AGC, etc., are handled on the client; server-side activation is only necessary for specific requirements.
|
|
85
|
+
- If you need to enable APM, please contact Agora technical support.
|
|
86
|
+
|
|
87
|
+
**Usage Examples:**
|
|
88
|
+
- [RTC usage example](https://github.com/AgoraIO-Extensions/Agora-Python-Server-SDK/tree/main/agora_rtc/examples)
|
|
89
|
+
- [RTM usage example](https://github.com/AgoraIO-Extensions/Agora-Python-Server-SDK/tree/main/agora_rtc/rtm_examples)
|
|
71
90
|
# 2025.11.07 release 2.3.3
|
|
72
91
|
-- update: to support rtm
|
|
73
92
|
-- adjust sdk's directory structure
|
|
74
93
|
-- change requests to urllib
|
|
75
|
-
# 2025.10.23 release 2.3.2: support rtc and rtm in one package
|
|
76
|
-
-- update: to support rtm.can support both rtc and rtm in one package.
|
|
77
|
-
-- adjust sdk's directory structure
|
|
78
|
-
-- update rtc sdk
|
|
79
94
|
# 2025.10.09 release 2.3.1
|
|
80
95
|
-- update arm64 rtc sdk:Fixed a JNI referencing issue in the previous arm64 build. This issue only outputs logs to the console and does not affect functionality.
|
|
81
96
|
|
|
@@ -95,7 +95,16 @@ def report_progress(blocknum, blocksize, totalsize):
|
|
|
95
95
|
downloaded = blocknum * blocksize
|
|
96
96
|
print(f"\rDownloading: ----{downloaded} bytes-----", end='', flush=True)
|
|
97
97
|
|
|
98
|
-
|
|
98
|
+
def _get_url_from_version_file(path: str):
|
|
99
|
+
if not os.path.exists(path):
|
|
100
|
+
return ""
|
|
101
|
+
try:
|
|
102
|
+
with open(path, 'r') as f:
|
|
103
|
+
lines = f.readline()
|
|
104
|
+
return lines
|
|
105
|
+
except Exception as e:
|
|
106
|
+
logger.error(f"Failed to read version file: {e}")
|
|
107
|
+
return ""
|
|
99
108
|
def _check_download_and_extract_sdk():
|
|
100
109
|
agora_service_path = os.path.dirname(os.path.abspath(__file__))
|
|
101
110
|
# change from dir like: /home/xxx/agora_rtc/agora/rtc/agora_sdk to
|
|
@@ -125,12 +134,20 @@ def _check_download_and_extract_sdk():
|
|
|
125
134
|
#20251110 Fusion version: with apm filter
|
|
126
135
|
mac_sdk="https://download.agora.io/sdk/release/agora_sdk_mac_v4.4.30_25869_FULL_20251030_1836_953684-aed.zip"
|
|
127
136
|
linux_sdk = "https://download.agora.io/sdk/release/agora_rtc_sdk_x86_64-linux-gnu-v4.4.32.150_26715_SERVER_20251030_1807-aed.zip"
|
|
137
|
+
|
|
138
|
+
linux_sdk = "https://download.agora.io/sdk/release/agora_rtc_sdk_x86_64-linux-gnu-Agora_Native_SDK_for_Linux_x64_zhourui_26895_SERVER_20251121_1628_987405_20251021_1427-3a.zip"
|
|
139
|
+
mac_sdk="https://download.agora.io/sdk/release/agora_sdk_mac_Agora_Native_SDK_for_Mac_zhourui_26101_FULL_20251121_2135_987705_20251021_1427-3a.zip"
|
|
140
|
+
|
|
141
|
+
linux_sdk="https://download.agora.io/sdk/release/agora_rtc_sdk_x86_64-linux-gnu-v4.4.32.154_26982_SERVER_20251210_1745_994155_20251021_1427-3a.zip"
|
|
142
|
+
mac_sdk="https://download.agora.io/sdk/release/agora_sdk_mac_v4.4.32.154_26308_FULL_20251210_1756_994156_20251021_1427-3a.zip"
|
|
143
|
+
|
|
144
|
+
|
|
128
145
|
|
|
129
146
|
|
|
130
147
|
linux_libfile_path = os.path.join(sdk_library_dir, "libagora_rtc_sdk.so")
|
|
131
148
|
mac_libfile_path = os.path.join(sdk_library_dir, "libAgoraRtcKit.dylib")
|
|
132
|
-
linux_md5 = "
|
|
133
|
-
mac_md5 = "
|
|
149
|
+
linux_md5 = "e89043f0db667c207d9308d3515a67ed"
|
|
150
|
+
mac_md5 = "f63e8af2047a53643a1ceb0a4b24b802"
|
|
134
151
|
|
|
135
152
|
#rtc_md5 = "7031dd10d1681cd88fd89d68c5b54282"
|
|
136
153
|
url = linux_sdk
|
|
@@ -156,6 +173,7 @@ def _check_download_and_extract_sdk():
|
|
|
156
173
|
url = "https://download.agora.io/sdk/release/Agora-RTC-aarch64-linux-gnu-v4.4.32-20251009_145437-921455_20251023_1538.zip"
|
|
157
174
|
rtc_md5 = "5c002f25d2b381e353082da4f835b4f2"
|
|
158
175
|
|
|
176
|
+
'''
|
|
159
177
|
is_file_exist = os.path.exists(rtc_libfile_path)
|
|
160
178
|
if is_file_exist:
|
|
161
179
|
md5_value = get_file_md5(rtc_libfile_path)
|
|
@@ -163,8 +181,15 @@ def _check_download_and_extract_sdk():
|
|
|
163
181
|
md5_value = ""
|
|
164
182
|
if md5_value == rtc_md5:
|
|
165
183
|
return
|
|
184
|
+
'''
|
|
185
|
+
is_file_exist = os.path.exists(rtc_libfile_path)
|
|
186
|
+
version_url = _get_url_from_version_file(os.path.join(sdk_root_dir, "version.txt"))
|
|
187
|
+
if version_url == url and is_file_exist:
|
|
188
|
+
return
|
|
189
|
+
|
|
190
|
+
#change from md5 check to url check
|
|
166
191
|
|
|
167
|
-
logger.error(f"missing agora sdk, now download it, please wait for a while...: {rtc_libfile_path} {
|
|
192
|
+
logger.error(f"missing agora sdk, now download it, please wait for a while...: {rtc_libfile_path} {version_url} {url} {is_file_exist}")
|
|
168
193
|
if os.path.exists(sdk_library_dir):
|
|
169
194
|
os.system(f"rm -rf {sdk_library_dir}")
|
|
170
195
|
os.makedirs(sdk_library_dir, exist_ok=True)
|
|
@@ -184,6 +209,9 @@ def _check_download_and_extract_sdk():
|
|
|
184
209
|
|
|
185
210
|
if os.path.exists(zip_path):
|
|
186
211
|
os.remove(zip_path)
|
|
212
|
+
#write version url to version.txt
|
|
213
|
+
with open(os.path.join(sdk_root_dir, "version.txt"), "w") as f:
|
|
214
|
+
f.write(url)
|
|
187
215
|
logger.error("download done, continue...")
|
|
188
216
|
|
|
189
217
|
|
|
@@ -207,5 +235,5 @@ if not os.path.exists(rtc_libfile_path):
|
|
|
207
235
|
logger.error(f"library {rtc_libfile_path} not found")
|
|
208
236
|
sys.exit(1)
|
|
209
237
|
|
|
210
|
-
#
|
|
238
|
+
# Explicitly export these variables to ensure that submodules can import them
|
|
211
239
|
__all__ = ['sdk_library_dir', 'sdk_rtc_dir', 'sdk_rtm_dir', 'sdk_root_dir']
|
|
@@ -1368,4 +1368,49 @@ class CapabilitiesItemMapInner(ctypes.Structure):
|
|
|
1368
1368
|
return CapabilitiesItemMap(
|
|
1369
1369
|
item=self.item,
|
|
1370
1370
|
size=self.size
|
|
1371
|
-
)
|
|
1371
|
+
)
|
|
1372
|
+
|
|
1373
|
+
class AudioSinkWantesInner(ctypes.Structure):
|
|
1374
|
+
_fields_ = [
|
|
1375
|
+
("samples_per_sec", ctypes.c_int),
|
|
1376
|
+
("channels", ctypes.c_uint32),
|
|
1377
|
+
]
|
|
1378
|
+
pass
|
|
1379
|
+
class AudioLabelInner(ctypes.Structure):
|
|
1380
|
+
_fields_ = [
|
|
1381
|
+
("far_filed_flag", ctypes.c_int),
|
|
1382
|
+
("rms", ctypes.c_int),
|
|
1383
|
+
("voice_prob", ctypes.c_int),
|
|
1384
|
+
("music_prob", ctypes.c_int),
|
|
1385
|
+
("pitch", ctypes.c_int),
|
|
1386
|
+
]
|
|
1387
|
+
class AudioPcmFrameInner(ctypes.Structure):
|
|
1388
|
+
_fields_ = [
|
|
1389
|
+
("capture_timestamp", ctypes.c_uint32),
|
|
1390
|
+
("samples_per_channel", ctypes.c_uint32),
|
|
1391
|
+
("sample_rate_hz", ctypes.c_int),
|
|
1392
|
+
("num_channels", ctypes.c_uint32),
|
|
1393
|
+
("bytes_per_sample", ctypes.c_uint32),
|
|
1394
|
+
("data", ctypes.c_int16*3840),
|
|
1395
|
+
("audio_label", AudioLabelInner),
|
|
1396
|
+
]
|
|
1397
|
+
def get(self):
|
|
1398
|
+
return AudioFrame(
|
|
1399
|
+
type=0,
|
|
1400
|
+
samples_per_channel=self.samples_per_channel,
|
|
1401
|
+
bytes_per_sample=self.bytes_per_sample,
|
|
1402
|
+
channels=self.num_channels,
|
|
1403
|
+
samples_per_sec=self.sample_rate_hz,
|
|
1404
|
+
buffer=bytearray(ctypes.string_at(self.data, self.samples_per_channel * self.bytes_per_sample * self.num_channels)),
|
|
1405
|
+
render_time_ms=self.capture_timestamp,
|
|
1406
|
+
avsync_type=0,
|
|
1407
|
+
presentation_ms=0,
|
|
1408
|
+
audio_track_number=0,
|
|
1409
|
+
rtp_timestamp=0,
|
|
1410
|
+
far_field_flag=self.audio_label.far_filed_flag,
|
|
1411
|
+
rms=self.audio_label.rms,
|
|
1412
|
+
voice_prob=self.audio_label.voice_prob,
|
|
1413
|
+
music_prob=self.audio_label.music_prob,
|
|
1414
|
+
pitch=self.audio_label.pitch
|
|
1415
|
+
)
|
|
1416
|
+
pass
|
|
@@ -118,6 +118,12 @@ class AgoraService:
|
|
|
118
118
|
result = agora_service_enable_extension(self.service_handle, cprovider, cgenerator, ctrak, 1)
|
|
119
119
|
if result != 0:
|
|
120
120
|
logger.error(f"Failed to enable audio processing remote playback filter. Error code: {result}")
|
|
121
|
+
if config.enable_apm:
|
|
122
|
+
generator = "audio_processing_pcm_source"
|
|
123
|
+
cgenerator = generator.encode('utf-8')
|
|
124
|
+
result = agora_service_enable_extension(self.service_handle, cprovider, cgenerator, ctrak, 1)
|
|
125
|
+
if result != 0:
|
|
126
|
+
logger.error(f"Failed to enable audio processing pcm source filter. Error code: {result}")
|
|
121
127
|
|
|
122
128
|
#versio 2.2.0 for callback when muted
|
|
123
129
|
if config.should_callbck_when_muted > 0:
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
import time
|
|
2
|
+
import ctypes
|
|
3
|
+
|
|
4
|
+
from .agora_base import *
|
|
5
|
+
from .agora_service import AgoraService, _set_filter_property_by_track, _enable_audio_filter_by_track
|
|
6
|
+
from .local_user import LocalUser
|
|
7
|
+
from .rtc_connection_observer import IRTCConnectionObserver
|
|
8
|
+
from ._ctypes_handle._audio_frame_observer import AudioFrameObserverInner
|
|
9
|
+
from .agora_parameter import AgoraParameter
|
|
10
|
+
from ._utils.globals import AgoraHandleInstanceMap
|
|
11
|
+
from ._ctypes_handle._rtc_connection_observer import RTCConnectionObserverInner, CapabilitiesObserverInner
|
|
12
|
+
from ._ctypes_handle._ctypes_data import *
|
|
13
|
+
from .utils.audio_consumer import PcmConsumeStats
|
|
14
|
+
from .voice_detection import AudioVadConfigV2, AudioVadV2
|
|
15
|
+
import logging
|
|
16
|
+
logger = logging.getLogger(__name__)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class IAudioSinkObserver:
|
|
22
|
+
def on_processed_audio_frame(self,processor: 'ExternalAudioProcessor',frame: AudioFrame,vad_result_state:int,vad_result_data:bytearray):
|
|
23
|
+
pass
|
|
24
|
+
|
|
25
|
+
agora_audio_sink_create = agora_lib.agora_audio_sink_create
|
|
26
|
+
agora_audio_sink_create.restype = ctypes.c_void_p
|
|
27
|
+
agora_audio_sink_create.argtypes = [ctypes.c_void_p]
|
|
28
|
+
|
|
29
|
+
agora_audio_track_add_audio_sink = agora_lib.agora_audio_track_add_audio_sink
|
|
30
|
+
agora_audio_track_add_audio_sink.restype = ctypes.c_int
|
|
31
|
+
agora_audio_track_add_audio_sink.argtypes = [ctypes.c_void_p, ctypes.c_void_p, ctypes.POINTER(AudioSinkWantesInner)]
|
|
32
|
+
|
|
33
|
+
agora_audio_sink_destroy = agora_lib.agora_audio_sink_destroy
|
|
34
|
+
agora_audio_sink_destroy.restype = None
|
|
35
|
+
agora_audio_sink_destroy.argtypes = [ctypes.c_void_p]
|
|
36
|
+
|
|
37
|
+
#call back dec
|
|
38
|
+
ON_AUDIO_SINK_DATA_CALLBACK = ctypes.CFUNCTYPE(ctypes.c_int, ctypes.c_void_p, ctypes.POINTER(AudioPcmFrameInner))
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
class AudioSinkObserverInner(ctypes.Structure):
|
|
42
|
+
_fields_ = [
|
|
43
|
+
("on_audio_sink_data", ON_AUDIO_SINK_DATA_CALLBACK),
|
|
44
|
+
("user_data", ctypes.c_void_p),
|
|
45
|
+
]
|
|
46
|
+
def __init__(self, processor: 'ExternalAudioProcessor'):
|
|
47
|
+
self.on_audio_sink_data = ON_AUDIO_SINK_DATA_CALLBACK(self._on_audio_sink_data)
|
|
48
|
+
self._processor = processor
|
|
49
|
+
pass
|
|
50
|
+
def _on_audio_sink_data(self, handle: ctypes.c_void_p, audio_pcm_frame_inner_ptr: ctypes.POINTER(AudioPcmFrameInner)):
|
|
51
|
+
|
|
52
|
+
#validity check
|
|
53
|
+
if audio_pcm_frame_inner_ptr is None:
|
|
54
|
+
return -1000
|
|
55
|
+
|
|
56
|
+
#convert to aduioframe, and get user data
|
|
57
|
+
pcm_frame = audio_pcm_frame_inner_ptr.contents
|
|
58
|
+
|
|
59
|
+
#conver to audioframe
|
|
60
|
+
audio_frame = pcm_frame.get()
|
|
61
|
+
|
|
62
|
+
if self._processor:
|
|
63
|
+
self._processor._do_result_frame(audio_frame)
|
|
64
|
+
|
|
65
|
+
return 0
|
|
66
|
+
|
|
67
|
+
class AudioSink:
|
|
68
|
+
def __init__(self, audio_processor: 'ExternalAudioProcessor'):
|
|
69
|
+
self._audio_sink_observer_inner = None
|
|
70
|
+
self._c_sink = None
|
|
71
|
+
self._audio_processor = audio_processor
|
|
72
|
+
pass
|
|
73
|
+
def release(self):
|
|
74
|
+
if self._c_sink:
|
|
75
|
+
agora_audio_sink_destroy(ctypes.c_void_p(self._c_sink))
|
|
76
|
+
self._c_sink = None
|
|
77
|
+
self._audio_sink_observer_inner = None
|
|
78
|
+
self._audio_processor = None
|
|
79
|
+
pass
|
|
80
|
+
|
|
81
|
+
class ExternalAudioProcessor:
|
|
82
|
+
|
|
83
|
+
def __init__(self, engine: AgoraService):
|
|
84
|
+
self._pcm_sender = None
|
|
85
|
+
self._local_audio_track = None
|
|
86
|
+
self._engine = engine
|
|
87
|
+
self._is_initialized = False
|
|
88
|
+
#do create sender and track
|
|
89
|
+
self._pcm_sender = self._engine.media_node_factory.create_audio_pcm_data_sender()
|
|
90
|
+
self._local_audio_track = self._engine._create_custom_audio_track_pcm(self._pcm_sender, AudioScenarioType.AUDIO_SCENARIO_DEFAULT)
|
|
91
|
+
self._audio_sink = self._create_audio_sink()
|
|
92
|
+
self._vad_instance = None
|
|
93
|
+
self._observer = None
|
|
94
|
+
pass
|
|
95
|
+
def initialize(self, apm_config: APMConfig, out_sample_rate: int, out_channels: int, vad_config: AudioVadConfigV2, observer: IAudioSinkObserver)->int:
|
|
96
|
+
if self._is_initialized:
|
|
97
|
+
return 0
|
|
98
|
+
if apm_config is None and vad_config is None:
|
|
99
|
+
logger.error("[ExternalAudioProcessor] apm_config and vad_config are both None")
|
|
100
|
+
return -1000
|
|
101
|
+
if out_sample_rate <= 0 or out_channels <= 0:
|
|
102
|
+
logger.error("[ExternalAudioProcessor] out_sample_rate or out_channels is invalid")
|
|
103
|
+
return -1001
|
|
104
|
+
if observer is None:
|
|
105
|
+
logger.error("[ExternalAudioProcessor] observer is None")
|
|
106
|
+
return -1002
|
|
107
|
+
|
|
108
|
+
#set filer properties
|
|
109
|
+
ret = self._set_filter_properties(apm_config)
|
|
110
|
+
if ret < 0:
|
|
111
|
+
logger.info(f"[ExternalAudioProcessor] Failed to set filter properties, error: {ret}")
|
|
112
|
+
return ret
|
|
113
|
+
|
|
114
|
+
#add sink
|
|
115
|
+
ret = self._add_audio_sink(out_sample_rate, out_channels)
|
|
116
|
+
if ret < 0:
|
|
117
|
+
logger.info(f"[ExternalAudioProcessor] Failed to add audio sink, error: {ret}")
|
|
118
|
+
return ret
|
|
119
|
+
|
|
120
|
+
#set track properties
|
|
121
|
+
self._local_audio_track.set_send_delay_ms(10)
|
|
122
|
+
self._local_audio_track.set_max_buffer_audio_frame_number(100000)
|
|
123
|
+
self._local_audio_track.set_enabled(True)
|
|
124
|
+
|
|
125
|
+
self._observer = observer
|
|
126
|
+
|
|
127
|
+
# create vad instance
|
|
128
|
+
if vad_config is not None:
|
|
129
|
+
self._vad_instance = AudioVadV2(vad_config)
|
|
130
|
+
return ret
|
|
131
|
+
pass
|
|
132
|
+
|
|
133
|
+
def push_audio_pcm_data(self, data, sample_rate, channels, start_pts:int=0)->int:
|
|
134
|
+
ret = -1000
|
|
135
|
+
if self._pcm_sender is None:
|
|
136
|
+
return -1001
|
|
137
|
+
readLen = len(data)
|
|
138
|
+
bytes_per_frame_in_ms = (sample_rate / 1000) * 2 * channels
|
|
139
|
+
remainder = readLen % bytes_per_frame_in_ms
|
|
140
|
+
if remainder != 0:
|
|
141
|
+
return -1002
|
|
142
|
+
pack_num_in_ms = readLen // bytes_per_frame_in_ms
|
|
143
|
+
|
|
144
|
+
frame = PcmAudioFrame()
|
|
145
|
+
frame.data = data
|
|
146
|
+
frame.sample_rate = sample_rate
|
|
147
|
+
frame.number_of_channels = channels
|
|
148
|
+
frame.bytes_per_sample = 2
|
|
149
|
+
frame.timestamp = 0
|
|
150
|
+
frame.samples_per_channel = readLen // (channels * 2)
|
|
151
|
+
frame.present_time_ms = start_pts
|
|
152
|
+
|
|
153
|
+
ret = self._pcm_sender.send_audio_pcm_data(frame)
|
|
154
|
+
return ret
|
|
155
|
+
def _create_audio_sink(self)->AudioSink:
|
|
156
|
+
audio_sink = AudioSink(self)
|
|
157
|
+
audio_sink_observer_inner = AudioSinkObserverInner(self)
|
|
158
|
+
audio_sink._audio_sink_observer_inner = audio_sink_observer_inner
|
|
159
|
+
audio_sink._c_sink = agora_audio_sink_create(ctypes.byref(audio_sink_observer_inner))
|
|
160
|
+
if audio_sink._c_sink is None:
|
|
161
|
+
return None
|
|
162
|
+
|
|
163
|
+
return audio_sink
|
|
164
|
+
def _add_audio_sink(self, out_sample_rate: int, out_channels: int)->int:
|
|
165
|
+
if self._audio_sink is None or self._audio_sink._c_sink is None:
|
|
166
|
+
return -1000
|
|
167
|
+
|
|
168
|
+
# call to c api
|
|
169
|
+
wants = AudioSinkWantesInner(samples_per_sec=out_sample_rate, channels=out_channels)
|
|
170
|
+
ret = agora_audio_track_add_audio_sink(self._local_audio_track.track_handle, self._audio_sink._c_sink, ctypes.byref(wants))
|
|
171
|
+
return ret
|
|
172
|
+
pass
|
|
173
|
+
def _set_filter_properties(self, apm_config: APMConfig)->int:
|
|
174
|
+
if self._audio_sink is None or self._audio_sink._c_sink is None:
|
|
175
|
+
return -2000
|
|
176
|
+
if apm_config is None:
|
|
177
|
+
return 0
|
|
178
|
+
#call to c api
|
|
179
|
+
track_handle = self._local_audio_track.track_handle
|
|
180
|
+
ret = _enable_audio_filter_by_track(track_handle, "audio_processing_pcm_source", True, True)
|
|
181
|
+
if ret != 0:
|
|
182
|
+
logger.info(f"[ExternalAudioProcessor] Failed to enable audio filter by track, error: {ret}")
|
|
183
|
+
return -2003
|
|
184
|
+
|
|
185
|
+
ret = _set_filter_property_by_track(track_handle, "audio_processing_pcm_source", "apm_load_resource", "ains", True)
|
|
186
|
+
if ret != 0:
|
|
187
|
+
logger.info(f"[ExternalAudioProcessor] Failed to set filter property by track, error: {ret}")
|
|
188
|
+
return -2004
|
|
189
|
+
|
|
190
|
+
apm_config_json = apm_config._to_json_string()
|
|
191
|
+
if apm_config_json is None:
|
|
192
|
+
logger.info(f"[ExternalAudioProcessor] Failed to get apm config json")
|
|
193
|
+
return -2005
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
ret = _set_filter_property_by_track(track_handle, "audio_processing_pcm_source", "apm_config", apm_config_json, True)
|
|
197
|
+
if ret != 0:
|
|
198
|
+
logger.info(f"[ExternalAudioProcessor]Failed to set filter property by track, error: {ret}")
|
|
199
|
+
return -2006
|
|
200
|
+
logger.info(f"[ExternalAudioProcessor] apm configure json: {apm_config_json}")
|
|
201
|
+
|
|
202
|
+
if apm_config.enable_dump:
|
|
203
|
+
ret = _set_filter_property_by_track(track_handle, "audio_processing_pcm_source", "apm_dump", "true", True)
|
|
204
|
+
if ret != 0:
|
|
205
|
+
logger.info(f"[ExternalAudioProcessor] Failed to set filter property by track, error: {ret}")
|
|
206
|
+
return -2007
|
|
207
|
+
|
|
208
|
+
return ret
|
|
209
|
+
def _do_result_frame(self, audio_frame: AudioFrame):
|
|
210
|
+
print(f"ExternalAudioProcessor _do_result_frame: audio_frame voice_prob {audio_frame.voice_prob}, rms {audio_frame.rms}, pitch {audio_frame.pitch}, far_field_flag {audio_frame.far_field_flag}")
|
|
211
|
+
ret = 0
|
|
212
|
+
data = None
|
|
213
|
+
if self._vad_instance is not None:
|
|
214
|
+
ret, data = self._vad_instance.process(audio_frame)
|
|
215
|
+
print(f"ExternalAudioProcessor _do_result_frame: vad result ret {ret}, data length {len(data)}")
|
|
216
|
+
#do callback now
|
|
217
|
+
if self._observer is not None:
|
|
218
|
+
self._observer.on_processed_audio_frame(self, audio_frame, ret, data)
|
|
219
|
+
pass
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
|
|
@@ -383,7 +383,7 @@ class LocalUser:
|
|
|
383
383
|
|
|
384
384
|
def subscribe_audio(self, user_id):
|
|
385
385
|
if user_id is None:
|
|
386
|
-
return -
|
|
386
|
+
return -1000
|
|
387
387
|
uid_str = user_id.encode('utf-8')
|
|
388
388
|
#ret = agora_local_user_subscribe_audio(self.user_handle, ctypes.create_string_buffer(uid_str))
|
|
389
389
|
# note:both ctypes.create_string_buffer and ctypes.c_char_p are all can change python's str to c_char_p
|
|
@@ -398,7 +398,7 @@ class LocalUser:
|
|
|
398
398
|
def unsubscribe_audio(self, user_id):
|
|
399
399
|
#validity check
|
|
400
400
|
if user_id is None:
|
|
401
|
-
return -
|
|
401
|
+
return -1000
|
|
402
402
|
uid_str = user_id.encode('utf-8')
|
|
403
403
|
ret = agora_local_user_unsubscribe_audio(self.user_handle, ctypes.c_char_p(uid_str))
|
|
404
404
|
if ret < 0:
|
|
@@ -517,7 +517,7 @@ class LocalUser:
|
|
|
517
517
|
|
|
518
518
|
def subscribe_video(self, user_id, options: VideoSubscriptionOptions):
|
|
519
519
|
if user_id is None:
|
|
520
|
-
return -
|
|
520
|
+
return -1000
|
|
521
521
|
uid_str = user_id.encode('utf-8')
|
|
522
522
|
|
|
523
523
|
|
|
@@ -540,7 +540,7 @@ class LocalUser:
|
|
|
540
540
|
|
|
541
541
|
def unsubscribe_video(self, user_id):
|
|
542
542
|
if user_id is None:
|
|
543
|
-
return -
|
|
543
|
+
return -1000
|
|
544
544
|
uid_str = user_id.encode('utf-8')
|
|
545
545
|
ret = agora_local_user_unsubscribe_video(self.user_handle, ctypes.c_char_p(uid_str))
|
|
546
546
|
if ret < 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.1
|
|
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
|
|
@@ -38,7 +38,7 @@ Description-Content-Type: text/markdown
|
|
|
38
38
|
# Required Operating Systems and Python Versions
|
|
39
39
|
- Supported Linux versions:
|
|
40
40
|
- Ubuntu 18.04 LTS and above
|
|
41
|
-
- CentOS
|
|
41
|
+
- CentOS 8.0 and above
|
|
42
42
|
|
|
43
43
|
- Supported Mac versions:
|
|
44
44
|
- MacOS 13 and above(only for coding and testing)
|
|
@@ -57,40 +57,55 @@ pip install agora_python_server_sdk
|
|
|
57
57
|
- Download and unzip [test_data.zip](https://download.agora.io/demo/test/test_data_202408221437.zip) to the Agora-Python-Server-SDK directory.
|
|
58
58
|
|
|
59
59
|
## Executing Test Script
|
|
60
|
-
|
|
60
|
+
for linux os, should set env to :/site_packages/agora/agora_sdk/, like:
|
|
61
61
|
export LD_LIBRARY_PATH=/site_packages/agora/agora_sdk/
|
|
62
62
|
```
|
|
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
|
# Change log
|
|
67
|
-
## 2025.
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
-
|
|
75
|
-
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
67
|
+
## 2025.12.17 Release 2.4.1
|
|
68
|
+
|
|
69
|
+
- Updated RTC SDK to version 154.
|
|
70
|
+
- Added support for VAD (Voice Activity Detection) for external audio sources, including:
|
|
71
|
+
- **Background voice removal**
|
|
72
|
+
- **Noise suppression**
|
|
73
|
+
- **Echo cancellation**
|
|
74
|
+
- **Automatic gain control**
|
|
75
|
+
- **Other 3A algorithms**
|
|
76
|
+
All supported via the `external_Audio_Processor`.
|
|
77
|
+
- Modified LocalUser return values for clearer SDK error code distinction.
|
|
78
|
+
- Added `example_external_Audio_Processor.py` to demonstrate external audio data processing.
|
|
79
|
+
|
|
80
|
+
---
|
|
81
|
+
|
|
82
|
+
## 2025.11.18 Release 2.4.0
|
|
83
|
+
|
|
84
|
+
- Updated SDK to APM version: `4.4.32/1025`
|
|
85
|
+
- Added configuration support to enable/disable APM.
|
|
86
|
+
- Updated methods in `setup.py` and `__init__.py`, including version/URL and MD5 processing.
|
|
87
|
+
- Completed main code pipeline (**further testing recommended**).
|
|
88
|
+
- Added RTM support: one SDK now supports both RTC and RTM.
|
|
89
|
+
|
|
90
|
+
**To-Do Items:**
|
|
91
|
+
- [x] Add VAD algorithm update
|
|
92
|
+
- [x] Add vad_dump modifications
|
|
93
|
+
- [x] Add APM algorithm VAD switch support
|
|
94
|
+
- [x] Add VAD configuration parameter setting
|
|
95
|
+
- [x] Download and check for MD5 mismatch on every download
|
|
96
|
+
|
|
97
|
+
**Notes:**
|
|
98
|
+
- **APM features** include server-side echo cancellation, noise suppression, automatic gain control, background voice removal, and more.
|
|
99
|
+
- Typically, AEC/AINS/AGC, etc., are handled on the client; server-side activation is only necessary for specific requirements.
|
|
100
|
+
- If you need to enable APM, please contact Agora technical support.
|
|
101
|
+
|
|
102
|
+
**Usage Examples:**
|
|
103
|
+
- [RTC usage example](https://github.com/AgoraIO-Extensions/Agora-Python-Server-SDK/tree/main/agora_rtc/examples)
|
|
104
|
+
- [RTM usage example](https://github.com/AgoraIO-Extensions/Agora-Python-Server-SDK/tree/main/agora_rtc/rtm_examples)
|
|
86
105
|
# 2025.11.07 release 2.3.3
|
|
87
106
|
-- update: to support rtm
|
|
88
107
|
-- adjust sdk's directory structure
|
|
89
108
|
-- change requests to urllib
|
|
90
|
-
# 2025.10.23 release 2.3.2: support rtc and rtm in one package
|
|
91
|
-
-- update: to support rtm.can support both rtc and rtm in one package.
|
|
92
|
-
-- adjust sdk's directory structure
|
|
93
|
-
-- update rtc sdk
|
|
94
109
|
# 2025.10.09 release 2.3.1
|
|
95
110
|
-- update arm64 rtc sdk:Fixed a JNI referencing issue in the previous arm64 build. This issue only outputs logs to the console and does not affect functionality.
|
|
96
111
|
|
|
@@ -12,6 +12,7 @@ agora/rtc/audio_frame_observer.py
|
|
|
12
12
|
agora/rtc/audio_pcm_data_sender.py
|
|
13
13
|
agora/rtc/audio_sessionctrl.py
|
|
14
14
|
agora/rtc/audio_vad_manager.py
|
|
15
|
+
agora/rtc/external_audio_processor.py
|
|
15
16
|
agora/rtc/local_audio_track.py
|
|
16
17
|
agora/rtc/local_user.py
|
|
17
18
|
agora/rtc/local_user_observer.py
|
|
@@ -84,6 +84,16 @@ class CustomInstallCommand(install):
|
|
|
84
84
|
#20251110 Fusion version: with apm filter
|
|
85
85
|
mac_sdk="https://download.agora.io/sdk/release/agora_sdk_mac_v4.4.30_25869_FULL_20251030_1836_953684-aed.zip"
|
|
86
86
|
url = "https://download.agora.io/sdk/release/agora_rtc_sdk_x86_64-linux-gnu-v4.4.32.150_26715_SERVER_20251030_1807-aed.zip"
|
|
87
|
+
#date:20251124 update sdk for fix the issue of auto load so and auto load ains resource
|
|
88
|
+
url = "https://download.agora.io/sdk/release/agora_rtc_sdk_x86_64-linux-gnu-Agora_Native_SDK_for_Linux_x64_zhourui_26895_SERVER_20251121_1628_987405_20251021_1427-3a.zip"
|
|
89
|
+
mac_sdk="https://download.agora.io/sdk/release/agora_sdk_mac_Agora_Native_SDK_for_Mac_zhourui_26101_FULL_20251121_2135_987705_20251021_1427-3a.zip"
|
|
90
|
+
#added local track apm filter
|
|
91
|
+
#date:20251217 for incremental sending mode support
|
|
92
|
+
url="https://download.agora.io/sdk/release/agora_rtc_sdk_x86_64-linux-gnu-v4.4.32.154_26982_SERVER_20251210_1745_994155_20251021_1427-3a.zip"
|
|
93
|
+
mac_sdk="https://download.agora.io/sdk/release/agora_sdk_mac_v4.4.32.154_26308_FULL_20251210_1756_994156_20251021_1427-3a.zip"
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
|
|
87
97
|
if sys.platform == 'darwin':
|
|
88
98
|
url = mac_sdk
|
|
89
99
|
|
|
@@ -109,11 +119,14 @@ class CustomInstallCommand(install):
|
|
|
109
119
|
|
|
110
120
|
if os.path.exists(zip_path):
|
|
111
121
|
os.remove(zip_path)
|
|
122
|
+
#write version url to version.txt ,to replace the md5 check
|
|
123
|
+
with open(os.path.join(agora_service_path, "version.txt"), "w") as f:
|
|
124
|
+
f.write(url)
|
|
112
125
|
|
|
113
126
|
|
|
114
127
|
setup(
|
|
115
128
|
name='agora_python_server_sdk',
|
|
116
|
-
version='2.4.
|
|
129
|
+
version='2.4.1',
|
|
117
130
|
description='A Python SDK for Agora Server',
|
|
118
131
|
long_description=open('README.md').read(),
|
|
119
132
|
long_description_content_type='text/markdown',
|
|
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.0 → agora_python_server_sdk-2.4.1}/agora/rtc/agora_parameter.py
RENAMED
|
File without changes
|
|
File without changes
|
{agora_python_server_sdk-2.4.0 → agora_python_server_sdk-2.4.1}/agora/rtc/audio_frame_observer.py
RENAMED
|
File without changes
|
{agora_python_server_sdk-2.4.0 → agora_python_server_sdk-2.4.1}/agora/rtc/audio_pcm_data_sender.py
RENAMED
|
File without changes
|
{agora_python_server_sdk-2.4.0 → agora_python_server_sdk-2.4.1}/agora/rtc/audio_sessionctrl.py
RENAMED
|
File without changes
|
{agora_python_server_sdk-2.4.0 → agora_python_server_sdk-2.4.1}/agora/rtc/audio_vad_manager.py
RENAMED
|
File without changes
|
{agora_python_server_sdk-2.4.0 → agora_python_server_sdk-2.4.1}/agora/rtc/local_audio_track.py
RENAMED
|
File without changes
|
{agora_python_server_sdk-2.4.0 → agora_python_server_sdk-2.4.1}/agora/rtc/local_user_observer.py
RENAMED
|
File without changes
|
{agora_python_server_sdk-2.4.0 → agora_python_server_sdk-2.4.1}/agora/rtc/local_video_track.py
RENAMED
|
File without changes
|
{agora_python_server_sdk-2.4.0 → agora_python_server_sdk-2.4.1}/agora/rtc/media_node_factory.py
RENAMED
|
File without changes
|
{agora_python_server_sdk-2.4.0 → agora_python_server_sdk-2.4.1}/agora/rtc/remote_audio_track.py
RENAMED
|
File without changes
|
{agora_python_server_sdk-2.4.0 → agora_python_server_sdk-2.4.1}/agora/rtc/remote_video_track.py
RENAMED
|
File without changes
|
|
File without changes
|
{agora_python_server_sdk-2.4.0 → agora_python_server_sdk-2.4.1}/agora/rtc/rtc_connection_observer.py
RENAMED
|
File without changes
|
{agora_python_server_sdk-2.4.0 → agora_python_server_sdk-2.4.1}/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.0 → agora_python_server_sdk-2.4.1}/agora/rtc/video_frame_observer.py
RENAMED
|
File without changes
|
{agora_python_server_sdk-2.4.0 → agora_python_server_sdk-2.4.1}/agora/rtc/video_frame_sender.py
RENAMED
|
File without changes
|
{agora_python_server_sdk-2.4.0 → agora_python_server_sdk-2.4.1}/agora/rtc/voice_detection.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{agora_python_server_sdk-2.4.0 → agora_python_server_sdk-2.4.1}/agora/rtm/rtm_event_handler.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|