44"""
55
66import ctypes
7+ import os
78import platform
89import sys
9- import os
10- from pathlib import Path
1110from enum import IntEnum
11+ from pathlib import Path
1212from typing import Optional
1313
14+
1415# 平台特定的库加载
1516def _get_library_path () -> str :
1617 """获取平台特定的库路径。"""
1718 current_dir = Path (__file__ ).parent
18-
19+
1920 system = platform .system ().lower ()
2021 arch = platform .machine ().lower ()
21-
22+
2223 # 标准化架构名称
2324 if arch in ['x86_64' , 'amd64' ]:
2425 arch = 'x64'
2526 elif arch in ['aarch64' , 'arm64' ]:
2627 arch = 'arm64'
2728 elif arch in ['i386' , 'i686' , 'x86' ]:
2829 arch = 'x86'
29-
30+
3031 if system == 'linux' :
3132 lib_path = current_dir / 'linux' / arch / 'libwebrtc_apm.so'
3233 elif system == 'darwin' :
@@ -35,14 +36,33 @@ def _get_library_path() -> str:
3536 lib_path = current_dir / 'windows' / arch / 'libwebrtc_apm.dll'
3637 else :
3738 raise RuntimeError (f"Unsupported platform: { system } " )
38-
39+
3940 if not lib_path .exists ():
4041 raise FileNotFoundError (f"Library not found: { lib_path } " )
41-
42+
4243 return str (lib_path )
4344
44- # 加载库
45- _lib = ctypes .CDLL (_get_library_path ())
45+ # 延迟加载库(仅在macOS平台需要时加载)
46+ _lib = None
47+
48+ def _ensure_library_loaded ():
49+ """确保库已加载(仅macOS平台)。"""
50+ global _lib
51+
52+ # 检查是否为macOS平台
53+ system = platform .system ().lower ()
54+ if system != 'darwin' :
55+ raise RuntimeError (
56+ f"WebRTC APM library is only supported on macOS, current platform: { system } . "
57+ f"Windows and Linux should use system-level AEC instead."
58+ )
59+
60+ # 如果已加载,直接返回
61+ if _lib is not None :
62+ return
63+
64+ # 加载库
65+ _lib = ctypes .CDLL (_get_library_path ())
4666
4767# 枚举类型
4868class DownmixMethod (IntEnum ):
@@ -215,48 +235,58 @@ class Config(ctypes.Structure):
215235 ('gain_control2' , GainController2 ),
216236 ]
217237
218- # 函数定义
219- _lib .WebRTC_APM_Create .argtypes = []
220- _lib .WebRTC_APM_Create .restype = ctypes .c_void_p
238+ # 函数定义(延迟初始化)
239+ def _init_function_signatures ():
240+ """初始化函数签名(仅在库加载后调用)。"""
241+ global _lib
242+ if _lib is None :
243+ raise RuntimeError ("Library not loaded. Call _ensure_library_loaded() first." )
221244
222- _lib .WebRTC_APM_Destroy .argtypes = [ctypes . c_void_p ]
223- _lib .WebRTC_APM_Destroy .restype = None
245+ _lib .WebRTC_APM_Create .argtypes = []
246+ _lib .WebRTC_APM_Create .restype = ctypes . c_void_p
224247
225- _lib .WebRTC_APM_CreateStreamConfig .argtypes = [ctypes .c_int , ctypes . c_int ]
226- _lib .WebRTC_APM_CreateStreamConfig .restype = ctypes . c_void_p
248+ _lib .WebRTC_APM_Destroy .argtypes = [ctypes .c_void_p ]
249+ _lib .WebRTC_APM_Destroy .restype = None
227250
228- _lib .WebRTC_APM_DestroyStreamConfig .argtypes = [ctypes .c_void_p ]
229- _lib .WebRTC_APM_DestroyStreamConfig .restype = ctypes .c_void_p
251+ _lib .WebRTC_APM_CreateStreamConfig .argtypes = [ctypes .c_int , ctypes . c_int ]
252+ _lib .WebRTC_APM_CreateStreamConfig .restype = ctypes .c_void_p
230253
231- _lib .WebRTC_APM_ApplyConfig .argtypes = [ctypes .c_void_p , ctypes . POINTER ( Config ) ]
232- _lib .WebRTC_APM_ApplyConfig .restype = ctypes .c_int
254+ _lib .WebRTC_APM_DestroyStreamConfig .argtypes = [ctypes .c_void_p ]
255+ _lib .WebRTC_APM_DestroyStreamConfig .restype = ctypes .c_void_p
233256
234- _lib .WebRTC_APM_ProcessReverseStream .argtypes = [
235- ctypes .c_void_p ,
236- ctypes .POINTER (ctypes .c_short ),
237- ctypes .c_void_p ,
238- ctypes .c_void_p ,
239- ctypes .POINTER (ctypes .c_short ),
240- ]
241- _lib .WebRTC_APM_ProcessReverseStream .restype = ctypes .c_int
257+ _lib .WebRTC_APM_ApplyConfig .argtypes = [ctypes .c_void_p , ctypes .POINTER (Config )]
258+ _lib .WebRTC_APM_ApplyConfig .restype = ctypes .c_int
242259
243- _lib .WebRTC_APM_ProcessStream .argtypes = [
244- ctypes .c_void_p ,
245- ctypes .POINTER (ctypes .c_short ),
246- ctypes .c_void_p ,
247- ctypes .c_void_p ,
248- ctypes .POINTER (ctypes .c_short ),
249- ]
250- _lib .WebRTC_APM_ProcessStream .restype = ctypes .c_int
260+ _lib .WebRTC_APM_ProcessReverseStream .argtypes = [
261+ ctypes .c_void_p ,
262+ ctypes .POINTER (ctypes .c_short ),
263+ ctypes .c_void_p ,
264+ ctypes .c_void_p ,
265+ ctypes .POINTER (ctypes .c_short ),
266+ ]
267+ _lib .WebRTC_APM_ProcessReverseStream .restype = ctypes .c_int
268+
269+ _lib .WebRTC_APM_ProcessStream .argtypes = [
270+ ctypes .c_void_p ,
271+ ctypes .POINTER (ctypes .c_short ),
272+ ctypes .c_void_p ,
273+ ctypes .c_void_p ,
274+ ctypes .POINTER (ctypes .c_short ),
275+ ]
276+ _lib .WebRTC_APM_ProcessStream .restype = ctypes .c_int
251277
252- _lib .WebRTC_APM_SetStreamDelayMs .argtypes = [ctypes .c_void_p , ctypes .c_int ]
253- _lib .WebRTC_APM_SetStreamDelayMs .restype = None
278+ _lib .WebRTC_APM_SetStreamDelayMs .argtypes = [ctypes .c_void_p , ctypes .c_int ]
279+ _lib .WebRTC_APM_SetStreamDelayMs .restype = None
254280
255281class WebRTCAudioProcessing :
256282 """WebRTC 音频处理的高级 Python 封装器。"""
257-
283+
258284 def __init__ (self ):
259285 """初始化音频处理模块。"""
286+ # 确保库已加载(仅macOS)
287+ _ensure_library_loaded ()
288+ _init_function_signatures ()
289+
260290 self ._handle = _lib .WebRTC_APM_Create ()
261291 if not self ._handle :
262292 raise RuntimeError ("Failed to create WebRTC APM instance" )
0 commit comments