YanTianlong commited on
Commit
5277693
·
1 Parent(s): c4ce813

Add VoiceGate workflow assets and TODO

Browse files
docs/deployment-plan.md CHANGED
@@ -28,8 +28,9 @@ Current local state:
28
  - `VoiceGate/.gitmodules` references `comfyui_voicebridge`, but the local
29
  `VoiceGate/comfyui_voicebridge/` directory is currently empty.
30
  - `VoiceGate/workflows/VoiceGate-Workflow.json` is the UI workflow.
31
- - `VoiceGate/workflows/VoiceGate-Workflow_api.json` exists, but currently fails
32
- JSON parsing and must be re-exported or repaired before API execution.
 
33
 
34
  ## Hugging Face Space Constraints
35
 
@@ -179,5 +180,6 @@ Verify in this order:
179
 
180
  ## Immediate Next Step
181
 
182
- Prepare the runtime bootstrap scripts and decide whether to vendor custom nodes
183
- into `custom_nodes/` or download pinned commits during Space startup.
 
 
28
  - `VoiceGate/.gitmodules` references `comfyui_voicebridge`, but the local
29
  `VoiceGate/comfyui_voicebridge/` directory is currently empty.
30
  - `VoiceGate/workflows/VoiceGate-Workflow.json` is the UI workflow.
31
+ - `VoiceGate/workflows/VoiceGate-Workflow_api.json` exists and has been
32
+ confirmed as valid JSON. It still needs parameterization before Gradio can
33
+ submit it to ComfyUI.
34
 
35
  ## Hugging Face Space Constraints
36
 
 
180
 
181
  ## Immediate Next Step
182
 
183
+ Copy the validated API workflow into the Space `workflows/` directory, prepare
184
+ the runtime bootstrap scripts, and decide whether to vendor custom nodes into
185
+ `custom_nodes/` or download pinned commits during Space startup.
docs/todo.md ADDED
@@ -0,0 +1,114 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # VoiceGate HF Space TODO
2
+
3
+ This is the execution checklist for bringing the VoiceGate Hugging Face Space
4
+ from scaffold to a working Gradio app.
5
+
6
+ ## Current Status
7
+
8
+ - [x] Create the `VoiceGate-hf` Space wrapper repository.
9
+ - [x] Configure and push to `build-small-hackathon/VoiceGate`.
10
+ - [x] Replace the default HF template with a VoiceGate scaffold.
11
+ - [x] Keep the upstream `VoiceGate/` checkout local-only and ignored.
12
+ - [x] Preserve Hugging Face LFS rules in `.gitattributes`.
13
+ - [x] Confirm `VoiceGate/workflows/VoiceGate-Workflow_api.json` is valid JSON.
14
+ - [x] Copy the validated API workflow into `workflows/voicegate_api.json`.
15
+
16
+ ## Phase 1: Repository Hygiene
17
+
18
+ - [x] Copy `VoiceGate/workflows/VoiceGate-Workflow_api.json` to
19
+ `workflows/voicegate_api.json`.
20
+ - [x] Copy `VoiceGate/workflows/VoiceGate-Workflow.json` to
21
+ `workflows/voicegate_ui.json` for reference.
22
+ - [ ] Update docs so `VoiceGate/` is clearly documented as a local upstream
23
+ checkout, not Space runtime content.
24
+ - [ ] Commit and push the workflow files after confirming they contain no
25
+ secrets or large media.
26
+
27
+ ## Phase 2: Dependency Inventory
28
+
29
+ - [ ] Identify exact repositories and pinned commits for every required custom
30
+ node package:
31
+ - [ ] `comfyui_voicebridge`
32
+ - [ ] RunningHub VoxCPM nodes
33
+ - [ ] MelBandRoFormer nodes
34
+ - [ ] rgthree nodes
35
+ - [ ] comfyui-easy-use
36
+ - [ ] Comfyroll text nodes or equivalent provider for `CR Text`
37
+ - [ ] `RH_LLMAPI_NODE` provider
38
+ - [ ] Identify Python dependency constraints for ComfyUI and all custom nodes.
39
+ - [ ] Identify system packages beyond `ffmpeg` and `git`, if any.
40
+ - [ ] Decide whether custom nodes are vendored in `custom_nodes/` or installed
41
+ by pinned git URL during bootstrap.
42
+ - [ ] Decide where model files are downloaded and cached in the Space.
43
+
44
+ ## Phase 3: Runtime Bootstrap
45
+
46
+ - [ ] Add `scripts/bootstrap_comfy.py`.
47
+ - [ ] Add `scripts/run_comfy.py`.
48
+ - [ ] Add `scripts/workflow_client.py`.
49
+ - [ ] Install or prepare ComfyUI on Space startup.
50
+ - [ ] Install custom node dependencies.
51
+ - [ ] Verify ComfyUI can start locally in the Space.
52
+ - [ ] Verify ComfyUI API endpoints are reachable:
53
+ - [ ] `/system_stats`
54
+ - [ ] `/upload/image` or the audio upload equivalent used by `LoadAudio`
55
+ - [ ] `/prompt`
56
+ - [ ] `/history/{prompt_id}`
57
+
58
+ ## Phase 4: Workflow Parameterization
59
+
60
+ - [ ] Replace node `16` `LoadAudio.inputs.audio` with the uploaded audio file.
61
+ - [ ] Replace node `105` `api_key` with `DEEPSEEK_API_KEY` from Space secrets.
62
+ - [ ] Parameterize node `105` `api_baseurl`.
63
+ - [ ] Parameterize node `105` `model`.
64
+ - [ ] Parameterize node `110` target language.
65
+ - [ ] Add unique job-specific output prefixes for node `180` and node `214`.
66
+ - [ ] Decide which user controls are exposed first:
67
+ - [ ] source language
68
+ - [ ] target language
69
+ - [ ] LLM model
70
+ - [ ] max input duration
71
+ - [ ] keep or drop background audio
72
+ - [ ] Remove or ignore display-only `easy showAnything` nodes if they are not
73
+ needed for API execution.
74
+
75
+ ## Phase 5: Gradio Interface
76
+
77
+ - [ ] Replace the placeholder `app.py` with the first VoiceGate interface.
78
+ - [ ] Add short audio upload input.
79
+ - [ ] Add target language input.
80
+ - [ ] Add status/log output.
81
+ - [ ] Add generated audio output.
82
+ - [ ] Add generated SRT file outputs.
83
+ - [ ] Wrap GPU-heavy execution with `@spaces.GPU(duration=...)`.
84
+ - [ ] Add guardrails for file type and duration.
85
+
86
+ ## Phase 6: Minimal Runtime Tests
87
+
88
+ - [ ] Start Space and confirm Gradio loads.
89
+ - [ ] Start ComfyUI from the Space process.
90
+ - [ ] Submit a minimal prompt to ComfyUI and receive a response.
91
+ - [ ] Run a tiny TTS-only workflow.
92
+ - [ ] Run a short ASR-only workflow.
93
+ - [ ] Run SRT split -> VoxCPM -> SRT merge.
94
+ - [ ] Run the full short-audio VoiceGate workflow.
95
+ - [ ] Confirm output audio and SRT files are downloadable from Gradio.
96
+
97
+ ## Phase 7: Full VoiceGate Path
98
+
99
+ - [ ] Add video input support after the audio path is stable.
100
+ - [ ] Extract audio from video with `ffmpeg`.
101
+ - [ ] Merge generated audio back into the original video if required.
102
+ - [ ] Add subtitle download and optional subtitle burn-in.
103
+ - [ ] Add examples with small sample files, if allowed by Space storage limits.
104
+
105
+ ## Open Questions
106
+
107
+ - [ ] Which exact node repository provides `RH_LLMAPI_NODE`?
108
+ - [ ] Which exact node repository provides `RunningHub_VoxCPM_*`?
109
+ - [ ] Is `flash_attention_2` available and reliable in the ZeroGPU environment?
110
+ - [ ] Does VoxCPM2 fit comfortably in ZeroGPU memory with ASR and
111
+ MelBandRoFormer in the same run?
112
+ - [ ] Should the first public demo disable background separation to reduce
113
+ runtime and memory pressure?
114
+ - [ ] What maximum uploaded audio/video duration should the first version allow?
workflows/voicegate_api.json ADDED
@@ -0,0 +1,375 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "16": {
3
+ "inputs": {
4
+ "audio": "fcecb7fd3827851a4fb22c52886610aed0a62e5fe32ea46f3b1291ff3dd236ab.mp3",
5
+ "audioUI": ""
6
+ },
7
+ "class_type": "LoadAudio",
8
+ "_meta": {
9
+ "title": "输入原音频"
10
+ }
11
+ },
12
+ "31": {
13
+ "inputs": {
14
+ "repo_id": "Qwen/Qwen3-ASR-1.7B",
15
+ "precision": "bf16",
16
+ "attention": "flash_attention_2",
17
+ "max_new_tokens": 1024,
18
+ "forced_aligner": "Qwen/Qwen3-ForcedAligner-0.6B"
19
+ },
20
+ "class_type": "VoiceBridgeASRLoader",
21
+ "_meta": {
22
+ "title": "VoiceBridge ASR Loader"
23
+ }
24
+ },
25
+ "33": {
26
+ "inputs": {
27
+ "language": "auto",
28
+ "context": "",
29
+ "return_timestamps": true,
30
+ "model_key": [
31
+ "31",
32
+ 0
33
+ ],
34
+ "audio": [
35
+ "99",
36
+ 0
37
+ ]
38
+ },
39
+ "class_type": "VoiceBridgeASRTranscribe",
40
+ "_meta": {
41
+ "title": "VoiceBridge ASR Transcribe"
42
+ }
43
+ },
44
+ "36": {
45
+ "inputs": {
46
+ "text": [
47
+ "33",
48
+ 1
49
+ ],
50
+ "language": [
51
+ "33",
52
+ 2
53
+ ],
54
+ "save_srt": true,
55
+ "filename_prefix": "VoiceBridge/subtitle",
56
+ "forced_aligns": [
57
+ "33",
58
+ 0
59
+ ]
60
+ },
61
+ "class_type": "GenerateSRT",
62
+ "_meta": {
63
+ "title": "Generate SRT"
64
+ }
65
+ },
66
+ "45": {
67
+ "inputs": {
68
+ "language": "auto",
69
+ "context": "",
70
+ "return_timestamps": false,
71
+ "model_key": [
72
+ "31",
73
+ 0
74
+ ],
75
+ "audio": [
76
+ "46",
77
+ 0
78
+ ]
79
+ },
80
+ "class_type": "VoiceBridgeASRTranscribe",
81
+ "_meta": {
82
+ "title": "VoiceBridge ASR Transcribe"
83
+ }
84
+ },
85
+ "46": {
86
+ "inputs": {
87
+ "start_index": 0,
88
+ "duration": 10.000000000000002,
89
+ "audio": [
90
+ "99",
91
+ 0
92
+ ]
93
+ },
94
+ "class_type": "TrimAudioDuration",
95
+ "_meta": {
96
+ "title": "Trim Audio Duration"
97
+ }
98
+ },
99
+ "61": {
100
+ "inputs": {
101
+ "text": "1\n00:00:00,000 --> 00:00:04,000\n我相信你在各种内容下面应该都见过这样一句类似的评论\n\n2\n00:00:04,240 --> 00:00:04,960\n那几个月之前\n\n3\n00:00:04,960 --> 00:00:06,879\n其实大家把这个当成一种调侃了\n\n4\n00:00:06,879 --> 00:00:07,679\n是一种梗\n\n5\n00:00:07,679 --> 00:00:07,919\n对吧\n\n6\n00:00:08,160 --> 00:00:09,359\n你看到太离谱的东西\n\n7\n00:00:09,439 --> 00:00:10,320\n你会说\n\n8\n00:00:10,320 --> 00:00:10,800\n“哎呀\n\n9\n00:00:10,800 --> 00:00:12,560\n这是AI或者AI太好用了\n\n10\n00:00:12,560 --> 00:00:12,960\n家人\n\n11\n00:00:13,359 --> 00:00:14,240\n”但有意思的就是\n\n12\n00:00:14,240 --> 00:00:15,359\n只过了短短几个月\n\n13\n00:00:15,519 --> 00:00:19,519\n你会发现现在这句“这是AI嘛”背后的情绪它变化了\n\n14\n00:00:19,839 --> 00:00:21,280\n因为AI它又变强了\n\n",
102
+ "anything": [
103
+ "36",
104
+ 0
105
+ ]
106
+ },
107
+ "class_type": "easy showAnything",
108
+ "_meta": {
109
+ "title": "Show Any"
110
+ }
111
+ },
112
+ "96": {
113
+ "inputs": {
114
+ "model_name": "MelBandRoFormer_comfy/MelBandRoformer_fp32.safetensors"
115
+ },
116
+ "class_type": "MelBandRoFormerModelLoader",
117
+ "_meta": {
118
+ "title": "Mel-Band RoFormer Model Loader"
119
+ }
120
+ },
121
+ "99": {
122
+ "inputs": {
123
+ "model": [
124
+ "96",
125
+ 0
126
+ ],
127
+ "audio": [
128
+ "16",
129
+ 0
130
+ ]
131
+ },
132
+ "class_type": "MelBandRoFormerSampler",
133
+ "_meta": {
134
+ "title": "Mel-Band RoFormer Sampler"
135
+ }
136
+ },
137
+ "105": {
138
+ "inputs": {
139
+ "api_baseurl": "https://api.deepseek.com",
140
+ "api_key": "",
141
+ "model": "deepseek-v4-flash",
142
+ "role": [
143
+ "109",
144
+ 0
145
+ ],
146
+ "prompt": [
147
+ "36",
148
+ 0
149
+ ],
150
+ "temperature": 0.5,
151
+ "seed": 1761935326
152
+ },
153
+ "class_type": "RH_LLMAPI_NODE",
154
+ "_meta": {
155
+ "title": "Runninghub LLM API Node"
156
+ }
157
+ },
158
+ "107": {
159
+ "inputs": {
160
+ "text": "1\n00:00:00,000 --> 00:00:04,000\nI bet you've seen a comment like this under all kinds of content.\n\n2\n00:00:04,240 --> 00:00:04,960\nA few months ago,\n\n3\n00:00:04,960 --> 00:00:06,879\neveryone used it as a joke.\n\n4\n00:00:06,879 --> 00:00:07,679\nIt was a meme.\n\n5\n00:00:07,679 --> 00:00:07,919\nRight?\n\n6\n00:00:08,160 --> 00:00:09,359\nYou see something absurd.\n\n7\n00:00:09,439 --> 00:00:10,320\nYou'd say,\n\n8\n00:00:10,320 --> 00:00:10,800\n\"Ah,\n\n9\n00:00:10,800 --> 00:00:12,560\nmust be AI, or AI is too good.\n\n10\n00:00:12,560 --> 00:00:12,960\nBro.\"\n\n11\n00:00:13,359 --> 00:00:14,240\nBut the interesting thing is,\n\n12\n00:00:14,240 --> 00:00:15,359\njust a few months later,\n\n13\n00:00:15,519 --> 00:00:19,519\nnow the emotion behind \"Is this AI?\" has changed.\n\n14\n00:00:19,839 --> 00:00:21,280\nBecause AI has gotten even stronger.",
161
+ "anything": [
162
+ "105",
163
+ 0
164
+ ]
165
+ },
166
+ "class_type": "easy showAnything",
167
+ "_meta": {
168
+ "title": "Show Any"
169
+ }
170
+ },
171
+ "108": {
172
+ "inputs": {
173
+ "text": "You are a professional subtitle translator. Please translate all the subtitles in this SRT file into natural, spoken [Language]. Keep each timestamp exactly the same. For each subtitle line, use the shortest possible phrasing that still captures the original meaning (it doesn't have to be a direct translation, just convey the correct idea). Output the content directly in SRT format, without any explanation or descriptive text."
174
+ },
175
+ "class_type": "CR Text",
176
+ "_meta": {
177
+ "title": "🔤 CR Text"
178
+ }
179
+ },
180
+ "109": {
181
+ "inputs": {
182
+ "texts": [
183
+ "108",
184
+ 0
185
+ ],
186
+ "find": "[Language]",
187
+ "replace": [
188
+ "110",
189
+ 0
190
+ ]
191
+ },
192
+ "class_type": "ReplaceText",
193
+ "_meta": {
194
+ "title": "Replace Text (DEPRECATED)"
195
+ }
196
+ },
197
+ "110": {
198
+ "inputs": {
199
+ "value": "English"
200
+ },
201
+ "class_type": "easy string",
202
+ "_meta": {
203
+ "title": "输入目标语言"
204
+ }
205
+ },
206
+ "176": {
207
+ "inputs": {
208
+ "tempo_limit": 2,
209
+ "mini_gap_ms": 10,
210
+ "srt_items": [
211
+ "177",
212
+ 1
213
+ ],
214
+ "audios": [
215
+ "268",
216
+ 0
217
+ ]
218
+ },
219
+ "class_type": "VoiceBridgeAudioListMergerBySRT",
220
+ "_meta": {
221
+ "title": "VoiceBridge Audio List Merger by SRT"
222
+ }
223
+ },
224
+ "177": {
225
+ "inputs": {
226
+ "srt_string": [
227
+ "105",
228
+ 0
229
+ ]
230
+ },
231
+ "class_type": "VoiceBridgeSRTSplitter",
232
+ "_meta": {
233
+ "title": "VoiceBridge SRT Splitter"
234
+ }
235
+ },
236
+ "179": {
237
+ "inputs": {
238
+ "text": "1\n00:00:00,000 --> 00:00:03,540\nI bet you've seen a comment like this under all kinds of content.\n\n2\n00:00:03,550 --> 00:00:04,681\nA few months ago,\n\n3\n00:00:04,960 --> 00:00:06,851\neveryone used it as a joke.\n\n4\n00:00:06,861 --> 00:00:07,835\nIt was a meme.\n\n5\n00:00:07,845 --> 00:00:08,400\nRight?\n\n6\n00:00:08,410 --> 00:00:09,683\nYou see something absurd.\n\n7\n00:00:09,693 --> 00:00:10,536\nYou'd say,\n\n8\n00:00:10,546 --> 00:00:10,996\n\"Ah,\n\n9\n00:00:11,006 --> 00:00:13,018\nmust be AI, or AI is too good.\n\n10\n00:00:13,028 --> 00:00:13,837\nBro.\"\n\n11\n00:00:13,847 --> 00:00:14,700\nBut the interesting thing is,\n\n12\n00:00:14,710 --> 00:00:15,946\njust a few months later,\n\n13\n00:00:15,956 --> 00:00:20,245\nnow the emotion behind \"Is this AI?\" has changed.\n\n14\n00:00:20,255 --> 00:00:23,795\nBecause AI has gotten even stronger.\n",
239
+ "anything": [
240
+ "176",
241
+ 1
242
+ ]
243
+ },
244
+ "class_type": "easy showAnything",
245
+ "_meta": {
246
+ "title": "Show Any"
247
+ }
248
+ },
249
+ "180": {
250
+ "inputs": {
251
+ "filename_prefix": "audio/ComfyUI",
252
+ "quality": "V0",
253
+ "audioUI": "",
254
+ "audio": [
255
+ "251",
256
+ 0
257
+ ]
258
+ },
259
+ "class_type": "SaveAudioMP3",
260
+ "_meta": {
261
+ "title": "Save Audio (MP3)"
262
+ }
263
+ },
264
+ "206": {
265
+ "inputs": {
266
+ "control_instruction": "",
267
+ "text": [
268
+ "177",
269
+ 0
270
+ ],
271
+ "cfg_value": 2,
272
+ "inference_steps": 10,
273
+ "seed": 220751697769047,
274
+ "ultimate_clone": true,
275
+ "reference_audio_text": [
276
+ "264",
277
+ 0
278
+ ],
279
+ "normalize_text": false,
280
+ "denoise_reference": false,
281
+ "max_len": 4096,
282
+ "retry_badcase": true,
283
+ "model": [
284
+ "207",
285
+ 0
286
+ ],
287
+ "reference_audio": [
288
+ "261",
289
+ 0
290
+ ]
291
+ },
292
+ "class_type": "RunningHub_VoxCPM_Generate",
293
+ "_meta": {
294
+ "title": "RunningHub VoxCPM Generate Speech"
295
+ }
296
+ },
297
+ "207": {
298
+ "inputs": {
299
+ "model_name": "VoxCPM2",
300
+ "optimize": false,
301
+ "lora_name": "None"
302
+ },
303
+ "class_type": "RunningHub_VoxCPM_LoadModel",
304
+ "_meta": {
305
+ "title": "RunningHub VoxCPM Load Model"
306
+ }
307
+ },
308
+ "214": {
309
+ "inputs": {
310
+ "srt_string": [
311
+ "179",
312
+ 0
313
+ ],
314
+ "filename_prefix": "VoiceBridge/subtitle"
315
+ },
316
+ "class_type": "SaveSRTFromString",
317
+ "_meta": {
318
+ "title": "Save SRT From String"
319
+ }
320
+ },
321
+ "251": {
322
+ "inputs": {
323
+ "audio_1": [
324
+ "176",
325
+ 0
326
+ ],
327
+ "audio_2": [
328
+ "99",
329
+ 1
330
+ ]
331
+ },
332
+ "class_type": "MergeAudioMW",
333
+ "_meta": {
334
+ "title": "Merge Audio"
335
+ }
336
+ },
337
+ "261": {
338
+ "inputs": {
339
+ "any_01": [
340
+ "46",
341
+ 0
342
+ ]
343
+ },
344
+ "class_type": "Any Switch (rgthree)",
345
+ "_meta": {
346
+ "title": "Any Switch (rgthree)"
347
+ }
348
+ },
349
+ "264": {
350
+ "inputs": {
351
+ "any_01": [
352
+ "45",
353
+ 1
354
+ ]
355
+ },
356
+ "class_type": "Any Switch (rgthree)",
357
+ "_meta": {
358
+ "title": "Any Switch (rgthree)"
359
+ }
360
+ },
361
+ "268": {
362
+ "inputs": {
363
+ "start_index": 0.30000000000000004,
364
+ "duration": 100.00000000000001,
365
+ "audio": [
366
+ "206",
367
+ 0
368
+ ]
369
+ },
370
+ "class_type": "TrimAudioDuration",
371
+ "_meta": {
372
+ "title": "Trim Audio Duration"
373
+ }
374
+ }
375
+ }
workflows/voicegate_ui.json ADDED
The diff for this file is too large to render. See raw diff