nuernie commited on
Commit
0c553fd
Β·
1 Parent(s): bb2aa1c
Files changed (2) hide show
  1. app.py +25 -99
  2. requirements.txt +5 -4
app.py CHANGED
@@ -4,6 +4,7 @@ import uvicorn
4
  from whisper_live.server import TranscriptionServer
5
  import logging
6
  import numpy as np
 
7
 
8
  # β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”
9
  # Logging
@@ -11,17 +12,29 @@ import numpy as np
11
  logging.basicConfig(level=logging.INFO)
12
  logger = logging.getLogger(__name__)
13
 
14
- # β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”
15
- # Instantiate the shared TranscriptionServer
16
- # (e.g. this loads your model once)
17
- # β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”
18
- transcription_server = TranscriptionServer()
19
 
20
  @asynccontextmanager
21
  async def lifespan(app: FastAPI):
22
- # any startup logic here (e.g. preload models)
 
 
 
 
 
 
 
 
 
 
 
 
23
  yield
24
- # any cleanup logic here
 
 
25
 
26
  app = FastAPI(
27
  title="Whisper Live Server",
@@ -33,103 +46,16 @@ app = FastAPI(
33
  async def root():
34
  return {
35
  "message": "Welcome to Whisper Live Server",
36
- "websocket_endpoint": "/ws",
37
  "health_endpoint": "/health"
38
  }
39
 
40
  @app.get("/health")
41
  async def health_check():
42
- return {"status": "healthy"}
43
-
44
-
45
- @app.websocket("/ws")
46
- async def websocket_endpoint(websocket: WebSocket):
47
- await websocket.accept()
48
- client_uid = None
49
- config = {}
50
-
51
- try:
52
- # β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”
53
- # 1) Read the per‑client config JSON
54
- #β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”
55
- config = await websocket.receive_json()
56
- client_uid = config.get("uid")
57
- if not client_uid:
58
- await websocket.close(code=4000, reason="No client UID provided")
59
- return
60
-
61
- logger.info(f"Client connected: {client_uid} | Config: {config}")
62
-
63
- # β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”
64
- # 2) Send back a SERVER_READY message
65
- #β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”
66
- await websocket.send_json({
67
- "uid": client_uid,
68
- "message": "SERVER_READY",
69
- "backend": "faster_whisper"
70
- })
71
-
72
- # β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”
73
- # 3) Configure the shared server for this client
74
- # (you can also patch transcription_server attributes here)
75
- #β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”
76
- language = config.get("language", "de")
77
- task = config.get("task", "transcribe")
78
- model = config.get("model", "tiny")
79
- use_vad = config.get("use_vad", True)
80
-
81
- # If your TranscriptionServer.process_audio takes kwargs, you can pass them directly.
82
- # Otherwise, you may need to set transcription_server.language = language, etc.
83
-
84
- # β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”
85
- # 4) Enter the receive‑loop
86
- #β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”
87
- while True:
88
- msg = await websocket.receive()
89
-
90
- # client closed connection
91
- if msg["type"] == "websocket.disconnect":
92
- break
93
-
94
- # binary audio frames
95
- if "bytes" in msg and msg["bytes"] is not None:
96
- audio_data = np.frombuffer(msg["bytes"], dtype=np.float32)
97
-
98
- # pass per‑client params into process_audio
99
- segments = transcription_server.process_audio(
100
- audio_data,
101
- language=language,
102
- task=task,
103
- model=model,
104
- use_vad=use_vad
105
- )
106
-
107
- if segments:
108
- await websocket.send_json({
109
- "uid": client_uid,
110
- "segments": segments
111
- })
112
-
113
- # text control messages
114
- elif "text" in msg and msg["text"] == "END_OF_AUDIO":
115
- logger.info(f"Client {client_uid} ended stream.")
116
- break
117
-
118
- except WebSocketDisconnect:
119
- logger.warning(f"WebSocket disconnected: {client_uid}")
120
- except Exception as e:
121
- logger.error(f"WebSocket error: {e}")
122
- if client_uid:
123
- try:
124
- await websocket.send_json({
125
- "uid": client_uid,
126
- "error": str(e)
127
- })
128
- except:
129
- pass
130
- finally:
131
- await websocket.close()
132
-
133
 
134
  if __name__ == "__main__":
135
  uvicorn.run(app, host="0.0.0.0", port=7860)
 
4
  from whisper_live.server import TranscriptionServer
5
  import logging
6
  import numpy as np
7
+ import threading
8
 
9
  # β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”
10
  # Logging
 
12
  logging.basicConfig(level=logging.INFO)
13
  logger = logging.getLogger(__name__)
14
 
15
+ # Global server instance
16
+ transcription_server = None
17
+ server_thread = None
 
 
18
 
19
  @asynccontextmanager
20
  async def lifespan(app: FastAPI):
21
+ # Startup: create and start the transcription server
22
+ global transcription_server, server_thread
23
+ transcription_server = TranscriptionServer()
24
+ server_thread = threading.Thread(
25
+ target=transcription_server.run,
26
+ kwargs={
27
+ 'host': '0.0.0.0',
28
+ 'port': 9090, # WebSocket port for transcription
29
+ 'backend': 'faster_whisper'
30
+ }
31
+ )
32
+ server_thread.daemon = True
33
+ server_thread.start()
34
  yield
35
+ # Cleanup
36
+ if transcription_server:
37
+ transcription_server.cleanup()
38
 
39
  app = FastAPI(
40
  title="Whisper Live Server",
 
46
  async def root():
47
  return {
48
  "message": "Welcome to Whisper Live Server",
49
+ "websocket_endpoint": "ws://localhost:9090", # Direct WebSocket connection
50
  "health_endpoint": "/health"
51
  }
52
 
53
  @app.get("/health")
54
  async def health_check():
55
+ global transcription_server, server_thread
56
+ if transcription_server and server_thread.is_alive():
57
+ return {"status": "healthy"}
58
+ return {"status": "unhealthy"}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
59
 
60
  if __name__ == "__main__":
61
  uvicorn.run(app, host="0.0.0.0", port=7860)
requirements.txt CHANGED
@@ -1,7 +1,8 @@
1
- fastapi>=0.68.0
2
- uvicorn>=0.15.0
3
- websockets>=10.0
4
- numpy>=1.21.0
 
5
  faster-whisper==1.1.0
6
  PyAudio
7
  websocket-client
 
1
+ fastapi==0.109.2
2
+ uvicorn==0.27.1
3
+ websockets==12.0
4
+ numpy==1.26.4
5
+ python-multipart==0.0.9
6
  faster-whisper==1.1.0
7
  PyAudio
8
  websocket-client