Connecting to ARI WebSocket at ws://127.0.0.1:8080/ari/events?app=my_stasis_app&api_key=tcriber:myst
AudioSocket server listening on 127.0.0.1:4000
Connected to ARI WebSocket.
Connected audio stream from (β127.0.0.1β, 35202)
Audio socket error: [Errno 104] Connection reset by peer
Stream ended.
I got this error actully i want to stream audio from asterisk to python server for real time transcribe but i got this error please tell me how to resolve it?
You havenβt provided sufficient information. What troubleshooting or debugging have you done already? Have you confirmed your code is actually correct (I would wager it is AI generated so it should still be reviewed regardless)? What are the ARI requests that are happening? How are you initiating the audiosocket request? If using the external media ARI request, is it going to the correct place in Asterisk? What shows on the Asterisk console?
[incoming]
exten => +911204845652,1,NoOp(
Incoming Call: ${EXTEN} from ${CALLERID(all)})
same => n,Answer()
same => n,NoOp(Diversion: ${PJSIP_HEADER(read,Diversion)})
same => n,NoOp(History-Info: ${PJSIP_HEADER(read,History-Info)})
same => n,NoOp(To: ${PJSIP_HEADER(read,To)})
same => n,NoOp(Channel UNIQUEID: ${UNIQUEID})
same => n,Set(UUID=${UUID()})
same => n,NoOp(Using AudioSocket UUID: ${UUID})
same => n,AudioSocket(${UUID},127.0.0.1:4000)
same => n,Hangup()
this my extension conf file and below is python code
#!/usr/bin/env python3
import requests
import json
import threading
import socket
import time
import websocket
import os
import sys
import numpy as np
import io
from faster_whisper import WhisperModel
---------------- CONFIG ----------------
ARI_URL = βhttp://127.0.0.1:8088/ariβ
ARI_USER = βtranscriberβ
ARI_PASS = βmysecretβ
STASIS_APP = βmy_stasis_appβ
AUDIOSOCKET_HOST = β127.0.0.1β
AUDIOSOCKET_PORT = 4000
choose a Whisper model size: tiny, base, small, medium, large-v2
WHISPER_MODEL_NAME = βsmallβ
WHISPER_DEVICE = βcpuβ # or βcudaβ for GPU
---------------- LOAD WHISPER MODEL ----------------
print(f"
Loading Whisper model β{WHISPER_MODEL_NAME}β on {WHISPER_DEVICE} β¦")
model = WhisperModel(WHISPER_MODEL_NAME, device=WHISPER_DEVICE, compute_type=βint8β)
print(β
Whisper model loaded!β)
---------------- AUDIO SOCKET HANDLER ----------------
def handle_audio(conn, addr):
print(f"
Connected audio stream from {addr}")
conn.settimeout(5.0)
# buffer for accumulating PCM samples (16-bit signed, mono)
audio_buffer = bytearray()
def transcribe_chunk(chunk):
"""Transcribe small PCM chunks in background."""
try:
# Convert raw PCM (16-bit, little-endian) to float32 numpy
audio_np = np.frombuffer(chunk, dtype=np.int16).astype(np.float32) / 32768.0
# Whisper expects 16 kHz audio
segments, _ = model.transcribe(audio_np, language="en", beam_size=5)
text = " ".join([seg.text.strip() for seg in segments])
if text.strip():
print("π£οΈ", text)
except Exception as e:
print("β οΈ Transcription error:", e)
def keep_alive():
"""Send silence periodically to keep Asterisk happy."""
while True:
try:
conn.send(b'\x00' * 320) # 20 ms silence
time.sleep(1)
except:
break
threading.Thread(target=keep_alive, daemon=True).start()
# --- receive audio in chunks ---
while True:
try:
data = conn.recv(320)
if not data:
break
audio_buffer.extend(data)
# every ~1 sec (16000 samples = 2 bytes * 16000 = 32000 bytes)
if len(audio_buffer) >= 32000:
chunk = bytes(audio_buffer[:32000])
audio_buffer = audio_buffer[32000:]
threading.Thread(target=transcribe_chunk, args=(chunk,), daemon=True).start()
except socket.timeout:
continue
except Exception as e:
print("β οΈ Audio socket error:", e)
break
print("β Stream ended.")
conn.close()
---------------- AUDIO SOCKET SERVER ----------------
def start_audiosocket_server():
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind((AUDIOSOCKET_HOST, AUDIOSOCKET_PORT))
s.listen(5)
print(f"
AudioSocket server listening on {AUDIOSOCKET_HOST}:{AUDIOSOCKET_PORT}")
while True:
conn, addr = s.accept()
threading.Thread(target=handle_audio, args=(conn, addr), daemon=True).start()
---------------- ARI HANDLERS ----------------
def on_incoming_call(channel_id):
print(f"
Incoming call on channel {channel_id}")
external_media_url = f"{ARI_URL}/channels"
payload = {
"endpoint": f"audiosocket:tcp://{AUDIOSOCKET_HOST}:{AUDIOSOCKET_PORT}?direction=send&timeout=0",
"app": STASIS_APP,
"appArgs": "audiosocket",
"format": "slin16"
}
print("β‘οΈ Creating external media channel...")
r = requests.post(external_media_url, auth=(ARI_USER, ARI_PASS), json=payload)
print(f"π ARI Response Status: {r.status_code}")
print(f"π ARI Response Body: {r.text}")
if r.status_code != 200:
print("β Failed to create external media channel.")
return
try:
ext_chan = r.json()
ext_id = ext_chan["id"]
print(f"π§ Created external media channel {ext_id}")
except Exception as e:
print(f"β Error parsing ARI response: {e}")
return
# Wait a moment before bridging
time.sleep(0.5)
bridge_id = f"bridge-{channel_id}"
bridge_url = f"{ARI_URL}/bridges/{bridge_id}"
requests.post(bridge_url, auth=(ARI_USER, ARI_PASS), json={"type": "mixing"})
requests.post(f"{bridge_url}/addChannel", auth=(ARI_USER, ARI_PASS),
json={"channel": [channel_id, ext_id]})
print("π Audio bridged to AudioSocket stream.")
---------------- ARI EVENT LISTENER ----------------
def listen_ari_events():
ws_url = f"ws://127.0.0.1:8088/ari/events?app={STASIS_APP}&api_key={ARI_USER}:{ARI_PASS}"
print(f"
Connecting to ARI WebSocket at {ws_url}")
ws = websocket.create_connection(ws_url)
print(β
Connected to ARI WebSocket.β)
while True:
try:
msg = ws.recv()
data = json.loads(msg)
event = data.get("type")
if event == "StasisStart":
channel = data["channel"]["id"]
on_incoming_call(channel)
except KeyboardInterrupt:
print("\nπ Stopping server.")
ws.close()
break
except Exception as e:
print("β οΈ WebSocket error:", e)
time.sleep(2)
try:
ws = websocket.create_connection(ws_url)
except:
pass
---------------- MAIN ----------------
if name == βmainβ:
threading.Thread(target=start_audiosocket_server, daemon=True).start()
listen_ari_events()