Creative Lab Fidget Pixel API
通过两个阶段将一张照片转换为可 3D 打印的多彩像素艺术指尖玩具板。原型任务会将照片转换为像素艺术图像。构建任务会将该图像转换为相互咬合的零件,并整合到单个 3MF 文件中,同时将原型任务的 ID 作为 input_task_id。
POST /openapi/creative-lab/fidget-pixel/v1/prototypePOST /openapi/creative-lab/fidget-pixel/v1/build
这两个 POST endpoint 都需要付费套餐。免费套餐账户发起的请求将返回 402。
创建 Fidget Pixel 原型任务
从一张照片生成一张像素画图像。要构建部件,请将此任务的 ID 作为 input_task_id 传给构建 endpoint。关于任务字段的说明,请参阅 Fidget Pixel 原型任务对象。
如果你不喜欢生成的图像,可以再创建一个原型任务。每个任务都会单独计费。
Request
# Stage 1: pixelize the source photo
curl https://api.meshy.ai/openapi/creative-lab/fidget-pixel/v1/prototype \
-X POST \
-H "Authorization: Bearer ${YOUR_API_KEY}" \
-H 'Content-Type: application/json' \
-d '{
"image_url": "<your publicly accessible image url or base64-encoded data URI>",
"type": "person"
}'
Response
{
"result": "019c4a1e-2b7d-7d03-8f6a-5c2e91f0a1b7"
}
参数
- Name
- image_url
- Type
- string
- 必选
- Description
要转换成像素画的照片,可以是公开可访问的 URL,或 data URI(
data:image/jpeg;base64,<your base64-encoded image data>)。图像必须是 JPG、JPEG、PNG 或 WebP 文件,且大小不超过 20 MB。Meshy 会根据图像数据来检测格式,而不是依据 URL 中的文件扩展名。没有扩展名的 URL 也可以正常工作,并且 Meshy 会跟随重定向。
- Name
- type
- Type
- string
- 必选
- Description
照片所展示的内容,决定了像素画的风格。这两种风格看起来有明显区别。传入其他任何值都会返回
400。可用取值:
person:人物,可以是肖像照或全身照。Meshy 会绘制 Q 版风格的像素精灵。other:其他任何主体,例如宠物、物品、吉祥物、徽标或风景。Meshy 会绘制拼豆风格的像素图标。
- Name
- name
- Type
- string
- Description
任务名称,最多 100 个字符。该名称会在任务的
name字段中返回。名称过长会返回400。
返回值
result 字段保存新建原型任务的 ID。获取该任务或对其进行流式获取,直到 status 变为 SUCCEEDED。然后将该 ID 作为 input_task_id 传给构建 endpoint。
失败情况
- Name
400 - Bad Request- Description
请求无法执行。例如:
- 缺少
image_url或type。 type既不是person也不是other。- 图像不是 JPG、JPEG、PNG 或 WebP 文件。
- 图像太小、超过 20 MB,或超过最大像素数。
- Meshy 无法下载该图像,例如因为该 URL 返回
404或请求超时。 - data URI 不是有效的 base64 编码。
- 该图像被标记为 NSFW(不适宜工作场合内容)。
错误消息会说明具体发现了什么问题。修正请求后重新发送。
- 缺少
- Name
401 - Unauthorized- Description
API key 缺失或无效。请检查
Authorization请求头。
- Name
402 - Payment Required- Description
以下情况之一适用:
- 账户没有足够的积分。
- API key、workspace 或成员已达到其积分限额。
- 账户处于免费套餐。
请检查你的积分和套餐,然后重试。
- Name
403 - Forbidden- Description
你的团队已开启IP Filtering(知识产权过滤),Meshy 将该图像标记为涉及第三方知识产权。请发送你拥有使用权的图像。
- Name
429 - Too Many Requests- Description
达到了以下限制之一:
- 你发送的请求数超过了速率限制所允许的数量。请等待几秒钟后重试。参阅速率限制。
- 你排队中或正在运行的任务过多。请等待部分任务完成后再重试。
- 在没有积分的无限量套餐下,你已达到可在无积分情况下运行的任务数量上限。请等待某个任务完成,或增加积分。
- Name
500 - Internal Server Error- Description
Meshy 遇到了服务器错误,例如无法对图像运行知识产权检查。Meshy 不会创建该任务,并会退还已扣除的所有积分。请重试该请求。
创建 Fidget Pixel 构建任务
根据一个成功的原型任务生成可用于 3D 打印的拼块。Meshy 会将像素艺术图像采样到网格上,并将其压缩为最多 color_count 种颜色。主体的每个单元格都会变成一个互锁的拼块,背景则不会被打印。
结果是一个单一的多色 3MF 文件,可直接彩色打印。每个拼块都有灰色的主体和与其像素颜色相同的顶部。关于其字段,参见 Fidget Pixel 构建任务对象。
Request
# Stage 2: chain build off a succeeded prototype task
curl https://api.meshy.ai/openapi/creative-lab/fidget-pixel/v1/build \
-X POST \
-H "Authorization: Bearer ${YOUR_API_KEY}" \
-H 'Content-Type: application/json' \
-d '{
"input_task_id": "019c4a1e-2b7d-7d03-8f6a-5c2e91f0a1b7",
"options": {
"shape": "square",
"grid_size": 32,
"piece_size_mm": 8,
"color_count": 8,
"piece_height_mm": 15
},
"output": {
"format": "3mf"
}
}'
Response
{
"result": "019c4a2f-6e81-7b44-9a1d-0d7f3c5e2b98"
}
参数
- Name
- input_task_id
- Type
- string
- 必选
- Description
要构建的原型任务的 ID。它必须是你的账户使用
POST /openapi/creative-lab/fidget-pixel/v1/prototype创建的任务,且状态为SUCCEEDED。如果该 ID 不是你通过 API 创建的 Fidget Pixel 原型任务之一,将返回
404,这也包括在 Web App 中创建的原型。
- Name
- name
- Type
- string
- Description
任务的名称,最多 100 个字符。它会在任务的
name字段中返回。更长的名称会返回400。
options
拼块形状和尺寸的设置。每个字段都有默认值,因此只需发送你想更改的字段。0 表示使用该字段的默认值。这些设置与 Creative Lab Web App 中的设置相同。其他形状设置是固定的,Meshy 会根据 shape 和 piece_size_mm 来设置它们。
- Name
- shape
- Type
- string
- 默认值 square
- Description
每个拼块的外形。任何其他值都会返回
400。可用值:
square: 方形网格上的方形拼块hex: 六边形网格上的六边形拼块,此时piece_size_mm需设置为6或8
- Name
- grid_size
- Type
- integer
- 默认值 32
- Description
棋盘每边的网格单元数,
16或32。任何其他值都会返回400。32网格能保留更多细节。16网格生成的拼块数量更少,但尺寸相同,因此棋盘的宽度约为一半。
- Name
- piece_size_mm
- Type
- integer
- 默认值 8
- Description
每个拼块的边长(毫米),
6、8或10。任何其他值都会返回400。结合grid_size,它决定了打印出的棋盘尺寸。例如,一个32网格、边长 8 毫米的拼块组成的棋盘,每边约为 26.5 厘米。10不能与hex一起使用,会返回400,因为在大多数消费级 FDM 打印机上,倾斜的六边形面会出现悬空问题。
- Name
- color_count
- Type
- integer
- 默认值 8
- Description
像素艺术调色板中的最大颜色数,范围从
1到8。超出该范围的值会返回400。打印时,你最多需要color_count加一种耗材,每种颜色一种,再加一种用于灰色主体。
- Name
- piece_height_mm
- Type
- integer
- 默认值 15
- Description
每个拼块的高度(毫米),范围从
10到80。超出该范围的值会返回400。
output
结果文件的设置。
- Name
- format
- Type
- string
- 默认值 3mf
- Description
结果的文件格式。任何其他值都会返回
400。可用值:
3mf: 一个多色model.3mf文件,在model_urls.3mf中返回
返回值
result 字段保存新构建任务的 ID。获取任务或对其进行流式获取,直到 status 为 SUCCEEDED。然后从 model_urls.3mf 下载 3MF 文件。
失败模式
- Name
400 - Bad Request- Description
请求无法运行。例如:
input_task_id缺失或不是有效的任务 ID。- 原型任务的状态不是
SUCCEEDED。如果它仍在运行,请等待后重试。如果它失败或被取消,请创建一个新的原型任务。 - 原型任务成功了,但没有图像。请创建一个新的原型任务。
- 某个
options字段超出了其允许的值范围,例如grid_size不是16或32。 piece_size_mm为10且shape为hex。六边形拼块仅支持 6 毫米和 8 毫米。output.format不是3mf。
错误消息会说明发现的具体问题。
- Name
401 - Unauthorized- Description
API key 缺失或无效。请检查
Authorization请求头。
- Name
402 - Payment Required- Description
以下情况之一适用:
- 账户的积分不足。
- API key、workspace 或成员已达到其积分限额。
- 账户处于免费方案。
请检查你的积分和方案,然后重试。
- Name
403 - Forbidden- Description
你的团队已开启IP 过滤,且 Meshy 将该原型任务的图像标记为涉及第三方知识产权。请使用你拥有使用权的图像创建原型任务。
- Name
404 - Not Found- Description
input_task_id与你的账户通过 API 创建的任何 Fidget Pixel 原型任务都不匹配。在 Web App 中创建的原型也会返回404。请发送原型创建响应中的resultID。
- Name
429 - Too Many Requests- Description
达到了以下某项限制:
- 你发送的请求数超过了速率限制所允许的数量。请等待几秒钟后重试。参见速率限制。
- 排队或正在运行的任务过多。请等待部分任务完成后重试。
- 在无限制方案下且没有剩余积分时,你达到了无需积分即可运行的任务数量上限。请等待某个任务完成,或增加积分。
- Name
500 - Internal Server Error- Description
Meshy 遇到了服务器错误,例如无法对原型任务的图像运行知识产权检查。Meshy 不会创建该任务,并会退还已收取的任何积分。请重试该请求。
获取 Fidget Pixel 任务
返回一个 prototype 或 build 任务。路径必须与任务所处的阶段相匹配。通过 /prototype/:id 请求的 build 任务会返回 404,通过 /build/:id 请求的 prototype 任务同样也会返回 404。
有关字段说明,请参阅 Fidget Pixel prototype 任务对象 和 Fidget Pixel build 任务对象。
Request
# Prototype
curl https://api.meshy.ai/openapi/creative-lab/fidget-pixel/v1/prototype/019c4a1e-2b7d-7d03-8f6a-5c2e91f0a1b7 \
-H "Authorization: Bearer ${YOUR_API_KEY}"
# Build
curl https://api.meshy.ai/openapi/creative-lab/fidget-pixel/v1/build/019c4a2f-6e81-7b44-9a1d-0d7f3c5e2b98 \
-H "Authorization: Bearer ${YOUR_API_KEY}"
Prototype Response
{
"id": "019c4a1e-2b7d-7d03-8f6a-5c2e91f0a1b7",
"type": "creative-lab-fidget-pixel-prototype",
"name": "",
"status": "SUCCEEDED",
"progress": 100,
"created_at": 1757001000000,
"started_at": 1757001005000,
"finished_at": 1757001178000,
"expires_at": 1757260378000,
"preceding_tasks": 0,
"task_error": null,
"consumed_credits": 6,
"image_urls": [
"https://assets.meshy.ai/***/pixel-art.jpg?Expires=***"
]
}
Build Response
{
"id": "019c4a2f-6e81-7b44-9a1d-0d7f3c5e2b98",
"type": "creative-lab-fidget-pixel-build",
"name": "",
"status": "SUCCEEDED",
"progress": 100,
"created_at": 1757001300000,
"started_at": 1757001304000,
"finished_at": 1757001309000,
"expires_at": 1757260509000,
"preceding_tasks": 0,
"task_error": null,
"consumed_credits": 30,
"model_urls": {
"3mf": "https://assets.meshy.ai/***/tasks/019c4a2f-6e81-7b44-9a1d-0d7f3c5e2b98/output/model.3mf?Expires=***"
}
}
参数
- Name
- id
- Type
- path
- Description
创建响应中返回的任务 ID。
返回值
与路径中阶段相匹配的 prototype 任务对象 或 build 任务对象。
失败模式
- Name
400 - Bad Request- Description
id不是有效的任务 ID。请发送创建响应中的resultID。
- Name
403 - Forbidden- Description
你的团队已开启 IP Filtering,且 Meshy 认定该 prototype 任务所用的图片涉及第三方知识产权问题。Build 任务以及 Enterprise 方案下的团队不会出现此错误。请使用你拥有合法使用权的图片来创建 prototype 任务。
- Name
404 - Not Found- Description
你的账户下不存在此 ID 对应的 Fidget Pixel 任务,或该任务所处的阶段与路径不匹配。请检查 ID,并使用
/prototype或/build以匹配对应的任务。
- Name
500 - Internal Server Error- Description
Meshy 无法完成知识产权检查。请重试该请求。
删除 Fidget Pixel 任务
取消一个 Fidget Pixel 任务。取消 PENDING 任务会退还其积分。IN_PROGRESS 任务会被取消但不会退款,因为已经有工作进程开始处理该任务。处于最终状态(SUCCEEDED、FAILED 或 CANCELED)的任务无法被取消。
路径必须与任务所处的阶段一致。例如,使用构建任务的 ID 对 /prototype/:id 执行 DELETE 会返回 404。
Request
curl --request DELETE \
--url https://api.meshy.ai/openapi/creative-lab/fidget-pixel/v1/prototype/019c4a1e-2b7d-7d03-8f6a-5c2e91f0a1b7 \
-H "Authorization: Bearer ${YOUR_API_KEY}"
Response
// Returns 204 No Content on success (empty body).
路径参数
- Name
- id
- Type
- path
- Description
要取消的任务的 ID。
返回值
返回空响应体的 204 No Content。
失败情况
- Name
400 - Bad Request- Description
以下情况之一适用:
id不是有效的任务 ID。请发送创建响应中的resultID。- 任务已处于最终状态(
SUCCEEDED、FAILED或CANCELED),因此无法取消。
- Name
404 - Not Found- Description
你的账户下没有该 ID 对应的 Fidget Pixel 任务,或者任务所处的阶段与路径不匹配。请检查 ID,并使用
/prototype或/build来匹配对应的任务。
流式获取 Fidget Pixel 任务
以 Server-Sent Events(SSE)的形式流式传输 Fidget Pixel 任务的更新。路径必须与任务所处的阶段相匹配。如果不匹配,例如在 /prototype/:id/stream 中使用了 build 任务的 ID,流会发送一个 status_code: 404 的 error 事件并关闭。如果 id 不是有效的任务 ID,也会发生同样的情况,但 status_code 为 400。
Request
curl -N https://api.meshy.ai/openapi/creative-lab/fidget-pixel/v1/build/019c4a2f-6e81-7b44-9a1d-0d7f3c5e2b98/stream \
-H "Authorization: Bearer ${YOUR_API_KEY}"
Response Stream
// Error event example (wrong stage or task not found)
event: error
data: {
"status_code": 404,
"message": "Task not found"
}
// Message event examples illustrate task progress.
// Every frame is the full task object for the stage; fields not yet populated are null / empty.
event: message
data: {
"id": "019c4a2f-6e81-7b44-9a1d-0d7f3c5e2b98",
"type": "creative-lab-fidget-pixel-build",
"name": "",
"status": "PENDING",
"progress": 0,
"created_at": 1757001300000,
"started_at": null,
"finished_at": null,
"expires_at": 1757260500000,
"preceding_tasks": 2,
"task_error": null,
"consumed_credits": 30,
"model_urls": {}
}
event: message
data: {
"id": "019c4a2f-6e81-7b44-9a1d-0d7f3c5e2b98",
"type": "creative-lab-fidget-pixel-build",
"status": "SUCCEEDED",
"progress": 100,
"created_at": 1757001300000,
"started_at": 1757001304000,
"finished_at": 1757001309000,
"expires_at": 1757260509000,
"task_error": null,
"consumed_credits": 30,
"model_urls": {
"3mf": "https://assets.meshy.ai/***/tasks/019c4a2f-6e81-7b44-9a1d-0d7f3c5e2b98/output/model.3mf?Expires=***"
}
}
参数
- Name
- id
- Type
- path
- Description
创建响应中返回的任务 ID。
返回值
返回 prototype 或 build 任务对象的流。每个事件都包含完整的任务对象,形式与 获取 Fidget Pixel 任务 返回的一致。当任务处于 PENDING 或 IN_PROGRESS 状态时,其输出字段仍为空(null、[] 或 {}),且 finished_at 为 null。
如果 IP 过滤 阻止了任务的结果,流会发送一个 error 事件代替,其中包含 get 请求本应返回的 status_code。
列出 Fidget Pixel 任务
按页返回你某个阶段的 Fidget Pixel 任务,每次返回一页。路径决定阶段:/prototype 仅返回原型任务,/build 仅返回构建任务。
Request
# List prototype tasks
curl https://api.meshy.ai/openapi/creative-lab/fidget-pixel/v1/prototype?page_size=10 \
-H "Authorization: Bearer ${YOUR_API_KEY}"
# List build tasks
curl https://api.meshy.ai/openapi/creative-lab/fidget-pixel/v1/build?page_size=10 \
-H "Authorization: Bearer ${YOUR_API_KEY}"
Response (List Prototype Tasks)
[
{
"id": "019c4a1e-2b7d-7d03-8f6a-5c2e91f0a1b7",
"type": "creative-lab-fidget-pixel-prototype",
"name": "",
"status": "SUCCEEDED",
"progress": 100,
"created_at": 1757001000000,
"started_at": 1757001005000,
"finished_at": 1757001178000,
"expires_at": 1757260378000,
"preceding_tasks": 0,
"task_error": null,
"consumed_credits": 6,
"image_urls": [
"https://assets.meshy.ai/***/pixel-art.jpg?Expires=***"
]
}
]
路径参数
- Name
- stage
- Type
- path
- 必选
- Description
要列出的阶段,
prototype或build。
查询参数
- Name
- page_num
- Type
- integer
- 默认值 1
- Description
要返回的页码,范围从
1到255。0返回第一页。超出0到255的值将返回400。
- Name
- page_size
- Type
- integer
- 默认值 10
- Description
每页任务数量,最多
100。101到255之间的值将返回 100 个任务,0则使用默认值。超出0到255的值将返回400。
- Name
- sort_by
- Type
- string
- 默认值 -created_at
- Description
排序方式。
可用值:
-created_at:最新优先+created_at:最旧优先
返回值
Fidget Pixel prototype 任务对象
prototype 任务会把一张照片转换为像素画图像。要把该图像转换为可 3D 打印的拼块,请将该任务的 ID 作为 input_task_id 传给构建 endpoint。
属性
Example Fidget Pixel Prototype Task Object
{
"id": "019c4a1e-2b7d-7d03-8f6a-5c2e91f0a1b7",
"type": "creative-lab-fidget-pixel-prototype",
"name": "",
"status": "SUCCEEDED",
"progress": 100,
"created_at": 1757001000000,
"started_at": 1757001005000,
"finished_at": 1757001178000,
"expires_at": 1757260378000,
"preceding_tasks": 0,
"task_error": null,
"consumed_credits": 6,
"image_urls": [
"https://assets.meshy.ai/***/pixel-art.jpg?Expires=***"
]
}
- Name
- id
- Type
- string
- Description
任务 ID。不要依赖其格式。
- Name
- type
- Type
- string
- Description
任务类型,始终为
creative-lab-fidget-pixel-prototype。
- Name
- name
- Type
- string
- Description
你在创建任务时传入的
name;如果未传入,则为""。
- Name
- status
- Type
- string
- Description
任务的状态。
可选值:
PENDING:正在队列中等待IN_PROGRESS:正在生成结果SUCCEEDED:最终状态,已生成结果FAILED:最终状态,失败原因见task_errorCANCELED:最终状态,没有结果
- Name
- progress
- Type
- integer
- Description
任务完成的百分比,范围从
0到100。任务开始前为0,成功后为100。
- Name
- created_at
- Type
- timestamp
- Description
任务创建的时间,单位为 Unix 毫秒。
- Name
- started_at
- Type
- timestamp
- Description
工作进程开始处理任务的时间,单位为 Unix 毫秒。在此之前为
null。
- Name
- finished_at
- Type
- timestamp
- Description
任务到达最终状态的时间,单位为 Unix 毫秒。在此之前为
null。
- Name
- expires_at
- Type
- timestamp
- Description
任务结果过期的时间,单位为 Unix 毫秒。该时间为
finished_at之后 3 天;在任务完成之前,则为created_at之后 3 天。对于会无限期保留 API 结果的企业账户,该时间约为 100 年后。参见资产保留期。
- Name
- preceding_tasks
- Type
- integer
- Description
任务处于
PENDING状态时在队列中的位置。1表示该任务将是下一个开始的任务。任务离开队列后为0,在列表结果中也始终为0。
- Name
- task_error
- Type
- object
- Description
任务失败的原因。除非
status为FAILED,否则为null。参见 Errors。
- Name
- consumed_credits
- Type
- integer
- Description
该任务扣除的积分数量(已计入任何退款)。返回错误的请求不会被扣费。失败的任务为
0,因为 Meshy 会退还积分。只有在任务处于PENDING状态时取消,才会退还积分。如果 Meshy 无法读取扣费信息,获取或流式响应中会省略该字段,而列表请求会返回500。遇到这种情况,请重试请求。
- Name
- image_urls
- Type
- array of strings
- Description
像素画图像的下载链接。任务成功后,该数组中会包含一个 URL;在此之前为空数组。
这些 URL 都是签名过的,获取时无需带
Authorization请求头。它们在expires_at之前一直有效。在此之前再次获取该任务,返回的仍是相同的 URL,而不是重新签名的 URL。过期的 URL 无法刷新,因此请在此之前下载并保存好文件。
Fidget Pixel 构建任务对象
构建任务会根据已成功的原型任务生成可供 3D 打印的拼块。Meshy 会将像素风图像采样到网格上,并以单个多色 3MF 文件返回这些拼块。
属性
Example Fidget Pixel Build Task Object
{
"id": "019c4a2f-6e81-7b44-9a1d-0d7f3c5e2b98",
"type": "creative-lab-fidget-pixel-build",
"name": "",
"status": "SUCCEEDED",
"progress": 100,
"created_at": 1757001300000,
"started_at": 1757001304000,
"finished_at": 1757001309000,
"expires_at": 1757260509000,
"preceding_tasks": 0,
"task_error": null,
"consumed_credits": 30,
"model_urls": {
"3mf": "https://assets.meshy.ai/***/tasks/019c4a2f-6e81-7b44-9a1d-0d7f3c5e2b98/output/model.3mf?Expires=***"
}
}
- Name
- id
- Type
- string
- Description
任务 ID。请勿依赖其格式。
- Name
- type
- Type
- string
- Description
任务类型,始终为
creative-lab-fidget-pixel-build。
- Name
- name
- Type
- string
- Description
你创建任务时发送的
name,如果未发送则为""。
- Name
- status
- Type
- string
- Description
任务的状态。
可用的值:
PENDING:正在队列中等待IN_PROGRESS:正在生成结果SUCCEEDED:最终状态,已有结果FAILED:最终状态,原因见task_errorCANCELED:最终状态,没有结果
- Name
- progress
- Type
- integer
- Description
已完成工作的百分比,范围从
0到100。任务开始前为0,成功后为100。
- Name
- created_at
- Type
- timestamp
- Description
任务创建的时间,以 Unix 毫秒表示。
- Name
- started_at
- Type
- timestamp
- Description
工作进程开始执行任务的时间,以 Unix 毫秒表示。在此之前为
null。
- Name
- finished_at
- Type
- timestamp
- Description
任务到达最终状态的时间,以 Unix 毫秒表示。在此之前为
null。
- Name
- expires_at
- Type
- timestamp
- Description
任务结果过期的时间,以 Unix 毫秒表示。它是
finished_at之后 3 天,或在任务完成之前是created_at之后 3 天。对于无限期保留 API 结果的企业版账户,这个时间大约是 100 年之后。请参阅资产保留期。
- Name
- preceding_tasks
- Type
- integer
- Description
任务处于
PENDING状态时在队列中的位置。1表示它将是下一个开始的任务。任务离开队列后为0,在列表结果中始终为0。
- Name
- task_error
- Type
- object
- Description
任务失败的原因。除非
status为FAILED,否则为null。请参阅 Errors。
- Name
- consumed_credits
- Type
- integer
- Description
任务所扣除的积分数量,已扣除任何退款。返回错误的请求不会被扣费。失败的任务为
0,因为 Meshy 会退还费用。取消任务只有在其处于PENDING状态时才会退款。如果 Meshy 无法读取扣费信息,获取或流式传输响应会省略该字段,而列表请求会返回500。在这种情况下,请重试该请求。
- Name
- model_urls
- Type
- object
- Description
结果的下载 URL,以文件格式作为键。该对象包含一个条目,对应你所发送的
output.format,在任务成功之前为空。这些 URL 是经过签名的,因此获取时无需携带
Authorization请求头。它们在expires_at之前一直有效。在此之前再次获取该任务会返回相同的 URL,而不是重新签名的 URL。过期的 URL 无法刷新,因此请在过期前下载并保存这些文件。- Name
3mf- Type
- string
- Description
多色 3MF 文件的下载 URL。每个拼块都有一个灰色主体和一个带有其像素颜色的顶部。当
output.format为3mf(默认值)时存在。
端到端示例
以下 cURL 和 Python 脚本运行整个流程。每个脚本都会根据一张照片创建一个 prototype 任务并等待其成功完成。然后创建一个 build 任务,等待该任务完成,并从 model_urls.3mf 下载 3MF 文件。
cURL 脚本需要 curl 和 jq,Python 脚本需要 requests 包。要运行脚本,请按以下步骤操作:
- 将
MESHY_API_KEY设置为你的 API key。 - 将
IMAGE_PATH设置为本地照片的路径,或将IMAGE_URL设置为公开可访问的图片 URL。 - 可选:如果要像素化的主体不是人物,请将
PIXEL_TYPE设置为other。 - 运行脚本。
prototype 任务通常会在几分钟内完成。build 任务通常会在不到一分钟内完成。
在你的应用中,在创建 build 任务之前,先向用户展示 image_urls 中的图片。如果他们不喜欢,就改为再创建一个 prototype 任务。这样,你只会在用户认可的图片上花费 build 积分。
Complete flow
#!/usr/bin/env bash
set -euo pipefail
# Requires curl and jq. Point IMAGE_PATH at a local photo, or IMAGE_URL at a public one:
# export MESHY_API_KEY=msy_...
# export IMAGE_PATH=./portrait.jpg # or: export IMAGE_URL=https://...
# export PIXEL_TYPE=person # or: other
: "${MESHY_API_KEY:?export MESHY_API_KEY first}"
if [[ -z "${IMAGE_PATH:-}" && -z "${IMAGE_URL:-}" ]]; then
echo "export IMAGE_PATH (local file) or IMAGE_URL (public url) first" >&2
exit 1
fi
PIXEL_TYPE=${PIXEL_TYPE:-person}
BASE="https://api.meshy.ai/openapi/creative-lab/fidget-pixel/v1"
AUTH="Authorization: Bearer $MESHY_API_KEY"
# api METHOD URL [curl args...] -> prints the response body, non-zero on failure.
# Note we do not use -f/--fail: it discards the body, and the body is the only
# place the reason appears.
api() {
local method=$1 url=$2 out http_code body
shift 2
out=$(curl --silent --show-error --max-time 60 --write-out $'\n%{http_code}' \
-X "$method" "$url" -H "$AUTH" "$@") || return 1
http_code=${out##*$'\n'}
body=${out%$'\n'*}
if ((http_code >= 400)); then
echo "HTTP $http_code for $url: $body" >&2
return 1
fi
printf '%s' "$body"
}
# Each task gets its own 40-minute budget.
poll() {
local kind=$1 id=$2 delay=5 task_status deadline
deadline=$(($(date +%s) + 2400))
while :; do
if (($(date +%s) >= deadline)); then
echo "gave up waiting for $kind $id" >&2
return 1
fi
task_status=$(api GET "$BASE/$kind/$id" | jq -r '.status')
echo "$kind: $task_status"
case "$task_status" in
SUCCEEDED) return 0 ;;
FAILED | CANCELED) return 1 ;;
esac
sleep "$delay"
delay=$((delay * 2 > 30 ? 30 : delay * 2))
done
}
# Build the request body in a file. A base64 data URI must never go on the
# command line or into an exported variable - a photo of any real size will
# exceed the OS argument limit.
BODY=$(mktemp)
trap 'rm -f "$BODY"' EXIT
if [[ -n "${IMAGE_PATH:-}" ]]; then
# Declare the real type: the API accepts JPEG, PNG and WebP.
case "$(printf '%s' "${IMAGE_PATH##*.}" | tr 'A-Z' 'a-z')" in
png) MIME=image/png ;;
webp) MIME=image/webp ;;
*) MIME=image/jpeg ;;
esac
{
printf '{"type":"%s","image_url":"data:%s;base64,' "$PIXEL_TYPE" "$MIME"
base64 <"$IMAGE_PATH" | tr -d '\n'
printf '"}'
} >"$BODY"
else
jq -n --arg t "$PIXEL_TYPE" --arg u "$IMAGE_URL" \
'{type: $t, image_url: $u}' >"$BODY"
fi
# 1. Create the prototype task
PROTO_ID=$(api POST "$BASE/prototype" \
-H 'Content-Type: application/json' --data-binary @"$BODY" | jq -r '.result')
# 2. Wait for the pixel-art image (show image_urls[0] to a user in production)
poll prototype "$PROTO_ID"
# 3. Create the build task (defaults: square pieces, 32x32 grid, 8 mm, 8 colors, 15 mm tall)
jq -n --arg p "$PROTO_ID" \
'{input_task_id: $p, options: {shape: "square", grid_size: 32, piece_size_mm: 8, color_count: 8, piece_height_mm: 15}, output: {format: "3mf"}}' >"$BODY"
BUILD_ID=$(api POST "$BASE/build" \
-H 'Content-Type: application/json' --data-binary @"$BODY" | jq -r '.result')
# 4. Wait for the pieces
poll build "$BUILD_ID"
# 5. Download the 3MF. This is a signed URL: no Authorization header,
# and it stays valid for 3 days after the task finishes.
TASK=$(api GET "$BASE/build/$BUILD_ID")
curl --silent --show-error --fail --max-time 900 \
-o fidget-pixel.3mf "$(jq -r '.model_urls["3mf"]' <<<"$TASK")"
echo "Done: fidget-pixel.3mf"