File size: 6,605 Bytes
6f7704a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
# rembg Β· birefnet-general β€” API Reference

Background-removal service (model: **birefnet-general**). Exposes a REST API and
a Gradio web UI on a single port (**7860**). All inference runs through **one
shared worker** β€” every request (UI or API) is queued and processed one image at
a time.

- **Base URL:** `https://xocen-rembg.hf.space`
- **Web UI:** `https://xocen-rembg.hf.space/` β†’ redirects to `/ui`
- **Content type of results:** `image/png` (single) or `application/zip` (batch)

> Note: birefnet-general on free CPU is slow (~10–30 s per image). Large batches
> take a while because they run sequentially through the single worker.

---

## Endpoints

| Method | Path | Purpose | Returns |
|--------|------|---------|---------|
| GET | `/` | Redirect to the web UI | 307 β†’ `/ui` |
| GET | `/health` | Liveness + queue status | JSON |
| GET | `/jobs` | List current jobs (queued + processing) | JSON |
| POST | `/remove` | Remove background from one image | `image/png` |
| POST | `/remove/batch` | Remove background from many images | `application/zip` |
| GET | `/kill?key=…` | Cancel queued jobs + hard-restart worker | JSON |

---

### GET /health

Health check and live queue stats.

```bash
curl https://xocen-rembg.hf.space/health
```

**200 OK**
```json
{
  "status": "ok",
  "model": "birefnet-general",
  "queue": 0,
  "in_flight": 0
}
```
- `queue` β€” jobs waiting to start.
- `in_flight` β€” jobs currently being processed (0 or 1 with a single worker).

---

### GET /jobs

List the jobs the server currently knows about β€” both waiting and processing.
Jobs disappear from the list once they finish (the response is already returned
to that client). Useful for watching a batch drain.

```bash
curl https://xocen-rembg.hf.space/jobs
```

**200 OK**
```json
{
  "total": 3,
  "queue": 2,
  "in_flight": 1,
  "jobs": [
    { "id": "9f2c…", "status": "processing", "label": "a.jpg", "age_seconds": 12.4 },
    { "id": "1b07…", "status": "queued",     "label": "b.jpg", "age_seconds": 12.3 },
    { "id": "44de…", "status": "queued",     "label": "c.jpg", "age_seconds": 12.3 }
  ]
}
```
- `jobs` is ordered oldest-first; with one worker the oldest is the one
  `processing`.
- `label` is the original filename when known (set by `/remove`,
  `/remove/batch`, and the UI), otherwise `null`.
- `age_seconds` is how long the job has existed (queued + processing time).

---

### POST /remove

Remove the background from a **single** image.

- **Body:** `multipart/form-data`
- **Field name:** `file` (must be an image; max size = `MAX_FILE_MB`, default 30 MB)
- **Response:** `image/png` with a transparent background

```bash
curl -X POST https://xocen-rembg.hf.space/remove \
  -F "file=@input.jpg" \
  --output output.png
```

**Errors**
| Status | When |
|--------|------|
| 400 | Field isn't an image, or file exceeds the size limit |

---

### POST /remove/batch

Remove backgrounds from **multiple** images in one call.

- **Body:** `multipart/form-data`
- **Field name:** `files` β€” repeat it once per image (max count = `MAX_BATCH_FILES`, default 20)
- **Response:** `application/zip` containing one PNG per input (named after the
  original file, with a `.png` extension). If any image fails, the ZIP also
  contains `_errors.txt` listing the failures β€” the rest still succeed.

```bash
curl -X POST https://xocen-rembg.hf.space/remove/batch \
  -F "files=@a.jpg" \
  -F "files=@b.png" \
  -F "files=@c.webp" \
  --output results.zip

unzip -l results.zip
#   a.png
#   b.png
#   c.png
#   _errors.txt   (only present if something failed)
```

**Errors**
| Status | When |
|--------|------|
| 400 | More than `MAX_BATCH_FILES` files uploaded |

Per-file problems (not an image, too large, inference error) do **not** fail the
whole batch β€” that file is skipped and recorded in `_errors.txt`.

---

### GET /kill

Cancel everything: drops all queued jobs and **hard-restarts the worker
process**, aborting the job currently in progress. Guarded by a secret key.

- **Query param:** `key` β€” must equal the `KILL_API_KEY` env var (set as a Space
  secret).

```bash
curl "https://xocen-rembg.hf.space/kill?key=YOUR_KEY"
```

**200 OK**
```json
{ "killed_pending": 3, "worker_restarted": true }
```

**Errors**
| Status | When |
|--------|------|
| 401 | Missing or wrong `key` |
| 503 | `KILL_API_KEY` is not configured on the server |

After a kill, the worker respawns and reloads the model on the next request
(a few seconds of warm-up).

---

## Usage examples

### Python (`requests`)

```python
import requests

BASE = "https://xocen-rembg.hf.space"

# single
with open("input.jpg", "rb") as f:
    r = requests.post(f"{BASE}/remove", files={"file": f})
r.raise_for_status()
with open("output.png", "wb") as out:
    out.write(r.content)

# batch
files = [
    ("files", ("a.jpg", open("a.jpg", "rb"), "image/jpeg")),
    ("files", ("b.png", open("b.png", "rb"), "image/png")),
]
r = requests.post(f"{BASE}/remove/batch", files=files)
r.raise_for_status()
with open("results.zip", "wb") as out:
    out.write(r.content)

# kill
requests.get(f"{BASE}/kill", params={"key": "YOUR_KEY"})
```

### JavaScript (browser / Node `fetch`)

```js
const BASE = "https://xocen-rembg.hf.space";

// single
const fd = new FormData();
fd.append("file", fileInput.files[0]);
const res = await fetch(`${BASE}/remove`, { method: "POST", body: fd });
const blob = await res.blob();              // image/png
const url = URL.createObjectURL(blob);

// batch
const fd2 = new FormData();
for (const f of fileInput.files) fd2.append("files", f);
const zip = await (await fetch(`${BASE}/remove/batch`, { method: "POST", body: fd2 })).blob();
```

---

## Configuration (server-side env vars)

Set these in the Space β†’ **Settings β†’ Variables and secrets**.

| Var | Default | Meaning |
|-----|---------|---------|
| `KILL_API_KEY` | _(unset)_ | Required for `/kill`; unset β†’ `/kill` returns 503. Store as a **secret**. |
| `WORKERS` | `1` | Worker processes (each holds one ~1 GB model copy). Keep at 1 on free CPU. |
| `MAX_BATCH_FILES` | `20` | Max files per `/remove/batch` request. |
| `MAX_FILE_MB` | `30` | Max size per uploaded file. |

---

## Behavior notes

- **Single queue:** UI and API share one worker. With `WORKERS=1`, only one image
  is processed at a time; others wait in `queue`. Check progress via `/health`.
- **No auth on `/remove*`:** only `/kill` is key-protected. Add a proxy/auth layer
  if you need to restrict who can submit images.
- **Output is always PNG** (RGBA with transparency), regardless of input format
  (JPG, PNG, WebP, …).