diff --git a/frigate/api/classification.py b/frigate/api/classification.py index 63f037ec24..0dc3a9d575 100644 --- a/frigate/api/classification.py +++ b/frigate/api/classification.py @@ -125,3 +125,20 @@ def deregister_faces(request: Request, name: str, body: dict = None): content=({"success": True, "message": "Successfully deleted faces."}), status_code=200, ) + + +@router.post("/faces/{name}/create") +def create_face(name: str): + """Create a new face directory without requiring an image.""" + folder = os.path.join(FACE_DIR, name) + if os.path.exists(folder): + return JSONResponse( + status_code=400, + content={"message": f"Face '{name}' already exists", "success": False}, + ) + + os.makedirs(folder, exist_ok=True) + return JSONResponse( + status_code=200, + content={"message": "Successfully created face", "success": True}, + ) diff --git a/web/src/pages/FaceLibrary.tsx b/web/src/pages/FaceLibrary.tsx index 53280d78f3..55698bea77 100644 --- a/web/src/pages/FaceLibrary.tsx +++ b/web/src/pages/FaceLibrary.tsx @@ -133,25 +133,8 @@ export default function FaceLibrary() { setIsCreatingFace(true); try { - const canvas = document.createElement('canvas'); - canvas.width = 1; - canvas.height = 1; - const ctx = canvas.getContext('2d'); - if (ctx) { - ctx.fillStyle = 'white'; - ctx.fillRect(0, 0, 1, 1); - } - - const base64Image = canvas.toDataURL('image/webp').split(',')[1]; - - const formData = new FormData(); - formData.append('cropped', 'true'); - formData.append('image', base64Image); - - const resp = await axios.post(`/faces/${newFaceName}`, { - cropped: true, - image: base64Image - }); + // Create a directory by making a POST request without a file + const resp = await axios.post(`/faces/${newFaceName}/create`); if (resp.status === 200) { setNewFaceDialog(false); @@ -182,26 +165,8 @@ export default function FaceLibrary() { setIsRenaming(true); try { - // Create a 1x1 transparent WebP image - const canvas = document.createElement('canvas'); - canvas.width = 1; - canvas.height = 1; - const ctx = canvas.getContext('2d'); - if (ctx) { - ctx.fillStyle = 'white'; - ctx.fillRect(0, 0, 1, 1); - } - - // Convert to base64 - const base64Image = canvas.toDataURL('image/webp').split(',')[1]; - - // Create new face directory - await axios.post(`/faces/${renameData.newName}`, { - cropped: true, - image: base64Image - }); + await axios.post(`/faces/${renameData.newName}/create`); - // Copy existing images const oldFaceImages = faceData[renameData.oldName] || []; for (const image of oldFaceImages) { const response = await fetch(`${baseUrl}clips/faces/${renameData.oldName}/${image}`);