File size: 6,510 Bytes
e267014 44aa21a | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 | import os
import requests
from flask import Flask, request, jsonify, send_file
import uuid
app = Flask(__name__)
def get_firebase_token():
"""Get a Firebase ID token using a refresh token"""
url = "https://securetoken.googleapis.com/v1/token?key=AIzaSyDbAIg5AN6Cb5kITejfovleb5VDWw0Kv7s"
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36",
"x-client-data": "CIq2yQEIprbJAQipncoBCOLwygEIlaHLAQiKo8sBCJz+zAEIhaDNAQj2ps0BCJDfzgE=",
"x-client-version": "Chrome/JsCore/10.14.1/FirebaseCore-web",
"x-firebase-gmpid": "1:593863204797:web:0b6f963bf7dfea5a28bcd4"
}
data = {
"grant_type": "refresh_token",
"refresh_token": "AMf-vBzwgbfU1K3obVOps6iNiXSW7-_i8XvcCLNyRuBhn0wP4PiMdnL74SUooQqW1fNQS3m-echJJDYpeTDv2kgdTMYQ6TMbvFv2PvYiSjDudoa_QdYuHwe44hP9RhPwt65N0yH-KdVJA0tziY7ihmYCG-14Inhas88TcQOmRZJdbr3vrIoaE7XI0vA-dFNYzfqcOyGxeDZWHnOj8fq3WR5K6LBHacavxOSyfBPDIHAHSaxhirhejFtkx1GPpSZ5L3zMKPlCohJ8NnvYquabhp_Uw7qPytHkAQjPLAlcyeJ4MR2BK0KLfnpLq1sR_mVPJ-Gm8NE89UIwM2XvdcZ6JWgHGEIxTR-hrfgxC0Ku0ZAGA4oDdBlndPIfc13tc-bcw7SEKpgOI6Gmb-4GH4_Tl7jgfJX8wI0O1x08nmb86BYyugf2eGCIKinv091o9cPPSZEvnweE8rX0"
}
response = requests.post(url, headers=headers, data=data)
if response.status_code == 200:
json_response = response.json()
id_token = json_response.get("id_token")
if id_token:
print("β
Firebase token retrieved successfully")
return id_token
else:
raise ValueError("Firebase ID token not found in the response")
else:
raise Exception(f"β Failed to retrieve Firebase token. Status code: {response.status_code}, Response: {response.text}")
def get_speechify_auth_token(firebase_token):
"""Exchange Firebase token for Speechify authentication token"""
url = f"https://audio.api.speechify.com/v1/auth/sign?id_token={firebase_token}"
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36",
"Authorization": f"Bearer {firebase_token}",
"Content-Type": "application/json"
}
response = requests.get(url, headers=headers)
if response.status_code == 200:
speechify_token = response.json().get('token')
if speechify_token:
print("β
Speechify token retrieved successfully")
return speechify_token
else:
raise ValueError("Speechify token not found in the response")
else:
raise Exception(f"β Failed to retrieve Speechify token. Status code: {response.status_code}, Response: {response.text}")
def synthesize_speech(token, text, voice_id, output_file):
"""Generate speech audio using Speechify API"""
url = "https://audio.api.speechify.com/v3/synthesis/get"
headers = {
"authorization": f"Bearer {token}",
"x-speechify-client": "WebApp",
"x-speechify-client-version": "2.3.0",
"Content-Type": "application/json"
}
payload = {
"ssml": f"<speak>{text}</speak>",
"voice": voice_id,
"forcedAudioFormat": "mp3"
}
try:
response = requests.post(url, headers=headers, json=payload)
if response.status_code == 200:
with open(output_file, "wb") as f:
f.write(response.content)
print(f"β
MP3 file saved as {output_file}")
return True
else:
print(f"β Failed to generate audio. Status code: {response.status_code}")
print(response.text)
return False
except Exception as e:
print(f"β An error occurred during speech synthesis: {str(e)}")
return False
# Create output directory if it doesn't exist
os.makedirs("output", exist_ok=True)
@app.route('/synthesize', methods=['POST'])
def api_synthesize_speech():
"""API endpoint to synthesize speech from text"""
try:
# Get parameters from request
data = request.json
if not data:
return jsonify({"error": "No JSON data provided"}), 400
text = data.get('text')
voice_id = data.get('voice_id', 'PVL:4f4a27ef-2b17-424f-904c-30bd1ed60fb8') # Default voice if not provided
if not text:
return jsonify({"error": "No text provided"}), 400
# Generate a unique filename
filename = f"output/{uuid.uuid4()}.mp3"
# Get tokens and synthesize speech
firebase_token = get_firebase_token()
speechify_token = get_speechify_auth_token(firebase_token)
result = synthesize_speech(speechify_token, text, voice_id, filename)
if result:
# Return the audio file
return send_file(filename, mimetype='audio/mpeg', as_attachment=True)
else:
return jsonify({"error": "Failed to synthesize speech"}), 500
except Exception as e:
return jsonify({"error": str(e)}), 500
@app.route('/', methods=['GET'])
def home():
"""Home page with usage instructions"""
return """
<html>
<head>
<title>Speechify API</title>
<style>
body { font-family: Arial, sans-serif; max-width: 800px; margin: 0 auto; padding: 20px; }
code { background-color: #f4f4f4; padding: 2px 5px; border-radius: 3px; }
pre { background-color: #f4f4f4; padding: 10px; border-radius: 5px; overflow-x: auto; }
</style>
</head>
<body>
<h1>Speechify Text-to-Speech API</h1>
<p>Use this API to convert text to speech using Speechify.</p>
<h2>Endpoint</h2>
<code>POST /synthesize</code>
<h2>Request Format</h2>
<pre>
{
"text": "Your text to be converted to speech",
"voice_id": "PVL:4f4a27ef-2b17-424f-904c-30bd1ed60fb8" (optional)
}
</pre>
<h2>Example Usage with cURL</h2>
<pre>
curl -X POST http://localhost:7860/synthesize \\
-H "Content-Type: application/json" \\
-d '{"text": "Hello, this is a test", "voice_id": "PVL:4f4a27ef-2b17-424f-904c-30bd1ed60fb8"}'
</pre>
<h2>Response</h2>
<p>The API returns an MP3 audio file if successful, or a JSON error message if there's a problem.</p>
</body>
</html>
"""
if __name__ == '__main__':
app.run(debug=True, host='0.0.0.0', port=7860) |