File size: 12,544 Bytes
94a0de3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
c9b8b64
 
94a0de3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5d6dcc3
 
94a0de3
 
 
 
 
 
 
 
d443689
94a0de3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5d6dcc3
 
 
d443689
f135496
 
 
d443689
 
 
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
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
# 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。