Spaces:
Sleeping
Sleeping
app
Browse files
app.py
ADDED
@@ -0,0 +1,206 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import traceback
|
2 |
+
import uuid
|
3 |
+
from models.whisper import model
|
4 |
+
import modules.register as register
|
5 |
+
from processor import generate_audio
|
6 |
+
import json
|
7 |
+
from fastapi import FastAPI, HTTPException
|
8 |
+
from pydantic import BaseModel, HttpUrl
|
9 |
+
from fastapi.middleware.cors import CORSMiddleware
|
10 |
+
from fastapi.openapi.docs import get_swagger_ui_html
|
11 |
+
import os
|
12 |
+
import requests
|
13 |
+
from modules.audio import convert, get_audio_duration
|
14 |
+
from modules.r2 import upload_to_s3
|
15 |
+
import threading
|
16 |
+
import queue
|
17 |
+
|
18 |
+
vpv_webhook = os.environ.get("VPV_WEBHOOK")
|
19 |
+
|
20 |
+
app = FastAPI(title="Minha API", description="API de exemplo com FastAPI e Swagger", version="1.0.0")
|
21 |
+
app.add_middleware(
|
22 |
+
CORSMiddleware,
|
23 |
+
allow_origins=["*"],
|
24 |
+
allow_credentials=True,
|
25 |
+
allow_methods=["*"],
|
26 |
+
allow_headers=["*"],
|
27 |
+
)
|
28 |
+
|
29 |
+
def download_file(url: str) -> str:
|
30 |
+
"""
|
31 |
+
Baixa um arquivo da URL fornecida e o salva no diretório 'downloads/'.
|
32 |
+
O nome do arquivo é extraído da URL automaticamente.
|
33 |
+
"""
|
34 |
+
try:
|
35 |
+
os.makedirs("downloads", exist_ok=True)
|
36 |
+
|
37 |
+
file_name = os.path.basename(url.split("?")[0])
|
38 |
+
save_path = os.path.join("downloads", file_name)
|
39 |
+
|
40 |
+
response = requests.get(url)
|
41 |
+
response.raise_for_status()
|
42 |
+
|
43 |
+
with open(save_path, 'wb') as f:
|
44 |
+
f.write(response.content)
|
45 |
+
|
46 |
+
return save_path
|
47 |
+
except requests.exceptions.RequestException as e:
|
48 |
+
raise Exception(f"Erro ao baixar o arquivo: {e}")
|
49 |
+
|
50 |
+
@app.get("/test", include_in_schema=False)
|
51 |
+
def test():
|
52 |
+
return {"ok": True}
|
53 |
+
|
54 |
+
@app.get("/", include_in_schema=False)
|
55 |
+
async def custom_swagger_ui_html():
|
56 |
+
return get_swagger_ui_html(openapi_url="/openapi.json", title="Alert Pix Ai v2")
|
57 |
+
|
58 |
+
@app.get("/openapi.json", include_in_schema=False)
|
59 |
+
async def openapi():
|
60 |
+
with open("swagger.json") as f:
|
61 |
+
return json.load(f)
|
62 |
+
|
63 |
+
|
64 |
+
class ProcessRequest(BaseModel):
|
65 |
+
key: str
|
66 |
+
text: str
|
67 |
+
id: str
|
68 |
+
receiver: str
|
69 |
+
webhook: str
|
70 |
+
censor: bool = False
|
71 |
+
offset: float = -0.3
|
72 |
+
format: str = "wav"
|
73 |
+
speed: float = 0.8
|
74 |
+
crossfade: float = 0.1
|
75 |
+
|
76 |
+
q = queue.Queue()
|
77 |
+
|
78 |
+
def process_queue(q):
|
79 |
+
while True:
|
80 |
+
try:
|
81 |
+
key, censor, offset, text, format, speed, crossfade, id, receiver, webhook = q.get(timeout=5)
|
82 |
+
audio = generate_audio(key, text, censor, offset, speed=speed, crossfade=crossfade)
|
83 |
+
convertedAudioPath = convert(audio, format)
|
84 |
+
duration = get_audio_duration(convertedAudioPath)
|
85 |
+
audioUrl = upload_to_s3(convertedAudioPath, f"{id}", format)
|
86 |
+
os.remove(audio)
|
87 |
+
os.remove(convertedAudioPath)
|
88 |
+
|
89 |
+
payload = {
|
90 |
+
"id": id,
|
91 |
+
"duration": duration,
|
92 |
+
"receiver": receiver,
|
93 |
+
"url": audioUrl
|
94 |
+
}
|
95 |
+
|
96 |
+
requests.post(webhook, json=payload)
|
97 |
+
except Exception as e:
|
98 |
+
print(e)
|
99 |
+
finally:
|
100 |
+
q.task_done()
|
101 |
+
|
102 |
+
|
103 |
+
worker_thread = threading.Thread(target=process_queue, args=(q,))
|
104 |
+
worker_thread.start()
|
105 |
+
|
106 |
+
@app.post("/process")
|
107 |
+
def process_audio(payload: ProcessRequest):
|
108 |
+
key = payload.key
|
109 |
+
censor = payload.censor
|
110 |
+
offset = payload.offset
|
111 |
+
text = payload.text
|
112 |
+
format = payload.format
|
113 |
+
speed = payload.speed
|
114 |
+
crossfade = payload.crossfade
|
115 |
+
id = payload.id
|
116 |
+
receiver = payload.receiver
|
117 |
+
webhook = payload.webhook
|
118 |
+
|
119 |
+
if len(text) >= 1000:
|
120 |
+
raise HTTPException(status_code=500, detail=str(e))
|
121 |
+
|
122 |
+
try:
|
123 |
+
q.put((key, censor, offset, text, format, speed, crossfade, id, receiver, webhook))
|
124 |
+
return {"success": True, "err": ""}
|
125 |
+
|
126 |
+
except ValueError as e:
|
127 |
+
raise HTTPException(status_code=400, detail=str(e))
|
128 |
+
|
129 |
+
except Exception as e:
|
130 |
+
error_trace = traceback.format_exc()
|
131 |
+
dc_callback = "https://discord.com/api/webhooks/1285586984898662511/QNVvY2rtoKICamlXsC1BreBaYjS9341jz9ANCDBzayXt4C7v-vTFzKfUtKQkwW7BwpfP"
|
132 |
+
|
133 |
+
data = {
|
134 |
+
"content": "",
|
135 |
+
"tts": False,
|
136 |
+
"embeds": [
|
137 |
+
{
|
138 |
+
"type": "rich",
|
139 |
+
"title": f"Erro aconteceu na IA - MIMIC - processo",
|
140 |
+
"description": f"Erro: {str(e)}\n\nDetalhes do erro:\n```{error_trace}```"
|
141 |
+
}
|
142 |
+
]
|
143 |
+
}
|
144 |
+
|
145 |
+
headers = {
|
146 |
+
"Content-Type": "application/json",
|
147 |
+
"Accept": "application/json",
|
148 |
+
}
|
149 |
+
requests.post(dc_callback, headers=headers, data=json.dumps(data))
|
150 |
+
raise HTTPException(status_code=500, detail=str(e))
|
151 |
+
|
152 |
+
class TrainRequest(BaseModel):
|
153 |
+
audio: HttpUrl
|
154 |
+
key: str
|
155 |
+
endpoint: str
|
156 |
+
id: str
|
157 |
+
|
158 |
+
@app.post("/train")
|
159 |
+
def create_item(payload: TrainRequest):
|
160 |
+
audio = payload.audio
|
161 |
+
key = payload.key
|
162 |
+
endpoint = payload.endpoint
|
163 |
+
|
164 |
+
try:
|
165 |
+
src = download_file(str(audio))
|
166 |
+
data = register.process_audio(src, key)
|
167 |
+
|
168 |
+
for i in range(3):
|
169 |
+
try:
|
170 |
+
payload = {"success": True, "id": payload.id}
|
171 |
+
requests.post(endpoint, json=payload)
|
172 |
+
break
|
173 |
+
except Exception as e:
|
174 |
+
pass
|
175 |
+
|
176 |
+
return data
|
177 |
+
|
178 |
+
except ValueError as e:
|
179 |
+
raise HTTPException(status_code=400, detail=str(e))
|
180 |
+
except Exception as e:
|
181 |
+
error_trace = traceback.format_exc()
|
182 |
+
dc_callback = "https://discord.com/api/webhooks/1285586984898662511/QNVvY2rtoKICamlXsC1BreBaYjS9341jz9ANCDBzayXt4C7v-vTFzKfUtKQkwW7BwpfP"
|
183 |
+
|
184 |
+
data = {
|
185 |
+
"content": "",
|
186 |
+
"tts": False,
|
187 |
+
"embeds": [
|
188 |
+
{
|
189 |
+
"type": "rich",
|
190 |
+
"title": f"Erro aconteceu na IA -MIMIC - treinar",
|
191 |
+
"description": f"Erro: {str(e)}\n\nDetalhes do erro:\n```{error_trace}```"
|
192 |
+
}
|
193 |
+
]
|
194 |
+
}
|
195 |
+
|
196 |
+
headers = {
|
197 |
+
"Content-Type": "application/json",
|
198 |
+
"Accept": "application/json",
|
199 |
+
}
|
200 |
+
requests.post(dc_callback, headers=headers, data=json.dumps(data))
|
201 |
+
|
202 |
+
raise HTTPException(status_code=500, detail=str(e))
|
203 |
+
|
204 |
+
if __name__ == "__main__":
|
205 |
+
import uvicorn
|
206 |
+
uvicorn.run("app:app", host="0.0.0.0", port=7860)
|