VeuReu commited on
Commit
322dc74
·
verified ·
1 Parent(s): 90ad2b1

Update api.py

Browse files
Files changed (1) hide show
  1. api.py +3 -229
api.py CHANGED
@@ -25,6 +25,7 @@ from character_detection import detect_characters_from_video
25
  from pipelines.audiodescription import generate as ad_generate
26
 
27
  from storage.files.file_manager import FileManager
 
28
 
29
  app = FastAPI(title="Veureu Engine API", version="0.2.0")
30
  app.add_middleware(
@@ -43,9 +44,7 @@ VIDEOS_ROOT = Path("/tmp/data/videos")
43
  VIDEOS_ROOT.mkdir(parents=True, exist_ok=True)
44
  IDENTITIES_ROOT = Path("/tmp/characters")
45
  IDENTITIES_ROOT.mkdir(parents=True, exist_ok=True)
46
- MEDIA_ROOT = Path("/data/media")
47
- file_manager = FileManager(MEDIA_ROOT)
48
- HF_TOKEN = os.getenv("HF_TOKEN")
49
 
50
  # Sistema de jobs asíncronos
51
  class JobStatus(str, Enum):
@@ -56,232 +55,7 @@ class JobStatus(str, Enum):
56
 
57
  jobs: Dict[str, dict] = {}
58
 
59
-
60
- def validate_token(token: str):
61
- """
62
- Validate the provided token against the HF_TOKEN environment variable.
63
- Raises an HTTPException if validation fails.
64
- """
65
- if HF_TOKEN is None:
66
- raise RuntimeError("HF_TOKEN environment variable is not set on the server.")
67
-
68
- if token != HF_TOKEN:
69
- raise HTTPException(status_code=401, detail="Invalid token")
70
-
71
-
72
- @app.post("/upload_cast_csv/{sha1}", tags=["Media Manager"])
73
- async def upload_cast_csv(
74
- sha1: str,
75
- cast_file: UploadFile = File(...),
76
- token: str = Query(..., description="Token required for authorization")
77
- ):
78
- """
79
- Upload a cast CSV file for a specific video identified by its SHA-1.
80
-
81
- The CSV will be stored under:
82
- /data/media/<sha1>/cast/cast.csv
83
-
84
- Steps:
85
- - Validate the token.
86
- - Ensure /data/media/<sha1> exists.
87
- - Create /cast folder if missing.
88
- - Save the CSV file inside /cast.
89
- """
90
- validate_token(token)
91
-
92
- base_folder = MEDIA_ROOT / sha1
93
- if not base_folder.exists() or not base_folder.is_dir():
94
- raise HTTPException(status_code=404, detail="SHA1 folder not found")
95
-
96
- cast_folder = base_folder / "cast"
97
- cast_folder.mkdir(parents=True, exist_ok=True)
98
-
99
- final_path = cast_folder / "cast.csv"
100
-
101
- file_bytes = await cast_file.read()
102
- save_result = file_manager.upload_file(io.BytesIO(file_bytes), final_path)
103
- if not save_result["operation_success"]:
104
- raise HTTPException(status_code=500, detail=save_result["error"])
105
-
106
- return JSONResponse(
107
- status_code=200,
108
- content={"status": "ok", "saved_to": str(final_path)}
109
- )
110
-
111
-
112
- @app.get("/download_cast_csv/{sha1}", tags=["Media Manager"])
113
- def download_cast_csv(
114
- sha1: str,
115
- token: str = Query(..., description="Token required for authorization")
116
- ):
117
- """
118
- Download the cast CSV for a specific video identified by its SHA-1.
119
-
120
- The CSV is expected under:
121
- /data/media/<sha1>/cast/cast.csv
122
-
123
- Steps:
124
- - Validate the token.
125
- - Ensure /data/media/<sha1> and /cast exist.
126
- - Return the CSV as a FileResponse.
127
- - Raise 404 if any folder or file is missing.
128
- """
129
- validate_token(token)
130
-
131
- base_folder = MEDIA_ROOT / sha1
132
- cast_folder = base_folder / "cast"
133
- csv_path = cast_folder / "cast.csv"
134
-
135
- if not base_folder.exists() or not base_folder.is_dir():
136
- raise HTTPException(status_code=404, detail="SHA1 folder not found")
137
- if not cast_folder.exists() or not cast_folder.is_dir():
138
- raise HTTPException(status_code=404, detail="Cast folder not found")
139
- if not csv_path.exists() or not csv_path.is_file():
140
- raise HTTPException(status_code=404, detail="Cast CSV not found")
141
-
142
- # Convert to relative path for FileManager
143
- relative_path = csv_path.relative_to(MEDIA_ROOT)
144
- handler = file_manager.get_file(relative_path)
145
- if handler is None:
146
- raise HTTPException(status_code=404, detail="Cast CSV not accessible")
147
- handler.close()
148
-
149
- return FileResponse(
150
- path=csv_path,
151
- media_type="text/csv",
152
- filename="cast.csv"
153
- )
154
-
155
- @app.post("/upload_original_video", tags=["Media Manager"])
156
- async def upload_video(
157
- video: UploadFile = File(...),
158
- token: str = Query(..., description="Token required for authorization")
159
- ):
160
- """
161
- Saves an uploaded video by hashing it with SHA1 and placing it under:
162
- /data/media/<sha1>/clip/<original_filename>
163
-
164
- Steps:
165
- - Compute SHA1 of the uploaded video.
166
- - Ensure /data/media exists.
167
- - Create folder /data/media/<sha1> if missing.
168
- - Create folder /data/media/<sha1>/clip if missing.
169
- - Save the video inside /data/media/<sha1>/clip/.
170
- """
171
- validate_token(token)
172
-
173
- # Read content into memory (needed to compute hash twice)
174
- file_bytes = await video.read()
175
-
176
- # Create an in-memory file handler
177
- import io
178
- file_handler = io.BytesIO(file_bytes)
179
-
180
- # Compute SHA1 using your FileManager method
181
- try:
182
- sha1 = file_manager.compute_sha1(file_handler)
183
- except Exception as exc:
184
- raise HTTPException(status_code=500, detail=f"SHA1 computation failed: {exc}")
185
-
186
- # Ensure /data/media exists
187
- MEDIA_ROOT.mkdir(parents=True, exist_ok=True)
188
-
189
- # Path: /data/media/<sha1>
190
- video_root = MEDIA_ROOT / sha1
191
- video_root.mkdir(parents=True, exist_ok=True)
192
-
193
- # Path: /data/media/<sha1>/clip
194
- clip_dir = video_root / "clip"
195
- clip_dir.mkdir(parents=True, exist_ok=True)
196
-
197
- # Final file path
198
- final_path = clip_dir / video.filename
199
-
200
- # Save file using your FileManager.upload_file
201
- save_result = file_manager.upload_file(io.BytesIO(file_bytes), final_path)
202
-
203
- if not save_result["operation_success"]:
204
- raise HTTPException(status_code=500, detail=save_result["error"])
205
-
206
- return JSONResponse(
207
- status_code=200,
208
- content={
209
- "status": "ok",
210
- "sha1": sha1,
211
- "saved_to": str(final_path)
212
- }
213
- )
214
-
215
-
216
- @app.get("/download_original_video/{sha1}", tags=["Media Manager"])
217
- def download_video(
218
- sha1: str,
219
- token: str = Query(..., description="Token required for authorization")
220
- ):
221
- """
222
- Download a stored video by its SHA-1 directory name.
223
-
224
- This endpoint looks for a video stored under the path:
225
- /data/media/<sha1>/clip/
226
- and returns the first MP4 file found in that folder.
227
-
228
- The method performs the following steps:
229
- - Checks if the SHA-1 folder exists inside the media root.
230
- - Validates that the "clip" subfolder exists.
231
- - Searches for the first .mp4 file inside the clip folder.
232
- - Uses the FileManager.get_file method to ensure the file is accessible.
233
- - Returns the video directly as a FileResponse.
234
-
235
- Parameters
236
- ----------
237
- sha1 : str
238
- The SHA-1 hash corresponding to the directory where the video is stored.
239
-
240
- Returns
241
- -------
242
- FileResponse
243
- A streaming response containing the MP4 video.
244
-
245
- Raises
246
- ------
247
- HTTPException
248
- - 404 if the SHA-1 folder does not exist.
249
- - 404 if the clip folder is missing.
250
- - 404 if no MP4 files are found.
251
- - 404 if the file cannot be retrieved using FileManager.
252
- """
253
- validate_token(token)
254
-
255
- sha1_folder = MEDIA_ROOT / sha1
256
- clip_folder = sha1_folder / "clip"
257
-
258
- if not sha1_folder.exists() or not sha1_folder.is_dir():
259
- raise HTTPException(status_code=404, detail="SHA1 folder not found")
260
-
261
- if not clip_folder.exists() or not clip_folder.is_dir():
262
- raise HTTPException(status_code=404, detail="Clip folder not found")
263
-
264
- # Find first MP4 file
265
- mp4_files = list(clip_folder.glob("*.mp4"))
266
- if not mp4_files:
267
- raise HTTPException(status_code=404, detail="No MP4 files found")
268
-
269
- video_path = mp4_files[0]
270
-
271
- # Convert to relative path for FileManager
272
- relative_path = video_path.relative_to(MEDIA_ROOT)
273
-
274
- handler = file_manager.get_file(relative_path)
275
- if handler is None:
276
- raise HTTPException(status_code=404, detail="Video not accessible")
277
-
278
- handler.close()
279
-
280
- return FileResponse(
281
- path=video_path,
282
- media_type="video/mp4",
283
- filename=video_path.name
284
- )
285
 
286
 
287
  def describe_image_with_svision(image_path: str, is_face: bool = True) -> tuple[str, str]:
 
25
  from pipelines.audiodescription import generate as ad_generate
26
 
27
  from storage.files.file_manager import FileManager
28
+ from storage import media_manager
29
 
30
  app = FastAPI(title="Veureu Engine API", version="0.2.0")
31
  app.add_middleware(
 
44
  VIDEOS_ROOT.mkdir(parents=True, exist_ok=True)
45
  IDENTITIES_ROOT = Path("/tmp/characters")
46
  IDENTITIES_ROOT.mkdir(parents=True, exist_ok=True)
47
+
 
 
48
 
49
  # Sistema de jobs asíncronos
50
  class JobStatus(str, Enum):
 
55
 
56
  jobs: Dict[str, dict] = {}
57
 
58
+ app.include_router(media_manager.router)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
59
 
60
 
61
  def describe_image_with_svision(image_path: str, is_face: bool = True) -> tuple[str, str]: