如何确保pjsua2音频回环录制保持原始音质?
解决pjsua2音频回环录制音质劣化问题
核心问题根源
你当前的方案依赖物理音频设备做回环(监听端采集本地播放的音频再回传),这会引入多次D/A/A/D转换损耗、硬件回声、虚拟化层干扰,再加上pjsua2默认音频处理模块的误触发,最终导致音质崩溃。要实现无损回环,必须绕过物理声卡,直接在数字媒体流层面完成路由。
具体修复步骤
1. 监听端:替换物理设备回环为媒体流端到端路由
删除监听端将capture_media路由到playback_media的逻辑,改为直接将呼叫的接收媒体流转发到发送媒体流,完全跳过物理声卡:
class MyCall(pj.Call): def onCallMediaState(self, prm): # 获取呼叫的音频媒体实例 call_info = self.getInfo() for mi in call_info.media: if mi.type == pj.PJMEDIA_TYPE_AUDIO and mi.status == pj.PJSUA_CALL_MEDIA_ACTIVE: # 获取接收(rx)和发送(tx)媒体 rx_media = pj.AudioMedia.typecastFromMedia(self.getMedia(mi.index)) tx_media = pj.AudioMedia.typecastFromMedia(self.getMedia(mi.index)) # 直接将收到的音频原路回传 rx_media.startTransmit(tx_media) break
2. 主叫端:绕过本地声卡,直接向呼叫流播放音频
不要将AudioMediaPlayer路由到系统playback_media,改为直接传输到呼叫的发送媒体流:
# 主叫端呼叫建立后,获取呼叫音频媒体 call_media = pj.AudioMedia.typecastFromMedia(my_call.getMedia(0)) # 初始化播放器(确保WAV参数与媒体配置一致) player = pj.AudioMediaPlayer() player.createPlayer("test_audio.wav") # 直接向呼叫流播放音频 player.startTransmit(call_media)
3. 主叫端:直接录制呼叫接收流,跳过本地声卡采集
不要从capture_media录制,改为直接录制呼叫的接收媒体流:
# 获取呼叫的接收音频媒体 call_rx_media = pj.AudioMedia.typecastFromMedia(my_call.getMedia(0)) # 初始化录制器 recorder = pj.AudioMediaRecorder() recorder.createRecorder("recorded_loop.wav") # 直接录制回传的音频流 call_rx_media.startTransmit(recorder)
4. 彻底禁用pjsua2所有音频处理模块
在初始化Endpoint时,关闭所有可能修改音频的功能,确保音频流无额外处理:
ep = pj.Endpoint() ep_cfg = pj.EpConfig() # 媒体核心配置 ep_cfg.mediaConfig.ecOptions.enabled = False # 关闭回声消除 ep_cfg.mediaConfig.vadOption = pj.PJMEDIA_VAD_DISABLED # 关闭语音活动检测 ep_cfg.mediaConfig.agcConfig.enabled = False # 关闭自动增益控制 ep_cfg.mediaConfig.noiseSuppressConfig.enabled = False # 关闭降噪 ep_cfg.mediaConfig.clockRate = 16000 # 与测试WAV采样率一致(如8kHz则设8000) ep_cfg.mediaConfig.channelCount = 1 # 与测试WAV声道数一致(单声道设1,立体声设2) ep_cfg.mediaConfig.sndClockRate = ep_cfg.mediaConfig.clockRate # 同步音频设备采样率 # 音频设备配置 ep_cfg.audDevConfig.ecEnabled = False ep_cfg.audDevConfig.agcEnabled = False ep_cfg.audDevConfig.vadEnabled = False ep.libCreate() ep.libInit(ep_cfg)
5. 确保音频文件与媒体配置完全匹配
测试用WAV文件的参数必须和pjsua2配置一致:
- 采样率:16kHz/8kHz(与
clockRate对应) - 声道数:单声道/立体声(与
channelCount对应) - 位深:16位(pjsua2默认支持,避免使用8位或24位)
6. 虚拟机环境优化
- 将虚拟机音频设备设置为直通模式,禁用虚拟声卡的内置回声消除、增益调整功能
- 确保虚拟机之间的网络延迟稳定,避免丢包导致的音频失真
为什么之前的尝试无效?
你之前调整的VAD、线程模式、quality参数都是针对媒体流的边缘设置,但核心问题是多次物理音频转换引入的不可逆损耗,以及默认音频处理模块在设备回环场景下的误触发(比如回声消除会把正常回传音频判定为回声进行压制,导致音量忽强忽弱)。只有跳过物理声卡,直接在数字流层面路由,才能彻底解决音质问题。
内容的提问来源于stack exchange,提问作者Paul Deva
相关产品推荐
相关产品推荐

