hello.py 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. #!/usr/bin/env python3
  2. # encoding:utf-8
  3. import time
  4. import json
  5. import wave
  6. import traceback
  7. import pjsua2 as pj
  8. calls = {}
  9. recording_file = '/code/pjsip-apps/src/swig/python/incoming_call.wav'
  10. player_file = '/code/pjsip-apps/src/swig/python/test111.wav'
  11. # Subclass to extend the Account and get notifications etc.
  12. class Account(pj.Account):
  13. def __init__(self):
  14. pj.Account.__init__(self)
  15. def onRegState(self, prm):
  16. print("***OnRegState: " + prm.reason)
  17. def onIncomingCall(self, prm):
  18. print("***onIncomingCall: ", prm.callId)
  19. call = MyCall(self, prm.callId)
  20. call_op_param = pj.CallOpParam(True)
  21. call_op_param.statusCode = pj.PJSIP_SC_OK
  22. call.answer(call_op_param)
  23. calls[prm.callId] = call
  24. class MyAudioMediaPort(pj.AudioMediaPort):
  25. def __init__(self):
  26. pj.AudioMediaPort.__init__(self)
  27. # 打开一个 .pcm 文件来保存音频流(可选:保存为 .wav)
  28. self.wav = wave.open(f"{recording_file}", "wb")
  29. self.wav.setnchannels(1)
  30. self.wav.setsampwidth(2) # 假设每个样本是 16 位(2 字节)
  31. self.wav.setframerate(16000)
  32. def onFrameRequested(self, frame):
  33. print("Request audio frame:", frame)
  34. def onFrameReceived(self, frame):
  35. self.wav.writeframes(bytes(frame.buf))
  36. # print("Received audio frame:", frame.buf, frame.size)
  37. class MyCall(pj.Call):
  38. def __init__(self, acc, call_id):
  39. pj.Call.__init__(self, acc, call_id)
  40. self.call_id = call_id
  41. self.audio_port = None
  42. self.aud_med = None
  43. self.recorder = None
  44. self.player = None # 用于播放录音的媒体播放器
  45. def onDtmfDigit(self, prm):
  46. digit = prm.digit
  47. print(f"Received DTMF digit: {digit}")
  48. def onCallState(self, prm):
  49. call_info = self.getInfo()
  50. print("Call state: ", call_info.stateText, dir(call_info))
  51. # if call_info.state == pj.PJSIP_INV_STATE_CONFIRMED:
  52. # # 当呼叫状态为已确认(即接通)
  53. # audio_media = self.getAudioMedia() # 获取音频媒体对象
  54. # audio_media.startTransmit(audio_media) # 这里可以对音频流进行处理
  55. # print ('11111111111')
  56. if call_info.state == pj.PJSIP_INV_STATE_DISCONNECTED:
  57. print("通话结束")
  58. self.delete()
  59. def onCallMediaState(self, prm):
  60. call_info = self.getInfo()
  61. print("Call Media state: ", call_info.stateText)
  62. for media in call_info.media:
  63. if media.type == pj.PJMEDIA_TYPE_AUDIO and \
  64. (media.status == pj.PJSUA_CALL_MEDIA_ACTIVE):
  65. self.aud_med = self.getAudioMedia(media.index)
  66. try:
  67. self.audio_port = MyAudioMediaPort()
  68. self.audio_port.createPort("Incoming Call Port", self.build_audio_format())
  69. self.aud_med.startTransmit(self.audio_port)
  70. # 录制来电声音
  71. # self.recorder = pj.AudioMediaRecorder()
  72. # self.recorder.createRecorder(recording_file)
  73. # self.aud_med.startTransmit(self.recorder)
  74. # self.send_audio_to_asr()
  75. # 播放其它录音文件
  76. self.player = pj.AudioMediaPlayer()
  77. self.player.createPlayer(player_file)
  78. self.player.startTransmit(self.aud_med)
  79. # 显示播放进度
  80. # self.display_playback_progress()
  81. except Exception as e:
  82. traceback.print_exc()
  83. def build_audio_format(self):
  84. fmt = pj.MediaFormatAudio()
  85. fmt.type = pj.PJMEDIA_TYPE_AUDIO
  86. fmt.id = pj.PJMEDIA_FORMAT_PCM
  87. fmt.clockRate = 16000 # 采样率
  88. fmt.channelCount = 1 # 通道数
  89. fmt.frameTimeUsec = 20000 # 每帧的时间(20 毫秒)
  90. fmt.bitsPerSample = 16 # 每个采样的位数
  91. return fmt
  92. def display_playback_progress(self):
  93. while self.player:
  94. # 获取当前播放位置和总时长
  95. current_pos = self.player.getPos()
  96. player_info = self.player.getInfo()
  97. print (current_pos, player_info.sizeBytes, player_info.sizeSamples)
  98. total_duration = player_info.sizeBytes
  99. if total_duration > 0:
  100. progress = (current_pos / total_duration) * 100
  101. print(f"播放进度: {progress:.2f}%")
  102. time.sleep(1) # 每隔1秒更新一次进度
  103. def stopMedia(self):
  104. pass
  105. # if self.player:
  106. # self.player.stopTransmit(self.aud_med)
  107. # self.player = None
  108. # if self.recorder:
  109. # self.recorder.stopTransmit(self.aud_med)
  110. # self.recorder = None
  111. def delete(self):
  112. self.stopMedia()
  113. # pjsua2 test function
  114. def pjsua2_test():
  115. # Create and initialize the library
  116. ep = pj.Endpoint()
  117. ep_cfg = pj.EpConfig()
  118. try:
  119. ep.libCreate()
  120. ep.libInit(ep_cfg)
  121. aud_dev_mgr = ep.audDevManager()
  122. aud_dev_mgr.setNullDev() # 使用虚拟音频设备(如果没有实际设备)
  123. # Create SIP transport. Error handling sample is shown
  124. sipTpConfig = pj.TransportConfig()
  125. sipTpConfig.port = 30506
  126. ep.transportCreate(pj.PJSIP_TRANSPORT_UDP, sipTpConfig)
  127. # Start the library
  128. ep.libStart()
  129. acfg = pj.AccountConfig()
  130. acfg.idUri = "sip:1001@172.16.12.16:5060"
  131. acfg.regConfig.registrarUri = "sip:172.16.12.16:5060"
  132. cred = pj.AuthCredInfo("digest", "*", "1001", 0, "slibra@#123456")
  133. # acfg.idUri = "sip:1013@test-bot.shuiditech.com:30506"
  134. # acfg.regConfig.registrarUri = "sip:test-bot.shuiditech.com:30506"
  135. # cred = pj.AuthCredInfo("digest", "*", "1013", 0, "000000")
  136. acfg.sipConfig.authCreds.append(cred)
  137. # Create the account
  138. acc = Account()
  139. acc.create(acfg)
  140. try:
  141. while True:
  142. ep.libHandleEvents(100)
  143. except KeyboardInterrupt:
  144. print('Existing...')
  145. # while True:
  146. # # Here we don't have anything else to do..
  147. # time.sleep(10);
  148. finally:
  149. # Destroy the library
  150. ep.libDestroy()
  151. #
  152. # main()
  153. #
  154. if __name__ == "__main__":
  155. pjsua2_test()