agora-python-server-sdk 2.4.1__tar.gz → 2.4.3__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.1 → agora_python_server_sdk-2.4.3}/PKG-INFO +35 -2
- agora_python_server_sdk-2.4.1/agora_python_server_sdk.egg-info/PKG-INFO → agora_python_server_sdk-2.4.3/README.md +28 -16
- {agora_python_server_sdk-2.4.1 → agora_python_server_sdk-2.4.3}/agora/rtc/_ctypes_handle/_local_user_observer.py +1 -1
- {agora_python_server_sdk-2.4.1 → agora_python_server_sdk-2.4.3}/agora/rtc/_ctypes_handle/_rtc_connection_observer.py +1 -1
- {agora_python_server_sdk-2.4.1 → agora_python_server_sdk-2.4.3}/agora/rtc/agora_base.py +13 -0
- {agora_python_server_sdk-2.4.1 → agora_python_server_sdk-2.4.3}/agora/rtc/agora_service.py +5 -5
- {agora_python_server_sdk-2.4.1 → agora_python_server_sdk-2.4.3}/agora/rtc/local_user.py +16 -1
- {agora_python_server_sdk-2.4.1 → agora_python_server_sdk-2.4.3}/agora/rtc/rtc_connection.py +94 -5
- agora_python_server_sdk-2.4.1/README.md → agora_python_server_sdk-2.4.3/agora_python_server_sdk.egg-info/PKG-INFO +49 -1
- {agora_python_server_sdk-2.4.1 → agora_python_server_sdk-2.4.3}/setup.py +1 -1
- {agora_python_server_sdk-2.4.1 → agora_python_server_sdk-2.4.3}/MANIFEST.in +0 -0
- {agora_python_server_sdk-2.4.1 → agora_python_server_sdk-2.4.3}/agora/__init__.py +0 -0
- {agora_python_server_sdk-2.4.1 → agora_python_server_sdk-2.4.3}/agora/rtc/__init__.py +0 -0
- {agora_python_server_sdk-2.4.1 → agora_python_server_sdk-2.4.3}/agora/rtc/_ctypes_handle/_audio_frame_observer.py +0 -0
- {agora_python_server_sdk-2.4.1 → agora_python_server_sdk-2.4.3}/agora/rtc/_ctypes_handle/_ctypes_data.py +0 -0
- {agora_python_server_sdk-2.4.1 → agora_python_server_sdk-2.4.3}/agora/rtc/_ctypes_handle/_video_encoded_frame_observer.py +0 -0
- {agora_python_server_sdk-2.4.1 → agora_python_server_sdk-2.4.3}/agora/rtc/_ctypes_handle/_video_frame_observer.py +0 -0
- {agora_python_server_sdk-2.4.1 → agora_python_server_sdk-2.4.3}/agora/rtc/_utils/globals.py +0 -0
- {agora_python_server_sdk-2.4.1 → agora_python_server_sdk-2.4.3}/agora/rtc/agora_parameter.py +0 -0
- {agora_python_server_sdk-2.4.1 → agora_python_server_sdk-2.4.3}/agora/rtc/audio_encoded_frame_sender.py +0 -0
- {agora_python_server_sdk-2.4.1 → agora_python_server_sdk-2.4.3}/agora/rtc/audio_frame_observer.py +0 -0
- {agora_python_server_sdk-2.4.1 → agora_python_server_sdk-2.4.3}/agora/rtc/audio_pcm_data_sender.py +0 -0
- {agora_python_server_sdk-2.4.1 → agora_python_server_sdk-2.4.3}/agora/rtc/audio_sessionctrl.py +0 -0
- {agora_python_server_sdk-2.4.1 → agora_python_server_sdk-2.4.3}/agora/rtc/audio_vad_manager.py +0 -0
- {agora_python_server_sdk-2.4.1 → agora_python_server_sdk-2.4.3}/agora/rtc/external_audio_processor.py +0 -0
- {agora_python_server_sdk-2.4.1 → agora_python_server_sdk-2.4.3}/agora/rtc/local_audio_track.py +0 -0
- {agora_python_server_sdk-2.4.1 → agora_python_server_sdk-2.4.3}/agora/rtc/local_user_observer.py +0 -0
- {agora_python_server_sdk-2.4.1 → agora_python_server_sdk-2.4.3}/agora/rtc/local_video_track.py +0 -0
- {agora_python_server_sdk-2.4.1 → agora_python_server_sdk-2.4.3}/agora/rtc/media_node_factory.py +0 -0
- {agora_python_server_sdk-2.4.1 → agora_python_server_sdk-2.4.3}/agora/rtc/remote_audio_track.py +0 -0
- {agora_python_server_sdk-2.4.1 → agora_python_server_sdk-2.4.3}/agora/rtc/remote_video_track.py +0 -0
- {agora_python_server_sdk-2.4.1 → agora_python_server_sdk-2.4.3}/agora/rtc/rtc_connection_observer.py +0 -0
- {agora_python_server_sdk-2.4.1 → agora_python_server_sdk-2.4.3}/agora/rtc/utils/audio_consumer.py +0 -0
- {agora_python_server_sdk-2.4.1 → agora_python_server_sdk-2.4.3}/agora/rtc/utils/vad_dump.py +0 -0
- {agora_python_server_sdk-2.4.1 → agora_python_server_sdk-2.4.3}/agora/rtc/video_encoded_frame_observer.py +0 -0
- {agora_python_server_sdk-2.4.1 → agora_python_server_sdk-2.4.3}/agora/rtc/video_encoded_image_sender.py +0 -0
- {agora_python_server_sdk-2.4.1 → agora_python_server_sdk-2.4.3}/agora/rtc/video_frame_observer.py +0 -0
- {agora_python_server_sdk-2.4.1 → agora_python_server_sdk-2.4.3}/agora/rtc/video_frame_sender.py +0 -0
- {agora_python_server_sdk-2.4.1 → agora_python_server_sdk-2.4.3}/agora/rtc/voice_detection.py +0 -0
- {agora_python_server_sdk-2.4.1 → agora_python_server_sdk-2.4.3}/agora/rtm/__init__.py +0 -0
- {agora_python_server_sdk-2.4.1 → agora_python_server_sdk-2.4.3}/agora/rtm/_ctypes_handle/_ctypes_data.py +0 -0
- {agora_python_server_sdk-2.4.1 → agora_python_server_sdk-2.4.3}/agora/rtm/rtm_base.py +0 -0
- {agora_python_server_sdk-2.4.1 → agora_python_server_sdk-2.4.3}/agora/rtm/rtm_client.py +0 -0
- {agora_python_server_sdk-2.4.1 → agora_python_server_sdk-2.4.3}/agora/rtm/rtm_event_handler.py +0 -0
- {agora_python_server_sdk-2.4.1 → agora_python_server_sdk-2.4.3}/agora_python_server_sdk.egg-info/SOURCES.txt +0 -0
- {agora_python_server_sdk-2.4.1 → agora_python_server_sdk-2.4.3}/agora_python_server_sdk.egg-info/dependency_links.txt +0 -0
- {agora_python_server_sdk-2.4.1 → agora_python_server_sdk-2.4.3}/agora_python_server_sdk.egg-info/top_level.txt +0 -0
- {agora_python_server_sdk-2.4.1 → agora_python_server_sdk-2.4.3}/pyproject.toml +0 -0
- {agora_python_server_sdk-2.4.1 → agora_python_server_sdk-2.4.3}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
2
|
Name: agora_python_server_sdk
|
|
3
|
-
Version: 2.4.
|
|
3
|
+
Version: 2.4.3
|
|
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
|
|
@@ -12,6 +12,12 @@ Classifier: Programming Language :: Python :: 3.10
|
|
|
12
12
|
Classifier: Programming Language :: Python :: 3 :: Only
|
|
13
13
|
Requires-Python: >=3.10
|
|
14
14
|
Description-Content-Type: text/markdown
|
|
15
|
+
Dynamic: classifier
|
|
16
|
+
Dynamic: description
|
|
17
|
+
Dynamic: description-content-type
|
|
18
|
+
Dynamic: home-page
|
|
19
|
+
Dynamic: requires-python
|
|
20
|
+
Dynamic: summary
|
|
15
21
|
|
|
16
22
|
# Note
|
|
17
23
|
- This is a Python SDK wrapper for the Agora RTC SDK.
|
|
@@ -64,6 +70,33 @@ python agora_rtc/examples/example_audio_pcm_send.py --appId=xxx --channelId=xxx
|
|
|
64
70
|
```
|
|
65
71
|
|
|
66
72
|
# Change log
|
|
73
|
+
|
|
74
|
+
## 2026.01.15 Release Version 2.4.3
|
|
75
|
+
|
|
76
|
+
- **Bugfix**: Fixed a bug to reset `pcm_consumer_` when calling `interrupt_audio`.
|
|
77
|
+
|
|
78
|
+
## 2025.12.29 Release Version 2.4.2
|
|
79
|
+
|
|
80
|
+
- Added **incremental send mode** support.
|
|
81
|
+
- New `connection::send_intra_request` API, allowing you to initiate an intra request to remote users and trigger them to send a key frame.
|
|
82
|
+
|
|
83
|
+
#### Example usage of incremental send mode
|
|
84
|
+
|
|
85
|
+
```python
|
|
86
|
+
# Configure incremental send parameters
|
|
87
|
+
publish_config.send_external_audio_parameters = SendExternalAudioParameters(
|
|
88
|
+
enabled=True,
|
|
89
|
+
send_ms=2000,
|
|
90
|
+
send_speed=2,
|
|
91
|
+
deliver_mute_data_for_fake_adm=False
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
# Create an RTC connection
|
|
95
|
+
connection = agora_service.create_rtc_connection(con_config, publish_config)
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
|
|
67
100
|
## 2025.12.17 Release 2.4.1
|
|
68
101
|
|
|
69
102
|
- Updated RTC SDK to version 154.
|
|
@@ -1,18 +1,3 @@
|
|
|
1
|
-
Metadata-Version: 2.1
|
|
2
|
-
Name: agora_python_server_sdk
|
|
3
|
-
Version: 2.4.1
|
|
4
|
-
Summary: A Python SDK for Agora Server
|
|
5
|
-
Home-page: https://github.com/AgoraIO-Extensions/Agora-Python-Server-SDK
|
|
6
|
-
Classifier: Intended Audience :: Developers
|
|
7
|
-
Classifier: License :: OSI Approved :: MIT License
|
|
8
|
-
Classifier: Topic :: Multimedia :: Sound/Audio
|
|
9
|
-
Classifier: Topic :: Multimedia :: Video
|
|
10
|
-
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
11
|
-
Classifier: Programming Language :: Python :: 3.10
|
|
12
|
-
Classifier: Programming Language :: Python :: 3 :: Only
|
|
13
|
-
Requires-Python: >=3.10
|
|
14
|
-
Description-Content-Type: text/markdown
|
|
15
|
-
|
|
16
1
|
# Note
|
|
17
2
|
- This is a Python SDK wrapper for the Agora RTC SDK.
|
|
18
3
|
- It supports Linux and Mac platforms.
|
|
@@ -64,6 +49,33 @@ python agora_rtc/examples/example_audio_pcm_send.py --appId=xxx --channelId=xxx
|
|
|
64
49
|
```
|
|
65
50
|
|
|
66
51
|
# Change log
|
|
52
|
+
|
|
53
|
+
## 2026.01.15 Release Version 2.4.3
|
|
54
|
+
|
|
55
|
+
- **Bugfix**: Fixed a bug to reset `pcm_consumer_` when calling `interrupt_audio`.
|
|
56
|
+
|
|
57
|
+
## 2025.12.29 Release Version 2.4.2
|
|
58
|
+
|
|
59
|
+
- Added **incremental send mode** support.
|
|
60
|
+
- New `connection::send_intra_request` API, allowing you to initiate an intra request to remote users and trigger them to send a key frame.
|
|
61
|
+
|
|
62
|
+
#### Example usage of incremental send mode
|
|
63
|
+
|
|
64
|
+
```python
|
|
65
|
+
# Configure incremental send parameters
|
|
66
|
+
publish_config.send_external_audio_parameters = SendExternalAudioParameters(
|
|
67
|
+
enabled=True,
|
|
68
|
+
send_ms=2000,
|
|
69
|
+
send_speed=2,
|
|
70
|
+
deliver_mute_data_for_fake_adm=False
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
# Create an RTC connection
|
|
74
|
+
connection = agora_service.create_rtc_connection(con_config, publish_config)
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
|
|
67
79
|
## 2025.12.17 Release 2.4.1
|
|
68
80
|
|
|
69
81
|
- Updated RTC SDK to version 154.
|
|
@@ -570,4 +582,4 @@ VAD: Good afternoon, what are some fun places to visit in Beijing?
|
|
|
570
582
|
|
|
571
583
|
|
|
572
584
|
|
|
573
|
-
If latency is a concern, you can lower this value, or consult with the development team to determine how to manage latency while ensuring semantic continuity in speech recognition. This will help avoid the AI being interrupted too sensitively.
|
|
585
|
+
If latency is a concern, you can lower this value, or consult with the development team to determine how to manage latency while ensuring semantic continuity in speech recognition. This will help avoid the AI being interrupted too sensitively.
|
|
@@ -171,7 +171,7 @@ class RTCLocalUserObserverInner(ctypes.Structure):
|
|
|
171
171
|
def _on_audio_track_publication_failure(self, local_user_handle, local_audio_track_handle, error_code):
|
|
172
172
|
logger.debug(f"LocalUserCB _on_audio_track_publication_failure: {local_user_handle}, {local_audio_track_handle}, {error_code}")
|
|
173
173
|
audio_track = self.local_user.get_audio_map(local_audio_track_handle)
|
|
174
|
-
self.local_user.
|
|
174
|
+
self.local_user._del_audio_map(local_audio_track_handle)
|
|
175
175
|
self.local_user_observer.on_audio_track_publication_failure(self.local_user, audio_track, error_code)
|
|
176
176
|
|
|
177
177
|
def _on_local_audio_track_state_changed(self, local_user_handle, local_audio_track_handle, state, error):
|
|
@@ -288,7 +288,7 @@ class CapabilitiesObserverInner(ctypes.Structure):
|
|
|
288
288
|
self.on_capabilities_changed = ON_CAPABILITIES_CHANGED_CALLBACK(self._on_capabilities_changed)
|
|
289
289
|
|
|
290
290
|
def _on_capabilities_changed(self, agora_capabilities_observer, ptr_caps_inner, size):
|
|
291
|
-
|
|
291
|
+
logger.debug(f"ConnCB _on_capabilities_changed: {agora_capabilities_observer}, {ptr_caps_inner}, {size}")
|
|
292
292
|
|
|
293
293
|
# 正确解析C指针数组
|
|
294
294
|
# 方法1: 使用ctypes.cast将指针转换为数组
|
|
@@ -427,6 +427,18 @@ class SenderOptions:
|
|
|
427
427
|
cc_mode: TCcMode = TCcMode.CC_ENABLED
|
|
428
428
|
codec_type: VideoCodecType = VideoCodecType.VIDEO_CODEC_H264
|
|
429
429
|
|
|
430
|
+
'''
|
|
431
|
+
note: DeliverMuteDataForFakeAdm can only set to rtc engine level, can not
|
|
432
|
+
set to connection level
|
|
433
|
+
so if once a connection has set to true, wihich will affect all the connections,
|
|
434
|
+
'''
|
|
435
|
+
@dataclass(kw_only=True)
|
|
436
|
+
class SendExternalAudioParameters:
|
|
437
|
+
enabled: bool = False
|
|
438
|
+
send_ms: int = 0
|
|
439
|
+
send_speed: int = 0
|
|
440
|
+
deliver_mute_data_for_fake_adm: bool = False
|
|
441
|
+
|
|
430
442
|
|
|
431
443
|
@dataclass(kw_only=True)
|
|
432
444
|
class RtcConnectionPublishConfig:
|
|
@@ -437,6 +449,7 @@ class RtcConnectionPublishConfig:
|
|
|
437
449
|
audio_publish_type: AudioPublishType = AudioPublishType.AUDIO_PUBLISH_TYPE_PCM
|
|
438
450
|
video_publish_type: VideoPublishType = VideoPublishType.VIDEO_PUBLISH_TYPE_NONE
|
|
439
451
|
video_encoded_image_sender_options: 'SenderOptions' = field(default_factory=SenderOptions)
|
|
452
|
+
send_external_audio_parameters: 'SendExternalAudioParameters | None' = None
|
|
440
453
|
|
|
441
454
|
@dataclass(kw_only=True)
|
|
442
455
|
class VideoSubscriptionOptions:
|
|
@@ -186,11 +186,11 @@ class AgoraService:
|
|
|
186
186
|
return RTCConnection(self, con_config, publish_config)
|
|
187
187
|
|
|
188
188
|
# createCustomAudioTrackPcm: creatae a custom audio track from pcm data sender
|
|
189
|
-
def _create_custom_audio_track_pcm(self, audio_pcm_data_sender: AudioPcmDataSender, scenario: AudioScenarioType) -> LocalAudioTrack:
|
|
189
|
+
def _create_custom_audio_track_pcm(self, audio_pcm_data_sender: AudioPcmDataSender, scenario: AudioScenarioType, is_extra_audio: bool) -> LocalAudioTrack:
|
|
190
190
|
if not self.inited:
|
|
191
191
|
logger.error("AgoraService is not initialized. Please call initialize() first.")
|
|
192
192
|
return None
|
|
193
|
-
if scenario == AudioScenarioType.AUDIO_SCENARIO_AI_SERVER:
|
|
193
|
+
if scenario == AudioScenarioType.AUDIO_SCENARIO_AI_SERVER and is_extra_audio == False:
|
|
194
194
|
custom_audio_track = agora_service_create_direct_custom_audio_track_pcm(self.service_handle, audio_pcm_data_sender.sender_handle)
|
|
195
195
|
else:
|
|
196
196
|
custom_audio_track = agora_service_create_custom_audio_track_pcm(self.service_handle, audio_pcm_data_sender.sender_handle)
|
|
@@ -198,10 +198,10 @@ class AgoraService:
|
|
|
198
198
|
return None
|
|
199
199
|
local_track = LocalAudioTrack(custom_audio_track)
|
|
200
200
|
#default for ai senario to set min delay to 10ms
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
local_track.set_max_buffer_audio_frame_number(100000)
|
|
201
|
+
|
|
202
|
+
local_track.set_max_buffer_audio_frame_number(100000)
|
|
204
203
|
#and set enable to true
|
|
204
|
+
local_track.set_send_delay_ms(10)
|
|
205
205
|
local_track.set_enabled(True)
|
|
206
206
|
return local_track
|
|
207
207
|
# mix_mode: MIX_ENABLED = 0, MIX_DISABLED = 1
|
|
@@ -230,7 +230,9 @@ agora_local_user_send_aduio_meta_data = agora_lib.agora_local_user_send_audio_me
|
|
|
230
230
|
agora_local_user_send_aduio_meta_data.restype = AGORA_API_C_INT
|
|
231
231
|
agora_local_user_send_aduio_meta_data.argtypes = [AGORA_HANDLE, ctypes.c_char_p, ctypes.c_size_t]
|
|
232
232
|
|
|
233
|
-
|
|
233
|
+
agora_local_user_send_intra_request = agora_lib.agora_local_user_send_intra_request
|
|
234
|
+
agora_local_user_send_intra_request.restype = AGORA_API_C_INT
|
|
235
|
+
agora_local_user_send_intra_request.argtypes = [AGORA_HANDLE, ctypes.c_char_p]
|
|
234
236
|
|
|
235
237
|
|
|
236
238
|
class LocalUser:
|
|
@@ -628,3 +630,16 @@ class LocalUser:
|
|
|
628
630
|
ret = self.connection._set_apm_filter_properties(remote_audio_track_handle, user_id_str)
|
|
629
631
|
print(f"**********LocalUser _set_apm_filter_properties: {ret}")
|
|
630
632
|
return ret
|
|
633
|
+
pass
|
|
634
|
+
def _send_intra_request(self, remote_uid: str) -> int:
|
|
635
|
+
#validity check
|
|
636
|
+
if remote_uid is None:
|
|
637
|
+
return -1000
|
|
638
|
+
if self.user_handle is None:
|
|
639
|
+
return -1001
|
|
640
|
+
uid_str = remote_uid.encode('utf-8')
|
|
641
|
+
ret = agora_local_user_send_intra_request(self.user_handle, ctypes.c_char_p(uid_str))
|
|
642
|
+
if ret < 0:
|
|
643
|
+
logger.error("Failed to send intra request")
|
|
644
|
+
return ret
|
|
645
|
+
pass
|
|
@@ -83,6 +83,13 @@ agora_local_user_unregister_capabilities_observer = agora_lib.agora_local_user_u
|
|
|
83
83
|
agora_local_user_unregister_capabilities_observer.restype = AGORA_API_C_INT
|
|
84
84
|
agora_local_user_unregister_capabilities_observer.argtypes = [AGORA_HANDLE, AGORA_HANDLE]
|
|
85
85
|
|
|
86
|
+
agora_local_audio_track_set_total_extra_send_ms = agora_lib.agora_local_audio_track_set_total_extra_send_ms
|
|
87
|
+
agora_local_audio_track_set_total_extra_send_ms.restype = AGORA_API_C_INT
|
|
88
|
+
agora_local_audio_track_set_total_extra_send_ms.argtypes = [AGORA_HANDLE, ctypes.c_uint64]
|
|
89
|
+
|
|
90
|
+
#global variable
|
|
91
|
+
_is_deliver_mute_data_has_set: bool = False
|
|
92
|
+
|
|
86
93
|
class RTCConnection:
|
|
87
94
|
def __init__(self, service: AgoraService, conn_config: RTCConnConfig, publish_config: RtcConnectionPublishConfig) -> None:
|
|
88
95
|
self.conn_handle = None
|
|
@@ -90,6 +97,7 @@ class RTCConnection:
|
|
|
90
97
|
self.local_user = None
|
|
91
98
|
self.rtc_engine = service
|
|
92
99
|
self._con_observer = None
|
|
100
|
+
self._agora_parameter = None
|
|
93
101
|
#1 create conn_handle
|
|
94
102
|
self.conn_handle = agora_rtc_conn_create(self.rtc_engine.service_handle, ctypes.byref(RTCConnConfigInner.create(conn_config)))
|
|
95
103
|
if self.conn_handle is None:
|
|
@@ -98,6 +106,7 @@ class RTCConnection:
|
|
|
98
106
|
self.local_user_handle = agora_rtc_conn_get_local_user(self.conn_handle)
|
|
99
107
|
if self.local_user_handle:
|
|
100
108
|
self.local_user = LocalUser(self.local_user_handle, self)
|
|
109
|
+
self._agora_parameter = self._init_agora_parameter()
|
|
101
110
|
#keep publish_config
|
|
102
111
|
self.publish_config = publish_config
|
|
103
112
|
#and prepare track and sender for publish
|
|
@@ -107,6 +116,9 @@ class RTCConnection:
|
|
|
107
116
|
self._audio_encoded_sender = None
|
|
108
117
|
self._video_sender = None
|
|
109
118
|
self._video_encoded_sender = None
|
|
119
|
+
# for external audio parameters
|
|
120
|
+
self._send_external_audio_parameters = publish_config.send_external_audio_parameters
|
|
121
|
+
|
|
110
122
|
self._pcm_consume_stats = PcmConsumeStats()
|
|
111
123
|
self._prepare_publish_track_and_sender()
|
|
112
124
|
#3 set profile and scenario
|
|
@@ -123,12 +135,15 @@ class RTCConnection:
|
|
|
123
135
|
self._capabilities_observer_obj = None
|
|
124
136
|
if self.publish_config.audio_scenario == AudioScenarioType.AUDIO_SCENARIO_AI_SERVER:
|
|
125
137
|
self._register_capabilities_observer()
|
|
138
|
+
# for external audio parameters
|
|
139
|
+
self._set_send_external_send_frame_speed(self._send_external_audio_parameters)
|
|
126
140
|
|
|
127
141
|
def _prepare_publish_track_and_sender(self)->int:
|
|
128
142
|
if self.publish_config.is_publish_audio:
|
|
129
143
|
if self.publish_config.audio_publish_type == AudioPublishType.AUDIO_PUBLISH_TYPE_PCM:
|
|
130
144
|
self._audio_sender = self.rtc_engine.media_node_factory.create_audio_pcm_data_sender()
|
|
131
|
-
|
|
145
|
+
is_extra_audio = self._is_support_send_external_audio()
|
|
146
|
+
self._audio_track = self.rtc_engine._create_custom_audio_track_pcm(self._audio_sender, self.publish_config.audio_scenario, is_extra_audio)
|
|
132
147
|
elif self.publish_config.audio_publish_type == AudioPublishType.AUDIO_PUBLISH_TYPE_ENCODED_PCM:
|
|
133
148
|
self._audio_encoded_sender = self.rtc_engine.media_node_factory.create_audio_encoded_frame_sender()
|
|
134
149
|
self._audio_track = self.rtc_engine.create_custom_audio_track_encoded(self._audio_encoded_sender, 1)#mix_mode: MIX_ENABLED = 0, MIX_DISABLED = 1
|
|
@@ -203,11 +218,13 @@ class RTCConnection:
|
|
|
203
218
|
return ret
|
|
204
219
|
|
|
205
220
|
#
|
|
206
|
-
def
|
|
221
|
+
def _init_agora_parameter(self):
|
|
207
222
|
agora_parameter = agora_rtc_conn_get_agora_parameter(self.conn_handle)
|
|
208
223
|
if not agora_parameter:
|
|
209
224
|
return None
|
|
210
225
|
return AgoraParameter(agora_parameter)
|
|
226
|
+
def get_agora_parameter(self):
|
|
227
|
+
return self._agora_parameter
|
|
211
228
|
|
|
212
229
|
#
|
|
213
230
|
|
|
@@ -337,6 +354,8 @@ class RTCConnection:
|
|
|
337
354
|
ret = -1000
|
|
338
355
|
if self.local_user and self._audio_track:
|
|
339
356
|
ret = self.local_user._unpublish_audio(self._audio_track)
|
|
357
|
+
#reset pcm consumer state now
|
|
358
|
+
self._pcm_consume_stats.reset()
|
|
340
359
|
return ret
|
|
341
360
|
def publish_video(self)->int:
|
|
342
361
|
ret = -1000
|
|
@@ -357,6 +376,9 @@ class RTCConnection:
|
|
|
357
376
|
self.publish_audio()
|
|
358
377
|
elif self._audio_track:
|
|
359
378
|
self._audio_track.clear_sender_buffer()
|
|
379
|
+
|
|
380
|
+
# reset pcm consumer to new state now
|
|
381
|
+
self._pcm_consume_stats.reset()
|
|
360
382
|
return ret
|
|
361
383
|
def send_audio_meta_data(self, data)->int:
|
|
362
384
|
ret = -1000
|
|
@@ -397,6 +419,11 @@ class RTCConnection:
|
|
|
397
419
|
frame.samples_per_channel = readLen // (channels * 2)
|
|
398
420
|
frame.present_time_ms = start_pts
|
|
399
421
|
|
|
422
|
+
#check if a new round or not. if new round should call _set_total_extra_send_ms()
|
|
423
|
+
is_new_round = self._pcm_consume_stats.is_new_round()
|
|
424
|
+
if is_new_round:
|
|
425
|
+
self._set_total_extra_send_ms()
|
|
426
|
+
|
|
400
427
|
ret = self._audio_sender.send_audio_pcm_data(frame)
|
|
401
428
|
self._pcm_consume_stats.add_pcm_data(readLen, sample_rate, channels)
|
|
402
429
|
return ret
|
|
@@ -431,8 +458,9 @@ class RTCConnection:
|
|
|
431
458
|
|
|
432
459
|
updated_track = None
|
|
433
460
|
delayed_del_track = None
|
|
461
|
+
is_extra_audio = False
|
|
434
462
|
if self._audio_sender:
|
|
435
|
-
updated_track = self.rtc_engine._create_custom_audio_track_pcm(self._audio_sender, scenario)
|
|
463
|
+
updated_track = self.rtc_engine._create_custom_audio_track_pcm(self._audio_sender, scenario, is_extra_audio)
|
|
436
464
|
elif self._audio_encoded_sender:
|
|
437
465
|
updated_track = self.rtc_engine.create_custom_audio_track_encoded(self._audio_encoded_sender, scenario)
|
|
438
466
|
|
|
@@ -440,6 +468,8 @@ class RTCConnection:
|
|
|
440
468
|
delayed_del_track = self._audio_track
|
|
441
469
|
self._audio_track = updated_track
|
|
442
470
|
self._audio_track.set_enabled(True)
|
|
471
|
+
self._audio_track.set_send_delay_ms(10)
|
|
472
|
+
self._audio_track.set_max_buffer_audio_frame_number(100000)
|
|
443
473
|
|
|
444
474
|
if delayed_del_track:
|
|
445
475
|
delayed_del_track.release()
|
|
@@ -467,10 +497,10 @@ class RTCConnection:
|
|
|
467
497
|
item_index = 0
|
|
468
498
|
for cap in capabilities:
|
|
469
499
|
item_index = 0
|
|
470
|
-
|
|
500
|
+
logger.debug(f"Capability[{index}] - Type: {cap.capability_type}")
|
|
471
501
|
index += 1
|
|
472
502
|
for item in cap.item_map.item:
|
|
473
|
-
|
|
503
|
+
logger.debug(f"Item[{item_index}] - ID: {item.id}, Name: {item.name}")
|
|
474
504
|
item_index += 1
|
|
475
505
|
if cap.capability_type == 19 and item.name and item.name.upper() == "SUPPORT":
|
|
476
506
|
fallback_scenario = False
|
|
@@ -541,5 +571,64 @@ class RTCConnection:
|
|
|
541
571
|
print(f"**********APM: to enable apm_dump, error: {ret}")
|
|
542
572
|
return ret
|
|
543
573
|
|
|
574
|
+
def _set_send_external_send_frame_speed(self, send_external_audio_parameters: SendExternalAudioParameters)->int:
|
|
575
|
+
ret = -1000
|
|
576
|
+
if send_external_audio_parameters == None or send_external_audio_parameters.enabled == False or send_external_audio_parameters.send_ms <= 0 or send_external_audio_parameters.send_speed <= 1:
|
|
577
|
+
return -1001
|
|
578
|
+
speed = send_external_audio_parameters.send_speed
|
|
579
|
+
if speed < 1:
|
|
580
|
+
speed = 1
|
|
581
|
+
if speed > 5:
|
|
582
|
+
speed = 5
|
|
583
|
+
#set send speed for fake adm to connection level
|
|
584
|
+
params = '{"che.audio.extra_send_frames_per_interval_for_fake_adm": %d}' % speed
|
|
585
|
+
|
|
586
|
+
if (self._agora_parameter is None):
|
|
587
|
+
return -1002
|
|
588
|
+
ret = self._agora_parameter.set_parameters(params)
|
|
589
|
+
|
|
590
|
+
|
|
591
|
+
# set deliver mute data for fake adm to service level and only once
|
|
592
|
+
self._set_deliver_mute_data_for_fake_adm(send_external_audio_parameters.deliver_mute_data_for_fake_adm)
|
|
593
|
+
|
|
594
|
+
return ret
|
|
595
|
+
pass
|
|
596
|
+
|
|
597
|
+
def _set_deliver_mute_data_for_fake_adm(self, deliver_mute_data_for_fake_adm: bool)->int:
|
|
598
|
+
ret = -1000
|
|
599
|
+
global _is_deliver_mute_data_has_set
|
|
600
|
+
if deliver_mute_data_for_fake_adm == False and _is_deliver_mute_data_has_set == False:
|
|
601
|
+
params = '{"che.audio.deliver_mute_data_for_fake_adm": false}'
|
|
602
|
+
rtc_parameter = self.rtc_engine.get_agora_parameter()
|
|
603
|
+
if rtc_parameter is not None:
|
|
604
|
+
ret = rtc_parameter.set_parameters(params)
|
|
605
|
+
_is_deliver_mute_data_has_set = True
|
|
606
|
+
return ret
|
|
607
|
+
def _is_support_send_external_audio(self)->bool:
|
|
608
|
+
ret = False
|
|
609
|
+
if ((self._send_external_audio_parameters is not None)
|
|
610
|
+
and (self._send_external_audio_parameters.enabled == True)
|
|
611
|
+
and (self._send_external_audio_parameters.send_ms > 0)
|
|
612
|
+
and (self._send_external_audio_parameters.send_speed > 1)):
|
|
613
|
+
ret = True
|
|
614
|
+
return ret
|
|
615
|
+
pass
|
|
616
|
+
#only valid after call this api
|
|
617
|
+
#and default call before each round
|
|
618
|
+
def _set_total_extra_send_ms(self)->int:
|
|
619
|
+
is_support = self._is_support_send_external_audio()
|
|
620
|
+
if is_support == False:
|
|
621
|
+
return 0
|
|
622
|
+
send_ms = self._send_external_audio_parameters.send_ms
|
|
623
|
+
ret = agora_local_audio_track_set_total_extra_send_ms(self._audio_track.track_handle, ctypes.c_uint64(send_ms))
|
|
544
624
|
|
|
625
|
+
return ret
|
|
626
|
+
pass
|
|
627
|
+
def send_intra_request(self, remote_uid: str) -> int:
|
|
628
|
+
ret = -1000
|
|
629
|
+
if self.local_user is None:
|
|
630
|
+
return -1001
|
|
631
|
+
ret = self.local_user._send_intra_request(remote_uid)
|
|
632
|
+
return ret
|
|
633
|
+
pass
|
|
545
634
|
|
|
@@ -1,3 +1,24 @@
|
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
|
+
Name: agora_python_server_sdk
|
|
3
|
+
Version: 2.4.3
|
|
4
|
+
Summary: A Python SDK for Agora Server
|
|
5
|
+
Home-page: https://github.com/AgoraIO-Extensions/Agora-Python-Server-SDK
|
|
6
|
+
Classifier: Intended Audience :: Developers
|
|
7
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
8
|
+
Classifier: Topic :: Multimedia :: Sound/Audio
|
|
9
|
+
Classifier: Topic :: Multimedia :: Video
|
|
10
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
12
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
13
|
+
Requires-Python: >=3.10
|
|
14
|
+
Description-Content-Type: text/markdown
|
|
15
|
+
Dynamic: classifier
|
|
16
|
+
Dynamic: description
|
|
17
|
+
Dynamic: description-content-type
|
|
18
|
+
Dynamic: home-page
|
|
19
|
+
Dynamic: requires-python
|
|
20
|
+
Dynamic: summary
|
|
21
|
+
|
|
1
22
|
# Note
|
|
2
23
|
- This is a Python SDK wrapper for the Agora RTC SDK.
|
|
3
24
|
- It supports Linux and Mac platforms.
|
|
@@ -49,6 +70,33 @@ python agora_rtc/examples/example_audio_pcm_send.py --appId=xxx --channelId=xxx
|
|
|
49
70
|
```
|
|
50
71
|
|
|
51
72
|
# Change log
|
|
73
|
+
|
|
74
|
+
## 2026.01.15 Release Version 2.4.3
|
|
75
|
+
|
|
76
|
+
- **Bugfix**: Fixed a bug to reset `pcm_consumer_` when calling `interrupt_audio`.
|
|
77
|
+
|
|
78
|
+
## 2025.12.29 Release Version 2.4.2
|
|
79
|
+
|
|
80
|
+
- Added **incremental send mode** support.
|
|
81
|
+
- New `connection::send_intra_request` API, allowing you to initiate an intra request to remote users and trigger them to send a key frame.
|
|
82
|
+
|
|
83
|
+
#### Example usage of incremental send mode
|
|
84
|
+
|
|
85
|
+
```python
|
|
86
|
+
# Configure incremental send parameters
|
|
87
|
+
publish_config.send_external_audio_parameters = SendExternalAudioParameters(
|
|
88
|
+
enabled=True,
|
|
89
|
+
send_ms=2000,
|
|
90
|
+
send_speed=2,
|
|
91
|
+
deliver_mute_data_for_fake_adm=False
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
# Create an RTC connection
|
|
95
|
+
connection = agora_service.create_rtc_connection(con_config, publish_config)
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
|
|
52
100
|
## 2025.12.17 Release 2.4.1
|
|
53
101
|
|
|
54
102
|
- Updated RTC SDK to version 154.
|
|
@@ -555,4 +603,4 @@ VAD: Good afternoon, what are some fun places to visit in Beijing?
|
|
|
555
603
|
|
|
556
604
|
|
|
557
605
|
|
|
558
|
-
If latency is a concern, you can lower this value, or consult with the development team to determine how to manage latency while ensuring semantic continuity in speech recognition. This will help avoid the AI being interrupted too sensitively.
|
|
606
|
+
If latency is a concern, you can lower this value, or consult with the development team to determine how to manage latency while ensuring semantic continuity in speech recognition. This will help avoid the AI being interrupted too sensitively.
|
|
@@ -126,7 +126,7 @@ class CustomInstallCommand(install):
|
|
|
126
126
|
|
|
127
127
|
setup(
|
|
128
128
|
name='agora_python_server_sdk',
|
|
129
|
-
version='2.4.
|
|
129
|
+
version='2.4.3',
|
|
130
130
|
description='A Python SDK for Agora Server',
|
|
131
131
|
long_description=open('README.md').read(),
|
|
132
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
|
{agora_python_server_sdk-2.4.1 → agora_python_server_sdk-2.4.3}/agora/rtc/agora_parameter.py
RENAMED
|
File without changes
|
|
File without changes
|
{agora_python_server_sdk-2.4.1 → agora_python_server_sdk-2.4.3}/agora/rtc/audio_frame_observer.py
RENAMED
|
File without changes
|
{agora_python_server_sdk-2.4.1 → agora_python_server_sdk-2.4.3}/agora/rtc/audio_pcm_data_sender.py
RENAMED
|
File without changes
|
{agora_python_server_sdk-2.4.1 → agora_python_server_sdk-2.4.3}/agora/rtc/audio_sessionctrl.py
RENAMED
|
File without changes
|
{agora_python_server_sdk-2.4.1 → agora_python_server_sdk-2.4.3}/agora/rtc/audio_vad_manager.py
RENAMED
|
File without changes
|
|
File without changes
|
{agora_python_server_sdk-2.4.1 → agora_python_server_sdk-2.4.3}/agora/rtc/local_audio_track.py
RENAMED
|
File without changes
|
{agora_python_server_sdk-2.4.1 → agora_python_server_sdk-2.4.3}/agora/rtc/local_user_observer.py
RENAMED
|
File without changes
|
{agora_python_server_sdk-2.4.1 → agora_python_server_sdk-2.4.3}/agora/rtc/local_video_track.py
RENAMED
|
File without changes
|
{agora_python_server_sdk-2.4.1 → agora_python_server_sdk-2.4.3}/agora/rtc/media_node_factory.py
RENAMED
|
File without changes
|
{agora_python_server_sdk-2.4.1 → agora_python_server_sdk-2.4.3}/agora/rtc/remote_audio_track.py
RENAMED
|
File without changes
|
{agora_python_server_sdk-2.4.1 → agora_python_server_sdk-2.4.3}/agora/rtc/remote_video_track.py
RENAMED
|
File without changes
|
{agora_python_server_sdk-2.4.1 → agora_python_server_sdk-2.4.3}/agora/rtc/rtc_connection_observer.py
RENAMED
|
File without changes
|
{agora_python_server_sdk-2.4.1 → agora_python_server_sdk-2.4.3}/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.1 → agora_python_server_sdk-2.4.3}/agora/rtc/video_frame_observer.py
RENAMED
|
File without changes
|
{agora_python_server_sdk-2.4.1 → agora_python_server_sdk-2.4.3}/agora/rtc/video_frame_sender.py
RENAMED
|
File without changes
|
{agora_python_server_sdk-2.4.1 → agora_python_server_sdk-2.4.3}/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.1 → agora_python_server_sdk-2.4.3}/agora/rtm/rtm_event_handler.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|