| import subprocess |
| import time |
| import os |
| from wit import Wit |
| import random |
| import json |
| from fastapi import FastAPI, Request, HTTPException |
| import logging |
| import threading |
| from mutagen.mp3 import MP3 |
|
|
| logging.basicConfig(filename='WebServer.log', filemode='w', level=logging.DEBUG) |
|
|
| |
| platform = "Linux" |
|
|
| |
| |
| |
| env_keys = os.getenv("WIT_API_KEY", "") |
| api_keys = [key.strip() for key in env_keys.split(",")] if env_keys else [] |
|
|
| if not api_keys or not api_keys[0]: |
| print("WARNING: WIT_API_KEY Secret is not set in Hugging Face!") |
| |
|
|
| wit_api = {} |
| resp = {} |
|
|
| for api_key in api_keys: |
| wit_api[api_key] = Wit(api_key) |
|
|
| |
| base_dir = "/tmp/SpeechRecognition" |
|
|
| if platform == "Linux": |
| try: |
| if not os.path.exists(base_dir): |
| os.makedirs(f"{base_dir}/Cache", exist_ok=True) |
| os.chdir(base_dir) |
| else: |
| os.chdir(base_dir) |
| except Exception as e: |
| print(f"Error setting up directory: {e}") |
|
|
| app = FastAPI() |
|
|
| |
|
|
| @app.get('/') |
| def index(request: Request): |
| return { |
| "status": "online", |
| "message": "Speech server is running. Send a .webm audio file via POST to /speech" |
| } |
|
|
| @app.post('/speech') |
| async def process(request: Request): |
| start_execution = time.time() |
|
|
| |
| data_length = str(round(float(int(request.headers.get('content-length', 0)) / 1024),2)) |
| random_hash = random.randint(10000000000,99999999999) |
|
|
| if float(data_length) > 500: |
| print('The incoming speech request has exceeded the 500KB limit established by the Developer, Size: ' + str(data_length) + "KB") |
| return |
|
|
| print("[" + str(random_hash) + "] Speech request received from " + request.client.host + " | " + " Size of incoming data: " + data_length + "KB.") |
| logging.info("[" + str(random_hash) + "] Speech request received from " + request.client.host + " | " + " Size of incoming data: " + data_length + "KB.") |
|
|
| webm = await request.body() |
| logging.debug("[" + str(random_hash) + "] .webm obtained from the Body request.") |
|
|
| |
| with open("Cache/" + str(random_hash) + ".webm", "wb") as file: |
| file.write(webm) |
| file.close() |
| logging.debug("[" + str(random_hash) + "] .webm written to file " + str(random_hash) + ".webm") |
|
|
| |
| logging.debug("[" + str(random_hash) + "] Starting conversion .webm to .mp3") |
| start_time = time.time() |
|
|
| if platform == "Linux": |
| convert = subprocess.Popen([ |
| "ffmpeg", "-i", f"{base_dir}/Cache/{random_hash}.webm", |
| "-af", "silenceremove=stop_periods=-1:stop_duration=0.02:stop_threshold=-53dB", |
| "-vn", "-ac", "1", "-b:a", "64k", f"{base_dir}/Cache/{random_hash}.mp3" |
| ], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) |
| convert.wait() |
| |
| logging.debug("[" + str(random_hash) + "] Conversion finished, time " + str(round(float((time.time() - start_time) * 1000),2)) + " msec") |
| |
| |
| with open("Cache/" + str(random_hash) + ".mp3", "rb") as file: |
| audio_read = file.read() |
| file.close() |
|
|
| |
| length = 0 |
| try: |
| audio = MP3("Cache/" + str(random_hash) + ".mp3") |
| length = audio.info.length |
| except: |
| print("Error reading Audio") |
|
|
| start_req = time.time() |
| |
| |
| if not api_keys: |
| return {"error": "API keys not configured on server."} |
| |
| random_api_key = random.choice(api_keys) |
| |
| |
| try: |
| resp[random_hash] = wit_api[random_api_key].speech(audio_read, {'Content-Type': 'audio/mpeg3'}) |
| logging.debug("[" + str(random_hash) + "] .mp3 sent to Wit.Ai | Request to Wit.Ai completed in " + str(round(float((time.time() - start_req) * 1000),2)) + " msec | Audio Length: " + str(round(float(length),2)) + "s") |
| print("[" + str(random_hash) + "] .mp3 sent to Wit.Ai | Request to Wit.Ai completed in " + str(round(float((time.time() - start_req) * 1000),2)) + " msec | Audio Length: " + str(round(float(length),2)) + "s") |
| print("[" + str(random_hash) + "] Recognized text ", resp[random_hash]) |
| except Exception as e: |
| logging.debug(e) |
| logging.info("[" + str(random_hash) + "] Unable to make request, manual check required.") |
|
|
| |
| def RemoveEnvironment(random_hash): |
| try: |
| os.remove("Cache/" + str(random_hash) + ".webm") |
| os.remove("Cache/" + str(random_hash) + ".mp3") |
| logging.debug("[" + str(random_hash) + "] Cleaned up environment.") |
| except: |
| logging.debug("[" + str(random_hash) + "] Unable to clean environment.") |
|
|
| threading.Thread(target=RemoveEnvironment, args=[random_hash]).start() |
|
|
| print("[" + str(random_hash) + "] Speech request completed for " + request.client.host) |
| logging.info("[" + str(random_hash) + "] Speech request completed for " + request.client.host) |
|
|
| logging.info("[" + str(random_hash) + "] Request completed in " + str(round(float((time.time() - start_execution) * 1000),2)) + " msec") |
| |
| try: |
| print("[" + str(random_hash) + "] Answer from Wit.Ai API: " + resp[random_hash]['text']) |
| return resp[random_hash]['text'] |
| except KeyError: |
| return {"error": "Could not recognize speech or invalid Wit.ai response."} |