I added this in asterisk conf
same => n(newIvr),Log(NOTICE, Start New IVR POC flow)
same => n,AudioSocket(${UUID()},172.25.25.150:1579)
same => n,Playback(goodbye)
same => n,Hangup()
and my python audio socket server
import sys
import threading
import time
import json
import os
import audioop
import wave
import logging
import signal
from google.cloud import speech
from google.protobuf.json_format import MessageToDict
from audiosocket import Audiosocket
logging.basicConfig(
stream=sys.stdout,
format='%(asctime)s [%(levelname)s] %(message)s',
level=logging.INFO
)
log = logging.getLogger()
# Configuration
port = 1579
audiosocket = Audiosocket(("0.0.0.0", port))
speech_client = speech.SpeechClient()
def graceful_shutdown(signum, frame):
log.info("๐ Shutting down service due to signal...")
sys.exit(0)
signal.signal(signal.SIGTERM, graceful_shutdown)
signal.signal(signal.SIGINT, graceful_shutdown)
def save_raw_to_wav(call_uuid, raw_filename, wav_filename, sample_rate=8000):
try:
file_size = os.path.getsize(raw_filename)
if file_size == 0:
log.warning(f"[{call_uuid}] โ ๏ธ Raw file is empty, skipping WAV conversion")
return
with open(raw_filename, 'rb') as raw_file:
raw_data = raw_file.read()
duration_seconds = len(raw_data) / (sample_rate * 2)
if duration_seconds < 0.1:
log.warning(f"[{call_uuid}] โ ๏ธ Duration < 0.1s ({duration_seconds:.2f}s), skipping WAV conversion")
return
with wave.open(wav_filename, 'wb') as wav_file:
wav_file.setnchannels(1)
wav_file.setsampwidth(2)
wav_file.setframerate(sample_rate)
wav_file.writeframes(raw_data)
log.info(f"[{call_uuid}] โ
WAV file saved: {wav_filename} ({duration_seconds:.2f} sec)")
except Exception as e:
log.error(f"[{call_uuid}] โ Error converting raw to WAV: {e}")
def handle_call(conn):
call_uuid = conn.uuid
log.info(f"[{call_uuid}] ๐ Incoming connection with UUID: {call_uuid}")
audio_filename = f"{call_uuid}.raw"
try:
audio_file = open(audio_filename, "wb")
log.info(f"[{call_uuid}] ๐พ Opened local raw audio file for writing: {audio_filename}")
except Exception as e:
log.error(f"[{call_uuid}] โ Failed to open file {audio_filename}: {e}")
audio_file = None
def audio_generator():
total_bytes = 0
last_data_time = time.time()
start_time = time.time()
while conn.connected:
data = conn.read()
now = time.time()
if not data:
if now - last_data_time > 2:
log.info(f"[{call_uuid}] ๐ค Detected silence > 2 seconds, stopping stream")
break
time.sleep(0.05)
continue
last_data_time = now
total_bytes += len(data)
# ๐ฅ Decode G.711 ฮผ-law (8-bit) to 16-bit PCM
# decoded_data = audioop.ulaw2lin(data, 2)
decoded_data = data
if audio_file:
try:
audio_file.write(decoded_data)
except Exception as file_write_err:
log.error(f"[{call_uuid}] โ Error writing audio data: {file_write_err}")
log.info(f"[{call_uuid}] ๐ง Received {len(data)} bytes (total: {total_bytes})")
yield speech.StreamingRecognizeRequest(audio_content=decoded_data)
if now - start_time > 8:
log.info(f"[{call_uuid}] โฐ Stream duration > 8s, stopping stream")
break
log.info(f"[{call_uuid}] ๐ Finished streaming audio. Total bytes: {total_bytes}")
config = speech.RecognitionConfig(
encoding=speech.RecognitionConfig.AudioEncoding.LINEAR16,
sample_rate_hertz=8000,
language_code="en-US",
)
streaming_config = speech.StreamingRecognitionConfig(
config=config,
interim_results=False # Only final results
)
try:
log.info(f"[{call_uuid}] ๐ Starting Google Speech API streaming")
responses = speech_client.streaming_recognize(
config=streaming_config,
requests=audio_generator()
)
responses_dict = [MessageToDict(responses) for response in responses]
log.info(f"[{call_uuid}] ๐๏ธ Full responses object:\n{json.dumps(responses_dict, indent=2)}")
# โ
Process responses here directly without exhausting the generator
for response in responses:
log.info(f"[{call_uuid}] ๐๏ธ Got response from Google")
for result in response.results:
if result.is_final:
transcript = result.alternatives[0].transcript
log.info(f"[{call_uuid}] ๐ Final transcript: {transcript}")
print(f"[{call_uuid}] ๐ฃ๏ธ Final transcript: {transcript}")
except Exception as e:
log.error(f"[{call_uuid}] โ Google Speech API error: {e}")
finally:
if audio_file:
try:
audio_file.close()
log.info(f"[{call_uuid}] ๐พ Closed raw audio file: {audio_filename}")
save_raw_to_wav(call_uuid, audio_filename, f"{call_uuid}.wav")
except Exception as e:
log.error(f"[{call_uuid}] โ Error closing file: {e}")
if conn:
try:
conn.hangup()
conn.close()
log.info(f"[{call_uuid}] โ
Connection closed")
except Exception as close_err:
log.error(f"[{call_uuid}] โ Error closing connection: {close_err}")
log.info("๐ฆ Server started and listening for incoming connections")
while True:
try:
conn = audiosocket.listen()
time.sleep(0.3)
log.info("๐ Received connection from audiosocket")
# print("conn.uuid:", getattr(conn, "uuid", "no uuid"))
threading.Thread(target=handle_call, args=(conn,), daemon=True).start()
except Exception as listener_err:
log.error(f"โ Exception in main listener loop: {listener_err}")
import traceback
traceback.print_exc()
and the logs
2025-06-06 12:53:53,404 [INFO] ๐ฆ Server started and listening for incoming connections
2025-06-06 12:53:58,886 [INFO] ๐ Received connection from audiosocket
2025-06-06 12:53:58,887 [INFO] [40325ec25efd4bd3805f53576e581d13] ๐ Incoming connection with UUID: 40325ec25efd4bd3805f53576e581d13
2025-06-06 12:53:58,951 [INFO] [40325ec25efd4bd3805f53576e581d13] ๐พ Opened local raw audio file for writing: 40325ec25efd4bd3805f53576e581d13.raw
2025-06-06 12:53:58,952 [INFO] [40325ec25efd4bd3805f53576e581d13] ๐ Starting Google Speech API streaming
2025-06-06 12:53:59,323 [INFO] [40325ec25efd4bd3805f53576e581d13] ๐ง Received 320 bytes (total: 320)
2025-06-06 12:53:59,527 [INFO] [40325ec25efd4bd3805f53576e581d13] ๐ง Received 320 bytes (total: 640)
2025-06-06 12:53:59,729 [INFO] [40325ec25efd4bd3805f53576e581d13] ๐ง Received 320 bytes (total: 960)
2025-06-06 12:53:59,931 [INFO] [40325ec25efd4bd3805f53576e581d13] ๐ง Received 320 bytes (total: 1280)
2025-06-06 12:54:00,132 [INFO] [40325ec25efd4bd3805f53576e581d13] ๐ง Received 320 bytes (total: 1600)
2025-06-06 12:54:00,334 [INFO] [40325ec25efd4bd3805f53576e581d13] ๐ง Received 320 bytes (total: 1920)
2025-06-06 12:54:00,536 [INFO] [40325ec25efd4bd3805f53576e581d13] ๐ง Received 320 bytes (total: 2240)
2025-06-06 12:54:00,737 [INFO] [40325ec25efd4bd3805f53576e581d13] ๐ง Received 320 bytes (total: 2560)
2025-06-06 12:54:00,939 [INFO] [40325ec25efd4bd3805f53576e581d13] ๐ง Received 320 bytes (total: 2880)
2025-06-06 12:54:01,141 [INFO] [40325ec25efd4bd3805f53576e581d13] ๐ง Received 320 bytes (total: 3200)
2025-06-06 12:54:01,348 [INFO] [40325ec25efd4bd3805f53576e581d13] ๐ง Received 320 bytes (total: 3520)
2025-06-06 12:54:01,550 [INFO] [40325ec25efd4bd3805f53576e581d13] ๐ง Received 320 bytes (total: 3840)
2025-06-06 12:54:01,753 [INFO] [40325ec25efd4bd3805f53576e581d13] ๐ง Received 320 bytes (total: 4160)
2025-06-06 12:54:01,959 [INFO] [40325ec25efd4bd3805f53576e581d13] ๐ง Received 320 bytes (total: 4480)
2025-06-06 12:54:02,164 [INFO] [40325ec25efd4bd3805f53576e581d13] ๐ง Received 320 bytes (total: 4800)
2025-06-06 12:54:02,369 [INFO] [40325ec25efd4bd3805f53576e581d13] ๐ง Received 320 bytes (total: 5120)
2025-06-06 12:54:02,572 [INFO] [40325ec25efd4bd3805f53576e581d13] ๐ง Received 320 bytes (total: 5440)
2025-06-06 12:54:02,778 [INFO] [40325ec25efd4bd3805f53576e581d13] ๐ง Received 320 bytes (total: 5760)
2025-06-06 12:54:02,985 [INFO] [40325ec25efd4bd3805f53576e581d13] ๐ง Received 320 bytes (total: 6080)
2025-06-06 12:54:03,194 [INFO] [40325ec25efd4bd3805f53576e581d13] ๐ง Received 320 bytes (total: 6400)
2025-06-06 12:54:03,404 [INFO] [40325ec25efd4bd3805f53576e581d13] ๐ง Received 320 bytes (total: 6720)
2025-06-06 12:54:03,606 [INFO] [40325ec25efd4bd3805f53576e581d13] ๐ง Received 320 bytes (total: 7040)
2025-06-06 12:54:03,808 [INFO] [40325ec25efd4bd3805f53576e581d13] ๐ง Received 320 bytes (total: 7360)
2025-06-06 12:54:04,011 [INFO] [40325ec25efd4bd3805f53576e581d13] ๐ง Received 320 bytes (total: 7680)
2025-06-06 12:54:04,213 [INFO] [40325ec25efd4bd3805f53576e581d13] ๐ง Received 320 bytes (total: 8000)
2025-06-06 12:54:04,416 [INFO] [40325ec25efd4bd3805f53576e581d13] ๐ง Received 320 bytes (total: 8320)
2025-06-06 12:54:04,619 [INFO] [40325ec25efd4bd3805f53576e581d13] ๐ง Received 320 bytes (total: 8640)
2025-06-06 12:54:04,821 [INFO] [40325ec25efd4bd3805f53576e581d13] ๐ง Received 320 bytes (total: 8960)
2025-06-06 12:54:05,044 [INFO] [40325ec25efd4bd3805f53576e581d13] ๐ง Received 320 bytes (total: 9280)
2025-06-06 12:54:05,246 [INFO] [40325ec25efd4bd3805f53576e581d13] ๐ง Received 320 bytes (total: 9600)
2025-06-06 12:54:05,447 [INFO] [40325ec25efd4bd3805f53576e581d13] ๐ง Received 320 bytes (total: 9920)
2025-06-06 12:54:05,649 [INFO] [40325ec25efd4bd3805f53576e581d13] ๐ง Received 320 bytes (total: 10240)
2025-06-06 12:54:05,851 [INFO] [40325ec25efd4bd3805f53576e581d13] ๐ง Received 320 bytes (total: 10560)
2025-06-06 12:54:06,053 [INFO] [40325ec25efd4bd3805f53576e581d13] ๐ง Received 320 bytes (total: 10880)
2025-06-06 12:54:06,255 [INFO] [40325ec25efd4bd3805f53576e581d13] ๐ง Received 320 bytes (total: 11200)
2025-06-06 12:54:06,458 [INFO] [40325ec25efd4bd3805f53576e581d13] ๐ง Received 320 bytes (total: 11520)
2025-06-06 12:54:06,659 [INFO] [40325ec25efd4bd3805f53576e581d13] ๐ง Received 320 bytes (total: 11840)
2025-06-06 12:54:06,861 [INFO] [40325ec25efd4bd3805f53576e581d13] ๐ง Received 320 bytes (total: 12160)
2025-06-06 12:54:07,063 [INFO] [40325ec25efd4bd3805f53576e581d13] ๐ง Received 320 bytes (total: 12480)
2025-06-06 12:54:07,265 [INFO] [40325ec25efd4bd3805f53576e581d13] ๐ง Received 320 bytes (total: 12800)
2025-06-06 12:54:07,265 [INFO] [40325ec25efd4bd3805f53576e581d13] โฐ Stream duration > 8s, stopping stream
2025-06-06 12:54:07,266 [INFO] [40325ec25efd4bd3805f53576e581d13] ๐ Finished streaming audio. Total bytes: 12800
2025-06-06 12:54:07,483 [INFO] [40325ec25efd4bd3805f53576e581d13] ๐๏ธ Full responses object:
[]
2025-06-06 12:54:07,490 [INFO] [40325ec25efd4bd3805f53576e581d13] ๐พ Closed raw audio file: 40325ec25efd4bd3805f53576e581d13.raw
2025-06-06 12:54:07,539 [INFO] [40325ec25efd4bd3805f53576e581d13] โ
WAV file saved: 40325ec25efd4bd3805f53576e581d13.wav (0.80 sec)
2025-06-06 12:54:25,390 [ERROR] [40325ec25efd4bd3805f53576e581d13] โ Error closing connection: [Errno 9] Bad file descriptor
the problem is i am not recieving any text response after streaming to google speech stream apis.
Additionally i tried to create files, it creats raw and wav file. both are 13kb every time, and 0 sec in wav. I tried online by converting raw to wav , but during conversion it shows invalid raw file.
Even in the pjsip.conf in asterisk i tried allow= slin,ulaw, alaw
but not working
in my python code i tried with
decoded_data = audioop.ulaw2lin(data, 2)
still same issue
i am using this audio repo audiosocket_server/README.md at master ยท silentindark/audiosocket_server ยท GitHub
any help on this?