from fastapi import FastAPI, UploadFile, File, Form from fastapi.middleware.cors import CORSMiddleware import uvicorn import whisper import tempfile import os app = FastAPI() # Allow your Blogger site to communicate with this server app.add_middleware( CORSMiddleware, allow_origins=["https://lyricvideogen.blogspot.com"], allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) print("Loading AI Model (this takes a moment on startup)...") # Using the "tiny" model so it runs fast on the free CPU tier model = whisper.load_model("tiny") @app.post("/sync") async def sync_lyrics(audio: UploadFile = File(...), lyrics: str = Form(...)): print(f"Processing audio: {audio.filename}") # 1. Save the uploaded audio to a temporary file so Whisper can read it with tempfile.NamedTemporaryFile(delete=False, suffix=".mp3") as temp_audio: temp_audio.write(await audio.read()) temp_audio_path = temp_audio.name try: # 2. Run the AI to detect vocal timestamps result = model.transcribe(temp_audio_path) # 3. Process the user's custom lyrics user_lines = [line.strip() for line in lyrics.split('\n') if line.strip()] timestamps = [] # 4. Map the AI's detected timestamps to the user's custom text for i, line in enumerate(user_lines): if i < len(result["segments"]): # Grab the start time of the vocal segment start_time = result["segments"][i]["start"] else: # Fallback if the user pasted more text lines than the AI heard vocals start_time = timestamps[-1]["time"] + 2.0 if timestamps else 0.0 timestamps.append({"text": line, "time": start_time}) return {"status": "success", "timestamps": timestamps} finally: # Clean up the server storage os.remove(temp_audio_path) if __name__ == "__main__": uvicorn.run(app, host="0.0.0.0", port=7860)