As I could not get any clue from here for Audio recorder, I tried to create virtual sound device using pulse audio and pipe that to a wave file. It worked. But now I am unable to route the audio to both speaker and this virtual device. How can I do it?
ep.audDevManager().setPlaybackDev(self.acc.callerVoiceRecorderDeviceID);
am.startTransmit(ep.audDevManager().getPlaybackDevMedia())
ep.audDevManager().setPlaybackDev(self.acc.speakerDeviceID);
am.startTransmit(ep.audDevManager().getPlaybackDevMedia())
self.acc.callerVoiceRecorderDeviceID points to virtual device ID and self.acc.speakerDeviceID
points to speaker.
What I observed
is voice is getting directed to second device and not to first one. Log shows
18:22:05.081
pjsua_call.c Answering call 0: code=200
18:22:05.081 pjsua_media.c ...Call 0: updating media.. 18:22:05.081 pjsua_media.c .....Media stream call00:0 is destroyed 18:22:05.082 pjsua_aud.c ....Audio channel update.. 18:22:05.082 strm0x235ef88 .....VAD temporarily disabled 18:22:05.082 strm0x235ef88 .....Encoder stream started 18:22:05.082 strm0x235ef88 .....Decoder stream started 18:22:05.082 pjsua_media.c ....Audio updated, stream #0: PCMU (sendrecv) 18:22:05.082 pjsua_aud.c ...Set sound device: capture=-1, playback=3 18:22:05.082 pjsua_aud.c ...Conf connect: 1 --> 0 18:22:05.082 pjsua_aud.c ....Set sound device: capture=-1, playback=3 18:22:05.082 pjsua_aud.c .....Opening sound device (speaker + mic) PCM@16000/1/20ms 18:22:05.090 ec0x2371c80 ......AEC created, clock_rate=16000, channel=1, samples per frame=320, tail length=200 ms, latency=0 ms 18:22:05.090 conference.c ....Port 1 (sip:192.168.1.3) transmitting to port 0 (default) 18:22:05.090 pjsua_aud.c ...Set sound device: capture=-1, playback=2 18:22:05.090 pjsua_aud.c .....Closing CallerVoice sound playback device and default sound capture device 18:22:05.110 pjsua_aud.c !....Opening sound device (speaker + mic) PCM@16000/1/20ms 18:22:05.119 ec0x238ff80 .....AEC created, clock_rate=16000, channel=1, samples per frame=320, tail length=200 ms, latency=0 ms 18:22:05.120 pjsua_aud.c ...Conf connect: 1 --> 0 18:22:05.120 pjsua_core.c !....TX 928 bytes Response msg 200/INVITE/cseq=4969 (tdta0x237ab38) to UDP 192.168.1.3:5060: When I switch from playback 3 (virtual) to 2 (speaker), it disconnects 3 as per log. How can I send caller voice to two sinks?
As I am running
it inside a docker and both sinks are actually virtual devices created thru pulse audio. I am trying to use one for full audio recording and another one for caller audio monitoring. Full code, if it helps is below. As per this code, full audio recording works
(both caller voice and outgoing wave file being played). I am looking for another recorder in paralllel which will only record caller audio.
------------------------------------
import
pjsua2 as pj
#import time
# Subclass to extend the Account and get notifications etc.
#from concurrent.futures import ProcessPoolExecutor
# Call class
class Call(pj.Call):
"""
High level Python Call object, derived from pjsua2's Call object.
"""
def __init__(self, acc, peer_uri='', chat=None, call_id = pj.PJSUA_INVALID_ID):
pj.Call.__init__(self, acc, call_id)
self.acc = acc
self._onhold_ = False
self.am=None
self.recorder=None
self.connected=False
self.canConnectPlayer=False
def onCallState(self, prm):
ci = self.getInfo()
connected = ci.state == pj.PJSIP_INV_STATE_CONFIRMED
if(connected==True):
self.connected=True
print("########################################## Call connected")
if(ci.state==pj.PJSIP_INV_STATE_DISCONNECTED):
self.connected=False
self.am=None
self.canConnectPlayer=False
print(">>>>>>>>>>>>>>>>>>>>>>> Call disconnected")
def onCallMediaState(self, prm):
ci = self.getInfo()
for mi in ci.media:
if mi.type == pj.PJMEDIA_TYPE_AUDIO and \
(mi.status == pj.PJSUA_CALL_MEDIA_ACTIVE or \
mi.status == pj.PJSUA_CALL_MEDIA_REMOTE_HOLD):
m = self.getMedia(mi.index)
am = pj.AudioMedia.typecastFromMedia(m)
# connect ports
#ep.audDevManager().getCaptureDevMedia().startTransmit(am)
ep.audDevManager().setPlaybackDev(self.acc.callerVoiceRecorderDeviceID);
am.startTransmit(ep.audDevManager().getPlaybackDevMedia())
ep.audDevManager().setPlaybackDev(self.acc.fullRecorderDeviceID);
am.startTransmit(ep.audDevManager().getPlaybackDevMedia())
self.am=am
self.canConnectPlayer=True
if mi.status == pj.PJSUA_CALL_MEDIA_REMOTE_HOLD and not self.onhold:
#self.chat.addMessage(None, "'%s' sets call onhold" % (self.peerUri))
self._onhold_ = True
elif mi.status == pj.PJSUA_CALL_MEDIA_ACTIVE and self.onhold:
#self.chat.addMessage(None, "'%s' sets call active" % (self.peerUri))
self._onhold_ = False
#raise Exception('onCallMediaState done!')
class Account(pj.Account):
def __init__(self, ep=None):
pj.Account.__init__(self)
self.ep=ep
self.c=None
self.acceptCall=False;
self.inCall=False;
self.call_id=None
self.callerVoiceRecorderDeviceID=None
self.fullRecorderDeviceID=None
def onRegState(self, prm):
print ("***OnRegState: " + prm.reason)
def onIncomingCall(self, prm):
self.call_id==prm.callId
self.acceptCall=True
self.c = Call(self, call_id=prm.callId)
ci = self.c.getInfo()
msg = "Incoming call from '%s'" % (ci.remoteUri)
print(msg)
self.inCall=True
# pjsua2 test function
def pjsua2_test():
# Create and initialize the library
global ep
ep_cfg = pj.EpConfig()
ep_cfg.uaConfig.threadCnt = 0
ep_cfg.uaConfig.mainThreadOnly = False
ep = pj.Endpoint()
ep.libCreate()
ep.libInit(ep_cfg)
# Create SIP transport. Error handling sample is shown
sipTpConfig = pj.TransportConfig();
sipTpConfig.port = 12345;
tp=ep.transportCreate(pj.PJSIP_TRANSPORT_UDP, sipTpConfig);
# Start the library
ep.libStart();
acfg = pj.AccountConfig();
acfg.idUri = "sip:192.168.1.11:12345";
# Create the account
acc = Account(ep);
acc.create(acfg)
#Get device list and collect device IDs of two virtual devices created
ep.audDevManager().refreshDevs();
devList=ep.audDevManager().enumDev()
fullRecorderDeviceID=0
devID=0
for dev in devList:
print(dev.name)
if(dev.name=="FullRecorder"):
acc.fullRecorderDeviceID=devID
if(dev.name=="CallerVoice"):
acc.callerVoiceRecorderDeviceID=devID
devID=devID+1
while True:
ep.libHandleEvents(10)
if(acc.acceptCall==True):
acc.acceptCall=False;
call_prm = pj.CallOpParam()
call_prm.statusCode = 200
acc.c.answer(call_prm)
if(acc.c.canConnectPlayer==True and acc.c.am!=None ):
acc.c.canConnectPlayer=False
player=pj.AudioMediaPlayer()
#Play welcome message
fn=u'/PJSUA2/example/welcomeFull.wav'
player.createPlayer(fn, pj.PJMEDIA_FILE_NO_LOOP);
# This will connect the sound device/mic to the call audio media
player.startTransmit( acc.c.am);
player.startTransmit( ep.audDevManager().getPlaybackDevMedia());
ep.libDestroy()
del ep;
#
# main()
#
if __name__ == "__main__":
#recorder=pj.AudioMediaRecorder()
#recorder.createRecorder("123.wav");
pjsua2_test();
-----------------------------------
Thanks
Sekar
From: Sekar S
Sent: Saturday, January 19, 2019 8:33 PM To: pjsip@xxxxxxxxxxxxxxx Subject: PJSUA2 - Python3 Create Recorder fails with error Wrong number or type of arguments for overloaded function
Hi all,
Even a simple 3 line code is giving error. Can anyone help on this? Where can I get any kind of help
import pjsua2 as pj
recorder=pj.AudioMediaRecorder()
recorder.createRecorder('file.wav');
return _pjsua2.AudioMediaRecorder_createRecorder(self, file_name, enc_type, max_size, options)
NotImplementedError: Wrong number or type of arguments for overloaded function 'AudioMediaRecorder_createRecorder'.
Possible C/C++ prototypes are:
pj::AudioMediaRecorder::createRecorder(pj::string const &,unsigned int,pj_ssize_t,unsigned int)
pj::AudioMediaRecorder::createRecorder(pj::string const &,unsigned int,pj_ssize_t)
pj::AudioMediaRecorder::createRecorder(pj::string const &,unsigned int)
pj::AudioMediaRecorder::createRecorder(pj::string const &)
I tried trunk,2.8 and 2.7 and same error is observed. I tried to compare createPlayer code and create recorder code in generated SWIG / h files in python folders and could not find any difference. However, create player works, but create recorder doesn't. Am
I only person having this issue with Python3? Is it working for anyone else?
Any help or guidance will be highly appreciated.
Sekar
|
_______________________________________________ Visit our blog: http://blog.pjsip.org pjsip mailing list pjsip@xxxxxxxxxxxxxxx http://lists.pjsip.org/mailman/listinfo/pjsip_lists.pjsip.org