Spaces:
Sleeping
Sleeping
| import json, uuid, time, requests, pathlib | |
| from typing import Optional | |
| from rich.console import Console | |
| from log_config import logger | |
| console = Console() | |
| def run_audio_workflow( | |
| server: str = "http://127.0.0.1:8188", | |
| workflow_path: str = "comfyui_workflows/stable_audio.json", | |
| prefix: str = "", | |
| positive: Optional[str] = None, | |
| negative: Optional[str] = None, | |
| steps: Optional[int] = None, | |
| seed: Optional[int] = None, | |
| duration: Optional[float] = None, | |
| save_node_id: str = "18", | |
| timeout: int = 300, | |
| ) -> Optional[pathlib.Path]: | |
| """根据提供的 ComfyUI workflow 生成音频 | |
| Parameters | |
| ---------- | |
| server: ComfyUI 后端地址 | |
| workflow_path: ComfyUI 导出的 workflow JSON 路径 | |
| prefix: 输出目录前缀 | |
| positive: 正面提示词 | |
| negative: 负面提示词 | |
| steps: 采样步数 | |
| seed: 随机种子 | |
| duration: 音频时长,单位秒 | |
| save_node_id: 保存节点 ID(默认18,对应 SaveAudio),用于从 history 中解析文件名 | |
| timeout: 轮询超时时间,单位秒 | |
| """ | |
| wf: dict = json.loads(pathlib.Path(workflow_path).read_text(encoding="utf-8")) | |
| # 参数注入 | |
| if positive is not None: | |
| wf["6"]["inputs"]["text"] = positive | |
| if negative is not None: | |
| wf["7"]["inputs"]["text"] = negative | |
| if steps is not None: | |
| wf["3"]["inputs"]["steps"] = steps | |
| if seed is not None: | |
| wf["3"]["inputs"]["seed"] = seed | |
| if duration is not None: | |
| wf["11"]["inputs"]["seconds"] = duration | |
| client_id = str(uuid.uuid4()) | |
| payload = {"prompt": wf, "client_id": client_id} | |
| try: | |
| resp = requests.post(f"{server}/prompt", json=payload, timeout=30) | |
| result = resp.json() | |
| logger.debug("ComfyUI /prompt 返回:\n{}", json.dumps(result, indent=2, ensure_ascii=False)) | |
| if "error" in result: | |
| logger.error("ComfyUI /prompt 接口报错,流程终止!") | |
| return None | |
| prompt_id = result["prompt_id"] | |
| except Exception as e: | |
| logger.error(f"提交 /prompt 失败:{e}") | |
| return None | |
| # 轮询生成状态 | |
| t0 = time.time() | |
| outputs = None | |
| with console.status("[bold cyan]ComfyUI 正在生成,请稍候…[/]", spinner="dots"): | |
| while True: | |
| try: | |
| hist = requests.get(f"{server}/history/{prompt_id}", timeout=30).json() | |
| if hist: | |
| if "error" in hist: | |
| msg = "ComfyUI /history 报错,流程终止" | |
| console.print(f"[red][b]{msg}[/b][/red]") | |
| logger.error(msg) | |
| return None | |
| if prompt_id in hist and hist[prompt_id].get("status", {}).get("status_str") == "success": | |
| outputs = hist[prompt_id].get("outputs") | |
| elapsed = time.time() - t0 | |
| msg = f"ComfyUI 音频生成成功!耗时 {elapsed:.1f} 秒" | |
| console.print(f"[green][b]{msg}[/b][/green]") | |
| logger.info(msg) | |
| break | |
| if time.time() - t0 > timeout: | |
| msg = "ComfyUI 生成超时" | |
| console.print(f"[red]{msg}[/red]") | |
| logger.error(msg) | |
| return None | |
| time.sleep(0.5) | |
| except Exception as e: | |
| logger.warning(f"轮询状态时出错: {e},继续等待...") | |
| console.print(f"[yellow]轮询状态时出错: {e},继续等待...[/yellow]") | |
| time.sleep(0.5) | |
| # 获取音频文件名 | |
| fname = None | |
| logger.debug(outputs) | |
| if isinstance(outputs, dict): | |
| node = outputs.get(str(save_node_id)) | |
| if node: | |
| if isinstance(node, dict): | |
| if "audio" in node and node["audio"]: | |
| item = node["audio"][0] | |
| if isinstance(item, dict) and "filename" in item: | |
| fname = item["filename"] | |
| elif "filename" in node: | |
| fname = node["filename"] | |
| if not fname: | |
| logger.error("未找到输出文件名,请检查 outputs 字段实际内容!") | |
| return None | |
| try: | |
| audio_bytes = requests.get(f"{server}/view?filename={fname}&type=output&subfolder=audio", timeout=60).content | |
| out_dir = pathlib.Path("outputs") / prefix / "audio" | |
| out_dir.mkdir(exist_ok=True, parents=True) | |
| out_path = out_dir / pathlib.Path(fname).name | |
| out_path.write_bytes(audio_bytes) | |
| logger.info(f"音频已保存到:{out_path}") | |
| return out_path | |
| except Exception as e: | |
| logger.error(f"音频下载失败:{e}") | |
| return None | |
| if __name__ == "__main__": | |
| logger.info("=== 音频生成示例 ===") | |
| audio_result = run_audio_workflow( | |
| prefix="demo", | |
| workflow_path="comfyui_workflows/stable_audio.json", | |
| positive="heaven church electronic dance music", | |
| negative="", | |
| steps=50, | |
| seed=657172215808422, | |
| duration=60.0, | |
| save_node_id="18", | |
| ) | |
| if audio_result: | |
| logger.info(f"音频生成完成!结果保存在:{audio_result}") | |
| else: | |
| logger.error("音频生成失败!") | |