PyVoIp отправляет звук в очень плохом качестве - просто шум
Я использую pyvoip 2.0.0-dev(потому что она поддерживает OPTIONS запросы и digest auth). Я использую этот аудио файл. Когда вызываю функцию write_audio в телефоне слышны только шумы. Это может быть связано с тем что sip сервер не поддерживает PCMU/PCMA кодеки или другые проблемы с сервером?
Возникла вторая проблема - функция read_audio не работает, ничего не возвращает
def voip_callback(call: VoIPCall):
print("CALLBACK STATEE", call.state)
while call.state == CallState.ANSWERED:
r = call.read_audio(blocking=True)
print(r)
call.write_audio(r)
time.sleep(0.01)
Если blocking=True
цикл блочиться, если blocking=False
всегда возвращаются одинаковые пакеты:
b'\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80'
Если записать это аудио в файл - ничего не услышишь. Если отправлять сразу в write_audio - в телефоне тоже ничего не услышишь
Полный код оставлю здесь, выше виделил только основной:
def voip_callback(self, call: VoIPCall):
is_incoming_call = call.id not in self.calls
if is_incoming_call:
phone = call.request.headers["From"]["user"]
self.calls[call.id] = call
self.ws.send_sync({
"status": "success",
"event": "calls:incoming_call",
"data": {"call_id": call.id, "state": "PENDING", "phone": phone}
})
else:
phone = call.request.headers["To"]["user"]
self.voice_buffers[call.id] = {
"receive": BytesIO(),
"send": BytesIO()
}
self.calls_statuses[call.id] = {
"webrtc": False,
"ws": False
}
start_time = time.time()
answered_at = 0
wait_sound_is_activated = False
dialing_sound_is_activated = False
is_answered = False
not_connect_webrtc_sound_is_activated = False
sent_is_answered_by_user = False
stop_at = None
try:
while call.state != CallState.ENDED:
now = time.time()
call_seconds = now-start_time
if answered_at != 0:
answered_seconds = now-answered_at
else:
answered_seconds = 0
print(call.state)
call_status = self.calls_statuses[call.id]
if stop_at is not None and now >= stop_at:
if call.state in (CallState.DIALING, CallState.PROGRESS):
call.cancel()
else:
try:
call.hangup()
except InvalidStateError:
call.bye()
break
if call.state == CallState.ANSWERED and not is_incoming_call and not sent_is_answered_by_user:
# Send ws message when user answer the call
self.ws.send_sync({
"status": "success",
"event": "calls:answered",
"data": {"call_id": call.id, "state": "ANSWERED"}
})
sent_is_answered_by_user = True
operator_is_connected = call_status["webrtc"] and call_status["ws"]
if call.state == CallState.ANSWERED and operator_is_connected:
# User and operator can speak only if call is answered and operator connect by ws and webrtc
is_answered = True
if answered_at == 0:
answered_at = now
self.voice_buffers[call.id]["receive"].write(call.read_audio(blocking=False))
call.write_audio(self.voice_buffers[call.id]["send"].read())
elif (
call.state == CallState.ANSWERED and
answered_seconds >= 15 and
call_status["ws"] and
not call_status["webrtc"] and
not not_connect_webrtc_sound_is_activated
):
# If operator doenst connect to webrtc
print("ANSWERED 2: Operator dont connected to webrtc after 15 seconds")
call.write_audio(self.wait_sound)
stop_at = now+30
not_connect_webrtc_sound_is_activated = True
elif (
call.state == CallState.RINGING and
call_seconds >= 30 and
is_incoming_call and
not wait_sound_is_activated
):
# User wait for operator answer
print("RINGING 1: User wait for operator answer")
# call.write_audio(self.wait_sound)
stop_at = now+30
wait_sound_is_activated = True
elif (
call.state in (CallState.DIALING, CallState.PROGRESS) and
call_seconds >= 10 and
not is_incoming_call and
not dialing_sound_is_activated and
operator_is_connected
):
# Operator wait for user answer
print("DIALING 1: Operator wait for user answer")
self.voice_buffers[call.id]["receive"].write(self.dialing_sound)
stop_at = now+10
dialing_sound_is_activated = True
elif (
call.state == CallState.ANSWERED and
call_seconds >= 5 and
not is_incoming_call and
not dialing_sound_is_activated
):
print("ELSE, FOR TESTING WRITE AUDIO")
call.write_audio(self.wait_sound)
stop_at = now+30
dialing_sound_is_activated = True
time.sleep(0.01)
except Exception as e:
print(e)
finally:
self.calls.pop(call.id)
self.calls_statuses.pop(call.id)
self.ws.send_sync({
"status": "success",
"event": "calls:ended",
"data": {
"state": "LOST" if is_incoming_call and not is_answered else "ENDED",
"call_id": call.id
}
})
Возможно есть какие-то решения по улучшению, критику з радостью прийму