agora-python-server-sdk 2.1.7__tar.gz → 2.2.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.
Files changed (42) hide show
  1. {agora_python_server_sdk-2.1.7 → agora_python_server_sdk-2.2.1}/PKG-INFO +28 -2
  2. agora_python_server_sdk-2.1.7/agora_python_server_sdk.egg-info/PKG-INFO → agora_python_server_sdk-2.2.1/README.md +21 -16
  3. {agora_python_server_sdk-2.1.7 → agora_python_server_sdk-2.2.1}/agora/rtc/__init__.py +14 -4
  4. {agora_python_server_sdk-2.1.7 → agora_python_server_sdk-2.2.1}/agora/rtc/_ctypes_handle/_ctypes_data.py +37 -7
  5. {agora_python_server_sdk-2.1.7 → agora_python_server_sdk-2.2.1}/agora/rtc/_ctypes_handle/_local_user_observer.py +9 -1
  6. {agora_python_server_sdk-2.1.7 → agora_python_server_sdk-2.2.1}/agora/rtc/agora_base.py +17 -0
  7. {agora_python_server_sdk-2.1.7 → agora_python_server_sdk-2.2.1}/agora/rtc/agora_service.py +4 -0
  8. {agora_python_server_sdk-2.1.7 → agora_python_server_sdk-2.2.1}/agora/rtc/local_user.py +18 -0
  9. {agora_python_server_sdk-2.1.7 → agora_python_server_sdk-2.2.1}/agora/rtc/local_user_observer.py +3 -0
  10. {agora_python_server_sdk-2.1.7 → agora_python_server_sdk-2.2.1}/agora/rtc/utils/audio_consumer.py +30 -4
  11. agora_python_server_sdk-2.1.7/README.md → agora_python_server_sdk-2.2.1/agora_python_server_sdk.egg-info/PKG-INFO +42 -1
  12. {agora_python_server_sdk-2.1.7 → agora_python_server_sdk-2.2.1}/setup.py +9 -4
  13. {agora_python_server_sdk-2.1.7 → agora_python_server_sdk-2.2.1}/MANIFEST.in +0 -0
  14. {agora_python_server_sdk-2.1.7 → agora_python_server_sdk-2.2.1}/agora/rtc/_ctypes_handle/_audio_frame_observer.py +0 -0
  15. {agora_python_server_sdk-2.1.7 → agora_python_server_sdk-2.2.1}/agora/rtc/_ctypes_handle/_rtc_connection_observer.py +0 -0
  16. {agora_python_server_sdk-2.1.7 → agora_python_server_sdk-2.2.1}/agora/rtc/_ctypes_handle/_video_encoded_frame_observer.py +0 -0
  17. {agora_python_server_sdk-2.1.7 → agora_python_server_sdk-2.2.1}/agora/rtc/_ctypes_handle/_video_frame_observer.py +0 -0
  18. {agora_python_server_sdk-2.1.7 → agora_python_server_sdk-2.2.1}/agora/rtc/_utils/globals.py +0 -0
  19. {agora_python_server_sdk-2.1.7 → agora_python_server_sdk-2.2.1}/agora/rtc/agora_parameter.py +0 -0
  20. {agora_python_server_sdk-2.1.7 → agora_python_server_sdk-2.2.1}/agora/rtc/audio_encoded_frame_sender.py +0 -0
  21. {agora_python_server_sdk-2.1.7 → agora_python_server_sdk-2.2.1}/agora/rtc/audio_frame_observer.py +0 -0
  22. {agora_python_server_sdk-2.1.7 → agora_python_server_sdk-2.2.1}/agora/rtc/audio_pcm_data_sender.py +0 -0
  23. {agora_python_server_sdk-2.1.7 → agora_python_server_sdk-2.2.1}/agora/rtc/audio_sessionctrl.py +0 -0
  24. {agora_python_server_sdk-2.1.7 → agora_python_server_sdk-2.2.1}/agora/rtc/audio_vad_manager.py +0 -0
  25. {agora_python_server_sdk-2.1.7 → agora_python_server_sdk-2.2.1}/agora/rtc/local_audio_track.py +0 -0
  26. {agora_python_server_sdk-2.1.7 → agora_python_server_sdk-2.2.1}/agora/rtc/local_video_track.py +0 -0
  27. {agora_python_server_sdk-2.1.7 → agora_python_server_sdk-2.2.1}/agora/rtc/media_node_factory.py +0 -0
  28. {agora_python_server_sdk-2.1.7 → agora_python_server_sdk-2.2.1}/agora/rtc/remote_audio_track.py +0 -0
  29. {agora_python_server_sdk-2.1.7 → agora_python_server_sdk-2.2.1}/agora/rtc/remote_video_track.py +0 -0
  30. {agora_python_server_sdk-2.1.7 → agora_python_server_sdk-2.2.1}/agora/rtc/rtc_connection.py +0 -0
  31. {agora_python_server_sdk-2.1.7 → agora_python_server_sdk-2.2.1}/agora/rtc/rtc_connection_observer.py +0 -0
  32. {agora_python_server_sdk-2.1.7 → agora_python_server_sdk-2.2.1}/agora/rtc/utils/vad_dump.py +0 -0
  33. {agora_python_server_sdk-2.1.7 → agora_python_server_sdk-2.2.1}/agora/rtc/video_encoded_frame_observer.py +0 -0
  34. {agora_python_server_sdk-2.1.7 → agora_python_server_sdk-2.2.1}/agora/rtc/video_encoded_image_sender.py +0 -0
  35. {agora_python_server_sdk-2.1.7 → agora_python_server_sdk-2.2.1}/agora/rtc/video_frame_observer.py +0 -0
  36. {agora_python_server_sdk-2.1.7 → agora_python_server_sdk-2.2.1}/agora/rtc/video_frame_sender.py +0 -0
  37. {agora_python_server_sdk-2.1.7 → agora_python_server_sdk-2.2.1}/agora/rtc/voice_detection.py +0 -0
  38. {agora_python_server_sdk-2.1.7 → agora_python_server_sdk-2.2.1}/agora_python_server_sdk.egg-info/SOURCES.txt +0 -0
  39. {agora_python_server_sdk-2.1.7 → agora_python_server_sdk-2.2.1}/agora_python_server_sdk.egg-info/dependency_links.txt +0 -0
  40. {agora_python_server_sdk-2.1.7 → agora_python_server_sdk-2.2.1}/agora_python_server_sdk.egg-info/top_level.txt +0 -0
  41. {agora_python_server_sdk-2.1.7 → agora_python_server_sdk-2.2.1}/pyproject.toml +0 -0
  42. {agora_python_server_sdk-2.1.7 → agora_python_server_sdk-2.2.1}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.2
2
2
  Name: agora_python_server_sdk
3
- Version: 2.1.7
3
+ Version: 2.2.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
@@ -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.
@@ -50,6 +56,26 @@ python agora_rtc/examples/example_audio_pcm_send.py --appId=xxx --channelId=xxx
50
56
  ```
51
57
 
52
58
  # Change log
59
+ 2025.02.26 Release 2.2.1
60
+ --Update:
61
+ ​- Reduced buffer size from ​180ms​ to ​100ms​ to minimize latency.
62
+ -- Added:
63
+ - AudioConsumer::is_push_to_rtc_completed: Add audio consumer support for playback state notifications.
64
+ -- ​Bug fix:
65
+ - Fixed incorrect _samples_per_channel calculation in stereo mode.
66
+
67
+ 2025.01.08 Release 2.2.0
68
+ -- Updates:
69
+ - Update the SDK version from 4.4.30 to 4.4.31. Done.
70
+ -- FEAT:
71
+ - Add serviceconfigure.
72
+ - Add domain_limit. Done.
73
+ - Add should_callback_when_muted. Done.
74
+ - Add colorspacetype to ExternalVideoFrame to support the encoding of solid-color backgrounds in virtual human scenarios. Done.
75
+ -- FEAT:
76
+ - Add the AudioMetaData interface: localuser::send_audio_meta_data. Done.
77
+ - Add the OnAudioMetaDataReceived callback to localuserObserver::on_audio_meta_data_received. Done.
78
+ -- Sample modifications.
53
79
 
54
80
  2024.12.17 Release 2.1.7
55
81
  --Changes:
@@ -1,18 +1,3 @@
1
- Metadata-Version: 2.1
2
- Name: agora_python_server_sdk
3
- Version: 2.1.7
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.
@@ -50,6 +35,26 @@ python agora_rtc/examples/example_audio_pcm_send.py --appId=xxx --channelId=xxx
50
35
  ```
51
36
 
52
37
  # Change log
38
+ 2025.02.26 Release 2.2.1
39
+ --Update:
40
+ ​- Reduced buffer size from ​180ms​ to ​100ms​ to minimize latency.
41
+ -- Added:
42
+ - AudioConsumer::is_push_to_rtc_completed: Add audio consumer support for playback state notifications.
43
+ -- ​Bug fix:
44
+ - Fixed incorrect _samples_per_channel calculation in stereo mode.
45
+
46
+ 2025.01.08 Release 2.2.0
47
+ -- Updates:
48
+ - Update the SDK version from 4.4.30 to 4.4.31. Done.
49
+ -- FEAT:
50
+ - Add serviceconfigure.
51
+ - Add domain_limit. Done.
52
+ - Add should_callback_when_muted. Done.
53
+ - Add colorspacetype to ExternalVideoFrame to support the encoding of solid-color backgrounds in virtual human scenarios. Done.
54
+ -- FEAT:
55
+ - Add the AudioMetaData interface: localuser::send_audio_meta_data. Done.
56
+ - Add the OnAudioMetaDataReceived callback to localuserObserver::on_audio_meta_data_received. Done.
57
+ -- Sample modifications.
53
58
 
54
59
  2024.12.17 Release 2.1.7
55
60
  --Changes:
@@ -322,4 +327,4 @@ VAD: Good afternoon, what are some fun places to visit in Beijing?
322
327
 
323
328
 
324
329
 
325
- 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.
330
+ 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.
@@ -26,13 +26,23 @@ def _check_download_and_extract_sdk():
26
26
  sdk_dir = os.path.join(agora_service_path, "agora_sdk")
27
27
  zip_path = os.path.join(agora_service_path, "agora_rtc_sdk.zip")
28
28
 
29
- url = "https://download.agora.io/sdk/release/agora_rtc_sdk-x86_64-linux-gnu-v4.4.30-20241024_101940-398537.zip"
29
+ #url = "https://download.agora.io/sdk/release/agora_rtc_sdk-x86_64-linux-gnu-v4.4.30-20241024_101940-398537.zip"
30
+ # version 2.2.0 for linux
31
+ url = "https://download.agora.io/sdk/release/agora_rtc_sdk-x86_64-linux-gnu-v4.4.31-20241223_111509-491956.zip"
32
+
33
+
30
34
  libagora_rtc_sdk_path = os.path.join(sdk_dir, "libagora_rtc_sdk.so")
31
- rtc_md5 = "7031dd10d1681cd88fd89d68c5b54282"
35
+ #rtc_md5 = "7031dd10d1681cd88fd89d68c5b54282"
36
+ rtc_md5 = "f2a9e3ed15f872cb7e3b62d1528ac5cb"
32
37
  if sys.platform == 'darwin':
33
- url = "https://download.agora.io/sdk/release/agora_rtc_sdk_mac_rel.v4.4.30_22472_FULL_20241024_1224_398653.zip"
38
+ #url = "https://download.agora.io/sdk/release/agora_rtc_sdk_mac_rel.v4.4.30_22472_FULL_20241024_1224_398653.zip"
39
+ # version 2.2.0 for mac
40
+ url = "https://download.agora.io/sdk/release/agora_sdk_mac_v4.4.31_23136_FULL_20241223_1245_492039.zip"
41
+
34
42
  libagora_rtc_sdk_path = os.path.join(sdk_dir, "libAgoraRtcKit.dylib")
35
- rtc_md5 = "ca3ca14f9e2b7d97eb2594d1f32dab9f"
43
+ #rtc_md5 = "ca3ca14f9e2b7d97eb2594d1f32dab9f"
44
+ rtc_md5 = "6821cae218c8f31f8d720ac0c77edab0"
45
+
36
46
 
37
47
  if os.path.exists(libagora_rtc_sdk_path) and get_file_md5(libagora_rtc_sdk_path) == rtc_md5:
38
48
  return
@@ -718,6 +718,29 @@ class RemoteVideoTrackStatsInner(ctypes.Structure):
718
718
  stats.total_active_time,
719
719
  stats.publish_duration
720
720
  )
721
+
722
+ class ColorSpaceTypeInner(ctypes.Structure):
723
+ _fields_ = [
724
+ ("primaries_id", ctypes.c_int),
725
+ ("transfer_id", ctypes.c_int),
726
+ ("matrix_id", ctypes.c_int),
727
+ ("range_id", ctypes.c_int)
728
+ ]
729
+ def get(self):
730
+ return ColorSpaceType(
731
+ primaries_id=self.primaries_id,
732
+ transfer_id=self.transfer_id,
733
+ matrix_id=self.matrix_id,
734
+ range_id=self.range_id
735
+ )
736
+ @staticmethod
737
+ def create(colorspace:ColorSpaceType) -> 'ColorSpaceTypeInner':
738
+ return ColorSpaceTypeInner(
739
+ primaries_id=colorspace.primaries_id,
740
+ transfer_id=colorspace.transfer_id,
741
+ matrix_id=colorspace.matrix_id,
742
+ range_id=colorspace.range_id
743
+ )
721
744
 
722
745
 
723
746
  class ExternalVideoFrameInner(ctypes.Structure):
@@ -741,7 +764,8 @@ class ExternalVideoFrameInner(ctypes.Structure):
741
764
  ("metadata_size", ctypes.c_int),
742
765
  ("alpha_buffer", ctypes.c_void_p),
743
766
  ("fill_alpha_buffer", ctypes.c_uint8),
744
- ("alpha_mode", ctypes.c_int)
767
+ ("alpha_mode", ctypes.c_int),
768
+ ("color_space", ColorSpaceTypeInner)
745
769
  ]
746
770
 
747
771
  def get(self):
@@ -765,7 +789,8 @@ class ExternalVideoFrameInner(ctypes.Structure):
765
789
  metadata_size=self.metadata_size,
766
790
  alpha_buffer=self.alpha_buffer,
767
791
  fill_alpha_buffer=self.fill_alpha_buffer,
768
- alpha_mode=self.alpha_mode
792
+ alpha_mode=self.alpha_mode,
793
+ color_space=self.color_space.get()
769
794
  )
770
795
 
771
796
  @staticmethod
@@ -784,12 +809,13 @@ class ExternalVideoFrameInner(ctypes.Structure):
784
809
  else:
785
810
  c_alpha_buffer_ptr = ctypes.c_void_p(0)
786
811
 
787
- c_metadata_size = len (frame.metadata)
812
+ c_metadata_size = len (frame.metadata) if frame.metadata is not None else 0
788
813
  if frame.metadata is not None and c_metadata_size > 0:
789
814
  c_metadata_ptr = (ctypes.c_uint8 * len(frame.metadata)).from_buffer(frame.metadata)
790
815
  c_metadata_size = len(frame.metadata)
791
816
  else:
792
- c_metadata_ptr = ctypes.c_void_p(0)
817
+ #c_metadata_ptr = ctypes.c_void_p(0)
818
+ c_metadata_ptr = ctypes.POINTER(ctypes.c_uint8)()
793
819
  c_metadata_size = 0
794
820
 
795
821
 
@@ -815,7 +841,8 @@ class ExternalVideoFrameInner(ctypes.Structure):
815
841
  c_metadata_size,
816
842
  c_alpha_buffer_ptr,
817
843
  frame.fill_alpha_buffer,
818
- frame.alpha_mode
844
+ frame.alpha_mode,
845
+ ColorSpaceTypeInner.create(frame.color_space)
819
846
  )
820
847
 
821
848
 
@@ -1105,6 +1132,7 @@ class AgoraServiceConfigInner(ctypes.Structure):
1105
1132
  ('audio_scenario', ctypes.c_int),
1106
1133
 
1107
1134
  ('use_string_uid', ctypes.c_int),
1135
+ ('domain_limit', ctypes.c_int),
1108
1136
  ]
1109
1137
 
1110
1138
  def get(self):
@@ -1117,7 +1145,8 @@ class AgoraServiceConfigInner(ctypes.Structure):
1117
1145
  area_code=self.area_code,
1118
1146
  channel_profile=self.channel_profile,
1119
1147
  audio_scenario=self.audio_scenario,
1120
- use_string_uid=self.use_string_uid
1148
+ use_string_uid=self.use_string_uid,
1149
+ domain_limit=self.domain_limit
1121
1150
  )
1122
1151
 
1123
1152
  @staticmethod
@@ -1131,7 +1160,8 @@ class AgoraServiceConfigInner(ctypes.Structure):
1131
1160
  config.area_code,
1132
1161
  config.channel_profile,
1133
1162
  config.audio_scenario,
1134
- config.use_string_uid
1163
+ config.use_string_uid,
1164
+ config.domain_limit
1135
1165
  )
1136
1166
 
1137
1167
 
@@ -44,6 +44,7 @@ ON_INTRA_REQUEST_RECEIVED_CALLBACK = ctypes.CFUNCTYPE(None, AGORA_HANDLE)
44
44
  ON_REMOTE_SUBSCRIBE_FALLBACK_TO_AUDIO_ONLY_CALLBACK = ctypes.CFUNCTYPE(None, AGORA_HANDLE, user_id_t, ctypes.c_int)
45
45
  ON_STREAM_MESSAGE_CALLBACK = ctypes.CFUNCTYPE(None, AGORA_HANDLE, user_id_t, ctypes.c_int, ctypes.c_char_p, ctypes.c_size_t)
46
46
  ON_USER_STATE_CHANGED_CALLBACK = ctypes.CFUNCTYPE(None, AGORA_HANDLE, user_id_t, ctypes.c_uint32)
47
+ ON_AUDIO_META_DATA_RECEIVED_CALLBACK = ctypes.CFUNCTYPE(None, AGORA_HANDLE, user_id_t, ctypes.c_char_p, ctypes.c_size_t)
47
48
 
48
49
 
49
50
  class RTCLocalUserObserverInner(ctypes.Structure):
@@ -85,7 +86,8 @@ class RTCLocalUserObserverInner(ctypes.Structure):
85
86
  ("on_intra_request_received", ON_INTRA_REQUEST_RECEIVED_CALLBACK),
86
87
  ("on_remote_subscribe_fallback_to_audio_only", ON_REMOTE_SUBSCRIBE_FALLBACK_TO_AUDIO_ONLY_CALLBACK),
87
88
  ("on_stream_message", ON_STREAM_MESSAGE_CALLBACK),
88
- ("on_user_state_changed", ON_USER_STATE_CHANGED_CALLBACK)
89
+ ("on_user_state_changed", ON_USER_STATE_CHANGED_CALLBACK),
90
+ ("on_audio_meta_data_received", ON_AUDIO_META_DATA_RECEIVED_CALLBACK)
89
91
  ]
90
92
 
91
93
  def __init__(self, local_user_observer: IRTCLocalUserObserver, local_user: 'LocalUser') -> None:
@@ -128,6 +130,7 @@ class RTCLocalUserObserverInner(ctypes.Structure):
128
130
  self.on_remote_subscribe_fallback_to_audio_only = ON_REMOTE_SUBSCRIBE_FALLBACK_TO_AUDIO_ONLY_CALLBACK(self._on_remote_subscribe_fallback_to_audio_only)
129
131
  self.on_stream_message = ON_STREAM_MESSAGE_CALLBACK(self._on_stream_message)
130
132
  self.on_user_state_changed = ON_USER_STATE_CHANGED_CALLBACK(self._on_user_state_changed)
133
+ self.on_audio_meta_data_received = ON_AUDIO_META_DATA_RECEIVED_CALLBACK(self._on_audio_meta_data_received)
131
134
 
132
135
  """
133
136
  it seems that this interface does not provide much value to the user's business,
@@ -348,3 +351,8 @@ class RTCLocalUserObserverInner(ctypes.Structure):
348
351
  logger.debug(f"LocalUserCB _on_user_state_changed: {local_user_handle}, {user_id}, {state}")
349
352
  user_id_str = user_id.decode('utf-8') if user_id else ""
350
353
  self.local_user_observer.on_user_state_changed(self.local_user, user_id_str, state)
354
+ def _on_audio_meta_data_received(self, local_user_handle, user_id, audio_meta_data, size):
355
+ user_id_str = user_id.decode('utf-8') if user_id else ""
356
+ bytes_from_c = bytearray(ctypes.string_at(audio_meta_data, size))
357
+
358
+ self.local_user_observer.on_audio_meta_data_received(self.local_user, user_id_str, bytes_from_c)
@@ -307,6 +307,15 @@ class AgoraServiceConfig:
307
307
  channel_profile: ChannelProfileType = ChannelProfileType.CHANNEL_PROFILE_LIVE_BROADCASTING
308
308
  audio_scenario: AudioScenarioType = AudioScenarioType.AUDIO_SCENARIO_CHORUS
309
309
  use_string_uid: int = 0
310
+ #version 2.2.0
311
+ # default to 0
312
+ domain_limit: int = 0
313
+ '''
314
+ // if >0, when remote user muted itself, the onplaybackbeforemixing will be still called badk with active pacakage
315
+ // if <=0, when remote user muted itself, the onplaybackbeforemixing will be no longer called back
316
+ // default to 0, i.e when muted, no callback will be triggered
317
+ '''
318
+ should_callbck_when_muted: int = 0
310
319
 
311
320
 
312
321
  @dataclass(kw_only=True)
@@ -423,6 +432,13 @@ class VideoEncoderConfiguration:
423
432
  mirror_mode: int = 0
424
433
  encode_alpha: int = 0
425
434
 
435
+ @dataclass(kw_only=True)
436
+ class ColorSpaceType:
437
+ primaries_id: int = 0
438
+ transfer_id: int = 0
439
+ matrix_id: int = 0
440
+ range_id: int = 0
441
+
426
442
 
427
443
  @dataclass(kw_only=True)
428
444
  class ExternalVideoFrame:
@@ -445,6 +461,7 @@ class ExternalVideoFrame:
445
461
  alpha_buffer: bytearray = None
446
462
  fill_alpha_buffer: int = 0
447
463
  alpha_mode: int = 0
464
+ color_space: ColorSpaceType = field(default_factory=ColorSpaceType)
448
465
 
449
466
 
450
467
  @dataclass(kw_only=True)
@@ -92,6 +92,10 @@ class AgoraService:
92
92
  # force audio vad v2 to be enabled
93
93
  agora_parameter.set_parameters("{\"che.audio.label.enable\": true}")
94
94
 
95
+ #versio 2.2.0 for callback when muted
96
+ if config.should_callbck_when_muted > 0:
97
+ agora_parameter.set_parameters("{\"rtc.audio.enable_user_silence_packet\": true}")
98
+
95
99
  if config.log_path:
96
100
  log_size = 512 * 1024
97
101
  if config.log_size > 0:
@@ -223,6 +223,15 @@ agora_local_user_set_audio_scenario = agora_lib.agora_local_user_set_audio_scena
223
223
  agora_local_user_set_audio_scenario.restype = AGORA_API_C_INT
224
224
  agora_local_user_set_audio_scenario.argtypes = [AGORA_HANDLE, ctypes.c_int]
225
225
 
226
+ #verison 2.2.0
227
+
228
+ #AGORA_API_C_INT agora_local_user_send_audio_meta_data(AGORA_HANDLE agora_local_user, const char* meta_data, size_t length);
229
+ agora_local_user_send_aduio_meta_data = agora_lib.agora_local_user_send_audio_meta_data
230
+ agora_local_user_send_aduio_meta_data.restype = AGORA_API_C_INT
231
+ agora_local_user_send_aduio_meta_data.argtypes = [AGORA_HANDLE, ctypes.c_char_p, ctypes.c_size_t]
232
+
233
+
234
+
226
235
 
227
236
  class LocalUser:
228
237
  def __init__(self, local_user_handle, connection):
@@ -594,3 +603,12 @@ class LocalUser:
594
603
  def set_audio_scenario(self, scenario_type: AudioScenarioType):
595
604
  ret = agora_local_user_set_audio_scenario(self.user_handle, scenario_type.value)
596
605
  return ret
606
+ # data can be str or bytes/bytearray object,is diff to send_sream_message which is a str object
607
+ def send_audio_meta_data(self, data):
608
+ # chang to ctypes.c_char_p
609
+ if isinstance(data, str):
610
+ data = data.encode('utf-8')
611
+ c_data = ctypes.create_string_buffer(bytes(data))
612
+ size = len(data)
613
+ ret = agora_local_user_send_aduio_meta_data(self.user_handle, c_data, ctypes.c_size_t(size))
614
+ return ret
@@ -117,3 +117,6 @@ class IRTCLocalUserObserver():
117
117
 
118
118
  def on_user_state_changed(self, agora_local_user, user_id, state):
119
119
  pass
120
+ # data is bytearray object, is diff to on_stream_msg which is str object
121
+ def on_audio_meta_data_received(self, agora_local_user, user_id, data):
122
+ pass
@@ -31,6 +31,8 @@ AudioConsumer调用方式:
31
31
  E 退出的时候,调用release()方法,释放资源
32
32
  """
33
33
  class AudioConsumer:
34
+ MIN_BUFFER_SIZE = 10
35
+ RTC_E2E_DELAY = 200 # e2e delay 90ms for iphone, 120ms for android;150ms for web. so we use 200ms here
34
36
  def __init__(self, pcm_sender: AudioPcmDataSender, sample_rate: int, channels: int) -> None:
35
37
  self._lock = threading.Lock()
36
38
  self._start_time = 0
@@ -45,11 +47,12 @@ class AudioConsumer:
45
47
  #audio parame
46
48
  self._frame.bytes_per_sample = 2
47
49
  self._bytes_per_frame = sample_rate // 100 * channels * 2
48
- self._samples_per_channel = sample_rate // 100* channels
50
+ self._samples_per_channel = sample_rate // 100
49
51
  #init pcmaudioframe
50
52
  self._frame.timestamp = 0
51
53
 
52
54
  self._init = True
55
+ self._last_consume_time = 0
53
56
 
54
57
  pass
55
58
  def push_pcm_data(self, data) ->None:
@@ -64,6 +67,7 @@ class AudioConsumer:
64
67
  return
65
68
  self._start_time = time.time()*1000
66
69
  self._consumed_packages = 0
70
+ self._last_consume_time = self._start_time
67
71
  pass
68
72
 
69
73
  def consume(self):
@@ -75,13 +79,16 @@ class AudioConsumer:
75
79
  expected_total_packages = int(elapsed_time//10)
76
80
  besent_packages = expected_total_packages - self._consumed_packages
77
81
  data_len = len(self._data)
82
+ #if data is not empty, to update last consume time
83
+ if data_len > 0:
84
+ self._last_consume_time = now
78
85
 
79
- if besent_packages > 18 and data_len //self._bytes_per_frame < 18: #for fist time, if data_len is not enough, just return and wait for next time
86
+ if besent_packages > AudioConsumer.MIN_BUFFER_SIZE and data_len //self._bytes_per_frame < AudioConsumer.MIN_BUFFER_SIZE: #for fist time, if data_len is not enough, just return and wait for next time
80
87
  #print("-----underflow data")
81
88
  return -2
82
- if besent_packages > 18: #rest to start state, push 18 packs in Start_STATE
89
+ if besent_packages > AudioConsumer.MIN_BUFFER_SIZE: #rest to start state, push 18 packs in Start_STATE
83
90
  self._reset()
84
- besent_packages = min(18, data_len//self._bytes_per_frame)
91
+ besent_packages = min(AudioConsumer.MIN_BUFFER_SIZE, data_len//self._bytes_per_frame)
85
92
  self._consumed_packages = -besent_packages
86
93
 
87
94
 
@@ -113,6 +120,25 @@ class AudioConsumer:
113
120
  return 0
114
121
  with self._lock:
115
122
  return len(self._data)
123
+
124
+ #判断AudioConsumer中的数据是否已经完全推送给了RTC 频道
125
+ #因为audioconsumer内部有一定的缓存机制,所以当get_remaining_data_size 返回是0的时候,还有数据没有推送给
126
+ #rtc 频道。如果要判断数据是否完全推送给了rtc 频道,需要调用这个api来做判断。
127
+ #return value:1--push to rtc completed, 0--push to rtc not completed -1--error
128
+ def is_push_to_rtc_completed(self)->int:
129
+ if self._init == False:
130
+ return -1
131
+ with self._lock:
132
+ remain_size = len(self._data)
133
+ if remain_size == 0:
134
+ now = time.time()*1000
135
+ diff = now - self._last_consume_time
136
+
137
+ if diff > AudioConsumer.MIN_BUFFER_SIZE*10 + AudioConsumer.RTC_E2E_DELAY:
138
+ return 1
139
+
140
+ return 0
141
+ pass
116
142
  def clear(self):
117
143
  if self._init == False:
118
144
  return
@@ -1,3 +1,24 @@
1
+ Metadata-Version: 2.2
2
+ Name: agora_python_server_sdk
3
+ Version: 2.2.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
+ 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.
@@ -35,6 +56,26 @@ python agora_rtc/examples/example_audio_pcm_send.py --appId=xxx --channelId=xxx
35
56
  ```
36
57
 
37
58
  # Change log
59
+ 2025.02.26 Release 2.2.1
60
+ --Update:
61
+ ​- Reduced buffer size from ​180ms​ to ​100ms​ to minimize latency.
62
+ -- Added:
63
+ - AudioConsumer::is_push_to_rtc_completed: Add audio consumer support for playback state notifications.
64
+ -- ​Bug fix:
65
+ - Fixed incorrect _samples_per_channel calculation in stereo mode.
66
+
67
+ 2025.01.08 Release 2.2.0
68
+ -- Updates:
69
+ - Update the SDK version from 4.4.30 to 4.4.31. Done.
70
+ -- FEAT:
71
+ - Add serviceconfigure.
72
+ - Add domain_limit. Done.
73
+ - Add should_callback_when_muted. Done.
74
+ - Add colorspacetype to ExternalVideoFrame to support the encoding of solid-color backgrounds in virtual human scenarios. Done.
75
+ -- FEAT:
76
+ - Add the AudioMetaData interface: localuser::send_audio_meta_data. Done.
77
+ - Add the OnAudioMetaDataReceived callback to localuserObserver::on_audio_meta_data_received. Done.
78
+ -- Sample modifications.
38
79
 
39
80
  2024.12.17 Release 2.1.7
40
81
  --Changes:
@@ -307,4 +348,4 @@ VAD: Good afternoon, what are some fun places to visit in Beijing?
307
348
 
308
349
 
309
350
 
310
- 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.
351
+ 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.
@@ -20,10 +20,15 @@ class CustomInstallCommand(install):
20
20
  agora_service_path = os.path.join(site.getsitepackages()[0], 'agora', 'rtc')
21
21
  sdk_dir = os.path.join(agora_service_path, "agora_sdk")
22
22
  zip_path = os.path.join(agora_service_path, "agora_rtc_sdk.zip")
23
-
24
- url = "https://download.agora.io/sdk/release/agora_rtc_sdk-x86_64-linux-gnu-v4.4.30-20241024_101940-398537.zip"
23
+ '''# version before 2.2.0
24
+ #url = "https://download.agora.io/sdk/release/agora_rtc_sdk-x86_64-linux-gnu-v4.4.30-20241024_101940-398537.zip"
25
+ #url = "https://download.agora.io/sdk/release/agora_rtc_sdk_mac_rel.v4.4.30_22472_FULL_20241024_1224_398653.zip"
26
+ '''
27
+ # verison 2.2.0
28
+ url = "https://download.agora.io/sdk/release/agora_rtc_sdk-x86_64-linux-gnu-v4.4.31-20241223_111509-491956.zip"
25
29
  if sys.platform == 'darwin':
26
- url = "https://download.agora.io/sdk/release/agora_rtc_sdk_mac_rel.v4.4.30_22472_FULL_20241024_1224_398653.zip"
30
+ url = "https://download.agora.io/sdk/release/agora_sdk_mac_v4.4.31_23136_FULL_20241223_1245_492039.zip"
31
+
27
32
 
28
33
  if os.path.exists(sdk_dir):
29
34
  os.system(f"rm -rf {sdk_dir}")
@@ -45,7 +50,7 @@ class CustomInstallCommand(install):
45
50
 
46
51
  setup(
47
52
  name='agora_python_server_sdk',
48
- version='2.1.7',
53
+ version='2.2.1',
49
54
  description='A Python SDK for Agora Server',
50
55
  long_description=open('README.md').read(),
51
56
  long_description_content_type='text/markdown',