PJSUA2-Python-如何处理回调和createRecorder?

PJSUA2-Python-如何处理回调和createRecorder?,python,python-3.x,pjsip,pjsua2,Python,Python 3.x,Pjsip,Pjsua2,在浏览了PJSIP库站点中可用的pygui代码之后,我修改了下面的示例。我有两个问题 在每个回调函数中,最后我需要添加一个伪raise异常,否则它会出现错误。例如,如果我注释onIncomingCall的虚拟异常,传入呼叫将断开连接,并出现500错误。在pyGUI中,ttk.master.after()似乎起着关键作用。因为我正在一个无头服务器(仅指cli)中尝试它,所以不确定如何处理它 当我尝试创建记录器时,出现以下错误: 回溯(最后一次调用):文件“pjsua2_cli_demo.py”,第

在浏览了PJSIP库站点中可用的pygui代码之后,我修改了下面的示例。我有两个问题

  • 在每个回调函数中,最后我需要添加一个伪raise异常,否则它会出现错误。例如,如果我注释onIncomingCall的虚拟异常,传入呼叫将断开连接,并出现500错误。在pyGUI中,ttk.master.after()似乎起着关键作用。因为我正在一个无头服务器(仅指cli)中尝试它,所以不确定如何处理它

  • 当我尝试创建记录器时,出现以下错误:

  • 回溯(最后一次调用):文件“pjsua2_cli_demo.py”,第行 33岁,在美国 createRecorder('xxxxxxxxxx/PJSUA2/example/pygui/file.wav'); 文件“xxxxxxxxxx/.local/lib/python3.6/site packages/pjsua2.py”,第行 4110,在createRecorder中 return _pjsua2.AudioMediaRecorder_createRecorder(自身、文件名、加密类型、最大大小、选项)未实现错误:错误的数字或类型 重载函数的参数类型 “AudioMediaRecorder\u createRecorder”。可能的C/C++原型包括: pj::AudioMediaRecorder::createRecorder(pj::字符串常量&,无符号整数,pj_ssize_t,无符号整数) pj::AudioMediaRecorder::createRecorder(pj::字符串常量&,无符号整数,pj_ssize_t) pj::AudioMediaRecorder::createRecorder(pj::字符串常量&,无符号整数) pj::AudioMediaRecorder::createRecorder(pj::string常量&)

    实际修改代码:

    import pjsua2 as pj
    import time
    # Subclass to extend the Account and get notifications etc.
    
    ep=None
    # 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.aud_med=pj.AudioMedia
    
        def onCallState(self, prm):
            ci = self.getInfo()
            self.connected = ci.state == pj.PJSIP_INV_STATE_CONFIRMED
            self.recorder=None
            if(self.connected ==True):
                player=pj.AudioMediaPlayer()
                #Play welcome message
                player.createPlayer('xxxxxxxxxxxxxx/PJSUA2/example/pygui/welcomeFull.wav');
    
                self.recorder=pj.AudioMediaRecorder()
                self.recorder.createRecorder('xxxxxxxxxxx/PJSUA2/example/pygui/file.wav', enc_type=0, max_size=0, options=0);
                i=0
                for media in ci.media:
    
                    if (media.type == pj.PJMEDIA_TYPE_AUDIO):
                        self.aud_med = self.getMedia(i);
                        break;
                    i=i+1;
                if self.aud_med!=None:
                    # This will connect the sound device/mic to the call audio media
                    mym= pj.AudioMedia.typecastFromMedia(self.aud_med)
                    player.startTransmit( mym);
                    #mym.startTransmit( self.recorder);        
            if(ci.state==pj.PJSIP_INV_STATE_DISCONNECTED):
                print(">>>>>>>>>>>>>>>>>>>>>>> Call disconnected")
                #mym= pj.AudioMedia.typecastFromMedia(self.aud_med)
                #mym.stopTransmit(self.recorder);
            raise Exception('onCallState done!')        
    
    
            if self.chat:
                self.chat.updateCallState(self, ci)
    
        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):
                    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 onRegState(self, prm):
            print ("***OnRegState: " + prm.reason)
        def onIncomingCall(self, prm):
            c = Call(self, call_id=prm.callId)
            call_prm = pj.CallOpParam()
            call_prm.statusCode = 180
            c.answer(call_prm)
    
            ci = c.getInfo()
            msg = "Incoming call  from  '%s'" % (ci.remoteUri)
            print(msg)
            call_prm.statusCode = 200
            c.answer(call_prm)
            raise Exception('onIncomingCall done!')        
    
    
    
    # pjsua2 test function
    def pjsua2_test():
        # Create and initialize the library
        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();
        acc.create(acfg)
    
    
        while True:    
            ep.libHandleEvents(10)
    
    
        ep.libDestroy()
        del ep;
    
    #
    # main()
    #
    if __name__ == "__main__":
        pjsua2_test()
    

    在编译pjsua swig之前,将以下行添加到pjsip apps/src/swig文件夹中的pjsua2.i

    %inline %{
    pj_ssize_t new_pj_ssize_t(int s) {
       return (pj_ssize_t) s;
    }
    %}
    
    使用这个额外的函数,您可以创建一个pj_ssize_t类型的变量,并将其传递给createRecorder函数

    max_size=pj.new_pj_ssize_t(0)
    recorder.createRecorder(file_to_record, max_size=max_size)
    

    基于讨论

    的解决方法,你能解决这个问题吗?不,我转到C++。但我能够解决除createRecorder之外的所有问题。此外,我还通过使用ffmpeg直接指向文件进行了POC。如果感兴趣,将上传到github并共享。想法是创建一个虚拟音频设备,并将其用作终端设备,在Linux操作系统级别使用ffmpeg写入文件。我想知道您是如何解决onIncomingCall上的回调问题的。你能通过github共享POC吗?不幸的是,我的硬盘坏了。我能恢复的,我上传到了。尚未测试(恢复后)。它还具有将音频发送到虚拟声音设备的代码,虚拟声音设备将进一步使用ffmpeg将语音重定向到wav文件。你会有一个想法的。