Spaces:
Running
Running
Update app.py
Browse files
app.py
CHANGED
|
@@ -1,5 +1,5 @@
|
|
| 1 |
#!/usr/bin/env python3
|
| 2 |
-
"""FaceFusion API
|
| 3 |
|
| 4 |
import os
|
| 5 |
import tempfile
|
|
@@ -19,32 +19,20 @@ app = FastAPI(title="FaceFusion API")
|
|
| 19 |
FACEFUSION_DIR = "/facefusion"
|
| 20 |
FACEFUSION_SCRIPT = os.path.join(FACEFUSION_DIR, "facefusion.py")
|
| 21 |
|
| 22 |
-
|
| 23 |
-
logger.error(f"FaceFusion script not found at {FACEFUSION_SCRIPT}")
|
| 24 |
-
else:
|
| 25 |
-
logger.info(f"FaceFusion script found at {FACEFUSION_SCRIPT}")
|
| 26 |
-
|
| 27 |
-
# Конфигурация для CPU (правильное значение)
|
| 28 |
EXECUTION_PROVIDERS = ["cpu"]
|
| 29 |
|
| 30 |
-
#
|
| 31 |
-
|
| 32 |
-
|
| 33 |
-
#
|
| 34 |
FACE_MASK_TYPES = ["box", "occlusion", "region"]
|
| 35 |
FACE_MASK_BLUR = 0.7
|
| 36 |
-
|
| 37 |
-
# Качество выходного изображения (1-100)
|
| 38 |
OUTPUT_IMAGE_QUALITY = 95
|
| 39 |
|
| 40 |
-
# Кэширование моделей
|
| 41 |
-
os.environ["FACEFUSION_CACHE"] = "/tmp/facefusion_cache"
|
| 42 |
-
os.makedirs("/tmp/facefusion_cache", exist_ok=True)
|
| 43 |
-
logger.info(f"Cache directory: /tmp/facefusion_cache")
|
| 44 |
-
|
| 45 |
@app.get("/health")
|
| 46 |
async def health():
|
| 47 |
-
return {"status": "ok"
|
| 48 |
|
| 49 |
@app.post("/swap")
|
| 50 |
async def swap_face(source: UploadFile = File(...), target: UploadFile = File(...)):
|
|
@@ -54,20 +42,21 @@ async def swap_face(source: UploadFile = File(...), target: UploadFile = File(..
|
|
| 54 |
output_path = os.path.join(temp_dir, f"output_{uuid.uuid4().hex}.jpg")
|
| 55 |
|
| 56 |
try:
|
| 57 |
-
logger.info(f"Received source: {source.filename}, target: {target.filename}")
|
| 58 |
with open(source_path, "wb") as f:
|
| 59 |
f.write(await source.read())
|
| 60 |
with open(target_path, "wb") as f:
|
| 61 |
f.write(await target.read())
|
| 62 |
|
| 63 |
-
#
|
| 64 |
cmd = [
|
| 65 |
"python", FACEFUSION_SCRIPT,
|
| 66 |
"headless-run",
|
| 67 |
"--source", source_path,
|
| 68 |
"--target", target_path,
|
| 69 |
"--output-path", output_path,
|
| 70 |
-
"--
|
|
|
|
|
|
|
| 71 |
"--face-mask-types", *FACE_MASK_TYPES,
|
| 72 |
"--face-mask-blur", str(FACE_MASK_BLUR),
|
| 73 |
"--output-image-quality", str(OUTPUT_IMAGE_QUALITY),
|
|
@@ -84,33 +73,17 @@ async def swap_face(source: UploadFile = File(...), target: UploadFile = File(..
|
|
| 84 |
text=True
|
| 85 |
)
|
| 86 |
|
| 87 |
-
|
| 88 |
-
stdout, stderr = process.communicate(timeout=180)
|
| 89 |
-
except subprocess.TimeoutExpired:
|
| 90 |
-
process.kill()
|
| 91 |
-
stdout, stderr = process.communicate()
|
| 92 |
-
logger.error("Process timed out")
|
| 93 |
-
raise HTTPException(status_code=504, detail="Processing timeout")
|
| 94 |
-
|
| 95 |
elapsed = time.time() - start_time
|
| 96 |
logger.info(f"Processing took {elapsed:.2f} seconds")
|
| 97 |
-
if stdout:
|
| 98 |
-
logger.info(f"STDOUT: {stdout}")
|
| 99 |
-
if stderr:
|
| 100 |
-
logger.error(f"STDERR: {stderr}")
|
| 101 |
|
| 102 |
if process.returncode != 0:
|
| 103 |
-
logger.error(f"FaceFusion
|
| 104 |
raise HTTPException(status_code=500, detail=f"FaceFusion error: {stderr}")
|
| 105 |
|
| 106 |
-
if not os.path.exists(output_path):
|
| 107 |
-
logger.error("Output file not created")
|
| 108 |
-
raise HTTPException(status_code=500, detail="Output file missing")
|
| 109 |
-
|
| 110 |
with open(output_path, "rb") as f:
|
| 111 |
image_data = f.read()
|
| 112 |
|
| 113 |
-
logger.info("Success, returning image")
|
| 114 |
return Response(content=image_data, media_type="image/jpeg")
|
| 115 |
|
| 116 |
except Exception as e:
|
|
|
|
| 1 |
#!/usr/bin/env python3
|
| 2 |
+
"""FaceFusion API — новая версия"""
|
| 3 |
|
| 4 |
import os
|
| 5 |
import tempfile
|
|
|
|
| 19 |
FACEFUSION_DIR = "/facefusion"
|
| 20 |
FACEFUSION_SCRIPT = os.path.join(FACEFUSION_DIR, "facefusion.py")
|
| 21 |
|
| 22 |
+
# Конфигурация для CPU
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 23 |
EXECUTION_PROVIDERS = ["cpu"]
|
| 24 |
|
| 25 |
+
# Максимальное качество — теперь параметры работают!
|
| 26 |
+
FACE_SWAPPER_MODEL = "ghost_3_256" # лучшая замена лица
|
| 27 |
+
FACE_ENHANCER_MODEL = "codeformer" # лучшее улучшение
|
| 28 |
+
FACE_ENHANCER_BLEND = 80 # вес улучшения
|
| 29 |
FACE_MASK_TYPES = ["box", "occlusion", "region"]
|
| 30 |
FACE_MASK_BLUR = 0.7
|
|
|
|
|
|
|
| 31 |
OUTPUT_IMAGE_QUALITY = 95
|
| 32 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 33 |
@app.get("/health")
|
| 34 |
async def health():
|
| 35 |
+
return {"status": "ok"}
|
| 36 |
|
| 37 |
@app.post("/swap")
|
| 38 |
async def swap_face(source: UploadFile = File(...), target: UploadFile = File(...)):
|
|
|
|
| 42 |
output_path = os.path.join(temp_dir, f"output_{uuid.uuid4().hex}.jpg")
|
| 43 |
|
| 44 |
try:
|
|
|
|
| 45 |
with open(source_path, "wb") as f:
|
| 46 |
f.write(await source.read())
|
| 47 |
with open(target_path, "wb") as f:
|
| 48 |
f.write(await target.read())
|
| 49 |
|
| 50 |
+
# Теперь все параметры поддерживаются!
|
| 51 |
cmd = [
|
| 52 |
"python", FACEFUSION_SCRIPT,
|
| 53 |
"headless-run",
|
| 54 |
"--source", source_path,
|
| 55 |
"--target", target_path,
|
| 56 |
"--output-path", output_path,
|
| 57 |
+
"--face-swapper-model", FACE_SWAPPER_MODEL, # работает
|
| 58 |
+
"--face-enhancer-model", FACE_ENHANCER_MODEL, # работает
|
| 59 |
+
"--face-enhancer-blend", str(FACE_ENHANCER_BLEND),
|
| 60 |
"--face-mask-types", *FACE_MASK_TYPES,
|
| 61 |
"--face-mask-blur", str(FACE_MASK_BLUR),
|
| 62 |
"--output-image-quality", str(OUTPUT_IMAGE_QUALITY),
|
|
|
|
| 73 |
text=True
|
| 74 |
)
|
| 75 |
|
| 76 |
+
stdout, stderr = process.communicate(timeout=180)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 77 |
elapsed = time.time() - start_time
|
| 78 |
logger.info(f"Processing took {elapsed:.2f} seconds")
|
|
|
|
|
|
|
|
|
|
|
|
|
| 79 |
|
| 80 |
if process.returncode != 0:
|
| 81 |
+
logger.error(f"FaceFusion error: {stderr}")
|
| 82 |
raise HTTPException(status_code=500, detail=f"FaceFusion error: {stderr}")
|
| 83 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 84 |
with open(output_path, "rb") as f:
|
| 85 |
image_data = f.read()
|
| 86 |
|
|
|
|
| 87 |
return Response(content=image_data, media_type="image/jpeg")
|
| 88 |
|
| 89 |
except Exception as e:
|