Spaces:
Running
Running
File size: 5,614 Bytes
2318eae a1d489d 0d6899b 516e9a4 2318eae 1d28d11 2318eae 1d28d11 2318eae 454a10d 7c3f2af 2318eae 7c3f2af 1d28d11 a1d489d 1d28d11 a1d489d 1d28d11 7c3f2af 0d6899b 1d28d11 ab74fc2 7c3f2af 1d28d11 454a10d ab74fc2 454a10d ab74fc2 548b7ed ab74fc2 548b7ed ab74fc2 454a10d 7c3f2af 1d28d11 b7b0486 1d28d11 69b815b b7b0486 548b7ed 1d28d11 548b7ed 1d28d11 a1d489d 7c3f2af b7b0486 1d28d11 7c3f2af 1d28d11 69b815b b7b0486 1d28d11 7c3f2af 69b815b 7c3f2af 548b7ed 7c3f2af 1d28d11 516e9a4 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 |
from fastapi import FastAPI, WebSocket
from fastapi.staticfiles import StaticFiles
from fastapi.responses import HTMLResponse
from app.asr_worker import create_recognizer, stream_audio
import json
from starlette.websockets import WebSocketDisconnect
app = FastAPI()
app.mount("/static", StaticFiles(directory="app/static"), name="static")
@app.get("/")
async def root():
with open("app/static/index.html") as f:
return HTMLResponse(f.read())
@app.websocket("/ws")
async def websocket_endpoint(websocket: WebSocket):
print("[DEBUG main] ▶ Attempting to accept WebSocket…")
await websocket.accept()
print("[DEBUG main] ▶ WebSocket.accept() returned → client is connected!")
recognizer = None
stream = None
orig_sr = 48000 # default fallback
try:
while True:
data = await websocket.receive()
kind = data.get("type")
# Handle config messages
if kind not in ("websocket.receive", "websocket.receive_bytes"):
print(f"[DEBUG main] Received control/frame: {data}")
continue
if kind == "websocket.receive" and "text" in data:
raw = data["text"]
try:
config_msg = json.loads(raw)
except Exception as e:
print(f"[ERROR main] JSON parse failed: {e}")
continue
if config_msg.get("type") == "config":
# 1) sample rate
orig_sr = int(config_msg["sampleRate"])
print(f"[INFO main] Set original sample rate to {orig_sr}")
# 2) model & precision
model_id = config_msg.get("model")
precision = config_msg.get("precision")
print(f"[INFO main] Selected model: {model_id}, precision: {precision}")
# 3) hotwords & boost score
hotwords = config_msg.get("hotwords", [])
hotwords_score = float(config_msg.get("hotwordsScore", 0.0))
print(f"[INFO main] Hotwords: {hotwords}, score: {hotwords_score}")
# 4) Parse endpoint detection rules
ep1 = float(config_msg.get("epRule1", 2.4))
ep2 = float(config_msg.get("epRule2", 1.2))
ep3 = int( config_msg.get("epRule3", 300))
print(f"[INFO main] Endpoint rules: rule1={ep1}s, rule2={ep2}s, rule3={ep3}ms")
# 5) create recognizer with endpoint settings & biasing
recognizer = create_recognizer(
model_id,
precision,
hotwords=hotwords,
hotwords_score=hotwords_score,
ep_rule1=ep1,
ep_rule2=ep2,
ep_rule3=ep3
)
stream = recognizer.create_stream()
print("[INFO main] WebSocket connection accepted; created a streaming context.")
continue
# Don't process audio until after config
if recognizer is None or stream is None:
continue
# If it’s a text payload but with bytes (some FastAPI versions put audio under 'text'!)
if kind == "websocket.receive" and "bytes" in data:
raw_audio = data["bytes"]
# print(f"[INFO main] (text+bytes) Received audio chunk: {len(raw_audio)} bytes")
result, rms = stream_audio(raw_audio, stream, recognizer, orig_sr)
vol_to_send = min(rms, 1.0)
# print(f"[INFO main] Sending → partial='{result[:30]}…', volume={vol_to_send:.4f}")
# 1) send the interim
await websocket.send_json({"partial": result, "volume": vol_to_send})
# 2) DEBUG: log when endpoint is seen
is_ep = recognizer.is_endpoint(stream)
# print(f"[DEBUG main] is_endpoint={is_ep}")
# 3) if endpoint, emit final and reset
if is_ep:
if result.strip():
print(f"[DEBUG main] Emitting final: {result!r}")
await websocket.send_json({"final": result})
recognizer.reset(stream)
continue
elif kind == "websocket.receive_bytes":
raw_audio = data["bytes"]
# print(f"[INFO main] Received audio chunk: {len(raw_audio)} bytes")
# This will also print its own debug info (see asr_worker.py)
result, rms = stream_audio(raw_audio, stream, recognizer, orig_sr)
vol_to_send = min(rms, 1.0)
# print(f"[INFO main] Sending → partial='{result[:30]}…', volume={vol_to_send:.4f}")
await websocket.send_json({
"partial": result,
"volume": min(rms, 1.0)
})
# -- INSERT: emit final on endpoint detection --
if recognizer.is_endpoint(stream):
if result.strip():
await websocket.send_json({"final": result})
recognizer.reset(stream)
except Exception as e:
print(f"[ERROR main] Unexpected exception: {e}")
try:
await websocket.close()
except:
pass
print("[INFO main] WebSocket closed, cleanup complete.")
|