Implement queued jobs workflow and uploaded source file browser
This commit is contained in:
+110
-4
@@ -166,9 +166,28 @@ class PreviewRequest(BaseModel):
|
||||
|
||||
|
||||
# Endpoints
|
||||
UPLOAD_METADATA_FILE = os.path.join(upscaler.UPLOAD_DIR, "metadata.json")
|
||||
|
||||
def load_upload_metadata():
|
||||
if os.path.exists(UPLOAD_METADATA_FILE):
|
||||
try:
|
||||
with open(UPLOAD_METADATA_FILE, "r") as f:
|
||||
return json.load(f)
|
||||
except Exception:
|
||||
pass
|
||||
return {}
|
||||
|
||||
def save_upload_metadata(metadata):
|
||||
try:
|
||||
with open(UPLOAD_METADATA_FILE, "w") as f:
|
||||
json.dump(metadata, f, indent=4)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
@app.post("/api/upload")
|
||||
async def upload_video(file: UploadFile = File(...)):
|
||||
"""Upload video to workspace directory and parse metadata"""
|
||||
import time
|
||||
file_id = str(uuid.uuid4())
|
||||
ext = os.path.splitext(file.filename)[1].lower()
|
||||
if ext not in [".mp4", ".mkv", ".avi", ".mov", ".webm"]:
|
||||
@@ -186,6 +205,18 @@ async def upload_video(file: UploadFile = File(...)):
|
||||
os.remove(save_path)
|
||||
raise HTTPException(status_code=400, detail="Could not read video file metadata. File may be corrupted.")
|
||||
|
||||
# Save upload metadata
|
||||
metadata = load_upload_metadata()
|
||||
metadata[file_id] = {
|
||||
"file_id": file_id,
|
||||
"original_filename": file.filename,
|
||||
"ext": ext,
|
||||
"size_bytes": os.path.getsize(save_path),
|
||||
"upload_time": time.time(),
|
||||
"metadata": info
|
||||
}
|
||||
save_upload_metadata(metadata)
|
||||
|
||||
return {
|
||||
"file_id": file_id,
|
||||
"filename": file.filename,
|
||||
@@ -193,6 +224,82 @@ async def upload_video(file: UploadFile = File(...)):
|
||||
"metadata": info
|
||||
}
|
||||
|
||||
@app.get("/api/uploads")
|
||||
def list_uploads():
|
||||
"""List all uploaded video source files"""
|
||||
metadata = load_upload_metadata()
|
||||
valid_uploads = []
|
||||
metadata_updated = False
|
||||
|
||||
if os.path.exists(upscaler.UPLOAD_DIR):
|
||||
all_files = os.listdir(upscaler.UPLOAD_DIR)
|
||||
|
||||
for filename in all_files:
|
||||
if filename == "metadata.json":
|
||||
continue
|
||||
|
||||
file_path = os.path.join(upscaler.UPLOAD_DIR, filename)
|
||||
file_id, ext = os.path.splitext(filename)
|
||||
|
||||
if file_id in metadata:
|
||||
valid_uploads.append(metadata[file_id])
|
||||
else:
|
||||
info = upscaler.get_video_info(file_path)
|
||||
if info:
|
||||
entry = {
|
||||
"file_id": file_id,
|
||||
"original_filename": filename,
|
||||
"ext": ext,
|
||||
"size_bytes": os.path.getsize(file_path),
|
||||
"upload_time": os.path.getmtime(file_path),
|
||||
"metadata": info
|
||||
}
|
||||
metadata[file_id] = entry
|
||||
valid_uploads.append(entry)
|
||||
metadata_updated = True
|
||||
|
||||
# Clean up missing files from metadata
|
||||
for fid in list(metadata.keys()):
|
||||
ext = metadata[fid].get("ext", ".mp4")
|
||||
expected_file = os.path.join(upscaler.UPLOAD_DIR, f"{fid}{ext}")
|
||||
if not os.path.exists(expected_file):
|
||||
del metadata[fid]
|
||||
metadata_updated = True
|
||||
|
||||
if metadata_updated:
|
||||
save_upload_metadata(metadata)
|
||||
|
||||
# Sort by upload time desc
|
||||
valid_uploads.sort(key=lambda x: x.get("upload_time", 0), reverse=True)
|
||||
return valid_uploads
|
||||
|
||||
@app.delete("/api/uploads/{file_id}")
|
||||
@app.post("/api/uploads/delete/{file_id}")
|
||||
def delete_upload(file_id: str):
|
||||
"""Delete an uploaded source file"""
|
||||
metadata = load_upload_metadata()
|
||||
if file_id not in metadata:
|
||||
exts = [".mp4", ".mkv", ".avi", ".mov", ".webm"]
|
||||
file_path = None
|
||||
for ext in exts:
|
||||
p = os.path.join(upscaler.UPLOAD_DIR, f"{file_id}{ext}")
|
||||
if os.path.exists(p):
|
||||
file_path = p
|
||||
break
|
||||
if not file_path:
|
||||
raise HTTPException(status_code=404, detail="Upload file not found.")
|
||||
os.remove(file_path)
|
||||
return {"file_id": file_id, "status": "deleted"}
|
||||
|
||||
ext = metadata[file_id].get("ext", ".mp4")
|
||||
file_path = os.path.join(upscaler.UPLOAD_DIR, f"{file_id}{ext}")
|
||||
if os.path.exists(file_path):
|
||||
os.remove(file_path)
|
||||
|
||||
del metadata[file_id]
|
||||
save_upload_metadata(metadata)
|
||||
return {"file_id": file_id, "status": "deleted"}
|
||||
|
||||
@app.post("/api/upscale/start")
|
||||
def start_upscale(req: StartUpscaleRequest):
|
||||
"""Queue upscaling task"""
|
||||
@@ -405,10 +512,6 @@ def delete_job(job_id: str):
|
||||
if not job:
|
||||
raise HTTPException(status_code=404, detail="Job not found.")
|
||||
|
||||
# Safely delete uploaded input file
|
||||
if job.video_path:
|
||||
safe_delete_file(job.video_path)
|
||||
|
||||
# Safely delete original preview video if present
|
||||
for ext in [".mp4", ".mkv", ".avi", ".mov", ".webm"]:
|
||||
orig_prev_path = os.path.join(upscaler.OUTPUT_DIR, f"original_{job_id}{ext}")
|
||||
@@ -459,6 +562,9 @@ def purge_all_jobs():
|
||||
# Reset in-memory database
|
||||
jobs_db.clear()
|
||||
|
||||
# Reset upload metadata file
|
||||
save_upload_metadata({})
|
||||
|
||||
return {"status": "all purged"}
|
||||
|
||||
# Websocket endpoint for real-time progress updates
|
||||
|
||||
Reference in New Issue
Block a user