from flask import Flask, request, Response import subprocess import os import time import random from datetime import datetime app = Flask(__name__) # Ensure storage directories exist os.makedirs('texts', exist_ok=True) os.makedirs('audio', exist_ok=True) def generate_filename(): """Generate timestamp + random number filename""" timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") random_num = random.randint(1000, 9999) return f"{timestamp}_{random_num}" @app.route('/tts', methods=['POST']) def tts(): # Validate input if not request.is_json: return {"error": "Request must be JSON"}, 400 text = request.json.get('text', '').strip() if not text: return {"error": "No text provided"}, 400 if len(text) > 1000: return {"error": "Text too long (max 1000 characters)"}, 400 # Generate unique filename base_filename = generate_filename() text_filename = f"data/texts/{base_filename}.txt" wav_filename = f"data/audio/{base_filename}.wav" try: # Save the input text with open(text_filename, 'w') as f: f.write(text) # Generate WAV audio with Piper - directly to file first piper_cmd = [ 'echo', f'"{text}"', '|', './piper/piper', '--model', './model/en_US-amy-medium.onnx', '--output_file', wav_filename ] # Run the command process = subprocess.run( ' '.join(piper_cmd), shell=True, check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE ) # Verify the output file was created if not os.path.exists(wav_filename): raise Exception("Piper failed to create audio file") # Get file size for logging file_size = os.path.getsize(wav_filename) # Read the generated audio with open(wav_filename, 'rb') as f: audio_data = f.read() # Log the successful generation print(f"Generated TTS: {len(text)} chars -> {file_size} bytes audio") # Return WAV audio directly return Response( audio_data, mimetype='audio/wav', headers={'Content-Disposition': f'attachment; filename={base_filename}.wav'} ) except subprocess.CalledProcessError as e: error_msg = f"Piper TTS failed: {e.stderr.decode().strip()}" print(error_msg) return {"error": "TTS generation failed", "details": error_msg}, 500 except Exception as e: error_msg = f"Unexpected error: {str(e)}" print(error_msg) return {"error": "TTS processing failed", "details": error_msg}, 500 if __name__ == '__main__': app.run(host='0.0.0.0', port=4005, debug=True)