| import os |
| import sys |
| import json |
| import base64 |
| import wave |
| import signal |
| import argparse |
| import threading |
| import logging |
| import time |
| from queue import Queue, Empty |
| from datetime import datetime |
| import httpx |
| from fastapi import FastAPI, WebSocket, Request |
| from fastapi.responses import JSONResponse |
| import requests |
|
|
| from deepgram import ( |
| DeepgramClient, |
| DeepgramClientOptions, |
| PrerecordedOptions, |
| FileSource, |
| ) |
| from deepgram.utils import verboselogs |
|
|
| from fastapi import FastAPI, WebSocket |
| import uvicorn |
|
|
| app = FastAPI() |
|
|
| def transcribe_audio_file(audio_file_path: str): |
| lang_file_updated_to_hindi = False |
| try: |
| if not os.path.exists(audio_file_path): |
| print(f"Error: File '{audio_file_path}' does not exist for transcription.") |
| return |
|
|
| |
| config = DeepgramClientOptions( |
| verbose=verboselogs.SPAM, |
| ) |
| deepgram = DeepgramClient("30880849b38adbbf45da95e3c7cb0f18ca89e6ea", config) |
|
|
| |
| print(f"Reading audio file for transcription: {audio_file_path}...") |
| with open(audio_file_path, "rb") as file: |
| buffer_data = file.read() |
|
|
| |
| payload: FileSource = { |
| "buffer": buffer_data, |
| } |
|
|
| |
| options = PrerecordedOptions( |
| model="general", |
| smart_format=True, |
| utterances=True, |
| punctuate=True, |
| diarize=True, |
| language="hi", |
| ) |
|
|
| |
| print("Transcribing...") |
| before = datetime.now() |
| response = deepgram.listen.rest.v("1").transcribe_file( |
| payload, options, timeout=httpx.Timeout(300.0, connect=10.0) |
| ) |
| after = datetime.now() |
|
|
| |
| response_json_str = response.to_json() |
| has_hindi_ha = "\\u0939" in response_json_str |
| has_hindi_na = "\\u0928" in response_json_str |
| |
| |
| if has_hindi_ha and not has_hindi_na: |
| print("[*] Detected Hindi character '\u0939' without '\u0928' in transcription response.") |
| with open("LANG.txt", "w") as f: |
| f.write("HINDI") |
| lang_file_updated_to_hindi = True |
| print("[*] Updated LANG.txt with HINDI.") |
| else: |
| if has_hindi_na: |
| print("[*] Detected Hindi character '\u0928' - not updating to Hindi.") |
| else: |
| print("[*] Did not detect required Hindi characters in transcription response.") |
|
|
| |
| print("\nTranscription Results:") |
| print("=" * 50) |
| print(response.to_json(indent=4)) |
| print("\nTime taken:", (after - before).seconds, "seconds") |
|
|
| except Exception as e: |
| print(f"Error during transcription: {e}") |
| finally: |
| |
| if not lang_file_updated_to_hindi: |
| try: |
| with open("LANG.txt", "w") as f: |
| f.write("") |
| print("[*] LANG.txt cleared (either not Hindi or error occurred).") |
| except IOError: |
| print("[*] Could not clear LANG.txt in finally block.") |
|
|
| class Stream: |
| def __init__(self, rate, channels, sample_width): |
| self.rate = rate |
| self.channels = channels |
| self.sample_width = sample_width |
| self.buff = Queue() |
| self.closed = False |
| self.output_file = "output.wav" |
| self.frames = [] |
| self.start_time = None |
| self.recording_duration = 5 |
|
|
| def fill_buffer(self, chunk): |
| if self.start_time is None: |
| self.start_time = time.time() |
| |
| |
| if time.time() - self.start_time <= self.recording_duration: |
| self.buff.put(chunk) |
| else: |
| if not self.closed: |
| self.closed = True |
| print(f"[*] Recording stopped after {self.recording_duration} seconds") |
|
|
| def save_audio(self): |
| print("[*] Saving audio to", self.output_file) |
| with wave.open(self.output_file, 'wb') as wf: |
| wf.setnchannels(self.channels) |
| wf.setsampwidth(self.sample_width) |
| wf.setframerate(self.rate) |
| wf.writeframes(b''.join(self.frames)) |
| print("[*] Audio saved successfully.") |
| |
| |
| if os.path.exists(self.output_file): |
| print(f"[*] Initiating transcription for {self.output_file}") |
| transcribe_audio_file(self.output_file) |
| else: |
| print(f"[*] Transcription skipped: {self.output_file} not found after saving.") |
|
|
| def consume_audio(self): |
| while not self.closed: |
| try: |
| chunk = self.buff.get(timeout=1) |
| if chunk is None: |
| break |
| self.frames.append(chunk) |
| except Empty: |
| continue |
|
|
| @app.websocket("/media") |
| async def media_endpoint(websocket: WebSocket): |
| await websocket.accept() |
| print("[*] WebSocket connection accepted") |
|
|
| has_seen_media = False |
| message_count = 0 |
|
|
| |
| stream = Stream(rate=8000, channels=1, sample_width=2) |
| consumer_thread = threading.Thread(target=stream.consume_audio) |
| consumer_thread.start() |
|
|
| while True: |
| try: |
| message = await websocket.receive_text() |
| except: |
| break |
|
|
| if message is None: |
| print("[*] No message received") |
| continue |
|
|
| data = json.loads(message) |
|
|
| if data["event"] == "connected": |
| print("[*] Connected Message:", message) |
| elif data["event"] == "start": |
| print("[*] Start Message:", message) |
| elif data["event"] == "media": |
| payload = data["media"]["payload"] |
| chunk = base64.b64decode(payload) |
| stream.fill_buffer(chunk) |
|
|
| if not has_seen_media: |
| print("[*] First media message received. Suppressing further logs.") |
| has_seen_media = True |
|
|
| elif data["event"] == "stop": |
| print("[*] Stop Message:", message) |
| break |
|
|
| message_count += 1 |
|
|
| |
| if stream.closed: |
| break |
|
|
| print(f"[*] WebSocket connection closed. Total messages: {message_count}") |
| stream.closed = True |
| consumer_thread.join() |
| stream.save_audio() |
|
|
| def signal_handler(sig, frame): |
| print("Exiting gracefully...") |
| sys.exit(0) |
|
|
| |
| @app.get("/health") |
| async def health_check_get(): |
| try: |
| with open("LANG.txt", "r") as f: |
| content = f.read().strip() |
| if content == "HINDI": |
| return JSONResponse(content={"message": "GET OK - Hindi language detected"}, status_code=200) |
| except FileNotFoundError: |
| pass |
| except IOError as e: |
| print(f"Error reading LANG.txt for GET health check: {e}") |
| return JSONResponse(content={"message": "GET OK - Hindi language not detected"}, status_code=404) |
|
|
| @app.post("/health") |
| async def health_check_post(request: Request): |
| try: |
| with open("LANG.txt", "r") as f: |
| content = f.read().strip() |
| if content == "HINDI": |
| return JSONResponse(content={"message": "POST OK - Hindi language detected"}, status_code=200) |
| except FileNotFoundError: |
| pass |
| except IOError as e: |
| print(f"Error reading LANG.txt for POST health check: {e}") |
| return JSONResponse(content={"message": "POST OK - Hindi language not detected"}, status_code=404) |
|
|
| if __name__ == "__main__": |
| parser = argparse.ArgumentParser(description='FastAPI WebSocket Audio Saver') |
| parser.add_argument('--port', type=int, default=8000, help='Port to run the server on') |
| args = parser.parse_args() |
|
|
| signal.signal(signal.SIGINT, signal_handler) |
|
|
| print(f"[*] Server running at ws://localhost:{args.port}/media") |
| uvicorn.run("app:app", host="0.0.0.0", port=args.port, log_level="info") |