benjolo commited on
Commit
9de3c31
1 Parent(s): 0e1fa07

Update backend/main.py

Browse files
Files changed (1) hide show
  1. backend/main.py +347 -343
backend/main.py CHANGED
@@ -1,362 +1,366 @@
1
- from operator import itemgetter
2
- import os
3
- from datetime import datetime
4
- import uvicorn
5
- from typing import Any, Optional, Tuple, Dict, TypedDict
6
- from urllib import parse
7
- from uuid import uuid4
8
- import logging
9
- from fastapi.logger import logger as fastapi_logger
10
- import sys
11
- # sys.path.append('/Users/benolojo/DCU/CA4/ca400_FinalYearProject/2024-ca400-olojob2-majdap2/src/backend/')
12
-
13
- from fastapi import FastAPI
14
- from fastapi.middleware.cors import CORSMiddleware
15
- from fastapi import APIRouter, Body, Request, status
16
- from pymongo import MongoClient
17
- from dotenv import dotenv_values
18
- from routes import router as api_router
19
- from contextlib import asynccontextmanager
20
- import requests
21
-
22
- from typing import List
23
- from datetime import date
24
- from mongodb.operations.calls import *
25
- from mongodb.models.calls import UserCall, UpdateCall
26
- # from mongodb.endpoints.calls import *
27
-
28
- # from transformers import AutoProcessor, SeamlessM4Tv2Model
29
-
30
- # from seamless_communication.inference import Translator
31
- from Client import Client
32
- #----------------------------------
33
- # base seamless imports
34
- # ---------------------------------
35
- import numpy as np
36
- import torch
37
- # ---------------------------------
38
- import socketio
39
-
40
- ###############################################
41
- # Configure logger
42
-
43
- gunicorn_error_logger = logging.getLogger("gunicorn.error")
44
- gunicorn_logger = logging.getLogger("gunicorn")
45
- uvicorn_access_logger = logging.getLogger("uvicorn.access")
46
-
47
- gunicorn_error_logger.propagate = True
48
- gunicorn_logger.propagate = True
49
- uvicorn_access_logger.propagate = True
50
-
51
- uvicorn_access_logger.handlers = gunicorn_error_logger.handlers
52
- fastapi_logger.handlers = gunicorn_error_logger.handlers
53
-
54
- ###############################################
55
-
56
- # sio is the main socket.io entrypoint
57
- sio = socketio.AsyncServer(
58
- async_mode="asgi",
59
- cors_allowed_origins="*",
60
- logger=gunicorn_logger,
61
- engineio_logger=gunicorn_logger,
62
- )
63
- # sio.logger.setLevel(logging.DEBUG)
64
- socketio_app = socketio.ASGIApp(sio)
65
- # app.mount("/", socketio_app)
66
-
67
- config = dotenv_values(".env")
68
-
69
- # Read connection string from environment vars
70
- # uri = os.environ['MONGODB_URI']
71
-
72
- # Read connection string from .env file
73
- uri = config['MONGODB_URI']
74
-
75
- # Set transformers cache
76
- # os.environ['HF_HOME'] = './.cache/'
77
- # os.environ['SENTENCE_TRANSFORMERS_HOME'] = './.cache'
78
-
79
- # MongoDB Connection Lifespan Events
80
- @asynccontextmanager
81
- async def lifespan(app: FastAPI):
82
- # startup logic
83
- app.mongodb_client = MongoClient(uri)
84
- app.database = app.mongodb_client['IT-Cluster1'] #connect to interpretalk primary db
85
- try:
86
- app.mongodb_client.admin.command('ping')
87
- print("MongoDB Connection Established...")
88
- except Exception as e:
89
- print(e)
90
 
91
- yield
92
 
93
- # shutdown logic
94
- print("Closing MongoDB Connection...")
95
- app.mongodb_client.close()
96
 
97
- app = FastAPI(lifespan=lifespan, logger=gunicorn_logger)
98
 
99
- # New CORS funcitonality
100
- app.add_middleware(
101
- CORSMiddleware,
102
- allow_origins=["*"], # configured node app port
103
- allow_credentials=True,
104
- allow_methods=["*"],
105
- allow_headers=["*"],
106
- )
107
 
108
- app.include_router(api_router) # include routers for user, calls and transcripts operations
109
 
110
- DEBUG = True
111
 
112
- ESCAPE_HATCH_SERVER_LOCK_RELEASE_NAME = "remove_server_lock"
113
 
114
- TARGET_SAMPLING_RATE = 16000
115
- MAX_BYTES_BUFFER = 480_000
116
 
117
- print("")
118
- print("")
119
- print("=" * 20 + " ⭐️ Starting Server... ⭐️ " + "=" * 20)
120
 
121
- ###############################################
122
- # Configure socketio server
123
- ###############################################
124
 
125
- # TODO PM - change this to the actual path
126
- # seamless remnant code
127
- # CLIENT_BUILD_PATH = "../streaming-react-app/dist/"
128
- # static_files = {
129
- # "/": CLIENT_BUILD_PATH,
130
- # "/assets/seamless-db6a2555.svg": {
131
- # "filename": CLIENT_BUILD_PATH + "assets/seamless-db6a2555.svg",
132
- # "content_type": "image/svg+xml",
133
- # },
134
- # }
135
- device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
136
- # processor = AutoProcessor.from_pretrained("facebook/seamless-m4t-v2-large", force_download=True)
137
- #cache_dir="/.cache"
138
-
139
- # PM - hardcoding temporarily as my GPU doesnt have enough vram
140
- # model = SeamlessM4Tv2Model.from_pretrained("facebook/seamless-m4t-v2-large").to("cpu")
141
- # model = SeamlessM4Tv2Model.from_pretrained("facebook/seamless-m4t-v2-large", force_download=True).to(device)
142
-
143
-
144
- bytes_data = bytearray()
145
- model_name = "seamlessM4T_v2_large"
146
- # vocoder_name = "vocoder_v2" if model_name == "seamlessM4T_v2_large" else "vocoder_36langs"
147
-
148
- clients = {}
149
- rooms = {}
150
-
151
- import torch
152
- from transformers import pipeline
153
- translator = pipeline("automatic-speech-recognition",
154
- "facebook/seamless-m4t-v2-large",
155
- torch_dtype=torch.float32,
156
- device="cpu")
157
-
158
- converter = pipeline("translation",
159
- "facebook/seamless-m4t-v2-large",
160
- torch_dtype=torch.float32,
161
- device="cpu")
162
-
163
-
164
- def get_collection_users():
165
- return app.database["user_records"]
166
-
167
- def get_collection_calls():
168
- # return app.database["call_records"]
169
- return app.database["call_test"]
170
-
171
-
172
- @app.get("/test/", response_description="Welcome User")
173
- def test():
174
-
175
- return {"message": "Welcome to InterpreTalk!"}
176
-
177
-
178
- @app.post("/test_post/", response_description="List more test call records")
179
- def test_post():
180
- request_data = {
181
- "call_id": "TESTID000001"
182
- }
183
-
184
- result = create_calls(get_collection_calls(), request_data)
185
-
186
- # return {"message": "Welcome to InterpreTalk!"}
187
- return result
188
-
189
- @app.put("/test_put/", response_description="List test call records")
190
- def test_put():
191
-
192
- # result = list_calls(get_collection_calls(), 100)
193
- # result = send_captions("TEST", "TEST", "TEST", "oUjUxTYTQFVVjEarIcZ0")
194
- result = send_captions("TEST", "TEST", "TEST", "TESTID000001")
195
-
196
- print(result)
197
- return result
198
-
199
-
200
- async def send_translated_text(client_id, original_text, translated_text, room_id):
201
- print('SEND_TRANSLATED_TEXT IS WOKRING IN FASTAPI BACKEND...')
202
- print(rooms)
203
- print(clients)
204
-
205
- data = {
206
- "author": str(client_id),
207
- "original_text": str(original_text),
208
- "translated_text": str(translated_text),
209
- "timestamp": str(datetime.now())
210
- }
211
- gunicorn_logger.info("SENDING TRANSLATED TEXT TO CLIENT")
212
- await sio.emit("translated_text", data, room=room_id)
213
- gunicorn_logger.info("SUCCESSFULLY SEND AUDIO TO FRONTEND")
214
-
215
- @sio.on("connect")
216
- async def connect(sid, environ):
217
- print(f"📥 [event: connected] sid={sid}")
218
- query_params = dict(parse.parse_qsl(environ["QUERY_STRING"]))
219
- client_id = query_params.get("client_id")
220
- gunicorn_logger.info(f"📥 [event: connected] sid={sid}, client_id={client_id}")
221
- # sid = socketid, client_id = client specific ID ,always the same for same user
222
- clients[sid] = Client(sid, client_id)
223
- gunicorn_logger.warning(f"Client connected: {sid}")
224
- gunicorn_logger.warning(clients)
225
-
226
- @sio.on("disconnect")
227
- async def disconnect(sid): # BO - also pass call id as parameter for updating MongoDB
228
- gunicorn_logger.debug(f"📤 [event: disconnected] sid={sid}")
229
- clients.pop(sid, None)
230
- # BO -> Update Call record with call duration, key terms
231
-
232
- @sio.on("target_language")
233
- async def target_language(sid, target_lang):
234
- gunicorn_logger.info(f"📥 [event: target_language] sid={sid}, target_lang={target_lang}")
235
- clients[sid].target_language = target_lang
236
-
237
- @sio.on("call_user")
238
- async def call_user(sid, call_id):
239
- clients[sid].call_id = call_id
240
- gunicorn_logger.info(f"CALL {sid}: entering room {call_id}")
241
- rooms[call_id] = rooms.get(call_id, [])
242
- if sid not in rooms[call_id] and len(rooms[call_id]) < 2:
243
- rooms[call_id].append(sid)
244
- sio.enter_room(sid, call_id)
245
- else:
246
- gunicorn_logger.info(f"CALL {sid}: room {call_id} is full")
247
- # await sio.emit("room_full", room=call_id, to=sid)
248
-
249
- # # BO - Get call id from dictionary created during socketio connection
250
- # client_id = clients[sid].client_id
251
 
252
- # gunicorn_logger.warning(f"NOW TRYING TO CREATE DB RECORD FOR Caller with ID: {client_id} for call: {call_id}")
253
- # # # BO -> Create Call Record with Caller and call_id field (None for callee, duration, terms..)
254
- # request_data = {
255
- # "call_id": str(call_id),
256
- # "caller_id": str(client_id),
257
- # "creation_date": str(datetime.now())
258
- # }
259
-
260
- # response = create_calls(get_collection_calls(), request_data)
261
- # print(response) # BO - print created db call record
262
-
263
- @sio.on("audio_config")
264
- async def audio_config(sid, sample_rate):
265
- clients[sid].original_sr = sample_rate
266
-
267
-
268
- @sio.on("answer_call")
269
- async def answer_call(sid, call_id):
270
-
271
- clients[sid].call_id = call_id
272
- gunicorn_logger.info(f"ANSWER {sid}: entering room {call_id}")
273
- rooms[call_id] = rooms.get(call_id, [])
274
- if sid not in rooms[call_id] and len(rooms[call_id]) < 2:
275
- rooms[call_id].append(sid)
276
- sio.enter_room(sid, call_id)
277
- else:
278
- gunicorn_logger.info(f"ANSWER {sid}: room {call_id} is full")
279
- # await sio.emit("room_full", room=call_id, to=sid)
280
-
281
-
282
- # # BO - Get call id from dictionary created during socketio connection
283
- # client_id = clients[sid].client_id
284
 
285
- # # BO -> Update Call Record with Callee field based on call_id
286
- # gunicorn_logger.warning(f"NOW UPDATING MongoDB RECORD FOR Caller with ID: {client_id} for call: {call_id}")
287
- # # # BO -> Create Call Record with callee_id field (None for callee, duration, terms..)
288
- # request_data = {
289
- # "callee_id": client_id
290
- # }
291
-
292
- # response = update_calls(get_collection_calls(), call_id, request_data)
293
- # print(response) # BO - print created db call record
294
 
295
 
296
- @sio.on("incoming_audio")
297
- async def incoming_audio(sid, data, call_id):
298
- try:
299
- clients[sid].add_bytes(data)
300
-
301
- if clients[sid].get_length() >= MAX_BYTES_BUFFER:
302
- gunicorn_logger.info('Buffer full, now outputting...')
303
- output_path = clients[sid].output_path
304
- vad_result, resampled_audio = clients[sid].resample_and_write_to_file()
305
- # source lang is speakers tgt language 😃
306
- src_lang = clients[sid].target_language
307
- if vad_result:
308
- gunicorn_logger.info('Speech detected, now processing audio.....')
309
- tgt_sid = next(id for id in rooms[call_id] if id != sid)
310
- tgt_lang = clients[tgt_sid].target_language
311
- # following example from https://github.com/facebookresearch/seamless_communication/blob/main/docs/m4t/README.md#transformers-usage
312
- # output_tokens = processor(audios=resampled_audio, src_lang=src_lang, return_tensors="pt")
313
- # model_output = model.generate(**output_tokens, tgt_lang=src_lang, generate_speech=False)[0].tolist()[0]
314
- # asr_text = processor.decode(model_output, skip_special_tokens=True)
315
- asr_text = translator(resampled_audio, generate_kwargs={"tgt_lang": src_lang})['text']
316
- print(f"ASR TEXT = {asr_text}")
317
- # ASR TEXT => ORIGINAL TEXT
318
-
319
- # t2t_tokens = processor(text=asr_text, src_lang=src_lang, tgt_lang=tgt_lang, return_tensors="pt")
320
- # print(f"FIRST TYPE = {type(output_tokens)}, SECOND TYPE = {type(t2t_tokens)}")
321
- # translated_data = model.generate(**t2t_tokens, tgt_lang=tgt_lang, generate_speech=False)[0].tolist()[0]
322
- # translated_text = processor.decode(translated_data, skip_special_tokens=True)
323
- translated_text = converter(asr_text, src_lang=src_lang, tgt_lang=tgt_lang)
324
- print(f"TRANSLATED TEXT = {translated_text}")
325
-
326
- # BO -> send translated_text to mongodb as caption record update based on call_id
327
- # send_captions(clients[sid].client_id, asr_text, translated_text, call_id)
328
 
329
- # TRANSLATED TEXT
330
- # PM - text_output is a list with 1 string
331
- await send_translated_text(clients[sid].client_id, asr_text, translated_text, call_id)
332
 
333
- # # BO -> send translated_text to mongodb as caption record update based on call_id
334
- # send_captions(clients[sid].client_id, asr_text, translated_text, call_id)
335
 
336
- except Exception as e:
337
- gunicorn_logger.error(f"Error in incoming_audio: {e.with_traceback()}")
338
 
339
- def send_captions(client_id, original_text, translated_text, call_id):
340
- # BO -> Update Call Record with Callee field based on call_id
341
- print(f"Now updating Caption field in call record for Caller with ID: {client_id} for call: {call_id}")
342
-
343
- data = {
344
- "author": str(client_id),
345
- "original_text": str(original_text),
346
- "translated_text": str(translated_text),
347
- "timestamp": str(datetime.now())
348
- }
349
-
350
- response = update_captions(get_collection_calls(), call_id, data)
351
- return response
352
-
353
- app.mount("/", socketio_app)
354
-
355
- if __name__ == '__main__':
356
- uvicorn.run("main:app", host='0.0.0.0', port=7860, log_level="debug")
357
-
358
- # Running in Docker Container
359
- if __name__ != "__main__":
360
- fastapi_logger.setLevel(gunicorn_logger.level)
361
- else:
362
- fastapi_logger.setLevel(logging.DEBUG)
 
 
 
 
 
1
+ # from operator import itemgetter
2
+ # import os
3
+ # from datetime import datetime
4
+ # import uvicorn
5
+ # from typing import Any, Optional, Tuple, Dict, TypedDict
6
+ # from urllib import parse
7
+ # from uuid import uuid4
8
+ # import logging
9
+ # from fastapi.logger import logger as fastapi_logger
10
+ # import sys
11
+ # # sys.path.append('/Users/benolojo/DCU/CA4/ca400_FinalYearProject/2024-ca400-olojob2-majdap2/src/backend/')
12
+
13
+ # from fastapi import FastAPI
14
+ # from fastapi.middleware.cors import CORSMiddleware
15
+ # from fastapi import APIRouter, Body, Request, status
16
+ # from pymongo import MongoClient
17
+ # from dotenv import dotenv_values
18
+ # from routes import router as api_router
19
+ # from contextlib import asynccontextmanager
20
+ # import requests
21
+
22
+ # from typing import List
23
+ # from datetime import date
24
+ # from mongodb.operations.calls import *
25
+ # from mongodb.models.calls import UserCall, UpdateCall
26
+ # # from mongodb.endpoints.calls import *
27
+
28
+ # # from transformers import AutoProcessor, SeamlessM4Tv2Model
29
+
30
+ # # from seamless_communication.inference import Translator
31
+ # from Client import Client
32
+ # #----------------------------------
33
+ # # base seamless imports
34
+ # # ---------------------------------
35
+ # import numpy as np
36
+ # import torch
37
+ # # ---------------------------------
38
+ # import socketio
39
+
40
+ # ###############################################
41
+ # # Configure logger
42
+
43
+ # gunicorn_error_logger = logging.getLogger("gunicorn.error")
44
+ # gunicorn_logger = logging.getLogger("gunicorn")
45
+ # uvicorn_access_logger = logging.getLogger("uvicorn.access")
46
+
47
+ # gunicorn_error_logger.propagate = True
48
+ # gunicorn_logger.propagate = True
49
+ # uvicorn_access_logger.propagate = True
50
+
51
+ # uvicorn_access_logger.handlers = gunicorn_error_logger.handlers
52
+ # fastapi_logger.handlers = gunicorn_error_logger.handlers
53
+
54
+ # ###############################################
55
+
56
+ # # sio is the main socket.io entrypoint
57
+ # sio = socketio.AsyncServer(
58
+ # async_mode="asgi",
59
+ # cors_allowed_origins="*",
60
+ # logger=gunicorn_logger,
61
+ # engineio_logger=gunicorn_logger,
62
+ # )
63
+ # # sio.logger.setLevel(logging.DEBUG)
64
+ # socketio_app = socketio.ASGIApp(sio)
65
+ # # app.mount("/", socketio_app)
66
+
67
+ # config = dotenv_values(".env")
68
+
69
+ # # Read connection string from environment vars
70
+ # # uri = os.environ['MONGODB_URI']
71
+
72
+ # # Read connection string from .env file
73
+ # uri = config['MONGODB_URI']
74
+
75
+ # # Set transformers cache
76
+ # # os.environ['HF_HOME'] = './.cache/'
77
+ # # os.environ['SENTENCE_TRANSFORMERS_HOME'] = './.cache'
78
+
79
+ # # MongoDB Connection Lifespan Events
80
+ # @asynccontextmanager
81
+ # async def lifespan(app: FastAPI):
82
+ # # startup logic
83
+ # app.mongodb_client = MongoClient(uri)
84
+ # app.database = app.mongodb_client['IT-Cluster1'] #connect to interpretalk primary db
85
+ # try:
86
+ # app.mongodb_client.admin.command('ping')
87
+ # print("MongoDB Connection Established...")
88
+ # except Exception as e:
89
+ # print(e)
90
 
91
+ # yield
92
 
93
+ # # shutdown logic
94
+ # print("Closing MongoDB Connection...")
95
+ # app.mongodb_client.close()
96
 
97
+ # app = FastAPI(lifespan=lifespan, logger=gunicorn_logger)
98
 
99
+ # # New CORS funcitonality
100
+ # app.add_middleware(
101
+ # CORSMiddleware,
102
+ # allow_origins=["*"], # configured node app port
103
+ # allow_credentials=True,
104
+ # allow_methods=["*"],
105
+ # allow_headers=["*"],
106
+ # )
107
 
108
+ # app.include_router(api_router) # include routers for user, calls and transcripts operations
109
 
110
+ # DEBUG = True
111
 
112
+ # ESCAPE_HATCH_SERVER_LOCK_RELEASE_NAME = "remove_server_lock"
113
 
114
+ # TARGET_SAMPLING_RATE = 16000
115
+ # MAX_BYTES_BUFFER = 480_000
116
 
117
+ # print("")
118
+ # print("")
119
+ # print("=" * 20 + " ⭐️ Starting Server... ⭐️ " + "=" * 20)
120
 
121
+ # ###############################################
122
+ # # Configure socketio server
123
+ # ###############################################
124
 
125
+ # # TODO PM - change this to the actual path
126
+ # # seamless remnant code
127
+ # # CLIENT_BUILD_PATH = "../streaming-react-app/dist/"
128
+ # # static_files = {
129
+ # # "/": CLIENT_BUILD_PATH,
130
+ # # "/assets/seamless-db6a2555.svg": {
131
+ # # "filename": CLIENT_BUILD_PATH + "assets/seamless-db6a2555.svg",
132
+ # # "content_type": "image/svg+xml",
133
+ # # },
134
+ # # }
135
+ # device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
136
+ # # processor = AutoProcessor.from_pretrained("facebook/seamless-m4t-v2-large", force_download=True)
137
+ # #cache_dir="/.cache"
138
+
139
+ # # PM - hardcoding temporarily as my GPU doesnt have enough vram
140
+ # # model = SeamlessM4Tv2Model.from_pretrained("facebook/seamless-m4t-v2-large").to("cpu")
141
+ # # model = SeamlessM4Tv2Model.from_pretrained("facebook/seamless-m4t-v2-large", force_download=True).to(device)
142
+
143
+
144
+ # bytes_data = bytearray()
145
+ # model_name = "seamlessM4T_v2_large"
146
+ # # vocoder_name = "vocoder_v2" if model_name == "seamlessM4T_v2_large" else "vocoder_36langs"
147
+
148
+ # clients = {}
149
+ # rooms = {}
150
+
151
+ # import torch
152
+ # from transformers import pipeline
153
+ # translator = pipeline("automatic-speech-recognition",
154
+ # "facebook/seamless-m4t-v2-large",
155
+ # torch_dtype=torch.float32,
156
+ # device="cpu")
157
+
158
+ # converter = pipeline("translation",
159
+ # "facebook/seamless-m4t-v2-large",
160
+ # torch_dtype=torch.float32,
161
+ # device="cpu")
162
+
163
+
164
+ # def get_collection_users():
165
+ # return app.database["user_records"]
166
+
167
+ # def get_collection_calls():
168
+ # # return app.database["call_records"]
169
+ # return app.database["call_test"]
170
+
171
+
172
+ # @app.get("/test/", response_description="Welcome User")
173
+ # def test():
174
+
175
+ # return {"message": "Welcome to InterpreTalk!"}
176
+
177
+
178
+ # @app.post("/test_post/", response_description="List more test call records")
179
+ # def test_post():
180
+ # request_data = {
181
+ # "call_id": "TESTID000001"
182
+ # }
183
+
184
+ # result = create_calls(get_collection_calls(), request_data)
185
+
186
+ # # return {"message": "Welcome to InterpreTalk!"}
187
+ # return result
188
+
189
+ # @app.put("/test_put/", response_description="List test call records")
190
+ # def test_put():
191
+
192
+ # # result = list_calls(get_collection_calls(), 100)
193
+ # # result = send_captions("TEST", "TEST", "TEST", "oUjUxTYTQFVVjEarIcZ0")
194
+ # result = send_captions("TEST", "TEST", "TEST", "TESTID000001")
195
+
196
+ # print(result)
197
+ # return result
198
+
199
+
200
+ # async def send_translated_text(client_id, original_text, translated_text, room_id):
201
+ # print('SEND_TRANSLATED_TEXT IS WOKRING IN FASTAPI BACKEND...')
202
+ # print(rooms)
203
+ # print(clients)
204
+
205
+ # data = {
206
+ # "author": str(client_id),
207
+ # "original_text": str(original_text),
208
+ # "translated_text": str(translated_text),
209
+ # "timestamp": str(datetime.now())
210
+ # }
211
+ # gunicorn_logger.info("SENDING TRANSLATED TEXT TO CLIENT")
212
+ # await sio.emit("translated_text", data, room=room_id)
213
+ # gunicorn_logger.info("SUCCESSFULLY SEND AUDIO TO FRONTEND")
214
+
215
+ # @sio.on("connect")
216
+ # async def connect(sid, environ):
217
+ # print(f"📥 [event: connected] sid={sid}")
218
+ # query_params = dict(parse.parse_qsl(environ["QUERY_STRING"]))
219
+ # client_id = query_params.get("client_id")
220
+ # gunicorn_logger.info(f"📥 [event: connected] sid={sid}, client_id={client_id}")
221
+ # # sid = socketid, client_id = client specific ID ,always the same for same user
222
+ # clients[sid] = Client(sid, client_id)
223
+ # gunicorn_logger.warning(f"Client connected: {sid}")
224
+ # gunicorn_logger.warning(clients)
225
+
226
+ # @sio.on("disconnect")
227
+ # async def disconnect(sid): # BO - also pass call id as parameter for updating MongoDB
228
+ # gunicorn_logger.debug(f"📤 [event: disconnected] sid={sid}")
229
+ # clients.pop(sid, None)
230
+ # # BO -> Update Call record with call duration, key terms
231
+
232
+ # @sio.on("target_language")
233
+ # async def target_language(sid, target_lang):
234
+ # gunicorn_logger.info(f"📥 [event: target_language] sid={sid}, target_lang={target_lang}")
235
+ # clients[sid].target_language = target_lang
236
+
237
+ # @sio.on("call_user")
238
+ # async def call_user(sid, call_id):
239
+ # clients[sid].call_id = call_id
240
+ # gunicorn_logger.info(f"CALL {sid}: entering room {call_id}")
241
+ # rooms[call_id] = rooms.get(call_id, [])
242
+ # if sid not in rooms[call_id] and len(rooms[call_id]) < 2:
243
+ # rooms[call_id].append(sid)
244
+ # sio.enter_room(sid, call_id)
245
+ # else:
246
+ # gunicorn_logger.info(f"CALL {sid}: room {call_id} is full")
247
+ # # await sio.emit("room_full", room=call_id, to=sid)
248
+
249
+ # # # BO - Get call id from dictionary created during socketio connection
250
+ # # client_id = clients[sid].client_id
251
 
252
+ # # gunicorn_logger.warning(f"NOW TRYING TO CREATE DB RECORD FOR Caller with ID: {client_id} for call: {call_id}")
253
+ # # # # BO -> Create Call Record with Caller and call_id field (None for callee, duration, terms..)
254
+ # # request_data = {
255
+ # # "call_id": str(call_id),
256
+ # # "caller_id": str(client_id),
257
+ # # "creation_date": str(datetime.now())
258
+ # # }
259
+
260
+ # # response = create_calls(get_collection_calls(), request_data)
261
+ # # print(response) # BO - print created db call record
262
+
263
+ # @sio.on("audio_config")
264
+ # async def audio_config(sid, sample_rate):
265
+ # clients[sid].original_sr = sample_rate
266
+
267
+
268
+ # @sio.on("answer_call")
269
+ # async def answer_call(sid, call_id):
270
+
271
+ # clients[sid].call_id = call_id
272
+ # gunicorn_logger.info(f"ANSWER {sid}: entering room {call_id}")
273
+ # rooms[call_id] = rooms.get(call_id, [])
274
+ # if sid not in rooms[call_id] and len(rooms[call_id]) < 2:
275
+ # rooms[call_id].append(sid)
276
+ # sio.enter_room(sid, call_id)
277
+ # else:
278
+ # gunicorn_logger.info(f"ANSWER {sid}: room {call_id} is full")
279
+ # # await sio.emit("room_full", room=call_id, to=sid)
280
+
281
+
282
+ # # # BO - Get call id from dictionary created during socketio connection
283
+ # # client_id = clients[sid].client_id
284
 
285
+ # # # BO -> Update Call Record with Callee field based on call_id
286
+ # # gunicorn_logger.warning(f"NOW UPDATING MongoDB RECORD FOR Caller with ID: {client_id} for call: {call_id}")
287
+ # # # # BO -> Create Call Record with callee_id field (None for callee, duration, terms..)
288
+ # # request_data = {
289
+ # # "callee_id": client_id
290
+ # # }
291
+
292
+ # # response = update_calls(get_collection_calls(), call_id, request_data)
293
+ # # print(response) # BO - print created db call record
294
 
295
 
296
+ # @sio.on("incoming_audio")
297
+ # async def incoming_audio(sid, data, call_id):
298
+ # try:
299
+ # clients[sid].add_bytes(data)
300
+
301
+ # if clients[sid].get_length() >= MAX_BYTES_BUFFER:
302
+ # gunicorn_logger.info('Buffer full, now outputting...')
303
+ # output_path = clients[sid].output_path
304
+ # vad_result, resampled_audio = clients[sid].resample_and_write_to_file()
305
+ # # source lang is speakers tgt language 😃
306
+ # src_lang = clients[sid].target_language
307
+ # if vad_result:
308
+ # gunicorn_logger.info('Speech detected, now processing audio.....')
309
+ # tgt_sid = next(id for id in rooms[call_id] if id != sid)
310
+ # tgt_lang = clients[tgt_sid].target_language
311
+ # # following example from https://github.com/facebookresearch/seamless_communication/blob/main/docs/m4t/README.md#transformers-usage
312
+ # # output_tokens = processor(audios=resampled_audio, src_lang=src_lang, return_tensors="pt")
313
+ # # model_output = model.generate(**output_tokens, tgt_lang=src_lang, generate_speech=False)[0].tolist()[0]
314
+ # # asr_text = processor.decode(model_output, skip_special_tokens=True)
315
+ # asr_text = translator(resampled_audio, generate_kwargs={"tgt_lang": src_lang})['text']
316
+ # print(f"ASR TEXT = {asr_text}")
317
+ # # ASR TEXT => ORIGINAL TEXT
318
+
319
+ # # t2t_tokens = processor(text=asr_text, src_lang=src_lang, tgt_lang=tgt_lang, return_tensors="pt")
320
+ # # print(f"FIRST TYPE = {type(output_tokens)}, SECOND TYPE = {type(t2t_tokens)}")
321
+ # # translated_data = model.generate(**t2t_tokens, tgt_lang=tgt_lang, generate_speech=False)[0].tolist()[0]
322
+ # # translated_text = processor.decode(translated_data, skip_special_tokens=True)
323
+ # translated_text = converter(asr_text, src_lang=src_lang, tgt_lang=tgt_lang)
324
+ # print(f"TRANSLATED TEXT = {translated_text}")
325
+
326
+ # # BO -> send translated_text to mongodb as caption record update based on call_id
327
+ # # send_captions(clients[sid].client_id, asr_text, translated_text, call_id)
328
 
329
+ # # TRANSLATED TEXT
330
+ # # PM - text_output is a list with 1 string
331
+ # await send_translated_text(clients[sid].client_id, asr_text, translated_text, call_id)
332
 
333
+ # # # BO -> send translated_text to mongodb as caption record update based on call_id
334
+ # # send_captions(clients[sid].client_id, asr_text, translated_text, call_id)
335
 
336
+ # except Exception as e:
337
+ # gunicorn_logger.error(f"Error in incoming_audio: {e.with_traceback()}")
338
 
339
+ # def send_captions(client_id, original_text, translated_text, call_id):
340
+ # # BO -> Update Call Record with Callee field based on call_id
341
+ # print(f"Now updating Caption field in call record for Caller with ID: {client_id} for call: {call_id}")
342
+
343
+ # data = {
344
+ # "author": str(client_id),
345
+ # "original_text": str(original_text),
346
+ # "translated_text": str(translated_text),
347
+ # "timestamp": str(datetime.now())
348
+ # }
349
+
350
+ # response = update_captions(get_collection_calls(), call_id, data)
351
+ # return response
352
+
353
+ # app.mount("/", socketio_app)
354
+
355
+ # if __name__ == '__main__':
356
+ # uvicorn.run("main:app", host='0.0.0.0', port=7860, log_level="debug")
357
+
358
+ # # Running in Docker Container
359
+ # if __name__ != "__main__":
360
+ # fastapi_logger.setLevel(gunicorn_logger.level)
361
+ # else:
362
+ # fastapi_logger.setLevel(logging.DEBUG)
363
+
364
+ from huggingface_hub import scan_cache_dir
365
+
366
+ hf_cache_info = scan_cache_dir()