我正在基于pjsua2使用python开发SIP客户端。我有一个基于python wrapper call的自定义Call类,并且我的代码能够建立活动连接。在我的自定义onCallMediaState
上,我可以访问音频会议桥:
def onCallMediaState(self, prm):
"""
Manage call media state callbacks.
- Autoconnect audio
"""
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":
"""
It seems a bug with callbacks. CONFIRMED
is send at start and disconnect. So stop
record is manual, cannot use DISCONNECTD
"""
logger.info("Call CONFIRMED")
此时,我可以使用media_index
录制或播放从呼叫传入的音频。例如,用于记录:
def record_call(self, media_index):
"""
Record the audio incoming from call using default playback device
"""
record_media = pj.Endpoint_instance().audDevManager().getCaptureDevMedia()
audio_media = pj.AudioMedia.typecastFromMedia(self.getMedia(media_index))
port_id = audio_media.getPortId()
rx_level = audio_media.getRxLevel()
tx_level = audio_media.getTxLevel()
filename = "file.wav"
logger.info("Recording audio media", port_id=port_id, rx_level=rx_level, tx_level=tx_level)
self._recorder = pj.AudioMediaRecorder()
self._recorder.createRecorder(filename);
self._is_recording = True
record_media.startTransmit(self._recorder)
然后创建一个file.wav。或用于使用默认音频设备:
def play_call(self, media_index):
"""
Play the audio incoming from call using default playback device
"""
playback_media = pj.Endpoint_instance().audDevManager().getPlaybackDevMedia()
audio_media = pj.AudioMedia.typecastFromMedia(self.getMedia(media_index))
port_id = audio_media.getPortId()
rx_level = audio_media.getRxLevel()
tx_level = audio_media.getTxLevel()
logger.info("Playing audio media", port_id=port_id, rx_level=rx_level, tx_level=tx_level)
audio_media.startTransmit(playback_media)
两个示例都起作用,并且根据PjSUA2 Media documentation和Audio media documentation,可以发送和接收音频,播放和记录WAV。但是根据pjsip Media Port documentation,其他媒体也是可能的。似乎SWIG wrapper不支持它。
最后,我的问题是,可以在不记录wav文件的情况下管理内存中的音频帧吗?
我不想将音频写入硬盘,仅在内存中使用它,为此,我直接需要原始数据。一种解决方法是编写一个大块的wav文件,并逐个读取它,但这是一个肮脏的解决方案,且开销很大。根据Media flow documentation,可以获取回调,但是我找不到如何在Python中执行此操作。试图绕过回调的python包装器中不存在typedef void *MediaPort
。
我一直在研究相同的东西,但是是pjsua而不是pjsua2。最初,pjsip不支持pjsua(不确定pjsua2),但是我在GitHub上找到了一个项目,该项目具有pjproject 2.2的自定义功能,带有缓冲流,称为“ UFAL-DSG / alex”。
我将定制移植到了“ nicolaipre / python3-pjsip-memory-buffer”中的python3和pjproject 2.9。
我知道它可能不适用于pjsua2,但也许可以帮助其他人寻找类似的东西。