sippjsippjsua2

How to send an audio file in a call


So, I want to make a call in pjsua2 python library and attach an audio along with it after answer but it doesn't seem to work correctly after call is confirmed.

This doesn't work:

class Call(pj.Call):
    def __init__(self, acc):
        pj.Call.__init__(self, acc)

    def onCallMediaState(self, prm):
        print("Call media state changed")
        ci = self.getInfo()

        if ci.state == pj.PJSIP_INV_STATE_CONFIRMED:
            print("Call is confirmed, starting audio playback")
            player = pj.AudioMediaPlayer()
            player.createPlayer("/root/audio.wav")
            aud_med = self.getAudioMedia(-1)
            player.startTransmit(aud_med)

but this works when i run it after being in a call for a while (3 - 4 seconds):

player = pj.AudioMediaPlayer()
player.createPlayer("/root/audio.wav", pj.PJMEDIA_FILE_NO_LOOP)
aud_med = call.getAudioMedia(-1)
player.startTransmit(aud_med)

This is my full code:

import pjsua2 as pj

ep_cfg = pj.EpConfig()
ep = pj.Endpoint()
ep.libCreate()
ep.libInit(ep_cfg)
ep_cfg.uaConfig.threadCnt = 0

sipTpConfig = pj.TransportConfig()
sipTpConfig.port = 5060
tp = ep.transportCreate(pj.PJSIP_TRANSPORT_UDP, sipTpConfig)
ep.libStart()

acfg = pj.AccountConfig()

acfg.idUri = "caller_id <sip:username@sip.example.com>"
acfg.regConfig.registrarUri = "sip:sip.example.com"

acfg.sipConfig.authCreds.append(pj.AuthCredInfo("digest", "*", "username", 0, "password"))

# Create the account
acc = pj.Account()

acc.create(acfg)

call = pj.Call(acc)
prm = pj.CallOpParam(True)

call.makeCall('sip:phone_number@sip.example.com', prm)

Solution

  • It was pain as hell but i finally figured it out:

    added self.player = None

    apparently you need to store a reference to the player object at a class level or in some other persistent scope.

    class Call(pj.Call):
        def __init__(self, acc):
            pj.Call.__init__(self, acc)
            self.player = None
    
        def onCallMediaState(self, prm):
            print("Call media state changed")
            ci = self.getInfo()
    
            if ci.state == pj.PJSIP_INV_STATE_CONFIRMED:
                print("Call is confirmed, starting audio playback")
                self.player = pj.AudioMediaPlayer()  # Use the class level attribute
                self.player.createPlayer("/root/audio.wav", pj.PJMEDIA_FILE_NO_LOOP)
                aud_med = self.getAudioMedia(-1)
                self.player.startTransmit(aud_med)
    

    for anyone struggling, make sure you install dummy soundcard (snd-dummy) on linux and all the drivers.