PJSUA2 - Python3 Create Recorder fails with error Wrong number or type of arguments for overloaded function

SS
Sekar S
Sat, Jan 19, 2019 3:03 PM

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

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
SS
Sekar S
Sat, Jan 26, 2019 6:36 PM

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@lists.pjsip.org
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

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@lists.pjsip.org 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