Upload api_env.py
Browse files- api_env.py +93 -0
api_env.py
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from flask import Flask, request, send_file, jsonify
|
| 2 |
+
from gevent.pywsgi import WSGIServer
|
| 3 |
+
from functools import wraps
|
| 4 |
+
from art import tprint
|
| 5 |
+
import edge_tts
|
| 6 |
+
import asyncio
|
| 7 |
+
import tempfile
|
| 8 |
+
import os
|
| 9 |
+
|
| 10 |
+
app = Flask(__name__)
|
| 11 |
+
|
| 12 |
+
# Use environment variables for API_KEY and PORT
|
| 13 |
+
API_KEY = os.environ.get('API_KEY')
|
| 14 |
+
PORT = int(os.environ.get('PORT', 5000))
|
| 15 |
+
|
| 16 |
+
tprint("OPEN SPEECH")
|
| 17 |
+
print(f"OpenSource TTS API Compatible with OpenAI API")
|
| 18 |
+
print(f" ")
|
| 19 |
+
print(f" ---------------------------------------------------------------- ")
|
| 20 |
+
print(f" * Serving OpenVoice API")
|
| 21 |
+
print(f" * Server running on http://localhost:{PORT}")
|
| 22 |
+
print(f" * Voice Endpoint Generated: http://localhost:{PORT}/v1/audio/speech")
|
| 23 |
+
print(f" ")
|
| 24 |
+
print("Press CTRL+C to quit")
|
| 25 |
+
|
| 26 |
+
def require_api_key(f):
|
| 27 |
+
@wraps(f)
|
| 28 |
+
def decorated_function(*args, **kwargs):
|
| 29 |
+
auth_header = request.headers.get('Authorization')
|
| 30 |
+
if not auth_header or not auth_header.startswith('Bearer '):
|
| 31 |
+
return jsonify({"error": "Missing or invalid API key"}), 401
|
| 32 |
+
token = auth_header.split('Bearer ')[1]
|
| 33 |
+
if token != API_KEY:
|
| 34 |
+
return jsonify({"error": "Invalid API key"}), 401
|
| 35 |
+
return f(*args, **kwargs)
|
| 36 |
+
return decorated_function
|
| 37 |
+
|
| 38 |
+
@app.route('/v1/audio/speech', methods=['POST'])
|
| 39 |
+
@require_api_key
|
| 40 |
+
def text_to_speech():
|
| 41 |
+
data = request.json
|
| 42 |
+
if not data or 'input' not in data:
|
| 43 |
+
return jsonify({"error": "Missing 'input' in request body"}), 400
|
| 44 |
+
|
| 45 |
+
text = data['input']
|
| 46 |
+
model = data.get('model', 'tts-1') # We will ignore this input
|
| 47 |
+
voice = data.get('voice', 'en-US-AriaNeural')
|
| 48 |
+
|
| 49 |
+
# Map OpenAI voices to edge-tts voices (this is a simple mapping, you might want to expand it)
|
| 50 |
+
voice_mapping = {
|
| 51 |
+
'alloy': 'en-US-AriaNeural',
|
| 52 |
+
'echo': 'en-US-GuyNeural',
|
| 53 |
+
'fable': 'en-GB-SoniaNeural',
|
| 54 |
+
'onyx': 'en-US-ChristopherNeural',
|
| 55 |
+
'nova': 'en-AU-NatashaNeural',
|
| 56 |
+
'shimmer': 'en-US-JennyNeural'
|
| 57 |
+
}
|
| 58 |
+
|
| 59 |
+
edge_tts_voice = voice_mapping.get(voice, voice)
|
| 60 |
+
|
| 61 |
+
output_file = tempfile.NamedTemporaryFile(delete=False, suffix=".mp3")
|
| 62 |
+
|
| 63 |
+
async def generate_speech():
|
| 64 |
+
communicate = edge_tts.Communicate(text, edge_tts_voice)
|
| 65 |
+
await communicate.save(output_file.name)
|
| 66 |
+
|
| 67 |
+
asyncio.run(generate_speech())
|
| 68 |
+
|
| 69 |
+
return send_file(output_file.name, mimetype="audio/mpeg", as_attachment=True, download_name="speech.mp3")
|
| 70 |
+
|
| 71 |
+
@app.route('/v1/models', methods=['GET'])
|
| 72 |
+
@require_api_key
|
| 73 |
+
def list_models():
|
| 74 |
+
# For simplicity, we're returning a fixed list of "models"
|
| 75 |
+
models = [
|
| 76 |
+
{"id": "tts-1", "name": "Text-to-speech v1"},
|
| 77 |
+
{"id": "tts-1-hd", "name": "Text-to-speech v1 HD"}
|
| 78 |
+
]
|
| 79 |
+
return jsonify({"data": models})
|
| 80 |
+
|
| 81 |
+
@app.route('/v1/voices', methods=['GET'])
|
| 82 |
+
@require_api_key
|
| 83 |
+
def list_voices():
|
| 84 |
+
voices = edge_tts.list_voices()
|
| 85 |
+
# Transform the voice data to match OpenAI's format
|
| 86 |
+
formatted_voices = [{"name": v['ShortName'], "language": v['Locale']} for v in voices]
|
| 87 |
+
return jsonify({"voices": formatted_voices})
|
| 88 |
+
|
| 89 |
+
if __name__ == '__main__':
|
| 90 |
+
if not API_KEY:
|
| 91 |
+
print("Warning: API_KEY environment variable is not set.")
|
| 92 |
+
http_server = WSGIServer(('0.0.0.0', PORT), app)
|
| 93 |
+
http_server.serve_forever()
|