| import os |
| import shutil |
| from fastapi import FastAPI, UploadFile, Form, HTTPException |
| from fastapi.responses import FileResponse, JSONResponse |
| from fastapi.middleware.cors import CORSMiddleware |
| from fastapi.staticfiles import StaticFiles |
| import time |
|
|
| |
| from utils import load_and_validate_audio, save_temp_wav, save_generated_audio, generate_history_list |
| from generate import generate_speech |
| from config import OUTPUTS_DIR, UPLOADS_DIR |
|
|
| app = FastAPI(title="Voice Cloning API") |
|
|
| |
| app.add_middleware( |
| CORSMiddleware, |
| allow_origins=["*"], |
| allow_credentials=True, |
| allow_methods=["*"], |
| allow_headers=["*"], |
| ) |
|
|
| @app.post("/api/generate") |
| async def api_generate( |
| audio_file: UploadFile, |
| text_prompt: str = Form(...) |
| ): |
| if not text_prompt or not text_prompt.strip(): |
| raise HTTPException(status_code=400, detail="Please enter some text to generate.") |
| |
| temp_upload_path = os.path.join(UPLOADS_DIR, audio_file.filename) |
| try: |
| |
| with open(temp_upload_path, "wb") as buffer: |
| shutil.copyfileobj(audio_file.file, buffer) |
| |
| |
| y, sr = load_and_validate_audio(temp_upload_path) |
| |
| |
| processed_path = save_temp_wav(y, sr, temp_upload_path) |
| |
| |
| out_sr, out_y, gen_time = generate_speech(text_prompt, processed_path) |
| |
| |
| out_path = save_generated_audio(out_y, out_sr, text_prompt) |
| |
| |
| if os.path.exists(processed_path): |
| os.remove(processed_path) |
| |
| return JSONResponse(content={ |
| "success": True, |
| "message": f"Generation successful in {gen_time:.1f} seconds.", |
| "generation_time": gen_time, |
| "audio_url": f"/outputs/{os.path.basename(out_path)}" |
| }) |
| |
| except ValueError as ve: |
| raise HTTPException(status_code=400, detail=str(ve)) |
| except Exception as e: |
| raise HTTPException(status_code=500, detail=f"An error occurred: {str(e)}") |
| finally: |
| |
| if os.path.exists(temp_upload_path): |
| os.remove(temp_upload_path) |
|
|
| @app.get("/api/history") |
| def get_history(): |
| history = generate_history_list() |
| |
| |
| items = [] |
| for f in history: |
| items.append({ |
| "filename": f[0], |
| "url": f"/outputs/{f[0]}", |
| "size": f[2] |
| }) |
| return {"history": items} |
|
|
| @app.delete("/api/history/{filename}") |
| def delete_history_item(filename: str): |
| file_path = os.path.join(OUTPUTS_DIR, filename) |
| if os.path.exists(file_path): |
| os.remove(file_path) |
| return {"success": True} |
| raise HTTPException(status_code=404, detail="File not found") |
|
|
| @app.get("/outputs/{filename}") |
| def serve_audio(filename: str): |
| file_path = os.path.join(OUTPUTS_DIR, filename) |
| if os.path.exists(file_path): |
| return FileResponse(file_path) |
| raise HTTPException(status_code=404, detail="File not found") |
|
|
| |
| dist_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "dist") |
| if os.path.exists(dist_path): |
| app.mount("/", StaticFiles(directory=dist_path, html=True), name="static") |
|
|