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()
|