File size: 5,112 Bytes
c44c3ce
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
# API reference

How this Space talks to VoxCPM2, and how you can do the same from your own code.

## This Space has no API of its own

`diatest/VoxCPM-Demo` is a **static** Space β€” one `index.html`, no server process,
nothing listening. There is no endpoint on `https://diatest-voxcpm-demo.static.hf.space`
to POST to.

| | |
|---|---|
| Repo page | https://huggingface.co/spaces/diatest/VoxCPM-Demo |
| Live app | https://diatest-voxcpm-demo.static.hf.space |
| SDK | `static`, public, no hardware |

What the page does is call the public Gradio API of the **official** Space from the
visitor's browser. Everything below is that API:

```
BASE = https://openbmb-voxcpm-demo.hf.space
```

Gradio's REST bridge is a two-step protocol: `POST /gradio_api/call/<endpoint>` returns
an `event_id`, then `GET /gradio_api/call/<endpoint>/<event_id>` streams the result as
Server-Sent Events. The payload you want arrives on `event: complete`; failures arrive
on `event: error`.

---

## 1. Upload a reference clip

Required before any call that takes audio. Returns a server-side path.

```bash
curl -X POST $BASE/gradio_api/upload -F "files=@reference.wav"
# ["/tmp/gradio/02a3dbd5.../reference.wav"]
```

Wherever an endpoint takes audio, pass that path wrapped as a Gradio `FileData`:

```json
{ "path": "/tmp/gradio/02a3dbd5.../reference.wav", "meta": { "_type": "gradio.FileData" } }
```

---

## 2. Generate speech β€” `/generate`

Arguments are **positional** in the `data` array. Order matters.

| # | Field | Type | Default | Notes |
|---|---|---|---|---|
| 0 | `text_input` | string | β€” | the text to speak |
| 1 | `control_instruction` | string | `""` | natural-language voice description |
| 2 | `reference_wav_path_input` | FileData \| null | `null` | clip to clone |
| 3 | `use_prompt_text` | bool | `false` | exact-clone mode |
| 4 | `prompt_text_input` | string | `""` | transcript of the reference clip |
| 5 | `cfg_value_input` | float | `2.0` | guidance scale |
| 6 | `do_normalize` | bool | `false` | normalize numbers/dates |
| 7 | `denoise` | bool | `false` | denoise the reference clip |

```bash
EID=$(curl -s -X POST $BASE/gradio_api/call/generate \
  -H "Content-Type: application/json" \
  -d '{"data":["Hello from VoxCPM.","",null,false,"",2.0,true,false]}' \
  | python3 -c "import sys,json;print(json.load(sys.stdin)['event_id'])")

curl -N $BASE/gradio_api/call/generate/$EID
```

```
event: complete
data: [{"path":"/tmp/gradio/.../tmp4wz.mp3","url":"https://openbmb-voxcpm-demo.hf.space/gradio_api/file=/tmp/gradio/.../tmp4wz.mp3", ...}]
```

Fetch the `url` for the audio. It is an **MP3**, despite the raw-PCM naming elsewhere in
the VoxCPM ecosystem.

**Voice cloning:** upload the clip (step 1), then pass the `FileData` at index 2, `true`
at index 3, and the clip's transcript at index 4.

---

## 3. Transcribe a reference clip β€” `/_run_asr_if_needed`

SenseVoice ASR. The page uses it to auto-fill the transcript for exact-clone mode.

```bash
curl -X POST $BASE/gradio_api/call/_run_asr_if_needed \
  -H "Content-Type: application/json" \
  -d '{"data":[true,{"path":"/tmp/gradio/.../reference.wav","meta":{"_type":"gradio.FileData"}}]}'
```

Collect the event id as above. The response is a Gradio *update* object, so the text is
under `.value`, not the top level:

```
data: [{"placeholder":"…","value":"Just by listening a few minutes a day, …","__type__":"update"}]
```

---

## Behaviour worth knowing

- **No auth.** These endpoints answer anonymously β€” that is why a static page can drive
  them. No token, no key.
- **CORS reflects the calling origin**, so browser calls work from this Space and from
  `localhost` during development.
- **Latency** is roughly 3–7 s for a short sentence. Measured throughput saturates around
  2–4 concurrent requests; beyond that you are queueing, not parallelising.
- **`_`-prefixed endpoints are internal.** `_run_asr_if_needed` is a Gradio event handler,
  not a published API. It can be renamed or removed by any upstream redeploy.

---

## Do not put production traffic through this

The API above is **openbmb's infrastructure, not ours**. It is a free, shared Space
serving other people: no SLA, no capacity guarantee, and it can change shape or vanish
without notice. Sustained production load would also degrade it for everyone else using
the demo.

Fine for: demos, prototypes, experimentation, this Space.

Not fine for: an application backend.

### If you want a Space serving your own model

`gradio-app/` in this repo is a complete standalone Gradio app that loads VoxCPM locally
through the [`voxcpm`](https://pypi.org/project/voxcpm/) package β€” no upstream dependency.
It is written ZeroGPU-first and defaults to the smaller `openbmb/VoxCPM-0.5B` so it also
runs on CPU. Deploying it needs a PRO account, since Gradio Spaces are no longer on the
free tier:

```bash
hf repos create <ns>/VoxCPM-Self-Hosted --type space --space-sdk gradio \
    --flavor zero-a10g --public
hf upload <ns>/VoxCPM-Self-Hosted ./gradio-app . --repo-type space
```

See `gradio-app/README.md` for its environment variables.