Spaces:
Sleeping
Sleeping
File size: 4,284 Bytes
d6fcf92 1323577 d6fcf92 2e0855f d6fcf92 2e0855f d6fcf92 d0ae679 d6fcf92 d0ae679 d6fcf92 9cbfee0 d6fcf92 2e0855f d6fcf92 2e0855f d6fcf92 046ebfc 2e0855f d6fcf92 2e0855f d6fcf92 2e0855f d6fcf92 2e0855f d6fcf92 2e0855f d6fcf92 2e0855f | 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 | import asyncio
import os
import ffmpeg
from fastapi import FastAPI, WebSocket, WebSocketDisconnect
from fastapi.responses import HTMLResponse
from fastapi.staticfiles import StaticFiles
from dotenv import load_dotenv
from translator import VoiceTranslator
load_dotenv()
app = FastAPI()
#app.mount("/static", StaticFiles(directory="static"), name="static")
# Load environment variables for API keys
google_creds = os.getenv("GOOGLE_APPLICATION_CREDENTIALS")
deepl_key = os.getenv("DEEPL_API_KEY")
eleven_key = os.getenv("ELEVENLABS_API_KEY")
voice_id = os.getenv("ELEVENLABS_VOICE_ID")
# --- Start Debug Prints ---
print("--- API Key Status ---")
print(f"GOOGLE_APPLICATION_CREDENTIALS loaded: {bool(google_creds)}")
print(f"DEEPL_API_KEY loaded: {bool(deepl_key)}")
print(f"ELEVENLABS_API_KEY loaded: {bool(eleven_key)}")
print(f"ELEVENLABS_VOICE_ID loaded: {bool(voice_id)}")
print("----------------------")
if not all([google_creds, deepl_key, eleven_key, voice_id]):
raise ValueError("CRITICAL: Missing one or more required API keys. Please check your Hugging Face secrets.")
translator = VoiceTranslator(deepl_key, eleven_key, voice_id)
@app.get("/")
async def get():
return HTMLResponse(open("index.html", "r").read())
async def audio_output_sender(ws: WebSocket, output_queue: asyncio.Queue):
print("Audio output sender started.")
while True:
try:
audio_chunk = await output_queue.get()
if audio_chunk is None:
break
await ws.send_bytes(audio_chunk)
except asyncio.CancelledError:
break
print("Audio output sender stopped.")
async def handle_audio_input(websocket: WebSocket, input_queue: asyncio.Queue):
print("Audio input handler started.")
while True:
try:
data = await websocket.receive_bytes()
# Use ffmpeg to convert webm/opus audio from browser to raw pcm
process = (
ffmpeg
.input('pipe:0')
.output('pipe:1', format='s16le', acodec='pcm_s16le', ac=1, ar='16k')
.run_async(pipe_stdin=True, pipe_stdout=True, pipe_stderr=True)
)
# Write the audio data to ffmpeg's stdin and close it
process.stdin.write(data)
process.stdin.close()
# Read the converted PCM data from ffmpeg's stdout
pcm_data = process.stdout.read()
await input_queue.put(pcm_data)
except WebSocketDisconnect:
break
except Exception as e:
print(f"Audio input error: {e}")
break
print("Audio input handler stopped.")
@app.websocket("/ws") # This was correct, the error was in the old HTML. No change needed here, but confirming it's /ws.
async def websocket_endpoint(websocket: WebSocket):
print("[SERVER] WebSocket endpoint called. Awaiting connection...")
await websocket.accept()
print("[SERVER] WebSocket connection accepted.")
output_sender_task = None
input_handler_task = None
try:
# Start translation and audio processing tasks
print("[SERVER] Awaiting translator.start_translation()...")
await translator.start_translation()
print("[SERVER] translator.start_translation() returned. Creating tasks...")
output_sender_task = asyncio.create_task(
audio_output_sender(websocket, translator.output_queue)
)
input_handler_task = asyncio.create_task(
handle_audio_input(websocket, translator.input_queue)
)
print("[SERVER] Awaiting asyncio.gather for I/O tasks...")
await asyncio.gather(input_handler_task, output_sender_task)
except WebSocketDisconnect:
print("[SERVER] Client disconnected via WebSocketDisconnect.")
except Exception as e:
print(f"[SERVER] An error occurred in websocket_endpoint: {e}")
finally:
print("[SERVER] Cleaning up tasks and stopping translation...")
if output_sender_task:
output_sender_task.cancel()
if input_handler_task:
input_handler_task.cancel()
translator.stop_translation()
await websocket.close()
print("[SERVER] WebSocket connection closed.")
|