agora-python-server-sdk 2.0.3__tar.gz → 2.0.4__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.0.4/PKG-INFO +53 -0
- agora_python_server_sdk-2.0.4/README.md +36 -0
- {agora_python_server_sdk-2.0.3 → agora_python_server_sdk-2.0.4}/agora/rtc/__init__.py +3 -3
- {agora_python_server_sdk-2.0.3 → agora_python_server_sdk-2.0.4}/agora/rtc/_audio_frame_observer.py +17 -31
- {agora_python_server_sdk-2.0.3 → agora_python_server_sdk-2.0.4}/agora/rtc/_local_user_observer.py +1 -51
- {agora_python_server_sdk-2.0.3 → agora_python_server_sdk-2.0.4}/agora/rtc/_rtc_connection_observer.py +5 -62
- {agora_python_server_sdk-2.0.3 → agora_python_server_sdk-2.0.4}/agora/rtc/_video_encoded_frame_observer.py +0 -6
- {agora_python_server_sdk-2.0.3 → agora_python_server_sdk-2.0.4}/agora/rtc/_video_frame_observer.py +6 -25
- {agora_python_server_sdk-2.0.3 → agora_python_server_sdk-2.0.4}/agora/rtc/agora_base.py +5 -0
- {agora_python_server_sdk-2.0.3 → agora_python_server_sdk-2.0.4}/agora/rtc/agora_service.py +19 -3
- {agora_python_server_sdk-2.0.3 → agora_python_server_sdk-2.0.4}/agora/rtc/audio_encoded_frame_sender.py +3 -20
- agora_python_server_sdk-2.0.4/agora/rtc/audio_frame_observer.py +32 -0
- {agora_python_server_sdk-2.0.3 → agora_python_server_sdk-2.0.4}/agora/rtc/audio_vad.py +1 -2
- {agora_python_server_sdk-2.0.3 → agora_python_server_sdk-2.0.4}/agora/rtc/globals.py +4 -4
- {agora_python_server_sdk-2.0.3 → agora_python_server_sdk-2.0.4}/agora/rtc/local_audio_track.py +11 -23
- {agora_python_server_sdk-2.0.3 → agora_python_server_sdk-2.0.4}/agora/rtc/local_user.py +11 -84
- {agora_python_server_sdk-2.0.3 → agora_python_server_sdk-2.0.4}/agora/rtc/local_user_observer.py +1 -1
- {agora_python_server_sdk-2.0.3 → agora_python_server_sdk-2.0.4}/agora/rtc/local_video_track.py +0 -6
- {agora_python_server_sdk-2.0.3 → agora_python_server_sdk-2.0.4}/agora/rtc/media_node_factory.py +5 -5
- {agora_python_server_sdk-2.0.3 → agora_python_server_sdk-2.0.4}/agora/rtc/remote_video_track.py +3 -12
- {agora_python_server_sdk-2.0.3 → agora_python_server_sdk-2.0.4}/agora/rtc/rtc_connection.py +11 -25
- {agora_python_server_sdk-2.0.3 → agora_python_server_sdk-2.0.4}/agora/rtc/rtc_connection_observer.py +0 -10
- {agora_python_server_sdk-2.0.3 → agora_python_server_sdk-2.0.4}/agora/rtc/video_encoded_frame_observer.py +0 -1
- agora_python_server_sdk-2.0.4/agora/rtc/video_encoded_image_sender.py +87 -0
- {agora_python_server_sdk-2.0.3 → agora_python_server_sdk-2.0.4}/agora/rtc/video_frame_observer.py +3 -0
- agora_python_server_sdk-2.0.4/agora/rtc/video_frame_sender.py +92 -0
- agora_python_server_sdk-2.0.4/agora_python_server_sdk.egg-info/PKG-INFO +53 -0
- {agora_python_server_sdk-2.0.3 → agora_python_server_sdk-2.0.4}/agora_python_server_sdk.egg-info/SOURCES.txt +1 -0
- {agora_python_server_sdk-2.0.3 → agora_python_server_sdk-2.0.4}/setup.py +3 -3
- agora_python_server_sdk-2.0.3/PKG-INFO +0 -76
- agora_python_server_sdk-2.0.3/README.md +0 -59
- agora_python_server_sdk-2.0.3/agora/rtc/audio_frame_observer.py +0 -50
- agora_python_server_sdk-2.0.3/agora/rtc/video_frame_sender.py +0 -200
- agora_python_server_sdk-2.0.3/agora_python_server_sdk.egg-info/PKG-INFO +0 -76
- {agora_python_server_sdk-2.0.3 → agora_python_server_sdk-2.0.4}/MANIFEST.in +0 -0
- {agora_python_server_sdk-2.0.3 → agora_python_server_sdk-2.0.4}/agora/rtc/agora_parameter.py +0 -0
- {agora_python_server_sdk-2.0.3 → agora_python_server_sdk-2.0.4}/agora/rtc/audio_pcm_data_sender.py +0 -0
- {agora_python_server_sdk-2.0.3 → agora_python_server_sdk-2.0.4}/agora/rtc/remote_audio_track.py +0 -0
- {agora_python_server_sdk-2.0.3 → agora_python_server_sdk-2.0.4}/agora_python_server_sdk.egg-info/dependency_links.txt +0 -0
- {agora_python_server_sdk-2.0.3 → agora_python_server_sdk-2.0.4}/agora_python_server_sdk.egg-info/top_level.txt +0 -0
- {agora_python_server_sdk-2.0.3 → agora_python_server_sdk-2.0.4}/pyproject.toml +0 -0
- {agora_python_server_sdk-2.0.3 → agora_python_server_sdk-2.0.4}/setup.cfg +0 -0
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: agora_python_server_sdk
|
|
3
|
+
Version: 2.0.4
|
|
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
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
14
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
15
|
+
Requires-Python: >=3.8
|
|
16
|
+
Description-Content-Type: text/markdown
|
|
17
|
+
|
|
18
|
+
# Note
|
|
19
|
+
- This is a Python SDK wrapper for the Agora RTC SDK.
|
|
20
|
+
- It supports Linux and Mac platforms.
|
|
21
|
+
- The examples are provided as very simple demonstrations and are not recommended for use in production environments.
|
|
22
|
+
|
|
23
|
+
# Very Important Notice !!!
|
|
24
|
+
- A process can only have one instance.
|
|
25
|
+
- An instance can have multiple connections.
|
|
26
|
+
- 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.
|
|
27
|
+
|
|
28
|
+
# Required Operating Systems and Python Versions
|
|
29
|
+
- Supported Linux versions:
|
|
30
|
+
- Ubuntu 18.04 LTS and above
|
|
31
|
+
- CentOS 7.0 and above
|
|
32
|
+
|
|
33
|
+
- Supported Mac versions:
|
|
34
|
+
- MacOS 13 and above
|
|
35
|
+
|
|
36
|
+
- Python version:
|
|
37
|
+
- Python 3.8 and above
|
|
38
|
+
|
|
39
|
+
# Using Agora-Python-Server-SDK
|
|
40
|
+
```
|
|
41
|
+
pip install agora_python_server_sdk
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
# Running Examples
|
|
45
|
+
|
|
46
|
+
## Preparing Test Data
|
|
47
|
+
- Download and unzip [test_data.zip](https://download.agora.io/demo/test/test_data_202408221437.zip) to the Agora-Python-Server-SDK directory.
|
|
48
|
+
|
|
49
|
+
## Executing Test Script
|
|
50
|
+
```
|
|
51
|
+
python agora_rtc/examples/example_audio_pcm_send.py --appId=xxx --channelId=xxx --userId=xxx --audioFile=./test_data/demo.pcm --sampleRate=16000 --numOfChannels=1
|
|
52
|
+
```
|
|
53
|
+
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Note
|
|
2
|
+
- This is a Python SDK wrapper for the Agora RTC SDK.
|
|
3
|
+
- It supports Linux and Mac platforms.
|
|
4
|
+
- The examples are provided as very simple demonstrations and are not recommended for use in production environments.
|
|
5
|
+
|
|
6
|
+
# Very Important Notice !!!
|
|
7
|
+
- A process can only have one instance.
|
|
8
|
+
- An instance can have multiple connections.
|
|
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
|
+
|
|
11
|
+
# Required Operating Systems and Python Versions
|
|
12
|
+
- Supported Linux versions:
|
|
13
|
+
- Ubuntu 18.04 LTS and above
|
|
14
|
+
- CentOS 7.0 and above
|
|
15
|
+
|
|
16
|
+
- Supported Mac versions:
|
|
17
|
+
- MacOS 13 and above
|
|
18
|
+
|
|
19
|
+
- Python version:
|
|
20
|
+
- Python 3.8 and above
|
|
21
|
+
|
|
22
|
+
# Using Agora-Python-Server-SDK
|
|
23
|
+
```
|
|
24
|
+
pip install agora_python_server_sdk
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
# Running Examples
|
|
28
|
+
|
|
29
|
+
## Preparing Test Data
|
|
30
|
+
- Download and unzip [test_data.zip](https://download.agora.io/demo/test/test_data_202408221437.zip) to the Agora-Python-Server-SDK directory.
|
|
31
|
+
|
|
32
|
+
## Executing Test Script
|
|
33
|
+
```
|
|
34
|
+
python agora_rtc/examples/example_audio_pcm_send.py --appId=xxx --channelId=xxx --userId=xxx --audioFile=./test_data/demo.pcm --sampleRate=16000 --numOfChannels=1
|
|
35
|
+
```
|
|
36
|
+
|
|
@@ -16,16 +16,16 @@ def _check_download_and_extract_sdk():
|
|
|
16
16
|
sdk_dir = os.path.join(agora_service_path, "agora_sdk")
|
|
17
17
|
zip_path = os.path.join(agora_service_path, "agora_rtc_sdk.zip")
|
|
18
18
|
|
|
19
|
-
url = "https://download.agora.io/sdk/release/agora_rtc_sdk_linux_v4.
|
|
19
|
+
url = "https://download.agora.io/sdk/release/agora_rtc_sdk_linux_v4.4.30-20240928_160128-358664.zip"
|
|
20
20
|
libagora_rtc_sdk_path = os.path.join(sdk_dir, "libagora_rtc_sdk.so")
|
|
21
21
|
if sys.platform == 'darwin':
|
|
22
|
-
url = "https://download.agora.io/sdk/release/
|
|
22
|
+
url = "https://download.agora.io/sdk/release/agora_sdk_mac_v4.4.30_22119_FULL_20240928_1647_358680.zip"
|
|
23
23
|
libagora_rtc_sdk_path = os.path.join(sdk_dir, "libAgoraRtcKit.dylib")
|
|
24
24
|
|
|
25
25
|
if os.path.exists(libagora_rtc_sdk_path):
|
|
26
26
|
return
|
|
27
27
|
|
|
28
|
-
logger.error("agora sdk
|
|
28
|
+
logger.error("missing agora sdk, now download it, please wait for a while...")
|
|
29
29
|
if os.path.exists(sdk_dir):
|
|
30
30
|
os.system(f"rm -rf {sdk_dir}")
|
|
31
31
|
os.makedirs(agora_service_path, exist_ok=True)
|
{agora_python_server_sdk-2.0.3 → agora_python_server_sdk-2.0.4}/agora/rtc/_audio_frame_observer.py
RENAMED
|
@@ -16,7 +16,12 @@ class AudioFrameInner(ctypes.Structure):
|
|
|
16
16
|
("samples_per_sec", ctypes.c_int),
|
|
17
17
|
("buffer", ctypes.c_void_p),
|
|
18
18
|
("render_time_ms", ctypes.c_int64),
|
|
19
|
-
("avsync_type", ctypes.c_int)
|
|
19
|
+
("avsync_type", ctypes.c_int),
|
|
20
|
+
("far_field_flag", ctypes.c_int),
|
|
21
|
+
("rms", ctypes.c_int),
|
|
22
|
+
("voice_prob", ctypes.c_int),
|
|
23
|
+
("music_prob", ctypes.c_int),
|
|
24
|
+
("pitch", ctypes.c_int)
|
|
20
25
|
]
|
|
21
26
|
def _to_audio_frame(self):
|
|
22
27
|
audio_frame = AudioFrame()
|
|
@@ -29,6 +34,12 @@ class AudioFrameInner(ctypes.Structure):
|
|
|
29
34
|
audio_frame.buffer = bytearray(cdata)
|
|
30
35
|
audio_frame.render_time_ms = self.render_time_ms
|
|
31
36
|
audio_frame.avsync_type = self.avsync_type
|
|
37
|
+
audio_frame.far_field_flag = self.far_field_flag
|
|
38
|
+
audio_frame.rms = self.rms
|
|
39
|
+
audio_frame.voice_prob = self.voice_prob
|
|
40
|
+
audio_frame.music_prob = self.music_prob
|
|
41
|
+
audio_frame.pitch = self.pitch
|
|
42
|
+
|
|
32
43
|
return audio_frame
|
|
33
44
|
|
|
34
45
|
|
|
@@ -99,7 +110,7 @@ class AudioFrameObserverInner(ctypes.Structure):
|
|
|
99
110
|
return ret
|
|
100
111
|
|
|
101
112
|
def _on_playback_audio_frame_before_mixing(self, local_user_handle, channel_id, user_id, audio_frame_inner):
|
|
102
|
-
logger.debug(f"AudioFrameObserverInner _on_playback_audio_frame_before_mixing: {local_user_handle}, {channel_id}, {user_id}, {audio_frame_inner}")
|
|
113
|
+
#logger.debug(f"AudioFrameObserverInner _on_playback_audio_frame_before_mixing: {local_user_handle}, {channel_id}, {user_id}, {audio_frame_inner}")
|
|
103
114
|
if channel_id is None:
|
|
104
115
|
channel_id_str = ""
|
|
105
116
|
else:
|
|
@@ -112,46 +123,21 @@ class AudioFrameObserverInner(ctypes.Structure):
|
|
|
112
123
|
|
|
113
124
|
def _on_get_audio_frame_position(self, local_user_handle):
|
|
114
125
|
logger.debug(f"AudioFrameObserverInner _on_get_audio_frame_position: {local_user_handle}")
|
|
115
|
-
return 0
|
|
116
126
|
return self.observer.on_get_audio_frame_position(self.local_user)
|
|
117
127
|
|
|
118
|
-
def _on_get_playback_audio_frame_param(self, local_user_handle):
|
|
128
|
+
def _on_get_playback_audio_frame_param(self, local_user_handle) -> AudioParams:
|
|
119
129
|
logger.debug(f"AudioFrameObserverInner _on_get_playback_audio_frame_param: {local_user_handle}")
|
|
120
|
-
params = AudioParams()
|
|
121
|
-
params.sample_rate = 16000 # 示例值
|
|
122
|
-
params.channels = 1 # 示例值
|
|
123
|
-
params.mode = 0 # 示例值
|
|
124
|
-
params.samples_per_call = 1024 # 示例值
|
|
125
|
-
return params
|
|
126
130
|
return self.observer.on_get_playback_audio_frame_param(self.local_user)
|
|
127
131
|
|
|
128
|
-
def _on_get_record_audio_frame_param(self, local_user_handle):
|
|
132
|
+
def _on_get_record_audio_frame_param(self, local_user_handle) -> AudioParams:
|
|
129
133
|
logger.debug(f"AudioFrameObserverInner _on_get_record_audio_frame_param: {local_user_handle}")
|
|
130
|
-
params = AudioParams()
|
|
131
|
-
params.sample_rate = 16000 # 示例值
|
|
132
|
-
params.channels = 1 # 示例值
|
|
133
|
-
params.mode = 0 # 示例值
|
|
134
|
-
params.samples_per_call = 1024 # 示例值
|
|
135
|
-
return params
|
|
136
134
|
return self.observer.on_get_record_audio_frame_param(self.local_user)
|
|
137
135
|
|
|
138
|
-
def _on_get_mixed_audio_frame_param(self, local_user_handle):
|
|
136
|
+
def _on_get_mixed_audio_frame_param(self, local_user_handle) -> AudioParams:
|
|
139
137
|
logger.debug(f"AudioFrameObserverInner _on_get_mixed_audio_frame_param: {local_user_handle}")
|
|
140
|
-
params = AudioParams()
|
|
141
|
-
params.sample_rate = 16000 # 示例值
|
|
142
|
-
params.channels = 1 # 示例值
|
|
143
|
-
params.mode = 0 # 示例值
|
|
144
|
-
params.samples_per_call = 1024 # 示例值
|
|
145
|
-
return params
|
|
146
138
|
return self.observer.on_get_mixed_audio_frame_param(self.local_user)
|
|
147
139
|
|
|
148
|
-
def _on_get_ear_monitoring_audio_frame_param(self, local_user_handle):
|
|
140
|
+
def _on_get_ear_monitoring_audio_frame_param(self, local_user_handle) -> AudioParams:
|
|
149
141
|
logger.debug(f"AudioFrameObserverInner _on_get_ear_monitoring_audio_frame_param: {local_user_handle}")
|
|
150
|
-
params = AudioParams()
|
|
151
|
-
params.sample_rate = 16000 # 示例值
|
|
152
|
-
params.channels = 1 # 示例值
|
|
153
|
-
params.mode = 0 # 示例值
|
|
154
|
-
params.samples_per_call = 1024 # 示例值
|
|
155
|
-
return params
|
|
156
142
|
return self.observer.on_get_ear_monitoring_audio_frame_param(self.local_user)
|
|
157
143
|
|
{agora_python_server_sdk-2.0.3 → agora_python_server_sdk-2.0.4}/agora/rtc/_local_user_observer.py
RENAMED
|
@@ -6,14 +6,6 @@ from .remote_video_track import RemoteVideoTrack, RemoteVideoTrackStats
|
|
|
6
6
|
import logging
|
|
7
7
|
logger = logging.getLogger(__name__)
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
uid_t = ctypes.c_uint
|
|
11
|
-
track_id_t = ctypes.c_uint
|
|
12
|
-
|
|
13
|
-
#========localuser observer=====
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
9
|
class VideoTrackInfoInner(ctypes.Structure):
|
|
18
10
|
_fields_ = [
|
|
19
11
|
("is_local", ctypes.c_int),
|
|
@@ -56,7 +48,6 @@ class RemoteVideoStreamInfo(ctypes.Structure):
|
|
|
56
48
|
("total_downscale_level_counts", ctypes.c_uint8)
|
|
57
49
|
]
|
|
58
50
|
|
|
59
|
-
# 定义回调函数类型
|
|
60
51
|
ON_AUDIO_TRACK_PUBLISH_SUCCESS_CALLBACK = ctypes.CFUNCTYPE(None, AGORA_HANDLE, AGORA_HANDLE)
|
|
61
52
|
ON_AUDIO_TRACK_PUBLISH_START_CALLBACK = ctypes.CFUNCTYPE(None, AGORA_HANDLE, AGORA_HANDLE)
|
|
62
53
|
ON_AUDIO_TRACK_UNPUBLISHED_CALLBACK = ctypes.CFUNCTYPE(None, AGORA_HANDLE, AGORA_HANDLE)
|
|
@@ -95,31 +86,6 @@ ON_REMOTE_SUBSCRIBE_FALLBACK_TO_AUDIO_ONLY_CALLBACK = ctypes.CFUNCTYPE(None, AGO
|
|
|
95
86
|
ON_STREAM_MESSAGE_CALLBACK = ctypes.CFUNCTYPE(None, AGORA_HANDLE, user_id_t, ctypes.c_int, ctypes.c_char_p, ctypes.c_size_t)
|
|
96
87
|
ON_USER_STATE_CHANGED_CALLBACK = ctypes.CFUNCTYPE(None, AGORA_HANDLE, user_id_t, ctypes.c_uint32)
|
|
97
88
|
|
|
98
|
-
|
|
99
|
-
"""
|
|
100
|
-
on_user_info_updated(user_id_t: string ; msg: int, val: int)
|
|
101
|
-
msg:
|
|
102
|
-
enum USER_MEDIA_INFO {
|
|
103
|
-
/**
|
|
104
|
-
* 0: The user has muted the audio.
|
|
105
|
-
*/
|
|
106
|
-
USER_MEDIA_INFO_MUTE_AUDIO = 0,
|
|
107
|
-
/**
|
|
108
|
-
* 1: The user has muted the video.
|
|
109
|
-
*/
|
|
110
|
-
USER_MEDIA_INFO_MUTE_VIDEO = 1,
|
|
111
|
-
/**
|
|
112
|
-
* 4: The user has enabled the video, which includes video capturing and encoding.
|
|
113
|
-
*/
|
|
114
|
-
USER_MEDIA_INFO_ENABLE_VIDEO = 4,
|
|
115
|
-
/**
|
|
116
|
-
* 8: The user has enabled the local video capturing.
|
|
117
|
-
*/
|
|
118
|
-
USER_MEDIA_INFO_ENABLE_LOCAL_VIDEO = 8,
|
|
119
|
-
};
|
|
120
|
-
val: 1: The user has muted the audio.0: unmuted the audio
|
|
121
|
-
参考:https://doc.shengwang.cn/api-ref/rtc-server-sdk/cpp/classagora_1_1rtc_1_1_i_local_user_observer#onUserInfoUpdated()
|
|
122
|
-
"""
|
|
123
89
|
class RTCLocalUserObserverInner(ctypes.Structure):
|
|
124
90
|
_fields_ = [
|
|
125
91
|
("on_audio_track_publish_success", ON_AUDIO_TRACK_PUBLISH_SUCCESS_CALLBACK),
|
|
@@ -241,7 +207,6 @@ class RTCLocalUserObserverInner(ctypes.Structure):
|
|
|
241
207
|
def _on_audio_track_publication_failure(self, local_user_handle, local_audio_track_handle, error_code):
|
|
242
208
|
logger.debug(f"LocalUserCB _on_audio_track_publication_failure: {local_user_handle}, {local_audio_track_handle}, {error_code}")
|
|
243
209
|
audio_track = self.local_user.get_audio_map(local_audio_track_handle)
|
|
244
|
-
#note :move from map for failed publish
|
|
245
210
|
self.local_user.del_audio_map(local_audio_track_handle)
|
|
246
211
|
self.local_user_observer.on_audio_track_publication_failure(self.local_user, audio_track, error_code)
|
|
247
212
|
|
|
@@ -251,22 +216,9 @@ class RTCLocalUserObserverInner(ctypes.Structure):
|
|
|
251
216
|
self.local_user_observer.on_local_audio_track_state_changed(self.local_user, audio_track, state, error)
|
|
252
217
|
|
|
253
218
|
def _on_local_audio_track_statistics(self, local_user_handle, stats):
|
|
254
|
-
#logger.debug("LocalUserCB _on_local_audio_track_statistics:", local_user_handle, stats)
|
|
255
|
-
#stats: pointer to LocalAudioStats
|
|
256
219
|
local_audio_stats = stats.contents
|
|
257
220
|
self.local_user_observer.on_local_audio_track_statistics(self.local_user, local_audio_stats)
|
|
258
|
-
|
|
259
|
-
"""
|
|
260
|
-
# 在LocalUser中是通过LocalUser.sub_audio(uid) 创建的,所以这里直接用uid来获取对应的RemoteAudioTrack
|
|
261
|
-
# 也就是说从app层的视角,对audio的区分是uid,但这边的回调并没有userid,所以对app层是不太友好的
|
|
262
|
-
# 也就是需要在LocalUser层中建立一个map表,用来记录userid和handle
|
|
263
|
-
# 然后在回调中,通过handle,找到uid,然后call 给app层的是uid
|
|
264
|
-
# 这样的话,在LocalUser层,就可以直接通过uid来获取对应的RemoteAudioTrack
|
|
265
|
-
"""
|
|
266
|
-
#
|
|
267
|
-
# _on_user_audio_track_subscribed:in LocalUser to do sub(userid), and in this call back it pass out with
|
|
268
|
-
# user_id & remote_audio_track_handle, so we should construct RemoteAudioTrack with (user_id & remote_audio_track_handle
|
|
269
|
-
# and save it in local_user, then in app layer, we can get RemoteAudioTrack with userid)
|
|
221
|
+
|
|
270
222
|
def _on_user_audio_track_subscribed(self, local_user_handle, user_id, remote_audio_track_handle):
|
|
271
223
|
logger.debug(f"LocalUserCB _on_user_audio_track_subscribed: {local_user_handle}, {user_id}, {remote_audio_track_handle}")
|
|
272
224
|
user_id_str = user_id.decode('utf-8') if user_id else ""
|
|
@@ -282,7 +234,6 @@ class RTCLocalUserObserverInner(ctypes.Structure):
|
|
|
282
234
|
remote_audio_track = self.local_user.get_remote_audio_map(remote_audio_track_handle)
|
|
283
235
|
self.local_user_observer.on_remote_audio_track_statistics(self.local_user, remote_audio_track, audio_stats)
|
|
284
236
|
|
|
285
|
-
|
|
286
237
|
def _on_user_audio_track_state_changed(self, local_user_handle, user_id, remote_audio_track_handle, state, reason, elapsed):
|
|
287
238
|
logger.debug(f"LocalUserCB _on_user_audio_track_state_changed: {local_user_handle}, {user_id}, {remote_audio_track_handle}, {state}, {reason}, {elapsed}")
|
|
288
239
|
user_id_str = user_id.decode('utf-8') if user_id else ""
|
|
@@ -333,7 +284,6 @@ class RTCLocalUserObserverInner(ctypes.Structure):
|
|
|
333
284
|
local_video_track = self.local_user.get_video_map(local_video_track_handle)
|
|
334
285
|
video_stats = stats.contents
|
|
335
286
|
self.local_user_observer.on_local_video_track_statistics(self.local_user, local_video_track, video_stats)
|
|
336
|
-
# # #ctypes.CFUNCTYPE(None, AGORA_HANDLE, user_id_t, ctypes.POINTER(VideoTrackInfo), AGORA_HANDLE)
|
|
337
287
|
def _on_user_video_track_subscribed(self, local_user_handle, user_id, video_track_info, remote_video_track_handle):
|
|
338
288
|
logger.debug(f"LocalUserCB _on_user_video_track_subscribed: {local_user_handle}, {user_id}, {remote_video_track_handle}, {video_track_info}")
|
|
339
289
|
user_id_str = user_id.decode('utf-8') if user_id else ""
|
|
@@ -3,7 +3,6 @@ import ctypes
|
|
|
3
3
|
from .agora_base import *
|
|
4
4
|
from .local_user import *
|
|
5
5
|
from .globals import *
|
|
6
|
-
# from .rtc_connection import *
|
|
7
6
|
from .rtc_connection_observer import *
|
|
8
7
|
import logging
|
|
9
8
|
logger = logging.getLogger(__name__)
|
|
@@ -19,20 +18,12 @@ class RTCConnInfoInner(ctypes.Structure):
|
|
|
19
18
|
def _convert_to_rtc_conn_info(self):
|
|
20
19
|
from .rtc_connection import RTCConnInfo
|
|
21
20
|
con_info = RTCConnInfo()
|
|
22
|
-
|
|
23
|
-
# 直接访问字段
|
|
24
21
|
con_info.id = self.id
|
|
25
22
|
con_info.channel_id = self.channel_id.decode('utf-8') if self.channel_id else ''
|
|
26
23
|
con_info.state = self.state
|
|
27
24
|
con_info.local_user_id = self.local_user_id.decode('utf-8') if self.local_user_id else ''
|
|
28
25
|
con_info.internal_uid = self.internal_uid
|
|
29
|
-
|
|
30
26
|
return con_info
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
uid_t = ctypes.c_uint
|
|
35
|
-
track_id_t = ctypes.c_uint
|
|
36
27
|
|
|
37
28
|
ON_CONNECTED_CALLBACK = ctypes.CFUNCTYPE(None, AGORA_HANDLE, ctypes.POINTER(RTCConnInfoInner), ctypes.c_int)
|
|
38
29
|
ON_DISCONNECTED_CALLBACK = ctypes.CFUNCTYPE(None, AGORA_HANDLE, ctypes.POINTER(RTCConnInfoInner), ctypes.c_int)
|
|
@@ -144,32 +135,6 @@ class RTCConnectionObserverInner(ctypes.Structure):
|
|
|
144
135
|
self.on_encryption_error = ON_ENCRYPTION_ERROR_CALLBACK(self._on_encryption_error)
|
|
145
136
|
self.on_upload_log_result = ON_UPLOAD_LOG_RESULT_CALLBACK(self._on_upload_log_result)
|
|
146
137
|
|
|
147
|
-
|
|
148
|
-
#agora_rtc_conn: handle of RTCConnection; conn_info_inner:pointer to RTCConnInfoInner
|
|
149
|
-
#reason: int type
|
|
150
|
-
#
|
|
151
|
-
"""
|
|
152
|
-
parameter type desp:
|
|
153
|
-
agora_rtc_conn: handle of RTCConnection;
|
|
154
|
-
conn_info_inner:pointer to RTCConnInfoInner
|
|
155
|
-
reason: int type
|
|
156
|
-
quality:int type
|
|
157
|
-
|
|
158
|
-
# note: sumary for ctypes.POINTER
|
|
159
|
-
#note: conn_info_inner is a pointer to RTCConnInfoInner, so we should do like following to ensure
|
|
160
|
-
# conn_info is a RTCConnInfo
|
|
161
|
-
# we make sure: conn_info_inner is a pointer to RTCConnInfoInner from ctypes, so
|
|
162
|
-
# no need to do type check like isinstance(xx),just use dereferencing method to get the contents
|
|
163
|
-
if isinstance(conn_info_inner, ctypes.POINTER(RTCConnInfoInner)):
|
|
164
|
-
conn_info = conn_info_inner.contents._convert_to_rtc_conn_info()
|
|
165
|
-
else:
|
|
166
|
-
conn_info = conn_info_inner._convert_to_rtc_conn_info()
|
|
167
|
-
|
|
168
|
-
just use:
|
|
169
|
-
conn_info = conn_info_inner.contents.()
|
|
170
|
-
|
|
171
|
-
to
|
|
172
|
-
"""
|
|
173
138
|
def _on_connected(self, agora_rtc_conn, conn_info_inner, reason):
|
|
174
139
|
logger.debug(f"ConnCB _on_connected: {agora_rtc_conn}, {conn_info_inner}, {reason}")
|
|
175
140
|
conn_info = conn_info_inner.contents._convert_to_rtc_conn_info()
|
|
@@ -204,16 +169,11 @@ class RTCConnectionObserverInner(ctypes.Structure):
|
|
|
204
169
|
logger.debug(f"ConnCB _on_lastmile_quality: {agora_rtc_conn}, {quality}")
|
|
205
170
|
self.conn_observer.on_lastmile_quality(self.conn, quality)
|
|
206
171
|
|
|
207
|
-
#last_mile_prob_result_ptr: ctypes.POINTER(LastmileProbeResult)) type
|
|
208
172
|
def _on_lastmile_probe_result(self, agora_rtc_conn, last_mile_prob_result_ptr):
|
|
209
173
|
logger.debug(f"ConnCB _on_lastmile_probe_result: {agora_rtc_conn}, {last_mile_prob_result_ptr}")
|
|
210
|
-
|
|
211
|
-
# we should dereference the pointer to get the LastmileProbeResult, thus we can access its fields
|
|
212
|
-
last_mile_result = last_mile_prob_result_ptr.contents
|
|
213
|
-
|
|
174
|
+
last_mile_result = last_mile_prob_result_ptr.contents
|
|
214
175
|
self.conn_observer.on_lastmile_probe_result(self.conn, last_mile_result)
|
|
215
176
|
|
|
216
|
-
#token: ctypes.char_p
|
|
217
177
|
def _on_token_privilege_will_expire(self, agora_rtc_conn, token):
|
|
218
178
|
logger.debug(f"ConnCB _on_token_privilege_will_expire: {agora_rtc_conn}, {token}")
|
|
219
179
|
token_str = token.decode('utf-8') #decode will generate a new object
|
|
@@ -231,7 +191,7 @@ class RTCConnectionObserverInner(ctypes.Structure):
|
|
|
231
191
|
logger.debug(f"ConnCB _on_connection_failure: {agora_rtc_conn}, {conn_info_inner}, {reason}")
|
|
232
192
|
conn_info = conn_info_inner.contents._convert_to_rtc_conn_info()
|
|
233
193
|
self.conn_observer.on_connection_failure(self.conn, conn_info, reason)
|
|
234
|
-
|
|
194
|
+
|
|
235
195
|
def _on_user_joined(self, agora_rtc_conn, user_id):
|
|
236
196
|
logger.debug(f"ConnCB _on_user_joined: {agora_rtc_conn}, {user_id}")
|
|
237
197
|
userid_str = user_id.decode('utf-8')
|
|
@@ -241,21 +201,12 @@ class RTCConnectionObserverInner(ctypes.Structure):
|
|
|
241
201
|
logger.debug(f"ConnCB _on_user_left: {agora_rtc_conn}, {user_id}, {reason}")
|
|
242
202
|
userid_str = user_id.decode('utf-8')
|
|
243
203
|
self.conn_observer.on_user_left(self.conn, userid_str, reason)
|
|
244
|
-
|
|
204
|
+
|
|
245
205
|
def _on_transport_stats(self, agora_rtc_conn, stats):
|
|
246
206
|
logger.debug(f"ConnCB _on_transport_stats: {agora_rtc_conn}, {stats}")
|
|
247
|
-
|
|
248
|
-
#should dereference the pointer to get the RTCStats, thus we can access its fields
|
|
249
|
-
rtc_stats = stats.contents
|
|
250
|
-
"""
|
|
251
|
-
if isinstance(stats, ctypes.POINTER(RTCStats)):
|
|
252
|
-
rtc_stats = stats.contents
|
|
253
|
-
else:
|
|
254
|
-
rtc_stats = stats
|
|
255
|
-
"""
|
|
256
|
-
|
|
207
|
+
rtc_stats = stats.contents
|
|
257
208
|
self.conn_observer.on_transport_stats(self.conn, rtc_stats)
|
|
258
|
-
|
|
209
|
+
|
|
259
210
|
def _on_change_role_success(self, agora_rtc_conn, old_role, new_role):
|
|
260
211
|
logger.debug(f"ConnCB _on_change_role_success: {agora_rtc_conn}, {old_role}, {new_role}")
|
|
261
212
|
self.conn_observer.on_change_role_success(self.conn, old_role, new_role)
|
|
@@ -266,32 +217,25 @@ class RTCConnectionObserverInner(ctypes.Structure):
|
|
|
266
217
|
|
|
267
218
|
def _on_user_network_quality(self, agora_rtc_conn, user_id, tx_quality, rx_quality):
|
|
268
219
|
logger.debug(f"ConnCB _on_user_network_quality: {agora_rtc_conn}, {user_id}, {tx_quality}, {rx_quality}")
|
|
269
|
-
#user_id: ctypes.char_p
|
|
270
|
-
#tx_quality: ctypes.int
|
|
271
|
-
#rx_quality: ctypes.int
|
|
272
220
|
userid_str = user_id.decode('utf-8') if user_id else ""
|
|
273
221
|
self.conn_observer.on_user_network_quality(self.conn, userid_str, tx_quality, rx_quality)
|
|
274
222
|
|
|
275
223
|
def _on_network_type_changed(self, agora_rtc_conn, network_type):
|
|
276
224
|
logger.debug(f"ConnCB _on_network_type_changed: {agora_rtc_conn}, {network_type}")
|
|
277
|
-
#network_type: ctypes.int
|
|
278
225
|
self.conn_observer.on_network_type_changed(self.conn, network_type)
|
|
279
226
|
|
|
280
227
|
def _on_api_call_executed(self, agora_rtc_conn, error, api_type, api_params):
|
|
281
228
|
logger.debug(f"ConnCB _on_api_call_executed: {agora_rtc_conn}, {error}, {api_type}, {api_params}")
|
|
282
|
-
#error: ctypes.int; api_type: ctypes.char_p; api_params: ctypes.char_p
|
|
283
229
|
_api_type_str = api_type.decode('utf-8') if api_type else ""
|
|
284
230
|
_api_param_str = api_params.decode('utf-8') if api_params else ""
|
|
285
231
|
self.conn_observer.on_api_call_executed(self.conn, error, _api_type_str, _api_param_str)
|
|
286
232
|
|
|
287
233
|
def _on_content_inspect_result(self, agora_rtc_conn, result):
|
|
288
234
|
logger.debug(f"ConnCB _on_content_inspect_result: {agora_rtc_conn}, {result}")
|
|
289
|
-
#result: ctypes.int
|
|
290
235
|
self.conn_observer.on_content_inspect_result(self.conn, result)
|
|
291
236
|
|
|
292
237
|
def _on_snapshot_taken(self, agora_rtc_conn, channel, uid, filepath, width, height, errCode):
|
|
293
238
|
logger.debug(f"ConnCB _on_snapshot_taken: {agora_rtc_conn}, {channel}, {uid}, {filepath}, {width}, {height}, {errCode}")
|
|
294
|
-
#channel: ctypes.c_char_p; uid: ctypes.c_uint32; filepath: ctypes.c_char_p; width: ctypes.c_int32; height: ctypes.c_int32; errCode: ctypes.c_int32
|
|
295
239
|
_channel_str = channel.decode('utf-8') if channel else ""
|
|
296
240
|
_file_path_str = filepath.decode('utf-8') if filepath else ""
|
|
297
241
|
self.conn_observer.on_snapshot_taken(self.conn, _channel_str, uid, _file_path_str, width, height, errCode)
|
|
@@ -330,7 +274,6 @@ class RTCConnectionObserverInner(ctypes.Structure):
|
|
|
330
274
|
logger.debug(f"ConnCB _on_encryption_error: {agora_rtc_conn}, {error_type}")
|
|
331
275
|
self.conn_observer.on_encryption_error(self.conn, error_type)
|
|
332
276
|
|
|
333
|
-
#request_id: ctypes.c_char_p; success/reason: ctypes.int
|
|
334
277
|
def _on_upload_log_result(self, agora_rtc_conn, request_id, success, reason):
|
|
335
278
|
logger.debug(f"ConnCB _on_upload_log_result: {agora_rtc_conn}, {request_id}, {success}, {reason}")
|
|
336
279
|
_request_id_str = request_id.decode("utf-8") if request_id else ""
|
|
@@ -6,12 +6,6 @@ from .video_encoded_frame_observer import IVideoEncodedFrameObserver, EncodedVid
|
|
|
6
6
|
import logging
|
|
7
7
|
logger = logging.getLogger(__name__)
|
|
8
8
|
|
|
9
|
-
# typedef struct _video_encoded_frame_observer {
|
|
10
|
-
# int (*on_encoded_video_frame)(AGORA_HANDLE agora_video_encoded_frame_observer, uid_t uid, const uint8_t* image_buffer, size_t length,
|
|
11
|
-
# const encoded_video_frame_info* video_encoded_frame_info);
|
|
12
|
-
# } video_encoded_frame_observer;
|
|
13
|
-
|
|
14
|
-
|
|
15
9
|
class EncodedVideoFrameInfoInner(ctypes.Structure):
|
|
16
10
|
_fields_ = [
|
|
17
11
|
("codec_type", ctypes.c_int),
|
{agora_python_server_sdk-2.0.3 → agora_python_server_sdk-2.0.4}/agora/rtc/_video_frame_observer.py
RENAMED
|
@@ -52,6 +52,11 @@ class VideoFrameInner(ctypes.Structure):
|
|
|
52
52
|
|
|
53
53
|
ON_FRAME_CALLBACK = ctypes.CFUNCTYPE(None, AGORA_HANDLE, ctypes.c_char_p, user_id_t, ctypes.POINTER(VideoFrameInner))
|
|
54
54
|
|
|
55
|
+
agora_video_frame_observer_get_rotation_applied = agora_lib.agora_video_frame_observer_get_rotation_applied
|
|
56
|
+
agora_video_frame_observer_get_rotation_applied.restype = ctypes.c_int
|
|
57
|
+
agora_video_frame_observer_get_rotation_applied.argtypes = [AGORA_HANDLE]
|
|
58
|
+
|
|
59
|
+
|
|
55
60
|
class VideoFrameObserverInner(ctypes.Structure):
|
|
56
61
|
_fields_ = [
|
|
57
62
|
("on_frame", ON_FRAME_CALLBACK)
|
|
@@ -65,29 +70,5 @@ class VideoFrameObserverInner(ctypes.Structure):
|
|
|
65
70
|
|
|
66
71
|
def _on_frame(self, agora_handle, channel_id, user_id, video_frame:VideoFrameInner):
|
|
67
72
|
vf = video_frame.contents
|
|
68
|
-
# logger.debug("VideoFrameObserver _on_frame:", agora_handle, channel_id, user_id, vf.metadata_buffer, vf.metadata_size)
|
|
69
73
|
self.video_frame_observer.on_frame(agora_handle, channel_id.decode() if channel_id else None, user_id.decode(), vf.to_video_frame())
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
# ON_ENCODED_VIDEO_IMAGE_RECEIVED_CALLBACK = ctypes.CFUNCTYPE(ctypes.c_int, ctypes.c_void_p, ctypes.POINTER(ctypes.c_uint8), ctypes.c_uint32, ctypes.POINTER(encoded_video_frame_info))
|
|
77
|
-
|
|
78
|
-
# class VideoEncodedImageReceiverInner(ctypes.Structure):
|
|
79
|
-
# _fields_ = [
|
|
80
|
-
# ("on_encoded_video_image_received", ON_ENCODED_VIDEO_IMAGE_RECEIVED_CALLBACK)
|
|
81
|
-
# ]
|
|
82
|
-
|
|
83
|
-
# def __init__(self, video_encoded_image_receiver:'IVideoEncodedImageReceiver'):
|
|
84
|
-
# self.video_encoded_image_receiver = video_encoded_image_receiver
|
|
85
|
-
# self.on_encoded_video_image_received = ON_ENCODED_VIDEO_IMAGE_RECEIVED_CALLBACK(self._on_encoded_video_image_received)
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
# def _on_encoded_video_image_received(self, agora_handle, image_buffer, length, info):
|
|
89
|
-
# logger.debug("VideoFrameObserver _on_frame:", agora_handle, image_buffer, length, info)
|
|
90
|
-
# # self.on_encoded_video_image_received(agora_handle, image_buffer, length, info)
|
|
91
|
-
# self.video_encoded_image_receiver.on_encoded_video_image_received(agora_handle, image_buffer, length, info)
|
|
92
|
-
|
|
93
|
-
|
|
74
|
+
|
|
@@ -294,6 +294,11 @@ class AudioFrame:
|
|
|
294
294
|
self.buffer = None
|
|
295
295
|
self.render_time_ms = 0
|
|
296
296
|
self.avsync_type = 0
|
|
297
|
+
self.far_field_flag = 0
|
|
298
|
+
self.rms = 0
|
|
299
|
+
self.voice_prob = 0
|
|
300
|
+
self.music_prob = 0
|
|
301
|
+
self.pitch = 0
|
|
297
302
|
|
|
298
303
|
class AudioParams(ctypes.Structure):
|
|
299
304
|
_fields_ = [
|
|
@@ -123,6 +123,11 @@ agora_service_create_custom_video_track_frame = agora_lib.agora_service_create_c
|
|
|
123
123
|
agora_service_create_custom_video_track_frame.restype = AGORA_HANDLE
|
|
124
124
|
agora_service_create_custom_video_track_frame.argtypes = [AGORA_HANDLE, AGORA_HANDLE]
|
|
125
125
|
|
|
126
|
+
agora_service_enable_extension = agora_lib.agora_service_enable_extension
|
|
127
|
+
agora_service_enable_extension.restype = AGORA_API_C_INT
|
|
128
|
+
agora_service_enable_extension.argtypes = [AGORA_HANDLE, ctypes.c_char_p, ctypes.c_char_p, ctypes.c_char_p, ctypes.c_uint]
|
|
129
|
+
|
|
130
|
+
|
|
126
131
|
class SenderOptions(ctypes.Structure):
|
|
127
132
|
_fields_ = [
|
|
128
133
|
("cc_mode", ctypes.c_int),
|
|
@@ -142,6 +147,8 @@ agora_service_create_custom_video_track_encoded.argtypes = [AGORA_HANDLE, AGORA_
|
|
|
142
147
|
class AgoraService:
|
|
143
148
|
def __init__(self) -> None:
|
|
144
149
|
self.service_handle = agora_service_create()
|
|
150
|
+
|
|
151
|
+
# set tag???
|
|
145
152
|
self.inited = False
|
|
146
153
|
|
|
147
154
|
def initialize(self, config: AgoraServiceConfig):
|
|
@@ -153,6 +160,15 @@ class AgoraService:
|
|
|
153
160
|
self.inited = True
|
|
154
161
|
logger.debug(f'Initialization result: {result}')
|
|
155
162
|
|
|
163
|
+
# to enable plugin
|
|
164
|
+
provider = "agora.builtin"
|
|
165
|
+
generator = "agora_audio_label_generator"
|
|
166
|
+
cprovider = provider.encode('utf-8')
|
|
167
|
+
cgenerator = generator.encode('utf-8')
|
|
168
|
+
ctrak = ctypes.c_char_p(None)
|
|
169
|
+
#agora_service_enable_extension(self.service_handle, "agora.builtin", "agora_audio_label_generator", None, 1)
|
|
170
|
+
agora_service_enable_extension(self.service_handle, cprovider, cgenerator, ctrak, 1)
|
|
171
|
+
|
|
156
172
|
if config.log_path:
|
|
157
173
|
log_size = 512 * 1024
|
|
158
174
|
if config.log_size > 0:
|
|
@@ -172,7 +188,7 @@ class AgoraService:
|
|
|
172
188
|
self.inited = False
|
|
173
189
|
self.service_handle = None
|
|
174
190
|
|
|
175
|
-
#createMediaNodeFactory
|
|
191
|
+
#createMediaNodeFactory: to create a medianode factory object
|
|
176
192
|
def create_media_node_factory(self):
|
|
177
193
|
if not self.inited:
|
|
178
194
|
logger.error("AgoraService is not initialized. Please call initialize() first.")
|
|
@@ -193,8 +209,8 @@ class AgoraService:
|
|
|
193
209
|
return RTCConnection(rtc_conn_handle)
|
|
194
210
|
|
|
195
211
|
|
|
196
|
-
#createCustomAudioTrackPcm
|
|
197
|
-
def create_custom_audio_track_pcm(self, audio_pcm_data_sender:AudioPcmDataSender):
|
|
212
|
+
#createCustomAudioTrackPcm: creatae a custom audio track from pcm data sender
|
|
213
|
+
def create_custom_audio_track_pcm(self, audio_pcm_data_sender:AudioPcmDataSender) -> LocalAudioTrack | None:
|
|
198
214
|
if not self.inited:
|
|
199
215
|
logger.error("AgoraService is not initialized. Please call initialize() first.")
|
|
200
216
|
return None
|
|
@@ -6,9 +6,6 @@ logger = logging.getLogger(__name__)
|
|
|
6
6
|
class EncodedAudioFrame:
|
|
7
7
|
def __init__(
|
|
8
8
|
self,
|
|
9
|
-
# data: bytearray = None,
|
|
10
|
-
# buffer_ptr: int = 0,
|
|
11
|
-
# buffer_size: int = 0,
|
|
12
9
|
capture_timems: int = 0,
|
|
13
10
|
codec: AudioCodecType = AudioCodecType.AUDIO_CODEC_AACLC,
|
|
14
11
|
number_of_channels: int = 1,
|
|
@@ -17,18 +14,13 @@ class EncodedAudioFrame:
|
|
|
17
14
|
send_even_if_empty: int = 1,
|
|
18
15
|
speech: int = 1
|
|
19
16
|
)->None:
|
|
20
|
-
|
|
21
|
-
# self.buffer_ptr = buffer_ptr
|
|
22
|
-
# self.buffer_size = buffer_size
|
|
23
|
-
self.capture_timems = capture_timems #int64, 音频帧的 Unix 时间戳(毫秒)
|
|
24
|
-
#int, 音频帧的编码格式; ref: https://doc.shengwang.cn/api-ref/rtc-server-sdk/cpp/namespaceagora_1_1rtc#ac211c1a503d38d504c92b5f006240053
|
|
17
|
+
self.capture_timems = capture_timems
|
|
25
18
|
self.codec = codec
|
|
26
19
|
self.number_of_channels = number_of_channels
|
|
27
20
|
self.sample_rate = sample_rate
|
|
28
|
-
#int, 对于 aac 编码格式,默认为 1024;对于 Opus 编码格式,默认为 960
|
|
29
21
|
self.samples_per_channel = samples_per_channel
|
|
30
|
-
self.send_even_if_empty = send_even_if_empty
|
|
31
|
-
self.speech = speech
|
|
22
|
+
self.send_even_if_empty = send_even_if_empty
|
|
23
|
+
self.speech = speech
|
|
32
24
|
|
|
33
25
|
def to_owned_encoded_audio_frame(self):
|
|
34
26
|
info = OwnedEncodedAudioFrameInfo()
|
|
@@ -75,19 +67,10 @@ class AudioEncodedFrameSender:
|
|
|
75
67
|
# c_date = (ctypes.c_char * len(frame.data)).from_buffer(frame.data)
|
|
76
68
|
# ownedinfo = frame.to_owned_encoded_audio_frame()
|
|
77
69
|
# ret = agora_audio_encoded_frame_sender_send(self.sender_handle, c_date, ctypes.c_uint32(len(frame.data)), ctypes.byref(ownedinfo))
|
|
78
|
-
# if ret < 0:
|
|
79
|
-
# logger.error(f"Failed to send encoded audio frame with error code: {ret}")
|
|
80
70
|
# return ret
|
|
81
71
|
|
|
82
72
|
def send_encoded_audio_frame(self, buffer_ptr:int, buffer_size:int, frame:EncodedAudioFrame):
|
|
83
73
|
buffer_ptr = ctypes.cast(buffer_ptr, ctypes.POINTER(ctypes.c_void_p))
|
|
84
74
|
ownedinfo = frame.to_owned_encoded_audio_frame()
|
|
85
75
|
ret = agora_audio_encoded_frame_sender_send(self.sender_handle, buffer_ptr, ctypes.c_uint32(buffer_size), ctypes.byref(ownedinfo))
|
|
86
|
-
if ret < 0:
|
|
87
|
-
logger.error(f"Failed to send encoded audio frame with error code: {ret}")
|
|
88
76
|
return ret
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
def release(self):
|
|
92
|
-
# agora_local_audio_track_destroy(self.sender_handle)
|
|
93
|
-
pass
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
from .agora_base import AudioFrame, AudioParams
|
|
2
|
+
|
|
3
|
+
class IAudioFrameObserver:
|
|
4
|
+
def on_record_audio_frame(self, agora_local_user, channelId, frame):
|
|
5
|
+
return 1
|
|
6
|
+
|
|
7
|
+
def on_playback_audio_frame(self, agora_local_user, channelId, frame):
|
|
8
|
+
return 1
|
|
9
|
+
|
|
10
|
+
def on_mixed_audio_frame(self, agora_local_user, channelId, frame):
|
|
11
|
+
return 1
|
|
12
|
+
|
|
13
|
+
def on_ear_monitoring_audio_frame(self, agora_local_user, frame):
|
|
14
|
+
return 1
|
|
15
|
+
|
|
16
|
+
def on_playback_audio_frame_before_mixing(self, agora_local_user, channelId, uid, frame:AudioFrame):
|
|
17
|
+
return 1
|
|
18
|
+
|
|
19
|
+
def on_get_audio_frame_position(self, agora_local_user):
|
|
20
|
+
return 1
|
|
21
|
+
|
|
22
|
+
def on_get_playback_audio_frame_param(self, agora_local_user) -> AudioParams:
|
|
23
|
+
pass
|
|
24
|
+
|
|
25
|
+
def on_get_record_audio_frame_param(self, agora_local_user) -> AudioParams:
|
|
26
|
+
pass
|
|
27
|
+
|
|
28
|
+
def on_get_mixed_audio_frame_param(self, agora_local_user) -> AudioParams:
|
|
29
|
+
pass
|
|
30
|
+
|
|
31
|
+
def on_get_ear_monitoring_audio_frame_param(self, agora_local_user) -> AudioParams:
|
|
32
|
+
pass
|