# API、MCP 与 Agent 调用 API 与 UI 共用同一任务实现,不能通过 API 绕开配置、上传、资源或 GPU 时限。启动后点击 Gradio 底部「Use via API」查看当前服务器生成的权威接口说明。任务 ID 是访问凭据,返回的文件 URL 也不应公开。 ## 端点约定 使用 `gradio_client.Client.predict(..., api_name="/端点名")` 调用。服务端函数返回 JSON 并不代表业务成功,必须同时检查 `status`、`error`、`remaining_frames`;导出还应检查 `export_complete` / `export_error`。 | API 名称 | 输入顺序 | 返回 | | --- | --- | --- | | `/environment_info` | 无 | 环境版本、ZeroGPU 标志、FFmpeg 可用性;不申请 GPU | | `/config_schema` | 无 | 允许字段、默认值与校验限制的 JSON Schema | | `/gpu_self_test` | 无 | `(report, files, image)`;真实小场景渲染,GPU 模式必须检查 `gpu_verified` | | `/prepare_job` | `files`, `config_json`, `config_file` | `(job_id, status)`;`config_file` 可为 null,非空时优先 | | `/inspect_job` | `job_id` | 状态与 `inspection`,包括场景/相机/`missing_assets` | | `/render_chunk` | `job_id` | 新状态;最多处理配置中的 `batch_size` 帧 | | `/job_status` | `job_id` | 当前状态与完成帧列表;不等待 Blender 队列 | | `/cancel_job` | `job_id` | 请求停止并保留完成帧;不等待 Blender 队列 | | `/resume_job` | `job_id` | 清除取消标记、验证已完成帧;不会启动渲染 | | `/finalize_job` | `job_id` | `(summary, files, image, video)`;部分结果也可导出,视频需完整帧 | `render_chunk` 使用队列并等待当前批次结束;客户端不应把多个批次并行提交。`job_status` 适合进度查看,轮询本身不会推进渲染。`prepare_job` 冻结配置,恢复沿用原配置;需要修改时创建新任务。 ## 完整命令行客户端 ```bash python -m pip install "gradio_client>=2.0,<3" python examples/client_render.py --space YOUR_NAME/YOUR_SPACE --project project.zip --config examples/video.json --output outputs --self-test ``` 脚本会上传本地文件、保存 ID、检查资源、串行渲染、检查每批 `error`,再调用导出并把文件复制到 `outputs`。所有进度为 JSON 行,便于 agent 解析。新建任务若发现已有任务文件会停止,避免不小心重复上传渲染。 | 参数 | 含义 | | --- | --- | | `--space` | 必需;`用户名/Space名` 或 Gradio 根 URL | | `--project` | 新任务必需;一个 ZIP 或多个本机文件路径 | | `--config` | 新任务必需;本机 JSON 配置路径 | | `--output` | 下载目录,默认 `outputs` | | `--job-file` | 任务凭据保存位置,默认 `OUTPUT/render-job.json` | | `--resume-job [ID]` | 有 ID 时恢复它;省略 ID 时从任务文件恢复 | | `--inspect` / `--inspect-only` | 上传/恢复后只检查,不开始渲染 | | `--max-batches N` | 本次最多处理 N 批并导出;0 为直到完成 | | `--self-test` | 先运行真实小场景自检 | ```bash # 只检查,保留 ID;确认相机/资源后再续渲。 python examples/client_render.py --space YOUR_NAME/YOUR_SPACE --project project.zip --config examples/image.json --output image-result --inspect # 每次处理最多 5 批,下载阶段性结果。 python examples/client_render.py --space YOUR_NAME/YOUR_SPACE --resume-job --output image-result --max-batches 5 # 多个上传文件:复杂目录结构请优先使用 ZIP。 python examples/client_render.py --space YOUR_NAME/YOUR_SPACE --project scene.blend texture.png --config examples/image.json --output another-result ``` 脚本默认把缺失/被阻止的资源视为错误;若 JSON 明确设置 `strict_assets=false`,会输出警告信息并继续,渲染效果可能因此变化。退出码:0 为完成或主动达到批数上限/仅检查;1 为错误;130 为键盘中断。遇到配额和超时不会循环重试。 ## 身份验证 私有 Space 以及需要账号身份的调用,先在运行客户端的环境设置 `HF_TOKEN`。令牌须有访问该 Space 的权限。不要将令牌写到场景、JSON、MCP 示例文件或 git 仓库里。脚本从环境读取令牌并兼容新版 `token=` 与旧版 `hf_token=` 构造参数,不打印令牌。 本机 PowerShell 可交互读取并设置令牌: ```powershell $env:HF_TOKEN = Read-Host "HF Token" -MaskInput python examples/client_render.py --space YOUR_NAME/YOUR_SPACE --project project.zip --config examples/video.json --output outputs ``` `-MaskInput` 需要 PowerShell 7;其他环境可使用系统环境变量/密码管理器。平台的账号配额、访问和计费规则仍适用。 ## Python 最小闭环 以下代码可直接保存执行;将 Space ID 与本机路径改为实际值。部署目录自带客户端提供更完整的恢复、下载与错误处理。 ```python import inspect import json import os from pathlib import Path from gradio_client import Client, handle_file space = "YOUR_NAME/YOUR_SPACE" output = Path("outputs").resolve() output.mkdir(parents=True, exist_ok=True) auth_name = "token" if "token" in inspect.signature(Client).parameters else "hf_token" client = Client(space, download_files=str(output), httpx_kwargs={"timeout": 120}, **{auth_name: os.getenv("HF_TOKEN")}) config = Path("examples/image.json").read_text(encoding="utf-8-sig") job_id, status = client.predict( [handle_file("project.zip")], config, None, api_name="/prepare_job" ) # ID 要立即保存;不要因网络中断直接重复 prepare_job。 (output / "job-id.txt").write_text(job_id, encoding="utf-8") status = client.predict(job_id, api_name="/inspect_job") if status.get("error"): raise RuntimeError(status["error"]) missing = (status.get("inspection") or {}).get("missing_assets") or [] if missing and status.get("config", {}).get("strict_assets", True): raise RuntimeError(json.dumps(missing, ensure_ascii=False)) while status.get("remaining_frames"): before = status["completed_count"] status = client.predict(job_id, api_name="/render_chunk") print(status["completed_count"], "/", status["total_frames"]) if status.get("error"): # 先导出完成帧与日志,再终止;不要在配额不足时无限重试。 client.predict(job_id, api_name="/finalize_job") raise RuntimeError(status["error"]) if status["completed_count"] <= before: raise RuntimeError("没有完成新帧,停止自动重试。") summary, files, image, video = client.predict(job_id, api_name="/finalize_job") if not summary.get("export_complete"): raise RuntimeError(summary.get("export_error") or "输出未完整生成") print(json.dumps({"job_id": job_id, "files": files}, ensure_ascii=False)) ``` 客户端使用 `handle_file` 自动上传;不能直接把本机路径文本当作远端服务器文件。若想上传独立 JSON 文件: ```python job_id, status = client.predict( [handle_file("project.zip")], "{}", handle_file("examples/video.json"), api_name="/prepare_job", ) ``` ## 常用 JSON 配置字段 以下是本应用字段,与任意 Blender Python 属性不是一一透传关系。未列出的完整字段请查询 `/config_schema`。 | 字段 | 示例 / 范围 | 说明 | | --- | --- | --- | | `schema_version` | `1` | 配置协议版本 | | `blend_file` | `project/scene.blend` 或 null | 主工程的解压根目录相对路径 | | `mode` | `image` / `frames` / `video` | 单图、帧序列或视频 | | `scene` / `camera` / `view_layer` | 名称或 null | 指定 Blender 数据块;默认沿用场景设置 | | `width` / `height` | 16–8192 | 基础分辨率,受像素总量上限限制 | | `resolution_percentage` | 1–100 | 实际输出缩放比例 | | `engine` | `EEVEE` / `CYCLES` | 默认 Eevee | | `samples` | 1–4096 | Eevee 渲染采样数或 Cycles 最大采样数 | | `denoise` | true / false | 降噪 | | `adaptive_threshold` | 0.0–1.0 | 自适应采样阈值 | | `frame` | 正整数 | 单图帧号 | | `frame_start` / `frame_end` / `frame_step` | 正整数 | 动画帧范围与步长 | | `fps` | 1–120 | 时间基准;跳帧输出的播放帧率为 `fps/frame_step` | | `format` | `PNG` / `OPEN_EXR` | 视频模式只接受 PNG | | `color_depth` | 8 / 16 / 32 | PNG:8/16;EXR:16/32 | | `transparent` | true / false | 透明背景;MP4 不支持 | | `device` | `AUTO` / `CUDA` / `OPTIX` / `CPU` | 默认 AUTO;无需管理员切换。AUTO 请求 GPU,CUDA/OPTIX 仅适用 Cycles | | `batch_size` | 1–64 | 每次请求最多渲染帧数 | | `gpu_seconds` | 10–600 | ZeroGPU 请求预算;平台可能另有限制,不是时长保证 | | `cpu_timeout` | 10–7200 | 普通 GPU/CPU 子进程与编码超时 | | `strict_assets` | true / false | 默认缺失资源拒绝渲染 | | `video_crf` | 0–40 | 视频质量;通常 18,越小输出越大 | | `video_preset` | medium / fast / slow | FFmpeg 编码速度/压缩取舍 | `gpu_seconds` 是当前批次的预算,不是整个动画的预算。应用给子进程预留收尾时间,因此可用于 Blender 的时间略短。普通 GPU/CPU 模式使用 `cpu_timeout`,名称保留用于同一配置协议。 ## MCP 接入 本项目通过 `demo.launch(mcp_server=True)` 暴露工具,要求已安装 `gradio[mcp]`。使用 Streamable HTTP: ```json { "mcpServers": { "blender-render": { "type": "http", "url": "https://YOUR-SPACE-DOMAIN.hf.space/gradio_api/mcp/" } } } ``` 不同 MCP 客户端可能使用 `servers` 代替 `mcpServers`,或自行管理 `Authorization` 头/OAuth;请在客户端的安全凭据设置中添加认证。示例文件不硬编码令牌。工具名以 `tools/list` 实际发现结果为准;某些客户端会自动添加服务名前缀。 MCP 的 JSON 参数不能携带本机文件系统权限。可采用以下方式: 1. Agent 先用 `gradio_client` 或完整示例脚本上传本地文件并执行 `/prepare_job`,取得 job ID;后续全部使用 MCP 的检查、渲染、查询与导出工具。 2. MCP 客户端支持 Gradio 文件上传时,使用其上传功能得到有效文件引用。不能虚构服务器路径或简单传入本机绝对路径。 3. 有可访问的托管文件时,遵循服务器生成的 MCP 文件 schema 和客户端支持的 URL 上传流程。服务器必须可访问该 URL;本应用不提供任意 URL 代理或自定义下载器,也不会替 URL 补上私有存储的认证。 大文件和私有本机文件推荐第一种方式。返回的结果由 Gradio 表达为文件引用/下载地址,MCP 客户端能否自动下载取决于其文件支持能力;Python 客户端已处理鉴权下载。 HF 也提供 Hub MCP 集成;是否能直接添加某个私有 Space、如何传递用户身份,以其客户端及 Hub 当前能力为准。[HF 的 MCP 官方文档](https://huggingface.co/docs/hub/en/spaces-mcp-servers)、[Gradio MCP 指南](https://www.gradio.app/guides/building-mcp-server-with-gradio) ## 推荐 Agent 策略 先读取 `environment_info` 与 `config_schema`;首次部署调用 `gpu_self_test`。准备后立刻保存 ID,检查场景相机和缺失资产,再串行调用 `render_chunk`,每次都判断错误和完成帧增量。全部完成后 `finalize_job` 并核验输出。出现配额、超时或兼容性失败时停止自动重试、取回部分输出和日志,明确报告原因;修复后用相同 ID 恢复,若修改工程或配置则新建任务。 ## 1.1.0 默认模式 空配置 `{}` 选择 `engine=EEVEE, device=AUTO`,请求 GPU 图形渲染。CPU 为可选模式,使用 Mesa 软件 OpenGL。`cpu_self_test` 无参数,返回真实 CPU Eevee 自检结果、日志与图片;`gpu_self_test` 明确测试 Cycles GPU。ZeroGPU 不保证提供 Eevee 所需硬件 EGL/OpenGL;Eevee GPU 检测到软件驱动会报错。已有旧任务按 Cycles 续渲,新任务使用新默认。 ## 1.1.1 GPU Eevee 检测 `eevee_gpu_self_test(gpu_size="large", graphics_backend="opengl")` 支持 `large` / `xlarge` 与 `opengl` / `vulkan`,返回 `(report, files, image)`;会显式申请一次 GPU,使用 Eevee 实际渲染小场景。`gpu_eevee_usable=true` 表示通过。GPU 计算可用不代表 GPU 图形接口可用,失败保留完整诊断;CPU 渲染不调用此接口;xlarge 消耗两倍配额。 `gpu_size` 默认 `large`,可选 `xlarge`,只影响 ZeroGPU 租约。`graphics_backend` 默认 `opengl`,可选 `vulkan`,只作用于 GPU + Eevee。