Spaces:
Build error
Build error
File size: 7,512 Bytes
6ce1ccd bf6b15c 6ce1ccd | 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 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 | """
ENDPOINT /api/predict para recibir trabajos desde tu servidor PHP
"""
from flask import Flask, request, jsonify
import json
import time
import threading
import requests
import hashlib
import hmac
app = Flask(__name__)
# Configuraci贸n - CAMBIAR ESTE VALOR
WEBHOOK_SECRET = "AB7k9mJlVQ8xR5vL3wE1sT26Y4oI0pZ9c2V26Bn5M8k7" # EL MISMO que pusiste en webhook.php
JOBS = {} # Almacenar estado de trabajos en memoria
def create_webhook_signature(payload, secret):
"""Crear firma HMAC para webhook"""
return 'sha256=' + hmac.new(
secret.encode(),
payload.encode(),
hashlib.sha256
).hexdigest()
def send_webhook(webhook_url, data):
"""Enviar webhook a tu servidor"""
try:
payload = json.dumps(data)
signature = create_webhook_signature(payload, WEBHOOK_SECRET)
headers = {
'Content-Type': 'application/json',
'X-Signature': signature
}
response = requests.post(webhook_url, data=payload, headers=headers)
print(f"Webhook enviado: {response.status_code}")
return response.status_code == 200
except Exception as e:
print(f"Error enviando webhook: {e}")
return False
def process_audiobook_background(job_id, text, voice, language, webhook_url):
"""Procesar audiolibro en background"""
try:
# Actualizar estado: iniciado
JOBS[job_id]['status'] = 'processing'
JOBS[job_id]['stage'] = 'preprocessing'
JOBS[job_id]['progress'] = 0
# Notificar inicio
send_webhook(webhook_url, {
'event_type': 'job_started',
'job_id': job_id,
'estimated_time': len(text) // 10 # Estimaci贸n simple
})
# Simular progreso (reemplazar con tu l贸gica real)
stages = [
('preprocessing', 10),
('text_analysis', 25),
('voice_synthesis', 60),
('audio_processing', 85),
('finalizing', 95)
]
for stage, progress in stages:
JOBS[job_id]['stage'] = stage
JOBS[job_id]['progress'] = progress
# Enviar progreso
send_webhook(webhook_url, {
'event_type': 'job_progress',
'job_id': job_id,
'progress': progress,
'stage': stage
})
# Simular tiempo de procesamiento
time.sleep(10) # En producci贸n, aqu铆 va tu l贸gica real
# AQU脥 VA TU L脫GICA REAL DE PROCESAMIENTO
# audio_file = tu_funcion_de_tts(text, voice, language)
# Por ahora, simular archivo de audio
audio_url = f"https://tu-space.hf.space/audio/{job_id}.mp3"
# Completar trabajo
JOBS[job_id]['status'] = 'completed'
JOBS[job_id]['progress'] = 100
JOBS[job_id]['audio_url'] = audio_url
JOBS[job_id]['duration'] = len(text) // 5 # Estimaci贸n de duraci贸n
# Notificar completaci贸n
send_webhook(webhook_url, {
'event_type': 'job_completed',
'job_id': job_id,
'audio_url': audio_url,
'duration': JOBS[job_id]['duration']
})
except Exception as e:
# Error en procesamiento
JOBS[job_id]['status'] = 'failed'
JOBS[job_id]['error'] = str(e)
# Notificar error
send_webhook(webhook_url, {
'event_type': 'job_failed',
'job_id': job_id,
'error': str(e),
'error_code': 'PROCESSING_ERROR'
})
@app.route('/api/predict', methods=['POST'])
def predict():
"""Endpoint principal para recibir trabajos"""
try:
data = request.get_json()
# Validar datos requeridos
required_fields = ['job_id', 'text', 'voice', 'language', 'webhook_url']
for field in required_fields:
if field not in data:
return jsonify({'error': f'Campo requerido: {field}'}), 400
job_id = data['job_id']
text = data['text']
voice = data['voice']
language = data['language']
webhook_url = data['webhook_url']
# Validaciones
if len(text) < 10:
return jsonify({'error': 'Texto demasiado corto'}), 400
if len(text) > 500000: # 500KB
return jsonify({'error': 'Texto demasiado largo'}), 400
# Crear registro del trabajo
JOBS[job_id] = {
'job_id': job_id,
'status': 'pending',
'text_length': len(text),
'voice': voice,
'language': language,
'created_at': time.time(),
'progress': 0,
'stage': 'pending'
}
# Iniciar procesamiento en background
thread = threading.Thread(
target=process_audiobook_background,
args=(job_id, text, voice, language, webhook_url)
)
thread.daemon = True
thread.start()
return jsonify({
'success': True,
'job_id': job_id,
'status': 'started',
'estimated_time': len(text) // 10,
'message': 'Procesamiento iniciado'
})
except Exception as e:
return jsonify({'error': str(e)}), 500
@app.route('/api/status/<job_id>', methods=['GET'])
def get_status(job_id):
"""Obtener estado de un trabajo"""
if job_id not in JOBS:
return jsonify({'error': 'Trabajo no encontrado'}), 404
job = JOBS[job_id]
return jsonify({
'job_id': job_id,
'status': job['status'],
'progress': job.get('progress', 0),
'stage': job.get('stage', 'pending'),
'created_at': job['created_at'],
'audio_url': job.get('audio_url'),
'duration': job.get('duration'),
'error': job.get('error')
})
@app.route('/api/voices', methods=['GET'])
def get_voices():
"""Obtener lista de voces disponibles"""
voices = [
{'id': 'maria', 'name': 'Mar铆a', 'language': 'es', 'gender': 'female'},
{'id': 'carlos', 'name': 'Carlos', 'language': 'es', 'gender': 'male'},
{'id': 'laura', 'name': 'Laura', 'language': 'es', 'gender': 'female'},
{'id': 'john', 'name': 'John', 'language': 'en', 'gender': 'male'},
{'id': 'sarah', 'name': 'Sarah', 'language': 'en', 'gender': 'female'},
{'id': 'james', 'name': 'James', 'language': 'en', 'gender': 'male'},
{'id': 'marie', 'name': 'Marie', 'language': 'fr', 'gender': 'female'},
{'id': 'pierre', 'name': 'Pierre', 'language': 'fr', 'gender': 'male'},
{'id': 'hans', 'name': 'Hans', 'language': 'de', 'gender': 'male'},
{'id': 'greta', 'name': 'Greta', 'language': 'de', 'gender': 'female'},
{'id': 'marco', 'name': 'Marco', 'language': 'it', 'gender': 'male'},
{'id': 'sofia', 'name': 'Sofia', 'language': 'it', 'gender': 'female'},
]
return jsonify({
'success': True,
'voices': voices
})
@app.route('/health', methods=['GET'])
def health_check():
"""Health check endpoint"""
return jsonify({
'status': 'healthy',
'active_jobs': len([j for j in JOBS.values() if j['status'] in ['pending', 'processing']]),
'total_jobs': len(JOBS)
})
if __name__ == '__main__':
app.run(host='0.0.0.0', port=7860) |