Skip to content

Commit 5c35546

Browse files
feat: 延迟加载WebRTC音频处理库并优化函数签名初始化
1 parent 58ade0c commit 5c35546

File tree

2 files changed

+69
-40
lines changed

2 files changed

+69
-40
lines changed

libs/webrtc_apm/__init__.py

Lines changed: 69 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -4,29 +4,30 @@
44
"""
55

66
import ctypes
7+
import os
78
import platform
89
import sys
9-
import os
10-
from pathlib import Path
1110
from enum import IntEnum
11+
from pathlib import Path
1212
from typing import Optional
1313

14+
1415
# 平台特定的库加载
1516
def _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
# 枚举类型
4868
class 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

255281
class 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")

src/plugins/wake_word.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,6 @@ async def shutdown(self) -> None:
5757
async def _on_detected(self, wake_word, full_text):
5858
# 检测到唤醒词:切到自动对话(根据 AEC 自动选择实时/自动停)
5959
try:
60-
print(wake_word, full_text)
6160
# 若正在说话,交给应用的打断/状态机处理
6261
if hasattr(self.app, "device_state") and hasattr(
6362
self.app, "start_auto_conversation"

0 commit comments

Comments
 (0)