LogicGoInfotechSpaces commited on
Commit
0e17006
·
1 Parent(s): b04dbb5

Configure HuggingFace Space for FastAPI with Docker SDK

Browse files
Files changed (5) hide show
  1. Dockerfile +3 -2
  2. README.md +2 -2
  3. combined_app.py +22 -0
  4. main_app.py +41 -0
  5. postman_collection.json +481 -0
Dockerfile CHANGED
@@ -18,10 +18,11 @@ RUN pip install --no-cache-dir -r requirements.txt
18
  # Copy source
19
  COPY . .
20
 
21
- EXPOSE 8000
22
 
23
  # Optional: set at runtime
24
  ENV FACE_SWAP_API_KEY=""
25
 
26
- CMD ["python3", "-m", "uvicorn", "fastapi_app:app", "--host", "0.0.0.0", "--port", "8000"]
 
27
 
 
18
  # Copy source
19
  COPY . .
20
 
21
+ EXPOSE 7860
22
 
23
  # Optional: set at runtime
24
  ENV FACE_SWAP_API_KEY=""
25
 
26
+ CMD ["python3", "-m", "uvicorn", "fastapi_app:app", "--host", "0.0.0.0", "--port", "7860"]
27
+
28
 
README.md CHANGED
@@ -3,9 +3,9 @@ title: FaceSwapAll
3
  emoji: 🏆
4
  colorFrom: green
5
  colorTo: indigo
6
- sdk: gradio
7
  sdk_version: 5.29.0
8
- app_file: app.py
9
  pinned: false
10
  license: unknown
11
  short_description: 'All-in-one face swapping: single photo, video, multi-source,'
 
3
  emoji: 🏆
4
  colorFrom: green
5
  colorTo: indigo
6
+ sdk: docker
7
  sdk_version: 5.29.0
8
+ app_file: Dockerfile
9
  pinned: false
10
  license: unknown
11
  short_description: 'All-in-one face swapping: single photo, video, multi-source,'
combined_app.py ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Combined app that runs both Gradio UI and FastAPI endpoints.
3
+ This allows HuggingFace Spaces to serve both the UI and API.
4
+ """
5
+ import os
6
+ import sys
7
+
8
+ # Import FastAPI app
9
+ from fastapi_app import app as fastapi_app
10
+
11
+ # Import Gradio app
12
+ import gradio as gr
13
+ from app import demo as gradio_demo
14
+
15
+ # Mount FastAPI app to Gradio
16
+ gradio_demo.mount("/api", fastapi_app)
17
+
18
+ if __name__ == "__main__":
19
+ # For HuggingFace Spaces, Gradio will handle the launch
20
+ # The FastAPI endpoints will be available at /api/*
21
+ gradio_demo.launch(server_name="0.0.0.0", server_port=7860)
22
+
main_app.py ADDED
@@ -0,0 +1,41 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Main app for HuggingFace Spaces - FastAPI with Gradio mounted.
3
+ FastAPI endpoints are at root, Gradio UI is at /gradio
4
+ """
5
+ from fastapi import FastAPI
6
+ from fastapi.middleware.wsgi import WSGIMiddleware
7
+ import gradio as gr
8
+
9
+ # Import FastAPI app
10
+ from fastapi_app import app as fastapi_app
11
+
12
+ # Import Gradio app components
13
+ from app import demo as gradio_demo
14
+
15
+ # Create main FastAPI app
16
+ main_app = FastAPI(title="FaceSwapAll - Combined API and UI")
17
+
18
+ # Mount FastAPI endpoints (they're already in fastapi_app)
19
+ # We'll include them directly
20
+ main_app.mount("/api", fastapi_app)
21
+
22
+ # Mount Gradio UI
23
+ main_app.mount("/gradio", WSGIMiddleware(gradio_demo.server))
24
+
25
+ # Also include health endpoint at root
26
+ @main_app.get("/")
27
+ def root():
28
+ return {
29
+ "message": "FaceSwapAll API",
30
+ "docs": "/docs",
31
+ "gradio_ui": "/gradio",
32
+ "api_endpoints": "/api"
33
+ }
34
+
35
+ # Re-export for uvicorn
36
+ app = main_app
37
+
38
+ if __name__ == "__main__":
39
+ import uvicorn
40
+ uvicorn.run(app, host="0.0.0.0", port=8000)
41
+
postman_collection.json ADDED
@@ -0,0 +1,481 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "info": {
3
+ "_postman_id": "faceswap-api-collection",
4
+ "name": "FaceSwapAll API",
5
+ "description": "Complete API collection for FaceSwapAll face swapping service",
6
+ "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
7
+ },
8
+ "item": [
9
+ {
10
+ "name": "Health Check",
11
+ "request": {
12
+ "method": "GET",
13
+ "header": [],
14
+ "url": {
15
+ "raw": "{{base_url}}/health",
16
+ "host": ["{{base_url}}"],
17
+ "path": ["health"]
18
+ }
19
+ },
20
+ "response": []
21
+ },
22
+ {
23
+ "name": "Photo Swapping",
24
+ "item": [
25
+ {
26
+ "name": "Single Photo Swap",
27
+ "request": {
28
+ "method": "POST",
29
+ "header": [
30
+ {
31
+ "key": "X-API-Key",
32
+ "value": "{{api_key}}",
33
+ "type": "text"
34
+ }
35
+ ],
36
+ "body": {
37
+ "mode": "formdata",
38
+ "formdata": [
39
+ {
40
+ "key": "source_image",
41
+ "type": "file",
42
+ "src": []
43
+ },
44
+ {
45
+ "key": "destination_image",
46
+ "type": "file",
47
+ "src": []
48
+ },
49
+ {
50
+ "key": "source_face_idx",
51
+ "value": "1",
52
+ "type": "text"
53
+ },
54
+ {
55
+ "key": "destination_face_idx",
56
+ "value": "1",
57
+ "type": "text"
58
+ }
59
+ ]
60
+ },
61
+ "url": {
62
+ "raw": "{{base_url}}/swap/photo",
63
+ "host": ["{{base_url}}"],
64
+ "path": ["swap", "photo"]
65
+ },
66
+ "description": "Swap a single face from source image to destination image"
67
+ },
68
+ "response": []
69
+ },
70
+ {
71
+ "name": "Single Source - Multiple Destinations",
72
+ "request": {
73
+ "method": "POST",
74
+ "header": [
75
+ {
76
+ "key": "X-API-Key",
77
+ "value": "{{api_key}}",
78
+ "type": "text"
79
+ }
80
+ ],
81
+ "body": {
82
+ "mode": "formdata",
83
+ "formdata": [
84
+ {
85
+ "key": "source_image",
86
+ "type": "file",
87
+ "src": []
88
+ },
89
+ {
90
+ "key": "destination_images",
91
+ "type": "file",
92
+ "src": []
93
+ },
94
+ {
95
+ "key": "destination_images",
96
+ "type": "file",
97
+ "src": []
98
+ },
99
+ {
100
+ "key": "destination_indices",
101
+ "value": "1,1,2",
102
+ "type": "text",
103
+ "description": "Comma-separated destination face indices (e.g., '1,1,2')"
104
+ }
105
+ ]
106
+ },
107
+ "url": {
108
+ "raw": "{{base_url}}/swap/photo/single-src-multi-dst",
109
+ "host": ["{{base_url}}"],
110
+ "path": ["swap", "photo", "single-src-multi-dst"]
111
+ },
112
+ "description": "Swap a single source face onto multiple destination images. Returns ZIP file."
113
+ },
114
+ "response": []
115
+ },
116
+ {
117
+ "name": "Multiple Sources - Single Destination",
118
+ "request": {
119
+ "method": "POST",
120
+ "header": [
121
+ {
122
+ "key": "X-API-Key",
123
+ "value": "{{api_key}}",
124
+ "type": "text"
125
+ }
126
+ ],
127
+ "body": {
128
+ "mode": "formdata",
129
+ "formdata": [
130
+ {
131
+ "key": "source_images",
132
+ "type": "file",
133
+ "src": []
134
+ },
135
+ {
136
+ "key": "source_images",
137
+ "type": "file",
138
+ "src": []
139
+ },
140
+ {
141
+ "key": "destination_image",
142
+ "type": "file",
143
+ "src": []
144
+ },
145
+ {
146
+ "key": "destination_face_idx",
147
+ "value": "1",
148
+ "type": "text"
149
+ }
150
+ ]
151
+ },
152
+ "url": {
153
+ "raw": "{{base_url}}/swap/photo/multi-src-single-dst",
154
+ "host": ["{{base_url}}"],
155
+ "path": ["swap", "photo", "multi-src-single-dst"]
156
+ },
157
+ "description": "Swap multiple source faces onto a single destination image. Returns ZIP file."
158
+ },
159
+ "response": []
160
+ },
161
+ {
162
+ "name": "Multiple Sources - Multiple Destinations",
163
+ "request": {
164
+ "method": "POST",
165
+ "header": [
166
+ {
167
+ "key": "X-API-Key",
168
+ "value": "{{api_key}}",
169
+ "type": "text"
170
+ }
171
+ ],
172
+ "body": {
173
+ "mode": "formdata",
174
+ "formdata": [
175
+ {
176
+ "key": "source_images",
177
+ "type": "file",
178
+ "src": []
179
+ },
180
+ {
181
+ "key": "source_images",
182
+ "type": "file",
183
+ "src": []
184
+ },
185
+ {
186
+ "key": "destination_images",
187
+ "type": "file",
188
+ "src": []
189
+ },
190
+ {
191
+ "key": "destination_images",
192
+ "type": "file",
193
+ "src": []
194
+ },
195
+ {
196
+ "key": "destination_indices",
197
+ "value": "1,1,2",
198
+ "type": "text",
199
+ "description": "Comma-separated destination face indices (e.g., '1,1,2')"
200
+ }
201
+ ]
202
+ },
203
+ "url": {
204
+ "raw": "{{base_url}}/swap/photo/multi-src-multi-dst",
205
+ "host": ["{{base_url}}"],
206
+ "path": ["swap", "photo", "multi-src-multi-dst"]
207
+ },
208
+ "description": "Swap multiple source faces onto multiple destination images. Returns ZIP file."
209
+ },
210
+ "response": []
211
+ },
212
+ {
213
+ "name": "Custom Face Mapping",
214
+ "request": {
215
+ "method": "POST",
216
+ "header": [
217
+ {
218
+ "key": "X-API-Key",
219
+ "value": "{{api_key}}",
220
+ "type": "text"
221
+ }
222
+ ],
223
+ "body": {
224
+ "mode": "formdata",
225
+ "formdata": [
226
+ {
227
+ "key": "source_images",
228
+ "type": "file",
229
+ "src": []
230
+ },
231
+ {
232
+ "key": "source_images",
233
+ "type": "file",
234
+ "src": []
235
+ },
236
+ {
237
+ "key": "destination_image",
238
+ "type": "file",
239
+ "src": []
240
+ },
241
+ {
242
+ "key": "mapping",
243
+ "value": "2,1,3",
244
+ "type": "text",
245
+ "description": "Comma-separated mapping (e.g., '2,1,3' means face1->src2, face2->src1, face3->src3)"
246
+ }
247
+ ]
248
+ },
249
+ "url": {
250
+ "raw": "{{base_url}}/swap/photo/custom-mapping",
251
+ "host": ["{{base_url}}"],
252
+ "path": ["swap", "photo", "custom-mapping"]
253
+ },
254
+ "description": "Swap faces with custom mapping: map destination faces to specific source images"
255
+ },
256
+ "response": []
257
+ }
258
+ ]
259
+ },
260
+ {
261
+ "name": "Video Swapping",
262
+ "item": [
263
+ {
264
+ "name": "Single Video Swap",
265
+ "request": {
266
+ "method": "POST",
267
+ "header": [
268
+ {
269
+ "key": "X-API-Key",
270
+ "value": "{{api_key}}",
271
+ "type": "text"
272
+ }
273
+ ],
274
+ "body": {
275
+ "mode": "formdata",
276
+ "formdata": [
277
+ {
278
+ "key": "source_image",
279
+ "type": "file",
280
+ "src": []
281
+ },
282
+ {
283
+ "key": "target_video",
284
+ "type": "file",
285
+ "src": []
286
+ },
287
+ {
288
+ "key": "source_face_idx",
289
+ "value": "1",
290
+ "type": "text"
291
+ },
292
+ {
293
+ "key": "destination_face_idx",
294
+ "value": "1",
295
+ "type": "text"
296
+ },
297
+ {
298
+ "key": "add_audio",
299
+ "value": "true",
300
+ "type": "text",
301
+ "description": "Add audio from original video (true/false)"
302
+ }
303
+ ]
304
+ },
305
+ "url": {
306
+ "raw": "{{base_url}}/swap/video",
307
+ "host": ["{{base_url}}"],
308
+ "path": ["swap", "video"]
309
+ },
310
+ "description": "Swap a single face from source image onto all frames of target video"
311
+ },
312
+ "response": []
313
+ },
314
+ {
315
+ "name": "Swap All Faces in Video",
316
+ "request": {
317
+ "method": "POST",
318
+ "header": [
319
+ {
320
+ "key": "X-API-Key",
321
+ "value": "{{api_key}}",
322
+ "type": "text"
323
+ }
324
+ ],
325
+ "body": {
326
+ "mode": "formdata",
327
+ "formdata": [
328
+ {
329
+ "key": "source_image",
330
+ "type": "file",
331
+ "src": []
332
+ },
333
+ {
334
+ "key": "target_video",
335
+ "type": "file",
336
+ "src": []
337
+ },
338
+ {
339
+ "key": "num_faces_to_swap",
340
+ "value": "1",
341
+ "type": "text",
342
+ "description": "Number of faces to swap"
343
+ },
344
+ {
345
+ "key": "add_audio",
346
+ "value": "true",
347
+ "type": "text",
348
+ "description": "Add audio from original video (true/false)"
349
+ }
350
+ ]
351
+ },
352
+ "url": {
353
+ "raw": "{{base_url}}/swap/video/all-faces",
354
+ "host": ["{{base_url}}"],
355
+ "path": ["swap", "video", "all-faces"]
356
+ },
357
+ "description": "Swap all faces in video with the same source face"
358
+ },
359
+ "response": []
360
+ },
361
+ {
362
+ "name": "Video Custom Face Mapping",
363
+ "request": {
364
+ "method": "POST",
365
+ "header": [
366
+ {
367
+ "key": "X-API-Key",
368
+ "value": "{{api_key}}",
369
+ "type": "text"
370
+ }
371
+ ],
372
+ "body": {
373
+ "mode": "formdata",
374
+ "formdata": [
375
+ {
376
+ "key": "source_images",
377
+ "type": "file",
378
+ "src": []
379
+ },
380
+ {
381
+ "key": "source_images",
382
+ "type": "file",
383
+ "src": []
384
+ },
385
+ {
386
+ "key": "target_video",
387
+ "type": "file",
388
+ "src": []
389
+ },
390
+ {
391
+ "key": "mapping",
392
+ "value": "2,1,3",
393
+ "type": "text",
394
+ "description": "Comma-separated mapping (e.g., '2,1,3')"
395
+ },
396
+ {
397
+ "key": "add_audio",
398
+ "value": "true",
399
+ "type": "text",
400
+ "description": "Add audio from original video (true/false)"
401
+ }
402
+ ]
403
+ },
404
+ "url": {
405
+ "raw": "{{base_url}}/swap/video/custom-mapping",
406
+ "host": ["{{base_url}}"],
407
+ "path": ["swap", "video", "custom-mapping"]
408
+ },
409
+ "description": "Swap faces in video with custom mapping: map destination faces to specific source images"
410
+ },
411
+ "response": []
412
+ },
413
+ {
414
+ "name": "Single Source - Multiple Videos",
415
+ "request": {
416
+ "method": "POST",
417
+ "header": [
418
+ {
419
+ "key": "X-API-Key",
420
+ "value": "{{api_key}}",
421
+ "type": "text"
422
+ }
423
+ ],
424
+ "body": {
425
+ "mode": "formdata",
426
+ "formdata": [
427
+ {
428
+ "key": "source_image",
429
+ "type": "file",
430
+ "src": []
431
+ },
432
+ {
433
+ "key": "target_videos",
434
+ "type": "file",
435
+ "src": []
436
+ },
437
+ {
438
+ "key": "target_videos",
439
+ "type": "file",
440
+ "src": []
441
+ },
442
+ {
443
+ "key": "destination_indices",
444
+ "value": "1,2,1",
445
+ "type": "text",
446
+ "description": "Comma-separated destination face indices (e.g., '1,2,1')"
447
+ },
448
+ {
449
+ "key": "add_audio",
450
+ "value": "true",
451
+ "type": "text",
452
+ "description": "Add audio from original video (true/false)"
453
+ }
454
+ ]
455
+ },
456
+ "url": {
457
+ "raw": "{{base_url}}/swap/video/single-src-multi-video",
458
+ "host": ["{{base_url}}"],
459
+ "path": ["swap", "video", "single-src-multi-video"]
460
+ },
461
+ "description": "Swap a single source face onto multiple videos. Returns ZIP file."
462
+ },
463
+ "response": []
464
+ }
465
+ ]
466
+ }
467
+ ],
468
+ "variable": [
469
+ {
470
+ "key": "base_url",
471
+ "value": "https://LogicGoInfotechSpaces-FaceSwapAll.hf.space",
472
+ "type": "string"
473
+ },
474
+ {
475
+ "key": "api_key",
476
+ "value": "your_api_key_here",
477
+ "type": "string"
478
+ }
479
+ ]
480
+ }
481
+