Spaces:
Paused
Paused
Update app.py
Browse files
app.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
| 1 |
#!/usr/bin/env python3
|
| 2 |
#
|
| 3 |
-
# san_integration_script.py (
|
| 4 |
-
# ========================================
|
| 5 |
# Description:
|
| 6 |
# - Establishes a real-time, two-way audio bridge between a SAN system
|
| 7 |
# and the Millis AI platform.
|
|
@@ -12,8 +12,10 @@
|
|
| 12 |
# it originally specified.
|
| 13 |
#
|
| 14 |
# Changes in this version:
|
| 15 |
-
# - Fixed `
|
| 16 |
-
#
|
|
|
|
|
|
|
| 17 |
# - Updated the final connection check to use `WebSocketState.DISCONNECTED`.
|
| 18 |
# -------------------------------------------------------------------
|
| 19 |
|
|
@@ -32,7 +34,7 @@ from websockets.connection import State as WsState
|
|
| 32 |
from fastapi import FastAPI, WebSocket, WebSocketDisconnect
|
| 33 |
import uvicorn
|
| 34 |
|
| 35 |
-
#
|
| 36 |
from starlette.websockets import WebSocketState
|
| 37 |
|
| 38 |
# ---------- Logging Configuration -----------------------------------------
|
|
@@ -184,14 +186,17 @@ class RealTimeAudioProcessor:
|
|
| 184 |
payload = base64.b64encode(chunk_resampled).decode()
|
| 185 |
sent_packets += 1
|
| 186 |
if sent_packets % 100 == 1:
|
| 187 |
-
logger.info(f"⬆️ Sending upstream audio packet #{sent_packets} to SAN
|
|
|
|
|
|
|
| 188 |
await client_ws.send_json({
|
| 189 |
"event": "reverse-media",
|
| 190 |
-
"
|
| 191 |
-
"callId": self.call_id,
|
| 192 |
-
"mediaFormat": self.media_format,
|
| 193 |
"payload": payload,
|
|
|
|
| 194 |
})
|
|
|
|
|
|
|
| 195 |
except Exception as e:
|
| 196 |
logger.error(f"❌ Error in _pump_outbound_to_carrier: {e}")
|
| 197 |
break
|
|
@@ -282,7 +287,6 @@ async def media_socket(ws: WebSocket):
|
|
| 282 |
logger.error(f"❌ Unhandled error in media_socket: {e}", exc_info=True)
|
| 283 |
finally:
|
| 284 |
await stop_processor(processor, tasks)
|
| 285 |
-
# *** KEY CHANGE 2: Use WebSocketState for the check ***
|
| 286 |
if ws.client_state != WebSocketState.DISCONNECTED:
|
| 287 |
await ws.close()
|
| 288 |
logger.info("✅ Cleanup complete for this WebSocket connection.")
|
|
@@ -292,5 +296,6 @@ async def health():
|
|
| 292 |
return {"status": "ok", "timestamp": datetime.now().isoformat()}
|
| 293 |
|
| 294 |
if __name__ == "__main__":
|
| 295 |
-
print("🚀 Starting SAN to Millis AI Integration Server (
|
| 296 |
uvicorn.run(app, host="0.0.0.0", port=7860)
|
|
|
|
|
|
| 1 |
#!/usr/bin/env python3
|
| 2 |
#
|
| 3 |
+
# san_integration_script.py (v5 - Provider Format Fix)
|
| 4 |
+
# ======================================================
|
| 5 |
# Description:
|
| 6 |
# - Establishes a real-time, two-way audio bridge between a SAN system
|
| 7 |
# and the Millis AI platform.
|
|
|
|
| 12 |
# it originally specified.
|
| 13 |
#
|
| 14 |
# Changes in this version:
|
| 15 |
+
# - Fixed the `reverse-media` event payload to match the provider's
|
| 16 |
+
# expected format (simplified JSON, lowercase 'callid').
|
| 17 |
+
# - Fixed `ImportError` by changing `starlette.websockets.State` to
|
| 18 |
+
# `starlette.websockets.WebSocketState`.
|
| 19 |
# - Updated the final connection check to use `WebSocketState.DISCONNECTED`.
|
| 20 |
# -------------------------------------------------------------------
|
| 21 |
|
|
|
|
| 34 |
from fastapi import FastAPI, WebSocket, WebSocketDisconnect
|
| 35 |
import uvicorn
|
| 36 |
|
| 37 |
+
# Import WebSocketState instead of State
|
| 38 |
from starlette.websockets import WebSocketState
|
| 39 |
|
| 40 |
# ---------- Logging Configuration -----------------------------------------
|
|
|
|
| 186 |
payload = base64.b64encode(chunk_resampled).decode()
|
| 187 |
sent_packets += 1
|
| 188 |
if sent_packets % 100 == 1:
|
| 189 |
+
logger.info(f"⬆️ Sending upstream audio packet #{sent_packets} to SAN...")
|
| 190 |
+
|
| 191 |
+
### --- FIX: Modified the JSON payload to match the provider's simple format --- ###
|
| 192 |
await client_ws.send_json({
|
| 193 |
"event": "reverse-media",
|
| 194 |
+
"callid": self.call_id, # Changed from "callId" to "callid"
|
|
|
|
|
|
|
| 195 |
"payload": payload,
|
| 196 |
+
# Removed "streamId" and "mediaFormat" fields
|
| 197 |
})
|
| 198 |
+
### --- END FIX --- ###
|
| 199 |
+
|
| 200 |
except Exception as e:
|
| 201 |
logger.error(f"❌ Error in _pump_outbound_to_carrier: {e}")
|
| 202 |
break
|
|
|
|
| 287 |
logger.error(f"❌ Unhandled error in media_socket: {e}", exc_info=True)
|
| 288 |
finally:
|
| 289 |
await stop_processor(processor, tasks)
|
|
|
|
| 290 |
if ws.client_state != WebSocketState.DISCONNECTED:
|
| 291 |
await ws.close()
|
| 292 |
logger.info("✅ Cleanup complete for this WebSocket connection.")
|
|
|
|
| 296 |
return {"status": "ok", "timestamp": datetime.now().isoformat()}
|
| 297 |
|
| 298 |
if __name__ == "__main__":
|
| 299 |
+
print("🚀 Starting SAN to Millis AI Integration Server (v5 - Provider Format Fix)...")
|
| 300 |
uvicorn.run(app, host="0.0.0.0", port=7860)
|
| 301 |
+
|