I'm developing a SIP client using python, based on pjsua2. I have a custom Call class based on python wrapper call and my code is able to get an active connection. On my custom onCallMediaState
, I have access to the Audio Conference Bridge:
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")
At this point I can use media_index
to record or play the audio incoming from the call. In example, for recording:
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)
And a file.wav is created. Or for use default audio device:
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)
Both examples work and according to PjSUA2 Media documentation and Audio media documentation it is possible transmit and receive audio, play and record WAV. But according with pjsip Media Port documentation other medias are possible. It seems that SWIG wrapper do not support it.
Finally, my question, Is it possible to manage the audio frame in memory without record a wav file?
I do not want to write in the hard disk the audio, just use it in memory, and for this purpose I need the raw data directly. One workaround is to write a chunk wav file, and read it one by one, but this is a dirty solution with a big overhead. According to Media flow documentation it is possible to get the callbacks, but I cannot find how to do this in Python. It doesn't exist the typedef void *MediaPort
in the python wrapper to try to bypass the callbacks.