基于pjsua2的Python SIP客户端能否内存实时处理音频帧?
在Python的pjsua2中直接内存处理音频帧的方案
好问题!直接跳过磁盘IO、在内存中处理通话音频帧确实是更高效的方案,结合你已经基于Call类实现的通话逻辑,我来给你分享最直接且官方推荐的实现方式:
方法:继承pj.Port实现自定义音频端口
虽然你提到SWIG封装没有直接暴露MediaPort的回调typedef,但pjsua2的Python绑定提供了pj.Port基类,我们可以通过继承它来创建自己的音频端口,从而直接捕获和处理内存中的PCM音频帧。
步骤1:实现自定义音频处理器类
创建一个继承自pj.Port的类,核心是覆盖onPutFrame方法(用于接收通话传入的音频帧)和onGetFrame方法(用于向通话发送处理后的音频帧):
import pj import numpy as np # 可选:用于数值化处理音频数据 class CustomAudioProcessor(pj.Port): def __init__(self, audio_media): super().__init__() # 同步通话音频的核心参数,必须和源音频一致 self.clock_rate = audio_media.getClockRate() self.channels = audio_media.getChannelCount() self.samples_per_frame = audio_media.getSamplesPerFrame() self.bits_per_sample = 16 # pjsua默认采用16位PCM格式 # 配置自定义端口的参数 self.setName("CustomAudioProcessor") self.setClockRate(self.clock_rate) self.setChannelCount(self.channels) self.setSamplesPerFrame(self.samples_per_frame) self.setBitsPerSample(self.bits_per_sample) def onPutFrame(self, frame): """收到通话传入的音频帧时触发,在这里处理内存中的PCM数据""" # frame.buf是原始的16位PCM字节数据 pcm_raw = frame.buf # 可选:转换为numpy数组方便后续处理(比如降噪、语音特征提取) pcm_array = np.frombuffer(pcm_raw, dtype=np.int16) # 加入你的自定义处理逻辑: # 示例:打印帧信息、实时滤波、语音识别预处理等 print(f"Received audio frame: {len(pcm_raw)} bytes | {len(pcm_array)} samples") return pj.PJ_SUCCESS def onGetFrame(self, frame): """当需要向通话发送音频帧时触发(比如回传处理后的音频)""" # 如果不需要回传音频,保持默认返回成功即可 # 若要回传处理后的音频,可以在这里填充PCM数据到frame.buf return pj.PJ_SUCCESS
步骤2:在通话回调中绑定自定义端口
修改你的onCallMediaState方法,将通话的AudioMedia流转发到自定义端口,触发帧处理回调:
def onCallMediaState(self, prm): ci = self.getInfo() logger.info("onCallMediaState", media_size=ci.media.size()) self._print_call_info("onCallMediaState") for media_index, media in enumerate(ci.media): if media.type == pj.PJMEDIA_TYPE_AUDIO: if ci.stateText == "CONFIRMED": logger.info("Call CONFIRMED") # 获取通话的AudioMedia实例 audio_media = pj.AudioMedia.typecastFromMedia(self.getMedia(media_index)) # 初始化自定义音频处理器 self.audio_processor = CustomAudioProcessor(audio_media) # 将通话音频流转发到自定义端口,触发onPutFrame回调 audio_media.startTransmit(self.audio_processor) # 可选:如果需要把处理后的音频回传给对方,添加下面一行 # self.audio_processor.startTransmit(audio_media)
关键细节说明
- PCM数据格式:pjsua默认使用16位有符号小端PCM,采样率通常为8kHz或16kHz,声道数默认单声道,你可以通过
audio_media的方法获取准确参数。 - 性能注意事项:
onPutFrame会被高频调用(比如8kHz采样率下每10ms触发一次),所以这里的处理逻辑要尽量轻量化,避免阻塞音频流。 - 彻底摆脱磁盘依赖:整个过程完全在内存中完成,不需要生成WAV文件,彻底避开磁盘IO的额外开销。
内容的提问来源于stack exchange,提问作者vgonisanz
相关产品推荐
相关产品推荐

