from fastapi import FastAPI, UploadFile, Form from fastapi.responses import FileResponse, JSONResponse from piper.voice import PiperVoice import soundfile as sf import numpy as np import uuid import os app = FastAPI() # Load the voice model voice_model_path = "en_US-hfc_female-medium.onnx" voice = PiperVoice.load(voice_model_path) # Directory to store generated audio files output_dir = "generated_audio" os.makedirs(output_dir, exist_ok=True) @app.post("/text-to-speech/") async def text_to_speech(text: str = Form(...)): """ Convert text to speech and return the generated audio file. Args: text: The input text to convert to speech. Returns: The path to the generated audio file. """ try: # Generate a unique filename output_file = os.path.join(output_dir, f"{uuid.uuid4()}.ogg") # Synthesize and save the audio with sf.SoundFile(output_file, mode='w', samplerate=voice.config.sample_rate, channels=1, format='OGG', subtype='VORBIS') as ogg_file: for audio_bytes in voice.synthesize_stream_raw(text): int_data = np.frombuffer(audio_bytes, dtype=np.int16) ogg_file.write(int_data) return FileResponse(output_file, media_type="audio/ogg", filename=output_file) except Exception as e: return JSONResponse(content={"error": str(e)}, status_code=500) @app.get("/") def root(): """ Root endpoint to confirm the API is running. """ return {"message": "Text-to-Speech API is up and running!"}