antigravity commited on
Commit
fffeb52
·
1 Parent(s): 8f40bf2

fix: clear ReferenceAudio cache before deleting temp files

Browse files
Files changed (3) hide show
  1. API_DOCUMENTATION.md +69 -0
  2. app.py +4 -2
  3. openapi.json +300 -0
API_DOCUMENTATION.md ADDED
@@ -0,0 +1,69 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Genie-TTS API 接口文档
2
+
3
+ 本文档列出了 `Genie-TTS` 在 Hugging Face Space 上部署的 API 接口及参数说明。
4
+
5
+ ## 1. 动态加载模型 (`/load_model`)
6
+ 用于在不重启服务的情况下,从指定目录加载新的角色模型。
7
+
8
+ - **URL**: `POST /load_model`
9
+ - **Content-Type**: `application/x-www-form-urlencoded`
10
+
11
+ ### 参数说明:
12
+ | 参数名 | 类型 | 必填 | 默认值 | 说明 |
13
+ | :--- | :--- | :--- | :--- | :--- |
14
+ | `character_name` | `string` | 是 | - | 角色名称(如 "mzm") |
15
+ | `model_path` | `string` | 是 | - | 相对于 `/app` 的路径(如 "models/mzm") |
16
+ | `language` | `string` | 否 | `zh` | 模型默认语言 |
17
+
18
+ ---
19
+
20
+ ## 2. 上传音频并合成 (`/upload_and_tts`)
21
+ 上传一段参考音频文件,并结合输入的文本生成语音。
22
+
23
+ - **URL**: `POST /upload_and_tts`
24
+ - **Content-Type**: `multipart/form-data`
25
+
26
+ ### 参数说明:
27
+ | 参数名 | 类型 | 必填 | 默认值 | 说明 |
28
+ | :--- | :--- | :--- | :--- | :--- |
29
+ | `character_name` | `string` | 否 | `Default` | 使用的模型角色名 |
30
+ | `prompt_text` | `string` | 是 | - | 参考音频对应的文本内容 |
31
+ | `language` | `string` | 否 | `zh` | 参考音频的语言类型 |
32
+ | `text` | `string` | 是 | - | 目标合成文本 |
33
+ | `text_lang` | `string` | 否 | - | 目标文本语言(用于跨语言合成) |
34
+ | `speed` | `number` | 否 | `1.0` | **语速调节** (0.5 - 2.0) |
35
+ | `file` | `binary` | 是 | - | 参考音频文件 (wav, flac 等) |
36
+
37
+ ---
38
+
39
+ ## 3. 通用 TTS 接口 (`/tts`)
40
+ 使用服务器已加载的模型和默认参考音频生成语音。
41
+
42
+ - **URL**: `POST /tts`
43
+ - **Content-Type**: `application/x-www-form-urlencoded`
44
+
45
+ ### 参数说明:
46
+ | 参数名 | 类型 | 必填 | 默认值 | 说明 |
47
+ | :--- | :--- | :--- | :--- | :--- |
48
+ | `text` | `string` | 是 | - | 目标合成文本 |
49
+ | `character_name` | `string` | 否 | `Base` | 指定角色名 |
50
+ | `prompt_text` | `string` | 否 | - | 覆盖默认的参考文本 |
51
+ | `prompt_lang` | `string` | 否 | `zh` | 参考音频语言 |
52
+ | `text_lang` | `string` | 否 | - | 目标文本语言 |
53
+ | `speed` | `number` | 否 | `1.0` | **语速调节** (0.5 - 2.0) |
54
+ | `use_default_ref` | `boolean`| 否 | `true` | 是否使用默认参考音频 |
55
+
56
+ ---
57
+
58
+ ## 4. 健康检查 (`/health`)
59
+ 查看服务在线状态及已加载的模型列表。
60
+
61
+ - **URL**: `GET /health`
62
+
63
+ ### 响应示例:
64
+ ```json
65
+ {
66
+ "status": "ok",
67
+ "models": ["Base", "god", "mzm"]
68
+ }
69
+ ```
app.py CHANGED
@@ -144,8 +144,10 @@ async def upload_and_tts(
144
  with open(out_path, "rb") as f:
145
  yield from f
146
  finally:
147
- # 给一点延迟确保读取完毕后再删除
148
- time.sleep(1)
 
 
149
  try:
150
  if os.path.exists(save_path): os.remove(save_path)
151
  if os.path.exists(out_path): os.remove(out_path)
 
144
  with open(out_path, "rb") as f:
145
  yield from f
146
  finally:
147
+ # 🔴 修复:先清除 ReferenceAudio 缓存,再删除临时文件
148
+ # 否则 LRU 缓存会继续引用已删除的文件路径,导致后续请求报错
149
+ genie_tts.clear_reference_audio_cache()
150
+ time.sleep(0.5)
151
  try:
152
  if os.path.exists(save_path): os.remove(save_path)
153
  if os.path.exists(out_path): os.remove(out_path)
openapi.json ADDED
@@ -0,0 +1,300 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "openapi": "3.1.0",
3
+ "info": {
4
+ "title": "FastAPI",
5
+ "version": "0.1.0"
6
+ },
7
+ "paths": {
8
+ "/load_model": {
9
+ "post": {
10
+ "summary": "Load Model",
11
+ "description": "动态加载新模型 API\nmodel_path: 相对于 /app 的路径,例如 \"models/my_character\"",
12
+ "operationId": "load_model_load_model_post",
13
+ "requestBody": {
14
+ "content": {
15
+ "application/x-www-form-urlencoded": {
16
+ "schema": {
17
+ "$ref": "#/components/schemas/Body_load_model_load_model_post"
18
+ }
19
+ }
20
+ },
21
+ "required": true
22
+ },
23
+ "responses": {
24
+ "200": {
25
+ "description": "Successful Response",
26
+ "content": {
27
+ "application/json": {
28
+ "schema": {}
29
+ }
30
+ }
31
+ },
32
+ "422": {
33
+ "description": "Validation Error",
34
+ "content": {
35
+ "application/json": {
36
+ "schema": {
37
+ "$ref": "#/components/schemas/HTTPValidationError"
38
+ }
39
+ }
40
+ }
41
+ }
42
+ }
43
+ }
44
+ },
45
+ "/upload_and_tts": {
46
+ "post": {
47
+ "summary": "Upload And Tts",
48
+ "description": "上传临时参考音频并生成语音",
49
+ "operationId": "upload_and_tts_upload_and_tts_post",
50
+ "requestBody": {
51
+ "content": {
52
+ "multipart/form-data": {
53
+ "schema": {
54
+ "$ref": "#/components/schemas/Body_upload_and_tts_upload_and_tts_post"
55
+ }
56
+ }
57
+ },
58
+ "required": true
59
+ },
60
+ "responses": {
61
+ "200": {
62
+ "description": "Successful Response",
63
+ "content": {
64
+ "application/json": {
65
+ "schema": {}
66
+ }
67
+ }
68
+ },
69
+ "422": {
70
+ "description": "Validation Error",
71
+ "content": {
72
+ "application/json": {
73
+ "schema": {
74
+ "$ref": "#/components/schemas/HTTPValidationError"
75
+ }
76
+ }
77
+ }
78
+ }
79
+ }
80
+ }
81
+ },
82
+ "/tts": {
83
+ "post": {
84
+ "summary": "Dynamic Tts",
85
+ "description": "通用 TTS 接口,支持切换已加载的角色\ntext_lang: 目标文本语言,如果和参考音频不同则可实现跨语言合成",
86
+ "operationId": "dynamic_tts_tts_post",
87
+ "requestBody": {
88
+ "content": {
89
+ "application/x-www-form-urlencoded": {
90
+ "schema": {
91
+ "$ref": "#/components/schemas/Body_dynamic_tts_tts_post"
92
+ }
93
+ }
94
+ },
95
+ "required": true
96
+ },
97
+ "responses": {
98
+ "200": {
99
+ "description": "Successful Response",
100
+ "content": {
101
+ "application/json": {
102
+ "schema": {}
103
+ }
104
+ }
105
+ },
106
+ "422": {
107
+ "description": "Validation Error",
108
+ "content": {
109
+ "application/json": {
110
+ "schema": {
111
+ "$ref": "#/components/schemas/HTTPValidationError"
112
+ }
113
+ }
114
+ }
115
+ }
116
+ }
117
+ }
118
+ },
119
+ "/health": {
120
+ "get": {
121
+ "summary": "Health",
122
+ "operationId": "health_health_get",
123
+ "responses": {
124
+ "200": {
125
+ "description": "Successful Response",
126
+ "content": {
127
+ "application/json": {
128
+ "schema": {}
129
+ }
130
+ }
131
+ }
132
+ }
133
+ }
134
+ }
135
+ },
136
+ "components": {
137
+ "schemas": {
138
+ "Body_dynamic_tts_tts_post": {
139
+ "properties": {
140
+ "text": {
141
+ "type": "string",
142
+ "title": "Text"
143
+ },
144
+ "character_name": {
145
+ "type": "string",
146
+ "title": "Character Name",
147
+ "default": "Base"
148
+ },
149
+ "prompt_text": {
150
+ "type": "string",
151
+ "title": "Prompt Text"
152
+ },
153
+ "prompt_lang": {
154
+ "type": "string",
155
+ "title": "Prompt Lang",
156
+ "default": "zh"
157
+ },
158
+ "text_lang": {
159
+ "type": "string",
160
+ "title": "Text Lang"
161
+ },
162
+ "speed": {
163
+ "type": "number",
164
+ "title": "Speed",
165
+ "default": 1.0
166
+ },
167
+ "use_default_ref": {
168
+ "type": "boolean",
169
+ "title": "Use Default Ref",
170
+ "default": true
171
+ }
172
+ },
173
+ "type": "object",
174
+ "required": [
175
+ "text"
176
+ ],
177
+ "title": "Body_dynamic_tts_tts_post"
178
+ },
179
+ "Body_load_model_load_model_post": {
180
+ "properties": {
181
+ "character_name": {
182
+ "type": "string",
183
+ "title": "Character Name"
184
+ },
185
+ "model_path": {
186
+ "type": "string",
187
+ "title": "Model Path"
188
+ },
189
+ "language": {
190
+ "type": "string",
191
+ "title": "Language",
192
+ "default": "zh"
193
+ }
194
+ },
195
+ "type": "object",
196
+ "required": [
197
+ "character_name",
198
+ "model_path"
199
+ ],
200
+ "title": "Body_load_model_load_model_post"
201
+ },
202
+ "Body_upload_and_tts_upload_and_tts_post": {
203
+ "properties": {
204
+ "character_name": {
205
+ "type": "string",
206
+ "title": "Character Name",
207
+ "default": "Default"
208
+ },
209
+ "prompt_text": {
210
+ "type": "string",
211
+ "title": "Prompt Text"
212
+ },
213
+ "text": {
214
+ "type": "string",
215
+ "title": "Text"
216
+ },
217
+ "language": {
218
+ "type": "string",
219
+ "title": "Language",
220
+ "default": "zh"
221
+ },
222
+ "text_lang": {
223
+ "type": "string",
224
+ "title": "Text Lang"
225
+ },
226
+ "speed": {
227
+ "type": "number",
228
+ "title": "Speed",
229
+ "default": 1.0
230
+ },
231
+ "file": {
232
+ "type": "string",
233
+ "format": "binary",
234
+ "title": "File"
235
+ }
236
+ },
237
+ "type": "object",
238
+ "required": [
239
+ "prompt_text",
240
+ "text",
241
+ "file"
242
+ ],
243
+ "title": "Body_upload_and_tts_upload_and_tts_post"
244
+ },
245
+ "HTTPValidationError": {
246
+ "properties": {
247
+ "detail": {
248
+ "items": {
249
+ "$ref": "#/components/schemas/ValidationError"
250
+ },
251
+ "type": "array",
252
+ "title": "Detail"
253
+ }
254
+ },
255
+ "type": "object",
256
+ "title": "HTTPValidationError"
257
+ },
258
+ "ValidationError": {
259
+ "properties": {
260
+ "loc": {
261
+ "items": {
262
+ "anyOf": [
263
+ {
264
+ "type": "string"
265
+ },
266
+ {
267
+ "type": "integer"
268
+ }
269
+ ]
270
+ },
271
+ "type": "array",
272
+ "title": "Location"
273
+ },
274
+ "msg": {
275
+ "type": "string",
276
+ "title": "Message"
277
+ },
278
+ "type": {
279
+ "type": "string",
280
+ "title": "Error Type"
281
+ },
282
+ "input": {
283
+ "title": "Input"
284
+ },
285
+ "ctx": {
286
+ "type": "object",
287
+ "title": "Context"
288
+ }
289
+ },
290
+ "type": "object",
291
+ "required": [
292
+ "loc",
293
+ "msg",
294
+ "type"
295
+ ],
296
+ "title": "ValidationError"
297
+ }
298
+ }
299
+ }
300
+ }