VeuReu commited on
Commit
f7254d9
·
verified ·
1 Parent(s): 09352a8

Delete api.py

Browse files
Files changed (1) hide show
  1. api.py +0 -167
api.py DELETED
@@ -1,167 +0,0 @@
1
- # api.py — versión corregida (orden de definición)
2
-
3
- import os
4
- import uuid
5
- from fastapi import FastAPI, UploadFile, File, Form, Depends, Header, HTTPException, APIRouter
6
- from fastapi.middleware.cors import CORSMiddleware
7
- from fastapi.responses import JSONResponse
8
- from typing import Optional
9
- from models_job import JobCreate, JobStatus, JobResult
10
- from queue_manager import job_store, job_queue, start_worker, UPLOAD_DIR
11
- from worker import process_job
12
- from pydantic import BaseModel
13
- import subprocess
14
- import tempfile
15
- import base64
16
- import requests
17
-
18
- API_SHARED_TOKEN = os.environ.get("API_SHARED_TOKEN")
19
- UI_SPACE_URL = os.environ.get("UI_SPACE_URL") # ej: https://org-tu--ui--space.hf.space
20
-
21
- # ---------- Matxa - Alvocat (router) ----------
22
- router = APIRouter()
23
-
24
- HF_TOKEN = os.getenv("HF_TOKEN", "")
25
- MATXA_TTS_URL = os.getenv("MATXA_TTS_URL", "").strip()
26
- INFERENCE_URL = "https://api-inference.huggingface.co/models/projecte-aina/matxa-alvocat"
27
-
28
- class TTSRequest(BaseModel):
29
- text: str
30
-
31
- @router.post("/tts/matxa")
32
- def tts_matxa(req: TTSRequest):
33
- text = (req.text or "").strip()
34
- if not text:
35
- raise HTTPException(status_code=400, detail="Empty text")
36
-
37
- try:
38
- if MATXA_TTS_URL:
39
- headers = {}
40
- if HF_TOKEN:
41
- headers["Authorization"] = f"Bearer {HF_TOKEN}"
42
- resp = requests.post(
43
- MATXA_TTS_URL,
44
- headers=headers,
45
- json={"text": text},
46
- timeout=60,
47
- )
48
- if resp.status_code != 200:
49
- raise HTTPException(status_code=502, detail=f"Space TTS error: {resp.text}")
50
-
51
- if resp.headers.get("content-type", "").startswith("audio/"):
52
- audio_bytes = resp.content
53
- b64 = base64.b64encode(audio_bytes).decode("utf-8")
54
- return {"mp3_data_url": f"data:audio/mpeg;base64,{b64}"}
55
- else:
56
- data = resp.json()
57
- if "audio" in data and isinstance(data["audio"], str) and data["audio"].startswith("data:audio"):
58
- return {"mp3_data_url": data["audio"]}
59
- elif "audio_b64" in data:
60
- audio_bytes = base64.b64decode(data["audio_b64"])
61
- b64 = base64.b64encode(audio_bytes).decode("utf-8")
62
- return {"mp3_data_url": f"data:audio/mpeg;base64,{b64}"}
63
- else:
64
- audio_bytes = data.get("bytes")
65
- if isinstance(audio_bytes, str):
66
- audio_bytes = base64.b64decode(audio_bytes)
67
- b64 = base64.b64encode(audio_bytes).decode("utf-8")
68
- return {"mp3_data_url": f"data:audio/mpeg;base64,{b64}"}
69
-
70
- else:
71
- if not HF_TOKEN:
72
- raise HTTPException(status_code=500, detail="HF_TOKEN not set")
73
- headers = {
74
- "Authorization": f"Bearer {HF_TOKEN}",
75
- "Accept": "audio/mpeg",
76
- }
77
- resp = requests.post(
78
- INFERENCE_URL,
79
- headers=headers,
80
- json={"inputs": text},
81
- timeout=60,
82
- )
83
- if resp.status_code != 200:
84
- raise HTTPException(status_code=502, detail=f"Inference API error: {resp.text}")
85
-
86
- audio_bytes = resp.content
87
- b64 = base64.b64encode(audio_bytes).decode("utf-8")
88
- return {"mp3_data_url": f"data:audio/mpeg;base64,{b64}"}
89
-
90
- except HTTPException:
91
- raise
92
- except Exception as e:
93
- raise HTTPException(status_code=500, detail=str(e))
94
-
95
- # ---------- FastAPI app principal ----------
96
- app = FastAPI(title="Veureu AD – API Space")
97
-
98
- # CORS (restringe a tu UI Space si pasas UI_SPACE_URL)
99
- app.add_middleware(
100
- CORSMiddleware,
101
- allow_origins=[UI_SPACE_URL] if UI_SPACE_URL else ["*"],
102
- allow_credentials=False,
103
- allow_methods=["*"],
104
- allow_headers=["*"],
105
- )
106
-
107
- # Lanza el worker al arrancar
108
- start_worker(process_job)
109
-
110
- # -------- Auth sencilla por token compartido --------
111
- def check_auth(authorization: Optional[str] = Header(None)):
112
- if not API_SHARED_TOKEN:
113
- return True
114
- if not authorization or not authorization.startswith("Bearer "):
115
- raise HTTPException(401, "Missing token")
116
- if authorization.split(" ", 1)[1] != API_SHARED_TOKEN:
117
- raise HTTPException(403, "Invalid token")
118
- return True
119
-
120
- # -------- Rutas "jobs" --------
121
- @app.get("/")
122
- def read_root():
123
- return {"message": "Hello World"}
124
-
125
- @app.post("/jobs")
126
- async def create_job(
127
- mode: str = Form(default="both"),
128
- video_file: Optional[UploadFile] = File(default=None),
129
- video_url: Optional[str] = Form(default=None),
130
- _auth=Depends(check_auth),
131
- ):
132
- if not video_file and not video_url:
133
- raise HTTPException(400, "Debe enviarse un 'video_file' o un 'video_url'.")
134
- job_id = str(uuid.uuid4())
135
- local_path = None
136
- if video_file:
137
- os.makedirs(UPLOAD_DIR, exist_ok=True)
138
- save_path = os.path.join(UPLOAD_DIR, f"{job_id}_{video_file.filename}")
139
- with open(save_path, "wb") as f:
140
- f.write(await video_file.read())
141
- local_path = save_path
142
- st = JobStatus(job_id=job_id, status="queued", progress=0, message="En cola")
143
- job_store.set_status(job_id, st)
144
- job_queue.put({"job_id": job_id, "mode": mode, "local_path": local_path, "video_url": video_url})
145
- return {"job_id": job_id}
146
-
147
- @app.get("/jobs/{job_id}/status", response_model=JobStatus)
148
- def get_status(job_id: str, _auth=Depends(check_auth)):
149
- st = job_store.get_status(job_id)
150
- if not st:
151
- raise HTTPException(404, "Job no encontrado")
152
- return st
153
-
154
- @app.get("/jobs/{job_id}/result", response_model=JobResult)
155
- def get_result(job_id: str, _auth=Depends(check_auth)):
156
- res = job_store.get_result(job_id)
157
- if not res:
158
- st = job_store.get_status(job_id)
159
- if st and st.status != "completed":
160
- raise HTTPException(409, "El job no ha terminado")
161
- raise HTTPException(404, "Resultado no encontrado")
162
- return res
163
-
164
- # <<< AHORA SÍ >>>
165
- app.include_router(router)
166
-
167
-