agora-python-server-sdk 2.2.4__tar.gz → 2.3.0__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.
Potentially problematic release.
This version of agora-python-server-sdk might be problematic. Click here for more details.
- {agora_python_server_sdk-2.2.4/agora_python_server_sdk.egg-info → agora_python_server_sdk-2.3.0}/PKG-INFO +166 -6
- {agora_python_server_sdk-2.2.4 → agora_python_server_sdk-2.3.0}/README.md +165 -5
- {agora_python_server_sdk-2.2.4 → agora_python_server_sdk-2.3.0}/agora/rtc/__init__.py +8 -4
- {agora_python_server_sdk-2.2.4 → agora_python_server_sdk-2.3.0}/agora/rtc/_ctypes_handle/_ctypes_data.py +129 -9
- {agora_python_server_sdk-2.2.4 → agora_python_server_sdk-2.3.0}/agora/rtc/_ctypes_handle/_local_user_observer.py +2 -2
- {agora_python_server_sdk-2.2.4 → agora_python_server_sdk-2.3.0}/agora/rtc/_ctypes_handle/_rtc_connection_observer.py +44 -1
- {agora_python_server_sdk-2.2.4 → agora_python_server_sdk-2.3.0}/agora/rtc/agora_base.py +61 -13
- {agora_python_server_sdk-2.2.4 → agora_python_server_sdk-2.3.0}/agora/rtc/agora_service.py +27 -21
- {agora_python_server_sdk-2.2.4 → agora_python_server_sdk-2.3.0}/agora/rtc/audio_encoded_frame_sender.py +12 -0
- {agora_python_server_sdk-2.2.4 → agora_python_server_sdk-2.3.0}/agora/rtc/audio_pcm_data_sender.py +5 -3
- {agora_python_server_sdk-2.2.4 → agora_python_server_sdk-2.3.0}/agora/rtc/local_user.py +27 -15
- agora_python_server_sdk-2.3.0/agora/rtc/rtc_connection.py +519 -0
- {agora_python_server_sdk-2.2.4 → agora_python_server_sdk-2.3.0}/agora/rtc/rtc_connection_observer.py +20 -0
- {agora_python_server_sdk-2.2.4 → agora_python_server_sdk-2.3.0}/agora/rtc/utils/audio_consumer.py +41 -0
- {agora_python_server_sdk-2.2.4 → agora_python_server_sdk-2.3.0}/agora/rtc/video_encoded_image_sender.py +8 -0
- {agora_python_server_sdk-2.2.4 → agora_python_server_sdk-2.3.0/agora_python_server_sdk.egg-info}/PKG-INFO +166 -6
- {agora_python_server_sdk-2.2.4 → agora_python_server_sdk-2.3.0}/setup.py +19 -2
- agora_python_server_sdk-2.2.4/agora/rtc/rtc_connection.py +0 -164
- {agora_python_server_sdk-2.2.4 → agora_python_server_sdk-2.3.0}/MANIFEST.in +0 -0
- {agora_python_server_sdk-2.2.4 → agora_python_server_sdk-2.3.0}/agora/rtc/_ctypes_handle/_audio_frame_observer.py +0 -0
- {agora_python_server_sdk-2.2.4 → agora_python_server_sdk-2.3.0}/agora/rtc/_ctypes_handle/_video_encoded_frame_observer.py +0 -0
- {agora_python_server_sdk-2.2.4 → agora_python_server_sdk-2.3.0}/agora/rtc/_ctypes_handle/_video_frame_observer.py +0 -0
- {agora_python_server_sdk-2.2.4 → agora_python_server_sdk-2.3.0}/agora/rtc/_utils/globals.py +0 -0
- {agora_python_server_sdk-2.2.4 → agora_python_server_sdk-2.3.0}/agora/rtc/agora_parameter.py +0 -0
- {agora_python_server_sdk-2.2.4 → agora_python_server_sdk-2.3.0}/agora/rtc/audio_frame_observer.py +0 -0
- {agora_python_server_sdk-2.2.4 → agora_python_server_sdk-2.3.0}/agora/rtc/audio_sessionctrl.py +0 -0
- {agora_python_server_sdk-2.2.4 → agora_python_server_sdk-2.3.0}/agora/rtc/audio_vad_manager.py +0 -0
- {agora_python_server_sdk-2.2.4 → agora_python_server_sdk-2.3.0}/agora/rtc/local_audio_track.py +0 -0
- {agora_python_server_sdk-2.2.4 → agora_python_server_sdk-2.3.0}/agora/rtc/local_user_observer.py +0 -0
- {agora_python_server_sdk-2.2.4 → agora_python_server_sdk-2.3.0}/agora/rtc/local_video_track.py +0 -0
- {agora_python_server_sdk-2.2.4 → agora_python_server_sdk-2.3.0}/agora/rtc/media_node_factory.py +0 -0
- {agora_python_server_sdk-2.2.4 → agora_python_server_sdk-2.3.0}/agora/rtc/remote_audio_track.py +0 -0
- {agora_python_server_sdk-2.2.4 → agora_python_server_sdk-2.3.0}/agora/rtc/remote_video_track.py +0 -0
- {agora_python_server_sdk-2.2.4 → agora_python_server_sdk-2.3.0}/agora/rtc/utils/vad_dump.py +0 -0
- {agora_python_server_sdk-2.2.4 → agora_python_server_sdk-2.3.0}/agora/rtc/video_encoded_frame_observer.py +0 -0
- {agora_python_server_sdk-2.2.4 → agora_python_server_sdk-2.3.0}/agora/rtc/video_frame_observer.py +0 -0
- {agora_python_server_sdk-2.2.4 → agora_python_server_sdk-2.3.0}/agora/rtc/video_frame_sender.py +0 -0
- {agora_python_server_sdk-2.2.4 → agora_python_server_sdk-2.3.0}/agora/rtc/voice_detection.py +0 -0
- {agora_python_server_sdk-2.2.4 → agora_python_server_sdk-2.3.0}/agora_python_server_sdk.egg-info/SOURCES.txt +0 -0
- {agora_python_server_sdk-2.2.4 → agora_python_server_sdk-2.3.0}/agora_python_server_sdk.egg-info/dependency_links.txt +0 -0
- {agora_python_server_sdk-2.2.4 → agora_python_server_sdk-2.3.0}/agora_python_server_sdk.egg-info/top_level.txt +0 -0
- {agora_python_server_sdk-2.2.4 → agora_python_server_sdk-2.3.0}/pyproject.toml +0 -0
- {agora_python_server_sdk-2.2.4 → agora_python_server_sdk-2.3.0}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: agora_python_server_sdk
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.3.0
|
|
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
|
|
@@ -19,9 +19,19 @@ Description-Content-Type: text/markdown
|
|
|
19
19
|
- The examples are provided as very simple demonstrations and are not recommended for use in production environments.
|
|
20
20
|
|
|
21
21
|
# Very Important Notice !!!
|
|
22
|
-
- A process can only have one instance.
|
|
22
|
+
- A process can only have one instance,and the instance created in process startup is the global instance,and released in process shutdown.
|
|
23
23
|
- An instance can have multiple connections.
|
|
24
24
|
- In all observers or callbacks, you must not call the SDK's own APIs, nor perform CPU-intensive tasks in the callbacks; data copying is allowed.
|
|
25
|
+
- supported video codec:
|
|
26
|
+
- H264: support both encoding and decoding
|
|
27
|
+
- VP8: support both encoding and decoding
|
|
28
|
+
- VP9: support both encoding and decoding
|
|
29
|
+
- H265: only decoding is supported, encoding willl support in the future
|
|
30
|
+
- AV1: both encoding and decoding are suported but if video image's solution is less than 360p, the codec will be changed to H264
|
|
31
|
+
- if you want to recive the encoded video data:
|
|
32
|
+
- set: video_subscription_options.encodedFrameOnly = 1
|
|
33
|
+
- and then register: set_encoded_video_frame_observer
|
|
34
|
+
|
|
25
35
|
|
|
26
36
|
# Required Operating Systems and Python Versions
|
|
27
37
|
- Supported Linux versions:
|
|
@@ -50,6 +60,157 @@ python agora_rtc/examples/example_audio_pcm_send.py --appId=xxx --channelId=xxx
|
|
|
50
60
|
```
|
|
51
61
|
|
|
52
62
|
# Change log
|
|
63
|
+
#2025.09.01 release 2.3.0
|
|
64
|
+
|
|
65
|
+
Overview
|
|
66
|
+
|
|
67
|
+
Agora Python SDK version 2.3.0 introduces significant enhancements for real-time audio and video communication, with particular optimizations for AI server scenarios. This release includes API improvements, automation of previously manual processes, and increased flexibility in connection configuration.
|
|
68
|
+
|
|
69
|
+
New Features
|
|
70
|
+
|
|
71
|
+
1. AudioScenarioAiServer Support
|
|
72
|
+
|
|
73
|
+
• Added support for the AudioScenarioAiServer scenario type, now set as the default AudioScenario.
|
|
74
|
+
|
|
75
|
+
• Enables configuration of different scenarios and profiles for connections within the same process.
|
|
76
|
+
|
|
77
|
+
• Important: When using AI server scenario, client-side must use AIClient scenario to avoid audio abnormalities. Please consult Agora support for SDK versions supporting AIClient scenario.
|
|
78
|
+
|
|
79
|
+
2. Enhanced Connection Configuration
|
|
80
|
+
|
|
81
|
+
• Introduced PublishConfigure parameter in connection creation for setting:
|
|
82
|
+
|
|
83
|
+
• Scenario and profile configurations
|
|
84
|
+
|
|
85
|
+
• Audio/Video publication settings
|
|
86
|
+
|
|
87
|
+
• Other publication parameters
|
|
88
|
+
|
|
89
|
+
• Added multiple observer registration methods to connections:
|
|
90
|
+
|
|
91
|
+
• RegisterLocalUserObserver
|
|
92
|
+
|
|
93
|
+
• RegisterAudioFrameObserver
|
|
94
|
+
|
|
95
|
+
• RegisterVideoFrameObserver
|
|
96
|
+
|
|
97
|
+
• RegisterVideoEncodedFrameObserver
|
|
98
|
+
|
|
99
|
+
3. Stream Management Improvements
|
|
100
|
+
|
|
101
|
+
• Added publication control methods:
|
|
102
|
+
|
|
103
|
+
• PublishAudio/UnpublishAudio
|
|
104
|
+
|
|
105
|
+
• PublishVideo/UnpublishVideo
|
|
106
|
+
|
|
107
|
+
• Added data pushing methods:
|
|
108
|
+
|
|
109
|
+
• PushAudioPcmData/PushAudioEncodedData
|
|
110
|
+
|
|
111
|
+
• PushVideoFrame/PushVideoEncodedData
|
|
112
|
+
|
|
113
|
+
• Added InterruptAudio method for supporting interruption functionality
|
|
114
|
+
|
|
115
|
+
• Added IsPushToRTCCompleted method for checking push status
|
|
116
|
+
|
|
117
|
+
• Added SendAudioMetaData method for audio metadata transmission
|
|
118
|
+
|
|
119
|
+
4. Automation Enhancements
|
|
120
|
+
|
|
121
|
+
• Eliminated manual CreateDataStream calls - now handled automatically
|
|
122
|
+
|
|
123
|
+
• Automatic observer unregistration on Release() instead of manual unregistering
|
|
124
|
+
|
|
125
|
+
• Internal handling of media node factory creation:
|
|
126
|
+
|
|
127
|
+
• No longer requires manual calls to newMediaNodeFactory
|
|
128
|
+
|
|
129
|
+
• Automatic handling of track creation (NewCustomAudioTrackPcm, NewCustomAudioTrackEncoded, NewCustomVideoTrack)
|
|
130
|
+
|
|
131
|
+
• Automatic management of audio data senders (NewAudioPcmDataSender)
|
|
132
|
+
|
|
133
|
+
Integration Process
|
|
134
|
+
|
|
135
|
+
The updated integration workflow is as follows:
|
|
136
|
+
|
|
137
|
+
1. Initialize Agora Service (once per process startup):
|
|
138
|
+
config = AgoraServiceConfig()
|
|
139
|
+
agora_service = AgoraService()
|
|
140
|
+
agora_service.initialize(config)
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
2. Connection Management (can be looped for multiple connections):
|
|
144
|
+
# Create connection with configuration
|
|
145
|
+
con = agora_service.create_rtc_connection(con_config, publish_config)
|
|
146
|
+
|
|
147
|
+
# Register observers
|
|
148
|
+
con.register_observer(conHandler)
|
|
149
|
+
con.register_audio_frame_observer(audioFrameObserver)
|
|
150
|
+
con.register_local_user_observer(localUserObserver)
|
|
151
|
+
|
|
152
|
+
# Connect and publish
|
|
153
|
+
con.connect(token, channelName, userId)
|
|
154
|
+
con.publish_audio() # or con.publish_video()
|
|
155
|
+
|
|
156
|
+
# Push data
|
|
157
|
+
con.push_audio_pcm_data() # or push_audio_encoded_data()
|
|
158
|
+
# or con.push_video_frame()/push_video_encoded_data()
|
|
159
|
+
|
|
160
|
+
# Disconnect and release
|
|
161
|
+
con.disconnect()
|
|
162
|
+
con.release()
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
3. Release Agora Service (once during process termination):
|
|
166
|
+
agora_service.release()
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
Performance Recommendations
|
|
170
|
+
|
|
171
|
+
1. For AI Scenarios:
|
|
172
|
+
• Use AudioScenarioAIServer for server-side applications
|
|
173
|
+
|
|
174
|
+
• Provides optimized performance with lower latency (20-30ms reduction on iPhone compared to chorus)
|
|
175
|
+
|
|
176
|
+
• Enhanced experience in weak network conditions
|
|
177
|
+
|
|
178
|
+
• Mandatory: Client must use AIClient scenario
|
|
179
|
+
|
|
180
|
+
2. For Non-AI Scenarios:
|
|
181
|
+
• Consult Agora technical support for appropriate scenario configuration
|
|
182
|
+
|
|
183
|
+
• Ensure configuration matches specific business use cases
|
|
184
|
+
|
|
185
|
+
Bug Fixes
|
|
186
|
+
|
|
187
|
+
• Updated RTC SDK with 2 bug fixes
|
|
188
|
+
|
|
189
|
+
Important Notes
|
|
190
|
+
|
|
191
|
+
• Backward Compatibility: Review integration code for manual calls that are now automated
|
|
192
|
+
|
|
193
|
+
• Scenario Matching: Ensure client-server scenario compatibility (AIServer requires AIClient)
|
|
194
|
+
|
|
195
|
+
• Resource Management: Connection release now automatically handles observer unregistration
|
|
196
|
+
|
|
197
|
+
• Consult Support: For specific integration guidance and upgrade assistance, contact Agora SA
|
|
198
|
+
|
|
199
|
+
Summary of Core Changes
|
|
200
|
+
|
|
201
|
+
Before After 2.3.0
|
|
202
|
+
|
|
203
|
+
Manual CreateDataStream ✅ Automatic
|
|
204
|
+
|
|
205
|
+
Manual observer unregistration ✅ Automatic on Release()
|
|
206
|
+
|
|
207
|
+
Fixed per-process scenario ✅ Multi-scenario per process
|
|
208
|
+
|
|
209
|
+
Client/Server scenario mismatch ❗ AIClient mandatory for AI use
|
|
210
|
+
|
|
211
|
+
For detailed implementation guidance and version-specific support, please consult Agora technical support.
|
|
212
|
+
|
|
213
|
+
|
|
53
214
|
## 2025.04.28 Release 2.2.4
|
|
54
215
|
-- Update: update rtc sdk from 4.4.31 to 4.4.32
|
|
55
216
|
## 2025.04.14 Release 2.2.3
|
|
@@ -69,6 +230,7 @@ python agora_rtc/examples/example_audio_pcm_send.py --appId=xxx --channelId=xxx
|
|
|
69
230
|
- Added connection::agora_rtc_conn_enable_encryption.
|
|
70
231
|
-- Additions:
|
|
71
232
|
- Added connectionObserver::on_encryption_error (but not working for now, need to fix in the next monthly version 4.4.32).
|
|
233
|
+
|
|
72
234
|
2025.02.26 Release 2.2.1
|
|
73
235
|
--Update:
|
|
74
236
|
- Reduced buffer size from 180ms to 100ms to minimize latency.
|
|
@@ -89,7 +251,6 @@ python agora_rtc/examples/example_audio_pcm_send.py --appId=xxx --channelId=xxx
|
|
|
89
251
|
- Add the AudioMetaData interface: localuser::send_audio_meta_data. Done.
|
|
90
252
|
- Add the OnAudioMetaDataReceived callback to localuserObserver::on_audio_meta_data_received. Done.
|
|
91
253
|
-- Sample modifications.
|
|
92
|
-
|
|
93
254
|
2024.12.17 Release 2.1.7
|
|
94
255
|
--Changes:
|
|
95
256
|
|
|
@@ -117,7 +278,6 @@ python agora_rtc/examples/example_audio_pcm_send.py --appId=xxx --channelId=xxx
|
|
|
117
278
|
-- Replaced the use of pacer with AudioConsumer for pushing PCM audio.
|
|
118
279
|
- Updates:
|
|
119
280
|
-- Updated the samples related to Pacer and VAD.
|
|
120
|
-
|
|
121
281
|
## 2024.12.03 release Version 2.1.5
|
|
122
282
|
- Modifications:
|
|
123
283
|
- LocalUser/audioTrack:
|
|
@@ -173,7 +333,6 @@ Fixed some bug.
|
|
|
173
333
|
- Handle business operations.
|
|
174
334
|
- When a user logs out, execute con.disconnect() and release the audio/video tracks and observers associated with the connection, but do not call con.release(); then put the connection back into the connection pool.
|
|
175
335
|
- When the process exits, release the connection pool (release each con.release()), service/media_node_factory, and the connection pool (release each con.release()) to ensure resource release and optimal performance.
|
|
176
|
-
|
|
177
336
|
## Use of VAD
|
|
178
337
|
# Source code: voice_detection.py
|
|
179
338
|
# Sample code: example_audio_vad.py
|
|
@@ -204,7 +363,8 @@ Judge the value of state according to the returned state, and do corresponding p
|
|
|
204
363
|
### How to push the audio generated by TTS into the channel?
|
|
205
364
|
# Source code: audio_consumer.py
|
|
206
365
|
# Sample code: example_audio_consumer.py
|
|
207
|
-
|
|
366
|
+
|
|
367
|
+
### How to release resource?
|
|
208
368
|
## 如何释放资源?
|
|
209
369
|
localuser.unpublish_audio(audio_track)
|
|
210
370
|
localuser.unpublish_video(video_track)
|
|
@@ -4,9 +4,19 @@
|
|
|
4
4
|
- The examples are provided as very simple demonstrations and are not recommended for use in production environments.
|
|
5
5
|
|
|
6
6
|
# Very Important Notice !!!
|
|
7
|
-
- A process can only have one instance.
|
|
7
|
+
- A process can only have one instance,and the instance created in process startup is the global instance,and released in process shutdown.
|
|
8
8
|
- An instance can have multiple connections.
|
|
9
9
|
- In all observers or callbacks, you must not call the SDK's own APIs, nor perform CPU-intensive tasks in the callbacks; data copying is allowed.
|
|
10
|
+
- supported video codec:
|
|
11
|
+
- H264: support both encoding and decoding
|
|
12
|
+
- VP8: support both encoding and decoding
|
|
13
|
+
- VP9: support both encoding and decoding
|
|
14
|
+
- H265: only decoding is supported, encoding willl support in the future
|
|
15
|
+
- AV1: both encoding and decoding are suported but if video image's solution is less than 360p, the codec will be changed to H264
|
|
16
|
+
- if you want to recive the encoded video data:
|
|
17
|
+
- set: video_subscription_options.encodedFrameOnly = 1
|
|
18
|
+
- and then register: set_encoded_video_frame_observer
|
|
19
|
+
|
|
10
20
|
|
|
11
21
|
# Required Operating Systems and Python Versions
|
|
12
22
|
- Supported Linux versions:
|
|
@@ -35,6 +45,157 @@ python agora_rtc/examples/example_audio_pcm_send.py --appId=xxx --channelId=xxx
|
|
|
35
45
|
```
|
|
36
46
|
|
|
37
47
|
# Change log
|
|
48
|
+
#2025.09.01 release 2.3.0
|
|
49
|
+
|
|
50
|
+
Overview
|
|
51
|
+
|
|
52
|
+
Agora Python SDK version 2.3.0 introduces significant enhancements for real-time audio and video communication, with particular optimizations for AI server scenarios. This release includes API improvements, automation of previously manual processes, and increased flexibility in connection configuration.
|
|
53
|
+
|
|
54
|
+
New Features
|
|
55
|
+
|
|
56
|
+
1. AudioScenarioAiServer Support
|
|
57
|
+
|
|
58
|
+
• Added support for the AudioScenarioAiServer scenario type, now set as the default AudioScenario.
|
|
59
|
+
|
|
60
|
+
• Enables configuration of different scenarios and profiles for connections within the same process.
|
|
61
|
+
|
|
62
|
+
• Important: When using AI server scenario, client-side must use AIClient scenario to avoid audio abnormalities. Please consult Agora support for SDK versions supporting AIClient scenario.
|
|
63
|
+
|
|
64
|
+
2. Enhanced Connection Configuration
|
|
65
|
+
|
|
66
|
+
• Introduced PublishConfigure parameter in connection creation for setting:
|
|
67
|
+
|
|
68
|
+
• Scenario and profile configurations
|
|
69
|
+
|
|
70
|
+
• Audio/Video publication settings
|
|
71
|
+
|
|
72
|
+
• Other publication parameters
|
|
73
|
+
|
|
74
|
+
• Added multiple observer registration methods to connections:
|
|
75
|
+
|
|
76
|
+
• RegisterLocalUserObserver
|
|
77
|
+
|
|
78
|
+
• RegisterAudioFrameObserver
|
|
79
|
+
|
|
80
|
+
• RegisterVideoFrameObserver
|
|
81
|
+
|
|
82
|
+
• RegisterVideoEncodedFrameObserver
|
|
83
|
+
|
|
84
|
+
3. Stream Management Improvements
|
|
85
|
+
|
|
86
|
+
• Added publication control methods:
|
|
87
|
+
|
|
88
|
+
• PublishAudio/UnpublishAudio
|
|
89
|
+
|
|
90
|
+
• PublishVideo/UnpublishVideo
|
|
91
|
+
|
|
92
|
+
• Added data pushing methods:
|
|
93
|
+
|
|
94
|
+
• PushAudioPcmData/PushAudioEncodedData
|
|
95
|
+
|
|
96
|
+
• PushVideoFrame/PushVideoEncodedData
|
|
97
|
+
|
|
98
|
+
• Added InterruptAudio method for supporting interruption functionality
|
|
99
|
+
|
|
100
|
+
• Added IsPushToRTCCompleted method for checking push status
|
|
101
|
+
|
|
102
|
+
• Added SendAudioMetaData method for audio metadata transmission
|
|
103
|
+
|
|
104
|
+
4. Automation Enhancements
|
|
105
|
+
|
|
106
|
+
• Eliminated manual CreateDataStream calls - now handled automatically
|
|
107
|
+
|
|
108
|
+
• Automatic observer unregistration on Release() instead of manual unregistering
|
|
109
|
+
|
|
110
|
+
• Internal handling of media node factory creation:
|
|
111
|
+
|
|
112
|
+
• No longer requires manual calls to newMediaNodeFactory
|
|
113
|
+
|
|
114
|
+
• Automatic handling of track creation (NewCustomAudioTrackPcm, NewCustomAudioTrackEncoded, NewCustomVideoTrack)
|
|
115
|
+
|
|
116
|
+
• Automatic management of audio data senders (NewAudioPcmDataSender)
|
|
117
|
+
|
|
118
|
+
Integration Process
|
|
119
|
+
|
|
120
|
+
The updated integration workflow is as follows:
|
|
121
|
+
|
|
122
|
+
1. Initialize Agora Service (once per process startup):
|
|
123
|
+
config = AgoraServiceConfig()
|
|
124
|
+
agora_service = AgoraService()
|
|
125
|
+
agora_service.initialize(config)
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
2. Connection Management (can be looped for multiple connections):
|
|
129
|
+
# Create connection with configuration
|
|
130
|
+
con = agora_service.create_rtc_connection(con_config, publish_config)
|
|
131
|
+
|
|
132
|
+
# Register observers
|
|
133
|
+
con.register_observer(conHandler)
|
|
134
|
+
con.register_audio_frame_observer(audioFrameObserver)
|
|
135
|
+
con.register_local_user_observer(localUserObserver)
|
|
136
|
+
|
|
137
|
+
# Connect and publish
|
|
138
|
+
con.connect(token, channelName, userId)
|
|
139
|
+
con.publish_audio() # or con.publish_video()
|
|
140
|
+
|
|
141
|
+
# Push data
|
|
142
|
+
con.push_audio_pcm_data() # or push_audio_encoded_data()
|
|
143
|
+
# or con.push_video_frame()/push_video_encoded_data()
|
|
144
|
+
|
|
145
|
+
# Disconnect and release
|
|
146
|
+
con.disconnect()
|
|
147
|
+
con.release()
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
3. Release Agora Service (once during process termination):
|
|
151
|
+
agora_service.release()
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
Performance Recommendations
|
|
155
|
+
|
|
156
|
+
1. For AI Scenarios:
|
|
157
|
+
• Use AudioScenarioAIServer for server-side applications
|
|
158
|
+
|
|
159
|
+
• Provides optimized performance with lower latency (20-30ms reduction on iPhone compared to chorus)
|
|
160
|
+
|
|
161
|
+
• Enhanced experience in weak network conditions
|
|
162
|
+
|
|
163
|
+
• Mandatory: Client must use AIClient scenario
|
|
164
|
+
|
|
165
|
+
2. For Non-AI Scenarios:
|
|
166
|
+
• Consult Agora technical support for appropriate scenario configuration
|
|
167
|
+
|
|
168
|
+
• Ensure configuration matches specific business use cases
|
|
169
|
+
|
|
170
|
+
Bug Fixes
|
|
171
|
+
|
|
172
|
+
• Updated RTC SDK with 2 bug fixes
|
|
173
|
+
|
|
174
|
+
Important Notes
|
|
175
|
+
|
|
176
|
+
• Backward Compatibility: Review integration code for manual calls that are now automated
|
|
177
|
+
|
|
178
|
+
• Scenario Matching: Ensure client-server scenario compatibility (AIServer requires AIClient)
|
|
179
|
+
|
|
180
|
+
• Resource Management: Connection release now automatically handles observer unregistration
|
|
181
|
+
|
|
182
|
+
• Consult Support: For specific integration guidance and upgrade assistance, contact Agora SA
|
|
183
|
+
|
|
184
|
+
Summary of Core Changes
|
|
185
|
+
|
|
186
|
+
Before After 2.3.0
|
|
187
|
+
|
|
188
|
+
Manual CreateDataStream ✅ Automatic
|
|
189
|
+
|
|
190
|
+
Manual observer unregistration ✅ Automatic on Release()
|
|
191
|
+
|
|
192
|
+
Fixed per-process scenario ✅ Multi-scenario per process
|
|
193
|
+
|
|
194
|
+
Client/Server scenario mismatch ❗ AIClient mandatory for AI use
|
|
195
|
+
|
|
196
|
+
For detailed implementation guidance and version-specific support, please consult Agora technical support.
|
|
197
|
+
|
|
198
|
+
|
|
38
199
|
## 2025.04.28 Release 2.2.4
|
|
39
200
|
-- Update: update rtc sdk from 4.4.31 to 4.4.32
|
|
40
201
|
## 2025.04.14 Release 2.2.3
|
|
@@ -54,6 +215,7 @@ python agora_rtc/examples/example_audio_pcm_send.py --appId=xxx --channelId=xxx
|
|
|
54
215
|
- Added connection::agora_rtc_conn_enable_encryption.
|
|
55
216
|
-- Additions:
|
|
56
217
|
- Added connectionObserver::on_encryption_error (but not working for now, need to fix in the next monthly version 4.4.32).
|
|
218
|
+
|
|
57
219
|
2025.02.26 Release 2.2.1
|
|
58
220
|
--Update:
|
|
59
221
|
- Reduced buffer size from 180ms to 100ms to minimize latency.
|
|
@@ -74,7 +236,6 @@ python agora_rtc/examples/example_audio_pcm_send.py --appId=xxx --channelId=xxx
|
|
|
74
236
|
- Add the AudioMetaData interface: localuser::send_audio_meta_data. Done.
|
|
75
237
|
- Add the OnAudioMetaDataReceived callback to localuserObserver::on_audio_meta_data_received. Done.
|
|
76
238
|
-- Sample modifications.
|
|
77
|
-
|
|
78
239
|
2024.12.17 Release 2.1.7
|
|
79
240
|
--Changes:
|
|
80
241
|
|
|
@@ -102,7 +263,6 @@ python agora_rtc/examples/example_audio_pcm_send.py --appId=xxx --channelId=xxx
|
|
|
102
263
|
-- Replaced the use of pacer with AudioConsumer for pushing PCM audio.
|
|
103
264
|
- Updates:
|
|
104
265
|
-- Updated the samples related to Pacer and VAD.
|
|
105
|
-
|
|
106
266
|
## 2024.12.03 release Version 2.1.5
|
|
107
267
|
- Modifications:
|
|
108
268
|
- LocalUser/audioTrack:
|
|
@@ -158,7 +318,6 @@ Fixed some bug.
|
|
|
158
318
|
- Handle business operations.
|
|
159
319
|
- When a user logs out, execute con.disconnect() and release the audio/video tracks and observers associated with the connection, but do not call con.release(); then put the connection back into the connection pool.
|
|
160
320
|
- When the process exits, release the connection pool (release each con.release()), service/media_node_factory, and the connection pool (release each con.release()) to ensure resource release and optimal performance.
|
|
161
|
-
|
|
162
321
|
## Use of VAD
|
|
163
322
|
# Source code: voice_detection.py
|
|
164
323
|
# Sample code: example_audio_vad.py
|
|
@@ -189,7 +348,8 @@ Judge the value of state according to the returned state, and do corresponding p
|
|
|
189
348
|
### How to push the audio generated by TTS into the channel?
|
|
190
349
|
# Source code: audio_consumer.py
|
|
191
350
|
# Sample code: example_audio_consumer.py
|
|
192
|
-
|
|
351
|
+
|
|
352
|
+
### How to release resource?
|
|
193
353
|
## 如何释放资源?
|
|
194
354
|
localuser.unpublish_audio(audio_track)
|
|
195
355
|
localuser.unpublish_video(video_track)
|
|
@@ -36,21 +36,25 @@ def _check_download_and_extract_sdk():
|
|
|
36
36
|
#url = "https://download.agora.io/sdk/release/agora_rtc_sdk-x86_64-linux-gnu-v4.4.30-20241024_101940-398537.zip"
|
|
37
37
|
# version 2.2.0 for linux
|
|
38
38
|
#url = "https://download.agora.io/sdk/release/agora_rtc_sdk-x86_64-linux-gnu-v4.4.31-20241223_111509-491956.zip"
|
|
39
|
-
url = "https://download.agora.io/sdk/release/agora_rtc_sdk-x86_64-linux-gnu-v4.4.32-
|
|
39
|
+
#url = "https://download.agora.io/sdk/release/agora_rtc_sdk-x86_64-linux-gnu-v4.4.32-20250715_161625-791246.zip"
|
|
40
|
+
url = "https://download.agora.io/sdk/release/agora_rtc_sdk-x86_64-linux-gnu-v4.4.32-20250829_160340-860733.zip"
|
|
41
|
+
|
|
40
42
|
|
|
41
43
|
|
|
42
44
|
libagora_rtc_sdk_path = os.path.join(sdk_dir, "libagora_rtc_sdk.so")
|
|
43
45
|
#rtc_md5 = "7031dd10d1681cd88fd89d68c5b54282"
|
|
44
|
-
rtc_md5 = "
|
|
46
|
+
rtc_md5 = "7eb8042e43246f95f188549d8711d1bf"
|
|
45
47
|
if sys.platform == 'darwin':
|
|
46
48
|
#url = "https://download.agora.io/sdk/release/agora_rtc_sdk_mac_rel.v4.4.30_22472_FULL_20241024_1224_398653.zip"
|
|
47
49
|
# version 2.2.0 for mac
|
|
48
50
|
#url = "https://download.agora.io/sdk/release/agora_sdk_mac_v4.4.31_23136_FULL_20241223_1245_492039.zip"
|
|
49
|
-
url = "https://download.agora.io/sdk/release/agora_sdk_mac_v4.4.
|
|
51
|
+
#url = "https://download.agora.io/sdk/release/agora_sdk_mac_v4.4.32_24915_FULL_20250715_1710_791284.zip"
|
|
52
|
+
url = "https://download.agora.io/sdk/release/agora_sdk_mac_v4.4.32_25418_FULL_20250829_1647_860754.zip"
|
|
53
|
+
|
|
50
54
|
|
|
51
55
|
libagora_rtc_sdk_path = os.path.join(sdk_dir, "libAgoraRtcKit.dylib")
|
|
52
56
|
#rtc_md5 = "ca3ca14f9e2b7d97eb2594d1f32dab9f"
|
|
53
|
-
rtc_md5 = "
|
|
57
|
+
rtc_md5 = "df0ec3b5073d17dee76cc4d97c13699a"
|
|
54
58
|
if arch == "aarch64" and sys.platform == 'linux':
|
|
55
59
|
#url = "https://download.agora.io/sdk/release/Agora-RTC-aarch64-linux-gnu-v4.4.31-20250307_175457-603878.zip"
|
|
56
60
|
url = "https://download.agora.io/sdk/release/Agora-RTC-aarch64-linux-gnu-v4.4.32-20250425_150503-675674.zip"
|
|
@@ -1000,7 +1000,6 @@ class RemoteAudioTrackStatsInner(ctypes.Structure):
|
|
|
1000
1000
|
stats.received_bytes
|
|
1001
1001
|
)
|
|
1002
1002
|
|
|
1003
|
-
|
|
1004
1003
|
class EncodedAudioFrameInfoInner(ctypes.Structure):
|
|
1005
1004
|
_fields_ = [
|
|
1006
1005
|
('speech', ctypes.c_int),
|
|
@@ -1008,7 +1007,8 @@ class EncodedAudioFrameInfoInner(ctypes.Structure):
|
|
|
1008
1007
|
('sample_rate_hz', ctypes.c_int),
|
|
1009
1008
|
('samples_per_channel', ctypes.c_int),
|
|
1010
1009
|
('send_even_if_empty', ctypes.c_int),
|
|
1011
|
-
('number_of_channels', ctypes.c_int)
|
|
1010
|
+
('number_of_channels', ctypes.c_int),
|
|
1011
|
+
('capture_time_ms', ctypes.c_int64)
|
|
1012
1012
|
]
|
|
1013
1013
|
|
|
1014
1014
|
@staticmethod
|
|
@@ -1019,7 +1019,8 @@ class EncodedAudioFrameInfoInner(ctypes.Structure):
|
|
|
1019
1019
|
info.sample_rate,
|
|
1020
1020
|
info.samples_per_channel,
|
|
1021
1021
|
info.send_even_if_empty,
|
|
1022
|
-
info.number_of_channels
|
|
1022
|
+
info.number_of_channels,
|
|
1023
|
+
info.capture_time_ms
|
|
1023
1024
|
)
|
|
1024
1025
|
|
|
1025
1026
|
|
|
@@ -1067,6 +1068,10 @@ class AudioFrameInner(ctypes.Structure):
|
|
|
1067
1068
|
("buffer", ctypes.c_void_p),
|
|
1068
1069
|
("render_time_ms", ctypes.c_int64),
|
|
1069
1070
|
("avsync_type", ctypes.c_int),
|
|
1071
|
+
("presentation_ms", ctypes.c_int64),
|
|
1072
|
+
("audio_track_number", ctypes.c_int),
|
|
1073
|
+
("rtp_timestamp", ctypes.c_uint32),
|
|
1074
|
+
|
|
1070
1075
|
("far_field_flag", ctypes.c_int),
|
|
1071
1076
|
("rms", ctypes.c_int),
|
|
1072
1077
|
("voice_prob", ctypes.c_int),
|
|
@@ -1084,6 +1089,9 @@ class AudioFrameInner(ctypes.Structure):
|
|
|
1084
1089
|
buffer=bytearray(ctypes.string_at(self.buffer, self.samples_per_channel * self.bytes_per_sample * self.channels)),
|
|
1085
1090
|
render_time_ms=self.render_time_ms,
|
|
1086
1091
|
avsync_type=self.avsync_type,
|
|
1092
|
+
presentation_ms=self.presentation_ms,
|
|
1093
|
+
audio_track_number=self.audio_track_number,
|
|
1094
|
+
rtp_timestamp=self.rtp_timestamp,
|
|
1087
1095
|
far_field_flag=self.far_field_flag,
|
|
1088
1096
|
rms=self.rms,
|
|
1089
1097
|
voice_prob=self.voice_prob,
|
|
@@ -1102,6 +1110,9 @@ class AudioFrameInner(ctypes.Structure):
|
|
|
1102
1110
|
ctypes.cast(frame.buffer, ctypes.c_void_p),
|
|
1103
1111
|
frame.render_time_ms,
|
|
1104
1112
|
frame.avsync_type,
|
|
1113
|
+
frame.presentation_ms,
|
|
1114
|
+
frame.audio_track_number,
|
|
1115
|
+
frame.rtp_timestamp,
|
|
1105
1116
|
frame.far_field_flag,
|
|
1106
1117
|
frame.rms,
|
|
1107
1118
|
frame.voice_prob,
|
|
@@ -1133,6 +1144,11 @@ class AgoraServiceConfigInner(ctypes.Structure):
|
|
|
1133
1144
|
|
|
1134
1145
|
('use_string_uid', ctypes.c_int),
|
|
1135
1146
|
('domain_limit', ctypes.c_int),
|
|
1147
|
+
('log_level', ctypes.c_int),
|
|
1148
|
+
('log_file_path', ctypes.c_char_p),
|
|
1149
|
+
('log_file_size_kb', ctypes.c_uint32),
|
|
1150
|
+
('data_dir', ctypes.c_char_p),
|
|
1151
|
+
('config_dir', ctypes.c_char_p),
|
|
1136
1152
|
]
|
|
1137
1153
|
|
|
1138
1154
|
def get(self):
|
|
@@ -1146,7 +1162,12 @@ class AgoraServiceConfigInner(ctypes.Structure):
|
|
|
1146
1162
|
channel_profile=self.channel_profile,
|
|
1147
1163
|
audio_scenario=self.audio_scenario,
|
|
1148
1164
|
use_string_uid=self.use_string_uid,
|
|
1149
|
-
domain_limit=self.domain_limit
|
|
1165
|
+
domain_limit=self.domain_limit,
|
|
1166
|
+
log_level=self.log_level,
|
|
1167
|
+
log_path=self.log_file_path.decode() if self.log_file_path else "",
|
|
1168
|
+
log_file_size_kb=self.log_file_size_kb,
|
|
1169
|
+
data_dir=self.data_dir.decode() if self.data_dir else "",
|
|
1170
|
+
config_dir=self.config_dir.decode() if self.config_dir else ""
|
|
1150
1171
|
)
|
|
1151
1172
|
|
|
1152
1173
|
@staticmethod
|
|
@@ -1156,12 +1177,17 @@ class AgoraServiceConfigInner(ctypes.Structure):
|
|
|
1156
1177
|
config.enable_audio_device,
|
|
1157
1178
|
config.enable_video,
|
|
1158
1179
|
config.context,
|
|
1159
|
-
config.appid.encode(),
|
|
1180
|
+
config.appid.encode() if config.appid else None,
|
|
1160
1181
|
config.area_code,
|
|
1161
1182
|
config.channel_profile,
|
|
1162
1183
|
config.audio_scenario,
|
|
1163
1184
|
config.use_string_uid,
|
|
1164
|
-
config.domain_limit
|
|
1185
|
+
config.domain_limit,
|
|
1186
|
+
config.log_level,
|
|
1187
|
+
config.log_path.encode() if config.log_path else None,
|
|
1188
|
+
config.log_file_size_kb,
|
|
1189
|
+
config.data_dir.encode() if config.data_dir else None,
|
|
1190
|
+
config.config_dir.encode() if config.config_dir else None
|
|
1165
1191
|
)
|
|
1166
1192
|
|
|
1167
1193
|
|
|
@@ -1177,7 +1203,8 @@ class EncodedVideoFrameInfoInner(ctypes.Structure):
|
|
|
1177
1203
|
("capture_time_ms", ctypes.c_int64),
|
|
1178
1204
|
("decode_time_ms", ctypes.c_int64),
|
|
1179
1205
|
("uid", ctypes.c_uint),
|
|
1180
|
-
("stream_type", ctypes.c_int)
|
|
1206
|
+
("stream_type", ctypes.c_int),
|
|
1207
|
+
("presentation_ms", ctypes.c_int64)
|
|
1181
1208
|
]
|
|
1182
1209
|
|
|
1183
1210
|
def get(self):
|
|
@@ -1192,7 +1219,8 @@ class EncodedVideoFrameInfoInner(ctypes.Structure):
|
|
|
1192
1219
|
capture_time_ms=self.capture_time_ms,
|
|
1193
1220
|
decode_time_ms=self.decode_time_ms,
|
|
1194
1221
|
uid=self.uid,
|
|
1195
|
-
stream_type=self.stream_type
|
|
1222
|
+
stream_type=self.stream_type,
|
|
1223
|
+
presentation_ms=self.presentation_ms
|
|
1196
1224
|
)
|
|
1197
1225
|
|
|
1198
1226
|
@staticmethod
|
|
@@ -1208,7 +1236,8 @@ class EncodedVideoFrameInfoInner(ctypes.Structure):
|
|
|
1208
1236
|
info.capture_time_ms,
|
|
1209
1237
|
info.decode_time_ms,
|
|
1210
1238
|
info.uid,
|
|
1211
|
-
info.stream_type
|
|
1239
|
+
info.stream_type,
|
|
1240
|
+
info.presentation_ms
|
|
1212
1241
|
)
|
|
1213
1242
|
|
|
1214
1243
|
|
|
@@ -1249,3 +1278,94 @@ class EncryptionConfigInner(ctypes.Structure):
|
|
|
1249
1278
|
encryption_key,
|
|
1250
1279
|
encryption_kdf_salt
|
|
1251
1280
|
)
|
|
1281
|
+
|
|
1282
|
+
|
|
1283
|
+
class CapabilityItemInner(ctypes.Structure):
|
|
1284
|
+
_fields_ = [
|
|
1285
|
+
("id", ctypes.c_uint8),
|
|
1286
|
+
("name", ctypes.c_char_p)
|
|
1287
|
+
]
|
|
1288
|
+
|
|
1289
|
+
def get(self):
|
|
1290
|
+
return CapabilityItem(
|
|
1291
|
+
id=self.id,
|
|
1292
|
+
name=self.name.decode() if self.name else ""
|
|
1293
|
+
)
|
|
1294
|
+
|
|
1295
|
+
@staticmethod
|
|
1296
|
+
def create(item: CapabilityItem) -> 'CapabilityItemInner':
|
|
1297
|
+
return CapabilityItemInner(
|
|
1298
|
+
item.id,
|
|
1299
|
+
item.name.encode() if item.name else None
|
|
1300
|
+
)
|
|
1301
|
+
|
|
1302
|
+
|
|
1303
|
+
class CapabilityItemMapInner(ctypes.Structure):
|
|
1304
|
+
_fields_ = [
|
|
1305
|
+
("item", ctypes.POINTER(CapabilityItemInner)),
|
|
1306
|
+
("size", ctypes.c_size_t)
|
|
1307
|
+
]
|
|
1308
|
+
|
|
1309
|
+
def get(self):
|
|
1310
|
+
items = []
|
|
1311
|
+
if self.item and self.size > 0:
|
|
1312
|
+
for i in range(self.size):
|
|
1313
|
+
items.append(self.item[i].get())
|
|
1314
|
+
return CapabilityItemMap(
|
|
1315
|
+
item=items,
|
|
1316
|
+
size=self.size
|
|
1317
|
+
)
|
|
1318
|
+
|
|
1319
|
+
@staticmethod
|
|
1320
|
+
def create(item_map: CapabilityItemMap) -> 'CapabilityItemMapInner':
|
|
1321
|
+
if item_map.item and len(item_map.item) > 0:
|
|
1322
|
+
items_array = (CapabilityItemInner * len(item_map.item))()
|
|
1323
|
+
for i, item in enumerate(item_map.item):
|
|
1324
|
+
items_array[i] = CapabilityItemInner.create(item)
|
|
1325
|
+
items_ptr = ctypes.cast(items_array, ctypes.POINTER(CapabilityItemInner))
|
|
1326
|
+
else:
|
|
1327
|
+
items_ptr = ctypes.POINTER(CapabilityItemInner)()
|
|
1328
|
+
|
|
1329
|
+
return CapabilityItemMapInner(
|
|
1330
|
+
items_ptr,
|
|
1331
|
+
len(item_map.item) if item_map.item else 0
|
|
1332
|
+
)
|
|
1333
|
+
|
|
1334
|
+
|
|
1335
|
+
class CapabilitiesInner(ctypes.Structure):
|
|
1336
|
+
_fields_ = [
|
|
1337
|
+
("item_map", ctypes.POINTER(CapabilityItemMapInner)),
|
|
1338
|
+
("capability_type", ctypes.c_int)
|
|
1339
|
+
]
|
|
1340
|
+
|
|
1341
|
+
def get(self):
|
|
1342
|
+
return Capabilities(
|
|
1343
|
+
item_map=self.item_map.contents.get() if self.item_map else None,
|
|
1344
|
+
capability_type=self.capability_type
|
|
1345
|
+
)
|
|
1346
|
+
|
|
1347
|
+
@staticmethod
|
|
1348
|
+
def create(capabilities: Capabilities) -> 'CapabilitiesInner':
|
|
1349
|
+
item_map_ptr = None
|
|
1350
|
+
if capabilities.item_map:
|
|
1351
|
+
item_map_inner = CapabilityItemMapInner.create(capabilities.item_map)
|
|
1352
|
+
item_map_ptr = ctypes.pointer(item_map_inner)
|
|
1353
|
+
|
|
1354
|
+
return CapabilitiesInner(
|
|
1355
|
+
item_map_ptr,
|
|
1356
|
+
capabilities.capability_type
|
|
1357
|
+
)
|
|
1358
|
+
|
|
1359
|
+
|
|
1360
|
+
|
|
1361
|
+
class CapabilitiesItemMapInner(ctypes.Structure):
|
|
1362
|
+
_fields_ = [
|
|
1363
|
+
("item", ctypes.POINTER(CapabilityItemInner)),
|
|
1364
|
+
("size", ctypes.c_size_t)
|
|
1365
|
+
]
|
|
1366
|
+
|
|
1367
|
+
def get(self):
|
|
1368
|
+
return CapabilitiesItemMap(
|
|
1369
|
+
item=self.item,
|
|
1370
|
+
size=self.size
|
|
1371
|
+
)
|