查询场景任务
curl --request GET \
--url https://apis.viggle.ai/v1/scenes/{task_id} \
--header 'Authorization: Bearer <token>'import requests
url = "https://apis.viggle.ai/v1/scenes/{task_id}"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://apis.viggle.ai/v1/scenes/{task_id}', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://apis.viggle.ai/v1/scenes/{task_id}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://apis.viggle.ai/v1/scenes/{task_id}"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://apis.viggle.ai/v1/scenes/{task_id}")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://apis.viggle.ai/v1/scenes/{task_id}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"id": "<string>",
"sessionId": "<string>",
"operation": "pano",
"status": "processing",
"createdAt": 123,
"completedAt": 123,
"result": {
"operation": "pano",
"sessionId": "<string>",
"spz": {
"url": "<string>"
},
"preview": {
"url": "<string>"
},
"panorama": {
"url": "<string>"
},
"outputBatch": {
"batchId": "<string>",
"createdAt": 123,
"manifest": {
"url": "<string>"
},
"kind": "initial",
"views": [
{
"index": 1,
"url": "<string>",
"c2w": [
[
1,
0,
0,
0
],
[
0,
1,
0,
0
],
[
0,
0,
1,
0
],
[
0,
0,
0,
1
]
],
"intrinsic": [
123
]
}
]
},
"referenceViewCount": 123,
"newViewCount": 123,
"seconds": {}
},
"error": {
"code": "UNAUTHENTICATED",
"message": "<string>",
"retryable": true,
"request_id": "<string>",
"details": {},
"remediation": {
"action": "<string>",
"retry_after_ms": 1
}
}
}{
"error": {
"code": "UNAUTHENTICATED",
"message": "<string>",
"retryable": true,
"request_id": "<string>",
"details": {},
"remediation": {
"action": "<string>",
"retry_after_ms": 1
}
}
}{
"error": {
"code": "UNAUTHENTICATED",
"message": "<string>",
"retryable": true,
"request_id": "<string>",
"details": {},
"remediation": {
"action": "<string>",
"retry_after_ms": 1
}
}
}{
"error": {
"code": "UNAUTHENTICATED",
"message": "<string>",
"retryable": true,
"request_id": "<string>",
"details": {},
"remediation": {
"action": "<string>",
"retry_after_ms": 1
}
}
}场景模型
查询场景任务
获取场景任务的状态,就绪后获取场景、全景图和图像的下载链接。
GET
/
v1
/
scenes
/
{task_id}
查询场景任务
curl --request GET \
--url https://apis.viggle.ai/v1/scenes/{task_id} \
--header 'Authorization: Bearer <token>'import requests
url = "https://apis.viggle.ai/v1/scenes/{task_id}"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://apis.viggle.ai/v1/scenes/{task_id}', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://apis.viggle.ai/v1/scenes/{task_id}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://apis.viggle.ai/v1/scenes/{task_id}"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://apis.viggle.ai/v1/scenes/{task_id}")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://apis.viggle.ai/v1/scenes/{task_id}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"id": "<string>",
"sessionId": "<string>",
"operation": "pano",
"status": "processing",
"createdAt": 123,
"completedAt": 123,
"result": {
"operation": "pano",
"sessionId": "<string>",
"spz": {
"url": "<string>"
},
"preview": {
"url": "<string>"
},
"panorama": {
"url": "<string>"
},
"outputBatch": {
"batchId": "<string>",
"createdAt": 123,
"manifest": {
"url": "<string>"
},
"kind": "initial",
"views": [
{
"index": 1,
"url": "<string>",
"c2w": [
[
1,
0,
0,
0
],
[
0,
1,
0,
0
],
[
0,
0,
1,
0
],
[
0,
0,
0,
1
]
],
"intrinsic": [
123
]
}
]
},
"referenceViewCount": 123,
"newViewCount": 123,
"seconds": {}
},
"error": {
"code": "UNAUTHENTICATED",
"message": "<string>",
"retryable": true,
"request_id": "<string>",
"details": {},
"remediation": {
"action": "<string>",
"retry_after_ms": 1
}
}
}{
"error": {
"code": "UNAUTHENTICATED",
"message": "<string>",
"retryable": true,
"request_id": "<string>",
"details": {},
"remediation": {
"action": "<string>",
"retry_after_ms": 1
}
}
}{
"error": {
"code": "UNAUTHENTICATED",
"message": "<string>",
"retryable": true,
"request_id": "<string>",
"details": {},
"remediation": {
"action": "<string>",
"retry_after_ms": 1
}
}
}{
"error": {
"code": "UNAUTHENTICATED",
"message": "<string>",
"retryable": true,
"request_id": "<string>",
"details": {},
"remediation": {
"action": "<string>",
"retry_after_ms": 1
}
}
}GET /v1/scenes/{task_id} 返回由创建场景、从自定义全景图创建场景、生成场景视图或重建场景发起的任务的当前状态,结构与提交时返回的场景任务对象相同。每 5 秒轮询一次,直到 status 为 ready、failed 或 cancelled,然后下载 result 下的文件。
任务归属于你的账号——即你的组织;密钥不属于任何组织时则为你的用户——因此同一账号的任何 API 密钥都能读取。ID 不存在或属于其他账号时返回 404 INVALID_REQUEST。
请求参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
task_id | string | 是 | 提交接口返回的完整任务 ID,以 scn_ 开头。格式为 scn_{runId}.{sessionId},请原样使用。 |
响应参数
返回200 OK 和场景任务对象。字段名使用 camelCase。
| 字段 | 类型 | 说明 |
|---|---|---|
id | string | 任务 ID,以 scn_ 开头。 |
sessionId | string | 提交任务时使用的 sessionId。 |
operation | string | pano、generate 或 reconstruct。custom-pano 任务返回 pano。 |
status | string | processing、ready、failed 或 cancelled,见下方“状态与错误码”一节。 |
createdAt | integer | 开始时间,Unix 毫秒。 |
completedAt | integer 或 null | 结束时间,Unix 毫秒;processing 时为 null。 |
result | object 或 null | 只在 status 为 ready 时有值,见下方“结果”一节。 |
error | object 或 null | 只在 status 为 failed 时有值。 |
结果
| 字段 | 类型 | 说明 |
|---|---|---|
operation | string | 与任务的 operation 相同。 |
sessionId | string | 与任务的 sessionId 相同。 |
spz | object 或 null | 3D 高斯泼溅场景,形如 { "url": ... },SPZ 格式。由 pano 和 reconstruct 产生。如果传了 spzOutputUrl(或 outputUris.spz),文件只上传到你的地址,url 即该地址。 |
preview | object 或 null | 预览图,形如 { "url": ... },仅在操作产生预览图时有值。 |
panorama | object 或 null | 构建场景所用的 360° 全景图,形如 { "url": ... }——根据描述文字生成的,或你提供的。由 pano 产生。 |
outputBatch | object 或 null | 本任务向会话添加的图像批次,见下方“输出批次”一节。由 pano(初始视图)和 generate(新视图)产生;reconstruct 时为 null。 |
referenceViewCount | integer | 任务从 referenceBatchIds 读取的参考视图数量。pano 为 0。 |
newViewCount | integer | 任务产生的新视图数量。reconstruct 为 0。 |
seconds | object | 各阶段处理耗时,单位为秒,例如 {"model": 4.2}。键因操作而异,仅供参考。 |
url 有效期为 3 小时。再查询一次任务即可拿到新链接。
输出批次
批次是一个会话中一组带位姿的图像。它的batchId 可传入 referenceBatchIds,用于生成更多视图或重建场景。
| 字段 | 类型 | 说明 |
|---|---|---|
batchId | string | 批次 ID,小写 UUID。 |
createdAt | number | 批次创建时间,Unix 毫秒。 |
manifest | object | 批次的 batch.json 清单,形如 { "url": ... }。 |
kind | string | pano 生成的批次为 initial,generate 生成的批次为 generated。 |
views | array | 批次中的所有图像,按顺序排列。 |
views[].index | integer | 在批次中的位置,从 0 开始。 |
views[].url | string | 图像的签名下载链接。 |
views[].c2w | number[4][4] | 视图的相机到世界矩阵(c2w)。custom-pano 场景中它位于你自己的世界坐标系,见从自定义全景图创建场景中的“坐标系”一节。 |
views[].intrinsic | number[] | 视图的相机内参,与批次清单中的记录一致。 |
kind 和 views 之前就已结束的任务可能缺少这两个字段;manifest 始终存在。
就绪示例
一个pano 任务。签名查询参数已缩写:
{
"id": "scn_0199f0c2-6a1e-7c3d-9b2a-4f5e6d7c8b9a.living-room-01",
"sessionId": "living-room-01",
"operation": "pano",
"status": "ready",
"createdAt": 1791856740000,
"completedAt": 1791856800000,
"result": {
"operation": "pano",
"sessionId": "living-room-01",
"spz": { "url": "https://.../scene.spz?X-Amz-Signature=..." },
"preview": null,
"panorama": { "url": "https://.../panorama.png?X-Amz-Signature=..." },
"outputBatch": {
"batchId": "3f0a6c1e-8d2b-4b7a-9e5c-1a2b3c4d5e6f",
"createdAt": 1791856800000,
"manifest": { "url": "https://.../batch.json?X-Amz-Signature=..." },
"kind": "initial",
"views": [
{
"index": 0,
"url": "https://.../0.png?X-Amz-Signature=...",
"c2w": [[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]],
"intrinsic": [0.5, 0.5, 0.5, 0.5]
}
]
},
"referenceViewCount": 0,
"newViewCount": 6,
"seconds": { "model": 4.2 }
},
"error": null
}
失败示例
{
"id": "scn_0199f0c2-6a1e-7c3d-9b2a-4f5e6d7c8b9a.living-room-01",
"sessionId": "living-room-01",
"operation": "generate",
"status": "failed",
"createdAt": 1791856740000,
"completedAt": 1791856765000,
"result": null,
"error": {
"code": "PROCESSING_FAILED",
"message": "The request could not be processed.",
"retryable": true,
"request_id": "req_7d3c...",
"details": {},
"remediation": { "action": "retry", "retry_after_ms": null }
}
}
状态与错误码
status | 含义 |
|---|---|
processing | 运行中。在它结束前,该会话不接受其他任务。 |
ready | 已完成,result 已填充。 |
failed | 失败,原因见 error。 |
cancelled | 在完成前被 Viggle 终止。请重新提交任务。 |
error.code 的取值:
code | retryable | 什么时候出现 | 建议 |
|---|---|---|---|
INVALID_REQUEST | false | 场景模型拒绝了输入,例如 referenceBatchIds 中有不属于本会话的批次。message 说明原因。 | 修正输入后重新提交。 |
PROCESSING_FAILED | true | 其他任何失败:模型、存储或超时。 | 重新提交同样的请求。反复出现请带上任务 id 联系我们。 |
| HTTP | code | 含义 |
|---|---|---|
401 | UNAUTHENTICATED | 缺少或无效的 API 密钥。 |
404 | INVALID_REQUEST | 你的账号中没有该任务,或已超过下方“数据保留”一节所述的保留期限。 |
503 | SERVICE_BUSY | 场景模型暂时不可用,可重试。 |
error 使用同样的结构,外面包一层 {"error": {...}}。详见错误与恢复。
数据保留
- 任务结束后约 72 小时内可以查询;之后本接口返回
404。请下载所需文件,或通过outputUris让 Viggle 直接上传到你的存储(见“上传到自己的存储”一节)。 - 每个签名链接有效期为 3 小时;在任务仍可查询期间,再查询一次即可拿到新链接。
示例
curl https://apis.viggle.ai/v1/scenes/scn_0199f0c2-6a1e-7c3d-9b2a-4f5e6d7c8b9a.living-room-01 \
-H "Authorization: Bearer $VIGGLE_API_KEY"
import os, requests
response = requests.get(
"https://apis.viggle.ai/v1/scenes/scn_0199f0c2-6a1e-7c3d-9b2a-4f5e6d7c8b9a.living-room-01",
headers={"Authorization": f"Bearer {os.environ['VIGGLE_API_KEY']}"},
)
response.raise_for_status()
task = response.json()
const response = await fetch("https://apis.viggle.ai/v1/scenes/scn_0199f0c2-6a1e-7c3d-9b2a-4f5e6d7c8b9a.living-room-01", {
headers: { Authorization: `Bearer ${process.env.VIGGLE_API_KEY}` },
});
const task = await response.json();
快速入门:场景模型
端到端完成构建场景、生成新视图和重建。
授权
服务端 SDK 使用项目 API 密钥,Remote MCP 使用 OAuth 访问令牌。不要在浏览器代码中暴露项目密钥。
请求头
可选的调用者自定义关联 ID,最长 128 字符。服务会在响应头返回实际使用的值,便于追踪和支持排查。
Required string length:
1 - 128可选来源标签,最长 128 字符,用于识别 SDK、集成、产品入口或内部工作流。
Required string length:
1 - 128路径参数
/v1/scenes 提交接口返回的场景任务 ID,以 scn_ 开头(格式 scn_{runId}.{sessionId}),必须属于当前账户。
Minimum string length:
1响应
请求成功。
场景任务(以 scn_ 开头),所有 /v1/scenes 提交接口和 GET /v1/scenes/{task_id} 都返回它。ready、failed、cancelled 为终态。任务结束后约 72 小时内可查询。
任务 ID,格式为 scn_{runId}.{sessionId}。
custom-pano 任务也返回 pano。
可用选项:
pano, generate, reconstruct 可用选项:
processing, ready, failed, cancelled 开始时间,Unix 毫秒。
结束时间,Unix 毫秒;processing 时为 null。
只在 ready 时有值。
Show child attributes
Show child attributes
只在 failed 时有值。code 为 INVALID_REQUEST(不可重试,模型拒绝了输入,例如引用了其他会话的批次)或 PROCESSING_FAILED(可重试)。
Show child attributes
Show child attributes

